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

(-)a/src/lte/model/epc-tft-classifier.cc (-46 / +131 lines)
 Lines 48-57    Link Here 
48
void
48
void
49
EpcTftClassifier::Add (Ptr<EpcTft> tft, uint32_t id)
49
EpcTftClassifier::Add (Ptr<EpcTft> tft, uint32_t id)
50
{
50
{
51
  NS_LOG_FUNCTION (this << tft);
51
  NS_LOG_FUNCTION (this << tft << id);
52
  
52
  m_tftMap[id] = tft;
53
  m_tftMap[id] = tft;  
53
54
  
55
  // simple sanity check: there shouldn't be more than 16 bearers (hence TFTs) per UE
54
  // simple sanity check: there shouldn't be more than 16 bearers (hence TFTs) per UE
56
  NS_ASSERT (m_tftMap.size () <= 16);
55
  NS_ASSERT (m_tftMap.size () <= 16);
57
}
56
}
 Lines 67-73    Link Here 
67
uint32_t 
66
uint32_t 
68
EpcTftClassifier::Classify (Ptr<Packet> p, EpcTft::Direction direction)
67
EpcTftClassifier::Classify (Ptr<Packet> p, EpcTft::Direction direction)
69
{
68
{
70
  NS_LOG_FUNCTION (this << p << direction);
69
  NS_LOG_FUNCTION (this << p << p->GetSize () << direction);
71
70
72
  Ptr<Packet> pCopy = p->Copy ();
71
  Ptr<Packet> pCopy = p->Copy ();
73
72
 Lines 105-112    Link Here 
105
        }
104
        }
106
      NS_LOG_INFO ("local address: " << localAddressIpv4 << " remote address: " << remoteAddressIpv4);
105
      NS_LOG_INFO ("local address: " << localAddressIpv4 << " remote address: " << remoteAddressIpv4);
107
106
107
      uint16_t payloadSize = ipv4Header.GetPayloadSize ();
108
      uint16_t fragmentOffset = ipv4Header.GetFragmentOffset ();
109
      bool isLastFragment = ipv4Header.IsLastFragment ();
110
111
      // NS_LOG_DEBUG ("PayloadSize = " << payloadSize);
112
      // NS_LOG_DEBUG ("fragmentOffset " << fragmentOffset << " isLastFragment " << isLastFragment);
113
108
      protocol = ipv4Header.GetProtocol ();
114
      protocol = ipv4Header.GetProtocol ();
109
      tos = ipv4Header.GetTos ();
115
      tos = ipv4Header.GetTos ();
116
117
      // Port info only can be get if it is the first fragment and
118
      // there is enough data in the payload
119
      // We keep the port info for fragmented packets,
120
      // i.e. it is the first one but it is not the last one
121
      if (fragmentOffset == 0)
122
        {
123
          if (protocol == UdpL4Protocol::PROT_NUMBER && payloadSize >= 8)
124
            {
125
              UdpHeader udpHeader;
126
              pCopy->RemoveHeader (udpHeader);
127
              if (direction ==  EpcTft::UPLINK)
128
                {
129
                  localPort = udpHeader.GetSourcePort ();
130
                  remotePort = udpHeader.GetDestinationPort ();
131
                }
132
              else
133
                {
134
                  remotePort = udpHeader.GetSourcePort ();
135
                  localPort = udpHeader.GetDestinationPort ();
136
                }
137
              if (!isLastFragment)
138
                {
139
                  std::tuple<uint32_t, uint32_t, uint8_t, uint16_t> fragmentKey =
140
                      std::make_tuple (ipv4Header.GetSource ().Get (),
141
                                       ipv4Header.GetDestination ().Get (),
142
                                       protocol,
143
                                       ipv4Header.GetIdentification ());
144
145
                  m_classifiedIpv4Fragments[fragmentKey] = std::make_pair (localPort, remotePort);
146
                }
147
            }
148
          else if (protocol == TcpL4Protocol::PROT_NUMBER && payloadSize >= 20)
149
            {
150
              TcpHeader tcpHeader;
151
              pCopy->RemoveHeader (tcpHeader);
152
              if (direction ==  EpcTft::UPLINK)
153
                {
154
                  localPort = tcpHeader.GetSourcePort ();
155
                  remotePort = tcpHeader.GetDestinationPort ();
156
                }
157
              else
158
                {
159
                  remotePort = tcpHeader.GetSourcePort ();
160
                  localPort = tcpHeader.GetDestinationPort ();
161
                }
162
163
              if (!isLastFragment)
164
                {
165
                  std::tuple<uint32_t, uint32_t, uint8_t, uint16_t> fragmentKey =
166
                      std::make_tuple (ipv4Header.GetSource ().Get (),
167
                                       ipv4Header.GetDestination ().Get (),
168
                                       protocol,
169
                                       ipv4Header.GetIdentification ());
170
171
                  m_classifiedIpv4Fragments[fragmentKey] = std::make_pair (localPort, remotePort);
172
                }
173
            }
174
175
          // else
176
          //   First fragment but not enough data for port info or not UDP/TCP protocol.
177
          //   Nothing can be done, i.e. we cannot get port info from packet.
178
        }
