View | Details | Raw Unified | Return to bug 2277
Collapse All | Expand All

(-)original/src/lte/model/epc-tft-classifier.cc (-77 / +151 lines)
 Lines 24-31    Link Here 
24
 */
24
 */
25
25
26
26
27
28
29
#include "epc-tft-classifier.h"
27
#include "epc-tft-classifier.h"
30
#include "epc-tft.h"
28
#include "epc-tft.h"
31
#include "ns3/log.h"
29
#include "ns3/log.h"
 Lines 48-54    Link Here 
48
void
46
void
49
EpcTftClassifier::Add (Ptr<EpcTft> tft, uint32_t id)
47
EpcTftClassifier::Add (Ptr<EpcTft> tft, uint32_t id)
50
{
48
{
51
  NS_LOG_FUNCTION (this << tft);
49
  NS_LOG_FUNCTION (this << tft << id);
52
  
50
  
53
  m_tftMap[id] = tft;  
51
  m_tftMap[id] = tft;  
54
  
52
  
 Lines 76-165    Link Here 
76
74
77
  Ipv4Address localAddress;
75
  Ipv4Address localAddress;
78
  Ipv4Address remoteAddress;
76
  Ipv4Address remoteAddress;
79
80
  
77
  
81
  if (direction ==  EpcTft::UPLINK)
78
  // Added to be able to classify fragmented packets
82
    {
79
  // The map key is taken from the Ipv4L3Protocol::ProcessFragment method
83
      localAddress = ipv4Header.GetSource ();
80
  // as it is the method used to keep track of fragmented IP packets
84
      remoteAddress = ipv4Header.GetDestination ();
81
  uint64_t addressCombination = uint64_t (ipv4Header.GetSource ().Get ()) << 32 | 
85
    }
82
                                uint64_t (ipv4Header.GetDestination ().Get ());
86
  else
83
  uint32_t idProto = uint32_t (ipv4Header.GetIdentification ()) << 16 | 
87
    { 
84
                     uint32_t (ipv4Header.GetProtocol ());
88
      NS_ASSERT (direction ==  EpcTft::DOWNLINK);
85
  std::pair <uint64_t, uint32_t> key;
89
      remoteAddress = ipv4Header.GetSource ();
86
  key.first = addressCombination;
90
      localAddress = ipv4Header.GetDestination ();      
87
  key.second = idProto;
91
    }
88
92
  
89
  // If an extry exists in the map, it means we already 
93
  uint8_t protocol = ipv4Header.GetProtocol ();
90
  // classified the first fragment.
94
91
  uint32_t teid = 0;
95
  uint8_t tos = ipv4Header.GetTos ();
92
  std::map <std::pair <uint64_t, uint32_t>, uint32_t>::iterator it = m_classifiedIpv4Fragments.find (key);
96
93
97
  uint16_t localPort = 0;
94
  if (it != m_classifiedIpv4Fragments.end ())
98
  uint16_t remotePort = 0;
99
100
  if (protocol == UdpL4Protocol::PROT_NUMBER)
101
    {
95
    {
102
      UdpHeader udpHeader;
96
      // The entry exists, so we use the teid stored 
103
      pCopy->RemoveHeader (udpHeader);
97
      // when the first fragment was classified
104
98
      teid = it->second;
105
      if (direction ==  EpcTft::UPLINK)
99
106
	{
100
      // If this is the last fragment, delete the entry. 
107
	  localPort = udpHeader.GetSourcePort ();
101
      // It is possible that the last fragment arrives before all intermediate
108
	  remotePort = udpHeader.GetDestinationPort ();
102
      // fragments have been classified; in this case, those intermediate fragments
109
	}
103
      // will be sent through the default bearer.
110
      else
104
      //
111
	{
105
      // Also, as this is the only mechanism to delete entries from the map, it is
112
	  remotePort = udpHeader.GetSourcePort ();
106
      // possible that if the last fragment is received before the first fragment,
113
	  localPort = udpHeader.GetDestinationPort ();
107
      // an entry is never deleted.
114
	}
108
      // 
115
    }
109
      // It is possible to address these two potential issues with a stateful 
116
  else if (protocol == TcpL4Protocol::PROT_NUMBER)
110
      // classifier.
117
    {
111
      if (ipv4Header.IsLastFragment ())
118
      TcpHeader tcpHeader;
112
        {
119
      pCopy->RemoveHeader (tcpHeader);
113
          m_classifiedIpv4Fragments.erase (key);
120
      if (direction ==  EpcTft::UPLINK)
114
        }
121
	{
122
	  localPort = tcpHeader.GetSourcePort ();
123
	  remotePort = tcpHeader.GetDestinationPort ();
124
	}
125
      else
126
	{
127
	  remotePort = tcpHeader.GetSourcePort ();
128
	  localPort = tcpHeader.GetDestinationPort ();
129
	}
130
    }
115
    }
131
  else
116
  else
132
    {
117
    {
133
      NS_LOG_INFO ("Unknown protocol: " << protocol);
118
      // There is no entry in the map.
134
      return 0;  // no match
119
      // Now we have three options:
135
    }
120
      //   - This is not the first fragment. We send it through the
121
      //   default bearer.
122
      //   - This is the first fragment  but it is not big enough to 
123
      //   hold all the information we may need from L4 for a classification. 
124
      //   In this case we send all the fragments through the default bearer.
125
      //   - This is the first fragment and we can obtain all information
126
      //   we may need for the classification from L4, so we classify as usual.
127
      uint16_t payloadSize = ipv4Header.GetPayloadSize ();
136
128
137
  NS_LOG_INFO ("Classifing packet:"
129
      if (ipv4Header.GetFragmentOffset () > 0 )
138
	       << " localAddr="  << localAddress 
139
	       << " remoteAddr=" << remoteAddress 
140
	       << " localPort="  << localPort 
141
	       << " remotePort=" << remotePort 
142
	       << " tos=0x" << (uint16_t) tos );
143
144
  // now it is possible to classify the packet!
145
  // we use a reverse iterator since filter priority is not implemented properly.
146
  // This way, since the default bearer is expected to be added first, it will be evaluated last.
147
  std::map <uint32_t, Ptr<EpcTft> >::const_reverse_iterator it;
148
  NS_LOG_LOGIC ("TFT MAP size: " << m_tftMap.size ());
149
150
  for (it = m_tftMap.rbegin (); it != m_tftMap.rend (); ++it)
151
    {
152
      NS_LOG_LOGIC ("TFT id: " << it->first );
153
      NS_LOG_LOGIC (" Ptr<EpcTft>: " << it->second);
154
      Ptr<EpcTft> tft = it->second;         
155
      if (tft->Matches (direction, remoteAddress, localAddress, remotePort, localPort, tos))
156
        {
130
        {
157
	  NS_LOG_LOGIC ("matches with TFT ID = " << it->first);
131
          // Not the first fragment.
158
	  return it->first; // the id of the matching TFT
132
          teid = m_tftMap.begin ()->first;
133
        }
134
      else 
135
        {
136
          uint8_t protocol = ipv4Header.GetProtocol ();
137
          uint8_t tos = ipv4Header.GetTos ();
138
          uint16_t localPort = 0;
139
          uint16_t remotePort = 0;
140
141
          if ( (protocol == UdpL4Protocol::PROT_NUMBER && payloadSize < 8) || 
142
              (protocol == TcpL4Protocol::PROT_NUMBER && payloadSize < 20) )
143
            {
144
              // First fragment, but with not enough information to classify it.
145
              // The whole packet will be sent through the default bearer.
146
              teid = m_tftMap.begin ()->first;
147
              m_classifiedIpv4Fragments.insert (std::make_pair (key, teid));
148
            }
149
          else 
150
            {
151
              // First fragment. Classify as usual.
152
              if (direction ==  EpcTft::UPLINK)
153
                {
154
                  localAddress = ipv4Header.GetSource ();
155
                  remoteAddress = ipv4Header.GetDestination ();
156
                }
157
              else
158
                { 
159
                  NS_ASSERT (direction ==  EpcTft::DOWNLINK);
160
                  remoteAddress = ipv4Header.GetSource ();
161
                  localAddress = ipv4Header.GetDestination ();      
162
                }
163
164
              if (protocol == UdpL4Protocol::PROT_NUMBER)
165
                {
166
                  UdpHeader udpHeader;
167
                  pCopy->RemoveHeader (udpHeader);
168
169
                  if (direction ==  EpcTft::UPLINK)
170
                    {
171
                      localPort = udpHeader.GetSourcePort ();
172
                      remotePort = udpHeader.GetDestinationPort ();
173
                    }
174
                  else
175
                    {
176
                      remotePort = udpHeader.GetSourcePort ();
177
                      localPort = udpHeader.GetDestinationPort ();
178
                    }
179
                }
180
              else if (protocol == TcpL4Protocol::PROT_NUMBER)
181
                {
182
                  TcpHeader tcpHeader;
183
                  pCopy->RemoveHeader (tcpHeader);
184
                  if (direction ==  EpcTft::UPLINK)
185
                    {
186
                      localPort = tcpHeader.GetSourcePort ();
187
                      remotePort = tcpHeader.GetDestinationPort ();
188
                    }
189
                  else
190
                    {
191
                      remotePort = tcpHeader.GetSourcePort ();
192
                      localPort = tcpHeader.GetDestinationPort ();
193
                    }
194
                }
195
              else
196
                {
197
                  NS_LOG_INFO ("Unknown protocol: " << protocol);
198
                  return 0;  // no match
199
                }
200
201
              NS_LOG_INFO ("Classifing packet:"
202
                  << " localAddr="  << localAddress 
203
                  << " remoteAddr=" << remoteAddress 
204
                  << " localPort="  << localPort 
205
                  << " remotePort=" << remotePort 
206
                  << " tos=0x" << (uint16_t) tos );
207
              
208
              // now it is possible to classify the packet!
209
              // we use a reverse iterator since filter priority is not implemented properly.
210
              // This way, since the default bearer is expected to be added first, it will be evaluated last.
211
              std::map <uint32_t, Ptr<EpcTft> >::const_reverse_iterator it;
212
              NS_LOG_LOGIC ("TFT MAP size: " << m_tftMap.size ());
213
214
              for (it = m_tftMap.rbegin (); it != m_tftMap.rend () && teid == 0; ++it)
215
                {
216
                  NS_LOG_LOGIC ("TFT id: " << it->first );
217
                  NS_LOG_LOGIC (" Ptr<EpcTft>: " << it->second);
218
                  Ptr<EpcTft> tft = it->second;         
219
                  if (tft->Matches (direction, remoteAddress, localAddress, remotePort, localPort, tos))
220
                    {
221
                      NS_LOG_LOGIC ("matches with TFT ID = " << it->first);
222
                      teid = it->first; // the id of the matching TFT
223
224
                      // If there are going to be more fragments, create an entry 
225
                      // in the map with the classified IP fragments
226
                      if (! ipv4Header.IsLastFragment ())
227
                        {
228
                          m_classifiedIpv4Fragments.insert (std::make_pair (key, teid));
229
                        }
230
                    }
231
                }
232
            }
159
        }
233
        }
160
    }
234
    }
161
  NS_LOG_LOGIC ("no match");
235
162
  return 0;  // no match
236
  return teid;  // will be 0 if there is no match
163
}
237
}
164
238
165
239
(-)original/src/lte/model/epc-tft-classifier.h (+5 lines)
 Lines 76-81    Link Here 
