blob: 3471a3f7dd59c041cbab58b6f42ff40ffe27bb94 [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 binascii
3import random
4import socket
Pavel Kotuceke88865d2018-11-28 07:42:11 +01005import os
Pavel Kotucek9edb83a2018-12-11 16:57:25 +01006import threading
7import struct
Neale Ranns50f0ac02019-05-15 02:13:37 -07008import copy
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +01009import fcntl
10import time
11
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010012from struct import unpack, unpack_from
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -080013
14try:
15 import unittest2 as unittest
16except ImportError:
17 import unittest
18
Pavel Kotuceke88865d2018-11-28 07:42:11 +010019from util import ppp, ppc
20from re import compile
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070021import scapy.compat
Pavel Kotuceke88865d2018-11-28 07:42:11 +010022from scapy.packet import Raw
23from scapy.layers.l2 import Ether
24from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns50f0ac02019-05-15 02:13:37 -070025from scapy.layers.ipsec import ESP
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -080026import scapy.layers.inet6 as inet6
Pavel Kotuceke88865d2018-11-28 07:42:11 +010027from scapy.layers.inet6 import IPv6, ICMPv6DestUnreach
Neale Rannsb538dd82019-05-21 06:54:54 -070028from scapy.contrib.ospf import OSPF_Hdr, OSPFv3_Hello
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +000029from framework import tag_fixme_vpp_workers
Pavel Kotuceke88865d2018-11-28 07:42:11 +010030from framework import VppTestCase, VppTestRunner
31
Neale Ranns76b56492018-09-28 15:16:14 +000032from vpp_ip import DpoProto
33from vpp_ip_route import VppIpRoute, VppRoutePath
Neale Rannsa9e27742020-12-23 16:22:28 +000034from vpp_ipsec import VppIpsecSA, VppIpsecTunProtect, VppIpsecInterface
Neale Ranns50f0ac02019-05-15 02:13:37 -070035from vpp_papi import VppEnum
Neale Ranns76b56492018-09-28 15:16:14 +000036
Paul Vinciguerra4271c972019-05-14 13:25:49 -040037NUM_PKTS = 67
38
Pavel Kotuceke88865d2018-11-28 07:42:11 +010039
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010040class serverSocketThread(threading.Thread):
41 """ Socket server thread"""
42
Neale Ranns50f0ac02019-05-15 02:13:37 -070043 def __init__(self, threadID, sockName):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010044 threading.Thread.__init__(self)
45 self.threadID = threadID
46 self.sockName = sockName
47 self.sock = None
Neale Ranns50f0ac02019-05-15 02:13:37 -070048 self.rx_pkts = []
Dave Wallacec44402f2021-05-07 21:40:54 -040049 self.stop_running = False
Neale Ranns50f0ac02019-05-15 02:13:37 -070050
51 def rx_packets(self):
52 # Wait for some packets on socket
Dave Wallacec44402f2021-05-07 21:40:54 -040053 while True:
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010054 try:
55 data = self.sock.recv(65536)
Neale Ranns50f0ac02019-05-15 02:13:37 -070056
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010057 # punt socket metadata
58 # packet_desc = data[0:8]
Neale Ranns50f0ac02019-05-15 02:13:37 -070059
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010060 # Ethernet
61 self.rx_pkts.append(Ether(data[8:]))
62 except IOError as e:
63 if e.errno == 11:
Dave Wallacec44402f2021-05-07 21:40:54 -040064 # nothing to receive, stop running or sleep a little
65 if self.stop_running:
66 break
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010067 time.sleep(0.1)
68 pass
69 else:
70 raise
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010071
72 def run(self):
73 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
74 try:
75 os.unlink(self.sockName)
76 except:
77 pass
Neale Ranns50f0ac02019-05-15 02:13:37 -070078 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
79 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010080 fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010081 self.sock.bind(self.sockName)
82
Neale Ranns50f0ac02019-05-15 02:13:37 -070083 self.rx_packets()
84
85 def close(self):
Dave Wallacec44402f2021-05-07 21:40:54 -040086 self.stop_running = True
Dave Wallacef4d338f2021-05-06 15:59:59 -040087 threading.Thread.join(self)
Dave Wallacec44402f2021-05-07 21:40:54 -040088 self.sock.close()
Neale Ranns50f0ac02019-05-15 02:13:37 -070089 return self.rx_pkts
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010090
91
Pavel Kotuceke88865d2018-11-28 07:42:11 +010092class TestPuntSocket(VppTestCase):
93 """ Punt Socket """
94
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010095 ports = [1111, 2222, 3333, 4444]
96 sock_servers = list()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +000097 # FIXME: nr_packets > 3 results in failure
98 # nr_packets = 3 makes the test unstable
99 nr_packets = 2
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100100
101 @classmethod
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800102 def setUpClass(cls):
103 super(TestPuntSocket, cls).setUpClass()
104
105 @classmethod
106 def tearDownClass(cls):
107 super(TestPuntSocket, cls).tearDownClass()
108
109 @classmethod
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100110 def setUpConstants(cls):
Ole Troana45dc072018-12-21 16:04:22 +0100111 cls.extra_vpp_punt_config = [
112 "punt", "{", "socket", cls.tempdir+"/socket_punt", "}"]
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100113 super(TestPuntSocket, cls).setUpConstants()
114
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100115 def setUp(self):
116 super(TestPuntSocket, self).setUp()
117 random.seed()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100118
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100119 self.create_pg_interfaces(range(2))
120 for i in self.pg_interfaces:
121 i.admin_up()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100122
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100123 def tearDown(self):
124 del self.sock_servers[:]
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800125 super(TestPuntSocket, self).tearDown()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100126
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100127 def socket_client_create(self, sock_name, id=None):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700128 thread = serverSocketThread(id, sock_name)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100129 self.sock_servers.append(thread)
130 thread.start()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700131 return thread
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100132
133 def socket_client_close(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700134 rx_pkts = []
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100135 for thread in self.sock_servers:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700136 rx_pkts += thread.close()
137 return rx_pkts
138
139 def verify_port(self, pr, vpr):
140 self.assertEqual(vpr.punt.type, pr['type'])
141 self.assertEqual(vpr.punt.punt.l4.port,
142 pr['punt']['l4']['port'])
143 self.assertEqual(vpr.punt.punt.l4.protocol,
144 pr['punt']['l4']['protocol'])
145 self.assertEqual(vpr.punt.punt.l4.af,
146 pr['punt']['l4']['af'])
147
148 def verify_exception(self, pr, vpr):
149 self.assertEqual(vpr.punt.type, pr['type'])
150 self.assertEqual(vpr.punt.punt.exception.id,
151 pr['punt']['exception']['id'])
152
Neale Rannsb538dd82019-05-21 06:54:54 -0700153 def verify_ip_proto(self, pr, vpr):
154 self.assertEqual(vpr.punt.type, pr['type'])
155 self.assertEqual(vpr.punt.punt.ip_proto.af,
156 pr['punt']['ip_proto']['af'])
157 self.assertEqual(vpr.punt.punt.ip_proto.protocol,
158 pr['punt']['ip_proto']['protocol'])
159
Neale Ranns50f0ac02019-05-15 02:13:37 -0700160 def verify_udp_pkts(self, rxs, n_rx, port):
161 n_match = 0
162 for rx in rxs:
163 self.assertTrue(rx.haslayer(UDP))
164 if rx[UDP].dport == port:
165 n_match += 1
166 self.assertEqual(n_match, n_rx)
167
168
169def set_port(pr, port):
170 pr['punt']['l4']['port'] = port
171 return pr
172
173
174def set_reason(pr, reason):
175 pr['punt']['exception']['id'] = reason
176 return pr
177
178
179def mk_vpp_cfg4():
180 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
181 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
182 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
183 punt_l4 = {
184 'type': pt_l4,
185 'punt': {
186 'l4': {
187 'af': af_ip4,
188 'protocol': udp_proto
189 }
190 }
191 }
192 return punt_l4
193
194
195def mk_vpp_cfg6():
196 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
197 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
198 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
199 punt_l4 = {
200 'type': pt_l4,
201 'punt': {
202 'l4': {
203 'af': af_ip6,
204 'protocol': udp_proto
205 }
206 }
207 }
208 return punt_l4
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100209
210
211class TestIP4PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700212 """ Punt Socket for IPv4 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100213
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800214 @classmethod
215 def setUpClass(cls):
216 super(TestIP4PuntSocket, cls).setUpClass()
217
218 @classmethod
219 def tearDownClass(cls):
220 super(TestIP4PuntSocket, cls).tearDownClass()
221
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100222 def setUp(self):
223 super(TestIP4PuntSocket, self).setUp()
224
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100225 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100226 i.config_ip4()
227 i.resolve_arp()
228
229 def tearDown(self):
230 super(TestIP4PuntSocket, self).tearDown()
231 for i in self.pg_interfaces:
232 i.unconfig_ip4()
233 i.admin_down()
234
235 def test_punt_socket_dump(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100236 """ Punt socket registration/deregistration"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100237
Neale Ranns50f0ac02019-05-15 02:13:37 -0700238 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
239 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
240 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
241
242 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100243 self.assertEqual(len(punts), 0)
244
245 #
246 # configure a punt socket
247 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700248 punt_l4 = mk_vpp_cfg4()
249
250 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200251 "%s/socket_punt_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700252 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
Ole Troan9cd8f332019-10-18 15:57:56 +0200253 "%s/socket_punt_2222" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700254 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100255 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700256 self.verify_port(set_port(punt_l4, 1111), punts[0])
257 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100258
259 #
260 # deregister a punt socket
261 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700262 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
263 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100264 self.assertEqual(len(punts), 1)
265
266 #
267 # configure a punt socket again
268 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700269 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200270 "%s/socket_punt_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700271 self.vapi.punt_socket_register(set_port(punt_l4, 3333),
Ole Troan9cd8f332019-10-18 15:57:56 +0200272 "%s/socket_punt_3333" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700273 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100274 self.assertEqual(len(punts), 3)
275
Neale Ranns50f0ac02019-05-15 02:13:37 -0700276 self.logger.info(self.vapi.cli("sh punt sock reg"))
277
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100278 #
279 # deregister all punt socket
280 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700281 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
282 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
283 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
284 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100285 self.assertEqual(len(punts), 0)
286
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100287 def test_punt_socket_traffic_single_port_single_socket(self):
288 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100289
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100290 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700291 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
292 punt_l4 = set_port(mk_vpp_cfg4(), port)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100293
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100294 p = (Ether(src=self.pg0.remote_mac,
295 dst=self.pg0.local_mac) /
296 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100297 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200298 Raw(b'\xa5' * 100))
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100299
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100300 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100301
Neale Ranns50f0ac02019-05-15 02:13:37 -0700302 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100303 self.assertEqual(len(punts), 0)
304
305 #
306 # expect ICMP - port unreachable for all packets
307 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700308 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
309
310 for p in rx:
311 self.assertEqual(int(p[IP].proto), 1) # ICMP
312 self.assertEqual(int(p[ICMP].code), 3) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100313
314 #
315 # configure a punt socket
316 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200317 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
318 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" %
319 (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700320 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100321 self.assertEqual(len(punts), 1)
322
323 #
324 # expect punt socket and no packets on pg0
325 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700326 self.send_and_assert_no_replies(self.pg0, pkts)
327 rx = self.socket_client_close()
328 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100329
330 #
331 # remove punt socket. expect ICMP - port unreachable for all packets
332 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700333 self.vapi.punt_socket_deregister(punt_l4)
334 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100335 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100336
Neale Ranns50f0ac02019-05-15 02:13:37 -0700337 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
338 for p in rx:
339 self.assertEqual(int(p[IP].proto), 1) # ICMP
340 self.assertEqual(int(p[ICMP].code), 3) # unreachable
341
342 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100343 """ Punt socket traffic multi ports and multi sockets"""
344
Neale Ranns50f0ac02019-05-15 02:13:37 -0700345 punt_l4 = mk_vpp_cfg4()
346
347 # configuration for each UDP port
348 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100349
350 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700351 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100352 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700353 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100354 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700355 cfgs[port] = {}
356
357 pkt = (Ether(src=self.pg0.remote_mac,
358 dst=self.pg0.local_mac) /
359 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
360 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200361 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700362 cfgs[port]['pkts'] = pkt * self.nr_packets
363 cfgs[port]['port'] = port
364 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
365
366 # configure punt sockets
367 cfgs[port]['sock'] = self.socket_client_create(
Ole Troan9cd8f332019-10-18 15:57:56 +0200368 "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700369 self.vapi.punt_socket_register(
370 cfgs[port]['vpp'],
Ole Troan9cd8f332019-10-18 15:57:56 +0200371 "%s/socket_%d" % (self.tempdir, port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100372
373 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700374 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100375 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700376 for cfg in cfgs.values():
377 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100378
379 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700380 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100381 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700382 for cfg in cfgs.values():
383 rx = cfg['sock'].close()
384 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
385 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100386
387 def test_punt_socket_traffic_multi_ports_single_socket(self):
388 """ Punt socket traffic multi ports and single socket"""
389
Neale Ranns50f0ac02019-05-15 02:13:37 -0700390 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
391 punt_l4 = mk_vpp_cfg4()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100392
393 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700394 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100395 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700396 pkts = []
397 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100398 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700399 pkt = (Ether(src=self.pg0.remote_mac,
400 dst=self.pg0.local_mac) /
401 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
402 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200403 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700404 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100405
406 #
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100407 # configure a punt socket
408 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200409 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100410 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700411 self.vapi.punt_socket_register(set_port(punt_l4, p),
Ole Troan9cd8f332019-10-18 15:57:56 +0200412 "%s/socket_multi" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700413 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100414 self.assertEqual(len(punts), len(self.ports))
415
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100416 #
417 # expect punt socket and no packets on pg0
418 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700419 self.send_and_assert_no_replies(self.pg0, pkts)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100420 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700421 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100422
423 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700424 self.verify_udp_pkts(rx, self.nr_packets, p)
425 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
426 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100427 self.assertEqual(len(punts), 0)
428
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100429
430class TestIP6PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700431 """ Punt Socket for IPv6 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100432
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800433 @classmethod
434 def setUpClass(cls):
435 super(TestIP6PuntSocket, cls).setUpClass()
436
437 @classmethod
438 def tearDownClass(cls):
439 super(TestIP6PuntSocket, cls).tearDownClass()
440
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100441 def setUp(self):
442 super(TestIP6PuntSocket, self).setUp()
443
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100444 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100445 i.config_ip6()
446 i.resolve_ndp()
447
448 def tearDown(self):
449 super(TestIP6PuntSocket, self).tearDown()
450 for i in self.pg_interfaces:
451 i.unconfig_ip6()
452 i.admin_down()
453
454 def test_punt_socket_dump(self):
455 """ Punt socket registration """
456
Neale Ranns50f0ac02019-05-15 02:13:37 -0700457 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
458 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
459 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
460 #
461 # configure a punt socket
462 #
463 punt_l4 = {
464 'type': pt_l4,
465 'punt': {
466 'l4': {
467 'af': af_ip6,
468 'protocol': udp_proto
469 }
470 }
471 }
472
473 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100474 self.assertEqual(len(punts), 0)
475
476 #
477 # configure a punt socket
478 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700479 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200480 "%s/socket_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700481 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
Ole Troan9cd8f332019-10-18 15:57:56 +0200482 "%s/socket_2222" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700483 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100484 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700485 self.verify_port(set_port(punt_l4, 1111), punts[0])
486 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100487
488 #
489 # deregister a punt socket
490 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700491 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
492 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100493 self.assertEqual(len(punts), 1)
494
495 #
496 # configure a punt socket again
497 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700498 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200499 "%s/socket_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700500 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100501 self.assertEqual(len(punts), 2)
502
503 #
504 # deregister all punt socket
505 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700506 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
507 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
508 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
509 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100510 self.assertEqual(len(punts), 0)
511
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100512 def test_punt_socket_traffic_single_port_single_socket(self):
513 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100514
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100515 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700516 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
517 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
518 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
519 punt_l4 = {
520 'type': pt_l4,
521 'punt': {
522 'l4': {
523 'af': af_ip6,
524 'protocol': udp_proto,
525 'port': port,
526 }
527 }
528 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100529
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100530 p = (Ether(src=self.pg0.remote_mac,
531 dst=self.pg0.local_mac) /
532 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100533 inet6.UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200534 Raw(b'\xa5' * 100))
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100535
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100536 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100537
Neale Ranns50f0ac02019-05-15 02:13:37 -0700538 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100539 self.assertEqual(len(punts), 0)
540
541 #
542 # expect ICMPv6 - destination unreachable for all packets
543 #
544 self.vapi.cli("clear trace")
545 self.pg0.add_stream(pkts)
546 self.pg_enable_capture(self.pg_interfaces)
547 self.pg_start()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100548 # FIXME - when punt socket deregister is implemented
549 # rx = self.pg0.get_capture(self.nr_packets)
550 # for p in rx:
551 # self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
552 # self.assertEqual(int(p[ICMPv6DestUnreach].code),4) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100553
554 #
555 # configure a punt socket
556 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200557 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
558 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" %
559 (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700560 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100561 self.assertEqual(len(punts), 1)
562
563 #
564 # expect punt socket and no packets on pg0
565 #
566 self.vapi.cli("clear errors")
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100567 self.vapi.cli("clear trace")
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100568 self.pg0.add_stream(pkts)
569 self.pg_enable_capture(self.pg_interfaces)
570 self.pg_start()
571 self.pg0.get_capture(0)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100572 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700573 rx = self.socket_client_close()
574 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100575
576 #
577 # remove punt socket. expect ICMP - dest. unreachable for all packets
578 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700579 self.vapi.punt_socket_deregister(punt_l4)
580 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100581 self.assertEqual(len(punts), 0)
582 self.pg0.add_stream(pkts)
583 self.pg_enable_capture(self.pg_interfaces)
584 self.pg_start()
585 # FIXME - when punt socket deregister is implemented
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100586 # self.pg0.get_capture(nr_packets)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100587
Neale Ranns50f0ac02019-05-15 02:13:37 -0700588 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100589 """ Punt socket traffic multi ports and multi sockets"""
590
Neale Ranns50f0ac02019-05-15 02:13:37 -0700591 punt_l4 = mk_vpp_cfg6()
592
593 # configuration for each UDP port
594 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100595
596 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700597 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100598 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700599 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100600 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700601 cfgs[port] = {}
602
603 pkt = (Ether(src=self.pg0.remote_mac,
604 dst=self.pg0.local_mac) /
605 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
606 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200607 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700608 cfgs[port]['pkts'] = pkt * self.nr_packets
609 cfgs[port]['port'] = port
610 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
611
612 # configure punt sockets
613 cfgs[port]['sock'] = self.socket_client_create(
Ole Troan9cd8f332019-10-18 15:57:56 +0200614 "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700615 self.vapi.punt_socket_register(
616 cfgs[port]['vpp'],
Ole Troan9cd8f332019-10-18 15:57:56 +0200617 "%s/socket_%d" % (self.tempdir, port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100618
619 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700620 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100621 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700622 for cfg in cfgs.values():
623 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100624
625 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700626 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100627 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700628 for cfg in cfgs.values():
629 rx = cfg['sock'].close()
630 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
631 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100632
633 def test_punt_socket_traffic_multi_ports_single_socket(self):
634 """ Punt socket traffic multi ports and single socket"""
635
Neale Ranns50f0ac02019-05-15 02:13:37 -0700636 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
637 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
638 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
639 punt_l4 = {
640 'type': pt_l4,
641 'punt': {
642 'l4': {
643 'af': af_ip6,
644 'protocol': udp_proto,
645 }
646 }
647 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100648
649 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700650 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100651 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700652 pkts = []
653 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100654 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700655 pkt = (Ether(src=self.pg0.remote_mac,
656 dst=self.pg0.local_mac) /
657 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
658 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200659 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700660 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100661
662 #
663 # no punt socket
664 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700665 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100666 self.assertEqual(len(punts), 0)
667
668 #
669 # configure a punt socket
670 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200671 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100672 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700673 self.vapi.punt_socket_register(set_port(punt_l4, p),
Ole Troan9cd8f332019-10-18 15:57:56 +0200674 "%s/socket_multi" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700675 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100676 self.assertEqual(len(punts), len(self.ports))
677
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100678 #
679 # expect punt socket and no packets on pg0
680 #
681 self.vapi.cli("clear errors")
682 self.vapi.cli("clear trace")
683 self.pg0.add_stream(pkts)
684 self.pg_enable_capture(self.pg_interfaces)
685 self.pg_start()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +0000686 # give a chance to punt socket to collect all packets
687 self.sleep(1)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100688 self.pg0.get_capture(0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700689 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100690
691 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700692 self.verify_udp_pkts(rx, self.nr_packets, p)
693 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
694 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100695 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100696
Neale Ranns76b56492018-09-28 15:16:14 +0000697
Neale Ranns50f0ac02019-05-15 02:13:37 -0700698class TestExceptionPuntSocket(TestPuntSocket):
699 """ Punt Socket for Exceptions """
700
701 @classmethod
702 def setUpClass(cls):
703 super(TestExceptionPuntSocket, cls).setUpClass()
704
705 @classmethod
706 def tearDownClass(cls):
707 super(TestExceptionPuntSocket, cls).tearDownClass()
708
709 def setUp(self):
710 super(TestExceptionPuntSocket, self).setUp()
711
Neale Ranns12989b52019-09-26 16:20:19 +0000712 self.create_pg_interfaces(range(2))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700713 for i in self.pg_interfaces:
714 i.config_ip4()
715 i.resolve_arp()
716
717 def tearDown(self):
718 super(TestExceptionPuntSocket, self).tearDown()
719 for i in self.pg_interfaces:
720 i.unconfig_ip4()
721 i.admin_down()
722
723 def test_registration(self):
724 """ Punt socket registration/deregistration"""
725
726 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
727
728 punts = self.vapi.punt_socket_dump(type=pt_ex)
729 self.assertEqual(len(punts), 0)
730
731 #
732 # configure a punt socket
733 #
734 punt_ex = {
735 'type': pt_ex,
736 'punt': {
737 'exception': {}
738 }
739 }
740
741 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
Ole Troan9cd8f332019-10-18 15:57:56 +0200742 "%s/socket_punt_1" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700743 self.vapi.punt_socket_register(set_reason(punt_ex, 2),
Ole Troan9cd8f332019-10-18 15:57:56 +0200744 "%s/socket_punt_2" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700745 punts = self.vapi.punt_socket_dump(type=pt_ex)
746 self.assertEqual(len(punts), 2)
747 self.verify_exception(set_reason(punt_ex, 1), punts[0])
748 self.verify_exception(set_reason(punt_ex, 2), punts[1])
749
750 #
751 # deregister a punt socket
752 #
753 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
754 punts = self.vapi.punt_socket_dump(type=pt_ex)
755 self.assertEqual(len(punts), 1)
756
757 #
758 # configure a punt socket again
759 #
760 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
Ole Troan9cd8f332019-10-18 15:57:56 +0200761 "%s/socket_punt_1" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700762 self.vapi.punt_socket_register(set_reason(punt_ex, 3),
Ole Troan9cd8f332019-10-18 15:57:56 +0200763 "%s/socket_punt_3" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700764 punts = self.vapi.punt_socket_dump(type=pt_ex)
765 self.assertEqual(len(punts), 3)
766
767 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
768
769 #
770 # deregister all punt socket
771 #
772 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
773 self.vapi.punt_socket_deregister(set_reason(punt_ex, 2))
774 self.vapi.punt_socket_deregister(set_reason(punt_ex, 3))
775 punts = self.vapi.punt_socket_dump(type=pt_ex)
776 self.assertEqual(len(punts), 0)
777
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700778 def verify_esp_pkts(self, rxs, n_sent, spi, has_udp):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700779 self.assertEqual(len(rxs), n_sent)
780 for rx in rxs:
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700781 self.assertTrue(rx.haslayer(IP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700782 self.assertTrue(rx.haslayer(ESP))
783 self.assertEqual(rx[ESP].spi, spi)
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700784 if has_udp:
785 self.assertTrue(rx.haslayer(UDP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700786
787 def test_traffic(self):
788 """ Punt socket traffic """
789
790 port = self.ports[0]
791 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
792 punt_ex = {
793 'type': pt_ex,
794 'punt': {
795 'exception': {}
796 }
797 }
798
799 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700800 # we're dealing with IPSec tunnels punting for no-such-tunnel
Filip Tehlar4362baa2020-04-02 13:13:39 +0000801 # (SPI=0 goes to ikev2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700802 #
803 cfgs = dict()
Neale Ranns12989b52019-09-26 16:20:19 +0000804 cfgs['ipsec4-no-such-tunnel'] = {'spi': 99,
805 'udp': False,
806 'itf': self.pg0}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700807
808 #
809 # find the VPP ID for these punt exception reasin
810 #
811 rs = self.vapi.punt_reason_dump()
812 for key in cfgs:
813 for r in rs:
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100814 print(r.reason.name)
815 print(key)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700816 if r.reason.name == key:
817 cfgs[key]['id'] = r.reason.id
818 cfgs[key]['vpp'] = copy.deepcopy(
819 set_reason(punt_ex,
820 cfgs[key]['id']))
821 break
822
823 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700824 # configure punt sockets
Neale Ranns50f0ac02019-05-15 02:13:37 -0700825 #
826 for cfg in cfgs.values():
Ole Troan9cd8f332019-10-18 15:57:56 +0200827 cfg['sock'] = self.socket_client_create("%s/socket_%d" %
828 (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700829 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +0200830 cfg['vpp'], "%s/socket_%d" % (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700831
832 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700833 # create packet streams for 'no-such-tunnel' exception
834 #
835 for cfg in cfgs.values():
Neale Ranns12989b52019-09-26 16:20:19 +0000836 pkt = (Ether(src=cfg['itf'].remote_mac,
837 dst=cfg['itf'].local_mac) /
838 IP(src=cfg['itf'].remote_ip4,
839 dst=cfg['itf'].local_ip4))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700840 if (cfg['udp']):
841 pkt = pkt / UDP(sport=666, dport=4500)
842 pkt = (pkt / ESP(spi=cfg['spi'], seq=3) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200843 Raw(b'\xa5' * 100))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700844 cfg['pkts'] = [pkt]
845
846 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700847 # send packets for each SPI we expect to be punted
848 #
849 for cfg in cfgs.values():
Neale Ranns12989b52019-09-26 16:20:19 +0000850 self.send_and_assert_no_replies(cfg['itf'], cfg['pkts'])
Neale Ranns50f0ac02019-05-15 02:13:37 -0700851
852 #
853 # verify the punted packets arrived on the associated socket
854 #
855 for cfg in cfgs.values():
856 rx = cfg['sock'].close()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700857 self.verify_esp_pkts(rx, len(cfg['pkts']),
858 cfg['spi'], cfg['udp'])
859
860 #
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000861 # add some tunnels, make sure it still punts
862 #
Neale Rannsa9e27742020-12-23 16:22:28 +0000863 tun = VppIpsecInterface(self).add_vpp_config()
864 sa_in = VppIpsecSA(self, 11, 11,
865 (VppEnum.vl_api_ipsec_integ_alg_t.
866 IPSEC_API_INTEG_ALG_SHA1_96),
867 b"0123456701234567",
868 (VppEnum.vl_api_ipsec_crypto_alg_t.
869 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
870 b"0123456701234567",
871 50,
872 self.pg0.local_ip4,
873 self.pg0.remote_ip4).add_vpp_config()
874 sa_out = VppIpsecSA(self, 22, 22,
875 (VppEnum.vl_api_ipsec_integ_alg_t.
876 IPSEC_API_INTEG_ALG_SHA1_96),
877 b"0123456701234567",
878 (VppEnum.vl_api_ipsec_crypto_alg_t.
879 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
880 b"0123456701234567",
881 50,
882 self.pg0.local_ip4,
883 self.pg0.remote_ip4).add_vpp_config()
884 protect = VppIpsecTunProtect(self, tun,
885 sa_out,
886 [sa_in]).add_vpp_config()
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000887
888 #
889 # send packets for each SPI we expect to be punted
890 #
891 for cfg in cfgs.values():
892 self.send_and_assert_no_replies(cfg['itf'], cfg['pkts'])
893
894 #
895 # verify the punted packets arrived on the associated socket
896 #
897 for cfg in cfgs.values():
898 rx = cfg['sock'].close()
899 self.verify_esp_pkts(rx, len(cfg['pkts']),
900 cfg['spi'], cfg['udp'])
901 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700902 # socket deregister
903 #
904 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700905 self.vapi.punt_socket_deregister(cfg['vpp'])
906
907
Neale Rannsb538dd82019-05-21 06:54:54 -0700908class TestIpProtoPuntSocket(TestPuntSocket):
909 """ Punt Socket for IP packets """
910
911 @classmethod
912 def setUpClass(cls):
913 super(TestIpProtoPuntSocket, cls).setUpClass()
914
915 @classmethod
916 def tearDownClass(cls):
917 super(TestIpProtoPuntSocket, cls).tearDownClass()
918
919 def setUp(self):
920 super(TestIpProtoPuntSocket, self).setUp()
921
922 for i in self.pg_interfaces:
923 i.config_ip4()
924 i.resolve_arp()
925
926 def tearDown(self):
927 super(TestIpProtoPuntSocket, self).tearDown()
928 for i in self.pg_interfaces:
929 i.unconfig_ip4()
930 i.admin_down()
931
932 def test_registration(self):
933 """ Punt socket registration/deregistration"""
934
935 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
936 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
937 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
938 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
939
940 punts = self.vapi.punt_socket_dump(type=pt_ip)
941 self.assertEqual(len(punts), 0)
942
943 #
944 # configure a punt socket
945 #
946 punt_ospf = {
947 'type': pt_ip,
948 'punt': {
949 'ip_proto': {
950 'af': af_ip4,
951 'protocol': proto_ospf
952 }
953 }
954 }
955 punt_eigrp = {
956 'type': pt_ip,
957 'punt': {
958 'ip_proto': {
959 'af': af_ip4,
960 'protocol': proto_eigrp
961 }
962 }
963 }
964
965 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200966 "%s/socket_punt_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700967 self.vapi.punt_socket_register(punt_eigrp,
Ole Troan9cd8f332019-10-18 15:57:56 +0200968 "%s/socket_punt_2" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700969 self.logger.info(self.vapi.cli("sh punt sock reg ip"))
970 punts = self.vapi.punt_socket_dump(type=pt_ip)
971 self.assertEqual(len(punts), 2)
972 self.verify_ip_proto(punt_ospf, punts[0])
973 self.verify_ip_proto(punt_eigrp, punts[1])
974
975 #
976 # deregister a punt socket
977 #
978 self.vapi.punt_socket_deregister(punt_ospf)
979 punts = self.vapi.punt_socket_dump(type=pt_ip)
980 self.assertEqual(len(punts), 1)
981
982 #
983 # configure a punt socket again
984 #
985 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200986 "%s/socket_punt_3" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700987 punts = self.vapi.punt_socket_dump(type=pt_ip)
988 self.assertEqual(len(punts), 2)
989
990 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
991
992 #
993 # deregister all punt socket
994 #
995 self.vapi.punt_socket_deregister(punt_eigrp)
996 self.vapi.punt_socket_deregister(punt_ospf)
997 punts = self.vapi.punt_socket_dump(type=pt_ip)
998 self.assertEqual(len(punts), 0)
999
1000 def verify_ospf_pkts(self, rxs, n_sent):
1001 self.assertEqual(len(rxs), n_sent)
1002 for rx in rxs:
1003 self.assertTrue(rx.haslayer(OSPF_Hdr))
1004
1005 def test_traffic(self):
1006 """ Punt socket traffic """
1007
1008 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1009 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
1010 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
1011
1012 #
1013 # configure a punt socket to capture OSPF packets
1014 #
1015 punt_ospf = {
1016 'type': pt_ip,
1017 'punt': {
1018 'ip_proto': {
1019 'af': af_ip4,
1020 'protocol': proto_ospf
1021 }
1022 }
1023 }
1024
1025 #
1026 # create packet streams and configure a punt sockets
1027 #
1028 pkt = (Ether(src=self.pg0.remote_mac,
1029 dst=self.pg0.local_mac) /
1030 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1031 OSPF_Hdr() /
1032 OSPFv3_Hello())
1033 pkts = pkt * 7
1034
Ole Troan9cd8f332019-10-18 15:57:56 +02001035 sock = self.socket_client_create("%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001036 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +02001037 punt_ospf, "%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001038
1039 #
1040 # send packets for each SPI we expect to be punted
1041 #
1042 self.send_and_assert_no_replies(self.pg0, pkts)
1043
1044 #
1045 # verify the punted packets arrived on the associated socket
1046 #
1047 rx = sock.close()
1048 self.verify_ospf_pkts(rx, len(pkts))
1049 self.vapi.punt_socket_deregister(punt_ospf)
1050
1051
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001052@tag_fixme_vpp_workers
Neale Ranns76b56492018-09-28 15:16:14 +00001053class TestPunt(VppTestCase):
Neale Rannsb538dd82019-05-21 06:54:54 -07001054 """ Exception Punt Test Case """
Neale Ranns76b56492018-09-28 15:16:14 +00001055
1056 @classmethod
1057 def setUpClass(cls):
1058 super(TestPunt, cls).setUpClass()
1059
1060 @classmethod
1061 def tearDownClass(cls):
1062 super(TestPunt, cls).tearDownClass()
1063
1064 def setUp(self):
1065 super(TestPunt, self).setUp()
1066
1067 self.create_pg_interfaces(range(4))
1068
1069 for i in self.pg_interfaces:
1070 i.admin_up()
1071 i.config_ip4()
1072 i.resolve_arp()
1073 i.config_ip6()
1074 i.resolve_ndp()
1075
1076 def tearDown(self):
1077 for i in self.pg_interfaces:
1078 i.unconfig_ip4()
1079 i.unconfig_ip6()
Neale Ranns76b56492018-09-28 15:16:14 +00001080 i.admin_down()
1081 super(TestPunt, self).tearDown()
1082
1083 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -07001084 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +00001085
1086 #
Neale Ranns719beb72019-07-10 07:10:25 +00001087 # dump the punt registered reasons
1088 # search for a few we know should be there
1089 #
1090 rs = self.vapi.punt_reason_dump()
1091
1092 reasons = ["ipsec6-no-such-tunnel",
1093 "ipsec4-no-such-tunnel",
1094 "ipsec4-spi-o-udp-0"]
1095
1096 for reason in reasons:
1097 found = False
1098 for r in rs:
1099 if r.reason.name == reason:
1100 found = True
1101 break
1102 self.assertTrue(found)
1103
1104 #
Neale Ranns76b56492018-09-28 15:16:14 +00001105 # Using the test CLI we will hook in a exception path to
1106 # send ACL deny packets out of pg0 and pg1.
1107 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1108 #
1109 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1110 [VppRoutePath(self.pg3.remote_ip4,
1111 self.pg3.sw_if_index)])
1112 ip_1_1_1_2.add_vpp_config()
1113 ip_1_2 = VppIpRoute(self, "1::2", 128,
1114 [VppRoutePath(self.pg3.remote_ip6,
1115 self.pg3.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001116 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns76b56492018-09-28 15:16:14 +00001117 ip_1_2.add_vpp_config()
1118
1119 p4 = (Ether(src=self.pg2.remote_mac,
1120 dst=self.pg2.local_mac) /
1121 IP(src="1.1.1.1", dst="1.1.1.2") /
1122 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001123 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001124 p6 = (Ether(src=self.pg2.remote_mac,
1125 dst=self.pg2.local_mac) /
1126 IPv6(src="1::1", dst="1::2") /
1127 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001128 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001129 self.send_and_expect(self.pg2, p4*1, self.pg3)
1130 self.send_and_expect(self.pg2, p6*1, self.pg3)
1131
1132 #
1133 # apply the punting features
1134 #
1135 self.vapi.cli("test punt pg2")
1136
1137 #
Neale Ranns719beb72019-07-10 07:10:25 +00001138 # dump the punt reasons to learn the IDs assigned
1139 #
1140 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v4"})
1141 r4 = rs[0].reason.id
1142 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v6"})
1143 r6 = rs[0].reason.id
1144
1145 #
Neale Ranns76b56492018-09-28 15:16:14 +00001146 # pkts now dropped
1147 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001148 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
1149 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001150
1151 #
1152 # Check state:
1153 # 1 - node error counters
1154 # 2 - per-reason counters
1155 # 2, 3 are the index of the assigned punt reason
1156 #
Ole Troan233e4682019-05-16 15:01:34 +02001157 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +00001158 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001159 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001160
1161 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001162 self.assertEqual(stats[0][r4]['packets'], NUM_PKTS)
1163 self.assertEqual(stats[0][r6]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001164
1165 #
1166 # use the test CLI to test a client that punts exception
1167 # packets out of pg0
1168 #
1169 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1170 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1171
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001172 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
1173 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001174
1175 #
1176 # check the packets come out IP unmodified but destined to pg0 host
1177 #
1178 for rx in rx4s:
1179 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1180 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1181 self.assertEqual(p4[IP].dst, rx[IP].dst)
1182 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1183 for rx in rx6s:
1184 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1185 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1186 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1187 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1188
1189 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001190 self.assertEqual(stats[0][r4]['packets'], 2*NUM_PKTS)
1191 self.assertEqual(stats[0][r6]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001192
1193 #
1194 # add another registration for the same reason to send packets
1195 # out of pg1
1196 #
1197 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1198 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1199
1200 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001201 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001202 self.pg_enable_capture(self.pg_interfaces)
1203 self.pg_start()
1204
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001205 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001206 for rx in rxd:
1207 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1208 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1209 self.assertEqual(p4[IP].dst, rx[IP].dst)
1210 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001211 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001212 for rx in rxd:
1213 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1214 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1215 self.assertEqual(p4[IP].dst, rx[IP].dst)
1216 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1217
1218 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001219 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001220 self.pg_enable_capture(self.pg_interfaces)
1221 self.pg_start()
1222
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001223 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001224 for rx in rxd:
1225 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1226 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1227 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1228 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001229 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001230 for rx in rxd:
1231 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1232 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1233 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1234 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1235
1236 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001237 self.assertEqual(stats[0][r4]['packets'], 3*NUM_PKTS)
1238 self.assertEqual(stats[0][r6]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001239
1240 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1241 self.logger.info(self.vapi.cli("show punt client"))
1242 self.logger.info(self.vapi.cli("show punt reason"))
1243 self.logger.info(self.vapi.cli("show punt stats"))
1244 self.logger.info(self.vapi.cli("show punt db"))
1245
Neale Ranns76b56492018-09-28 15:16:14 +00001246
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001247if __name__ == '__main__':
1248 unittest.main(testRunner=VppTestRunner)