blob: ecd34f6eea7a315962fdcf7b2c0a355e3400cd7d [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:
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100814 print(r.reason.name)
815 print(key)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700816 if r.reason.name == key:
817 cfgs[key]['id'] = r.reason.id
818 cfgs[key]['vpp'] = copy.deepcopy(
819 set_reason(punt_ex,
820 cfgs[key]['id']))
821 break
822
823 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700824 # configure punt sockets
Neale Ranns50f0ac02019-05-15 02:13:37 -0700825 #
826 for cfg in cfgs.values():
Ole Troan9cd8f332019-10-18 15:57:56 +0200827 cfg['sock'] = self.socket_client_create("%s/socket_%d" %
828 (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700829 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +0200830 cfg['vpp'], "%s/socket_%d" % (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700831
832 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700833 # create packet streams for 'no-such-tunnel' exception
834 #
835 for cfg in cfgs.values():
Neale Ranns12989b52019-09-26 16:20:19 +0000836 pkt = (Ether(src=cfg['itf'].remote_mac,
837 dst=cfg['itf'].local_mac) /
838 IP(src=cfg['itf'].remote_ip4,
839 dst=cfg['itf'].local_ip4))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700840 if (cfg['udp']):
841 pkt = pkt / UDP(sport=666, dport=4500)
842 pkt = (pkt / ESP(spi=cfg['spi'], seq=3) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200843 Raw(b'\xa5' * 100))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700844 cfg['pkts'] = [pkt]
845
846 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700847 # send packets for each SPI we expect to be punted
848 #
849 for cfg in cfgs.values():
Neale Ranns12989b52019-09-26 16:20:19 +0000850 self.send_and_assert_no_replies(cfg['itf'], cfg['pkts'])
Neale Ranns50f0ac02019-05-15 02:13:37 -0700851
852 #
853 # verify the punted packets arrived on the associated socket
854 #
855 for cfg in cfgs.values():
856 rx = cfg['sock'].close()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700857 self.verify_esp_pkts(rx, len(cfg['pkts']),
858 cfg['spi'], cfg['udp'])
859
860 #
Neale Ranns8d6d74c2020-02-20 09:45:16 +0000861 # add some tunnels, make sure it still punts
862 #
863 VppIpsecTunInterface(self, self.pg0, 1000, 1000,
864 (VppEnum.vl_api_ipsec_crypto_alg_t.
865 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
866 b"0123456701234567",
867 b"0123456701234567",
868 (VppEnum.vl_api_ipsec_integ_alg_t.
869 IPSEC_API_INTEG_ALG_SHA1_96),
870 b"0123456701234567",
871 b"0123456701234567").add_vpp_config()
872 VppIpsecTunInterface(self, self.pg1, 1000, 1000,
873 (VppEnum.vl_api_ipsec_crypto_alg_t.
874 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
875 b"0123456701234567",
876 b"0123456701234567",
877 (VppEnum.vl_api_ipsec_integ_alg_t.
878 IPSEC_API_INTEG_ALG_SHA1_96),
879 b"0123456701234567",
880 b"0123456701234567",
881 udp_encap=True).add_vpp_config()
882
883 #
884 # send packets for each SPI we expect to be punted
885 #
886 for cfg in cfgs.values():
887 self.send_and_assert_no_replies(cfg['itf'], cfg['pkts'])
888
889 #
890 # verify the punted packets arrived on the associated socket
891 #
892 for cfg in cfgs.values():
893 rx = cfg['sock'].close()
894 self.verify_esp_pkts(rx, len(cfg['pkts']),
895 cfg['spi'], cfg['udp'])
896 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700897 # socket deregister
898 #
899 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700900 self.vapi.punt_socket_deregister(cfg['vpp'])
901
902
Neale Rannsb538dd82019-05-21 06:54:54 -0700903class TestIpProtoPuntSocket(TestPuntSocket):
904 """ Punt Socket for IP packets """
905
906 @classmethod
907 def setUpClass(cls):
908 super(TestIpProtoPuntSocket, cls).setUpClass()
909
910 @classmethod
911 def tearDownClass(cls):
912 super(TestIpProtoPuntSocket, cls).tearDownClass()
913
914 def setUp(self):
915 super(TestIpProtoPuntSocket, self).setUp()
916
917 for i in self.pg_interfaces:
918 i.config_ip4()
919 i.resolve_arp()
920
921 def tearDown(self):
922 super(TestIpProtoPuntSocket, self).tearDown()
923 for i in self.pg_interfaces:
924 i.unconfig_ip4()
925 i.admin_down()
926
927 def test_registration(self):
928 """ Punt socket registration/deregistration"""
929
930 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
931 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
932 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
933 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
934
935 punts = self.vapi.punt_socket_dump(type=pt_ip)
936 self.assertEqual(len(punts), 0)
937
938 #
939 # configure a punt socket
940 #
941 punt_ospf = {
942 'type': pt_ip,
943 'punt': {
944 'ip_proto': {
945 'af': af_ip4,
946 'protocol': proto_ospf
947 }
948 }
949 }
950 punt_eigrp = {
951 'type': pt_ip,
952 'punt': {
953 'ip_proto': {
954 'af': af_ip4,
955 'protocol': proto_eigrp
956 }
957 }
958 }
959
960 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200961 "%s/socket_punt_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700962 self.vapi.punt_socket_register(punt_eigrp,
Ole Troan9cd8f332019-10-18 15:57:56 +0200963 "%s/socket_punt_2" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700964 self.logger.info(self.vapi.cli("sh punt sock reg ip"))
965 punts = self.vapi.punt_socket_dump(type=pt_ip)
966 self.assertEqual(len(punts), 2)
967 self.verify_ip_proto(punt_ospf, punts[0])
968 self.verify_ip_proto(punt_eigrp, punts[1])
969
970 #
971 # deregister a punt socket
972 #
973 self.vapi.punt_socket_deregister(punt_ospf)
974 punts = self.vapi.punt_socket_dump(type=pt_ip)
975 self.assertEqual(len(punts), 1)
976
977 #
978 # configure a punt socket again
979 #
980 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200981 "%s/socket_punt_3" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700982 punts = self.vapi.punt_socket_dump(type=pt_ip)
983 self.assertEqual(len(punts), 2)
984
985 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
986
987 #
988 # deregister all punt socket
989 #
990 self.vapi.punt_socket_deregister(punt_eigrp)
991 self.vapi.punt_socket_deregister(punt_ospf)
992 punts = self.vapi.punt_socket_dump(type=pt_ip)
993 self.assertEqual(len(punts), 0)
994
995 def verify_ospf_pkts(self, rxs, n_sent):
996 self.assertEqual(len(rxs), n_sent)
997 for rx in rxs:
998 self.assertTrue(rx.haslayer(OSPF_Hdr))
999
1000 def test_traffic(self):
1001 """ Punt socket traffic """
1002
1003 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
1004 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
1005 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
1006
1007 #
1008 # configure a punt socket to capture OSPF packets
1009 #
1010 punt_ospf = {
1011 'type': pt_ip,
1012 'punt': {
1013 'ip_proto': {
1014 'af': af_ip4,
1015 'protocol': proto_ospf
1016 }
1017 }
1018 }
1019
1020 #
1021 # create packet streams and configure a punt sockets
1022 #
1023 pkt = (Ether(src=self.pg0.remote_mac,
1024 dst=self.pg0.local_mac) /
1025 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1026 OSPF_Hdr() /
1027 OSPFv3_Hello())
1028 pkts = pkt * 7
1029
Ole Troan9cd8f332019-10-18 15:57:56 +02001030 sock = self.socket_client_create("%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001031 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +02001032 punt_ospf, "%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001033
1034 #
1035 # send packets for each SPI we expect to be punted
1036 #
1037 self.send_and_assert_no_replies(self.pg0, pkts)
1038
1039 #
1040 # verify the punted packets arrived on the associated socket
1041 #
1042 rx = sock.close()
1043 self.verify_ospf_pkts(rx, len(pkts))
1044 self.vapi.punt_socket_deregister(punt_ospf)
1045
1046
Neale Ranns76b56492018-09-28 15:16:14 +00001047class TestPunt(VppTestCase):
Neale Rannsb538dd82019-05-21 06:54:54 -07001048 """ Exception Punt Test Case """
Neale Ranns76b56492018-09-28 15:16:14 +00001049
1050 @classmethod
1051 def setUpClass(cls):
1052 super(TestPunt, cls).setUpClass()
1053
1054 @classmethod
1055 def tearDownClass(cls):
1056 super(TestPunt, cls).tearDownClass()
1057
1058 def setUp(self):
1059 super(TestPunt, self).setUp()
1060
1061 self.create_pg_interfaces(range(4))
1062
1063 for i in self.pg_interfaces:
1064 i.admin_up()
1065 i.config_ip4()
1066 i.resolve_arp()
1067 i.config_ip6()
1068 i.resolve_ndp()
1069
1070 def tearDown(self):
1071 for i in self.pg_interfaces:
1072 i.unconfig_ip4()
1073 i.unconfig_ip6()
Neale Ranns76b56492018-09-28 15:16:14 +00001074 i.admin_down()
1075 super(TestPunt, self).tearDown()
1076
1077 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -07001078 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +00001079
1080 #
Neale Ranns719beb72019-07-10 07:10:25 +00001081 # dump the punt registered reasons
1082 # search for a few we know should be there
1083 #
1084 rs = self.vapi.punt_reason_dump()
1085
1086 reasons = ["ipsec6-no-such-tunnel",
1087 "ipsec4-no-such-tunnel",
1088 "ipsec4-spi-o-udp-0"]
1089
1090 for reason in reasons:
1091 found = False
1092 for r in rs:
1093 if r.reason.name == reason:
1094 found = True
1095 break
1096 self.assertTrue(found)
1097
1098 #
Neale Ranns76b56492018-09-28 15:16:14 +00001099 # Using the test CLI we will hook in a exception path to
1100 # send ACL deny packets out of pg0 and pg1.
1101 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1102 #
1103 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1104 [VppRoutePath(self.pg3.remote_ip4,
1105 self.pg3.sw_if_index)])
1106 ip_1_1_1_2.add_vpp_config()
1107 ip_1_2 = VppIpRoute(self, "1::2", 128,
1108 [VppRoutePath(self.pg3.remote_ip6,
1109 self.pg3.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001110 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns76b56492018-09-28 15:16:14 +00001111 ip_1_2.add_vpp_config()
1112
1113 p4 = (Ether(src=self.pg2.remote_mac,
1114 dst=self.pg2.local_mac) /
1115 IP(src="1.1.1.1", dst="1.1.1.2") /
1116 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001117 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001118 p6 = (Ether(src=self.pg2.remote_mac,
1119 dst=self.pg2.local_mac) /
1120 IPv6(src="1::1", dst="1::2") /
1121 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001122 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001123 self.send_and_expect(self.pg2, p4*1, self.pg3)
1124 self.send_and_expect(self.pg2, p6*1, self.pg3)
1125
1126 #
1127 # apply the punting features
1128 #
1129 self.vapi.cli("test punt pg2")
1130
1131 #
Neale Ranns719beb72019-07-10 07:10:25 +00001132 # dump the punt reasons to learn the IDs assigned
1133 #
1134 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v4"})
1135 r4 = rs[0].reason.id
1136 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v6"})
1137 r6 = rs[0].reason.id
1138
1139 #
Neale Ranns76b56492018-09-28 15:16:14 +00001140 # pkts now dropped
1141 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001142 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
1143 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001144
1145 #
1146 # Check state:
1147 # 1 - node error counters
1148 # 2 - per-reason counters
1149 # 2, 3 are the index of the assigned punt reason
1150 #
Ole Troan233e4682019-05-16 15:01:34 +02001151 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +00001152 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001153 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001154
1155 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001156 self.assertEqual(stats[0][r4]['packets'], NUM_PKTS)
1157 self.assertEqual(stats[0][r6]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001158
1159 #
1160 # use the test CLI to test a client that punts exception
1161 # packets out of pg0
1162 #
1163 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1164 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1165
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001166 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
1167 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001168
1169 #
1170 # check the packets come out IP unmodified but destined to pg0 host
1171 #
1172 for rx in rx4s:
1173 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1174 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1175 self.assertEqual(p4[IP].dst, rx[IP].dst)
1176 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1177 for rx in rx6s:
1178 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1179 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1180 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1181 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1182
1183 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001184 self.assertEqual(stats[0][r4]['packets'], 2*NUM_PKTS)
1185 self.assertEqual(stats[0][r6]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001186
1187 #
1188 # add another registration for the same reason to send packets
1189 # out of pg1
1190 #
1191 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1192 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1193
1194 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001195 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001196 self.pg_enable_capture(self.pg_interfaces)
1197 self.pg_start()
1198
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001199 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001200 for rx in rxd:
1201 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1202 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1203 self.assertEqual(p4[IP].dst, rx[IP].dst)
1204 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001205 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001206 for rx in rxd:
1207 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1208 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1209 self.assertEqual(p4[IP].dst, rx[IP].dst)
1210 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1211
1212 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001213 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001214 self.pg_enable_capture(self.pg_interfaces)
1215 self.pg_start()
1216
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001217 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001218 for rx in rxd:
1219 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1220 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1221 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1222 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001223 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001224 for rx in rxd:
1225 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1226 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1227 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1228 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1229
1230 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001231 self.assertEqual(stats[0][r4]['packets'], 3*NUM_PKTS)
1232 self.assertEqual(stats[0][r6]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001233
1234 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1235 self.logger.info(self.vapi.cli("show punt client"))
1236 self.logger.info(self.vapi.cli("show punt reason"))
1237 self.logger.info(self.vapi.cli("show punt stats"))
1238 self.logger.info(self.vapi.cli("show punt db"))
1239
Neale Ranns76b56492018-09-28 15:16:14 +00001240
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001241if __name__ == '__main__':
1242 unittest.main(testRunner=VppTestRunner)