179
      else
180
        {
181
          // Not first fragment, so port info is not available but
182
          // port info should already be known (if there is not fragment reordering)
183
          std::tuple<uint32_t, uint32_t, uint8_t, uint16_t> fragmentKey =
184
              std::make_tuple (ipv4Header.GetSource ().Get (),
185
                               ipv4Header.GetDestination ().Get (),
186
                               protocol,
187
                               ipv4Header.GetIdentification ());
188
189
          std::map< std::tuple<uint32_t, uint32_t, uint8_t, uint16_t>,
190
                    std::pair<uint32_t, uint32_t> >::iterator it =
191
              m_classifiedIpv4Fragments.find (fragmentKey);
192
193
          if (it != m_classifiedIpv4Fragments.end ())
194
            {
195
              localPort = it->second.first;
196
              remotePort = it->second.second;
197
198
              if (isLastFragment)
199
                {
200
                  m_classifiedIpv4Fragments.erase (fragmentKey);
201
                }
202
            }
203
        }
110
    }
204
    }
111
  else if (ipType == 0x06)
205
  else if (ipType == 0x06)
112
    {
206
    {
 Lines 128-180    Link Here 
128
222
129
      protocol = ipv6Header.GetNextHeader ();
223
      protocol = ipv6Header.GetNextHeader ();
130
      tos = ipv6Header.GetTrafficClass ();
224
      tos = ipv6Header.GetTrafficClass ();
225
226
      if (protocol == UdpL4Protocol::PROT_NUMBER)
227
        {
228
          UdpHeader udpHeader;
229
          pCopy->RemoveHeader (udpHeader);
230
231
          if (direction ==  EpcTft::UPLINK)
232
            {
233
              localPort = udpHeader.GetSourcePort ();
234
              remotePort = udpHeader.GetDestinationPort ();
235
            }
236
          else
237
            {
238
              remotePort = udpHeader.GetSourcePort ();
239
              localPort = udpHeader.GetDestinationPort ();
240
            }
241
        }
242
      else if (protocol == TcpL4Protocol::PROT_NUMBER)
243
        {
244
          TcpHeader tcpHeader;
245
          pCopy->RemoveHeader (tcpHeader);
246
          if (direction ==  EpcTft::UPLINK)
247
            {
248
              localPort = tcpHeader.GetSourcePort ();
249
              remotePort = tcpHeader.GetDestinationPort ();
250
            }
251
          else
252
            {
253
              remotePort = tcpHeader.GetSourcePort ();
254
              localPort = tcpHeader.GetDestinationPort ();
255
            }
256
        }
131
    }
257
    }
132
  else
258
  else
133
    {
259
    {
134
      NS_ABORT_MSG ("EpcTftClassifier::Classify - Unknown IP type...");
260
      NS_ABORT_MSG ("EpcTftClassifier::Classify - Unknown IP type...");
135
    }
261
    }
136
262
137
  if (protocol == UdpL4Protocol::PROT_NUMBER)
138
    {
139
      UdpHeader udpHeader;
140
      pCopy->RemoveHeader (udpHeader);
141
142
      if (direction ==  EpcTft::UPLINK)
143
        {
144
          localPort = udpHeader.GetSourcePort ();
145
          remotePort = udpHeader.GetDestinationPort ();
146
        }
147
      else
148
        {
149
          remotePort = udpHeader.GetSourcePort ();
150
          localPort = udpHeader.GetDestinationPort ();
151
        }
152
    }
153
  else if (protocol == TcpL4Protocol::PROT_NUMBER)
154
    {
155
      TcpHeader tcpHeader;
156
      pCopy->RemoveHeader (tcpHeader);
157
      if (direction ==  EpcTft::UPLINK)
158
        {
159
          localPort = tcpHeader.GetSourcePort ();
160
          remotePort = tcpHeader.GetDestinationPort ();
161
        }
162
      else
163
        {
164
          remotePort = tcpHeader.GetSourcePort ();
165
          localPort = tcpHeader.GetDestinationPort ();
166
        }
167
    }
