blob: 8ee43f1ed73f82e82088669f0d61dd207baa7df1 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Pavel Kotuceke88865d2018-11-28 07:42:11 +01002import random
3import socket
Pavel Kotuceke88865d2018-11-28 07:42:11 +01004import os
Pavel Kotucek9edb83a2018-12-11 16:57:25 +01005import threading
Neale Ranns50f0ac02019-05-15 02:13:37 -07006import copy
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +01007import fcntl
8import time
Tom Jones853cc9f2024-02-07 13:28:58 +00009import errno
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010010
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -080011try:
12 import unittest2 as unittest
13except ImportError:
14 import unittest
15
Pavel Kotuceke88865d2018-11-28 07:42:11 +010016from scapy.packet import Raw
17from scapy.layers.l2 import Ether
Andrew Yourtchenkofeb77422023-03-17 01:47:58 +000018from scapy.layers.l2 import Dot1Q
Pavel Kotuceke88865d2018-11-28 07:42:11 +010019from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns50f0ac02019-05-15 02:13:37 -070020from scapy.layers.ipsec import ESP
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -080021import scapy.layers.inet6 as inet6
Dave Wallace8800f732023-08-31 00:47:44 -040022from scapy.layers.inet6 import IPv6
Neale Rannsb538dd82019-05-21 06:54:54 -070023from scapy.contrib.ospf import OSPF_Hdr, OSPFv3_Hello
Dave Wallace8800f732023-08-31 00:47:44 -040024from framework import VppTestCase
25from asfframework import VppTestRunner, tag_fixme_vpp_workers
26from vpp_sub_interface import VppDot1QSubint
Pavel Kotuceke88865d2018-11-28 07:42:11 +010027
Neale Ranns76b56492018-09-28 15:16:14 +000028from vpp_ip import DpoProto
29from vpp_ip_route import VppIpRoute, VppRoutePath
Neale Rannsa9e27742020-12-23 16:22:28 +000030from vpp_ipsec import VppIpsecSA, VppIpsecTunProtect, VppIpsecInterface
Neale Ranns50f0ac02019-05-15 02:13:37 -070031from vpp_papi import VppEnum
Neale Ranns76b56492018-09-28 15:16:14 +000032
Paul Vinciguerra4271c972019-05-14 13:25:49 -040033NUM_PKTS = 67
34
Pavel Kotuceke88865d2018-11-28 07:42:11 +010035
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010036class serverSocketThread(threading.Thread):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020037 """Socket server thread"""
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010038
Neale Ranns50f0ac02019-05-15 02:13:37 -070039 def __init__(self, threadID, sockName):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010040 threading.Thread.__init__(self)
41 self.threadID = threadID
42 self.sockName = sockName
43 self.sock = None
Neale Ranns50f0ac02019-05-15 02:13:37 -070044 self.rx_pkts = []
Dave Wallacec44402f2021-05-07 21:40:54 -040045 self.stop_running = False
Neale Ranns50f0ac02019-05-15 02:13:37 -070046
47 def rx_packets(self):
48 # Wait for some packets on socket
Dave Wallacec44402f2021-05-07 21:40:54 -040049 while True:
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010050 try:
51 data = self.sock.recv(65536)
Neale Ranns50f0ac02019-05-15 02:13:37 -070052
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010053 # punt socket metadata
54 # packet_desc = data[0:8]
Neale Ranns50f0ac02019-05-15 02:13:37 -070055
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010056 # Ethernet
57 self.rx_pkts.append(Ether(data[8:]))
58 except IOError as e:
Tom Jones853cc9f2024-02-07 13:28:58 +000059 if e.errno == errno.EAGAIN:
Dave Wallacec44402f2021-05-07 21:40:54 -040060 # nothing to receive, stop running or sleep a little
61 if self.stop_running:
62 break
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010063 time.sleep(0.1)
64 pass
65 else:
66 raise
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010067
68 def run(self):
69 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
70 try:
71 os.unlink(self.sockName)
72 except:
73 pass
Neale Ranns50f0ac02019-05-15 02:13:37 -070074 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
75 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010076 fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010077 self.sock.bind(self.sockName)
78
Neale Ranns50f0ac02019-05-15 02:13:37 -070079 self.rx_packets()
80
81 def close(self):
Dave Wallacec44402f2021-05-07 21:40:54 -040082 self.stop_running = True
Dave Wallacef4d338f2021-05-06 15:59:59 -040083 threading.Thread.join(self)
Dave Wallacec44402f2021-05-07 21:40:54 -040084 self.sock.close()
Neale Ranns50f0ac02019-05-15 02:13:37 -070085 return self.rx_pkts
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010086
87
Pavel Kotuceke88865d2018-11-28 07:42:11 +010088class TestPuntSocket(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020089 """Punt Socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +010090
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010091 ports = [1111, 2222, 3333, 4444]
92 sock_servers = list()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +000093 # FIXME: nr_packets > 3 results in failure
94 # nr_packets = 3 makes the test unstable
95 nr_packets = 2
Pavel Kotuceke88865d2018-11-28 07:42:11 +010096
97 @classmethod
Paul Vinciguerra8d991d92019-01-25 14:05:48 -080098 def setUpClass(cls):
99 super(TestPuntSocket, cls).setUpClass()
100
101 @classmethod
102 def tearDownClass(cls):
103 super(TestPuntSocket, cls).tearDownClass()
104
105 @classmethod
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100106 def setUpConstants(cls):
Klement Sekerad3e0d102023-01-26 12:35:35 +0100107 cls.extra_vpp_config = [
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200108 "punt",
109 "{",
110 "socket",
111 cls.tempdir + "/socket_punt",
112 "}",
113 ]
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100114 super(TestPuntSocket, cls).setUpConstants()
115
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100116 def setUp(self):
117 super(TestPuntSocket, self).setUp()
118 random.seed()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100119
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100120 self.create_pg_interfaces(range(2))
121 for i in self.pg_interfaces:
122 i.admin_up()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100123
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100124 def tearDown(self):
125 del self.sock_servers[:]
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800126 super(TestPuntSocket, self).tearDown()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100127
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100128 def socket_client_create(self, sock_name, id=None):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700129 thread = serverSocketThread(id, sock_name)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100130 self.sock_servers.append(thread)
131 thread.start()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700132 return thread
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100133
134 def socket_client_close(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700135 rx_pkts = []
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100136 for thread in self.sock_servers:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700137 rx_pkts += thread.close()
138 return rx_pkts
139
140 def verify_port(self, pr, vpr):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200141 self.assertEqual(vpr.punt.type, pr["type"])
142 self.assertEqual(vpr.punt.punt.l4.port, pr["punt"]["l4"]["port"])
143 self.assertEqual(vpr.punt.punt.l4.protocol, pr["punt"]["l4"]["protocol"])
144 self.assertEqual(vpr.punt.punt.l4.af, pr["punt"]["l4"]["af"])
Neale Ranns50f0ac02019-05-15 02:13:37 -0700145
146 def verify_exception(self, pr, vpr):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200147 self.assertEqual(vpr.punt.type, pr["type"])
148 self.assertEqual(vpr.punt.punt.exception.id, pr["punt"]["exception"]["id"])
Neale Ranns50f0ac02019-05-15 02:13:37 -0700149
Neale Rannsb538dd82019-05-21 06:54:54 -0700150 def verify_ip_proto(self, pr, vpr):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200151 self.assertEqual(vpr.punt.type, pr["type"])
152 self.assertEqual(vpr.punt.punt.ip_proto.af, pr["punt"]["ip_proto"]["af"])
153 self.assertEqual(
154 vpr.punt.punt.ip_proto.protocol, pr["punt"]["ip_proto"]["protocol"]
155 )
Neale Rannsb538dd82019-05-21 06:54:54 -0700156
Neale Ranns50f0ac02019-05-15 02:13:37 -0700157 def verify_udp_pkts(self, rxs, n_rx, port):
158 n_match = 0
159 for rx in rxs:
160 self.assertTrue(rx.haslayer(UDP))
161 if rx[UDP].dport == port:
162 n_match += 1
163 self.assertEqual(n_match, n_rx)
164
165
166def set_port(pr, port):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200167 pr["punt"]["l4"]["port"] = port
Neale Ranns50f0ac02019-05-15 02:13:37 -0700168 return pr
169
170
171def set_reason(pr, reason):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200172 pr["punt"]["exception"]["id"] = reason
Neale Ranns50f0ac02019-05-15 02:13:37 -0700173 return pr
174
175
176def mk_vpp_cfg4():
177 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
178 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
179 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200180 punt_l4 = {"type": pt_l4, "punt": {"l4": {"af": af_ip4, "protocol": udp_proto}}}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700181 return punt_l4
182
183
184def mk_vpp_cfg6():
185 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
186 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
187 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200188 punt_l4 = {"type": pt_l4, "punt": {"l4": {"af": af_ip6, "protocol": udp_proto}}}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700189 return punt_l4
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100190
191
192class TestIP4PuntSocket(TestPuntSocket):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200193 """Punt Socket for IPv4 UDP"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100194
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800195 @classmethod
196 def setUpClass(cls):
197 super(TestIP4PuntSocket, cls).setUpClass()
198
199 @classmethod
200 def tearDownClass(cls):
201 super(TestIP4PuntSocket, cls).tearDownClass()
202
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100203 def setUp(self):
204 super(TestIP4PuntSocket, self).setUp()
205
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100206 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100207 i.config_ip4()
208 i.resolve_arp()
209
210 def tearDown(self):
211 super(TestIP4PuntSocket, self).tearDown()
212 for i in self.pg_interfaces:
213 i.unconfig_ip4()
214 i.admin_down()
215
216 def test_punt_socket_dump(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200217 """Punt socket registration/deregistration"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100218
Neale Ranns50f0ac02019-05-15 02:13:37 -0700219 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
220 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
221 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
222
223 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100224 self.assertEqual(len(punts), 0)
225
226 #
227 # configure a punt socket
228 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700229 punt_l4 = mk_vpp_cfg4()
230
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200231 self.vapi.punt_socket_register(
232 set_port(punt_l4, 1111), "%s/socket_punt_1111" % self.tempdir
233 )
234 self.vapi.punt_socket_register(
235 set_port(punt_l4, 2222), "%s/socket_punt_2222" % self.tempdir
236 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700237 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100238 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700239 self.verify_port(set_port(punt_l4, 1111), punts[0])
240 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100241
242 #
243 # deregister a punt socket
244 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700245 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
246 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100247 self.assertEqual(len(punts), 1)
248
249 #
250 # configure a punt socket again
251 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200252 self.vapi.punt_socket_register(
253 set_port(punt_l4, 1111), "%s/socket_punt_1111" % self.tempdir
254 )
255 self.vapi.punt_socket_register(
256 set_port(punt_l4, 3333), "%s/socket_punt_3333" % self.tempdir
257 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700258 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100259 self.assertEqual(len(punts), 3)
260
Neale Ranns50f0ac02019-05-15 02:13:37 -0700261 self.logger.info(self.vapi.cli("sh punt sock reg"))
262
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100263 #
264 # deregister all punt socket
265 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700266 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
267 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
268 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
269 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100270 self.assertEqual(len(punts), 0)
271
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100272 def test_punt_socket_traffic_single_port_single_socket(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200273 """Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100274
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100275 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700276 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
277 punt_l4 = set_port(mk_vpp_cfg4(), port)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100278
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200279 p = (
280 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
281 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
282 / UDP(sport=9876, dport=port)
283 / Raw(b"\xa5" * 100)
284 )
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100285
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100286 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100287
Neale Ranns50f0ac02019-05-15 02:13:37 -0700288 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100289 self.assertEqual(len(punts), 0)
290
291 #
292 # expect ICMP - port unreachable for all packets
293 #
Neale Ranns5c6dd172022-02-17 09:08:47 +0000294 rx = self.send_and_expect_some(self.pg0, pkts, self.pg0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700295
296 for p in rx:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200297 self.assertEqual(int(p[IP].proto), 1) # ICMP
Neale Ranns50f0ac02019-05-15 02:13:37 -0700298 self.assertEqual(int(p[ICMP].code), 3) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100299
300 #
301 # configure a punt socket
302 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200303 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200304 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700305 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100306 self.assertEqual(len(punts), 1)
307
308 #
309 # expect punt socket and no packets on pg0
310 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700311 self.send_and_assert_no_replies(self.pg0, pkts)
312 rx = self.socket_client_close()
313 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100314
315 #
316 # remove punt socket. expect ICMP - port unreachable for all packets
317 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700318 self.vapi.punt_socket_deregister(punt_l4)
319 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100320 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100321
Neale Ranns5c6dd172022-02-17 09:08:47 +0000322 rx = self.send_and_expect_some(self.pg0, pkts, self.pg0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700323 for p in rx:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200324 self.assertEqual(int(p[IP].proto), 1) # ICMP
Neale Ranns50f0ac02019-05-15 02:13:37 -0700325 self.assertEqual(int(p[ICMP].code), 3) # unreachable
326
327 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200328 """Punt socket traffic multi ports and multi sockets"""
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100329
Neale Ranns50f0ac02019-05-15 02:13:37 -0700330 punt_l4 = mk_vpp_cfg4()
331
332 # configuration for each UDP port
333 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100334
335 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700336 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100337 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700338 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100339 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700340 cfgs[port] = {}
341
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200342 pkt = (
343 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
344 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
345 / UDP(sport=9876, dport=port)
346 / Raw(b"\xa5" * 100)
347 )
348 cfgs[port]["pkts"] = pkt * self.nr_packets
349 cfgs[port]["port"] = port
350 cfgs[port]["vpp"] = copy.deepcopy(set_port(punt_l4, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700351
352 # configure punt sockets
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200353 cfgs[port]["sock"] = self.socket_client_create(
354 "%s/socket_%d" % (self.tempdir, port)
355 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700356 self.vapi.punt_socket_register(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200357 cfgs[port]["vpp"], "%s/socket_%d" % (self.tempdir, port)
358 )
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100359
360 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700361 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100362 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700363 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200364 self.send_and_assert_no_replies(self.pg0, cfg["pkts"])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100365
366 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700367 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100368 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700369 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200370 rx = cfg["sock"].close()
371 self.verify_udp_pkts(rx, len(cfg["pkts"]), cfg["port"])
372 self.vapi.punt_socket_deregister(cfg["vpp"])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100373
374 def test_punt_socket_traffic_multi_ports_single_socket(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200375 """Punt socket traffic multi ports and single socket"""
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100376
Neale Ranns50f0ac02019-05-15 02:13:37 -0700377 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
378 punt_l4 = mk_vpp_cfg4()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100379
380 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700381 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100382 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700383 pkts = []
384 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100385 # choose port from port list
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200386 pkt = (
387 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
388 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
389 / UDP(sport=9876, dport=port)
390 / Raw(b"\xa5" * 100)
391 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700392 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100393
394 #
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100395 # configure a punt socket
396 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200397 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100398 for p in self.ports:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200399 self.vapi.punt_socket_register(
400 set_port(punt_l4, p), "%s/socket_multi" % self.tempdir
401 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700402 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100403 self.assertEqual(len(punts), len(self.ports))
404
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100405 #
406 # expect punt socket and no packets on pg0
407 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700408 self.send_and_assert_no_replies(self.pg0, pkts)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100409 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700410 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100411
412 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700413 self.verify_udp_pkts(rx, self.nr_packets, p)
414 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
415 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100416 self.assertEqual(len(punts), 0)
417
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100418
419class TestIP6PuntSocket(TestPuntSocket):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200420 """Punt Socket for IPv6 UDP"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100421
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800422 @classmethod
423 def setUpClass(cls):
424 super(TestIP6PuntSocket, cls).setUpClass()
425
426 @classmethod
427 def tearDownClass(cls):
428 super(TestIP6PuntSocket, cls).tearDownClass()
429
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100430 def setUp(self):
431 super(TestIP6PuntSocket, self).setUp()
432
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100433 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100434 i.config_ip6()
435 i.resolve_ndp()
436
437 def tearDown(self):
438 super(TestIP6PuntSocket, self).tearDown()
439 for i in self.pg_interfaces:
440 i.unconfig_ip6()
441 i.admin_down()
442
443 def test_punt_socket_dump(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200444 """Punt socket registration"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100445
Neale Ranns50f0ac02019-05-15 02:13:37 -0700446 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
447 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
448 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
449 #
450 # configure a punt socket
451 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200452 punt_l4 = {"type": pt_l4, "punt": {"l4": {"af": af_ip6, "protocol": udp_proto}}}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700453
454 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100455 self.assertEqual(len(punts), 0)
456
457 #
458 # configure a punt socket
459 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200460 self.vapi.punt_socket_register(
461 set_port(punt_l4, 1111), "%s/socket_1111" % self.tempdir
462 )
463 self.vapi.punt_socket_register(
464 set_port(punt_l4, 2222), "%s/socket_2222" % self.tempdir
465 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700466 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100467 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700468 self.verify_port(set_port(punt_l4, 1111), punts[0])
469 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100470
471 #
472 # deregister a punt socket
473 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700474 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
475 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100476 self.assertEqual(len(punts), 1)
477
478 #
479 # configure a punt socket again
480 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200481 self.vapi.punt_socket_register(
482 set_port(punt_l4, 1111), "%s/socket_1111" % self.tempdir
483 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700484 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100485 self.assertEqual(len(punts), 2)
486
487 #
488 # deregister all punt socket
489 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700490 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)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100494 self.assertEqual(len(punts), 0)
495
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100496 def test_punt_socket_traffic_single_port_single_socket(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200497 """Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100498
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100499 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700500 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
503 punt_l4 = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200504 "type": pt_l4,
505 "punt": {
506 "l4": {
507 "af": af_ip6,
508 "protocol": udp_proto,
509 "port": port,
Neale Ranns50f0ac02019-05-15 02:13:37 -0700510 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200511 },
Neale Ranns50f0ac02019-05-15 02:13:37 -0700512 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100513
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200514 p = (
515 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
516 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6)
517 / inet6.UDP(sport=9876, dport=port)
518 / Raw(b"\xa5" * 100)
519 )
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100520
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100521 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100522
Neale Ranns50f0ac02019-05-15 02:13:37 -0700523 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100524 self.assertEqual(len(punts), 0)
525
526 #
527 # expect ICMPv6 - destination unreachable for all packets
528 #
529 self.vapi.cli("clear trace")
530 self.pg0.add_stream(pkts)
531 self.pg_enable_capture(self.pg_interfaces)
532 self.pg_start()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100533 # FIXME - when punt socket deregister is implemented
534 # rx = self.pg0.get_capture(self.nr_packets)
535 # for p in rx:
536 # self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
537 # self.assertEqual(int(p[ICMPv6DestUnreach].code),4) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100538
539 #
540 # configure a punt socket
541 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200542 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200543 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700544 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100545 self.assertEqual(len(punts), 1)
546
547 #
548 # expect punt socket and no packets on pg0
549 #
550 self.vapi.cli("clear errors")
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100551 self.vapi.cli("clear trace")
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100552 self.pg0.add_stream(pkts)
553 self.pg_enable_capture(self.pg_interfaces)
554 self.pg_start()
555 self.pg0.get_capture(0)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100556 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700557 rx = self.socket_client_close()
558 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100559
560 #
561 # remove punt socket. expect ICMP - dest. unreachable for all packets
562 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700563 self.vapi.punt_socket_deregister(punt_l4)
564 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100565 self.assertEqual(len(punts), 0)
566 self.pg0.add_stream(pkts)
567 self.pg_enable_capture(self.pg_interfaces)
568 self.pg_start()
569 # FIXME - when punt socket deregister is implemented
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100570 # self.pg0.get_capture(nr_packets)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100571
Neale Ranns50f0ac02019-05-15 02:13:37 -0700572 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200573 """Punt socket traffic multi ports and multi sockets"""
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100574
Neale Ranns50f0ac02019-05-15 02:13:37 -0700575 punt_l4 = mk_vpp_cfg6()
576
577 # configuration for each UDP port
578 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100579
580 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700581 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100582 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700583 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100584 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700585 cfgs[port] = {}
586
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200587 pkt = (
588 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
589 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6)
590 / UDP(sport=9876, dport=port)
591 / Raw(b"\xa5" * 100)
592 )
593 cfgs[port]["pkts"] = pkt * self.nr_packets
594 cfgs[port]["port"] = port
595 cfgs[port]["vpp"] = copy.deepcopy(set_port(punt_l4, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700596
597 # configure punt sockets
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200598 cfgs[port]["sock"] = self.socket_client_create(
599 "%s/socket_%d" % (self.tempdir, port)
600 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700601 self.vapi.punt_socket_register(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200602 cfgs[port]["vpp"], "%s/socket_%d" % (self.tempdir, port)
603 )
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100604
605 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700606 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100607 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700608 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200609 self.send_and_assert_no_replies(self.pg0, cfg["pkts"])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100610
611 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700612 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100613 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700614 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200615 rx = cfg["sock"].close()
616 self.verify_udp_pkts(rx, len(cfg["pkts"]), cfg["port"])
617 self.vapi.punt_socket_deregister(cfg["vpp"])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100618
619 def test_punt_socket_traffic_multi_ports_single_socket(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200620 """Punt socket traffic multi ports and single socket"""
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100621
Neale Ranns50f0ac02019-05-15 02:13:37 -0700622 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
625 punt_l4 = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200626 "type": pt_l4,
627 "punt": {
628 "l4": {
629 "af": af_ip6,
630 "protocol": udp_proto,
Neale Ranns50f0ac02019-05-15 02:13:37 -0700631 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200632 },
Neale Ranns50f0ac02019-05-15 02:13:37 -0700633 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100634
635 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700636 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100637 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700638 pkts = []
639 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100640 # choose port from port list
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200641 pkt = (
642 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
643 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6)
644 / UDP(sport=9876, dport=port)
645 / Raw(b"\xa5" * 100)
646 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700647 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100648
649 #
650 # no punt socket
651 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700652 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100653 self.assertEqual(len(punts), 0)
654
655 #
656 # configure a punt socket
657 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200658 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100659 for p in self.ports:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200660 self.vapi.punt_socket_register(
661 set_port(punt_l4, p), "%s/socket_multi" % self.tempdir
662 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700663 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100664 self.assertEqual(len(punts), len(self.ports))
665
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100666 #
667 # expect punt socket and no packets on pg0
668 #
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)
673 self.pg_start()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +0000674 # give a chance to punt socket to collect all packets
675 self.sleep(1)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100676 self.pg0.get_capture(0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700677 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100678
679 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700680 self.verify_udp_pkts(rx, self.nr_packets, p)
681 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
682 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100683 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100684
Neale Ranns76b56492018-09-28 15:16:14 +0000685
Neale Ranns50f0ac02019-05-15 02:13:37 -0700686class TestExceptionPuntSocket(TestPuntSocket):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200687 """Punt Socket for Exceptions"""
Neale Ranns50f0ac02019-05-15 02:13:37 -0700688
689 @classmethod
690 def setUpClass(cls):
691 super(TestExceptionPuntSocket, cls).setUpClass()
692
693 @classmethod
694 def tearDownClass(cls):
695 super(TestExceptionPuntSocket, cls).tearDownClass()
696
697 def setUp(self):
698 super(TestExceptionPuntSocket, self).setUp()
699
Neale Ranns12989b52019-09-26 16:20:19 +0000700 self.create_pg_interfaces(range(2))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700701 for i in self.pg_interfaces:
702 i.config_ip4()
703 i.resolve_arp()
704
705 def tearDown(self):
706 super(TestExceptionPuntSocket, self).tearDown()
707 for i in self.pg_interfaces:
708 i.unconfig_ip4()
709 i.admin_down()
710
711 def test_registration(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200712 """Punt socket registration/deregistration"""
Neale Ranns50f0ac02019-05-15 02:13:37 -0700713
714 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
715
716 punts = self.vapi.punt_socket_dump(type=pt_ex)
717 self.assertEqual(len(punts), 0)
718
719 #
720 # configure a punt socket
721 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200722 punt_ex = {"type": pt_ex, "punt": {"exception": {}}}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700723
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200724 self.vapi.punt_socket_register(
725 set_reason(punt_ex, 1), "%s/socket_punt_1" % self.tempdir
726 )
727 self.vapi.punt_socket_register(
728 set_reason(punt_ex, 2), "%s/socket_punt_2" % self.tempdir
729 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700730 punts = self.vapi.punt_socket_dump(type=pt_ex)
731 self.assertEqual(len(punts), 2)
732 self.verify_exception(set_reason(punt_ex, 1), punts[0])
733 self.verify_exception(set_reason(punt_ex, 2), punts[1])
734
735 #
736 # deregister a punt socket
737 #
738 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
739 punts = self.vapi.punt_socket_dump(type=pt_ex)
740 self.assertEqual(len(punts), 1)
741
742 #
743 # configure a punt socket again
744 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200745 self.vapi.punt_socket_register(
746 set_reason(punt_ex, 1), "%s/socket_punt_1" % self.tempdir
747 )
748 self.vapi.punt_socket_register(
749 set_reason(punt_ex, 3), "%s/socket_punt_3" % self.tempdir
750 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700751 punts = self.vapi.punt_socket_dump(type=pt_ex)
752 self.assertEqual(len(punts), 3)
753
754 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
755
756 #
757 # deregister all punt socket
758 #
759 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
760 self.vapi.punt_socket_deregister(set_reason(punt_ex, 2))
761 self.vapi.punt_socket_deregister(set_reason(punt_ex, 3))
762 punts = self.vapi.punt_socket_dump(type=pt_ex)
763 self.assertEqual(len(punts), 0)
764
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700765 def verify_esp_pkts(self, rxs, n_sent, spi, has_udp):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700766 self.assertEqual(len(rxs), n_sent)
767 for rx in rxs:
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700768 self.assertTrue(rx.haslayer(IP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700769 self.assertTrue(rx.haslayer(ESP))
770 self.assertEqual(rx[ESP].spi, spi)
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700771 if has_udp:
772 self.assertTrue(rx.haslayer(UDP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700773
774 def test_traffic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200775 """Punt socket traffic"""
Neale Ranns50f0ac02019-05-15 02:13:37 -0700776
777 port = self.ports[0]
778 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200779 punt_ex = {"type": pt_ex, "punt": {"exception": {}}}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700780
781 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700782 # we're dealing with IPSec tunnels punting for no-such-tunnel
Filip Tehlar4362baa2020-04-02 13:13:39 +0000783 # (SPI=0 goes to ikev2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700784 #
785 cfgs = dict()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200786 cfgs["ipsec4-no-such-tunnel"] = {"spi": 99, "udp": False, "itf": self.pg0}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700787
788 #
789 # find the VPP ID for these punt exception reasin
790 #
791 rs = self.vapi.punt_reason_dump()
792 for key in cfgs:
793 for r in rs:
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100794 print(r.reason.name)
795 print(key)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700796 if r.reason.name == key:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200797 cfgs[key]["id"] = r.reason.id
798 cfgs[key]["vpp"] = copy.deepcopy(
799 set_reason(punt_ex, cfgs[key]["id"])
800 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700801 break
802
803 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700804 # configure punt sockets
Neale Ranns50f0ac02019-05-15 02:13:37 -0700805 #
806 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200807 cfg["sock"] = self.socket_client_create(
808 "%s/socket_%d" % (self.tempdir, cfg["id"])
809 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700810 self.vapi.punt_socket_register(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200811 cfg["vpp"], "%s/socket_%d" % (self.tempdir, cfg["id"])
812 )
Neale Ranns50f0ac02019-05-15 02:13:37 -0700813
814 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700815 # create packet streams for 'no-such-tunnel' exception
816 #
817 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200818 pkt = Ether(src=cfg["itf"].remote_mac, dst=cfg["itf"].local_mac) / IP(
819 src=cfg["itf"].remote_ip4, dst=cfg["itf"].local_ip4
820 )
821 if cfg["udp"]:
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700822 pkt = pkt / UDP(sport=666, dport=4500)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200823 pkt = pkt / ESP(spi=cfg["spi"], seq=3) / Raw(b"\xa5" * 100)
824 cfg["pkts"] = [pkt]
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700825
826 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700827 # send packets for each SPI we expect to be punted
828 #
829 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200830 self.send_and_assert_no_replies(cfg["itf"], cfg["pkts"])
Neale Ranns50f0ac02019-05-15 02:13:37 -0700831
832 #
833 # verify the punted packets arrived on the associated socket
834 #
835 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200836 rx = cfg["sock"].close()
837 self.verify_esp_pkts(rx, len(cfg["pkts"]), cfg["spi"], cfg["udp"])
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700838
839 #
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000840 # add some tunnels, make sure it still punts
841 #
Neale Rannsa9e27742020-12-23 16:22:28 +0000842 tun = VppIpsecInterface(self).add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200843 sa_in = VppIpsecSA(
844 self,
845 11,
846 11,
847 (VppEnum.vl_api_ipsec_integ_alg_t.IPSEC_API_INTEG_ALG_SHA1_96),
848 b"0123456701234567",
849 (VppEnum.vl_api_ipsec_crypto_alg_t.IPSEC_API_CRYPTO_ALG_AES_CBC_128),
850 b"0123456701234567",
851 50,
852 self.pg0.local_ip4,
853 self.pg0.remote_ip4,
854 ).add_vpp_config()
855 sa_out = VppIpsecSA(
856 self,
857 22,
858 22,
859 (VppEnum.vl_api_ipsec_integ_alg_t.IPSEC_API_INTEG_ALG_SHA1_96),
860 b"0123456701234567",
861 (VppEnum.vl_api_ipsec_crypto_alg_t.IPSEC_API_CRYPTO_ALG_AES_CBC_128),
862 b"0123456701234567",
863 50,
864 self.pg0.local_ip4,
865 self.pg0.remote_ip4,
866 ).add_vpp_config()
867 protect = VppIpsecTunProtect(self, tun, sa_out, [sa_in]).add_vpp_config()
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000868
869 #
870 # send packets for each SPI we expect to be punted
871 #
872 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200873 self.send_and_assert_no_replies(cfg["itf"], cfg["pkts"])
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000874
875 #
876 # verify the punted packets arrived on the associated socket
877 #
878 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200879 rx = cfg["sock"].close()
880 self.verify_esp_pkts(rx, len(cfg["pkts"]), cfg["spi"], cfg["udp"])
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000881 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700882 # socket deregister
883 #
884 for cfg in cfgs.values():
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200885 self.vapi.punt_socket_deregister(cfg["vpp"])
Neale Ranns50f0ac02019-05-15 02:13:37 -0700886
887
Neale Rannsb538dd82019-05-21 06:54:54 -0700888class TestIpProtoPuntSocket(TestPuntSocket):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200889 """Punt Socket for IP packets"""
Neale Rannsb538dd82019-05-21 06:54:54 -0700890
891 @classmethod
892 def setUpClass(cls):
893 super(TestIpProtoPuntSocket, cls).setUpClass()
894
895 @classmethod
896 def tearDownClass(cls):
897 super(TestIpProtoPuntSocket, cls).tearDownClass()
898
899 def setUp(self):
900 super(TestIpProtoPuntSocket, self).setUp()
901
902 for i in self.pg_interfaces:
903 i.config_ip4()
904 i.resolve_arp()
905
906 def tearDown(self):
907 super(TestIpProtoPuntSocket, self).tearDown()
908 for i in self.pg_interfaces:
909 i.unconfig_ip4()
910 i.admin_down()
911
912 def test_registration(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200913 """Punt socket registration/deregistration"""
Neale Rannsb538dd82019-05-21 06:54:54 -0700914
915 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
916 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
917 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
918 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
919
920 punts = self.vapi.punt_socket_dump(type=pt_ip)
921 self.assertEqual(len(punts), 0)
922
923 #
924 # configure a punt socket
925 #
926 punt_ospf = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200927 "type": pt_ip,
928 "punt": {"ip_proto": {"af": af_ip4, "protocol": proto_ospf}},
Neale Rannsb538dd82019-05-21 06:54:54 -0700929 }
930 punt_eigrp = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200931 "type": pt_ip,
932 "punt": {"ip_proto": {"af": af_ip4, "protocol": proto_eigrp}},
Neale Rannsb538dd82019-05-21 06:54:54 -0700933 }
934
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200935 self.vapi.punt_socket_register(punt_ospf, "%s/socket_punt_1" % self.tempdir)
936 self.vapi.punt_socket_register(punt_eigrp, "%s/socket_punt_2" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700937 self.logger.info(self.vapi.cli("sh punt sock reg ip"))
938 punts = self.vapi.punt_socket_dump(type=pt_ip)
939 self.assertEqual(len(punts), 2)
940 self.verify_ip_proto(punt_ospf, punts[0])
941 self.verify_ip_proto(punt_eigrp, punts[1])
942
943 #
944 # deregister a punt socket
945 #
946 self.vapi.punt_socket_deregister(punt_ospf)
947 punts = self.vapi.punt_socket_dump(type=pt_ip)
948 self.assertEqual(len(punts), 1)
949
950 #
951 # configure a punt socket again
952 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200953 self.vapi.punt_socket_register(punt_ospf, "%s/socket_punt_3" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700954 punts = self.vapi.punt_socket_dump(type=pt_ip)
955 self.assertEqual(len(punts), 2)
956
957 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
958
959 #
960 # deregister all punt socket
961 #
962 self.vapi.punt_socket_deregister(punt_eigrp)
963 self.vapi.punt_socket_deregister(punt_ospf)
964 punts = self.vapi.punt_socket_dump(type=pt_ip)
965 self.assertEqual(len(punts), 0)
966
967 def verify_ospf_pkts(self, rxs, n_sent):
968 self.assertEqual(len(rxs), n_sent)
969 for rx in rxs:
970 self.assertTrue(rx.haslayer(OSPF_Hdr))
971
972 def test_traffic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200973 """Punt socket traffic"""
Neale Rannsb538dd82019-05-21 06:54:54 -0700974
975 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
976 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
977 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
978
979 #
980 # configure a punt socket to capture OSPF packets
981 #
982 punt_ospf = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200983 "type": pt_ip,
984 "punt": {"ip_proto": {"af": af_ip4, "protocol": proto_ospf}},
Neale Rannsb538dd82019-05-21 06:54:54 -0700985 }
986
987 #
988 # create packet streams and configure a punt sockets
989 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200990 pkt = (
991 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
992 / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
993 / OSPF_Hdr()
994 / OSPFv3_Hello()
995 )
Neale Rannsb538dd82019-05-21 06:54:54 -0700996 pkts = pkt * 7
997
Ole Troan9cd8f332019-10-18 15:57:56 +0200998 sock = self.socket_client_create("%s/socket_1" % self.tempdir)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200999 self.vapi.punt_socket_register(punt_ospf, "%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001000
1001 #
1002 # send packets for each SPI we expect to be punted
1003 #
1004 self.send_and_assert_no_replies(self.pg0, pkts)
1005
1006 #
1007 # verify the punted packets arrived on the associated socket
1008 #
1009 rx = sock.close()
1010 self.verify_ospf_pkts(rx, len(pkts))
1011 self.vapi.punt_socket_deregister(punt_ospf)
1012
1013
Andrew Yourtchenkofeb77422023-03-17 01:47:58 +00001014class TestDot1QPuntSocket(TestPuntSocket):
1015 """Punt Socket for 802.1Q (dot1q)"""
1016
1017 def setUp(self):
1018 super(TestDot1QPuntSocket, self).setUp()
1019
1020 for i in self.pg_interfaces:
1021 i.admin_up()
1022 i.config_ip4()
1023 i.resolve_arp()
1024
1025 def tearDown(self):
1026 super(TestDot1QPuntSocket, self).tearDown()
1027 for i in self.pg_interfaces:
1028 i.unconfig_ip4()
1029 i.admin_down()
1030
1031 def test_dot1q_header_punt(self):
1032 """Punt socket traffic with Dot1q header"""
1033
1034 port = self.ports[0]
1035 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
1036 punt_l4 = set_port(mk_vpp_cfg4(), port)
1037
1038 # VLAN ID
1039 vlan_id = 100
1040
1041 # Create a subinterface with the VLAN ID
1042 subif = VppDot1QSubint(self, self.pg0, vlan_id)
1043 subif.admin_up()
1044 subif.config_ip4()
1045
1046 # Configure an IP address on the subinterface
1047 subif_ip4 = subif.local_ip4
1048
1049 p = (
1050 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1051 / Dot1Q(vlan=vlan_id)
1052 / IP(src=self.pg0.remote_ip4, dst=subif_ip4)
1053 / UDP(sport=9876, dport=port)
1054 / Raw(b"\xa5" * 100)
1055 )
1056
1057 pkts = p * self.nr_packets
1058
1059 # Expect ICMP - port unreachable for all packets
1060 rx = self.send_and_expect_some(self.pg0, pkts, self.pg0)
1061
1062 for p in rx:
1063 self.assertEqual(int(p[IP].proto), 1) # ICMP
1064 self.assertEqual(int(p[ICMP].code), 3) # unreachable
1065
1066 # Configure a punt socket
1067 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
1068 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" % (self.tempdir, port))
1069 punts = self.vapi.punt_socket_dump(type=pt_l4)
1070 self.assertEqual(len(punts), 1)
1071
1072 # Expect punt socket and no packets on pg0
1073 self.send_and_assert_no_replies(self.pg0, pkts)
1074 rx = self.socket_client_close()
1075 self.logger.info("RXPKT")
1076 self.logger.info(rx)
1077 self.verify_udp_pkts(rx, len(pkts), port)
1078 for pkt in rx:
1079 self.assertEqual(pkt[Ether].src, self.pg0.remote_mac)
1080 self.assertEqual(pkt[Ether].dst, self.pg0.local_mac)
1081 self.assertEqual(pkt[Dot1Q].vlan, 100)
1082
1083 # Remove punt socket. Expect ICMP - port unreachable for all packets
1084 self.vapi.punt_socket_deregister(punt_l4)
1085 punts = self.vapi.punt_socket_dump(type=pt_l4)
1086 self.assertEqual(len(punts), 0)
1087
1088 rx = self.send_and_expect_some(self.pg0, pkts, self.pg0)
1089 for p in rx:
1090 self.assertEqual(int(p[IP].proto), 1) # ICMP
1091 self.assertEqual(int(p[ICMP].code), 3) # unreachable
1092
1093
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001094@tag_fixme_vpp_workers
Neale Ranns76b56492018-09-28 15:16:14 +00001095class TestPunt(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001096 """Exception Punt Test Case"""
Neale Ranns76b56492018-09-28 15:16:14 +00001097
1098 @classmethod
1099 def setUpClass(cls):
1100 super(TestPunt, cls).setUpClass()
1101
1102 @classmethod
1103 def tearDownClass(cls):
1104 super(TestPunt, cls).tearDownClass()
1105
1106 def setUp(self):
1107 super(TestPunt, self).setUp()
1108
1109 self.create_pg_interfaces(range(4))
1110
1111 for i in self.pg_interfaces:
1112 i.admin_up()
1113 i.config_ip4()
1114 i.resolve_arp()
1115 i.config_ip6()
1116 i.resolve_ndp()
1117
1118 def tearDown(self):
1119 for i in self.pg_interfaces:
1120 i.unconfig_ip4()
1121 i.unconfig_ip6()
Neale Ranns76b56492018-09-28 15:16:14 +00001122 i.admin_down()
1123 super(TestPunt, self).tearDown()
1124
1125 def test_punt(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001126 """Exception Path testing"""
Neale Ranns76b56492018-09-28 15:16:14 +00001127
1128 #
Neale Ranns719beb72019-07-10 07:10:25 +00001129 # dump the punt registered reasons
1130 # search for a few we know should be there
1131 #
1132 rs = self.vapi.punt_reason_dump()
1133
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001134 reasons = [
1135 "ipsec6-no-such-tunnel",
1136 "ipsec4-no-such-tunnel",
1137 "ipsec4-spi-o-udp-0",
1138 ]
Neale Ranns719beb72019-07-10 07:10:25 +00001139
1140 for reason in reasons:
1141 found = False
1142 for r in rs:
1143 if r.reason.name == reason:
1144 found = True
1145 break
1146 self.assertTrue(found)
1147
1148 #
Neale Ranns76b56492018-09-28 15:16:14 +00001149 # Using the test CLI we will hook in a exception path to
1150 # send ACL deny packets out of pg0 and pg1.
1151 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1152 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001153 ip_1_1_1_2 = VppIpRoute(
1154 self,
1155 "1.1.1.2",
1156 32,
1157 [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)],
1158 )
Neale Ranns76b56492018-09-28 15:16:14 +00001159 ip_1_1_1_2.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001160 ip_1_2 = VppIpRoute(
1161 self,
1162 "1::2",
1163 128,
1164 [
1165 VppRoutePath(
1166 self.pg3.remote_ip6,
1167 self.pg3.sw_if_index,
1168 proto=DpoProto.DPO_PROTO_IP6,
1169 )
1170 ],
1171 )
Neale Ranns76b56492018-09-28 15:16:14 +00001172 ip_1_2.add_vpp_config()
1173
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001174 p4 = (
1175 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
1176 / IP(src="1.1.1.1", dst="1.1.1.2")
1177 / UDP(sport=1234, dport=1234)
1178 / Raw(b"\xa5" * 100)
1179 )
1180 p6 = (
1181 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
1182 / IPv6(src="1::1", dst="1::2")
1183 / UDP(sport=1234, dport=1234)
1184 / Raw(b"\xa5" * 100)
1185 )
1186 self.send_and_expect(self.pg2, p4 * 1, self.pg3)
1187 self.send_and_expect(self.pg2, p6 * 1, self.pg3)
Neale Ranns76b56492018-09-28 15:16:14 +00001188
1189 #
1190 # apply the punting features
1191 #
1192 self.vapi.cli("test punt pg2")
1193
1194 #
Neale Ranns719beb72019-07-10 07:10:25 +00001195 # dump the punt reasons to learn the IDs assigned
1196 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001197 rs = self.vapi.punt_reason_dump(reason={"name": "reason-v4"})
Neale Ranns719beb72019-07-10 07:10:25 +00001198 r4 = rs[0].reason.id
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001199 rs = self.vapi.punt_reason_dump(reason={"name": "reason-v6"})
Neale Ranns719beb72019-07-10 07:10:25 +00001200 r6 = rs[0].reason.id
1201
1202 #
Neale Ranns76b56492018-09-28 15:16:14 +00001203 # pkts now dropped
1204 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001205 self.send_and_assert_no_replies(self.pg2, p4 * NUM_PKTS)
1206 self.send_and_assert_no_replies(self.pg2, p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001207
1208 #
1209 # Check state:
1210 # 1 - node error counters
1211 # 2 - per-reason counters
1212 # 2, 3 are the index of the assigned punt reason
1213 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001214 stats = self.statistics.get_err_counter("/err/punt-dispatch/No registrations")
1215 self.assertEqual(stats, 2 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001216
1217 stats = self.statistics.get_counter("/net/punt")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001218 self.assertEqual(stats[0][r4]["packets"], NUM_PKTS)
1219 self.assertEqual(stats[0][r6]["packets"], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001220
1221 #
1222 # use the test CLI to test a client that punts exception
1223 # packets out of pg0
1224 #
1225 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1226 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1227
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001228 rx4s = self.send_and_expect(self.pg2, p4 * NUM_PKTS, self.pg0)
1229 rx6s = self.send_and_expect(self.pg2, p6 * NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001230
1231 #
1232 # check the packets come out IP unmodified but destined to pg0 host
1233 #
1234 for rx in rx4s:
1235 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1236 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1237 self.assertEqual(p4[IP].dst, rx[IP].dst)
1238 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1239 for rx in rx6s:
1240 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1241 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1242 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1243 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1244
1245 stats = self.statistics.get_counter("/net/punt")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001246 self.assertEqual(stats[0][r4]["packets"], 2 * NUM_PKTS)
1247 self.assertEqual(stats[0][r6]["packets"], 2 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001248
1249 #
1250 # add another registration for the same reason to send packets
1251 # out of pg1
1252 #
1253 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1254 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1255
1256 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001257 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001258 self.pg_enable_capture(self.pg_interfaces)
1259 self.pg_start()
1260
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001261 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001262 for rx in rxd:
1263 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1264 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1265 self.assertEqual(p4[IP].dst, rx[IP].dst)
1266 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001267 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001268 for rx in rxd:
1269 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1270 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1271 self.assertEqual(p4[IP].dst, rx[IP].dst)
1272 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1273
1274 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001275 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001276 self.pg_enable_capture(self.pg_interfaces)
1277 self.pg_start()
1278
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001279 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001280 for rx in rxd:
1281 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1282 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1283 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1284 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001285 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001286 for rx in rxd:
1287 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1288 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1289 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1290 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1291
1292 stats = self.statistics.get_counter("/net/punt")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001293 self.assertEqual(stats[0][r4]["packets"], 3 * NUM_PKTS)
1294 self.assertEqual(stats[0][r6]["packets"], 3 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001295
1296 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1297 self.logger.info(self.vapi.cli("show punt client"))
1298 self.logger.info(self.vapi.cli("show punt reason"))
1299 self.logger.info(self.vapi.cli("show punt stats"))
1300 self.logger.info(self.vapi.cli("show punt db"))
1301
Neale Ranns76b56492018-09-28 15:16:14 +00001302
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001303if __name__ == "__main__":
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001304 unittest.main(testRunner=VppTestRunner)