3 from framework import tag_fixme_vpp_workers
4 from framework import VppTestCase, VppTestRunner
6 from vpp_udp_encap import find_udp_encap, VppUdpEncap
7 from vpp_udp_decap import VppUdpDecap
8 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, VppMplsLabel, \
9 VppMplsTable, VppMplsRoute, FibPathType, FibPathProto
10 from vpp_neighbor import VppNeighbor
11 from vpp_papi import VppEnum
13 from scapy.packet import Raw
14 from scapy.layers.l2 import Ether
15 from scapy.layers.inet import IP, UDP, ICMP
16 from scapy.layers.inet6 import IPv6
17 from scapy.contrib.mpls import MPLS
22 @tag_fixme_vpp_workers
23 class TestUdpEncap(VppTestCase):
24 """ UDP Encap Test Case """
28 super(TestUdpEncap, cls).setUpClass()
31 def tearDownClass(cls):
32 super(TestUdpEncap, cls).tearDownClass()
35 super(TestUdpEncap, self).setUp()
37 # create 2 pg interfaces
38 self.create_pg_interfaces(range(4))
41 # assign them different tables.
45 for i in self.pg_interfaces:
49 tbl = VppIpTable(self, table_id)
51 self.tables.append(tbl)
52 tbl = VppIpTable(self, table_id, is_ip6=1)
54 self.tables.append(tbl)
56 i.set_table_ip4(table_id)
57 i.set_table_ip6(table_id)
65 for i in self.pg_interfaces:
71 super(TestUdpEncap, self).tearDown()
73 def validate_outer4(self, rx, encap_obj):
74 self.assertEqual(rx[IP].src, encap_obj.src_ip_s)
75 self.assertEqual(rx[IP].dst, encap_obj.dst_ip_s)
76 self.assertEqual(rx[UDP].sport, encap_obj.src_port)
77 self.assertEqual(rx[UDP].dport, encap_obj.dst_port)
79 def validate_outer6(self, rx, encap_obj):
80 self.assertEqual(rx[IPv6].src, encap_obj.src_ip_s)
81 self.assertEqual(rx[IPv6].dst, encap_obj.dst_ip_s)
82 self.assertEqual(rx[UDP].sport, encap_obj.src_port)
83 self.assertEqual(rx[UDP].dport, encap_obj.dst_port)
85 def validate_inner4(self, rx, tx, ttl=None):
86 self.assertEqual(rx[IP].src, tx[IP].src)
87 self.assertEqual(rx[IP].dst, tx[IP].dst)
89 self.assertEqual(rx[IP].ttl, ttl)
91 self.assertEqual(rx[IP].ttl, tx[IP].ttl)
93 def validate_inner6(self, rx, tx, hlim=None):
94 self.assertEqual(rx.src, tx[IPv6].src)
95 self.assertEqual(rx.dst, tx[IPv6].dst)
97 self.assertEqual(rx.hlim, hlim)
99 self.assertEqual(rx.hlim, tx[IPv6].hlim)
101 def test_udp_encap(self):
106 # construct a UDP encap object through each of the peers
107 # v4 through the first two peers, v6 through the second.
108 # The last encap is v4 and is used to check the codepath
109 # where 2 different udp encap objects are processed at the
112 udp_encap_0 = VppUdpEncap(self,
116 udp_encap_1 = VppUdpEncap(self,
121 udp_encap_2 = VppUdpEncap(self,
126 udp_encap_3 = VppUdpEncap(self,
131 udp_encap_4 = VppUdpEncap(self,
135 udp_encap_0.add_vpp_config()
136 udp_encap_1.add_vpp_config()
137 udp_encap_2.add_vpp_config()
138 udp_encap_3.add_vpp_config()
139 udp_encap_4.add_vpp_config()
141 self.logger.info(self.vapi.cli("sh udp encap"))
143 self.assertTrue(find_udp_encap(self, udp_encap_2))
144 self.assertTrue(find_udp_encap(self, udp_encap_3))
145 self.assertTrue(find_udp_encap(self, udp_encap_0))
146 self.assertTrue(find_udp_encap(self, udp_encap_1))
147 self.assertTrue(find_udp_encap(self, udp_encap_4))
150 # Routes via each UDP encap object - all combinations of v4 and v6.
152 route_4o4 = VppIpRoute(
154 [VppRoutePath("0.0.0.0",
156 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
157 next_hop_id=udp_encap_0.id,
158 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)],
160 # specific route to match encap4, to test encap of 2 packets using 2
162 route_4o4_2 = VppIpRoute(
164 [VppRoutePath("0.0.0.0",
166 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
167 next_hop_id=udp_encap_4.id,
168 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)],
170 route_4o6 = VppIpRoute(
172 [VppRoutePath("0.0.0.0",
174 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
175 next_hop_id=udp_encap_2.id,
176 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
177 route_6o4 = VppIpRoute(
178 self, "2001::1", 128,
179 [VppRoutePath("0.0.0.0",
181 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
182 next_hop_id=udp_encap_1.id,
183 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
184 route_6o6 = VppIpRoute(
185 self, "2001::3", 128,
186 [VppRoutePath("0.0.0.0",
188 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
189 next_hop_id=udp_encap_3.id,
190 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
191 route_4o6.add_vpp_config()
192 route_6o6.add_vpp_config()
193 route_6o4.add_vpp_config()
194 route_4o4.add_vpp_config()
195 route_4o4_2.add_vpp_config()
199 # we add a single packet matching the last encap at the beginning of
200 # the packet vector so that we encap 2 packets with different udp
201 # encap object at the same time
203 p_4o4 = (Ether(src=self.pg1.remote_mac,
204 dst=self.pg1.local_mac) /
205 IP(src="2.2.2.2", dst="1.1.0.1") /
206 UDP(sport=1234, dport=1234) /
208 p_4o4_2 = (Ether(src=self.pg1.remote_mac,
209 dst=self.pg1.local_mac) /
210 IP(src="2.2.2.2", dst="1.1.0.2") /
211 UDP(sport=1234, dport=1234) /
213 rx = self.send_and_expect(
214 self.pg1, p_4o4_2 * 1 + p_4o4 * (NUM_PKTS - 1), self.pg0)
215 # checking encap4 magic packet
217 self.validate_outer4(p, udp_encap_4)
218 p = IP(p["UDP"].payload.load)
219 self.validate_inner4(p, p_4o4_2)
220 self.assertEqual(udp_encap_4.get_stats()['packets'], 1)
221 # checking remaining packets for encap0
223 self.validate_outer4(p, udp_encap_0)
224 p = IP(p["UDP"].payload.load)
225 self.validate_inner4(p, p_4o4)
226 self.assertEqual(udp_encap_0.get_stats()['packets'], NUM_PKTS - 1)
231 p_4o6 = (Ether(src=self.pg0.remote_mac,
232 dst=self.pg0.local_mac) /
233 IP(src="2.2.2.2", dst="1.1.2.1") /
234 UDP(sport=1234, dport=1234) /
236 rx = self.send_and_expect(self.pg0, p_4o6*NUM_PKTS, self.pg2)
238 self.validate_outer6(p, udp_encap_2)
239 p = IP(p["UDP"].payload.load)
240 self.validate_inner4(p, p_4o6)
241 self.assertEqual(udp_encap_2.get_stats()['packets'], NUM_PKTS)
246 p_6o4 = (Ether(src=self.pg0.remote_mac,
247 dst=self.pg0.local_mac) /
248 IPv6(src="2001::100", dst="2001::1") /
249 UDP(sport=1234, dport=1234) /
251 rx = self.send_and_expect(self.pg0, p_6o4*NUM_PKTS, self.pg1)
253 self.validate_outer4(p, udp_encap_1)
254 p = IPv6(p["UDP"].payload.load)
255 self.validate_inner6(p, p_6o4)
256 self.assertEqual(udp_encap_1.get_stats()['packets'], NUM_PKTS)
261 p_6o6 = (Ether(src=self.pg0.remote_mac,
262 dst=self.pg0.local_mac) /
263 IPv6(src="2001::100", dst="2001::3") /
264 UDP(sport=1234, dport=1234) /
266 rx = self.send_and_expect(self.pg0, p_6o6*NUM_PKTS, self.pg3)
268 self.validate_outer6(p, udp_encap_3)
269 p = IPv6(p["UDP"].payload.load)
270 self.validate_inner6(p, p_6o6)
271 self.assertEqual(udp_encap_3.get_stats()['packets'], NUM_PKTS)
274 # A route with an output label
275 # the TTL of the inner packet is decremented on LSP ingress
277 route_4oMPLSo4 = VppIpRoute(
278 self, "1.1.2.22", 32,
279 [VppRoutePath("0.0.0.0",
281 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
283 labels=[VppMplsLabel(66)])])
284 route_4oMPLSo4.add_vpp_config()
286 p_4omo4 = (Ether(src=self.pg0.remote_mac,
287 dst=self.pg0.local_mac) /
288 IP(src="2.2.2.2", dst="1.1.2.22") /
289 UDP(sport=1234, dport=1234) /
291 rx = self.send_and_expect(self.pg0, p_4omo4*NUM_PKTS, self.pg1)
293 self.validate_outer4(p, udp_encap_1)
294 p = MPLS(p["UDP"].payload.load)
295 self.validate_inner4(p, p_4omo4, ttl=63)
296 self.assertEqual(udp_encap_1.get_stats()['packets'], 2*NUM_PKTS)
298 def test_udp_decap(self):
302 # construct a UDP decap object for each type of protocol
306 udp_api_proto = VppEnum.vl_api_udp_decap_next_proto_t
307 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP4
308 udp_decap_0 = VppUdpDecap(self, 1, 220, next_proto)
311 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP6
312 udp_decap_1 = VppUdpDecap(self, 0, 221, next_proto)
315 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_MPLS
316 udp_decap_2 = VppUdpDecap(self, 1, 222, next_proto)
318 udp_decap_0.add_vpp_config()
319 udp_decap_1.add_vpp_config()
320 udp_decap_2.add_vpp_config()
323 # Routes via the corresponding pg after the UDP decap
325 route_4 = VppIpRoute(
327 [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)],
330 route_6 = VppIpRoute(
331 self, "2001::1", 128,
332 [VppRoutePath("::", self.pg1.sw_if_index)],
335 route_mo4 = VppIpRoute(
337 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
340 route_4.add_vpp_config()
341 route_6.add_vpp_config()
342 route_mo4.add_vpp_config()
345 # Adding neighbors to route the packets
347 n_4 = VppNeighbor(self,
348 self.pg0.sw_if_index,
351 n_6 = VppNeighbor(self,
352 self.pg1.sw_if_index,
355 n_mo4 = VppNeighbor(self,
356 self.pg2.sw_if_index,
362 n_mo4.add_vpp_config()
365 # MPLS decapsulation config
367 mpls_table = VppMplsTable(self, 0)
368 mpls_table.add_vpp_config()
369 mpls_route = VppMplsRoute(
371 [VppRoutePath("0.0.0.0",
374 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
375 mpls_route.add_vpp_config()
378 # UDP over ipv4 decap
380 p_4 = (Ether(src=self.pg0.remote_mac,
381 dst=self.pg0.local_mac) /
382 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
383 UDP(sport=1111, dport=220) /
384 IP(src="2.2.2.2", dst="1.1.1.1") /
385 UDP(sport=1234, dport=4321) /
388 rx = self.send_and_expect(self.pg0, p_4*NUM_PKTS, self.pg0)
389 p_4 = IP(p_4["UDP"].payload)
391 p = IP(p["Ether"].payload)
392 self.validate_inner4(p, p_4, ttl=63)
395 # UDP over ipv6 decap
397 p_6 = (Ether(src=self.pg1.remote_mac,
398 dst=self.pg1.local_mac) /
399 IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6) /
400 UDP(sport=2222, dport=221) /
401 IPv6(src="2001::100", dst="2001::1") /
402 UDP(sport=1234, dport=4321) /
405 rx = self.send_and_expect(self.pg1, p_6*NUM_PKTS, self.pg1)
406 p_6 = IPv6(p_6["UDP"].payload)
407 p = IPv6(rx[0]["Ether"].payload)
409 p = IPv6(p["Ether"].payload)
410 self.validate_inner6(p, p_6, hlim=63)
413 # UDP over mpls decap
415 p_mo4 = (Ether(src=self.pg2.remote_mac,
416 dst=self.pg2.local_mac) /
417 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
418 UDP(sport=3333, dport=222) /
419 MPLS(label=77, ttl=1) /
420 IP(src="4.4.4.4", dst="3.3.3.3") /
421 UDP(sport=1234, dport=4321) /
424 self.pg2.enable_mpls()
425 rx = self.send_and_expect(self.pg2, p_mo4*NUM_PKTS, self.pg2)
426 self.pg2.disable_mpls()
427 p_mo4 = IP(MPLS(p_mo4["UDP"].payload).payload)
429 p = IP(p["Ether"].payload)
430 self.validate_inner4(p, p_mo4, ttl=63)
433 @tag_fixme_vpp_workers
434 class TestUDP(VppTestCase):
435 """ UDP Test Case """
439 super(TestUDP, cls).setUpClass()
442 def tearDownClass(cls):
443 super(TestUDP, cls).tearDownClass()
446 super(TestUDP, self).setUp()
447 self.vapi.session_enable_disable(is_enable=1)
448 self.create_loopback_interfaces(2)
452 for i in self.lo_interfaces:
456 tbl = VppIpTable(self, table_id)
459 i.set_table_ip4(table_id)
463 # Configure namespaces
464 self.vapi.app_namespace_add_del(namespace_id="0",
465 sw_if_index=self.loop0.sw_if_index)
466 self.vapi.app_namespace_add_del(namespace_id="1",
467 sw_if_index=self.loop1.sw_if_index)
470 for i in self.lo_interfaces:
474 self.vapi.session_enable_disable(is_enable=0)
475 super(TestUDP, self).tearDown()
477 def test_udp_transfer(self):
478 """ UDP echo client/server transfer """
480 # Add inter-table routes
481 ip_t01 = VppIpRoute(self, self.loop1.local_ip4, 32,
482 [VppRoutePath("0.0.0.0",
485 ip_t10 = VppIpRoute(self, self.loop0.local_ip4, 32,
486 [VppRoutePath("0.0.0.0",
488 nh_table_id=0)], table_id=1)
489 ip_t01.add_vpp_config()
490 ip_t10.add_vpp_config()
492 # Start builtin server and client
493 uri = "udp://" + self.loop0.local_ip4 + "/1234"
494 error = self.vapi.cli("test echo server appns 0 fifo-size 4 no-echo" +
497 self.logger.critical(error)
498 self.assertNotIn("failed", error)
500 error = self.vapi.cli("test echo client mbytes 10 appns 1 " +
501 "fifo-size 4 no-output test-bytes " +
502 "syn-timeout 2 no-return uri " + uri)
504 self.logger.critical(error)
505 self.assertNotIn("failed", error)
507 self.logger.debug(self.vapi.cli("show session verbose 2"))
509 # Delete inter-table routes
510 ip_t01.remove_vpp_config()
511 ip_t10.remove_vpp_config()
514 if __name__ == '__main__':
515 unittest.main(testRunner=VppTestRunner)