EventHelix.com: CASE Tools; Real-time and Embedded System Design; Object Oriented Design
  Home  |  EventStudio System Designer 4.0  |  VisualEther Protocol Analyzer 1.0  Real-time Mantra  Contact Us

Home > Real-time Mantra > Design Patterns > Protocol Stack Design Pattern
Protocol Stack Design Pattern

Intent

We have already seen that Protocol Layer and Protocol Packet provide a standardized interface between different layers of a protocol. The Protocol Stack design pattern takes advantage of the layer decoupling and provides a mechanism for dynamic insertion and removal of protocol layers from a stack.

Also Known As

  • Protocol Layer Manager
  • Protocol Layer Collection

Motivation

Protocol stacks tend to be rigid in design and protocol layers cannot be dynamically added or removed from a protocol stack. This limits the use of protocol stacks in the even changing world of protocol standards. There are several scenarios where the layers in a protocol stack need to be changed on the fly. A few examples are:

  • An application detects the failure of the physical layer and decides to use a different medium to transport data. The application decides to change the lower layers of the protocol while keeping the upper layers intact.
  • The user has enabled encryption and this requires the sandwiching of the encryption layer between the network layer and the data-link layer.
  • The protocol stack designer needs to debug the interactions between the network layer and transport layer. This can be accomplished by sandwiching a pass-through logging layer that stores all the messages that get exchanged between the layers.

The Protocol Stack design pattern addresses this issue and introduces a flexible architecture for dynamic addition and removal of protocol layers.

Applicability

The Protocol Stack Design pattern can be used to implement any type of layered protocol. It can be also used when different operations on an entity need to be performed in a pipeline fashion. Each stage of the pipeline could be modeled as a layer. This pattern is particularly useful in applications involving dynamic layer manipulation. A few applications are:

  • Changing the physical layer when the application detects failure of the physical layer.
  • Dynamically adding layers to handle demands from the user session (e.g. enabling encryption)
  • Debugging inter-layer interactions by adding a pass-through debug only layer.
  • Testing higher layers of a protocol by adding a special loop-back layer to connect the lower layer transmit and receive.
  • Emulating a node by configuring a echo-back layer to connect the higher layer transmit and receive.

Structure

The Protocol Stack Design Pattern is implemented by the Protocol Stack class. This class maintains a doubly linked list of active layers.

Participants

The key actors of this design pattern:

  • Protocol Stack: This class maintains a doubly linked list of Protocol layers. It supports dynamic addition and removal of protocol layers.
  • Protocol Layer: This is the base class for all protocol layers. The individual layers interface with each other via pointers to this class. The actual type of the upper layer and lower layer classes is not known to the implementers of a certain layer.

Collaboration

The following diagram shows the relationship and collaboration between various classes needed for the Datalink layer example. 

Collaboration graph

Consequences

The Protocol Stack design pattern breaks down the rigid protocol layer structure and provides a very flexible solution where layers can be dynamically added and removed from the stack.

The figure below shows the flexibility of the pattern in supporting different layer organizations. The examples in the figure demonstrate:

  • A debug pass-through layer that displays the messages being exchanged between the datalink layer and the physical layer.
  • A loopback layer that facilitates the testing of the datalink and network layers by just looping back all transmitted messages back for receive.
  • An echo-back layer allows the protocol stack to emulate a node by just echoing back all higher layer messages back for transmission.
  • An encryption layer sandwiched between the datalink and physical layers. This layers encrypts and decrypts data that is passed between these layers.

Protocol stack configurations with debug layer, a loopback layer, and echo back layer and an encryption layer.

Implementation

The Protocol Stack is implemented as a single class. The class maintains a doubly linked list of Protocol Layers. Important methods of the class are:

  • Handle_Transmit: This handler is invoked by the application to transmit messages using the protocol stack.
  • Handle_Receive: This handler is invoked by the device to pass received messages to the protocol stack.
  • Add_Layer: Add a protocol layer at a specific position in the protocol stack.
  • Remove_Layer: Remove a layer from the protocol stack.

Sample Code and Usage