76
protected:
76
protected:
77
  
77
  
78
  std::map <uint32_t, Ptr<EpcTft> > m_tftMap; ///< TFT map
78
  std::map <uint32_t, Ptr<EpcTft> > m_tftMap; ///< TFT map
79
80
  /**
81
   * Map to keep track of the classification for fragmented IPv4 packets
82
   */
83
  std::map <std::pair <uint64_t, uint32_t>, uint32_t> m_classifiedIpv4Fragments;
79
  
84
  
80
};
85
};
81
86
(-)original/src/lte/test/test-epc-tft-classifier.cc (+1 lines)
 Lines 121-126    Link Here 
121
  m_ipHeader.SetSource (sa);
121
  m_ipHeader.SetSource (sa);
122
  m_ipHeader.SetDestination (da);
122
  m_ipHeader.SetDestination (da);
123
  m_ipHeader.SetTos (tos);  
123
  m_ipHeader.SetTos (tos);  
124
  m_ipHeader.SetPayloadSize (8); // A full UDP header
124
125
125
  m_udpHeader.SetSourcePort (sp);
126
  m_udpHeader.SetSourcePort (sp);
126
  m_udpHeader.SetDestinationPort (dp);  
127
  m_udpHeader.SetDestinationPort (dp);  

Return to bug 2277