blob: c6d6dbc51409134db14f8eb64b59d93a6a0e17f9 [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 = []
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010049 self.keep_running = True
Neale Ranns50f0ac02019-05-15 02:13:37 -070050
51 def rx_packets(self):
52 # Wait for some packets on socket
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010053 while self.keep_running:
54 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:
64 # nothing to receive, sleep a little
65 time.sleep(0.1)
66 pass
67 else:
68 raise
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010069
70 def run(self):
71 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
72 try:
73 os.unlink(self.sockName)
74 except:
75 pass
Neale Ranns50f0ac02019-05-15 02:13:37 -070076 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
77 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010078 fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010079 self.sock.bind(self.sockName)
80
Neale Ranns50f0ac02019-05-15 02:13:37 -070081 self.rx_packets()
82
83 def close(self):
84 self.sock.close()
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010085 self.keep_running = False
Neale Ranns50f0ac02019-05-15 02:13:37 -070086 return self.rx_pkts
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010087
88
Pavel Kotuceke88865d2018-11-28 07:42:11 +010089class TestPuntSocket(VppTestCase):
90 """ Punt Socket """
91
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010092 ports = [1111, 2222, 3333, 4444]
93 sock_servers = list()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +000094 # FIXME: nr_packets > 3 results in failure
95 # nr_packets = 3 makes the test unstable
96 nr_packets = 2
Pavel Kotuceke88865d2018-11-28 07:42:11 +010097
98 @classmethod
Paul Vinciguerra8d991d92019-01-25 14:05:48 -080099 def setUpClass(cls):
100 super(TestPuntSocket, cls).setUpClass()
101
102 @classmethod
103 def tearDownClass(cls):
104 super(TestPuntSocket, cls).tearDownClass()
105
106 @classmethod
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100107 def setUpConstants(cls):
Ole Troana45dc072018-12-21 16:04:22 +0100108 cls.extra_vpp_punt_config = [
109 "punt", "{", "socket", cls.tempdir+"/socket_punt", "}"]
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100110 super(TestPuntSocket, cls).setUpConstants()
111
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100112 def setUp(self):
113 super(TestPuntSocket, self).setUp()
114 random.seed()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100115
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100116 self.create_pg_interfaces(range(2))
117 for i in self.pg_interfaces:
118 i.admin_up()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100119
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100120 def tearDown(self):
121 del self.sock_servers[:]
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800122 super(TestPuntSocket, self).tearDown()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100123
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100124 def socket_client_create(self, sock_name, id=None):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700125 thread = serverSocketThread(id, sock_name)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100126 self.sock_servers.append(thread)
127 thread.start()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700128 return thread
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100129
130 def socket_client_close(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700131 rx_pkts = []
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100132 for thread in self.sock_servers:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700133 rx_pkts += thread.close()
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +0100134 thread.join()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700135 return rx_pkts
136
137 def verify_port(self, pr, vpr):
138 self.assertEqual(vpr.punt.type, pr['type'])
139 self.assertEqual(vpr.punt.punt.l4.port,
140 pr['punt']['l4']['port'])
141 self.assertEqual(vpr.punt.punt.l4.protocol,
142 pr['punt']['l4']['protocol'])
143 self.assertEqual(vpr.punt.punt.l4.af,
144 pr['punt']['l4']['af'])
145
146 def verify_exception(self, pr, vpr):
147 self.assertEqual(vpr.punt.type, pr['type'])
148 self.assertEqual(vpr.punt.punt.exception.id,
149 pr['punt']['exception']['id'])
150
Neale Rannsb538dd82019-05-21 06:54:54 -0700151 def verify_ip_proto(self, pr, vpr):
152 self.assertEqual(vpr.punt.type, pr['type'])
153 self.assertEqual(vpr.punt.punt.ip_proto.af,
154 pr['punt']['ip_proto']['af'])
155 self.assertEqual(vpr.punt.punt.ip_proto.protocol,
156 pr['punt']['ip_proto']['protocol'])
157
Neale Ranns50f0ac02019-05-15 02:13:37 -0700158 def verify_udp_pkts(self, rxs, n_rx, port):
159 n_match = 0
160 for rx in rxs:
161 self.assertTrue(rx.haslayer(UDP))
162 if rx[UDP].dport == port:
163 n_match += 1
164 self.assertEqual(n_match, n_rx)
165
166
167def set_port(pr, port):
168 pr['punt']['l4']['port'] = port
169 return pr
170
171
172def set_reason(pr, reason):
173 pr['punt']['exception']['id'] = reason
174 return pr
175
176
177def mk_vpp_cfg4():
178 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
179 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
180 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
181 punt_l4 = {
182 'type': pt_l4,
183 'punt': {
184 'l4': {
185 'af': af_ip4,
186 'protocol': udp_proto
187 }
188 }
189 }
190 return punt_l4
191
192
193def mk_vpp_cfg6():
194 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
195 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
196 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
197 punt_l4 = {
198 'type': pt_l4,
199 'punt': {
200 'l4': {
201 'af': af_ip6,
202 'protocol': udp_proto
203 }
204 }
205 }
206 return punt_l4
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100207
208
209class TestIP4PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700210 """ Punt Socket for IPv4 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100211
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800212 @classmethod
213 def setUpClass(cls):
214 super(TestIP4PuntSocket, cls).setUpClass()
215
216 @classmethod
217 def tearDownClass(cls):
218 super(TestIP4PuntSocket, cls).tearDownClass()
219
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100220 def setUp(self):
221 super(TestIP4PuntSocket, self).setUp()
222
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100223 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100224 i.config_ip4()
225 i.resolve_arp()
226
227 def tearDown(self):
228 super(TestIP4PuntSocket, self).tearDown()
229 for i in self.pg_interfaces:
230 i.unconfig_ip4()
231 i.admin_down()
232
233 def test_punt_socket_dump(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100234 """ Punt socket registration/deregistration"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100235
Neale Ranns50f0ac02019-05-15 02:13:37 -0700236 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
237 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
238 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
239
240 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100241 self.assertEqual(len(punts), 0)
242
243 #
244 # configure a punt socket
245 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700246 punt_l4 = mk_vpp_cfg4()
247
248 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200249 "%s/socket_punt_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700250 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
Ole Troan9cd8f332019-10-18 15:57:56 +0200251 "%s/socket_punt_2222" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700252 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100253 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700254 self.verify_port(set_port(punt_l4, 1111), punts[0])
255 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100256
257 #
258 # deregister a punt socket
259 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700260 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
261 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100262 self.assertEqual(len(punts), 1)
263
264 #
265 # configure a punt socket again
266 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700267 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200268 "%s/socket_punt_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700269 self.vapi.punt_socket_register(set_port(punt_l4, 3333),
Ole Troan9cd8f332019-10-18 15:57:56 +0200270 "%s/socket_punt_3333" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700271 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100272 self.assertEqual(len(punts), 3)
273
Neale Ranns50f0ac02019-05-15 02:13:37 -0700274 self.logger.info(self.vapi.cli("sh punt sock reg"))
275
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100276 #
277 # deregister all punt socket
278 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700279 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
280 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
281 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
282 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100283 self.assertEqual(len(punts), 0)
284
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100285 def test_punt_socket_traffic_single_port_single_socket(self):
286 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100287
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100288 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700289 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
290 punt_l4 = set_port(mk_vpp_cfg4(), port)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100291
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100292 p = (Ether(src=self.pg0.remote_mac,
293 dst=self.pg0.local_mac) /
294 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100295 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200296 Raw(b'\xa5' * 100))
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100297
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100298 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100299
Neale Ranns50f0ac02019-05-15 02:13:37 -0700300 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100301 self.assertEqual(len(punts), 0)
302
303 #
304 # expect ICMP - port unreachable for all packets
305 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700306 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
307
308 for p in rx:
309 self.assertEqual(int(p[IP].proto), 1) # ICMP
310 self.assertEqual(int(p[ICMP].code), 3) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100311
312 #
313 # configure a punt socket
314 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200315 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
316 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" %
317 (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700318 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100319 self.assertEqual(len(punts), 1)
320
321 #
322 # expect punt socket and no packets on pg0
323 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700324 self.send_and_assert_no_replies(self.pg0, pkts)
325 rx = self.socket_client_close()
326 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100327
328 #
329 # remove punt socket. expect ICMP - port unreachable for all packets
330 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700331 self.vapi.punt_socket_deregister(punt_l4)
332 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100333 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100334
Neale Ranns50f0ac02019-05-15 02:13:37 -0700335 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
336 for p in rx:
337 self.assertEqual(int(p[IP].proto), 1) # ICMP
338 self.assertEqual(int(p[ICMP].code), 3) # unreachable
339
340 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100341 """ Punt socket traffic multi ports and multi sockets"""
342
Neale Ranns50f0ac02019-05-15 02:13:37 -0700343 punt_l4 = mk_vpp_cfg4()
344
345 # configuration for each UDP port
346 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100347
348 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700349 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100350 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700351 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100352 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700353 cfgs[port] = {}
354
355 pkt = (Ether(src=self.pg0.remote_mac,
356 dst=self.pg0.local_mac) /
357 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
358 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200359 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700360 cfgs[port]['pkts'] = pkt * self.nr_packets
361 cfgs[port]['port'] = port
362 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
363
364 # configure punt sockets
365 cfgs[port]['sock'] = self.socket_client_create(
Ole Troan9cd8f332019-10-18 15:57:56 +0200366 "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700367 self.vapi.punt_socket_register(
368 cfgs[port]['vpp'],
Ole Troan9cd8f332019-10-18 15:57:56 +0200369 "%s/socket_%d" % (self.tempdir, port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100370
371 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700372 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100373 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700374 for cfg in cfgs.values():
375 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100376
377 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700378 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100379 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700380 for cfg in cfgs.values():
381 rx = cfg['sock'].close()
382 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
383 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100384
385 def test_punt_socket_traffic_multi_ports_single_socket(self):
386 """ Punt socket traffic multi ports and single socket"""
387
Neale Ranns50f0ac02019-05-15 02:13:37 -0700388 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
389 punt_l4 = mk_vpp_cfg4()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100390
391 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700392 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100393 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700394 pkts = []
395 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100396 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700397 pkt = (Ether(src=self.pg0.remote_mac,
398 dst=self.pg0.local_mac) /
399 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
400 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200401 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700402 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100403
404 #
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100405 # configure a punt socket
406 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200407 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100408 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700409 self.vapi.punt_socket_register(set_port(punt_l4, p),
Ole Troan9cd8f332019-10-18 15:57:56 +0200410 "%s/socket_multi" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700411 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100412 self.assertEqual(len(punts), len(self.ports))
413
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100414 #
415 # expect punt socket and no packets on pg0
416 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700417 self.send_and_assert_no_replies(self.pg0, pkts)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100418 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700419 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100420
421 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700422 self.verify_udp_pkts(rx, self.nr_packets, p)
423 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
424 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100425 self.assertEqual(len(punts), 0)
426
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100427
428class TestIP6PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700429 """ Punt Socket for IPv6 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100430
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800431 @classmethod
432 def setUpClass(cls):
433 super(TestIP6PuntSocket, cls).setUpClass()
434
435 @classmethod
436 def tearDownClass(cls):
437 super(TestIP6PuntSocket, cls).tearDownClass()
438
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100439 def setUp(self):
440 super(TestIP6PuntSocket, self).setUp()
441
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100442 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100443 i.config_ip6()
444 i.resolve_ndp()
445
446 def tearDown(self):
447 super(TestIP6PuntSocket, self).tearDown()
448 for i in self.pg_interfaces:
449 i.unconfig_ip6()
450 i.admin_down()
451
452 def test_punt_socket_dump(self):
453 """ Punt socket registration """
454
Neale Ranns50f0ac02019-05-15 02:13:37 -0700455 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
456 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
457 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
458 #
459 # configure a punt socket
460 #
461 punt_l4 = {
462 'type': pt_l4,
463 'punt': {
464 'l4': {
465 'af': af_ip6,
466 'protocol': udp_proto
467 }
468 }
469 }
470
471 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100472 self.assertEqual(len(punts), 0)
473
474 #
475 # configure a punt socket
476 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700477 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200478 "%s/socket_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700479 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
Ole Troan9cd8f332019-10-18 15:57:56 +0200480 "%s/socket_2222" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700481 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100482 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700483 self.verify_port(set_port(punt_l4, 1111), punts[0])
484 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100485
486 #
487 # deregister a punt socket
488 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700489 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
490 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100491 self.assertEqual(len(punts), 1)
492
493 #
494 # configure a punt socket again
495 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700496 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200497 "%s/socket_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700498 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100499 self.assertEqual(len(punts), 2)
500
501 #
502 # deregister all punt socket
503 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700504 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
505 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
506 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
507 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100508 self.assertEqual(len(punts), 0)
509
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100510 def test_punt_socket_traffic_single_port_single_socket(self):
511 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100512
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100513 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700514 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
515 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
516 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
517 punt_l4 = {
518 'type': pt_l4,
519 'punt': {
520 'l4': {
521 'af': af_ip6,
522 'protocol': udp_proto,
523 'port': port,
524 }
525 }
526 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100527
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100528 p = (Ether(src=self.pg0.remote_mac,
529 dst=self.pg0.local_mac) /
530 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100531 inet6.UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200532 Raw(b'\xa5' * 100))
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100533
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100534 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100535
Neale Ranns50f0ac02019-05-15 02:13:37 -0700536 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100537 self.assertEqual(len(punts), 0)
538
539 #
540 # expect ICMPv6 - destination unreachable for all packets
541 #
542 self.vapi.cli("clear trace")
543 self.pg0.add_stream(pkts)
544 self.pg_enable_capture(self.pg_interfaces)
545 self.pg_start()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100546 # FIXME - when punt socket deregister is implemented
547 # rx = self.pg0.get_capture(self.nr_packets)
548 # for p in rx:
549 # self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
550 # self.assertEqual(int(p[ICMPv6DestUnreach].code),4) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100551
552 #
553 # configure a punt socket
554 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200555 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
556 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" %
557 (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700558 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100559 self.assertEqual(len(punts), 1)
560
561 #
562 # expect punt socket and no packets on pg0
563 #
564 self.vapi.cli("clear errors")
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100565 self.vapi.cli("clear trace")
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100566 self.pg0.add_stream(pkts)
567 self.pg_enable_capture(self.pg_interfaces)
568 self.pg_start()
569 self.pg0.get_capture(0)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100570 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700571 rx = self.socket_client_close()
572 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100573
574 #
575 # remove punt socket. expect ICMP - dest. unreachable for all packets
576 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700577 self.vapi.punt_socket_deregister(punt_l4)
578 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100579 self.assertEqual(len(punts), 0)
580 self.pg0.add_stream(pkts)
581 self.pg_enable_capture(self.pg_interfaces)
582 self.pg_start()
583 # FIXME - when punt socket deregister is implemented
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100584 # self.pg0.get_capture(nr_packets)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100585
Neale Ranns50f0ac02019-05-15 02:13:37 -0700586 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100587 """ Punt socket traffic multi ports and multi sockets"""
588
Neale Ranns50f0ac02019-05-15 02:13:37 -0700589 punt_l4 = mk_vpp_cfg6()
590
591 # configuration for each UDP port
592 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100593
594 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700595 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100596 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700597 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100598 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700599 cfgs[port] = {}
600
601 pkt = (Ether(src=self.pg0.remote_mac,
602 dst=self.pg0.local_mac) /
603 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
604 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200605 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700606 cfgs[port]['pkts'] = pkt * self.nr_packets
607 cfgs[port]['port'] = port
608 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
609
610 # configure punt sockets
611 cfgs[port]['sock'] = self.socket_client_create(
Ole Troan9cd8f332019-10-18 15:57:56 +0200612 "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700613 self.vapi.punt_socket_register(
614 cfgs[port]['vpp'],
Ole Troan9cd8f332019-10-18 15:57:56 +0200615 "%s/socket_%d" % (self.tempdir, port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100616
617 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700618 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100619 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700620 for cfg in cfgs.values():
621 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100622
623 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700624 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100625 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700626 for cfg in cfgs.values():
627 rx = cfg['sock'].close()
628 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
629 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100630
631 def test_punt_socket_traffic_multi_ports_single_socket(self):
632 """ Punt socket traffic multi ports and single socket"""
633
Neale Ranns50f0ac02019-05-15 02:13:37 -0700634 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
635 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
636 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
637 punt_l4 = {
638 'type': pt_l4,
639 'punt': {
640 'l4': {
641 'af': af_ip6,
642 'protocol': udp_proto,
643 }
644 }
645 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100646
647 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700648 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100649 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700650 pkts = []
651 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100652 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700653 pkt = (Ether(src=self.pg0.remote_mac,
654 dst=self.pg0.local_mac) /
655 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
656 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200657 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700658 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100659
660 #
661 # no punt socket
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), 0)
665
666 #
667 # configure a punt socket
668 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200669 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100670 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700671 self.vapi.punt_socket_register(set_port(punt_l4, p),
Ole Troan9cd8f332019-10-18 15:57:56 +0200672 "%s/socket_multi" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700673 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100674 self.assertEqual(len(punts), len(self.ports))
675
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100676 #
677 # expect punt socket and no packets on pg0
678 #
679 self.vapi.cli("clear errors")
680 self.vapi.cli("clear trace")
681 self.pg0.add_stream(pkts)
682 self.pg_enable_capture(self.pg_interfaces)
683 self.pg_start()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +0000684 # give a chance to punt socket to collect all packets
685 self.sleep(1)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100686 self.pg0.get_capture(0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700687 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100688
689 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700690 self.verify_udp_pkts(rx, self.nr_packets, p)
691 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
692 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100693 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100694
Neale Ranns76b56492018-09-28 15:16:14 +0000695
Neale Ranns50f0ac02019-05-15 02:13:37 -0700696class TestExceptionPuntSocket(TestPuntSocket):
697 """ Punt Socket for Exceptions """
698
699 @classmethod
700 def setUpClass(cls):
701 super(TestExceptionPuntSocket, cls).setUpClass()
702
703 @classmethod
704 def tearDownClass(cls):
705 super(TestExceptionPuntSocket, cls).tearDownClass()
706
707 def setUp(self):
708 super(TestExceptionPuntSocket, self).setUp()
709
Neale Ranns12989b52019-09-26 16:20:19 +0000710 self.create_pg_interfaces(range(2))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700711 for i in self.pg_interfaces:
712 i.config_ip4()
713 i.resolve_arp()
714
715 def tearDown(self):
716 super(TestExceptionPuntSocket, self).tearDown()
717 for i in self.pg_interfaces:
718 i.unconfig_ip4()
719 i.admin_down()
720
721 def test_registration(self):
722 """ Punt socket registration/deregistration"""
723
724 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
725
726 punts = self.vapi.punt_socket_dump(type=pt_ex)
727 self.assertEqual(len(punts), 0)
728
729 #
730 # configure a punt socket
731 #
732 punt_ex = {
733 'type': pt_ex,
734 'punt': {
735 'exception': {}
736 }
737 }
738
739 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
Ole Troan9cd8f332019-10-18 15:57:56 +0200740 "%s/socket_punt_1" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700741 self.vapi.punt_socket_register(set_reason(punt_ex, 2),
Ole Troan9cd8f332019-10-18 15:57:56 +0200742 "%s/socket_punt_2" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700743 punts = self.vapi.punt_socket_dump(type=pt_ex)
744 self.assertEqual(len(punts), 2)
745 self.verify_exception(set_reason(punt_ex, 1), punts[0])
746 self.verify_exception(set_reason(punt_ex, 2), punts[1])
747
748 #
749 # deregister a punt socket
750 #
751 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
752 punts = self.vapi.punt_socket_dump(type=pt_ex)
753 self.assertEqual(len(punts), 1)
754
755 #
756 # configure a punt socket again
757 #
758 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
Ole Troan9cd8f332019-10-18 15:57:56 +0200759 "%s/socket_punt_1" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700760 self.vapi.punt_socket_register(set_reason(punt_ex, 3),
Ole Troan9cd8f332019-10-18 15:57:56 +0200761 "%s/socket_punt_3" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700762 punts = self.vapi.punt_socket_dump(type=pt_ex)
763 self.assertEqual(len(punts), 3)
764
765 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
766
767 #
768 # deregister all punt socket
769 #
770 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
771 self.vapi.punt_socket_deregister(set_reason(punt_ex, 2))
772 self.vapi.punt_socket_deregister(set_reason(punt_ex, 3))
773 punts = self.vapi.punt_socket_dump(type=pt_ex)
774 self.assertEqual(len(punts), 0)
775
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700776 def verify_esp_pkts(self, rxs, n_sent, spi, has_udp):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700777 self.assertEqual(len(rxs), n_sent)
778 for rx in rxs:
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700779 self.assertTrue(rx.haslayer(IP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700780 self.assertTrue(rx.haslayer(ESP))
781 self.assertEqual(rx[ESP].spi, spi)
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700782 if has_udp:
783 self.assertTrue(rx.haslayer(UDP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700784
785 def test_traffic(self):
786 """ Punt socket traffic """
787
788 port = self.ports[0]
789 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
790 punt_ex = {
791 'type': pt_ex,
792 'punt': {
793 'exception': {}
794 }
795 }
796
797 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700798 # we're dealing with IPSec tunnels punting for no-such-tunnel
Filip Tehlar4362baa2020-04-02 13:13:39 +0000799 # (SPI=0 goes to ikev2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700800 #
801 cfgs = dict()
Neale Ranns12989b52019-09-26 16:20:19 +0000802 cfgs['ipsec4-no-such-tunnel'] = {'spi': 99,
803 'udp': False,
804 'itf': self.pg0}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700805
806 #
807 # find the VPP ID for these punt exception reasin
808 #
809 rs = self.vapi.punt_reason_dump()
810 for key in cfgs:
811 for r in rs:
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100812 print(r.reason.name)
813 print(key)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700814 if r.reason.name == key:
815 cfgs[key]['id'] = r.reason.id
816 cfgs[key]['vpp'] = copy.deepcopy(
817 set_reason(punt_ex,
818 cfgs[key]['id']))
819 break
820
821 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700822 # configure punt sockets
Neale Ranns50f0ac02019-05-15 02:13:37 -0700823 #
824 for cfg in cfgs.values():
Ole Troan9cd8f332019-10-18 15:57:56 +0200825 cfg['sock'] = self.socket_client_create("%s/socket_%d" %
826 (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700827 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +0200828 cfg['vpp'], "%s/socket_%d" % (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700829
830 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700831 # create packet streams for 'no-such-tunnel' exception
832 #
833 for cfg in cfgs.values():
Neale Ranns12989b52019-09-26 16:20:19 +0000834 pkt = (Ether(src=cfg['itf'].remote_mac,
835 dst=cfg['itf'].local_mac) /
836 IP(src=cfg['itf'].remote_ip4,
837 dst=cfg['itf'].local_ip4))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700838 if (cfg['udp']):
839 pkt = pkt / UDP(sport=666, dport=4500)
840 pkt = (pkt / ESP(spi=cfg['spi'], seq=3) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200841 Raw(b'\xa5' * 100))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700842 cfg['pkts'] = [pkt]
843
844 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700845 # send packets for each SPI we expect to be punted
846 #
847 for cfg in cfgs.values():
Neale Ranns12989b52019-09-26 16:20:19 +0000848 self.send_and_assert_no_replies(cfg['itf'], cfg['pkts'])
Neale Ranns50f0ac02019-05-15 02:13:37 -0700849
850 #
851 # verify the punted packets arrived on the associated socket
852 #
853 for cfg in cfgs.values():
854 rx = cfg['sock'].close()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700855 self.verify_esp_pkts(rx, len(cfg['pkts']),
856 cfg['spi'], cfg['udp'])
857
858 #
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000859 # add some tunnels, make sure it still punts
860 #
Neale Rannsa9e27742020-12-23 16:22:28 +0000861 tun = VppIpsecInterface(self).add_vpp_config()
862 sa_in = VppIpsecSA(self, 11, 11,
863 (VppEnum.vl_api_ipsec_integ_alg_t.
864 IPSEC_API_INTEG_ALG_SHA1_96),
865 b"0123456701234567",
866 (VppEnum.vl_api_ipsec_crypto_alg_t.
867 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
868 b"0123456701234567",
869 50,
870 self.pg0.local_ip4,
871 self.pg0.remote_ip4).add_vpp_config()
872 sa_out = VppIpsecSA(self, 22, 22,
873 (VppEnum.vl_api_ipsec_integ_alg_t.
874 IPSEC_API_INTEG_ALG_SHA1_96),
875 b"0123456701234567",
876 (VppEnum.vl_api_ipsec_crypto_alg_t.
877 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
878 b"0123456701234567",
879 50,
880 self.pg0.local_ip4,
881 self.pg0.remote_ip4).add_vpp_config()
882 protect = VppIpsecTunProtect(self, tun,
883 sa_out,
884 [sa_in]).add_vpp_config()
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000885
886 #
887 # send packets for each SPI we expect to be punted
888 #
889 for cfg in cfgs.values():
890 self.send_and_assert_no_replies(cfg['itf'], cfg['pkts'])
891
892 #
893 # verify the punted packets arrived on the associated socket
894 #
895 for cfg in cfgs.values():
896 rx = cfg['sock'].close()
897 self.verify_esp_pkts(rx, len(cfg['pkts']),
898 cfg['spi'], cfg['udp'])
899 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700900 # socket deregister
901 #
902 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700903 self.vapi.punt_socket_deregister(cfg['vpp'])
904
905
Neale Rannsb538dd82019-05-21 06:54:54 -0700906class TestIpProtoPuntSocket(TestPuntSocket):
907 """ Punt Socket for IP packets """
908
909 @classmethod
910 def setUpClass(cls):
911 super(TestIpProtoPuntSocket, cls).setUpClass()
912
913 @classmethod
914 def tearDownClass(cls):
915 super(TestIpProtoPuntSocket, cls).tearDownClass()
916
917 def setUp(self):
918 super(TestIpProtoPuntSocket, self).setUp()
919
920 for i in self.pg_interfaces:
921 i.config_ip4()
922 i.resolve_arp()
923
924 def tearDown(self):
925 super(TestIpProtoPuntSocket, self).tearDown()
926 for i in self.pg_interfaces:
927 i.unconfig_ip4()
928 i.admin_down()
929
930 def test_registration(self):
931 """ Punt socket registration/deregistration"""
932
933 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
934 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
935 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
936 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
937
938 punts = self.vapi.punt_socket_dump(type=pt_ip)
939 self.assertEqual(len(punts), 0)
940
941 #
942 # configure a punt socket
943 #
944 punt_ospf = {
945 'type': pt_ip,
946 'punt': {
947 'ip_proto': {
948 'af': af_ip4,
949 'protocol': proto_ospf
950 }
951 }
952 }
953 punt_eigrp = {
954 'type': pt_ip,
955 'punt': {
956 'ip_proto': {
957 'af': af_ip4,
958 'protocol': proto_eigrp
959 }
960 }
961 }
962
963 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200964 "%s/socket_punt_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700965 self.vapi.punt_socket_register(punt_eigrp,
Ole Troan9cd8f332019-10-18 15:57:56 +0200966 "%s/socket_punt_2" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700967 self.logger.info(self.vapi.cli("sh punt sock reg ip"))
968 punts = self.vapi.punt_socket_dump(type=pt_ip)
969 self.assertEqual(len(punts), 2)
970 self.verify_ip_proto(punt_ospf, punts[0])
971 self.verify_ip_proto(punt_eigrp, punts[1])
972
973 #
974 # deregister a punt socket
975 #
976 self.vapi.punt_socket_deregister(punt_ospf)
977 punts = self.vapi.punt_socket_dump(type=pt_ip)
978 self.assertEqual(len(punts), 1)
979
980 #
981 # configure a punt socket again
982 #
983 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200984 "%s/socket_punt_3" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700985 punts = self.vapi.punt_socket_dump(type=pt_ip)
986 self.assertEqual(len(punts), 2)
987
988 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
989
990 #
991 # deregister all punt socket
992 #
993 self.vapi.punt_socket_deregister(punt_eigrp)
994 self.vapi.punt_socket_deregister(punt_ospf)
995 punts = self.vapi.punt_socket_dump(type=pt_ip)
996 self.assertEqual(len(punts), 0)
997
998 def verify_ospf_pkts(self, rxs, n_sent):
999 self.assertEqual(len(rxs), n_sent)
1000 for rx in rxs:
1001 self.assertTrue(rx.haslayer(OSPF_Hdr))
1002
1003 def test_traffic(self):
1004 """ Punt socket traffic """
1005
1006 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1007 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
1008 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
1009
1010 #
1011 # configure a punt socket to capture OSPF packets
1012 #
1013 punt_ospf = {
1014 'type': pt_ip,
1015 'punt': {
1016 'ip_proto': {
1017 'af': af_ip4,
1018 'protocol': proto_ospf
1019 }
1020 }
1021 }
1022
1023 #
1024 # create packet streams and configure a punt sockets
1025 #
1026 pkt = (Ether(src=self.pg0.remote_mac,
1027 dst=self.pg0.local_mac) /
1028 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1029 OSPF_Hdr() /
1030 OSPFv3_Hello())
1031 pkts = pkt * 7
1032
Ole Troan9cd8f332019-10-18 15:57:56 +02001033 sock = self.socket_client_create("%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001034 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +02001035 punt_ospf, "%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001036
1037 #
1038 # send packets for each SPI we expect to be punted
1039 #
1040 self.send_and_assert_no_replies(self.pg0, pkts)
1041
1042 #
1043 # verify the punted packets arrived on the associated socket
1044 #
1045 rx = sock.close()
1046 self.verify_ospf_pkts(rx, len(pkts))
1047 self.vapi.punt_socket_deregister(punt_ospf)
1048
1049
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001050@tag_fixme_vpp_workers
Neale Ranns76b56492018-09-28 15:16:14 +00001051class TestPunt(VppTestCase):
Neale Rannsb538dd82019-05-21 06:54:54 -07001052 """ Exception Punt Test Case """
Neale Ranns76b56492018-09-28 15:16:14 +00001053
1054 @classmethod
1055 def setUpClass(cls):
1056 super(TestPunt, cls).setUpClass()
1057
1058 @classmethod
1059 def tearDownClass(cls):
1060 super(TestPunt, cls).tearDownClass()
1061
1062 def setUp(self):
1063 super(TestPunt, self).setUp()
1064
1065 self.create_pg_interfaces(range(4))
1066
1067 for i in self.pg_interfaces:
1068 i.admin_up()
1069 i.config_ip4()
1070 i.resolve_arp()
1071 i.config_ip6()
1072 i.resolve_ndp()
1073
1074 def tearDown(self):
1075 for i in self.pg_interfaces:
1076 i.unconfig_ip4()
1077 i.unconfig_ip6()
Neale Ranns76b56492018-09-28 15:16:14 +00001078 i.admin_down()
1079 super(TestPunt, self).tearDown()
1080
1081 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -07001082 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +00001083
1084 #
Neale Ranns719beb72019-07-10 07:10:25 +00001085 # dump the punt registered reasons
1086 # search for a few we know should be there
1087 #
1088 rs = self.vapi.punt_reason_dump()
1089
1090 reasons = ["ipsec6-no-such-tunnel",
1091 "ipsec4-no-such-tunnel",
1092 "ipsec4-spi-o-udp-0"]
1093
1094 for reason in reasons:
1095 found = False
1096 for r in rs:
1097 if r.reason.name == reason:
1098 found = True
1099 break
1100 self.assertTrue(found)
1101
1102 #
Neale Ranns76b56492018-09-28 15:16:14 +00001103 # Using the test CLI we will hook in a exception path to
1104 # send ACL deny packets out of pg0 and pg1.
1105 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1106 #
1107 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1108 [VppRoutePath(self.pg3.remote_ip4,
1109 self.pg3.sw_if_index)])
1110 ip_1_1_1_2.add_vpp_config()
1111 ip_1_2 = VppIpRoute(self, "1::2", 128,
1112 [VppRoutePath(self.pg3.remote_ip6,
1113 self.pg3.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001114 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns76b56492018-09-28 15:16:14 +00001115 ip_1_2.add_vpp_config()
1116
1117 p4 = (Ether(src=self.pg2.remote_mac,
1118 dst=self.pg2.local_mac) /
1119 IP(src="1.1.1.1", dst="1.1.1.2") /
1120 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001121 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001122 p6 = (Ether(src=self.pg2.remote_mac,
1123 dst=self.pg2.local_mac) /
1124 IPv6(src="1::1", dst="1::2") /
1125 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001126 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001127 self.send_and_expect(self.pg2, p4*1, self.pg3)
1128 self.send_and_expect(self.pg2, p6*1, self.pg3)
1129
1130 #
1131 # apply the punting features
1132 #
1133 self.vapi.cli("test punt pg2")
1134
1135 #
Neale Ranns719beb72019-07-10 07:10:25 +00001136 # dump the punt reasons to learn the IDs assigned
1137 #
1138 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v4"})
1139 r4 = rs[0].reason.id
1140 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v6"})
1141 r6 = rs[0].reason.id
1142
1143 #
Neale Ranns76b56492018-09-28 15:16:14 +00001144 # pkts now dropped
1145 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001146 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
1147 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001148
1149 #
1150 # Check state:
1151 # 1 - node error counters
1152 # 2 - per-reason counters
1153 # 2, 3 are the index of the assigned punt reason
1154 #
Ole Troan233e4682019-05-16 15:01:34 +02001155 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +00001156 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001157 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001158
1159 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001160 self.assertEqual(stats[0][r4]['packets'], NUM_PKTS)
1161 self.assertEqual(stats[0][r6]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001162
1163 #
1164 # use the test CLI to test a client that punts exception
1165 # packets out of pg0
1166 #
1167 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1168 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1169
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001170 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
1171 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001172
1173 #
1174 # check the packets come out IP unmodified but destined to pg0 host
1175 #
1176 for rx in rx4s:
1177 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1178 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1179 self.assertEqual(p4[IP].dst, rx[IP].dst)
1180 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1181 for rx in rx6s:
1182 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1183 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1184 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1185 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1186
1187 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001188 self.assertEqual(stats[0][r4]['packets'], 2*NUM_PKTS)
1189 self.assertEqual(stats[0][r6]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001190
1191 #
1192 # add another registration for the same reason to send packets
1193 # out of pg1
1194 #
1195 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1196 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1197
1198 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001199 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001200 self.pg_enable_capture(self.pg_interfaces)
1201 self.pg_start()
1202
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001203 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001204 for rx in rxd:
1205 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1206 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1207 self.assertEqual(p4[IP].dst, rx[IP].dst)
1208 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001209 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001210 for rx in rxd:
1211 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1212 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1213 self.assertEqual(p4[IP].dst, rx[IP].dst)
1214 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1215
1216 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001217 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001218 self.pg_enable_capture(self.pg_interfaces)
1219 self.pg_start()
1220
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001221 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001222 for rx in rxd:
1223 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1224 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1225 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1226 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001227 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001228 for rx in rxd:
1229 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1230 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1231 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1232 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1233
1234 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001235 self.assertEqual(stats[0][r4]['packets'], 3*NUM_PKTS)
1236 self.assertEqual(stats[0][r6]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001237
1238 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1239 self.logger.info(self.vapi.cli("show punt client"))
1240 self.logger.info(self.vapi.cli("show punt reason"))
1241 self.logger.info(self.vapi.cli("show punt stats"))
1242 self.logger.info(self.vapi.cli("show punt db"))
1243
Neale Ranns76b56492018-09-28 15:16:14 +00001244
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001245if __name__ == '__main__':
1246 unittest.main(testRunner=VppTestRunner)