blob: 345d9309c8bdf99af7e10b3ade97b7f558fa08a5 [file] [log] [blame]
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001#!/usr/bin/env python
2import 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
Pavel Kotucek9edb83a2018-12-11 16:57:25 +01009from struct import unpack, unpack_from
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -080010
11try:
12 import unittest2 as unittest
13except ImportError:
14 import unittest
15
Pavel Kotuceke88865d2018-11-28 07:42:11 +010016from util import ppp, ppc
17from re import compile
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070018import scapy.compat
Pavel Kotuceke88865d2018-11-28 07:42:11 +010019from scapy.packet import Raw
20from scapy.layers.l2 import Ether
21from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns50f0ac02019-05-15 02:13:37 -070022from scapy.layers.ipsec import ESP
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -080023import scapy.layers.inet6 as inet6
Pavel Kotuceke88865d2018-11-28 07:42:11 +010024from scapy.layers.inet6 import IPv6, ICMPv6DestUnreach
Neale Rannsb538dd82019-05-21 06:54:54 -070025from scapy.contrib.ospf import OSPF_Hdr, OSPFv3_Hello
Pavel Kotuceke88865d2018-11-28 07:42:11 +010026from framework import VppTestCase, VppTestRunner
27
Neale Ranns76b56492018-09-28 15:16:14 +000028from vpp_ip import DpoProto
29from vpp_ip_route import VppIpRoute, VppRoutePath
Neale Ranns50f0ac02019-05-15 02:13:37 -070030from vpp_papi import VppEnum
31from vpp_ipsec_tun_interface import VppIpsecTunInterface
Neale Ranns76b56492018-09-28 15:16:14 +000032
Paul Vinciguerra4271c972019-05-14 13:25:49 -040033NUM_PKTS = 67
34
Pavel Kotuceke88865d2018-11-28 07:42:11 +010035
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010036class serverSocketThread(threading.Thread):
37 """ Socket server thread"""
38
Neale Ranns50f0ac02019-05-15 02:13:37 -070039 def __init__(self, threadID, sockName):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010040 threading.Thread.__init__(self)
41 self.threadID = threadID
42 self.sockName = sockName
43 self.sock = None
Neale Ranns50f0ac02019-05-15 02:13:37 -070044 self.rx_pkts = []
45
46 def rx_packets(self):
47 # Wait for some packets on socket
48 while True:
49 data = self.sock.recv(65536)
50
51 # punt socket metadata
52 # packet_desc = data[0:8]
53
54 # Ethernet
55 self.rx_pkts.append(Ether(data[8:]))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010056
57 def run(self):
58 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
59 try:
60 os.unlink(self.sockName)
61 except:
62 pass
Neale Ranns50f0ac02019-05-15 02:13:37 -070063 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
64 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010065 self.sock.bind(self.sockName)
66
Neale Ranns50f0ac02019-05-15 02:13:37 -070067 self.rx_packets()
68
69 def close(self):
70 self.sock.close()
71 return self.rx_pkts
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010072
73
Pavel Kotuceke88865d2018-11-28 07:42:11 +010074class TestPuntSocket(VppTestCase):
75 """ Punt Socket """
76
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010077 ports = [1111, 2222, 3333, 4444]
78 sock_servers = list()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +000079 # FIXME: nr_packets > 3 results in failure
80 # nr_packets = 3 makes the test unstable
81 nr_packets = 2
Pavel Kotuceke88865d2018-11-28 07:42:11 +010082
83 @classmethod
Paul Vinciguerra8d991d92019-01-25 14:05:48 -080084 def setUpClass(cls):
85 super(TestPuntSocket, cls).setUpClass()
86
87 @classmethod
88 def tearDownClass(cls):
89 super(TestPuntSocket, cls).tearDownClass()
90
91 @classmethod
Pavel Kotuceke88865d2018-11-28 07:42:11 +010092 def setUpConstants(cls):
Ole Troana45dc072018-12-21 16:04:22 +010093 cls.extra_vpp_punt_config = [
94 "punt", "{", "socket", cls.tempdir+"/socket_punt", "}"]
Pavel Kotuceke88865d2018-11-28 07:42:11 +010095 super(TestPuntSocket, cls).setUpConstants()
96
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010097 def setUp(self):
98 super(TestPuntSocket, self).setUp()
99 random.seed()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100100
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100101 self.create_pg_interfaces(range(2))
102 for i in self.pg_interfaces:
103 i.admin_up()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100104
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100105 def tearDown(self):
106 del self.sock_servers[:]
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800107 super(TestPuntSocket, self).tearDown()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100108
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100109 def socket_client_create(self, sock_name, id=None):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700110 thread = serverSocketThread(id, sock_name)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100111 self.sock_servers.append(thread)
112 thread.start()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700113 return thread
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100114
115 def socket_client_close(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700116 rx_pkts = []
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100117 for thread in self.sock_servers:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700118 rx_pkts += thread.close()
119 return rx_pkts
120
121 def verify_port(self, pr, vpr):
122 self.assertEqual(vpr.punt.type, pr['type'])
123 self.assertEqual(vpr.punt.punt.l4.port,
124 pr['punt']['l4']['port'])
125 self.assertEqual(vpr.punt.punt.l4.protocol,
126 pr['punt']['l4']['protocol'])
127 self.assertEqual(vpr.punt.punt.l4.af,
128 pr['punt']['l4']['af'])
129
130 def verify_exception(self, pr, vpr):
131 self.assertEqual(vpr.punt.type, pr['type'])
132 self.assertEqual(vpr.punt.punt.exception.id,
133 pr['punt']['exception']['id'])
134
Neale Rannsb538dd82019-05-21 06:54:54 -0700135 def verify_ip_proto(self, pr, vpr):
136 self.assertEqual(vpr.punt.type, pr['type'])
137 self.assertEqual(vpr.punt.punt.ip_proto.af,
138 pr['punt']['ip_proto']['af'])
139 self.assertEqual(vpr.punt.punt.ip_proto.protocol,
140 pr['punt']['ip_proto']['protocol'])
141
Neale Ranns50f0ac02019-05-15 02:13:37 -0700142 def verify_udp_pkts(self, rxs, n_rx, port):
143 n_match = 0
144 for rx in rxs:
145 self.assertTrue(rx.haslayer(UDP))
146 if rx[UDP].dport == port:
147 n_match += 1
148 self.assertEqual(n_match, n_rx)
149
150
151def set_port(pr, port):
152 pr['punt']['l4']['port'] = port
153 return pr
154
155
156def set_reason(pr, reason):
157 pr['punt']['exception']['id'] = reason
158 return pr
159
160
161def mk_vpp_cfg4():
162 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
163 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
164 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
165 punt_l4 = {
166 'type': pt_l4,
167 'punt': {
168 'l4': {
169 'af': af_ip4,
170 'protocol': udp_proto
171 }
172 }
173 }
174 return punt_l4
175
176
177def mk_vpp_cfg6():
178 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
179 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
180 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
181 punt_l4 = {
182 'type': pt_l4,
183 'punt': {
184 'l4': {
185 'af': af_ip6,
186 'protocol': udp_proto
187 }
188 }
189 }
190 return punt_l4
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100191
192
193class TestIP4PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700194 """ Punt Socket for IPv4 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100195
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800196 @classmethod
197 def setUpClass(cls):
198 super(TestIP4PuntSocket, cls).setUpClass()
199
200 @classmethod
201 def tearDownClass(cls):
202 super(TestIP4PuntSocket, cls).tearDownClass()
203
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100204 def setUp(self):
205 super(TestIP4PuntSocket, self).setUp()
206
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100207 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100208 i.config_ip4()
209 i.resolve_arp()
210
211 def tearDown(self):
212 super(TestIP4PuntSocket, self).tearDown()
213 for i in self.pg_interfaces:
214 i.unconfig_ip4()
215 i.admin_down()
216
217 def test_punt_socket_dump(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100218 """ Punt socket registration/deregistration"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100219
Neale Ranns50f0ac02019-05-15 02:13:37 -0700220 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
221 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
222 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
223
224 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100225 self.assertEqual(len(punts), 0)
226
227 #
228 # configure a punt socket
229 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700230 punt_l4 = mk_vpp_cfg4()
231
232 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200233 "%s/socket_punt_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700234 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
Ole Troan9cd8f332019-10-18 15:57:56 +0200235 "%s/socket_punt_2222" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700236 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100237 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700238 self.verify_port(set_port(punt_l4, 1111), punts[0])
239 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100240
241 #
242 # deregister a punt socket
243 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700244 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
245 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100246 self.assertEqual(len(punts), 1)
247
248 #
249 # configure a punt socket again
250 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700251 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200252 "%s/socket_punt_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700253 self.vapi.punt_socket_register(set_port(punt_l4, 3333),
Ole Troan9cd8f332019-10-18 15:57:56 +0200254 "%s/socket_punt_3333" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700255 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100256 self.assertEqual(len(punts), 3)
257
Neale Ranns50f0ac02019-05-15 02:13:37 -0700258 self.logger.info(self.vapi.cli("sh punt sock reg"))
259
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100260 #
261 # deregister all punt socket
262 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700263 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
264 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
265 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
266 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100267 self.assertEqual(len(punts), 0)
268
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100269 def test_punt_socket_traffic_single_port_single_socket(self):
270 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100271
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100272 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700273 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
274 punt_l4 = set_port(mk_vpp_cfg4(), port)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100275
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100276 p = (Ether(src=self.pg0.remote_mac,
277 dst=self.pg0.local_mac) /
278 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100279 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200280 Raw(b'\xa5' * 100))
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100281
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100282 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100283
Neale Ranns50f0ac02019-05-15 02:13:37 -0700284 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100285 self.assertEqual(len(punts), 0)
286
287 #
288 # expect ICMP - port unreachable for all packets
289 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700290 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
291
292 for p in rx:
293 self.assertEqual(int(p[IP].proto), 1) # ICMP
294 self.assertEqual(int(p[ICMP].code), 3) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100295
296 #
297 # configure a punt socket
298 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200299 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
300 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" %
301 (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700302 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100303 self.assertEqual(len(punts), 1)
304
305 #
306 # expect punt socket and no packets on pg0
307 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700308 self.send_and_assert_no_replies(self.pg0, pkts)
309 rx = self.socket_client_close()
310 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100311
312 #
313 # remove punt socket. expect ICMP - port unreachable for all packets
314 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700315 self.vapi.punt_socket_deregister(punt_l4)
316 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100317 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100318
Neale Ranns50f0ac02019-05-15 02:13:37 -0700319 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
320 for p in rx:
321 self.assertEqual(int(p[IP].proto), 1) # ICMP
322 self.assertEqual(int(p[ICMP].code), 3) # unreachable
323
324 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100325 """ Punt socket traffic multi ports and multi sockets"""
326
Neale Ranns50f0ac02019-05-15 02:13:37 -0700327 punt_l4 = mk_vpp_cfg4()
328
329 # configuration for each UDP port
330 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100331
332 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700333 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100334 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700335 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100336 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700337 cfgs[port] = {}
338
339 pkt = (Ether(src=self.pg0.remote_mac,
340 dst=self.pg0.local_mac) /
341 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
342 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200343 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700344 cfgs[port]['pkts'] = pkt * self.nr_packets
345 cfgs[port]['port'] = port
346 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
347
348 # configure punt sockets
349 cfgs[port]['sock'] = self.socket_client_create(
Ole Troan9cd8f332019-10-18 15:57:56 +0200350 "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700351 self.vapi.punt_socket_register(
352 cfgs[port]['vpp'],
Ole Troan9cd8f332019-10-18 15:57:56 +0200353 "%s/socket_%d" % (self.tempdir, port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100354
355 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700356 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100357 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700358 for cfg in cfgs.values():
359 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100360
361 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700362 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100363 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700364 for cfg in cfgs.values():
365 rx = cfg['sock'].close()
366 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
367 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100368
369 def test_punt_socket_traffic_multi_ports_single_socket(self):
370 """ Punt socket traffic multi ports and single socket"""
371
Neale Ranns50f0ac02019-05-15 02:13:37 -0700372 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
373 punt_l4 = mk_vpp_cfg4()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100374
375 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700376 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100377 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700378 pkts = []
379 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100380 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700381 pkt = (Ether(src=self.pg0.remote_mac,
382 dst=self.pg0.local_mac) /
383 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
384 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200385 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700386 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100387
388 #
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100389 # configure a punt socket
390 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200391 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100392 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700393 self.vapi.punt_socket_register(set_port(punt_l4, p),
Ole Troan9cd8f332019-10-18 15:57:56 +0200394 "%s/socket_multi" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700395 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100396 self.assertEqual(len(punts), len(self.ports))
397
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100398 #
399 # expect punt socket and no packets on pg0
400 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700401 self.send_and_assert_no_replies(self.pg0, pkts)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100402 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700403 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100404
405 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700406 self.verify_udp_pkts(rx, self.nr_packets, p)
407 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
408 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100409 self.assertEqual(len(punts), 0)
410
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100411
412class TestIP6PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700413 """ Punt Socket for IPv6 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100414
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800415 @classmethod
416 def setUpClass(cls):
417 super(TestIP6PuntSocket, cls).setUpClass()
418
419 @classmethod
420 def tearDownClass(cls):
421 super(TestIP6PuntSocket, cls).tearDownClass()
422
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100423 def setUp(self):
424 super(TestIP6PuntSocket, self).setUp()
425
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100426 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100427 i.config_ip6()
428 i.resolve_ndp()
429
430 def tearDown(self):
431 super(TestIP6PuntSocket, self).tearDown()
432 for i in self.pg_interfaces:
433 i.unconfig_ip6()
434 i.admin_down()
435
436 def test_punt_socket_dump(self):
437 """ Punt socket registration """
438
Neale Ranns50f0ac02019-05-15 02:13:37 -0700439 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
440 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
441 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
442 #
443 # configure a punt socket
444 #
445 punt_l4 = {
446 'type': pt_l4,
447 'punt': {
448 'l4': {
449 'af': af_ip6,
450 'protocol': udp_proto
451 }
452 }
453 }
454
455 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100456 self.assertEqual(len(punts), 0)
457
458 #
459 # configure a punt socket
460 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700461 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200462 "%s/socket_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700463 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
Ole Troan9cd8f332019-10-18 15:57:56 +0200464 "%s/socket_2222" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700465 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100466 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700467 self.verify_port(set_port(punt_l4, 1111), punts[0])
468 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100469
470 #
471 # deregister a punt socket
472 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700473 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
474 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100475 self.assertEqual(len(punts), 1)
476
477 #
478 # configure a punt socket again
479 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700480 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200481 "%s/socket_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700482 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100483 self.assertEqual(len(punts), 2)
484
485 #
486 # deregister all punt socket
487 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700488 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
489 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
490 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
491 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100492 self.assertEqual(len(punts), 0)
493
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100494 def test_punt_socket_traffic_single_port_single_socket(self):
495 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100496
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100497 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700498 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
499 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
500 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
501 punt_l4 = {
502 'type': pt_l4,
503 'punt': {
504 'l4': {
505 'af': af_ip6,
506 'protocol': udp_proto,
507 'port': port,
508 }
509 }
510 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100511
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100512 p = (Ether(src=self.pg0.remote_mac,
513 dst=self.pg0.local_mac) /
514 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100515 inet6.UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200516 Raw(b'\xa5' * 100))
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100517
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100518 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100519
Neale Ranns50f0ac02019-05-15 02:13:37 -0700520 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100521 self.assertEqual(len(punts), 0)
522
523 #
524 # expect ICMPv6 - destination unreachable for all packets
525 #
526 self.vapi.cli("clear trace")
527 self.pg0.add_stream(pkts)
528 self.pg_enable_capture(self.pg_interfaces)
529 self.pg_start()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100530 # FIXME - when punt socket deregister is implemented
531 # rx = self.pg0.get_capture(self.nr_packets)
532 # for p in rx:
533 # self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
534 # self.assertEqual(int(p[ICMPv6DestUnreach].code),4) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100535
536 #
537 # configure a punt socket
538 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200539 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
540 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" %
541 (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700542 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100543 self.assertEqual(len(punts), 1)
544
545 #
546 # expect punt socket and no packets on pg0
547 #
548 self.vapi.cli("clear errors")
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100549 self.vapi.cli("clear trace")
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100550 self.pg0.add_stream(pkts)
551 self.pg_enable_capture(self.pg_interfaces)
552 self.pg_start()
553 self.pg0.get_capture(0)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100554 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700555 rx = self.socket_client_close()
556 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100557
558 #
559 # remove punt socket. expect ICMP - dest. unreachable for all packets
560 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700561 self.vapi.punt_socket_deregister(punt_l4)
562 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100563 self.assertEqual(len(punts), 0)
564 self.pg0.add_stream(pkts)
565 self.pg_enable_capture(self.pg_interfaces)
566 self.pg_start()
567 # FIXME - when punt socket deregister is implemented
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100568 # self.pg0.get_capture(nr_packets)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100569
Neale Ranns50f0ac02019-05-15 02:13:37 -0700570 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100571 """ Punt socket traffic multi ports and multi sockets"""
572
Neale Ranns50f0ac02019-05-15 02:13:37 -0700573 punt_l4 = mk_vpp_cfg6()
574
575 # configuration for each UDP port
576 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100577
578 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700579 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100580 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700581 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100582 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700583 cfgs[port] = {}
584
585 pkt = (Ether(src=self.pg0.remote_mac,
586 dst=self.pg0.local_mac) /
587 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
588 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200589 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700590 cfgs[port]['pkts'] = pkt * self.nr_packets
591 cfgs[port]['port'] = port
592 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
593
594 # configure punt sockets
595 cfgs[port]['sock'] = self.socket_client_create(
Ole Troan9cd8f332019-10-18 15:57:56 +0200596 "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700597 self.vapi.punt_socket_register(
598 cfgs[port]['vpp'],
Ole Troan9cd8f332019-10-18 15:57:56 +0200599 "%s/socket_%d" % (self.tempdir, port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100600
601 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700602 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100603 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700604 for cfg in cfgs.values():
605 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100606
607 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700608 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100609 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700610 for cfg in cfgs.values():
611 rx = cfg['sock'].close()
612 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
613 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100614
615 def test_punt_socket_traffic_multi_ports_single_socket(self):
616 """ Punt socket traffic multi ports and single socket"""
617
Neale Ranns50f0ac02019-05-15 02:13:37 -0700618 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
619 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
620 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
621 punt_l4 = {
622 'type': pt_l4,
623 'punt': {
624 'l4': {
625 'af': af_ip6,
626 'protocol': udp_proto,
627 }
628 }
629 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100630
631 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700632 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100633 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700634 pkts = []
635 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100636 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700637 pkt = (Ether(src=self.pg0.remote_mac,
638 dst=self.pg0.local_mac) /
639 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
640 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200641 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700642 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100643
644 #
645 # no punt socket
646 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700647 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100648 self.assertEqual(len(punts), 0)
649
650 #
651 # configure a punt socket
652 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200653 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100654 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700655 self.vapi.punt_socket_register(set_port(punt_l4, p),
Ole Troan9cd8f332019-10-18 15:57:56 +0200656 "%s/socket_multi" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700657 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100658 self.assertEqual(len(punts), len(self.ports))
659
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100660 #
661 # expect punt socket and no packets on pg0
662 #
663 self.vapi.cli("clear errors")
664 self.vapi.cli("clear trace")
665 self.pg0.add_stream(pkts)
666 self.pg_enable_capture(self.pg_interfaces)
667 self.pg_start()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +0000668 # give a chance to punt socket to collect all packets
669 self.sleep(1)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100670 self.pg0.get_capture(0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700671 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100672
673 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700674 self.verify_udp_pkts(rx, self.nr_packets, p)
675 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
676 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100677 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100678
Neale Ranns76b56492018-09-28 15:16:14 +0000679
Neale Ranns50f0ac02019-05-15 02:13:37 -0700680class TestExceptionPuntSocket(TestPuntSocket):
681 """ Punt Socket for Exceptions """
682
683 @classmethod
684 def setUpClass(cls):
685 super(TestExceptionPuntSocket, cls).setUpClass()
686
687 @classmethod
688 def tearDownClass(cls):
689 super(TestExceptionPuntSocket, cls).tearDownClass()
690
691 def setUp(self):
692 super(TestExceptionPuntSocket, self).setUp()
693
694 for i in self.pg_interfaces:
695 i.config_ip4()
696 i.resolve_arp()
697
698 def tearDown(self):
699 super(TestExceptionPuntSocket, self).tearDown()
700 for i in self.pg_interfaces:
701 i.unconfig_ip4()
702 i.admin_down()
703
704 def test_registration(self):
705 """ Punt socket registration/deregistration"""
706
707 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
708
709 punts = self.vapi.punt_socket_dump(type=pt_ex)
710 self.assertEqual(len(punts), 0)
711
712 #
713 # configure a punt socket
714 #
715 punt_ex = {
716 'type': pt_ex,
717 'punt': {
718 'exception': {}
719 }
720 }
721
722 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
Ole Troan9cd8f332019-10-18 15:57:56 +0200723 "%s/socket_punt_1" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700724 self.vapi.punt_socket_register(set_reason(punt_ex, 2),
Ole Troan9cd8f332019-10-18 15:57:56 +0200725 "%s/socket_punt_2" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700726 punts = self.vapi.punt_socket_dump(type=pt_ex)
727 self.assertEqual(len(punts), 2)
728 self.verify_exception(set_reason(punt_ex, 1), punts[0])
729 self.verify_exception(set_reason(punt_ex, 2), punts[1])
730
731 #
732 # deregister a punt socket
733 #
734 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
735 punts = self.vapi.punt_socket_dump(type=pt_ex)
736 self.assertEqual(len(punts), 1)
737
738 #
739 # configure a punt socket again
740 #
741 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
Ole Troan9cd8f332019-10-18 15:57:56 +0200742 "%s/socket_punt_1" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700743 self.vapi.punt_socket_register(set_reason(punt_ex, 3),
Ole Troan9cd8f332019-10-18 15:57:56 +0200744 "%s/socket_punt_3" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700745 punts = self.vapi.punt_socket_dump(type=pt_ex)
746 self.assertEqual(len(punts), 3)
747
748 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
749
750 #
751 # deregister all punt socket
752 #
753 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
754 self.vapi.punt_socket_deregister(set_reason(punt_ex, 2))
755 self.vapi.punt_socket_deregister(set_reason(punt_ex, 3))
756 punts = self.vapi.punt_socket_dump(type=pt_ex)
757 self.assertEqual(len(punts), 0)
758
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700759 def verify_esp_pkts(self, rxs, n_sent, spi, has_udp):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700760 self.assertEqual(len(rxs), n_sent)
761 for rx in rxs:
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700762 self.assertTrue(rx.haslayer(IP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700763 self.assertTrue(rx.haslayer(ESP))
764 self.assertEqual(rx[ESP].spi, spi)
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700765 if has_udp:
766 self.assertTrue(rx.haslayer(UDP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700767
768 def test_traffic(self):
769 """ Punt socket traffic """
770
771 port = self.ports[0]
772 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
773 punt_ex = {
774 'type': pt_ex,
775 'punt': {
776 'exception': {}
777 }
778 }
779
780 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700781 # we need an IPSec tunnels for this to work otherwise ESP gets dropped
Neale Ranns50f0ac02019-05-15 02:13:37 -0700782 # due to unknown IP proto
783 #
784 VppIpsecTunInterface(self, self.pg0, 1000, 1000,
785 (VppEnum.vl_api_ipsec_crypto_alg_t.
786 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
Ole Troan9cd8f332019-10-18 15:57:56 +0200787 b"0123456701234567",
788 b"0123456701234567",
Neale Ranns50f0ac02019-05-15 02:13:37 -0700789 (VppEnum.vl_api_ipsec_integ_alg_t.
790 IPSEC_API_INTEG_ALG_SHA1_96),
Ole Troan9cd8f332019-10-18 15:57:56 +0200791 b"0123456701234567",
792 b"0123456701234567").add_vpp_config()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700793 VppIpsecTunInterface(self, self.pg0, 1001, 1001,
794 (VppEnum.vl_api_ipsec_crypto_alg_t.
795 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
Ole Troan9cd8f332019-10-18 15:57:56 +0200796 b"0123456701234567",
797 b"0123456701234567",
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700798 (VppEnum.vl_api_ipsec_integ_alg_t.
799 IPSEC_API_INTEG_ALG_SHA1_96),
Ole Troan9cd8f332019-10-18 15:57:56 +0200800 b"0123456701234567",
801 b"0123456701234567",
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700802 udp_encap=True).add_vpp_config()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700803
804 #
805 # we're dealing with IPSec tunnels punting for no-such-tunnel
806 # adn SPI=0
807 #
808 cfgs = dict()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700809 cfgs['ipsec4-no-such-tunnel'] = {'spi': 99, 'udp': False}
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700810 cfgs['ipsec4-spi-o-udp-0'] = {'spi': 0, 'udp': True}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700811
812 #
813 # find the VPP ID for these punt exception reasin
814 #
815 rs = self.vapi.punt_reason_dump()
816 for key in cfgs:
817 for r in rs:
818 if r.reason.name == key:
819 cfgs[key]['id'] = r.reason.id
820 cfgs[key]['vpp'] = copy.deepcopy(
821 set_reason(punt_ex,
822 cfgs[key]['id']))
823 break
824
825 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700826 # configure punt sockets
Neale Ranns50f0ac02019-05-15 02:13:37 -0700827 #
828 for cfg in cfgs.values():
Ole Troan9cd8f332019-10-18 15:57:56 +0200829 cfg['sock'] = self.socket_client_create("%s/socket_%d" %
830 (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700831 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +0200832 cfg['vpp'], "%s/socket_%d" % (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700833
834 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700835 # create packet streams for 'no-such-tunnel' exception
836 #
837 for cfg in cfgs.values():
838 pkt = (Ether(src=self.pg0.remote_mac,
839 dst=self.pg0.local_mac) /
840 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4))
841 if (cfg['udp']):
842 pkt = pkt / UDP(sport=666, dport=4500)
843 pkt = (pkt / ESP(spi=cfg['spi'], seq=3) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200844 Raw(b'\xa5' * 100))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700845 cfg['pkts'] = [pkt]
846
847 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700848 # send packets for each SPI we expect to be punted
849 #
850 for cfg in cfgs.values():
851 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
852
853 #
854 # verify the punted packets arrived on the associated socket
855 #
856 for cfg in cfgs.values():
857 rx = cfg['sock'].close()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700858 self.verify_esp_pkts(rx, len(cfg['pkts']),
859 cfg['spi'], cfg['udp'])
860
861 #
862 # socket deregister
863 #
864 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700865 self.vapi.punt_socket_deregister(cfg['vpp'])
866
867
Neale Rannsb538dd82019-05-21 06:54:54 -0700868class TestIpProtoPuntSocket(TestPuntSocket):
869 """ Punt Socket for IP packets """
870
871 @classmethod
872 def setUpClass(cls):
873 super(TestIpProtoPuntSocket, cls).setUpClass()
874
875 @classmethod
876 def tearDownClass(cls):
877 super(TestIpProtoPuntSocket, cls).tearDownClass()
878
879 def setUp(self):
880 super(TestIpProtoPuntSocket, self).setUp()
881
882 for i in self.pg_interfaces:
883 i.config_ip4()
884 i.resolve_arp()
885
886 def tearDown(self):
887 super(TestIpProtoPuntSocket, self).tearDown()
888 for i in self.pg_interfaces:
889 i.unconfig_ip4()
890 i.admin_down()
891
892 def test_registration(self):
893 """ Punt socket registration/deregistration"""
894
895 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
896 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
897 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
898 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
899
900 punts = self.vapi.punt_socket_dump(type=pt_ip)
901 self.assertEqual(len(punts), 0)
902
903 #
904 # configure a punt socket
905 #
906 punt_ospf = {
907 'type': pt_ip,
908 'punt': {
909 'ip_proto': {
910 'af': af_ip4,
911 'protocol': proto_ospf
912 }
913 }
914 }
915 punt_eigrp = {
916 'type': pt_ip,
917 'punt': {
918 'ip_proto': {
919 'af': af_ip4,
920 'protocol': proto_eigrp
921 }
922 }
923 }
924
925 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200926 "%s/socket_punt_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700927 self.vapi.punt_socket_register(punt_eigrp,
Ole Troan9cd8f332019-10-18 15:57:56 +0200928 "%s/socket_punt_2" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700929 self.logger.info(self.vapi.cli("sh punt sock reg ip"))
930 punts = self.vapi.punt_socket_dump(type=pt_ip)
931 self.assertEqual(len(punts), 2)
932 self.verify_ip_proto(punt_ospf, punts[0])
933 self.verify_ip_proto(punt_eigrp, punts[1])
934
935 #
936 # deregister a punt socket
937 #
938 self.vapi.punt_socket_deregister(punt_ospf)
939 punts = self.vapi.punt_socket_dump(type=pt_ip)
940 self.assertEqual(len(punts), 1)
941
942 #
943 # configure a punt socket again
944 #
945 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200946 "%s/socket_punt_3" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700947 punts = self.vapi.punt_socket_dump(type=pt_ip)
948 self.assertEqual(len(punts), 2)
949
950 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
951
952 #
953 # deregister all punt socket
954 #
955 self.vapi.punt_socket_deregister(punt_eigrp)
956 self.vapi.punt_socket_deregister(punt_ospf)
957 punts = self.vapi.punt_socket_dump(type=pt_ip)
958 self.assertEqual(len(punts), 0)
959
960 def verify_ospf_pkts(self, rxs, n_sent):
961 self.assertEqual(len(rxs), n_sent)
962 for rx in rxs:
963 self.assertTrue(rx.haslayer(OSPF_Hdr))
964
965 def test_traffic(self):
966 """ Punt socket traffic """
967
968 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
969 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
970 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
971
972 #
973 # configure a punt socket to capture OSPF packets
974 #
975 punt_ospf = {
976 'type': pt_ip,
977 'punt': {
978 'ip_proto': {
979 'af': af_ip4,
980 'protocol': proto_ospf
981 }
982 }
983 }
984
985 #
986 # create packet streams and configure a punt sockets
987 #
988 pkt = (Ether(src=self.pg0.remote_mac,
989 dst=self.pg0.local_mac) /
990 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
991 OSPF_Hdr() /
992 OSPFv3_Hello())
993 pkts = pkt * 7
994
Ole Troan9cd8f332019-10-18 15:57:56 +0200995 sock = self.socket_client_create("%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700996 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +0200997 punt_ospf, "%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700998
999 #
1000 # send packets for each SPI we expect to be punted
1001 #
1002 self.send_and_assert_no_replies(self.pg0, pkts)
1003
1004 #
1005 # verify the punted packets arrived on the associated socket
1006 #
1007 rx = sock.close()
1008 self.verify_ospf_pkts(rx, len(pkts))
1009 self.vapi.punt_socket_deregister(punt_ospf)
1010
1011
Neale Ranns76b56492018-09-28 15:16:14 +00001012class TestPunt(VppTestCase):
Neale Rannsb538dd82019-05-21 06:54:54 -07001013 """ Exception Punt Test Case """
Neale Ranns76b56492018-09-28 15:16:14 +00001014
1015 @classmethod
1016 def setUpClass(cls):
1017 super(TestPunt, cls).setUpClass()
1018
1019 @classmethod
1020 def tearDownClass(cls):
1021 super(TestPunt, cls).tearDownClass()
1022
1023 def setUp(self):
1024 super(TestPunt, self).setUp()
1025
1026 self.create_pg_interfaces(range(4))
1027
1028 for i in self.pg_interfaces:
1029 i.admin_up()
1030 i.config_ip4()
1031 i.resolve_arp()
1032 i.config_ip6()
1033 i.resolve_ndp()
1034
1035 def tearDown(self):
1036 for i in self.pg_interfaces:
1037 i.unconfig_ip4()
1038 i.unconfig_ip6()
1039 i.ip6_disable()
1040 i.admin_down()
1041 super(TestPunt, self).tearDown()
1042
1043 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -07001044 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +00001045
1046 #
Neale Ranns719beb72019-07-10 07:10:25 +00001047 # dump the punt registered reasons
1048 # search for a few we know should be there
1049 #
1050 rs = self.vapi.punt_reason_dump()
1051
1052 reasons = ["ipsec6-no-such-tunnel",
1053 "ipsec4-no-such-tunnel",
1054 "ipsec4-spi-o-udp-0"]
1055
1056 for reason in reasons:
1057 found = False
1058 for r in rs:
1059 if r.reason.name == reason:
1060 found = True
1061 break
1062 self.assertTrue(found)
1063
1064 #
Neale Ranns76b56492018-09-28 15:16:14 +00001065 # Using the test CLI we will hook in a exception path to
1066 # send ACL deny packets out of pg0 and pg1.
1067 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1068 #
1069 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1070 [VppRoutePath(self.pg3.remote_ip4,
1071 self.pg3.sw_if_index)])
1072 ip_1_1_1_2.add_vpp_config()
1073 ip_1_2 = VppIpRoute(self, "1::2", 128,
1074 [VppRoutePath(self.pg3.remote_ip6,
1075 self.pg3.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001076 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns76b56492018-09-28 15:16:14 +00001077 ip_1_2.add_vpp_config()
1078
1079 p4 = (Ether(src=self.pg2.remote_mac,
1080 dst=self.pg2.local_mac) /
1081 IP(src="1.1.1.1", dst="1.1.1.2") /
1082 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001083 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001084 p6 = (Ether(src=self.pg2.remote_mac,
1085 dst=self.pg2.local_mac) /
1086 IPv6(src="1::1", dst="1::2") /
1087 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001088 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001089 self.send_and_expect(self.pg2, p4*1, self.pg3)
1090 self.send_and_expect(self.pg2, p6*1, self.pg3)
1091
1092 #
1093 # apply the punting features
1094 #
1095 self.vapi.cli("test punt pg2")
1096
1097 #
Neale Ranns719beb72019-07-10 07:10:25 +00001098 # dump the punt reasons to learn the IDs assigned
1099 #
1100 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v4"})
1101 r4 = rs[0].reason.id
1102 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v6"})
1103 r6 = rs[0].reason.id
1104
1105 #
Neale Ranns76b56492018-09-28 15:16:14 +00001106 # pkts now dropped
1107 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001108 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
1109 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001110
1111 #
1112 # Check state:
1113 # 1 - node error counters
1114 # 2 - per-reason counters
1115 # 2, 3 are the index of the assigned punt reason
1116 #
Ole Troan233e4682019-05-16 15:01:34 +02001117 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +00001118 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001119 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001120
1121 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001122 self.assertEqual(stats[0][r4]['packets'], NUM_PKTS)
1123 self.assertEqual(stats[0][r6]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001124
1125 #
1126 # use the test CLI to test a client that punts exception
1127 # packets out of pg0
1128 #
1129 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1130 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1131
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001132 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
1133 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001134
1135 #
1136 # check the packets come out IP unmodified but destined to pg0 host
1137 #
1138 for rx in rx4s:
1139 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1140 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1141 self.assertEqual(p4[IP].dst, rx[IP].dst)
1142 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1143 for rx in rx6s:
1144 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1145 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1146 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1147 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1148
1149 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001150 self.assertEqual(stats[0][r4]['packets'], 2*NUM_PKTS)
1151 self.assertEqual(stats[0][r6]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001152
1153 #
1154 # add another registration for the same reason to send packets
1155 # out of pg1
1156 #
1157 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1158 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1159
1160 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001161 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001162 self.pg_enable_capture(self.pg_interfaces)
1163 self.pg_start()
1164
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001165 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001166 for rx in rxd:
1167 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1168 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1169 self.assertEqual(p4[IP].dst, rx[IP].dst)
1170 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001171 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001172 for rx in rxd:
1173 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1174 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1175 self.assertEqual(p4[IP].dst, rx[IP].dst)
1176 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1177
1178 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001179 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001180 self.pg_enable_capture(self.pg_interfaces)
1181 self.pg_start()
1182
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001183 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001184 for rx in rxd:
1185 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1186 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1187 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1188 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001189 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001190 for rx in rxd:
1191 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1192 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1193 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1194 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1195
1196 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001197 self.assertEqual(stats[0][r4]['packets'], 3*NUM_PKTS)
1198 self.assertEqual(stats[0][r6]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001199
1200 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1201 self.logger.info(self.vapi.cli("show punt client"))
1202 self.logger.info(self.vapi.cli("show punt reason"))
1203 self.logger.info(self.vapi.cli("show punt stats"))
1204 self.logger.info(self.vapi.cli("show punt db"))
1205
Neale Ranns76b56492018-09-28 15:16:14 +00001206
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001207if __name__ == '__main__':
1208 unittest.main(testRunner=VppTestRunner)