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,
149 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)],
151 route_4o6 = VppIpRoute(
153 [VppRoutePath("0.0.0.0",
155 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
156 next_hop_id=udp_encap_2.id,
157 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
158 route_6o4 = VppIpRoute(
159 self, "2001::1", 128,
160 [VppRoutePath("0.0.0.0",
162 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
163 next_hop_id=udp_encap_1.id,
164 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
165 route_6o6 = VppIpRoute(
166 self, "2001::3", 128,
167 [VppRoutePath("0.0.0.0",
169 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
170 next_hop_id=udp_encap_3.id,
171 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
172 route_4o6.add_vpp_config()
173 route_6o6.add_vpp_config()
174 route_6o4.add_vpp_config()
175 route_4o4.add_vpp_config()
180 p_4o4 = (Ether(src=self.pg1.remote_mac,
181 dst=self.pg1.local_mac) /
182 IP(src="2.2.2.2", dst="1.1.0.1") /
183 UDP(sport=1234, dport=1234) /
185 rx = self.send_and_expect(self.pg1, p_4o4*NUM_PKTS, self.pg0)
187 self.validate_outer4(p, udp_encap_0)
188 p = IP(p["UDP"].payload.load)
189 self.validate_inner4(p, p_4o4)
190 self.assertEqual(udp_encap_0.get_stats()['packets'], NUM_PKTS)
195 p_4o6 = (Ether(src=self.pg0.remote_mac,
196 dst=self.pg0.local_mac) /
197 IP(src="2.2.2.2", dst="1.1.2.1") /
198 UDP(sport=1234, dport=1234) /
200 rx = self.send_and_expect(self.pg0, p_4o6*NUM_PKTS, self.pg2)
202 self.validate_outer6(p, udp_encap_2)
203 p = IP(p["UDP"].payload.load)
204 self.validate_inner4(p, p_4o6)
205 self.assertEqual(udp_encap_2.get_stats()['packets'], NUM_PKTS)
210 p_6o4 = (Ether(src=self.pg0.remote_mac,
211 dst=self.pg0.local_mac) /
212 IPv6(src="2001::100", dst="2001::1") /
213 UDP(sport=1234, dport=1234) /
215 rx = self.send_and_expect(self.pg0, p_6o4*NUM_PKTS, self.pg1)
217 self.validate_outer4(p, udp_encap_1)
218 p = IPv6(p["UDP"].payload.load)
219 self.validate_inner6(p, p_6o4)
220 self.assertEqual(udp_encap_1.get_stats()['packets'], NUM_PKTS)
225 p_6o6 = (Ether(src=self.pg0.remote_mac,
226 dst=self.pg0.local_mac) /
227 IPv6(src="2001::100", dst="2001::3") /
228 UDP(sport=1234, dport=1234) /
230 rx = self.send_and_expect(self.pg0, p_6o6*NUM_PKTS, self.pg3)
232 self.validate_outer6(p, udp_encap_3)
233 p = IPv6(p["UDP"].payload.load)
234 self.validate_inner6(p, p_6o6)
235 self.assertEqual(udp_encap_3.get_stats()['packets'], NUM_PKTS)
238 # A route with an output label
239 # the TTL of the inner packet is decremented on LSP ingress
241 route_4oMPLSo4 = VppIpRoute(
242 self, "1.1.2.22", 32,
243 [VppRoutePath("0.0.0.0",
245 type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP,
247 labels=[VppMplsLabel(66)])])
248 route_4oMPLSo4.add_vpp_config()
250 p_4omo4 = (Ether(src=self.pg0.remote_mac,
251 dst=self.pg0.local_mac) /
252 IP(src="2.2.2.2", dst="1.1.2.22") /
253 UDP(sport=1234, dport=1234) /
255 rx = self.send_and_expect(self.pg0, p_4omo4*NUM_PKTS, self.pg1)
257 self.validate_outer4(p, udp_encap_1)
258 p = MPLS(p["UDP"].payload.load)
259 self.validate_inner4(p, p_4omo4, ttl=63)
260 self.assertEqual(udp_encap_1.get_stats()['packets'], 2*NUM_PKTS)
262 def test_udp_decap(self):
266 # construct a UDP decap object for each type of protocol
270 udp_api_proto = VppEnum.vl_api_udp_decap_next_proto_t
271 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP4
272 udp_decap_0 = VppUdpDecap(self, 1, 220, next_proto)
275 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP6
276 udp_decap_1 = VppUdpDecap(self, 0, 221, next_proto)
279 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_MPLS
280 udp_decap_2 = VppUdpDecap(self, 1, 222, next_proto)
282 udp_decap_0.add_vpp_config()
283 udp_decap_1.add_vpp_config()
284 udp_decap_2.add_vpp_config()
287 # Routes via the corresponding pg after the UDP decap
289 route_4 = VppIpRoute(
291 [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)],
294 route_6 = VppIpRoute(
295 self, "2001::1", 128,
296 [VppRoutePath("::", self.pg1.sw_if_index)],
299 route_mo4 = VppIpRoute(
301 [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)],
304 route_4.add_vpp_config()
305 route_6.add_vpp_config()
306 route_mo4.add_vpp_config()
309 # Adding neighbors to route the packets
311 n_4 = VppNeighbor(self,
312 self.pg0.sw_if_index,
315 n_6 = VppNeighbor(self,
316 self.pg1.sw_if_index,
319 n_mo4 = VppNeighbor(self,
320 self.pg2.sw_if_index,
326 n_mo4.add_vpp_config()
329 # MPLS decapsulation config
331 mpls_table = VppMplsTable(self, 0)
332 mpls_table.add_vpp_config()
333 mpls_route = VppMplsRoute(
335 [VppRoutePath("0.0.0.0",
338 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
339 mpls_route.add_vpp_config()
342 # UDP over ipv4 decap
344 p_4 = (Ether(src=self.pg0.remote_mac,
345 dst=self.pg0.local_mac) /
346 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
347 UDP(sport=1111, dport=220) /
348 IP(src="2.2.2.2", dst="1.1.1.1") /
349 UDP(sport=1234, dport=4321) /
352 rx = self.send_and_expect(self.pg0, p_4*NUM_PKTS, self.pg0)
353 p_4 = IP(p_4["UDP"].payload)
355 p = IP(p["Ether"].payload)
356 self.validate_inner4(p, p_4, ttl=63)
359 # UDP over ipv6 decap
361 p_6 = (Ether(src=self.pg1.remote_mac,
362 dst=self.pg1.local_mac) /
363 IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6) /
364 UDP(sport=2222, dport=221) /
365 IPv6(src="2001::100", dst="2001::1") /
366 UDP(sport=1234, dport=4321) /
369 rx = self.send_and_expect(self.pg1, p_6*NUM_PKTS, self.pg1)
370 p_6 = IPv6(p_6["UDP"].payload)
371 p = IPv6(rx[0]["Ether"].payload)
373 p = IPv6(p["Ether"].payload)
374 self.validate_inner6(p, p_6, hlim=63)
377 # UDP over mpls decap
379 p_mo4 = (Ether(src=self.pg2.remote_mac,
380 dst=self.pg2.local_mac) /
381 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
382 UDP(sport=3333, dport=222) /
383 MPLS(label=77, ttl=1) /
384 IP(src="4.4.4.4", dst="3.3.3.3") /
385 UDP(sport=1234, dport=4321) /
388 self.pg2.enable_mpls()
389 rx = self.send_and_expect(self.pg2, p_mo4*NUM_PKTS, self.pg2)
390 self.pg2.disable_mpls()
391 p_mo4 = IP(MPLS(p_mo4["UDP"].payload).payload)
393 p = IP(p["Ether"].payload)
394 self.validate_inner4(p, p_mo4, ttl=63)
397 @tag_fixme_vpp_workers
398 class TestUDP(VppTestCase):
399 """ UDP Test Case """
403 super(TestUDP, cls).setUpClass()
406 def tearDownClass(cls):
407 super(TestUDP, cls).tearDownClass()
410 super(TestUDP, self).setUp()
411 self.vapi.session_enable_disable(is_enable=1)
412 self.create_loopback_interfaces(2)
416 for i in self.lo_interfaces:
420 tbl = VppIpTable(self, table_id)
423 i.set_table_ip4(table_id)
427 # Configure namespaces
428 self.vapi.app_namespace_add_del(namespace_id="0",
429 sw_if_index=self.loop0.sw_if_index)
430 self.vapi.app_namespace_add_del(namespace_id="1",
431 sw_if_index=self.loop1.sw_if_index)
434 for i in self.lo_interfaces:
438 self.vapi.session_enable_disable(is_enable=0)
439 super(TestUDP, self).tearDown()
441 def test_udp_transfer(self):
442 """ UDP echo client/server transfer """
444 # Add inter-table routes
445 ip_t01 = VppIpRoute(self, self.loop1.local_ip4, 32,
446 [VppRoutePath("0.0.0.0",
449 ip_t10 = VppIpRoute(self, self.loop0.local_ip4, 32,
450 [VppRoutePath("0.0.0.0",
452 nh_table_id=0)], table_id=1)
453 ip_t01.add_vpp_config()
454 ip_t10.add_vpp_config()
456 # Start builtin server and client
457 uri = "udp://" + self.loop0.local_ip4 + "/1234"
458 error = self.vapi.cli("test echo server appns 0 fifo-size 4 no-echo" +
461 self.logger.critical(error)
462 self.assertNotIn("failed", error)
464 error = self.vapi.cli("test echo client mbytes 10 appns 1 " +
465 "fifo-size 4 no-output test-bytes " +
466 "syn-timeout 2 no-return uri " + uri)
468 self.logger.critical(error)
469 self.assertNotIn("failed", error)
471 self.logger.debug(self.vapi.cli("show session verbose 2"))
473 # Delete inter-table routes
474 ip_t01.remove_vpp_config()
475 ip_t10.remove_vpp_config()
478 if __name__ == '__main__':
479 unittest.main(testRunner=VppTestRunner)