|
Home >
Real-time Mantra >
Design Patterns > Protocol Packet Design Pattern
|
|
|
Simplify buffer management in protocol stacks by supporting a single buffer that allows addition and extraction of different protocol layers.
A protocol stack generally handles multiple layers of a protocol. Each layer of the protocol adds its own headers and trailers. Due to these headers and trailers, the size of the buffer containing the message keeps changing. In most implementations this results in each layer allocating a new buffer to adjust to the changed buffer size. The Protocol Packet pattern addresses this issue with a simple and efficient buffering architecture.
This design pattern can be applied in any protocol scenario involving multiple layers.
This pattern is implemented by just one class, the Protocol Packet. This class works on a raw buffer that is capable of holding the entire packet with protocol headers added for all the layers in the protocol stack. The raw buffer is dynamically partitioned into three regions:
As the message moves from one layer to the the other the location of the different regions is adjusted. The region adjustments are described below:
| Layer 1 Header Region | Transmitted Bytes Body Region | |||
| Layer 2 Header Region | Layer 1 Body Region | |||
| Layer 3 Header Region | Layer 2 Body Region | |||
| Application Body Region | Layer 3 Body Region | |||
| Layer 3 Trailer Region | ||||
| Layer 2 Trailer Region | ||||
| Layer 1 Trailer Region |
The figure above shows the adjustments to the region definition as an application packet moves through the different layers for transmission:
| Received Bytes Body Region | Layer 1 Header Region | |||
| Layer 1 Body Region | Layer 2 Header Region | |||
| Layer 2 Body Region | Layer 3 Header Region | |||
| Layer 3 Body Region | Application Body Region | |||
| Layer 3 Trailer Region | ||||
| Layer 2 Trailer Region | ||||
| Layer 1 Trailer Region |
The figure above shows how the region definition changes for a received packet:
This pattern is implemented by just one class, the Protocol Packet. The class has three internal constituent regions. These regions are defined by the Region private structure.
The Protocol Packet class contains the header, body and trailer regions. This relationship is shown in the following collaboration graph:

Using this pattern provides allows efficient handling of packets as different layers are added or extracted. A single buffer is used across layers. This reduces the overhead in buffer processing. In addition, this pattern brings uniformity to the design of the protocol stack.
The Protocol Packet class consists of the following methods:
The source code for the Protocol_Packet class is presented below:
| Protocol Packet |
00032 class Protocol_Packet 00033 { 00036 enum { MAXIMUM_PACKET_LENGTH = 1500}; 00037 00039 struct Region 00040 { 00043 int offset; 00044 00046 int length; 00047 }; 00048 00051 Region m_header; 00052 00055 Region m_body; 00056 00059 Region m_trailer; 00060 00063 char m_buffer[MAXIMUM_PACKET_LENGTH]; 00064 public: 00065 00091 00092 Protocol_Packet(int body_Length, int body_Offset) 00093 { 00094 m_header.length = 0; 00095 m_trailer.length = 0; 00096 m_body.offset = body_Offset; 00097 m_body.length = body_Length; 00098 } 00099 00109 00110 void Add_Header(int length) 00111 { 00112 // Consider the header of the higher layer to be a part of 00113 // the body for the this layer. 00114 m_body.offset -= m_header.length; 00115 m_body.length += m_header.length; 00116 00117 // Save the length and header offset of the new layer. Addition 00118 // of the header would move up the header offset. 00119 m_header.length = length; 00120 m_header.offset = m_body.offset - length; 00121 } 00122 00131 00132 void Add_Trailer(int length) 00133 { 00134 // Consider the trailer of the higher layer to be a part of 00135 // the body of this layer. 00136 m_body.length += m_trailer.length; 00137 00138 // Now add the trailer at the end of the updated body. 00139 m_trailer.length = length; 00140 m_trailer.offset = m_body.offset + m_body.length; 00141 } 00142 00153 00154 void Extract_Header(int length) 00155 { 00156 // Update the new header. The header begins at current 00157 // body start offset. 00158 m_header.offset = m_body.offset; 00159 m_header.length = length; 00160 00161 // Reduce the body size to account for the removed header. 00162 m_body.offset += length; 00163 m_body.length -= length; 00164 } 00165 00174 00175 void Extract_Trailer(int length) 00176 { 00177 // Reduce the length to adjust for the extracted trailer. 00178 m_body.length -= length; 00179 00180 // Setup the trailer to start at the end of the body. 00181 m_trailer.offset = m_body.offset + m_body.length; 00182 m_trailer.length = length; 00183 } 00184 00186 char *Get_Header() 00187 { 00188 return (&m_buffer[m_header.offset]); 00189 } 00190 00192 char *Get_Body() 00193 { 00194 return (&m_buffer[m_body.offset]); 00195 } 00196 00198 char *Get_Trailer() 00199 { 00200 return (&m_buffer[m_trailer.offset]); 00201 } 00202 00205 int Get_Length() 00206 { 00207 return (m_header.length + m_body.length + m_trailer.length); 00208 } 00209 }; |
| Explore More... |
|
|
|