2 """IP{4,6} over IP{v,6} tunnel functional tests"""
5 from scapy.layers.inet6 import IPv6, Ether, IP, UDP, IPv6ExtHdrFragment, Raw
6 from scapy.contrib.mpls import MPLS
7 from scapy.all import fragment, fragment6, RandShort, defragment6
8 from framework import VppTestCase, VppTestRunner
9 from vpp_ip import DpoProto
10 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, FibPathProto, \
11 VppMplsLabel, VppMplsRoute, VppMplsTable
12 from vpp_ipip_tun_interface import VppIpIpTunInterface
13 from vpp_teib import VppTeib
14 from vpp_papi import VppEnum
15 from socket import AF_INET, AF_INET6, inet_pton
16 from util import reassemble4
18 """ Testipip is a subclass of VPPTestCase classes.
25 def ipip_add_tunnel(test, src, dst, table_id=0, dscp=0x0,
27 """ Add a IPIP tunnel """
28 return test.vapi.ipip_add_tunnel(
33 'instance': 0xffffffff,
39 # the number of packets to send when injecting traffic.
40 # a multiple of 8 minus one, so we test all by 8/4/2/1 loops
44 class TestIPIP(VppTestCase):
45 """ IPIP Test Case """
49 super(TestIPIP, cls).setUpClass()
50 cls.create_pg_interfaces(range(3))
51 cls.interfaces = list(cls.pg_interfaces)
54 def tearDownClass(cls):
55 super(TestIPIP, cls).tearDownClass()
58 super(TestIPIP, self).setUp()
59 self.table = VppIpTable(self, 1, register=False)
60 self.table.add_vpp_config()
62 for i in self.interfaces:
65 self.pg2.set_table_ip4(self.table.table_id)
66 for i in self.interfaces:
74 super(TestIPIP, self).tearDown()
76 for i in self.pg_interfaces:
82 self.table.remove_vpp_config()
84 def validate(self, rx, expected):
85 self.assertEqual(rx, expected.__class__(expected))
87 def generate_ip4_frags(self, payload_length, fragment_size):
88 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
89 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
90 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
91 outer_ip4 = (p_ether / IP(src=self.pg1.remote_ip4,
93 dst=self.pg0.local_ip4) / p_ip4 / p_payload)
94 frags = fragment(outer_ip4, fragment_size)
95 p4_reply = (p_ip4 / p_payload)
97 return frags, p4_reply
99 def verify_ip4ip4_encaps(self, a, p_ip4s, p_ip4_encaps):
100 for i, p_ip4 in enumerate(p_ip4s):
102 p4 = (self.p_ether / p_ip4 / self.p_payload)
105 p4_reply = (p_ip4_encaps[i] / p_ip4_inner / self.p_payload)
108 rx = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1)
110 self.validate(p[1], p4_reply)
111 self.assert_packet_checksums_valid(p)
113 def verify_ip6ip4_encaps(self, a, p_ip6s, p_ip4_encaps):
114 for i, p_ip6 in enumerate(p_ip6s):
116 p6 = (self.p_ether / p_ip6 / self.p_payload)
118 p_inner_ip6.hlim -= 1
119 p6_reply = (p_ip4_encaps[i] / p_inner_ip6 / self.p_payload)
121 rx = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1)
123 self.validate(p[1], p6_reply)
124 self.assert_packet_checksums_valid(p)
126 def test_ipip4(self):
127 """ ip{v4,v6} over ip4 test """
129 self.pg1.generate_remote_hosts(5)
130 self.pg1.configure_ipv4_neighbors()
131 e = VppEnum.vl_api_tunnel_encap_decap_flags_t
132 d = VppEnum.vl_api_ip_dscp_t
133 self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
134 self.p_payload = UDP(sport=1234, dport=1234) / Raw(b'X' * 100)
136 # create a TOS byte by shifting a DSCP code point 2 bits. those 2 bits
138 dscp = d.IP_API_DSCP_AF31 << 2
140 dscp_ecn = d.IP_API_DSCP_AF31 << 2 | ecn
142 # IPv4 transport that copies the DCSP from the payload
143 tun_dscp = VppIpIpTunInterface(
147 self.pg1.remote_hosts[0].ip4,
148 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP)
149 tun_dscp.add_vpp_config()
150 # IPv4 transport that copies the DCSP and ECN from the payload
151 tun_dscp_ecn = VppIpIpTunInterface(
155 self.pg1.remote_hosts[1].ip4,
156 flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP |
157 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN))
158 tun_dscp_ecn.add_vpp_config()
159 # IPv4 transport that copies the ECN from the payload and sets the
160 # DF bit on encap. copies the ECN on decap
161 tun_ecn = VppIpIpTunInterface(
165 self.pg1.remote_hosts[2].ip4,
166 flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN |
167 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_DF |
168 e.TUNNEL_API_ENCAP_DECAP_FLAG_DECAP_COPY_ECN))
169 tun_ecn.add_vpp_config()
170 # IPv4 transport that sets a fixed DSCP in the encap and copies
172 tun = VppIpIpTunInterface(
176 self.pg1.remote_hosts[3].ip4,
177 dscp=d.IP_API_DSCP_AF11,
178 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DF)
181 # array of all the tunnels
182 tuns = [tun_dscp, tun_dscp_ecn, tun_ecn, tun]
184 # addresses for prefixes routed via each tunnel
185 a4s = ["" for i in range(len(tuns))]
186 a6s = ["" for i in range(len(tuns))]
188 # IP headers with each combination of DSCp/ECN tested
189 p_ip6s = [IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=dscp),
190 IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=dscp_ecn),
191 IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=ecn),
192 IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=0xff)]
193 p_ip4s = [IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp, flags='DF'),
194 IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp_ecn),
195 IP(src="1.2.3.4", dst="130.67.0.1", tos=ecn),
196 IP(src="1.2.3.4", dst="130.67.0.1", tos=0xff)]
198 # Configure each tunnel
199 for i, t in enumerate(tuns):
200 # Set interface up and enable IP on it
201 self.vapi.sw_interface_set_flags(t.sw_if_index, 1)
202 self.vapi.sw_interface_set_unnumbered(
203 sw_if_index=self.pg0.sw_if_index,
204 unnumbered_sw_if_index=t.sw_if_index)
206 # prefix for route / destination address for packets
207 a4s[i] = "130.67.%d.0" % i
208 a6s[i] = "dead:%d::" % i
210 # Add IPv4 and IPv6 routes via tunnel interface
211 ip4_via_tunnel = VppIpRoute(
213 [VppRoutePath("0.0.0.0",
215 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
216 ip4_via_tunnel.add_vpp_config()
218 ip6_via_tunnel = VppIpRoute(
222 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
223 ip6_via_tunnel.add_vpp_config()
229 # tun_dscp copies only the dscp
230 # expected TC values are thus only the DCSP value is present from the
232 exp_tcs = [dscp, dscp, 0, 0xfc]
233 p_ip44_encaps = [IP(src=self.pg0.local_ip4,
235 tos=tc) for tc in exp_tcs]
236 p_ip64_encaps = [IP(src=self.pg0.local_ip4,
238 proto='ipv6', id=0, tos=tc) for tc in exp_tcs]
240 # IPv4 in to IPv4 tunnel
241 self.verify_ip4ip4_encaps(a4s[0], p_ip4s, p_ip44_encaps)
242 # IPv6 in to IPv4 tunnel
243 self.verify_ip6ip4_encaps(a6s[0], p_ip6s, p_ip64_encaps)
245 # tun_dscp_ecn copies the dscp and the ecn
246 exp_tcs = [dscp, dscp_ecn, ecn, 0xff]
247 p_ip44_encaps = [IP(src=self.pg0.local_ip4,
248 dst=tun_dscp_ecn.dst,
249 tos=tc) for tc in exp_tcs]
250 p_ip64_encaps = [IP(src=self.pg0.local_ip4,
251 dst=tun_dscp_ecn.dst,
252 proto='ipv6', id=0, tos=tc) for tc in exp_tcs]
254 self.verify_ip4ip4_encaps(a4s[1], p_ip4s, p_ip44_encaps)
255 self.verify_ip6ip4_encaps(a6s[1], p_ip6s, p_ip64_encaps)
257 # tun_ecn copies only the ecn and always sets DF
258 exp_tcs = [0, ecn, ecn, ecn]
259 p_ip44_encaps = [IP(src=self.pg0.local_ip4,
261 flags='DF', tos=tc) for tc in exp_tcs]
262 p_ip64_encaps = [IP(src=self.pg0.local_ip4,
264 flags='DF', proto='ipv6', id=0, tos=tc)
267 self.verify_ip4ip4_encaps(a4s[2], p_ip4s, p_ip44_encaps)
268 self.verify_ip6ip4_encaps(a6s[2], p_ip6s, p_ip64_encaps)
270 # tun sets a fixed dscp and copies DF
271 fixed_dscp = tun.dscp << 2
272 flags = ['DF', 0, 0, 0]
273 p_ip44_encaps = [IP(src=self.pg0.local_ip4,
276 tos=fixed_dscp) for f in flags]
277 p_ip64_encaps = [IP(src=self.pg0.local_ip4,
280 tos=fixed_dscp) for i in range(len(p_ip4s))]
282 self.verify_ip4ip4_encaps(a4s[3], p_ip4s, p_ip44_encaps)
283 self.verify_ip6ip4_encaps(a6s[3], p_ip6s, p_ip64_encaps)
288 n_packets_decapped = 0
289 self.p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
291 # IPv4 tunnel to IPv4
292 tcs = [0, dscp, dscp_ecn, ecn]
294 # one overlay packet and all combinations of its encap
295 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
296 p_ip4_encaps = [IP(src=tun.dst,
297 dst=self.pg0.local_ip4,
298 tos=tc) for tc in tcs]
300 # for each encap tun will produce the same inner packet because it does
301 # not copy up fields from the payload
302 for p_ip4_encap in p_ip4_encaps:
303 p4 = (self.p_ether / p_ip4_encap / p_ip4 / self.p_payload)
304 p4_reply = (p_ip4 / self.p_payload)
306 rx = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
307 n_packets_decapped += N_PACKETS
309 self.validate(p[1], p4_reply)
310 self.assert_packet_checksums_valid(p)
312 err = self.statistics.get_err_counter(
313 '/err/ipip4-input/packets decapsulated')
314 self.assertEqual(err, n_packets_decapped)
316 # tun_ecn copies the ECN bits from the encap to the inner
317 p_ip4_encaps = [IP(src=tun_ecn.dst,
318 dst=self.pg0.local_ip4,
319 tos=tc) for tc in tcs]
320 p_ip4_replys = [p_ip4.copy() for i in range(len(p_ip4_encaps))]
321 p_ip4_replys[2].tos = ecn
322 p_ip4_replys[3].tos = ecn
323 for i, p_ip4_encap in enumerate(p_ip4_encaps):
324 p4 = (self.p_ether / p_ip4_encap / p_ip4 / self.p_payload)
325 p4_reply = (p_ip4_replys[i] / self.p_payload)
327 rx = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
328 n_packets_decapped += N_PACKETS
330 self.validate(p[1], p4_reply)
331 self.assert_packet_checksums_valid(p)
333 err = self.statistics.get_err_counter(
334 '/err/ipip4-input/packets decapsulated')
335 self.assertEqual(err, n_packets_decapped)
337 # IPv4 tunnel to IPv6
338 # for each encap tun will produce the same inner packet because it does
339 # not copy up fields from the payload
340 p_ip4_encaps = [IP(src=tun.dst,
341 dst=self.pg0.local_ip4,
342 tos=tc) for tc in tcs]
343 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
344 for p_ip4_encap in p_ip4_encaps:
346 p_ip4_encap / p_ip6 /
348 p6_reply = (p_ip6 / self.p_payload)
350 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
351 n_packets_decapped += N_PACKETS
353 self.validate(p[1], p6_reply)
354 self.assert_packet_checksums_valid(p)
356 err = self.statistics.get_err_counter(
357 '/err/ipip4-input/packets decapsulated')
358 self.assertEqual(err, n_packets_decapped)
360 # IPv4 tunnel to IPv6
361 # tun_ecn copies the ECN bits from the encap to the inner
362 p_ip4_encaps = [IP(src=tun_ecn.dst,
363 dst=self.pg0.local_ip4,
364 tos=tc) for tc in tcs]
365 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
366 p_ip6_replys = [p_ip6.copy() for i in range(len(p_ip4_encaps))]
367 p_ip6_replys[2].tc = ecn
368 p_ip6_replys[3].tc = ecn
369 for i, p_ip4_encap in enumerate(p_ip4_encaps):
370 p6 = (self.p_ether / p_ip4_encap / p_ip6 / self.p_payload)
371 p6_reply = (p_ip6_replys[i] / self.p_payload)
373 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
374 n_packets_decapped += N_PACKETS
376 self.validate(p[1], p6_reply)
377 self.assert_packet_checksums_valid(p)
379 err = self.statistics.get_err_counter(
380 '/err/ipip4-input/packets decapsulated')
381 self.assertEqual(err, n_packets_decapped)
384 # Fragmentation / Reassembly and Re-fragmentation
386 rv = self.vapi.ip_reassembly_enable_disable(
387 sw_if_index=self.pg1.sw_if_index,
390 self.vapi.ip_reassembly_set(timeout_ms=1000, max_reassemblies=1000,
391 max_reassembly_length=1000,
392 expire_walk_interval_ms=10000,
395 # Send lots of fragments, verify reassembled packet
396 frags, p4_reply = self.generate_ip4_frags(3131, 1400)
398 for i in range(0, 1000):
400 self.pg1.add_stream(f)
401 self.pg_enable_capture()
403 rx = self.pg0.get_capture(1000)
404 n_packets_decapped += 1000
407 self.validate(p[1], p4_reply)
409 err = self.statistics.get_err_counter(
410 '/err/ipip4-input/packets decapsulated')
411 self.assertEqual(err, n_packets_decapped)
415 for i in range(1, 90):
416 frags, p4_reply = self.generate_ip4_frags(i * 100, 1000)
419 self.pg_enable_capture()
420 self.pg1.add_stream(f)
422 rx = self.pg0.get_capture(89)
425 self.validate(p[1], r[i])
428 # Now try with re-fragmentation
430 # Send fragments to tunnel head-end, for the tunnel head end
431 # to reassemble and then refragment
433 self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [576, 0, 0, 0])
434 frags, p4_reply = self.generate_ip4_frags(3123, 1200)
435 self.pg_enable_capture()
436 self.pg1.add_stream(frags)
438 rx = self.pg0.get_capture(6)
439 reass_pkt = reassemble4(rx)
441 self.validate(reass_pkt, p4_reply)
443 self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1600, 0, 0, 0])
444 frags, p4_reply = self.generate_ip4_frags(3123, 1200)
445 self.pg_enable_capture()
446 self.pg1.add_stream(frags)
448 rx = self.pg0.get_capture(2)
449 reass_pkt = reassemble4(rx)
451 self.validate(reass_pkt, p4_reply)
453 # send large packets through the tunnel, expect them to be fragmented
454 self.vapi.sw_interface_set_mtu(tun_dscp.sw_if_index, [600, 0, 0, 0])
456 p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
457 IP(src="1.2.3.4", dst="130.67.0.1", tos=42) /
458 UDP(sport=1234, dport=1234) / Raw(b'Q' * 1000))
459 rx = self.send_and_expect(self.pg0, p4 * 15, self.pg1, 30)
462 inners.append(p[IP].payload)
463 reass_pkt = reassemble4(inners)
465 self.assert_packet_checksums_valid(p)
466 self.assertEqual(p[IP].ttl, 63)
468 def test_ipip_create(self):
469 """ ipip create / delete interface test """
470 rv = ipip_add_tunnel(self, '1.2.3.4', '2.3.4.5')
471 sw_if_index = rv.sw_if_index
472 self.vapi.ipip_del_tunnel(sw_if_index)
474 def test_ipip_vrf_create(self):
475 """ ipip create / delete interface VRF test """
477 t = VppIpTable(self, 20)
479 rv = ipip_add_tunnel(self, '1.2.3.4', '2.3.4.5', table_id=20)
480 sw_if_index = rv.sw_if_index
481 self.vapi.ipip_del_tunnel(sw_if_index)
483 def payload(self, len):
486 def test_mipip4(self):
487 """ p2mp IPv4 tunnel Tests """
489 for itf in self.pg_interfaces[:2]:
491 # one underlay nh for each overlay/tunnel peer
493 itf.generate_remote_hosts(4)
494 itf.configure_ipv4_neighbors()
497 # Create an p2mo IPIP tunnel.
499 # - assign an IP Addres
500 # - Add a route via the tunnel
502 ipip_if = VppIpIpTunInterface(self, itf,
505 mode=(VppEnum.vl_api_tunnel_mode_t.
507 ipip_if.add_vpp_config()
510 ipip_if.generate_remote_hosts(4)
512 self.logger.info(self.vapi.cli("sh adj"))
513 self.logger.info(self.vapi.cli("sh ip fib"))
516 # ensure we don't match to the tunnel if the source address
519 # tx = self.create_tunnel_stream_4o4(self.pg0,
522 # self.pg0.local_ip4,
523 # self.pg0.remote_ip4)
524 # self.send_and_assert_no_replies(self.pg0, tx)
529 for ii in range(1, 4):
530 route_addr = "4.4.4.%d" % ii
533 # route traffic via the peer
535 route_via_tun = VppIpRoute(
536 self, route_addr, 32,
537 [VppRoutePath(ipip_if._remote_hosts[ii].ip4,
538 ipip_if.sw_if_index)])
539 route_via_tun.add_vpp_config()
542 # Add a TEIB entry resolves the peer
544 teib = VppTeib(self, ipip_if,
545 ipip_if._remote_hosts[ii].ip4,
546 itf._remote_hosts[ii].ip4)
547 teib.add_vpp_config()
548 self.logger.info(self.vapi.cli("sh adj nbr ipip0 %s" %
549 ipip_if._remote_hosts[ii].ip4))
552 # Send a packet stream that is routed into the tunnel
553 # - packets are IPIP encapped
555 inner = (IP(dst=route_addr, src="5.5.5.5") /
556 UDP(sport=1234, dport=1234) /
558 tx_e = [(Ether(dst=self.pg0.local_mac,
559 src=self.pg0.remote_mac) /
560 inner) for x in range(63)]
562 rxs = self.send_and_expect(self.pg0, tx_e, itf)
565 self.assertEqual(rx[IP].src, itf.local_ip4)
566 self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4)
568 tx_i = [(Ether(dst=self.pg0.local_mac,
569 src=self.pg0.remote_mac) /
570 IP(src=itf._remote_hosts[ii].ip4,
572 IP(src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) /
573 UDP(sport=1234, dport=1234) /
574 Raw(b'0x44' * 100)) for x in range(63)]
576 self.logger.info(self.vapi.cli("sh ipip tunnel-hash"))
577 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
580 # delete and re-add the TEIB
582 teib.remove_vpp_config()
583 self.send_and_assert_no_replies(self.pg0, tx_e)
584 self.send_and_assert_no_replies(self.pg0, tx_i)
586 teib.add_vpp_config()
587 rx = self.send_and_expect(self.pg0, tx_e, itf)
589 self.assertEqual(rx[IP].src, itf.local_ip4)
590 self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4)
591 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
594 # we can also send to the peer's address
596 inner = (IP(dst=teib.peer, src="5.5.5.5") /
597 UDP(sport=1234, dport=1234) /
599 tx_e = [(Ether(dst=self.pg0.local_mac,
600 src=self.pg0.remote_mac) /
601 inner) for x in range(63)]
603 rxs = self.send_and_expect(self.pg0, tx_e, itf)
606 # with all of the peers in place, swap the ip-table of
609 table = VppIpTable(self, 2)
610 table.add_vpp_config()
612 ipip_if.unconfig_ip4()
613 ipip_if.set_table_ip4(self.table.table_id)
617 # we should still be able to reach the peers from the new table
619 inner = (IP(dst=teib.peer, src="5.5.5.5") /
620 UDP(sport=1234, dport=1234) /
622 tx_e = [(Ether(dst=self.pg0.local_mac,
623 src=self.pg0.remote_mac) /
624 inner) for x in range(63)]
626 rxs = self.send_and_expect(self.pg2, tx_e, itf)
629 ipip_if.unconfig_ip4()
630 ipip_if.set_table_ip4(0)
633 class TestIPIP6(VppTestCase):
634 """ IPIP6 Test Case """
638 super(TestIPIP6, cls).setUpClass()
639 cls.create_pg_interfaces(range(2))
640 cls.interfaces = list(cls.pg_interfaces)
643 def tearDownClass(cls):
644 super(TestIPIP6, cls).tearDownClass()
647 super(TestIPIP6, self).setUp()
648 for i in self.interfaces:
658 if not self.vpp_dead:
659 self.destroy_tunnel()
660 for i in self.pg_interfaces:
664 super(TestIPIP6, self).tearDown()
666 def setup_tunnel(self):
668 rv = ipip_add_tunnel(self,
672 sw_if_index = rv.sw_if_index
673 self.tunnel_if_index = sw_if_index
674 self.vapi.sw_interface_set_flags(sw_if_index, 1)
675 self.vapi.sw_interface_set_unnumbered(
676 sw_if_index=self.pg0.sw_if_index,
677 unnumbered_sw_if_index=sw_if_index)
679 # Add IPv4 and IPv6 routes via tunnel interface
680 ip4_via_tunnel = VppIpRoute(
681 self, "130.67.0.0", 16,
682 [VppRoutePath("0.0.0.0",
684 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
685 ip4_via_tunnel.add_vpp_config()
687 ip6_via_tunnel = VppIpRoute(
691 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
692 ip6_via_tunnel.add_vpp_config()
694 self.tunnel_ip6_via_tunnel = ip6_via_tunnel
695 self.tunnel_ip4_via_tunnel = ip4_via_tunnel
697 def destroy_tunnel(self):
699 self.tunnel_ip4_via_tunnel.remove_vpp_config()
700 self.tunnel_ip6_via_tunnel.remove_vpp_config()
702 rv = self.vapi.ipip_del_tunnel(sw_if_index=self.tunnel_if_index)
704 def validate(self, rx, expected):
705 self.assertEqual(rx, expected.__class__(expected))
707 def generate_ip6_frags(self, payload_length, fragment_size):
708 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
709 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
710 p_ip6 = IPv6(src="1::1", dst=self.pg0.remote_ip6)
711 outer_ip6 = (p_ether / IPv6(src=self.pg1.remote_ip6,
712 dst=self.pg0.local_ip6) /
713 IPv6ExtHdrFragment() / p_ip6 / p_payload)
714 frags = fragment6(outer_ip6, fragment_size)
715 p6_reply = (p_ip6 / p_payload)
717 return frags, p6_reply
719 def generate_ip6_hairpin_frags(self, payload_length, fragment_size):
720 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
721 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
722 p_ip6 = IPv6(src="1::1", dst="dead::1")
723 outer_ip6 = (p_ether / IPv6(src=self.pg1.remote_ip6,
724 dst=self.pg0.local_ip6) /
725 IPv6ExtHdrFragment() / p_ip6 / p_payload)
726 frags = fragment6(outer_ip6, fragment_size)
728 p6_reply = (IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6,
729 hlim=63) / p_ip6 / p_payload)
731 return frags, p6_reply
733 def test_encap(self):
734 """ ip{v4,v6} over ip6 test encap """
735 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
736 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh='UDP')
737 p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42)
738 p_payload = UDP(sport=1234, dport=1234)
741 # IPv6 in to IPv6 tunnel
742 p6 = (p_ether / p_ip6 / p_payload)
743 p6_reply = (IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6,
746 p6_reply[1].hlim -= 1
747 rx = self.send_and_expect(self.pg0, p6 * 11, self.pg1)
749 self.validate(p[1], p6_reply)
751 # IPv4 in to IPv6 tunnel
752 p4 = (p_ether / p_ip4 / p_payload)
753 p4_reply = (IPv6(src=self.pg0.local_ip6,
754 dst=self.pg1.remote_ip6, hlim=64) /
757 rx = self.send_and_expect(self.pg0, p4 * 11, self.pg1)
759 self.validate(p[1], p4_reply)
761 def test_decap(self):
762 """ ip{v4,v6} over ip6 test decap """
764 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
765 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh='UDP')
766 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
767 p_payload = UDP(sport=1234, dport=1234)
770 # IPv6 tunnel to IPv4
772 p4 = (p_ether / IPv6(src=self.pg1.remote_ip6,
773 dst=self.pg0.local_ip6) / p_ip4 / p_payload)
774 p4_reply = (p_ip4 / p_payload)
776 rx = self.send_and_expect(self.pg1, p4 * 11, self.pg0)
778 self.validate(p[1], p4_reply)
780 # IPv6 tunnel to IPv6
781 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
782 p6 = (p_ether / IPv6(src=self.pg1.remote_ip6,
783 dst=self.pg0.local_ip6) / p_ip6 / p_payload)
784 p6_reply = (p_ip6 / p_payload)
786 rx = self.send_and_expect(self.pg1, p6 * 11, self.pg0)
788 self.validate(p[1], p6_reply)
790 def verify_ip4ip6_encaps(self, a, p_ip4s, p_ip6_encaps):
791 for i, p_ip4 in enumerate(p_ip4s):
793 p4 = (self.p_ether / p_ip4 / self.p_payload)
796 p6_reply = (p_ip6_encaps[i] / p_ip4_inner / self.p_payload)
797 rx = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1)
799 self.validate(p[1], p6_reply)
800 self.assert_packet_checksums_valid(p)
802 def verify_ip6ip6_encaps(self, a, p_ip6s, p_ip6_encaps):
803 for i, p_ip6 in enumerate(p_ip6s):
805 p6 = (self.p_ether / p_ip6 / self.p_payload)
807 p_inner_ip6.hlim -= 1
808 p6_reply = (p_ip6_encaps[i] / p_inner_ip6 / self.p_payload)
809 rx = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1)
811 self.validate(p[1], p6_reply)
812 self.assert_packet_checksums_valid(p)
814 def test_ipip6(self):
815 """ ip{v4,v6} over ip6 test """
818 self.destroy_tunnel()
820 self.pg1.generate_remote_hosts(5)
821 self.pg1.configure_ipv6_neighbors()
822 e = VppEnum.vl_api_tunnel_encap_decap_flags_t
823 d = VppEnum.vl_api_ip_dscp_t
824 self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
825 self.p_payload = UDP(sport=1234, dport=1234) / Raw(b'X' * 100)
827 # create a TOS byte by shifting a DSCP code point 2 bits. those 2 bits
829 dscp = d.IP_API_DSCP_AF31 << 2
831 dscp_ecn = d.IP_API_DSCP_AF31 << 2 | ecn
833 # IPv4 transport that copies the DCSP from the payload
834 tun_dscp = VppIpIpTunInterface(
838 self.pg1.remote_hosts[0].ip6,
839 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP)
840 tun_dscp.add_vpp_config()
841 # IPv4 transport that copies the DCSP and ECN from the payload
842 tun_dscp_ecn = VppIpIpTunInterface(
846 self.pg1.remote_hosts[1].ip6,
847 flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP |
848 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN))
849 tun_dscp_ecn.add_vpp_config()
850 # IPv4 transport that copies the ECN from the payload and sets the
851 # DF bit on encap. copies the ECN on decap
852 tun_ecn = VppIpIpTunInterface(
856 self.pg1.remote_hosts[2].ip6,
857 flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN |
858 e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_DF |
859 e.TUNNEL_API_ENCAP_DECAP_FLAG_DECAP_COPY_ECN))
860 tun_ecn.add_vpp_config()
861 # IPv4 transport that sets a fixed DSCP in the encap and copies
863 tun = VppIpIpTunInterface(
867 self.pg1.remote_hosts[3].ip6,
868 dscp=d.IP_API_DSCP_AF11,
869 flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DF)
872 # array of all the tunnels
873 tuns = [tun_dscp, tun_dscp_ecn, tun_ecn, tun]
875 # addresses for prefixes routed via each tunnel
876 a4s = ["" for i in range(len(tuns))]
877 a6s = ["" for i in range(len(tuns))]
879 # IP headers for inner packets with each combination of DSCp/ECN tested
880 p_ip6s = [IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=dscp),
881 IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=dscp_ecn),
882 IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=ecn),
883 IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=0xff)]
884 p_ip4s = [IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp, flags='DF'),
885 IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp_ecn),
886 IP(src="1.2.3.4", dst="130.67.0.1", tos=ecn),
887 IP(src="1.2.3.4", dst="130.67.0.1", tos=0xff)]
889 # Configure each tunnel
890 for i, t in enumerate(tuns):
891 # Set interface up and enable IP on it
892 self.vapi.sw_interface_set_flags(t.sw_if_index, 1)
893 self.vapi.sw_interface_set_unnumbered(
894 sw_if_index=self.pg0.sw_if_index,
895 unnumbered_sw_if_index=t.sw_if_index)
897 # prefix for route / destination address for packets
898 a4s[i] = "130.67.%d.0" % i
899 a6s[i] = "dead:%d::" % i
901 # Add IPv4 and IPv6 routes via tunnel interface
902 ip4_via_tunnel = VppIpRoute(
904 [VppRoutePath("0.0.0.0",
906 proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
907 ip4_via_tunnel.add_vpp_config()
909 ip6_via_tunnel = VppIpRoute(
913 proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
914 ip6_via_tunnel.add_vpp_config()
920 # tun_dscp copies only the dscp
921 # expected TC values are thus only the DCSP value is present from the
923 exp_tcs = [dscp, dscp, 0, 0xfc]
924 p_ip6_encaps = [IPv6(src=self.pg0.local_ip6,
926 tc=tc) for tc in exp_tcs]
928 # IPv4 in to IPv4 tunnel
929 self.verify_ip4ip6_encaps(a4s[0], p_ip4s, p_ip6_encaps)
930 # IPv6 in to IPv4 tunnel
931 self.verify_ip6ip6_encaps(a6s[0], p_ip6s, p_ip6_encaps)
933 # tun_dscp_ecn copies the dscp and the ecn
934 exp_tcs = [dscp, dscp_ecn, ecn, 0xff]
935 p_ip6_encaps = [IPv6(src=self.pg0.local_ip6,
936 dst=tun_dscp_ecn.dst,
937 tc=tc) for tc in exp_tcs]
939 self.verify_ip4ip6_encaps(a4s[1], p_ip4s, p_ip6_encaps)
940 self.verify_ip6ip6_encaps(a6s[1], p_ip6s, p_ip6_encaps)
942 # tun_ecn copies only the ecn and always sets DF
943 exp_tcs = [0, ecn, ecn, ecn]
944 p_ip6_encaps = [IPv6(src=self.pg0.local_ip6,
946 tc=tc) for tc in exp_tcs]
948 self.verify_ip4ip6_encaps(a4s[2], p_ip4s, p_ip6_encaps)
949 self.verify_ip6ip6_encaps(a6s[2], p_ip6s, p_ip6_encaps)
951 # tun sets a fixed dscp
952 fixed_dscp = tun.dscp << 2
953 p_ip6_encaps = [IPv6(src=self.pg0.local_ip6,
955 tc=fixed_dscp) for i in range(len(p_ip4s))]
957 self.verify_ip4ip6_encaps(a4s[3], p_ip4s, p_ip6_encaps)
958 self.verify_ip6ip6_encaps(a6s[3], p_ip6s, p_ip6_encaps)
963 n_packets_decapped = self.statistics.get_err_counter(
964 '/err/ipip6-input/packets decapsulated')
966 self.p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
968 # IPv6 tunnel to IPv4
969 tcs = [0, dscp, dscp_ecn, ecn]
971 # one overlay packet and all combinations of its encap
972 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
973 p_ip6_encaps = [IPv6(src=tun.dst,
974 dst=self.pg0.local_ip6,
975 tc=tc) for tc in tcs]
977 # for each encap tun will produce the same inner packet because it does
978 # not copy up fields from the payload
979 for p_ip6_encap in p_ip6_encaps:
980 p6 = (self.p_ether / p_ip6_encap / p_ip4 / self.p_payload)
981 p4_reply = (p_ip4 / self.p_payload)
983 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
984 n_packets_decapped += N_PACKETS
986 self.validate(p[1], p4_reply)
987 self.assert_packet_checksums_valid(p)
989 err = self.statistics.get_err_counter(
990 '/err/ipip6-input/packets decapsulated')
991 self.assertEqual(err, n_packets_decapped)
993 # tun_ecn copies the ECN bits from the encap to the inner
994 p_ip6_encaps = [IPv6(src=tun_ecn.dst,
995 dst=self.pg0.local_ip6,
996 tc=tc) for tc in tcs]
997 p_ip4_replys = [p_ip4.copy() for i in range(len(p_ip6_encaps))]
998 p_ip4_replys[2].tos = ecn
999 p_ip4_replys[3].tos = ecn
1000 for i, p_ip6_encap in enumerate(p_ip6_encaps):
1001 p6 = (self.p_ether / p_ip6_encap / p_ip4 / self.p_payload)
1002 p4_reply = (p_ip4_replys[i] / self.p_payload)
1004 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1005 n_packets_decapped += N_PACKETS
1007 self.validate(p[1], p4_reply)
1008 self.assert_packet_checksums_valid(p)
1010 err = self.statistics.get_err_counter(
1011 '/err/ipip6-input/packets decapsulated')
1012 self.assertEqual(err, n_packets_decapped)
1014 # IPv6 tunnel to IPv6
1015 # for each encap tun will produce the same inner packet because it does
1016 # not copy up fields from the payload
1017 p_ip6_encaps = [IPv6(src=tun.dst,
1018 dst=self.pg0.local_ip6,
1019 tc=tc) for tc in tcs]
1020 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
1021 for p_ip6_encap in p_ip6_encaps:
1022 p6 = (self.p_ether / p_ip6_encap / p_ip6 / self.p_payload)
1023 p6_reply = (p_ip6 / self.p_payload)
1025 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1026 n_packets_decapped += N_PACKETS
1028 self.validate(p[1], p6_reply)
1029 self.assert_packet_checksums_valid(p)
1031 err = self.statistics.get_err_counter(
1032 '/err/ipip6-input/packets decapsulated')
1033 self.assertEqual(err, n_packets_decapped)
1035 # IPv6 tunnel to IPv6
1036 # tun_ecn copies the ECN bits from the encap to the inner
1037 p_ip6_encaps = [IPv6(src=tun_ecn.dst,
1038 dst=self.pg0.local_ip6,
1039 tc=tc) for tc in tcs]
1040 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
1041 p_ip6_replys = [p_ip6.copy() for i in range(len(p_ip6_encaps))]
1042 p_ip6_replys[2].tc = ecn
1043 p_ip6_replys[3].tc = ecn
1044 for i, p_ip6_encap in enumerate(p_ip6_encaps):
1045 p6 = (self.p_ether / p_ip6_encap / p_ip6 / self.p_payload)
1046 p6_reply = (p_ip6_replys[i] / self.p_payload)
1048 rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1049 n_packets_decapped += N_PACKETS
1051 self.validate(p[1], p6_reply)
1052 self.assert_packet_checksums_valid(p)
1054 err = self.statistics.get_err_counter(
1055 '/err/ipip6-input/packets decapsulated')
1056 self.assertEqual(err, n_packets_decapped)
1058 def test_frag(self):
1059 """ ip{v4,v6} over ip6 test frag """
1061 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1062 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh='UDP')
1063 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
1064 p_payload = UDP(sport=1234, dport=1234)
1067 # Fragmentation / Reassembly and Re-fragmentation
1069 rv = self.vapi.ip_reassembly_enable_disable(
1070 sw_if_index=self.pg1.sw_if_index,
1073 self.vapi.ip_reassembly_set(timeout_ms=1000, max_reassemblies=1000,
1074 max_reassembly_length=1000,
1075 expire_walk_interval_ms=10000,
1078 # Send lots of fragments, verify reassembled packet
1079 before_cnt = self.statistics.get_err_counter(
1080 '/err/ipip6-input/packets decapsulated')
1081 frags, p6_reply = self.generate_ip6_frags(3131, 1400)
1083 for i in range(0, 1000):
1085 self.pg1.add_stream(f)
1086 self.pg_enable_capture()
1088 rx = self.pg0.get_capture(1000)
1091 self.validate(p[1], p6_reply)
1093 cnt = self.statistics.get_err_counter(
1094 '/err/ipip6-input/packets decapsulated')
1095 self.assertEqual(cnt, before_cnt + 1000)
1099 # TODO: Check out why reassembly of atomic fragments don't work
1100 for i in range(10, 90):
1101 frags, p6_reply = self.generate_ip6_frags(i * 100, 1000)
1104 self.pg_enable_capture()
1105 self.pg1.add_stream(f)
1107 rx = self.pg0.get_capture(80)
1110 self.validate(p[1], r[i])
1113 # Simple fragmentation
1114 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1115 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
1117 # IPv6 in to IPv6 tunnel
1118 p_payload = UDP(sport=1234, dport=1234) / self.payload(1300)
1120 p6 = (p_ether / p_ip6 / p_payload)
1121 p6_reply = (IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6,
1124 p6_reply[1].hlim -= 1
1125 self.pg_enable_capture()
1126 self.pg0.add_stream(p6)
1128 rx = self.pg1.get_capture(2)
1130 # Scapy defragment doesn't deal well with multiple layers
1131 # of same type / Ethernet header first
1132 f = [p[1] for p in rx]
1133 reass_pkt = defragment6(f)
1134 self.validate(reass_pkt, p6_reply)
1136 # Now try with re-fragmentation
1138 # Send large fragments to tunnel head-end, for the tunnel head end
1139 # to reassemble and then refragment out the tunnel again.
1142 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
1143 frags, p6_reply = self.generate_ip6_hairpin_frags(8000, 1200)
1144 self.pg_enable_capture()
1145 self.pg1.add_stream(frags)
1147 rx = self.pg1.get_capture(7)
1148 f = [p[1] for p in rx]
1149 reass_pkt = defragment6(f)
1151 self.validate(reass_pkt, p6_reply)
1153 def test_ip6_mpls_frag(self):
1154 """ Test fragmenting IPv6 over MPLS """
1156 # IPv6 packets must be locally generated to be fragmented
1157 # the use of tunnel encaps
1158 tun_dst = VppIpRoute(
1159 self, "1000::1", 128,
1160 [VppRoutePath(self.pg1.remote_ip6,
1161 self.pg1.sw_if_index,
1162 labels=[VppMplsLabel(32)])]).add_vpp_config()
1164 tun = VppIpIpTunInterface(
1168 "1000::1").add_vpp_config()
1174 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index,
1177 p_6k = (Ether(dst=self.pg0.local_mac,
1178 src=self.pg0.remote_mac) /
1179 IPv6(src=self.pg0.remote_ip6,
1180 dst=tun.remote_ip6) /
1181 UDP(sport=1234, dport=5678) /
1183 p_2k = (Ether(dst=self.pg0.local_mac,
1184 src=self.pg0.remote_mac) /
1185 IPv6(src=self.pg0.remote_ip6,
1186 dst=tun.remote_ip6) /
1187 UDP(sport=1234, dport=5678) /
1189 p_1k = (Ether(dst=self.pg0.local_mac,
1190 src=self.pg0.remote_mac) /
1191 IPv6(src=self.pg0.remote_ip6,
1192 dst=tun.remote_ip6) /
1193 UDP(sport=1234, dport=5678) /
1196 # this is now the interface MTU frags
1197 rxs = self.send_and_expect(self.pg0, [p_6k], self.pg1, n_rx=4)
1198 self.assertEqual(rxs[0][UDP].dport, 5678)
1200 self.assertEqual(rx[MPLS].label, 32)
1201 self.assertEqual(rx[IPv6].dst, "1000::1")
1202 self.assertEqual(rx[IPv6].dst, "1000::1")
1203 self.send_and_expect(self.pg0, [p_2k], self.pg1, n_rx=2)
1204 self.send_and_expect(self.pg0, [p_1k], self.pg1)
1206 def test_ipip_create(self):
1207 """ ipip create / delete interface test """
1208 rv = ipip_add_tunnel(self, '1.2.3.4', '2.3.4.5')
1209 sw_if_index = rv.sw_if_index
1210 self.vapi.ipip_del_tunnel(sw_if_index)
1212 def test_ipip_vrf_create(self):
1213 """ ipip create / delete interface VRF test """
1215 t = VppIpTable(self, 20)
1217 rv = ipip_add_tunnel(self, '1.2.3.4', '2.3.4.5', table_id=20)
1218 sw_if_index = rv.sw_if_index
1219 self.vapi.ipip_del_tunnel(sw_if_index)
1221 def payload(self, len):
1225 class TestIPIPMPLS(VppTestCase):
1226 """ MPLS Test Case """
1229 def setUpClass(cls):
1230 super(TestIPIPMPLS, cls).setUpClass()
1231 cls.create_pg_interfaces(range(2))
1232 cls.interfaces = list(cls.pg_interfaces)
1235 def tearDownClass(cls):
1236 super(TestIPIPMPLS, cls).tearDownClass()
1239 super(TestIPIPMPLS, self).setUp()
1240 for i in self.interfaces:
1249 super(TestIPIPMPLS, self).tearDown()
1251 for i in self.pg_interfaces:
1256 def test_mpls(self):
1257 """ MPLS over ip{6,4} test """
1259 tbl = VppMplsTable(self, 0)
1260 tbl.add_vpp_config()
1262 self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1263 self.p_payload = UDP(sport=1234, dport=1234) / Raw(b'X' * 100)
1267 tun4 = VppIpIpTunInterface(
1271 self.pg1.remote_ip4).add_vpp_config()
1277 tun6 = VppIpIpTunInterface(
1281 self.pg1.remote_ip6).add_vpp_config()
1286 # ip routes into the tunnels with output labels
1287 r4 = VppIpRoute(self, "1.1.1.1", 32,
1291 labels=[VppMplsLabel(44)])]).add_vpp_config()
1292 r6 = VppIpRoute(self, "1::1", 128,
1296 labels=[VppMplsLabel(66)])]).add_vpp_config()
1298 # deag MPLS routes from the tunnel
1299 r4 = VppMplsRoute(self, 44, 1,
1301 self.pg0.remote_ip4,
1302 self.pg0.sw_if_index)]).add_vpp_config()
1303 r6 = VppMplsRoute(self, 66, 1,
1305 self.pg0.remote_ip6,
1306 self.pg0.sw_if_index)],
1307 eos_proto=f.FIB_PATH_NH_PROTO_IP6).add_vpp_config()
1312 p4 = (self.p_ether / IP(src="2.2.2.2", dst="1.1.1.1") / self.p_payload)
1314 rxs = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1)
1317 self.assertEqual(rx[IP].src, self.pg1.local_ip4)
1318 self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
1319 self.assertEqual(rx[MPLS].label, 44)
1320 inner = rx[MPLS].payload
1321 self.assertEqual(inner.src, "2.2.2.2")
1322 self.assertEqual(inner.dst, "1.1.1.1")
1324 p6 = (self.p_ether / IPv6(src="2::2", dst="1::1") / self.p_payload)
1326 rxs = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1)
1329 self.assertEqual(rx[IPv6].src, self.pg1.local_ip6)
1330 self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6)
1331 self.assertEqual(rx[MPLS].label, 66)
1332 inner = rx[MPLS].payload
1333 self.assertEqual(inner.src, "2::2")
1334 self.assertEqual(inner.dst, "1::1")
1339 p4 = (self.p_ether /
1340 IP(src=self.pg1.remote_ip4,
1341 dst=self.pg1.local_ip4) /
1342 MPLS(label=44, ttl=4) /
1347 rxs = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
1350 self.assertEqual(rx[IP].src, "1.1.1.1")
1351 self.assertEqual(rx[IP].dst, "2.2.2.2")
1353 p6 = (self.p_ether /
1354 IPv6(src=self.pg1.remote_ip6,
1355 dst=self.pg1.local_ip6) /
1356 MPLS(label=66, ttl=4) /
1361 rxs = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
1364 self.assertEqual(rx[IPv6].src, "1::1")
1365 self.assertEqual(rx[IPv6].dst, "2::2")
1371 if __name__ == '__main__':
1372 unittest.main(testRunner=VppTestRunner)