blob: d3a9307c3676edec50c1459ff6f786927469df78 [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
Pavel Kotuceke88865d2018-11-28 07:42:11 +010029from framework import VppTestCase, VppTestRunner
30
Neale Ranns76b56492018-09-28 15:16:14 +000031from vpp_ip import DpoProto
32from vpp_ip_route import VppIpRoute, VppRoutePath
Neale Rannsa9e27742020-12-23 16:22:28 +000033from vpp_ipsec import VppIpsecSA, VppIpsecTunProtect, VppIpsecInterface
Neale Ranns50f0ac02019-05-15 02:13:37 -070034from vpp_papi import VppEnum
Neale Ranns76b56492018-09-28 15:16:14 +000035
Paul Vinciguerra4271c972019-05-14 13:25:49 -040036NUM_PKTS = 67
37
Pavel Kotuceke88865d2018-11-28 07:42:11 +010038
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010039class serverSocketThread(threading.Thread):
40 """ Socket server thread"""
41
Neale Ranns50f0ac02019-05-15 02:13:37 -070042 def __init__(self, threadID, sockName):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010043 threading.Thread.__init__(self)
44 self.threadID = threadID
45 self.sockName = sockName
46 self.sock = None
Neale Ranns50f0ac02019-05-15 02:13:37 -070047 self.rx_pkts = []
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010048 self.keep_running = True
Neale Ranns50f0ac02019-05-15 02:13:37 -070049
50 def rx_packets(self):
51 # Wait for some packets on socket
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010052 while self.keep_running:
53 try:
54 data = self.sock.recv(65536)
Neale Ranns50f0ac02019-05-15 02:13:37 -070055
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010056 # punt socket metadata
57 # packet_desc = data[0:8]
Neale Ranns50f0ac02019-05-15 02:13:37 -070058
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010059 # Ethernet
60 self.rx_pkts.append(Ether(data[8:]))
61 except IOError as e:
62 if e.errno == 11:
63 # nothing to receive, sleep a little
64 time.sleep(0.1)
65 pass
66 else:
67 raise
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010068
69 def run(self):
70 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
71 try:
72 os.unlink(self.sockName)
73 except:
74 pass
Neale Ranns50f0ac02019-05-15 02:13:37 -070075 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
76 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010077 fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010078 self.sock.bind(self.sockName)
79
Neale Ranns50f0ac02019-05-15 02:13:37 -070080 self.rx_packets()
81
82 def close(self):
83 self.sock.close()
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010084 self.keep_running = False
Neale Ranns50f0ac02019-05-15 02:13:37 -070085 return self.rx_pkts
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010086
87
Pavel Kotuceke88865d2018-11-28 07:42:11 +010088class TestPuntSocket(VppTestCase):
89 """ Punt Socket """
90
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010091 ports = [1111, 2222, 3333, 4444]
92 sock_servers = list()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +000093 # FIXME: nr_packets > 3 results in failure
94 # nr_packets = 3 makes the test unstable
95 nr_packets = 2
Pavel Kotuceke88865d2018-11-28 07:42:11 +010096
97 @classmethod
Paul Vinciguerra8d991d92019-01-25 14:05:48 -080098 def setUpClass(cls):
99 super(TestPuntSocket, cls).setUpClass()
100
101 @classmethod
102 def tearDownClass(cls):
103 super(TestPuntSocket, cls).tearDownClass()
104
105 @classmethod
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100106 def setUpConstants(cls):
Ole Troana45dc072018-12-21 16:04:22 +0100107 cls.extra_vpp_punt_config = [
108 "punt", "{", "socket", cls.tempdir+"/socket_punt", "}"]
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100109 super(TestPuntSocket, cls).setUpConstants()
110
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100111 def setUp(self):
112 super(TestPuntSocket, self).setUp()
113 random.seed()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100114
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100115 self.create_pg_interfaces(range(2))
116 for i in self.pg_interfaces:
117 i.admin_up()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100118
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100119 def tearDown(self):
120 del self.sock_servers[:]
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800121 super(TestPuntSocket, self).tearDown()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100122
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100123 def socket_client_create(self, sock_name, id=None):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700124 thread = serverSocketThread(id, sock_name)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100125 self.sock_servers.append(thread)
126 thread.start()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700127 return thread
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100128
129 def socket_client_close(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700130 rx_pkts = []
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100131 for thread in self.sock_servers:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700132 rx_pkts += thread.close()
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +0100133 thread.join()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700134 return rx_pkts
135
136 def verify_port(self, pr, vpr):
137 self.assertEqual(vpr.punt.type, pr['type'])
138 self.assertEqual(vpr.punt.punt.l4.port,
139 pr['punt']['l4']['port'])
140 self.assertEqual(vpr.punt.punt.l4.protocol,
141 pr['punt']['l4']['protocol'])
142 self.assertEqual(vpr.punt.punt.l4.af,
143 pr['punt']['l4']['af'])
144
145 def verify_exception(self, pr, vpr):
146 self.assertEqual(vpr.punt.type, pr['type'])
147 self.assertEqual(vpr.punt.punt.exception.id,
148 pr['punt']['exception']['id'])
149
Neale Rannsb538dd82019-05-21 06:54:54 -0700150 def verify_ip_proto(self, pr, vpr):
151 self.assertEqual(vpr.punt.type, pr['type'])
152 self.assertEqual(vpr.punt.punt.ip_proto.af,
153 pr['punt']['ip_proto']['af'])
154 self.assertEqual(vpr.punt.punt.ip_proto.protocol,
155 pr['punt']['ip_proto']['protocol'])
156
Neale Ranns50f0ac02019-05-15 02:13:37 -0700157 def verify_udp_pkts(self, rxs, n_rx, port):
158 n_match = 0
159 for rx in rxs:
160 self.assertTrue(rx.haslayer(UDP))
161 if rx[UDP].dport == port:
162 n_match += 1
163 self.assertEqual(n_match, n_rx)
164
165
166def set_port(pr, port):
167 pr['punt']['l4']['port'] = port
168 return pr
169
170
171def set_reason(pr, reason):
172 pr['punt']['exception']['id'] = reason
173 return pr
174
175
176def mk_vpp_cfg4():
177 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
178 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
179 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
180 punt_l4 = {
181 'type': pt_l4,
182 'punt': {
183 'l4': {
184 'af': af_ip4,
185 'protocol': udp_proto
186 }
187 }
188 }
189 return punt_l4
190
191
192def mk_vpp_cfg6():
193 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
194 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
195 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
196 punt_l4 = {
197 'type': pt_l4,
198 'punt': {
199 'l4': {
200 'af': af_ip6,
201 'protocol': udp_proto
202 }
203 }
204 }
205 return punt_l4
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100206
207
208class TestIP4PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700209 """ Punt Socket for IPv4 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100210
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800211 @classmethod
212 def setUpClass(cls):
213 super(TestIP4PuntSocket, cls).setUpClass()
214
215 @classmethod
216 def tearDownClass(cls):
217 super(TestIP4PuntSocket, cls).tearDownClass()
218
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100219 def setUp(self):
220 super(TestIP4PuntSocket, self).setUp()
221
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100222 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100223 i.config_ip4()
224 i.resolve_arp()
225
226 def tearDown(self):
227 super(TestIP4PuntSocket, self).tearDown()
228 for i in self.pg_interfaces:
229 i.unconfig_ip4()
230 i.admin_down()
231
232 def test_punt_socket_dump(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100233 """ Punt socket registration/deregistration"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100234
Neale Ranns50f0ac02019-05-15 02:13:37 -0700235 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
236 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
237 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
238
239 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100240 self.assertEqual(len(punts), 0)
241
242 #
243 # configure a punt socket
244 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700245 punt_l4 = mk_vpp_cfg4()
246
247 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200248 "%s/socket_punt_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700249 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
Ole Troan9cd8f332019-10-18 15:57:56 +0200250 "%s/socket_punt_2222" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700251 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100252 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700253 self.verify_port(set_port(punt_l4, 1111), punts[0])
254 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100255
256 #
257 # deregister a punt socket
258 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700259 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
260 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100261 self.assertEqual(len(punts), 1)
262
263 #
264 # configure a punt socket again
265 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700266 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200267 "%s/socket_punt_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700268 self.vapi.punt_socket_register(set_port(punt_l4, 3333),
Ole Troan9cd8f332019-10-18 15:57:56 +0200269 "%s/socket_punt_3333" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700270 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100271 self.assertEqual(len(punts), 3)
272
Neale Ranns50f0ac02019-05-15 02:13:37 -0700273 self.logger.info(self.vapi.cli("sh punt sock reg"))
274
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100275 #
276 # deregister all punt socket
277 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700278 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
279 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
280 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
281 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100282 self.assertEqual(len(punts), 0)
283
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100284 def test_punt_socket_traffic_single_port_single_socket(self):
285 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100286
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100287 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700288 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
289 punt_l4 = set_port(mk_vpp_cfg4(), port)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100290
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100291 p = (Ether(src=self.pg0.remote_mac,
292 dst=self.pg0.local_mac) /
293 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100294 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200295 Raw(b'\xa5' * 100))
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100296
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100297 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100298
Neale Ranns50f0ac02019-05-15 02:13:37 -0700299 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100300 self.assertEqual(len(punts), 0)
301
302 #
303 # expect ICMP - port unreachable for all packets
304 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700305 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
306
307 for p in rx:
308 self.assertEqual(int(p[IP].proto), 1) # ICMP
309 self.assertEqual(int(p[ICMP].code), 3) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100310
311 #
312 # configure a punt socket
313 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200314 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
315 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" %
316 (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700317 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100318 self.assertEqual(len(punts), 1)
319
320 #
321 # expect punt socket and no packets on pg0
322 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700323 self.send_and_assert_no_replies(self.pg0, pkts)
324 rx = self.socket_client_close()
325 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100326
327 #
328 # remove punt socket. expect ICMP - port unreachable for all packets
329 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700330 self.vapi.punt_socket_deregister(punt_l4)
331 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100332 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100333
Neale Ranns50f0ac02019-05-15 02:13:37 -0700334 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
335 for p in rx:
336 self.assertEqual(int(p[IP].proto), 1) # ICMP
337 self.assertEqual(int(p[ICMP].code), 3) # unreachable
338
339 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100340 """ Punt socket traffic multi ports and multi sockets"""
341
Neale Ranns50f0ac02019-05-15 02:13:37 -0700342 punt_l4 = mk_vpp_cfg4()
343
344 # configuration for each UDP port
345 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100346
347 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700348 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100349 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700350 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100351 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700352 cfgs[port] = {}
353
354 pkt = (Ether(src=self.pg0.remote_mac,
355 dst=self.pg0.local_mac) /
356 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
357 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200358 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700359 cfgs[port]['pkts'] = pkt * self.nr_packets
360 cfgs[port]['port'] = port
361 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
362
363 # configure punt sockets
364 cfgs[port]['sock'] = self.socket_client_create(
Ole Troan9cd8f332019-10-18 15:57:56 +0200365 "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700366 self.vapi.punt_socket_register(
367 cfgs[port]['vpp'],
Ole Troan9cd8f332019-10-18 15:57:56 +0200368 "%s/socket_%d" % (self.tempdir, port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100369
370 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700371 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100372 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700373 for cfg in cfgs.values():
374 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100375
376 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700377 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100378 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700379 for cfg in cfgs.values():
380 rx = cfg['sock'].close()
381 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
382 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100383
384 def test_punt_socket_traffic_multi_ports_single_socket(self):
385 """ Punt socket traffic multi ports and single socket"""
386
Neale Ranns50f0ac02019-05-15 02:13:37 -0700387 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
388 punt_l4 = mk_vpp_cfg4()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100389
390 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700391 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100392 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700393 pkts = []
394 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100395 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700396 pkt = (Ether(src=self.pg0.remote_mac,
397 dst=self.pg0.local_mac) /
398 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
399 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200400 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700401 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100402
403 #
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100404 # configure a punt socket
405 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200406 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100407 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700408 self.vapi.punt_socket_register(set_port(punt_l4, p),
Ole Troan9cd8f332019-10-18 15:57:56 +0200409 "%s/socket_multi" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700410 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100411 self.assertEqual(len(punts), len(self.ports))
412
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100413 #
414 # expect punt socket and no packets on pg0
415 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700416 self.send_and_assert_no_replies(self.pg0, pkts)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100417 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700418 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100419
420 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700421 self.verify_udp_pkts(rx, self.nr_packets, p)
422 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
423 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100424 self.assertEqual(len(punts), 0)
425
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100426
427class TestIP6PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700428 """ Punt Socket for IPv6 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100429
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800430 @classmethod
431 def setUpClass(cls):
432 super(TestIP6PuntSocket, cls).setUpClass()
433
434 @classmethod
435 def tearDownClass(cls):
436 super(TestIP6PuntSocket, cls).tearDownClass()
437
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100438 def setUp(self):
439 super(TestIP6PuntSocket, self).setUp()
440
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100441 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100442 i.config_ip6()
443 i.resolve_ndp()
444
445 def tearDown(self):
446 super(TestIP6PuntSocket, self).tearDown()
447 for i in self.pg_interfaces:
448 i.unconfig_ip6()
449 i.admin_down()
450
451 def test_punt_socket_dump(self):
452 """ Punt socket registration """
453
Neale Ranns50f0ac02019-05-15 02:13:37 -0700454 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
455 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
456 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
457 #
458 # configure a punt socket
459 #
460 punt_l4 = {
461 'type': pt_l4,
462 'punt': {
463 'l4': {
464 'af': af_ip6,
465 'protocol': udp_proto
466 }
467 }
468 }
469
470 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100471 self.assertEqual(len(punts), 0)
472
473 #
474 # configure a punt socket
475 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700476 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200477 "%s/socket_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700478 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
Ole Troan9cd8f332019-10-18 15:57:56 +0200479 "%s/socket_2222" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700480 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100481 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700482 self.verify_port(set_port(punt_l4, 1111), punts[0])
483 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100484
485 #
486 # deregister a punt socket
487 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700488 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
489 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100490 self.assertEqual(len(punts), 1)
491
492 #
493 # configure a punt socket again
494 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700495 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200496 "%s/socket_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700497 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100498 self.assertEqual(len(punts), 2)
499
500 #
501 # deregister all punt socket
502 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700503 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
504 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
505 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
506 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100507 self.assertEqual(len(punts), 0)
508
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100509 def test_punt_socket_traffic_single_port_single_socket(self):
510 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100511
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100512 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700513 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
514 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
515 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
516 punt_l4 = {
517 'type': pt_l4,
518 'punt': {
519 'l4': {
520 'af': af_ip6,
521 'protocol': udp_proto,
522 'port': port,
523 }
524 }
525 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100526
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100527 p = (Ether(src=self.pg0.remote_mac,
528 dst=self.pg0.local_mac) /
529 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100530 inet6.UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200531 Raw(b'\xa5' * 100))
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100532
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100533 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100534
Neale Ranns50f0ac02019-05-15 02:13:37 -0700535 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100536 self.assertEqual(len(punts), 0)
537
538 #
539 # expect ICMPv6 - destination unreachable for all packets
540 #
541 self.vapi.cli("clear trace")
542 self.pg0.add_stream(pkts)
543 self.pg_enable_capture(self.pg_interfaces)
544 self.pg_start()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100545 # FIXME - when punt socket deregister is implemented
546 # rx = self.pg0.get_capture(self.nr_packets)
547 # for p in rx:
548 # self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
549 # self.assertEqual(int(p[ICMPv6DestUnreach].code),4) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100550
551 #
552 # configure a punt socket
553 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200554 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
555 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" %
556 (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700557 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100558 self.assertEqual(len(punts), 1)
559
560 #
561 # expect punt socket and no packets on pg0
562 #
563 self.vapi.cli("clear errors")
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100564 self.vapi.cli("clear trace")
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100565 self.pg0.add_stream(pkts)
566 self.pg_enable_capture(self.pg_interfaces)
567 self.pg_start()
568 self.pg0.get_capture(0)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100569 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700570 rx = self.socket_client_close()
571 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100572
573 #
574 # remove punt socket. expect ICMP - dest. unreachable for all packets
575 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700576 self.vapi.punt_socket_deregister(punt_l4)
577 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100578 self.assertEqual(len(punts), 0)
579 self.pg0.add_stream(pkts)
580 self.pg_enable_capture(self.pg_interfaces)
581 self.pg_start()
582 # FIXME - when punt socket deregister is implemented
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100583 # self.pg0.get_capture(nr_packets)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100584
Neale Ranns50f0ac02019-05-15 02:13:37 -0700585 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100586 """ Punt socket traffic multi ports and multi sockets"""
587
Neale Ranns50f0ac02019-05-15 02:13:37 -0700588 punt_l4 = mk_vpp_cfg6()
589
590 # configuration for each UDP port
591 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100592
593 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700594 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100595 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700596 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100597 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700598 cfgs[port] = {}
599
600 pkt = (Ether(src=self.pg0.remote_mac,
601 dst=self.pg0.local_mac) /
602 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
603 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200604 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700605 cfgs[port]['pkts'] = pkt * self.nr_packets
606 cfgs[port]['port'] = port
607 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
608
609 # configure punt sockets
610 cfgs[port]['sock'] = self.socket_client_create(
Ole Troan9cd8f332019-10-18 15:57:56 +0200611 "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700612 self.vapi.punt_socket_register(
613 cfgs[port]['vpp'],
Ole Troan9cd8f332019-10-18 15:57:56 +0200614 "%s/socket_%d" % (self.tempdir, port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100615
616 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700617 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100618 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700619 for cfg in cfgs.values():
620 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100621
622 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700623 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100624 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700625 for cfg in cfgs.values():
626 rx = cfg['sock'].close()
627 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
628 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100629
630 def test_punt_socket_traffic_multi_ports_single_socket(self):
631 """ Punt socket traffic multi ports and single socket"""
632
Neale Ranns50f0ac02019-05-15 02:13:37 -0700633 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
634 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
635 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
636 punt_l4 = {
637 'type': pt_l4,
638 'punt': {
639 'l4': {
640 'af': af_ip6,
641 'protocol': udp_proto,
642 }
643 }
644 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100645
646 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700647 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100648 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700649 pkts = []
650 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100651 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700652 pkt = (Ether(src=self.pg0.remote_mac,
653 dst=self.pg0.local_mac) /
654 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
655 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200656 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700657 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100658
659 #
660 # no punt socket
661 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700662 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100663 self.assertEqual(len(punts), 0)
664
665 #
666 # configure a punt socket
667 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200668 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100669 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700670 self.vapi.punt_socket_register(set_port(punt_l4, p),
Ole Troan9cd8f332019-10-18 15:57:56 +0200671 "%s/socket_multi" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700672 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100673 self.assertEqual(len(punts), len(self.ports))
674
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100675 #
676 # expect punt socket and no packets on pg0
677 #
678 self.vapi.cli("clear errors")
679 self.vapi.cli("clear trace")
680 self.pg0.add_stream(pkts)
681 self.pg_enable_capture(self.pg_interfaces)
682 self.pg_start()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +0000683 # give a chance to punt socket to collect all packets
684 self.sleep(1)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100685 self.pg0.get_capture(0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700686 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100687
688 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700689 self.verify_udp_pkts(rx, self.nr_packets, p)
690 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
691 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100692 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100693
Neale Ranns76b56492018-09-28 15:16:14 +0000694
Neale Ranns50f0ac02019-05-15 02:13:37 -0700695class TestExceptionPuntSocket(TestPuntSocket):
696 """ Punt Socket for Exceptions """
697
698 @classmethod
699 def setUpClass(cls):
700 super(TestExceptionPuntSocket, cls).setUpClass()
701
702 @classmethod
703 def tearDownClass(cls):
704 super(TestExceptionPuntSocket, cls).tearDownClass()
705
706 def setUp(self):
707 super(TestExceptionPuntSocket, self).setUp()
708
Neale Ranns12989b52019-09-26 16:20:19 +0000709 self.create_pg_interfaces(range(2))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700710 for i in self.pg_interfaces:
711 i.config_ip4()
712 i.resolve_arp()
713
714 def tearDown(self):
715 super(TestExceptionPuntSocket, self).tearDown()
716 for i in self.pg_interfaces:
717 i.unconfig_ip4()
718 i.admin_down()
719
720 def test_registration(self):
721 """ Punt socket registration/deregistration"""
722
723 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
724
725 punts = self.vapi.punt_socket_dump(type=pt_ex)
726 self.assertEqual(len(punts), 0)
727
728 #
729 # configure a punt socket
730 #
731 punt_ex = {
732 'type': pt_ex,
733 'punt': {
734 'exception': {}
735 }
736 }
737
738 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
Ole Troan9cd8f332019-10-18 15:57:56 +0200739 "%s/socket_punt_1" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700740 self.vapi.punt_socket_register(set_reason(punt_ex, 2),
Ole Troan9cd8f332019-10-18 15:57:56 +0200741 "%s/socket_punt_2" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700742 punts = self.vapi.punt_socket_dump(type=pt_ex)
743 self.assertEqual(len(punts), 2)
744 self.verify_exception(set_reason(punt_ex, 1), punts[0])
745 self.verify_exception(set_reason(punt_ex, 2), punts[1])
746
747 #
748 # deregister a punt socket
749 #
750 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
751 punts = self.vapi.punt_socket_dump(type=pt_ex)
752 self.assertEqual(len(punts), 1)
753
754 #
755 # configure a punt socket again
756 #
757 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
Ole Troan9cd8f332019-10-18 15:57:56 +0200758 "%s/socket_punt_1" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700759 self.vapi.punt_socket_register(set_reason(punt_ex, 3),
Ole Troan9cd8f332019-10-18 15:57:56 +0200760 "%s/socket_punt_3" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700761 punts = self.vapi.punt_socket_dump(type=pt_ex)
762 self.assertEqual(len(punts), 3)
763
764 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
765
766 #
767 # deregister all punt socket
768 #
769 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
770 self.vapi.punt_socket_deregister(set_reason(punt_ex, 2))
771 self.vapi.punt_socket_deregister(set_reason(punt_ex, 3))
772 punts = self.vapi.punt_socket_dump(type=pt_ex)
773 self.assertEqual(len(punts), 0)
774
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700775 def verify_esp_pkts(self, rxs, n_sent, spi, has_udp):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700776 self.assertEqual(len(rxs), n_sent)
777 for rx in rxs:
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700778 self.assertTrue(rx.haslayer(IP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700779 self.assertTrue(rx.haslayer(ESP))
780 self.assertEqual(rx[ESP].spi, spi)
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700781 if has_udp:
782 self.assertTrue(rx.haslayer(UDP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700783
784 def test_traffic(self):
785 """ Punt socket traffic """
786
787 port = self.ports[0]
788 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
789 punt_ex = {
790 'type': pt_ex,
791 'punt': {
792 'exception': {}
793 }
794 }
795
796 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700797 # we're dealing with IPSec tunnels punting for no-such-tunnel
Filip Tehlar4362baa2020-04-02 13:13:39 +0000798 # (SPI=0 goes to ikev2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700799 #
800 cfgs = dict()
Neale Ranns12989b52019-09-26 16:20:19 +0000801 cfgs['ipsec4-no-such-tunnel'] = {'spi': 99,
802 'udp': False,
803 'itf': self.pg0}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700804
805 #
806 # find the VPP ID for these punt exception reasin
807 #
808 rs = self.vapi.punt_reason_dump()
809 for key in cfgs:
810 for r in rs:
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100811 print(r.reason.name)
812 print(key)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700813 if r.reason.name == key:
814 cfgs[key]['id'] = r.reason.id
815 cfgs[key]['vpp'] = copy.deepcopy(
816 set_reason(punt_ex,
817 cfgs[key]['id']))
818 break
819
820 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700821 # configure punt sockets
Neale Ranns50f0ac02019-05-15 02:13:37 -0700822 #
823 for cfg in cfgs.values():
Ole Troan9cd8f332019-10-18 15:57:56 +0200824 cfg['sock'] = self.socket_client_create("%s/socket_%d" %
825 (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700826 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +0200827 cfg['vpp'], "%s/socket_%d" % (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700828
829 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700830 # create packet streams for 'no-such-tunnel' exception
831 #
832 for cfg in cfgs.values():
Neale Ranns12989b52019-09-26 16:20:19 +0000833 pkt = (Ether(src=cfg['itf'].remote_mac,
834 dst=cfg['itf'].local_mac) /
835 IP(src=cfg['itf'].remote_ip4,
836 dst=cfg['itf'].local_ip4))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700837 if (cfg['udp']):
838 pkt = pkt / UDP(sport=666, dport=4500)
839 pkt = (pkt / ESP(spi=cfg['spi'], seq=3) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200840 Raw(b'\xa5' * 100))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700841 cfg['pkts'] = [pkt]
842
843 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700844 # send packets for each SPI we expect to be punted
845 #
846 for cfg in cfgs.values():
Neale Ranns12989b52019-09-26 16:20:19 +0000847 self.send_and_assert_no_replies(cfg['itf'], cfg['pkts'])
Neale Ranns50f0ac02019-05-15 02:13:37 -0700848
849 #
850 # verify the punted packets arrived on the associated socket
851 #
852 for cfg in cfgs.values():
853 rx = cfg['sock'].close()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700854 self.verify_esp_pkts(rx, len(cfg['pkts']),
855 cfg['spi'], cfg['udp'])
856
857 #
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000858 # add some tunnels, make sure it still punts
859 #
Neale Rannsa9e27742020-12-23 16:22:28 +0000860 tun = VppIpsecInterface(self).add_vpp_config()
861 sa_in = VppIpsecSA(self, 11, 11,
862 (VppEnum.vl_api_ipsec_integ_alg_t.
863 IPSEC_API_INTEG_ALG_SHA1_96),
864 b"0123456701234567",
865 (VppEnum.vl_api_ipsec_crypto_alg_t.
866 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
867 b"0123456701234567",
868 50,
869 self.pg0.local_ip4,
870 self.pg0.remote_ip4).add_vpp_config()
871 sa_out = VppIpsecSA(self, 22, 22,
872 (VppEnum.vl_api_ipsec_integ_alg_t.
873 IPSEC_API_INTEG_ALG_SHA1_96),
874 b"0123456701234567",
875 (VppEnum.vl_api_ipsec_crypto_alg_t.
876 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
877 b"0123456701234567",
878 50,
879 self.pg0.local_ip4,
880 self.pg0.remote_ip4).add_vpp_config()
881 protect = VppIpsecTunProtect(self, tun,
882 sa_out,
883 [sa_in]).add_vpp_config()
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000884
885 #
886 # send packets for each SPI we expect to be punted
887 #
888 for cfg in cfgs.values():
889 self.send_and_assert_no_replies(cfg['itf'], cfg['pkts'])
890
891 #
892 # verify the punted packets arrived on the associated socket
893 #
894 for cfg in cfgs.values():
895 rx = cfg['sock'].close()
896 self.verify_esp_pkts(rx, len(cfg['pkts']),
897 cfg['spi'], cfg['udp'])
898 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700899 # socket deregister
900 #
901 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700902 self.vapi.punt_socket_deregister(cfg['vpp'])
903
904
Neale Rannsb538dd82019-05-21 06:54:54 -0700905class TestIpProtoPuntSocket(TestPuntSocket):
906 """ Punt Socket for IP packets """
907
908 @classmethod
909 def setUpClass(cls):
910 super(TestIpProtoPuntSocket, cls).setUpClass()
911
912 @classmethod
913 def tearDownClass(cls):
914 super(TestIpProtoPuntSocket, cls).tearDownClass()
915
916 def setUp(self):
917 super(TestIpProtoPuntSocket, self).setUp()
918
919 for i in self.pg_interfaces:
920 i.config_ip4()
921 i.resolve_arp()
922
923 def tearDown(self):
924 super(TestIpProtoPuntSocket, self).tearDown()
925 for i in self.pg_interfaces:
926 i.unconfig_ip4()
927 i.admin_down()
928
929 def test_registration(self):
930 """ Punt socket registration/deregistration"""
931
932 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
933 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
934 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
935 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
936
937 punts = self.vapi.punt_socket_dump(type=pt_ip)
938 self.assertEqual(len(punts), 0)
939
940 #
941 # configure a punt socket
942 #
943 punt_ospf = {
944 'type': pt_ip,
945 'punt': {
946 'ip_proto': {
947 'af': af_ip4,
948 'protocol': proto_ospf
949 }
950 }
951 }
952 punt_eigrp = {
953 'type': pt_ip,
954 'punt': {
955 'ip_proto': {
956 'af': af_ip4,
957 'protocol': proto_eigrp
958 }
959 }
960 }
961
962 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200963 "%s/socket_punt_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700964 self.vapi.punt_socket_register(punt_eigrp,
Ole Troan9cd8f332019-10-18 15:57:56 +0200965 "%s/socket_punt_2" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700966 self.logger.info(self.vapi.cli("sh punt sock reg ip"))
967 punts = self.vapi.punt_socket_dump(type=pt_ip)
968 self.assertEqual(len(punts), 2)
969 self.verify_ip_proto(punt_ospf, punts[0])
970 self.verify_ip_proto(punt_eigrp, punts[1])
971
972 #
973 # deregister a punt socket
974 #
975 self.vapi.punt_socket_deregister(punt_ospf)
976 punts = self.vapi.punt_socket_dump(type=pt_ip)
977 self.assertEqual(len(punts), 1)
978
979 #
980 # configure a punt socket again
981 #
982 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200983 "%s/socket_punt_3" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700984 punts = self.vapi.punt_socket_dump(type=pt_ip)
985 self.assertEqual(len(punts), 2)
986
987 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
988
989 #
990 # deregister all punt socket
991 #
992 self.vapi.punt_socket_deregister(punt_eigrp)
993 self.vapi.punt_socket_deregister(punt_ospf)
994 punts = self.vapi.punt_socket_dump(type=pt_ip)
995 self.assertEqual(len(punts), 0)
996
997 def verify_ospf_pkts(self, rxs, n_sent):
998 self.assertEqual(len(rxs), n_sent)
999 for rx in rxs:
1000 self.assertTrue(rx.haslayer(OSPF_Hdr))
1001
1002 def test_traffic(self):
1003 """ Punt socket traffic """
1004
1005 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1006 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
1007 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
1008
1009 #
1010 # configure a punt socket to capture OSPF packets
1011 #
1012 punt_ospf = {
1013 'type': pt_ip,
1014 'punt': {
1015 'ip_proto': {
1016 'af': af_ip4,
1017 'protocol': proto_ospf
1018 }
1019 }
1020 }
1021
1022 #
1023 # create packet streams and configure a punt sockets
1024 #
1025 pkt = (Ether(src=self.pg0.remote_mac,
1026 dst=self.pg0.local_mac) /
1027 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1028 OSPF_Hdr() /
1029 OSPFv3_Hello())
1030 pkts = pkt * 7
1031
Ole Troan9cd8f332019-10-18 15:57:56 +02001032 sock = self.socket_client_create("%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001033 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +02001034 punt_ospf, "%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001035
1036 #
1037 # send packets for each SPI we expect to be punted
1038 #
1039 self.send_and_assert_no_replies(self.pg0, pkts)
1040
1041 #
1042 # verify the punted packets arrived on the associated socket
1043 #
1044 rx = sock.close()
1045 self.verify_ospf_pkts(rx, len(pkts))
1046 self.vapi.punt_socket_deregister(punt_ospf)
1047
1048
Neale Ranns76b56492018-09-28 15:16:14 +00001049class TestPunt(VppTestCase):
Neale Rannsb538dd82019-05-21 06:54:54 -07001050 """ Exception Punt Test Case """
Neale Ranns76b56492018-09-28 15:16:14 +00001051
1052 @classmethod
1053 def setUpClass(cls):
1054 super(TestPunt, cls).setUpClass()
1055
1056 @classmethod
1057 def tearDownClass(cls):
1058 super(TestPunt, cls).tearDownClass()
1059
1060 def setUp(self):
1061 super(TestPunt, self).setUp()
1062
1063 self.create_pg_interfaces(range(4))
1064
1065 for i in self.pg_interfaces:
1066 i.admin_up()
1067 i.config_ip4()
1068 i.resolve_arp()
1069 i.config_ip6()
1070 i.resolve_ndp()
1071
1072 def tearDown(self):
1073 for i in self.pg_interfaces:
1074 i.unconfig_ip4()
1075 i.unconfig_ip6()
Neale Ranns76b56492018-09-28 15:16:14 +00001076 i.admin_down()
1077 super(TestPunt, self).tearDown()
1078
1079 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -07001080 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +00001081
1082 #
Neale Ranns719beb72019-07-10 07:10:25 +00001083 # dump the punt registered reasons
1084 # search for a few we know should be there
1085 #
1086 rs = self.vapi.punt_reason_dump()
1087
1088 reasons = ["ipsec6-no-such-tunnel",
1089 "ipsec4-no-such-tunnel",
1090 "ipsec4-spi-o-udp-0"]
1091
1092 for reason in reasons:
1093 found = False
1094 for r in rs:
1095 if r.reason.name == reason:
1096 found = True
1097 break
1098 self.assertTrue(found)
1099
1100 #
Neale Ranns76b56492018-09-28 15:16:14 +00001101 # Using the test CLI we will hook in a exception path to
1102 # send ACL deny packets out of pg0 and pg1.
1103 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1104 #
1105 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1106 [VppRoutePath(self.pg3.remote_ip4,
1107 self.pg3.sw_if_index)])
1108 ip_1_1_1_2.add_vpp_config()
1109 ip_1_2 = VppIpRoute(self, "1::2", 128,
1110 [VppRoutePath(self.pg3.remote_ip6,
1111 self.pg3.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001112 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns76b56492018-09-28 15:16:14 +00001113 ip_1_2.add_vpp_config()
1114
1115 p4 = (Ether(src=self.pg2.remote_mac,
1116 dst=self.pg2.local_mac) /
1117 IP(src="1.1.1.1", dst="1.1.1.2") /
1118 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001119 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001120 p6 = (Ether(src=self.pg2.remote_mac,
1121 dst=self.pg2.local_mac) /
1122 IPv6(src="1::1", dst="1::2") /
1123 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001124 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001125 self.send_and_expect(self.pg2, p4*1, self.pg3)
1126 self.send_and_expect(self.pg2, p6*1, self.pg3)
1127
1128 #
1129 # apply the punting features
1130 #
1131 self.vapi.cli("test punt pg2")
1132
1133 #
Neale Ranns719beb72019-07-10 07:10:25 +00001134 # dump the punt reasons to learn the IDs assigned
1135 #
1136 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v4"})
1137 r4 = rs[0].reason.id
1138 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v6"})
1139 r6 = rs[0].reason.id
1140
1141 #
Neale Ranns76b56492018-09-28 15:16:14 +00001142 # pkts now dropped
1143 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001144 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
1145 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001146
1147 #
1148 # Check state:
1149 # 1 - node error counters
1150 # 2 - per-reason counters
1151 # 2, 3 are the index of the assigned punt reason
1152 #
Ole Troan233e4682019-05-16 15:01:34 +02001153 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +00001154 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001155 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001156
1157 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001158 self.assertEqual(stats[0][r4]['packets'], NUM_PKTS)
1159 self.assertEqual(stats[0][r6]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001160
1161 #
1162 # use the test CLI to test a client that punts exception
1163 # packets out of pg0
1164 #
1165 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1166 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1167
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001168 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
1169 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001170
1171 #
1172 # check the packets come out IP unmodified but destined to pg0 host
1173 #
1174 for rx in rx4s:
1175 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1176 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1177 self.assertEqual(p4[IP].dst, rx[IP].dst)
1178 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1179 for rx in rx6s:
1180 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1181 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1182 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1183 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1184
1185 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001186 self.assertEqual(stats[0][r4]['packets'], 2*NUM_PKTS)
1187 self.assertEqual(stats[0][r6]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001188
1189 #
1190 # add another registration for the same reason to send packets
1191 # out of pg1
1192 #
1193 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1194 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1195
1196 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001197 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001198 self.pg_enable_capture(self.pg_interfaces)
1199 self.pg_start()
1200
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001201 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001202 for rx in rxd:
1203 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1204 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1205 self.assertEqual(p4[IP].dst, rx[IP].dst)
1206 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001207 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001208 for rx in rxd:
1209 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1210 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1211 self.assertEqual(p4[IP].dst, rx[IP].dst)
1212 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1213
1214 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001215 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001216 self.pg_enable_capture(self.pg_interfaces)
1217 self.pg_start()
1218
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001219 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001220 for rx in rxd:
1221 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1222 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1223 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1224 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001225 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001226 for rx in rxd:
1227 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1228 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1229 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1230 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1231
1232 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001233 self.assertEqual(stats[0][r4]['packets'], 3*NUM_PKTS)
1234 self.assertEqual(stats[0][r6]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001235
1236 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1237 self.logger.info(self.vapi.cli("show punt client"))
1238 self.logger.info(self.vapi.cli("show punt reason"))
1239 self.logger.info(self.vapi.cli("show punt stats"))
1240 self.logger.info(self.vapi.cli("show punt db"))
1241
Neale Ranns76b56492018-09-28 15:16:14 +00001242
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001243if __name__ == '__main__':
1244 unittest.main(testRunner=VppTestRunner)