168
  else if (protocol == Icmpv6L4Protocol::PROT_NUMBER || protocol == Icmpv4L4Protocol::PROT_NUMBER)
169
    {
170
      remotePort = 0;
171
      localPort = 0;
172
    }
173
  else
174
    {
175
      NS_LOG_INFO ("Unknown protocol: " << protocol);
176
      return 0;  // no match
177
    }
178
263
179
  if (ipType == 0x04)
264
  if (ipType == 0x04)
180
    {
265
    {
(-)a/src/lte/model/epc-tft-classifier.h (-4 / +24 lines)
 Lines 36-44    Link Here 
36
class Packet;
36
class Packet;
37
37
38
/**
38
/**
39
 * \brief classifies IP packets accoding to Traffic Flow Templates (TFTs)
39
 * \brief classifies IP packets according to Traffic Flow Templates (TFTs)
40
 * 
40
 *
41
 * \note this implementation works with IPv4 only.
41
 * \note this implementation works with IPv4 and IPv6.
42
 * When there is fragmentation of IP packets, UDP/TCP ports maybe missing.
43
 *
44
 * The following actions are performed to use the port info present in the first segment with
45
 * the next fragments:
46
 *  - Port info is stored if it is available, i.e. it is the first fragment with UDP/TCP protocol
47
 *    and there is enough data in the payload of the IP packet for the port numbers.
48
 *  - Port info is used for the next fragments.
49
 *  - Port info is deleted, when the last fragment is processed.
50
 *
51
 * When we cannot cache the port info, the TFT of the default bearer is used. This may happen
52
 * if there is reordering or losses of IP packets.
42
 */
53
 */
43
class EpcTftClassifier : public SimpleRefCount<EpcTftClassifier>
54
class EpcTftClassifier : public SimpleRefCount<EpcTftClassifier>
44
{
55
{
 Lines 76-82    Link Here 
76
protected:
87
protected:
77
  
88
  
78
  std::map <uint32_t, Ptr<EpcTft> > m_tftMap; ///< TFT map
89
  std::map <uint32_t, Ptr<EpcTft> > m_tftMap; ///< TFT map
79
  
90
91
  std::map < std::tuple<uint32_t, uint32_t, uint8_t, uint16_t>,
92
             std::pair<uint32_t, uint32_t> >
93
      m_classifiedIpv4Fragments; ///< Map with already classified IPv4 Fragments
94
                                 ///< An entry is added when the port info is available, i.e.
95
                                 ///<   first fragment, UDP/TCP protocols and enough payload data
96
                                 ///< An entry is used if port info is not available, i.e.
97
                                 ///<   not first fragment or not enough payload data for TCP/UDP
98
                                 ///< An entry is removed when the last fragment is classified
99
                                 ///<   Note: If last fragment is lost, entry is not removed
80
};
100
};
81
101
82
102
(-)a/src/lte/test/test-epc-tft-classifier.cc (-4 / +5 lines)
 Lines 116-129    Link Here 
116
    m_d (d),    
116
    m_d (d),    
117
    m_tftId (tftId)
117
    m_tftId (tftId)
118
{
118
{
119
  NS_LOG_FUNCTION (this);
119
  NS_LOG_FUNCTION (this << c << d << sa << da << sp << dp << tos << tftId);
120
120
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); // 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);
127
}
128
}
128
129
129
EpcTftClassifierTestCase::~EpcTftClassifierTestCase ()
130
EpcTftClassifierTestCase::~EpcTftClassifierTestCase ()
 Lines 163-169    Link Here 
163
  udpPacket->AddHeader (m_ipHeader);
164
  udpPacket->AddHeader (m_ipHeader);
164
  NS_LOG_LOGIC (this << *udpPacket);
165
  NS_LOG_LOGIC (this << *udpPacket);
165
  uint32_t obtainedTftId = m_c ->Classify (udpPacket, m_d);
166
  uint32_t obtainedTftId = m_c ->Classify (udpPacket, m_d);
166
  NS_TEST_ASSERT_MSG_EQ (obtainedTftId, m_tftId, "bad classification of UDP packet");
167
  NS_TEST_ASSERT_MSG_EQ (obtainedTftId, (uint16_t) m_tftId, "bad classification of UDP packet");
167
}
168
}
168
169
169
170

Return to bug 2277