blob: 8ebf44767f3e1ba5d61ec4dec4f9ea0da722ebee [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 Ranns50f0ac02019-05-15 02:13:37 -070033from vpp_papi import VppEnum
34from vpp_ipsec_tun_interface import VppIpsecTunInterface
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
798 # adn SPI=0
799 #
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}
804 cfgs['ipsec4-spi-o-udp-0'] = {'spi': 0,
805 'udp': True,
806 'itf': self.pg1}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700807
808 #
809 # find the VPP ID for these punt exception reasin
810 #
811 rs = self.vapi.punt_reason_dump()
812 for key in cfgs:
813 for r in rs:
814 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 #
861 VppIpsecTunInterface(self, self.pg0, 1000, 1000,
862 (VppEnum.vl_api_ipsec_crypto_alg_t.
863 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
864 b"0123456701234567",
865 b"0123456701234567",
866 (VppEnum.vl_api_ipsec_integ_alg_t.
867 IPSEC_API_INTEG_ALG_SHA1_96),
868 b"0123456701234567",
869 b"0123456701234567").add_vpp_config()
870 VppIpsecTunInterface(self, self.pg1, 1000, 1000,
871 (VppEnum.vl_api_ipsec_crypto_alg_t.
872 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
873 b"0123456701234567",
874 b"0123456701234567",
875 (VppEnum.vl_api_ipsec_integ_alg_t.
876 IPSEC_API_INTEG_ALG_SHA1_96),
877 b"0123456701234567",
878 b"0123456701234567",
879 udp_encap=True).add_vpp_config()
880
881 #
882 # send packets for each SPI we expect to be punted
883 #
884 for cfg in cfgs.values():
885 self.send_and_assert_no_replies(cfg['itf'], cfg['pkts'])
886
887 #
888 # verify the punted packets arrived on the associated socket
889 #
890 for cfg in cfgs.values():
891 rx = cfg['sock'].close()
892 self.verify_esp_pkts(rx, len(cfg['pkts']),
893 cfg['spi'], cfg['udp'])
894 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700895 # socket deregister
896 #
897 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700898 self.vapi.punt_socket_deregister(cfg['vpp'])
899
900
Neale Rannsb538dd82019-05-21 06:54:54 -0700901class TestIpProtoPuntSocket(TestPuntSocket):
902 """ Punt Socket for IP packets """
903
904 @classmethod
905 def setUpClass(cls):
906 super(TestIpProtoPuntSocket, cls).setUpClass()
907
908 @classmethod
909 def tearDownClass(cls):
910 super(TestIpProtoPuntSocket, cls).tearDownClass()
911
912 def setUp(self):
913 super(TestIpProtoPuntSocket, self).setUp()
914
915 for i in self.pg_interfaces:
916 i.config_ip4()
917 i.resolve_arp()
918
919 def tearDown(self):
920 super(TestIpProtoPuntSocket, self).tearDown()
921 for i in self.pg_interfaces:
922 i.unconfig_ip4()
923 i.admin_down()
924
925 def test_registration(self):
926 """ Punt socket registration/deregistration"""
927
928 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
929 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
930 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
931 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
932
933 punts = self.vapi.punt_socket_dump(type=pt_ip)
934 self.assertEqual(len(punts), 0)
935
936 #
937 # configure a punt socket
938 #
939 punt_ospf = {
940 'type': pt_ip,
941 'punt': {
942 'ip_proto': {
943 'af': af_ip4,
944 'protocol': proto_ospf
945 }
946 }
947 }
948 punt_eigrp = {
949 'type': pt_ip,
950 'punt': {
951 'ip_proto': {
952 'af': af_ip4,
953 'protocol': proto_eigrp
954 }
955 }
956 }
957
958 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200959 "%s/socket_punt_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700960 self.vapi.punt_socket_register(punt_eigrp,
Ole Troan9cd8f332019-10-18 15:57:56 +0200961 "%s/socket_punt_2" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700962 self.logger.info(self.vapi.cli("sh punt sock reg ip"))
963 punts = self.vapi.punt_socket_dump(type=pt_ip)
964 self.assertEqual(len(punts), 2)
965 self.verify_ip_proto(punt_ospf, punts[0])
966 self.verify_ip_proto(punt_eigrp, punts[1])
967
968 #
969 # deregister a punt socket
970 #
971 self.vapi.punt_socket_deregister(punt_ospf)
972 punts = self.vapi.punt_socket_dump(type=pt_ip)
973 self.assertEqual(len(punts), 1)
974
975 #
976 # configure a punt socket again
977 #
978 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200979 "%s/socket_punt_3" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700980 punts = self.vapi.punt_socket_dump(type=pt_ip)
981 self.assertEqual(len(punts), 2)
982
983 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
984
985 #
986 # deregister all punt socket
987 #
988 self.vapi.punt_socket_deregister(punt_eigrp)
989 self.vapi.punt_socket_deregister(punt_ospf)
990 punts = self.vapi.punt_socket_dump(type=pt_ip)
991 self.assertEqual(len(punts), 0)
992
993 def verify_ospf_pkts(self, rxs, n_sent):
994 self.assertEqual(len(rxs), n_sent)
995 for rx in rxs:
996 self.assertTrue(rx.haslayer(OSPF_Hdr))
997
998 def test_traffic(self):
999 """ Punt socket traffic """
1000
1001 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1002 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
1003 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
1004
1005 #
1006 # configure a punt socket to capture OSPF packets
1007 #
1008 punt_ospf = {
1009 'type': pt_ip,
1010 'punt': {
1011 'ip_proto': {
1012 'af': af_ip4,
1013 'protocol': proto_ospf
1014 }
1015 }
1016 }
1017
1018 #
1019 # create packet streams and configure a punt sockets
1020 #
1021 pkt = (Ether(src=self.pg0.remote_mac,
1022 dst=self.pg0.local_mac) /
1023 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1024 OSPF_Hdr() /
1025 OSPFv3_Hello())
1026 pkts = pkt * 7
1027
Ole Troan9cd8f332019-10-18 15:57:56 +02001028 sock = self.socket_client_create("%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001029 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +02001030 punt_ospf, "%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001031
1032 #
1033 # send packets for each SPI we expect to be punted
1034 #
1035 self.send_and_assert_no_replies(self.pg0, pkts)
1036
1037 #
1038 # verify the punted packets arrived on the associated socket
1039 #
1040 rx = sock.close()
1041 self.verify_ospf_pkts(rx, len(pkts))
1042 self.vapi.punt_socket_deregister(punt_ospf)
1043
1044
Neale Ranns76b56492018-09-28 15:16:14 +00001045class TestPunt(VppTestCase):
Neale Rannsb538dd82019-05-21 06:54:54 -07001046 """ Exception Punt Test Case """
Neale Ranns76b56492018-09-28 15:16:14 +00001047
1048 @classmethod
1049 def setUpClass(cls):
1050 super(TestPunt, cls).setUpClass()
1051
1052 @classmethod
1053 def tearDownClass(cls):
1054 super(TestPunt, cls).tearDownClass()
1055
1056 def setUp(self):
1057 super(TestPunt, self).setUp()
1058
1059 self.create_pg_interfaces(range(4))
1060
1061 for i in self.pg_interfaces:
1062 i.admin_up()
1063 i.config_ip4()
1064 i.resolve_arp()
1065 i.config_ip6()
1066 i.resolve_ndp()
1067
1068 def tearDown(self):
1069 for i in self.pg_interfaces:
1070 i.unconfig_ip4()
1071 i.unconfig_ip6()
Neale Ranns76b56492018-09-28 15:16:14 +00001072 i.admin_down()
1073 super(TestPunt, self).tearDown()
1074
1075 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -07001076 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +00001077
1078 #
Neale Ranns719beb72019-07-10 07:10:25 +00001079 # dump the punt registered reasons
1080 # search for a few we know should be there
1081 #
1082 rs = self.vapi.punt_reason_dump()
1083
1084 reasons = ["ipsec6-no-such-tunnel",
1085 "ipsec4-no-such-tunnel",
1086 "ipsec4-spi-o-udp-0"]
1087
1088 for reason in reasons:
1089 found = False
1090 for r in rs:
1091 if r.reason.name == reason:
1092 found = True
1093 break
1094 self.assertTrue(found)
1095
1096 #
Neale Ranns76b56492018-09-28 15:16:14 +00001097 # Using the test CLI we will hook in a exception path to
1098 # send ACL deny packets out of pg0 and pg1.
1099 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1100 #
1101 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1102 [VppRoutePath(self.pg3.remote_ip4,
1103 self.pg3.sw_if_index)])
1104 ip_1_1_1_2.add_vpp_config()
1105 ip_1_2 = VppIpRoute(self, "1::2", 128,
1106 [VppRoutePath(self.pg3.remote_ip6,
1107 self.pg3.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001108 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns76b56492018-09-28 15:16:14 +00001109 ip_1_2.add_vpp_config()
1110
1111 p4 = (Ether(src=self.pg2.remote_mac,
1112 dst=self.pg2.local_mac) /
1113 IP(src="1.1.1.1", dst="1.1.1.2") /
1114 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001115 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001116 p6 = (Ether(src=self.pg2.remote_mac,
1117 dst=self.pg2.local_mac) /
1118 IPv6(src="1::1", dst="1::2") /
1119 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001120 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001121 self.send_and_expect(self.pg2, p4*1, self.pg3)
1122 self.send_and_expect(self.pg2, p6*1, self.pg3)
1123
1124 #
1125 # apply the punting features
1126 #
1127 self.vapi.cli("test punt pg2")
1128
1129 #
Neale Ranns719beb72019-07-10 07:10:25 +00001130 # dump the punt reasons to learn the IDs assigned
1131 #
1132 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v4"})
1133 r4 = rs[0].reason.id
1134 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v6"})
1135 r6 = rs[0].reason.id
1136
1137 #
Neale Ranns76b56492018-09-28 15:16:14 +00001138 # pkts now dropped
1139 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001140 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
1141 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001142
1143 #
1144 # Check state:
1145 # 1 - node error counters
1146 # 2 - per-reason counters
1147 # 2, 3 are the index of the assigned punt reason
1148 #
Ole Troan233e4682019-05-16 15:01:34 +02001149 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +00001150 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001151 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001152
1153 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001154 self.assertEqual(stats[0][r4]['packets'], NUM_PKTS)
1155 self.assertEqual(stats[0][r6]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001156
1157 #
1158 # use the test CLI to test a client that punts exception
1159 # packets out of pg0
1160 #
1161 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1162 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1163
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001164 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
1165 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001166
1167 #
1168 # check the packets come out IP unmodified but destined to pg0 host
1169 #
1170 for rx in rx4s:
1171 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1172 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1173 self.assertEqual(p4[IP].dst, rx[IP].dst)
1174 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1175 for rx in rx6s:
1176 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1177 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1178 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1179 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1180
1181 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001182 self.assertEqual(stats[0][r4]['packets'], 2*NUM_PKTS)
1183 self.assertEqual(stats[0][r6]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001184
1185 #
1186 # add another registration for the same reason to send packets
1187 # out of pg1
1188 #
1189 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1190 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1191
1192 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001193 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001194 self.pg_enable_capture(self.pg_interfaces)
1195 self.pg_start()
1196
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001197 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001198 for rx in rxd:
1199 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1200 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1201 self.assertEqual(p4[IP].dst, rx[IP].dst)
1202 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001203 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001204 for rx in rxd:
1205 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1206 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1207 self.assertEqual(p4[IP].dst, rx[IP].dst)
1208 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1209
1210 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001211 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001212 self.pg_enable_capture(self.pg_interfaces)
1213 self.pg_start()
1214
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001215 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001216 for rx in rxd:
1217 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1218 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1219 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1220 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001221 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001222 for rx in rxd:
1223 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1224 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1225 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1226 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1227
1228 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001229 self.assertEqual(stats[0][r4]['packets'], 3*NUM_PKTS)
1230 self.assertEqual(stats[0][r6]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001231
1232 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1233 self.logger.info(self.vapi.cli("show punt client"))
1234 self.logger.info(self.vapi.cli("show punt reason"))
1235 self.logger.info(self.vapi.cli("show punt stats"))
1236 self.logger.info(self.vapi.cli("show punt db"))
1237
Neale Ranns76b56492018-09-28 15:16:14 +00001238
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001239if __name__ == '__main__':
1240 unittest.main(testRunner=VppTestRunner)