9 from struct import unpack, unpack_from
12 import unittest2 as unittest
16 from util import ppp, ppc
17 from re import compile
19 from scapy.packet import Raw
20 from scapy.layers.l2 import Ether
21 from scapy.layers.inet import IP, UDP, ICMP
22 from scapy.layers.ipsec import ESP
23 import scapy.layers.inet6 as inet6
24 from scapy.layers.inet6 import IPv6, ICMPv6DestUnreach
26 from framework import VppTestCase, VppTestRunner
28 from vpp_ip import DpoProto
29 from vpp_ip_route import VppIpRoute, VppRoutePath
30 from vpp_papi import VppEnum
31 from vpp_ipsec_tun_interface import VppIpsecTunInterface
36 class serverSocketThread(threading.Thread):
37 """ Socket server thread"""
39 def __init__(self, threadID, sockName):
40 threading.Thread.__init__(self)
41 self.threadID = threadID
42 self.sockName = sockName
47 # Wait for some packets on socket
49 data = self.sock.recv(65536)
51 # punt socket metadata
52 # packet_desc = data[0:8]
55 self.rx_pkts.append(Ether(data[8:]))
58 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
60 os.unlink(self.sockName)
63 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
64 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
65 self.sock.bind(self.sockName)
74 class TestPuntSocket(VppTestCase):
77 ports = [1111, 2222, 3333, 4444]
83 super(TestPuntSocket, cls).setUpClass()
86 def tearDownClass(cls):
87 super(TestPuntSocket, cls).tearDownClass()
90 def setUpConstants(cls):
91 cls.extra_vpp_punt_config = [
92 "punt", "{", "socket", cls.tempdir+"/socket_punt", "}"]
93 super(TestPuntSocket, cls).setUpConstants()
96 super(TestPuntSocket, self).setUp()
99 self.create_pg_interfaces(range(2))
100 for i in self.pg_interfaces:
104 del self.sock_servers[:]
105 super(TestPuntSocket, self).tearDown()
107 def socket_client_create(self, sock_name, id=None):
108 thread = serverSocketThread(id, sock_name)
109 self.sock_servers.append(thread)
113 def socket_client_close(self):
115 for thread in self.sock_servers:
116 rx_pkts += thread.close()
119 def verify_port(self, pr, vpr):
120 self.assertEqual(vpr.punt.type, pr['type'])
121 self.assertEqual(vpr.punt.punt.l4.port,
122 pr['punt']['l4']['port'])
123 self.assertEqual(vpr.punt.punt.l4.protocol,
124 pr['punt']['l4']['protocol'])
125 self.assertEqual(vpr.punt.punt.l4.af,
126 pr['punt']['l4']['af'])
128 def verify_exception(self, pr, vpr):
129 self.assertEqual(vpr.punt.type, pr['type'])
130 self.assertEqual(vpr.punt.punt.exception.id,
131 pr['punt']['exception']['id'])
133 def verify_udp_pkts(self, rxs, n_rx, port):
136 self.assertTrue(rx.haslayer(UDP))
137 if rx[UDP].dport == port:
139 self.assertEqual(n_match, n_rx)
142 def set_port(pr, port):
143 pr['punt']['l4']['port'] = port
147 def set_reason(pr, reason):
148 pr['punt']['exception']['id'] = reason
153 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
154 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
155 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
161 'protocol': udp_proto
169 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
170 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
171 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
177 'protocol': udp_proto
184 class TestIP4PuntSocket(TestPuntSocket):
185 """ Punt Socket for IPv4 """
189 super(TestIP4PuntSocket, cls).setUpClass()
192 def tearDownClass(cls):
193 super(TestIP4PuntSocket, cls).tearDownClass()
196 super(TestIP4PuntSocket, self).setUp()
198 for i in self.pg_interfaces:
203 super(TestIP4PuntSocket, self).tearDown()
204 for i in self.pg_interfaces:
208 def test_punt_socket_dump(self):
209 """ Punt socket registration/deregistration"""
211 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
212 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
213 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
215 punts = self.vapi.punt_socket_dump(type=pt_l4)
216 self.assertEqual(len(punts), 0)
219 # configure a punt socket
221 punt_l4 = mk_vpp_cfg4()
223 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
224 b"%s/socket_punt_1111" %
225 six.ensure_binary(self.tempdir))
226 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
227 b"%s/socket_punt_2222" %
228 six.ensure_binary(self.tempdir))
229 punts = self.vapi.punt_socket_dump(type=pt_l4)
230 self.assertEqual(len(punts), 2)
231 self.verify_port(set_port(punt_l4, 1111), punts[0])
232 self.verify_port(set_port(punt_l4, 2222), punts[1])
235 # deregister a punt socket
237 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
238 punts = self.vapi.punt_socket_dump(type=pt_l4)
239 self.assertEqual(len(punts), 1)
242 # configure a punt socket again
244 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
245 b"%s/socket_punt_1111" %
246 six.ensure_binary(self.tempdir))
247 self.vapi.punt_socket_register(set_port(punt_l4, 3333),
248 b"%s/socket_punt_3333" %
249 six.ensure_binary(self.tempdir))
250 punts = self.vapi.punt_socket_dump(type=pt_l4)
251 self.assertEqual(len(punts), 3)
253 self.logger.info(self.vapi.cli("sh punt sock reg"))
256 # deregister all punt socket
258 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
259 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
260 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
261 punts = self.vapi.punt_socket_dump(type=pt_l4)
262 self.assertEqual(len(punts), 0)
264 def test_punt_socket_traffic_single_port_single_socket(self):
265 """ Punt socket traffic single port single socket"""
268 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
269 punt_l4 = set_port(mk_vpp_cfg4(), port)
271 p = (Ether(src=self.pg0.remote_mac,
272 dst=self.pg0.local_mac) /
273 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
274 UDP(sport=9876, dport=port) /
277 pkts = p * self.nr_packets
279 punts = self.vapi.punt_socket_dump(type=pt_l4)
280 self.assertEqual(len(punts), 0)
283 # expect ICMP - port unreachable for all packets
285 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
288 self.assertEqual(int(p[IP].proto), 1) # ICMP
289 self.assertEqual(int(p[ICMP].code), 3) # unreachable
292 # configure a punt socket
294 self.socket_client_create(b"%s/socket_%d" % (
295 six.ensure_binary(self.tempdir), port))
296 self.vapi.punt_socket_register(punt_l4, b"%s/socket_%d" % (
297 six.ensure_binary(self.tempdir), port))
298 punts = self.vapi.punt_socket_dump(type=pt_l4)
299 self.assertEqual(len(punts), 1)
302 # expect punt socket and no packets on pg0
304 self.send_and_assert_no_replies(self.pg0, pkts)
305 rx = self.socket_client_close()
306 self.verify_udp_pkts(rx, len(pkts), port)
309 # remove punt socket. expect ICMP - port unreachable for all packets
311 self.vapi.punt_socket_deregister(punt_l4)
312 punts = self.vapi.punt_socket_dump(type=pt_l4)
313 self.assertEqual(len(punts), 0)
315 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
317 self.assertEqual(int(p[IP].proto), 1) # ICMP
318 self.assertEqual(int(p[ICMP].code), 3) # unreachable
320 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
321 """ Punt socket traffic multi ports and multi sockets"""
323 punt_l4 = mk_vpp_cfg4()
325 # configuration for each UDP port
329 # create stream of packets for each port
331 for port in self.ports:
332 # choose port from port list
335 pkt = (Ether(src=self.pg0.remote_mac,
336 dst=self.pg0.local_mac) /
337 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
338 UDP(sport=9876, dport=port) /
340 cfgs[port]['pkts'] = pkt * self.nr_packets
341 cfgs[port]['port'] = port
342 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
344 # configure punt sockets
345 cfgs[port]['sock'] = self.socket_client_create(
346 b"%s/socket_%d" % (six.ensure_binary(self.tempdir), port))
347 self.vapi.punt_socket_register(
349 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
353 # send the packets that get punted
355 for cfg in cfgs.values():
356 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
359 # test that we got the excepted packets on the expected socket
361 for cfg in cfgs.values():
362 rx = cfg['sock'].close()
363 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
364 self.vapi.punt_socket_deregister(cfg['vpp'])
366 def test_punt_socket_traffic_multi_ports_single_socket(self):
367 """ Punt socket traffic multi ports and single socket"""
369 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
370 punt_l4 = mk_vpp_cfg4()
373 # create stream of packets with each port
376 for port in self.ports:
377 # choose port from port list
378 pkt = (Ether(src=self.pg0.remote_mac,
379 dst=self.pg0.local_mac) /
380 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
381 UDP(sport=9876, dport=port) /
383 pkts += pkt * self.nr_packets
386 # configure a punt socket
388 self.socket_client_create(b"%s/socket_multi" %
389 six.ensure_binary(self.tempdir))
391 self.vapi.punt_socket_register(set_port(punt_l4, p),
393 six.ensure_binary(self.tempdir))
394 punts = self.vapi.punt_socket_dump(type=pt_l4)
395 self.assertEqual(len(punts), len(self.ports))
398 # expect punt socket and no packets on pg0
400 self.send_and_assert_no_replies(self.pg0, pkts)
401 self.logger.info(self.vapi.cli("show trace"))
402 rx = self.socket_client_close()
405 self.verify_udp_pkts(rx, self.nr_packets, p)
406 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
407 punts = self.vapi.punt_socket_dump(type=pt_l4)
408 self.assertEqual(len(punts), 0)
411 class TestIP6PuntSocket(TestPuntSocket):
412 """ Punt Socket for IPv6"""
416 super(TestIP6PuntSocket, cls).setUpClass()
419 def tearDownClass(cls):
420 super(TestIP6PuntSocket, cls).tearDownClass()
423 super(TestIP6PuntSocket, self).setUp()
425 for i in self.pg_interfaces:
430 super(TestIP6PuntSocket, self).tearDown()
431 for i in self.pg_interfaces:
435 def test_punt_socket_dump(self):
436 """ Punt socket registration """
438 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
439 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
440 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
442 # configure a punt socket
449 'protocol': udp_proto
454 punts = self.vapi.punt_socket_dump(type=pt_l4)
455 self.assertEqual(len(punts), 0)
458 # configure a punt socket
460 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
462 six.ensure_binary(self.tempdir))
463 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
465 six.ensure_binary(self.tempdir))
466 punts = self.vapi.punt_socket_dump(type=pt_l4)
467 self.assertEqual(len(punts), 2)
468 self.verify_port(set_port(punt_l4, 1111), punts[0])
469 self.verify_port(set_port(punt_l4, 2222), punts[1])
472 # deregister a punt socket
474 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
475 punts = self.vapi.punt_socket_dump(type=pt_l4)
476 self.assertEqual(len(punts), 1)
479 # configure a punt socket again
481 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
483 six.ensure_binary(self.tempdir))
484 punts = self.vapi.punt_socket_dump(type=pt_l4)
485 self.assertEqual(len(punts), 2)
488 # deregister all punt socket
490 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
491 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
492 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
493 punts = self.vapi.punt_socket_dump(type=pt_l4)
494 self.assertEqual(len(punts), 0)
496 def test_punt_socket_traffic_single_port_single_socket(self):
497 """ Punt socket traffic single port single socket"""
500 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
501 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
502 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
508 'protocol': udp_proto,
514 p = (Ether(src=self.pg0.remote_mac,
515 dst=self.pg0.local_mac) /
516 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
517 inet6.UDP(sport=9876, dport=port) /
520 pkts = p * self.nr_packets
522 punts = self.vapi.punt_socket_dump(type=pt_l4)
523 self.assertEqual(len(punts), 0)
526 # expect ICMPv6 - destination unreachable for all packets
528 self.vapi.cli("clear trace")
529 self.pg0.add_stream(pkts)
530 self.pg_enable_capture(self.pg_interfaces)
532 # FIXME - when punt socket deregister is implemented
533 # rx = self.pg0.get_capture(self.nr_packets)
535 # self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
536 # self.assertEqual(int(p[ICMPv6DestUnreach].code),4) # unreachable
539 # configure a punt socket
541 self.socket_client_create(b"%s/socket_%d" % (
542 six.ensure_binary(self.tempdir), port))
543 self.vapi.punt_socket_register(punt_l4, b"%s/socket_%d" % (
544 six.ensure_binary(self.tempdir), port))
545 punts = self.vapi.punt_socket_dump(type=pt_l4)
546 self.assertEqual(len(punts), 1)
549 # expect punt socket and no packets on pg0
551 self.vapi.cli("clear errors")
552 self.vapi.cli("clear trace")
553 self.pg0.add_stream(pkts)
554 self.pg_enable_capture(self.pg_interfaces)
556 self.pg0.get_capture(0)
557 self.logger.info(self.vapi.cli("show trace"))
558 rx = self.socket_client_close()
559 self.verify_udp_pkts(rx, len(pkts), port)
562 # remove punt socket. expect ICMP - dest. unreachable for all packets
564 self.vapi.punt_socket_deregister(punt_l4)
565 punts = self.vapi.punt_socket_dump(type=pt_l4)
566 self.assertEqual(len(punts), 0)
567 self.pg0.add_stream(pkts)
568 self.pg_enable_capture(self.pg_interfaces)
570 # FIXME - when punt socket deregister is implemented
571 # self.pg0.get_capture(nr_packets)
573 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
574 """ Punt socket traffic multi ports and multi sockets"""
576 punt_l4 = mk_vpp_cfg6()
578 # configuration for each UDP port
582 # create stream of packets for each port
584 for port in self.ports:
585 # choose port from port list
588 pkt = (Ether(src=self.pg0.remote_mac,
589 dst=self.pg0.local_mac) /
590 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
591 UDP(sport=9876, dport=port) /
593 cfgs[port]['pkts'] = pkt * self.nr_packets
594 cfgs[port]['port'] = port
595 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
597 # configure punt sockets
598 cfgs[port]['sock'] = self.socket_client_create(
599 b"%s/socket_%d" % (six.ensure_binary(self.tempdir), port))
600 self.vapi.punt_socket_register(
602 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
606 # send the packets that get punted
608 for cfg in cfgs.values():
609 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
612 # test that we got the excepted packets on the expected socket
614 for cfg in cfgs.values():
615 rx = cfg['sock'].close()
616 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
617 self.vapi.punt_socket_deregister(cfg['vpp'])
619 def test_punt_socket_traffic_multi_ports_single_socket(self):
620 """ Punt socket traffic multi ports and single socket"""
622 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
623 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
624 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
630 'protocol': udp_proto,
636 # create stream of packets with each port
639 for port in self.ports:
640 # choose port from port list
641 pkt = (Ether(src=self.pg0.remote_mac,
642 dst=self.pg0.local_mac) /
643 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
644 UDP(sport=9876, dport=port) /
646 pkts += pkt * self.nr_packets
651 punts = self.vapi.punt_socket_dump(type=pt_l4)
652 self.assertEqual(len(punts), 0)
655 # configure a punt socket
657 self.socket_client_create(b"%s/socket_multi" %
658 six.ensure_binary(self.tempdir))
660 self.vapi.punt_socket_register(set_port(punt_l4, p),
662 six.ensure_binary(self.tempdir))
663 punts = self.vapi.punt_socket_dump(type=pt_l4)
664 self.assertEqual(len(punts), len(self.ports))
667 # expect punt socket and no packets on pg0
669 self.vapi.cli("clear errors")
670 self.vapi.cli("clear trace")
671 self.pg0.add_stream(pkts)
672 self.pg_enable_capture(self.pg_interfaces)
674 self.pg0.get_capture(0)
675 rx = self.socket_client_close()
678 self.verify_udp_pkts(rx, self.nr_packets, p)
679 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
680 punts = self.vapi.punt_socket_dump(type=pt_l4)
681 self.assertEqual(len(punts), 0)
684 class TestExceptionPuntSocket(TestPuntSocket):
685 """ Punt Socket for Exceptions """
689 super(TestExceptionPuntSocket, cls).setUpClass()
692 def tearDownClass(cls):
693 super(TestExceptionPuntSocket, cls).tearDownClass()
696 super(TestExceptionPuntSocket, self).setUp()
698 for i in self.pg_interfaces:
703 super(TestExceptionPuntSocket, self).tearDown()
704 for i in self.pg_interfaces:
708 def test_registration(self):
709 """ Punt socket registration/deregistration"""
711 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
713 punts = self.vapi.punt_socket_dump(type=pt_ex)
714 self.assertEqual(len(punts), 0)
717 # configure a punt socket
726 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
727 b"%s/socket_punt_1" %
728 six.ensure_binary(self.tempdir))
729 self.vapi.punt_socket_register(set_reason(punt_ex, 2),
730 b"%s/socket_punt_2" %
731 six.ensure_binary(self.tempdir))
732 punts = self.vapi.punt_socket_dump(type=pt_ex)
733 self.assertEqual(len(punts), 2)
734 self.verify_exception(set_reason(punt_ex, 1), punts[0])
735 self.verify_exception(set_reason(punt_ex, 2), punts[1])
738 # deregister a punt socket
740 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
741 punts = self.vapi.punt_socket_dump(type=pt_ex)
742 self.assertEqual(len(punts), 1)
745 # configure a punt socket again
747 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
748 b"%s/socket_punt_1" %
749 six.ensure_binary(self.tempdir))
750 self.vapi.punt_socket_register(set_reason(punt_ex, 3),
751 b"%s/socket_punt_3" %
752 six.ensure_binary(self.tempdir))
753 punts = self.vapi.punt_socket_dump(type=pt_ex)
754 self.assertEqual(len(punts), 3)
756 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
759 # deregister all punt socket
761 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
762 self.vapi.punt_socket_deregister(set_reason(punt_ex, 2))
763 self.vapi.punt_socket_deregister(set_reason(punt_ex, 3))
764 punts = self.vapi.punt_socket_dump(type=pt_ex)
765 self.assertEqual(len(punts), 0)
767 def verify_esp_pkts(self, rxs, n_sent, spi):
768 self.assertEqual(len(rxs), n_sent)
770 self.assertTrue(rx.haslayer(ESP))
771 self.assertEqual(rx[ESP].spi, spi)
773 def test_traffic(self):
774 """ Punt socket traffic """
777 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
786 # we need an IPSec tunnel for this to work otherwise ESP gets dropped
787 # due to unknown IP proto
789 VppIpsecTunInterface(self, self.pg0, 1000, 1000,
790 (VppEnum.vl_api_ipsec_crypto_alg_t.
791 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
794 (VppEnum.vl_api_ipsec_integ_alg_t.
795 IPSEC_API_INTEG_ALG_SHA1_96),
797 "0123456701234567").add_vpp_config()
800 # we're dealing with IPSec tunnels punting for no-such-tunnel
804 cfgs['ipsec4-no-such-tunnel'] = {'spi': 99}
805 cfgs['ipsec4-spi-0'] = {'spi': 0}
808 # find the VPP ID for these punt exception reasin
810 rs = self.vapi.punt_reason_dump()
813 if r.reason.name == key:
814 cfgs[key]['id'] = r.reason.id
815 cfgs[key]['vpp'] = copy.deepcopy(
821 # create packet streams and configure a punt sockets
823 for cfg in cfgs.values():
824 pkt = (Ether(src=self.pg0.remote_mac,
825 dst=self.pg0.local_mac) /
826 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
827 ESP(spi=cfg['spi'], seq=3) /
829 cfg['pkts'] = pkt * self.nr_packets
831 cfg['sock'] = self.socket_client_create(b"%s/socket_%d" % (
832 six.ensure_binary(self.tempdir), cfg['id']))
833 self.vapi.punt_socket_register(
835 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
839 # send packets for each SPI we expect to be punted
841 for cfg in cfgs.values():
842 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
845 # verify the punted packets arrived on the associated socket
847 for cfg in cfgs.values():
848 rx = cfg['sock'].close()
849 self.verify_esp_pkts(rx, len(cfg['pkts']), cfg['spi'])
850 self.vapi.punt_socket_deregister(cfg['vpp'])
853 class TestPunt(VppTestCase):
854 """ Punt Test Case """
858 super(TestPunt, cls).setUpClass()
861 def tearDownClass(cls):
862 super(TestPunt, cls).tearDownClass()
865 super(TestPunt, self).setUp()
867 self.create_pg_interfaces(range(4))
869 for i in self.pg_interfaces:
877 for i in self.pg_interfaces:
882 super(TestPunt, self).tearDown()
885 """ Exception Path testing """
888 # Using the test CLI we will hook in a exception path to
889 # send ACL deny packets out of pg0 and pg1.
890 # the ACL is src,dst = 1.1.1.1,1.1.1.2
892 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
893 [VppRoutePath(self.pg3.remote_ip4,
894 self.pg3.sw_if_index)])
895 ip_1_1_1_2.add_vpp_config()
896 ip_1_2 = VppIpRoute(self, "1::2", 128,
897 [VppRoutePath(self.pg3.remote_ip6,
898 self.pg3.sw_if_index,
899 proto=DpoProto.DPO_PROTO_IP6)],
901 ip_1_2.add_vpp_config()
903 p4 = (Ether(src=self.pg2.remote_mac,
904 dst=self.pg2.local_mac) /
905 IP(src="1.1.1.1", dst="1.1.1.2") /
906 UDP(sport=1234, dport=1234) /
908 p6 = (Ether(src=self.pg2.remote_mac,
909 dst=self.pg2.local_mac) /
910 IPv6(src="1::1", dst="1::2") /
911 UDP(sport=1234, dport=1234) /
913 self.send_and_expect(self.pg2, p4*1, self.pg3)
914 self.send_and_expect(self.pg2, p6*1, self.pg3)
917 # apply the punting features
919 self.vapi.cli("test punt pg2")
924 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
925 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
929 # 1 - node error counters
930 # 2 - per-reason counters
931 # 2, 3 are the index of the assigned punt reason
933 stats = self.statistics.get_err_counter(
934 "/err/punt-dispatch/No registrations")
935 self.assertEqual(stats, 2*NUM_PKTS)
937 stats = self.statistics.get_counter("/net/punt")
938 self.assertEqual(stats[0][7]['packets'], NUM_PKTS)
939 self.assertEqual(stats[0][8]['packets'], NUM_PKTS)
942 # use the test CLI to test a client that punts exception
945 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
946 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
948 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
949 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
952 # check the packets come out IP unmodified but destined to pg0 host
955 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
956 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
957 self.assertEqual(p4[IP].dst, rx[IP].dst)
958 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
960 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
961 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
962 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
963 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
965 stats = self.statistics.get_counter("/net/punt")
966 self.assertEqual(stats[0][7]['packets'], 2*NUM_PKTS)
967 self.assertEqual(stats[0][8]['packets'], 2*NUM_PKTS)
970 # add another registration for the same reason to send packets
973 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
974 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
976 self.vapi.cli("clear trace")
977 self.pg2.add_stream(p4 * NUM_PKTS)
978 self.pg_enable_capture(self.pg_interfaces)
981 rxd = self.pg0.get_capture(NUM_PKTS)
983 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
984 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
985 self.assertEqual(p4[IP].dst, rx[IP].dst)
986 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
987 rxd = self.pg1.get_capture(NUM_PKTS)
989 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
990 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
991 self.assertEqual(p4[IP].dst, rx[IP].dst)
992 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
994 self.vapi.cli("clear trace")
995 self.pg2.add_stream(p6 * NUM_PKTS)
996 self.pg_enable_capture(self.pg_interfaces)
999 rxd = self.pg0.get_capture(NUM_PKTS)
1001 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1002 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1003 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1004 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1005 rxd = self.pg1.get_capture(NUM_PKTS)
1007 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1008 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1009 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1010 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1012 stats = self.statistics.get_counter("/net/punt")
1013 self.assertEqual(stats[0][7]['packets'], 3*NUM_PKTS)
1014 self.assertEqual(stats[0][8]['packets'], 3*NUM_PKTS)
1016 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1017 self.logger.info(self.vapi.cli("show punt client"))
1018 self.logger.info(self.vapi.cli("show punt reason"))
1019 self.logger.info(self.vapi.cli("show punt stats"))
1020 self.logger.info(self.vapi.cli("show punt db"))
1023 # dump the punt registered reasons
1024 # search for a few we know should be there
1026 rs = self.vapi.punt_reason_dump()
1028 reasons = ["ipsec6-no-such-tunnel",
1029 "ipsec4-no-such-tunnel",
1033 for reason in reasons:
1036 if r.reason.name == reason:
1039 self.assertTrue(found)
1042 if __name__ == '__main__':
1043 unittest.main(testRunner=VppTestRunner)