The code for the Protocol Stack class is presented below:

Protocol Stack Header File
00009 #ifndef PROTOCOL_STACK_H
00010 #define PROTOCOL_STACK_H
00011 
00012 #include <stdio.h>
00013 
00014 class Protocol_Packet;
00015 class Protocol_Layer;
00016 
00035 
00036 class Protocol_Stack
00037 {
00038 public:
00039 
00041     enum Placement
00042     {
00043         TOP,  
00044         ABOVE,
00045         BELOW
00046     };
00047 
00048     void Handle_Transmit(Protocol_Packet *p_Packet);
00049     void Handle_Receive(Protocol_Packet *p_Packet);
00050 
00051     void Add_Layer(Protocol_Layer *p_Layer, Placement placement = TOP, 
                         Protocol_Layer *p_Existing_Layer = NULL);
00052     void Remove_Layer(Protocol_Layer *p_Layer);
00053 
00054     Protocol_Stack();
00055 
00056 private:
00057 
00061     Protocol_Layer *m_p_Highest_Layer;
00062 
00066     Protocol_Layer *m_p_Lowest_Layer;
00067 };
00068 #endif

 

Protocol Stack Source File
00009 #include "Protocol_Stack.h"
00010 #include "Protocol_Layer.h"
00011 #include <assert.h>
00012 
00021 
00022 void Protocol_Stack::Handle_Transmit(Protocol_Packet *p_Packet)
00023 {
00024     if (m_p_Highest_Layer)
00025     {
00026         m_p_Highest_Layer->Transmit(p_Packet);
00027     }
00028 }
00029 
00039 
00040 void Protocol_Stack::Handle_Receive(Protocol_Packet *p_Packet)
00041 {
00042     if (m_p_Lowest_Layer)
00043     {
00044         m_p_Lowest_Layer->Handle_Receive(p_Packet);
00045     }
00046 }
00047 
00061 
00062 void Protocol_Stack::Add_Layer(Protocol_Layer *p_Layer, Placement placement, 
                                       Protocol_Layer *p_Existing_Layer)
