packet_format.tex
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:16k
源码类别:

通讯编程

开发平台:

Visual C++

  1. %
  2. % personal commentary:
  3. %        DRAFT DRAFT DRAFT
  4. %        - KFALL
  5. %
  6. section{shdr{Packet Headers and Formats}{packet.h}{sec:pformat}}
  7. Objects of the class code{Packet} are the fundamental unit of
  8. exchange between objects in the simulation.
  9. The code{Packet} class provides enough information to
  10. link a packet on to a list (i.e. in a code{PacketQueue} or on a free
  11. list of packets), refer to a buffer containing packet headers
  12. which are defined on a per-protocol basis, and to refer to a buffer
  13. of packet data.
  14. New protocols may define their own packet headers or may extend
  15. existing headers with additional fields.
  16. New packet headers are introduced into the simulator
  17. by defining a C++ structure with the needed
  18. fields, defining a static class to provide
  19. OTcl linkage, and then modifying some of the simulator initialization
  20. code to assign a byte offset in each packet where the new header
  21. is to be located relative to others.
  22. When the simulator is initialized through OTcl,
  23. a user may choose to enable
  24. only a subset of the compiled-in packet formats, resulting in
  25. a modest savings of memory during the execution of the simulation.
  26. Presently, all configured-in packet formats are enabled.
  27. The management of which packet formats are currently enabled
  28. in a simulation is handled by a special packet header manager
  29. object described below.
  30. This object supports an OTcl method used to specify
  31. which packet headers will be used in a simulation.
  32. If an object in the simulator makes use of a field in a header
  33. which has not been enabled, a run-time fatal program abort occurs.
  34. subsection{shdr{A Protocol-Specific Packet Header}{rtp.h}{sec:ppackethdr}}
  35. Protocol developers
  36. will often wish to provide a specific header type to be used in packets.
  37. Doing so allows a new protocol implementation
  38. to avoid overloading already-existing header fields.
  39. We consider a simplified version of RTP as an example.
  40. The RTP header will require a sequence number fields and a source
  41. identifier field.
  42. The following classes create the needed header
  43. (see code{rtp.h} and code{rtp.cc}):
  44. begin{small}
  45. begin{verbatim}
  46. From rtp.h:
  47. /* rtp packet.  For now, just have srcid + seqno. */
  48. struct hdr_rtp { 
  49. u_int32_t srcid_;
  50. int seqno_;
  51. /* per-field member functions */
  52. u_int32_t& srcid() { return (srcid_); }
  53. int& seqno() { return (seqno_); }
  54. };   
  55. From rtp.cc:
  56. class RTPAgent: public CBR_Agent {
  57. ...
  58. int off_rtp_;
  59. };
  60. class RTPHeaderClass : public PacketHeaderClass {
  61. public: 
  62. RTPHeaderClass() : PacketHeaderClass("PacketHeader/RTP",
  63.      sizeof(hdr_rtp)) {}
  64. } class_rtphdr;
  65. void RTPAgent::sendpkt()
  66. {
  67. Packet* p = allocpkt();
  68. hdr_rtp *rh = (hdr_rtp*)p->access(off_rtp_);
  69. lastpkttime_ = Scheduler::instance().clock();
  70. /* Fill in srcid_ and seqno */
  71. rh->seqno() = seqno_++;
  72. rh->srcid() = session_->srcid();
  73. target_->recv(p, 0);
  74. }
  75. RTPAgent::RTPAgent()
  76. : session_(0), lastpkttime_(-1e6)
  77. {
  78. type_ = PT_RTP;
  79. bind("seqno_", &seqno_);
  80. bind("off_rtp_", &off_rtp_);
  81. }
  82. end{verbatim}
  83. end{small}
  84. The first structure defines the layout (in terms of words and their
  85. placement): which fields are needed and how big they are.
  86. This structure definition is only used by the
  87. compiler to compute byte offsets of fields;
  88. no objects of this structure type are ever directly allocated.
  89. The structure also provides member functions
  90. which in turn
  91. provide a layer of data hiding for objects wishing to read
  92. or modify header fields of packets.
  93. Note that the variable code{off_rtp_} is used
  94. to find the byte offset at which the rtp header is located
  95. in an arbitrary packet.
  96. To access any packet header other than the ``common'' header
  97. (see below, sectionref{sec:commonhdr}), the accessing code
  98. must obtain the appropriate header offset.
  99. This is accomplished by declaring and binding
  100. the integer variable code{off_<hdrname>_}
  101. where code{<hdrname>} refers to a shorthand name
  102. of the header of interest which must match the
  103. name assigned in code{tcl/lib/ns-packet.tcl}.
  104. This is performed above by the RTPAgent's constructor.
  105. Generally, one header object for each type of header
  106. in the simulation is instantiated at simulator run-time.
  107. A particular header is enabled via OTcl in the simulation during
  108. simulator configuration time (see ref{sec:configpacket}).
  109. The static object code{class_rtphdr} of class code{RTPHeaderClass}
  110. is used to provide linkage to OTcl when the RTP header is
  111. enabled at configuration time.
  112. When the simulator executes, this static object calls
  113. the code{PacketHeaderClass} constructor with arguments
  114. code{"PacketHeader/RTP"} and code{sizeof(hdr_rtp}.
  115. This causes the size of the RTP header to be stored
  116. and made available to the packet header manager
  117. at configuration time (see below, sectionref{sec:packethdrmgr}).
  118. The sample member function code{sendpkt()}
  119. of code{RTPAgent} creates a new packet
  120. to send by calling code{allocpkt()}, which handles assignment
  121. of all the network-layer packet header fields (in this case, IP).
  122. Headers other than IP are handled separately.
  123. In this case, the agent uses the code{RTPHeader} defined above.
  124. The code{Packet::access()} member function returns the address
  125. of the first byte in a buffer used to hold header information (see below).
  126. Its return value is cast as a pointer to the header of interest,
  127. after which member functions of the code{RTPHeader}
  128. object are used to access individual fields.
  129. subsubsection{adding a new packet header type}
  130. Assuming we wish to create a new header called code{newhdr}
  131. the following steps are performed:
  132. begin{enumerate}
  133.         item create a new structure defining the raw fields (called code{hdr_newhdr})
  134.         item define member functions for needed fields
  135. item create a static class to perform OTcl linkage (defines code{PacketHeader/Newhdr})
  136.         item edit code{tcl/lib/ns-packet.tcl} to enable new packet format (see ref{sec:configpacket})
  137. end{enumerate}
  138. subsection{shdr{Packet Classes}{packet.h}{sec:packetclasses}}
  139. There are three C++ classes relevant to the handling of packets
  140. and packet headers in general: code{Packet},
  141. code{PacketHeader}, and code{PacketHeaderManager}.
  142. The code{Packet} class defines the type for all packets in the
  143. simulation; it is a subclass of code{Event} so that packets may
  144. be scheduled (e.g.~for later arrival at some queue).
  145. The code{PacketHeader} class provides a base class for
  146. any packet header configured into the simulation.
  147. It essentially provides 
  148. enough internal state to locate any particular packet
  149. header in the collection of packet headers present in any given packet.
  150. The code{PacketHeaderManager} defines a class used to collect
  151. and manage currently-configured headers.
  152. It is invoked by a method available to OTcl at simulation configuration
  153. time to enable some subset of the compiled-in packet headers.
  154. begin{figure}[h]
  155. centerline{psfig{figure=packet.eps,width=4in}}
  156. caption{label{pic:packet}A Packet Object}
  157. end{figure}
  158. subsubsection{shdr{the Packet class}{packet.h}{sec:packetclass}}
  159. The code{Packet} class defines the structure of a
  160. packet and provides member functions to handle a
  161. free list for objects of this type.
  162. It is illustrated in Figure~ref{pic:packet} and
  163. defined as follows in code{packet.h}:
  164. begin{small}
  165. begin{verbatim}
  166. class Packet : public Event {
  167. private:
  168. friend class PacketQueue;
  169. u_char* bits_;  
  170. u_char* data_;  // variable size buffer for 'data'
  171. u_int datalen_; // length of variable size buffer
  172. protected:
  173. static Packet* free_;
  174. public: 
  175. Packet* next_;  // for queues and the free list
  176. static int hdrlen_;
  177. Packet() : bits_(0), datalen_(0), next_(0) { }
  178. u_char* const bits() { return (bits_); }
  179. Packet* copy() const;
  180. static Packet* alloc();
  181. static Packet* alloc(int);
  182. inline void allocdata(int);
  183. static void free(Packet*);
  184. inline u_char* access(int off) { if (off < 0) abort(); return (&bits_[of
  185. f]); }  
  186. inline u_char* accessdata() {return data_;}
  187. };
  188. end{verbatim}
  189. end{small}
  190. This class holds a pointer to a generic array of unsigned
  191. characters (commonly called the ``bag of bits'' or BOB for short)
  192. where packet header fields are stored.
  193. It also holds a pointer to packet ``data'' (which is often not used in
  194. simulations).
  195. The code{bits_} variable contains the address of
  196. the first byte of the BOB.
  197. Effectively BOB is (currently implemented as) a concatenation
  198. of all the structures defined for each packet header (by convention,
  199. the structures with names beginning code{hdr_<something>}) that have
  200. been configured in.
  201. BOB generally remains a fixed size throughout a simulation, and
  202. the size is recorded in the code{Packet::hdrlen_} member
  203. variable.
  204. This size is updated during simulator configuration by
  205. OTcl.footnote{It is not intended to be updated after configuration
  206. time.  Doing so {em should} be possible, but is currently untested.}
  207. The other methods of the code{Packet} class are for creating new
  208. packets and storing old (unused) ones on a private free list.
  209. Such allocation and deallocation is performed by the
  210. following code (in code{packet.h}):
  211. begin{small}
  212. begin{verbatim}
  213.         inline Packet* Packet::alloc()
  214.         {
  215.                 Packet* p = free_;
  216.                 if (p != 0)
  217.                         free_ = p->next_;
  218.                 else {
  219.                         p = new Packet;
  220.                         p->bits_ = new u_char[hdrsize_];
  221.                         if (p == 0 || p->bits_ == 0)
  222.                                 abort();
  223.                 }
  224.                 return (p);
  225.         }
  226. /* allocate a packet with an n byte data buffer */
  227. inline Packet* Packet::alloc(int n)
  228. {
  229. Packet* p = alloc();
  230. if (n > 0)
  231.        p->allocdata(n);
  232. return (p);
  233. }
  234. /* allocate an n byte data buffer to an existing packet */
  235. inline void Packet::allocdata(int n)
  236. {       
  237. datalen_ = n; 
  238. data_ = new u_char[n];
  239. if (data_ == 0)
  240. abort();
  241.  
  242. }       
  243. inline void Packet::free(Packet* p)
  244. {
  245. p->next_ = free_;
  246. free_ = p;
  247. if (p->datalen_) {
  248. delete p->data_;
  249. p->datalen_ = 0;
  250. }
  251. }       
  252.  
  253. inline Packet* Packet::copy() const
  254. {               
  255. Packet* p = alloc();
  256. memcpy(p->bits(), bits_, hdrlen_);  
  257. if (datalen_) { 
  258. p->datalen_ = datalen_;
  259. p->data_ = new u_char[datalen_];
  260. memcpy(p->data_, data_, datalen_);
  261. }
  262. return (p);
  263. }
  264. end{verbatim}
  265. end{small}
  266. The code{alloc} method is a support function commonly
  267. used to create new packets.
  268. It is most often called by the code{Agent::allocpkt()} method on
  269. behalf of agents and is thus not normally invoked directly by most objects.
  270. It first attempts to locate an old packet on the free list and
  271. if this fails allocates a new one using the C++ code{new} operator.
  272. Note that code{Packet} class objects and BOBs are
  273. allocated separately.
  274. The code{free} method frees a packet by returning it to the free
  275. list.
  276. Note that {bf packets are never returned to the system's memory
  277. allocator}.
  278. Instead, they are stored on a free list when code{Packet::free} is called.
  279. The code{copy} member creates a new, identical copy of a packet
  280. with the exception of the code{uid} field, which is unique.
  281. This function is used by code{Replicator} objects to support
  282. multicast distribution and LANs.
  283. subsubsection{shdr{the hdr_cmn class}{packet.h}{sec:commonhdr}}
  284. Each packet in the simulator has a ``common''
  285. header which is defined in code{packet.h} as follows:
  286. begin{small}
  287. begin{verbatim}
  288. struct hdr_cmn {
  289. double  ts_;            // timestamp: for q-delay measurement
  290. int     ptype_;         // packet type (see above)
  291. int     uid_;           // unique id 
  292. int     size_;          // simulated packet size
  293. int     iface_;         // receiving interface (label)
  294.  
  295. /* per-field member functions */
  296. int& ptype() { return (ptype_); }
  297. int& uid() { return (uid_); }
  298. int& size() { return (size_); }
  299. int& iface() { return (iface_); }
  300. double& timestamp() { return (ts_); }
  301. }; 
  302. end{verbatim}
  303. end{small}
  304. This structure primarily defines fields used for tracing
  305. the flow of packets or measuring other quantities.
  306. The time stamp field is used to measure queueing delay
  307. at switch nodes.
  308. The code{ptype_} field is used to identify the
  309. type of packets, which makes reading traces simpler.
  310. The code{uid_} field is used by the scheduler in scheduling
  311. packet arrivals.
  312. The code{size_} field is of general use and gives the
  313. simulated packet's size.
  314. Note that the actual number of bytes consumed in the simulation
  315. may not relate to the value of this field.
  316. Rather, it is used most often in computing the time required for a packet
  317. to be delivered along a network link.
  318. The code{iface_} field is used by the simulator when performing
  319. multicast distribution tree computations.
  320. It is a label indicating (typically) on which link a packet was received.
  321. subsubsection{shdr{the PacketHeaderManager class}{packet.cc}{sec:packethdrmgr}}
  322. An object of the class code{PacketHeaderManager} is used
  323. to manage the set of currently-active packet header types and
  324. assign each of them unique offsets in the BOB.
  325. It is defined in both the C++ and OTcl code:
  326. begin{small}
  327. begin{verbatim}
  328. From tcl/lib/ns-packet.h:
  329. PacketHeaderManager set hdrlen_ 0
  330. #XXX could potentially get rid of this by searching having a more
  331. # uniform offset concept...
  332. foreach pair {
  333. { Common off_cmn_ }
  334. { Mac off_mac_ }
  335. { LL off_ll_ }
  336. { Snoop off_snoop_ }
  337. { IP off_ip_ }
  338. { TCP off_tcp_ }
  339. { TCPA off_tcpasym_ }
  340. { Flags off_flags_ }
  341. { RTP off_rtp_ }
  342. { Message off_msg_ }
  343. { IVS off_ivs_ }
  344. { rtProtoDV off_DV_ }
  345. { CtrMcast off_CtrMcast_ }
  346. { Prune off_prune_ }
  347. { Tap off_tap_ }
  348. { aSRM off_asrm_ }
  349. { SRM off_srm_ }} {
  350. set cl [lindex $pair 0]
  351. set var [lindex $pair 1]
  352. PacketHeaderManager set vartab_($cl) $var
  353. }    
  354. Simulator instproc create_packetformat { } {
  355. set pm [new PacketHeaderManager]
  356. foreach oclass [PacketHeader info subclass] {
  357. set L [split $oclass /]
  358. set cl [lindex $L 1]
  359. set var [PacketHeaderManager set vartab_($cl)]
  360. set off [$pm allochdr $cl]
  361. TclObject set $var $off
  362. }       
  363. $self set packetManager_ $pm
  364. }    
  365. PacketHeaderManager instproc allochdr cl {
  366. set size [PacketHeader/$cl set hdrlen_]
  367.      
  368. $self instvar hdrlen_ 
  369. set NS_ALIGN 8
  370. # round up to nearest NS_ALIGN bytes
  371. set incr [expr ($size + ($NS_ALIGN-1)) & ~($NS_ALIGN-1)]
  372. set base $hdrlen_
  373. incr hdrlen_ $incr
  374. return $base
  375. }
  376. From packet.cc:
  377. /* manages active packet header types */
  378. class PacketHeaderManager : public TclObject {
  379. public:
  380. PacketHeaderManager() {
  381. bind("hdrlen_", &Packet::hdrlen_);
  382. }
  383. };
  384. end{verbatim}
  385. end{small}
  386. The code in code{ns-packet.tcl} is executed when the
  387. simulator initializes.
  388. Thus, the {tt foreach} statement is executed before the
  389. simulation begins, and initializes the OTcl class array
  390. code{vartab_} to contain the mapping between class
  391. the name and the name of the variable used to contain
  392. that class's header in a packet (which is initialized later).
  393. For example, the value of code{vartab_(IP)} is set to
  394. code{off_ip_}.
  395. The code{create_packetformat} instance procedure is part of the
  396. basic Simulator class and is called one time during simulator
  397. configuration.
  398. It first creates a single code{PacketHeaderManager} object.
  399. The C++ constructor links the OTcl instance
  400. variable code{hdrlen_} (of class code{PacketHeaderManager})
  401. to the C++ variable code{Packet::hdrlen_} (a static
  402. member of the code{Packet} class).
  403. This has the effect of setting code{Packet::hdrlen_} to
  404. zero.
  405. Note that binding across class types in this fashion is
  406. unusual.
  407. label{sec:configpacket}
  408. After creating the packet manager, the code{foreach}
  409. loop enables each of the packet headers of interest.
  410. This loop iterates through the list of defined
  411. packet headers of the form
  412. $(h_i, o_i)$ where $h_i$ is the name of the  $i$th header
  413. and $o_i$ is the name of the variable containing the
  414. location of the $h_i$ header in BOB.
  415. The placement of headers is performed by the code{allochdr}
  416. instproc of the code{PacketHeaderManager} OTcl class.
  417. The procedure keeps a running variable code{hdrlen_} with
  418. the current length of BOB as new packet headers are enabled.
  419. It also arranges for 8-byte alignment for any newly-enabled packet
  420. header.
  421. This is needed to ensure that when double-world length quantities
  422. are used in packet headers on machines where double-word alignment
  423. is required, access faults are not produced.footnote{In
  424. some processer architectures, including the
  425. Sparc and HP-PA, double-word access must be performed on a double-word
  426. boundary (i.e. addresses ending in 0 mod 8).  Attempting to perform
  427. unaligned accesses result in an abnormal program termination.}.