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.
109 udp_encap_0 = VppUdpEncap(self,
113 udp_encap_1 = VppUdpEncap(self,
118 udp_encap_2 = VppUdpEncap(self,
123 udp_encap_3 = VppUdpEncap(self,
128 udp_encap_0.add_vpp_config()
129 udp_encap_1.add_vpp_config()
130 udp_encap_2.add_vpp_config()
131 udp_encap_3.add_vpp_config()
133 self.logger.info(self.vapi.cli("sh udp encap"))
135 self.assertTrue(find_udp_encap(self, udp_encap_2))
136 self.assertTrue(find_udp_encap(self, udp_encap_3))
137 self.assertTrue(find_udp_encap(self, udp_encap_0))
138 self.assertTrue(find_udp_encap(self, udp_encap_1))
141 # Routes via each UDP encap object - all combinations of v4 and v6.
143 route_4o4 = VppIpRoute(
145 [VppRoutePath("0.0.0.0",
147 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
148 next_hop_id=udp_encap_0.id)], table_id=1)
149 route_4o6 = VppIpRoute(
151 [VppRoutePath("0.0.0.0",
153 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
154 next_hop_id=udp_encap_2.id)])
155 route_6o4 = VppIpRoute(
156 self, "2001::1", 128,
157 [VppRoutePath("0.0.0.0",
159 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
160 next_hop_id=udp_encap_1.id)])
161 route_6o6 = VppIpRoute(
162 self, "2001::3", 128,
163 [VppRoutePath("0.0.0.0",
165 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
166 next_hop_id=udp_encap_3.id)])
167 route_4o6.add_vpp_config()
168 route_6o6.add_vpp_config()
169 route_6o4.add_vpp_config()
170 route_4o4.add_vpp_config()
175 p_4o4 = (Ether(src=self.pg1.remote_mac,
176 dst=self.pg1.local_mac) /
177 IP(src="2.2.2.2", dst="1.1.0.1") /
178 UDP(sport=1234, dport=1234) /
180 rx = self.send_and_expect(self.pg1, p_4o4*NUM_PKTS, self.pg0)
182 self.validate_outer4(p, udp_encap_0)
183 p = IP(p["UDP"].payload.load)
184 self.validate_inner4(p, p_4o4)
185 self.assertEqual(udp_encap_0.get_stats()['packets'], NUM_PKTS)
190 p_4o6 = (Ether(src=self.pg0.remote_mac,
191 dst=self.pg0.local_mac) /
192 IP(src="2.2.2.2", dst="1.1.2.1") /
193 UDP(sport=1234, dport=1234) /
195 rx = self.send_and_expect(self.pg0, p_4o6*NUM_PKTS, self.pg2)
197 self.validate_outer6(p, udp_encap_2)
198 p = IP(p["UDP"].payload.load)
199 self.validate_inner4(p, p_4o6)
200 self.assertEqual(udp_encap_2.get_stats()['packets'], NUM_PKTS)
205 p_6o4 = (Ether(src=self.pg0.remote_mac,
206 dst=self.pg0.local_mac) /
207 IPv6(src="2001::100", dst="2001::1") /
208 UDP(sport=1234, dport=1234) /
210 rx = self.send_and_expect(self.pg0, p_6o4*NUM_PKTS, self.pg1)
212 self.validate_outer4(p, udp_encap_1)
213 p = IPv6(p["UDP"].payload.load)
214 self.validate_inner6(p, p_6o4)
215 self.assertEqual(udp_encap_1.get_stats()['packets'], NUM_PKTS)
220 p_6o6 = (Ether(src=self.pg0.remote_mac,
221 dst=self.pg0.local_mac) /
222 IPv6(src="2001::100", dst="2001::3") /
223 UDP(sport=1234, dport=1234) /
225 rx = self.send_and_expect(self.pg0, p_6o6*NUM_PKTS, self.pg3)
227 self.validate_outer6(p, udp_encap_3)
228 p = IPv6(p["UDP"].payload.load)
229 self.validate_inner6(p, p_6o6)
230 self.assertEqual(udp_encap_3.get_stats()['packets'], NUM_PKTS)
233 # A route with an output label
234 # the TTL of the inner packet is decremented on LSP ingress
236 route_4oMPLSo4 = VppIpRoute(
237 self, "1.1.2.22", 32,
238 [VppRoutePath("0.0.0.0",
240 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
242 labels=[VppMplsLabel(66)])])
243 route_4oMPLSo4.add_vpp_config()
245 p_4omo4 = (Ether(src=self.pg0.remote_mac,
246 dst=self.pg0.local_mac) /
247 IP(src="2.2.2.2", dst="1.1.2.22") /
248 UDP(sport=1234, dport=1234) /
250 rx = self.send_and_expect(self.pg0, p_4omo4*NUM_PKTS, self.pg1)
252 self.validate_outer4(p, udp_encap_1)
253 p = MPLS(p["UDP"].payload.load)
254 self.validate_inner4(p, p_4omo4, ttl=63)
255 self.assertEqual(udp_encap_1.get_stats()['packets'], 2*NUM_PKTS)
257 def test_udp_decap(self):
261 # construct a UDP decap object for each type of protocol
265 udp_api_proto = VppEnum.vl_api_udp_decap_next_proto_t
266 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP4
267 udp_decap_0 = VppUdpDecap(self, 1, 220, next_proto)
270 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP6
271 udp_decap_1 = VppUdpDecap(self, 0, 221, next_proto)
274 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_MPLS
275 udp_decap_2 = VppUdpDecap(self, 1, 222, next_proto)
277 udp_decap_0.add_vpp_config()
278 udp_decap_1.add_vpp_config()
279 udp_decap_2.add_vpp_config()
282 # Routes via the corresponding pg after the UDP decap
284 route_4 = VppIpRoute(
286 [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)],
289 route_6 = VppIpRoute(
290 self, "2001::1", 128,
291 [VppRoutePath("::", self.pg1.sw_if_index)],
294 route_mo4 = VppIpRoute(
296 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
299 route_4.add_vpp_config()
300 route_6.add_vpp_config()
301 route_mo4.add_vpp_config()
304 # Adding neighbors to route the packets
306 n_4 = VppNeighbor(self,
307 self.pg0.sw_if_index,
310 n_6 = VppNeighbor(self,
311 self.pg1.sw_if_index,
314 n_mo4 = VppNeighbor(self,
315 self.pg2.sw_if_index,
321 n_mo4.add_vpp_config()
324 # MPLS decapsulation config
326 mpls_table = VppMplsTable(self, 0)
327 mpls_table.add_vpp_config()
328 mpls_route = VppMplsRoute(
330 [VppRoutePath("0.0.0.0",
333 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
334 mpls_route.add_vpp_config()
337 # UDP over ipv4 decap
339 p_4 = (Ether(src=self.pg0.remote_mac,
340 dst=self.pg0.local_mac) /
341 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
342 UDP(sport=1111, dport=220) /
343 IP(src="2.2.2.2", dst="1.1.1.1") /
344 UDP(sport=1234, dport=4321) /
347 rx = self.send_and_expect(self.pg0, p_4*NUM_PKTS, self.pg0)
348 p_4 = IP(p_4["UDP"].payload)
350 p = IP(p["Ether"].payload)
351 self.validate_inner4(p, p_4, ttl=63)
354 # UDP over ipv6 decap
356 p_6 = (Ether(src=self.pg1.remote_mac,
357 dst=self.pg1.local_mac) /
358 IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6) /
359 UDP(sport=2222, dport=221) /
360 IPv6(src="2001::100", dst="2001::1") /
361 UDP(sport=1234, dport=4321) /
364 rx = self.send_and_expect(self.pg1, p_6*NUM_PKTS, self.pg1)
365 p_6 = IPv6(p_6["UDP"].payload)
366 p = IPv6(rx[0]["Ether"].payload)
368 p = IPv6(p["Ether"].payload)
369 self.validate_inner6(p, p_6, hlim=63)
372 # UDP over mpls decap
374 p_mo4 = (Ether(src=self.pg2.remote_mac,
375 dst=self.pg2.local_mac) /
376 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
377 UDP(sport=3333, dport=222) /
378 MPLS(label=77, ttl=1) /
379 IP(src="4.4.4.4", dst="3.3.3.3") /
380 UDP(sport=1234, dport=4321) /
383 self.pg2.enable_mpls()
384 rx = self.send_and_expect(self.pg2, p_mo4*NUM_PKTS, self.pg2)
385 self.pg2.disable_mpls()
386 p_mo4 = IP(MPLS(p_mo4["UDP"].payload).payload)
388 p = IP(p["Ether"].payload)
389 self.validate_inner4(p, p_mo4, ttl=63)
392 @tag_fixme_vpp_workers
393 class TestUDP(VppTestCase):
394 """ UDP Test Case """
398 super(TestUDP, cls).setUpClass()
401 def tearDownClass(cls):
402 super(TestUDP, cls).tearDownClass()
405 super(TestUDP, self).setUp()
406 self.vapi.session_enable_disable(is_enable=1)
407 self.create_loopback_interfaces(2)
411 for i in self.lo_interfaces:
415 tbl = VppIpTable(self, table_id)
418 i.set_table_ip4(table_id)
422 # Configure namespaces
423 self.vapi.app_namespace_add_del(namespace_id="0",
424 sw_if_index=self.loop0.sw_if_index)
425 self.vapi.app_namespace_add_del(namespace_id="1",
426 sw_if_index=self.loop1.sw_if_index)
429 for i in self.lo_interfaces:
433 self.vapi.session_enable_disable(is_enable=0)
434 super(TestUDP, self).tearDown()
436 def test_udp_transfer(self):
437 """ UDP echo client/server transfer """
439 # Add inter-table routes
440 ip_t01 = VppIpRoute(self, self.loop1.local_ip4, 32,
441 [VppRoutePath("0.0.0.0",
444 ip_t10 = VppIpRoute(self, self.loop0.local_ip4, 32,
445 [VppRoutePath("0.0.0.0",
447 nh_table_id=0)], table_id=1)
448 ip_t01.add_vpp_config()
449 ip_t10.add_vpp_config()
451 # Start builtin server and client
452 uri = "udp://" + self.loop0.local_ip4 + "/1234"
453 error = self.vapi.cli("test echo server appns 0 fifo-size 4 no-echo" +
456 self.logger.critical(error)
457 self.assertNotIn("failed", error)
459 error = self.vapi.cli("test echo client mbytes 10 appns 1 " +
460 "fifo-size 4 no-output test-bytes " +
461 "syn-timeout 2 no-return uri " + uri)
463 self.logger.critical(error)
464 self.assertNotIn("failed", error)
466 self.logger.debug(self.vapi.cli("show session verbose 2"))
468 # Delete inter-table routes
469 ip_t01.remove_vpp_config()
470 ip_t10.remove_vpp_config()
473 if __name__ == '__main__':
474 unittest.main(testRunner=VppTestRunner)