00063 {
00064     // Start with a clean slate. Initialize the upper and lower protocol
00065     // layers to NULL. The pointers will be suitably initialized after insertion.
00066 
00067     p_Layer->Set_Lower_Layer(NULL);
00068     p_Layer->Set_Upper_Layer(NULL);
00069 
00070     // Check if some other layer is already present in the protocol stack. 
00071     // The placement processing applies only if this is not the first layer 
00072     // being added to the stack.
00073     if (m_p_Highest_Layer)
00074     {
00075         // This is not the first layer
00076 
00077         switch (placement)
00078         {
00079         case TOP:   // Add the layer at the top
00080             assert(p_Existing_Layer == NULL);
00081             m_p_Highest_Layer->Set_Upper_Layer(p_Layer);
00082             p_Layer->Set_Lower_Layer(m_p_Highest_Layer);
00083             m_p_Highest_Layer = p_Layer;
00084             break;
00085 
00086         case ABOVE: // Place the layer above the existing layer
00087             assert(p_Existing_Layer);
00088 
00089             Protocol_Layer *p_Previous_Upper_Layer;
00090 
00091             // Linking up the new layer above the existing layer
00092             p_Previous_Upper_Layer = p_Existing_Layer->Get_Upper_Layer();
00093             p_Layer->Set_Upper_Layer(p_Previous_Upper_Layer);
00094             p_Layer->Set_Lower_Layer(p_Existing_Layer);
00095             p_Existing_Layer->Set_Upper_Layer(p_Layer);
00096 
00097             // Check if the existing layer was the highest layer
00098             if (p_Existing_Layer == m_p_Highest_Layer)
00099             {
00100                 // If it was, make the new layer the highest layer
00101                 m_p_Highest_Layer = p_Layer;
00102             }
00103             else
00104             {
00105                 // Change the pointer of the existing layer's upper layer
00106                 // to point to the newly inserted layer.
00107                 p_Previous_Upper_Layer->Set_Lower_Layer(p_Layer);
00108             }
00109             break;
00110 
00111         case BELOW:    // Place the layer below the existing layer
00112 
00113             assert(p_Existing_Layer);
00114             Protocol_Layer *p_Previous_Lower_Layer;
00115 
00116             // Linking up the new layer below the existing layer
00117             p_Previous_Lower_Layer = p_Existing_Layer->Get_Lower_Layer();
00118             p_Layer->Set_Upper_Layer(p_Existing_Layer);
00119             p_Layer->Set_Lower_Layer(p_Previous_Lower_Layer);
00120             p_Existing_Layer->Set_Lower_Layer(p_Layer);
00121 
00122             // Check if the existing layer was the lowest layer
00123             if (p_Existing_Layer == m_p_Lowest_Layer)
00124             {
00125                 // If it was, make the new layer the lowest layer
00126                 m_p_Lowest_Layer = p_Layer;
00127             }
00128             else
00129             {
00130                 // Change the pointer of the existing layer's lower layer
00131                 // to point to the newly inserted layer.
00132                 p_Previous_Lower_Layer->Set_Upper_Layer(p_Layer);
00133             }
00134             break;
00135 
00136         }
00137     }
00138     else  // The highest layer is NULL
00139     {
00140         // This means that this is the first layer in the protocol stack.
00141         assert(p_Existing_Layer == NULL);
00142         m_p_Highest_Layer = p_Layer;
00143         m_p_Lowest_Layer = p_Layer;
00144     }
00145 }
00146 
00150 
00151 void Protocol_Stack::Remove_Layer(Protocol_Layer *p_Layer)
00152 {
00153     // Check if the layer to be removed is the highest layer.
00154     if (p_Layer == m_p_Highest_Layer)
00155     {
00156         // Yes it is, so set the removed layer's lower layer as the highest layer
00157         // in the protocol stack.
00158         m_p_Highest_Layer = p_Layer->Get_Lower_Layer();
00159 
00160         // If this was not the only layer in the stack, set the
00161         // upper layer of this layer as NULL.
00162         if (m_p_Highest_Layer)
00163         {
00164             m_p_Highest_Layer->Set_Upper_Layer(NULL);
00165         }
00166     }
00167     else // Not the highest layer
00168     {
00169         // Stitch the upper layer to lower layer link after the layer is removed.
00170         (p_Layer->Get_Upper_Layer())->Set_Lower_Layer(p_Layer->Get_Lower_Layer());
00171     }
00172 
00173     // Check if the layer to be removed is the lowest layer.
00174     if (p_Layer == m_p_Lowest_Layer)
00175     {
00176         // Yes it is, so set the removed layer's upper layer as the lowest layer
00177         // in the protocol stack.
00178         m_p_Lowest_Layer = p_Layer->Get_Upper_Layer();
00179 
00180         // If this was not the only layer in the stack, set the
00181         // lower layer of this layer as NULL.
00182         if (m_p_Lowest_Layer)
00183         {
00184             m_p_Lowest_Layer->Set_Lower_Layer(NULL);
00185         }
00186     }
00187     else
00188     {
00189         // Stitch the lower layer to upper layer link after the layer is removed.
00190         (p_Layer->Get_Lower_Layer())->Set_Upper_Layer(p_Layer->Get_Upper_Layer());
00191     }
00192 
00193     // Set the upper and lower layer pointers of the removed layer as NULL.
00194     // This is a safety measure.
00195     p_Layer->Set_Lower_Layer(NULL);
00196     p_Layer->Set_Upper_Layer(NULL);
00197 }
00198 
00201 
00202 Protocol_Stack::Protocol_Stack()
00203 {
00204     m_p_Highest_Layer = NULL;
00205     m_p_Lowest_Layer = NULL;
00206 }

Known Uses

The Protocol Stack design pattern can be used where ever a layered but decoupled organization is required.

Related Patterns/Principles

Explore More...

 

 

  Home  |  EventStudio System Designer 4.0  |  VisualEther Protocol Analyzer 1.0  Real-time Mantra  Contact Us
Copyright © 2000-2010 EventHelix.com Inc. All Rights Reserved.