blob: 3ba1be4d5edc27808bfd3a02fda968d8efd8d5e6 [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
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -080026import six
Pavel Kotuceke88865d2018-11-28 07:42:11 +010027from framework import VppTestCase, VppTestRunner
28
Neale Ranns76b56492018-09-28 15:16:14 +000029from vpp_ip import DpoProto
30from vpp_ip_route import VppIpRoute, VppRoutePath
Neale Ranns50f0ac02019-05-15 02:13:37 -070031from vpp_papi import VppEnum
32from vpp_ipsec_tun_interface import VppIpsecTunInterface
Neale Ranns76b56492018-09-28 15:16:14 +000033
Paul Vinciguerra4271c972019-05-14 13:25:49 -040034NUM_PKTS = 67
35
Pavel Kotuceke88865d2018-11-28 07:42:11 +010036
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010037class serverSocketThread(threading.Thread):
38 """ Socket server thread"""
39
Neale Ranns50f0ac02019-05-15 02:13:37 -070040 def __init__(self, threadID, sockName):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010041 threading.Thread.__init__(self)
42 self.threadID = threadID
43 self.sockName = sockName
44 self.sock = None
Neale Ranns50f0ac02019-05-15 02:13:37 -070045 self.rx_pkts = []
46
47 def rx_packets(self):
48 # Wait for some packets on socket
49 while True:
50 data = self.sock.recv(65536)
51
52 # punt socket metadata
53 # packet_desc = data[0:8]
54
55 # Ethernet
56 self.rx_pkts.append(Ether(data[8:]))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010057
58 def run(self):
59 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
60 try:
61 os.unlink(self.sockName)
62 except:
63 pass
Neale Ranns50f0ac02019-05-15 02:13:37 -070064 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
65 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010066 self.sock.bind(self.sockName)
67
Neale Ranns50f0ac02019-05-15 02:13:37 -070068 self.rx_packets()
69
70 def close(self):
71 self.sock.close()
72 return self.rx_pkts
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010073
74
Pavel Kotuceke88865d2018-11-28 07:42:11 +010075class TestPuntSocket(VppTestCase):
76 """ Punt Socket """
77
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010078 ports = [1111, 2222, 3333, 4444]
79 sock_servers = list()
Neale Ranns50f0ac02019-05-15 02:13:37 -070080 nr_packets = 3
Pavel Kotuceke88865d2018-11-28 07:42:11 +010081
82 @classmethod
Paul Vinciguerra8d991d92019-01-25 14:05:48 -080083 def setUpClass(cls):
84 super(TestPuntSocket, cls).setUpClass()
85
86 @classmethod
87 def tearDownClass(cls):
88 super(TestPuntSocket, cls).tearDownClass()
89
90 @classmethod
Pavel Kotuceke88865d2018-11-28 07:42:11 +010091 def setUpConstants(cls):
Ole Troana45dc072018-12-21 16:04:22 +010092 cls.extra_vpp_punt_config = [
93 "punt", "{", "socket", cls.tempdir+"/socket_punt", "}"]
Pavel Kotuceke88865d2018-11-28 07:42:11 +010094 super(TestPuntSocket, cls).setUpConstants()
95
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010096 def setUp(self):
97 super(TestPuntSocket, self).setUp()
98 random.seed()
Pavel Kotuceke88865d2018-11-28 07:42:11 +010099
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100100 self.create_pg_interfaces(range(2))
101 for i in self.pg_interfaces:
102 i.admin_up()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100103
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100104 def tearDown(self):
105 del self.sock_servers[:]
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800106 super(TestPuntSocket, self).tearDown()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100107
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100108 def socket_client_create(self, sock_name, id=None):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700109 thread = serverSocketThread(id, sock_name)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100110 self.sock_servers.append(thread)
111 thread.start()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700112 return thread
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100113
114 def socket_client_close(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700115 rx_pkts = []
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100116 for thread in self.sock_servers:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700117 rx_pkts += thread.close()
118 return rx_pkts
119
120 def verify_port(self, pr, vpr):
121 self.assertEqual(vpr.punt.type, pr['type'])
122 self.assertEqual(vpr.punt.punt.l4.port,
123 pr['punt']['l4']['port'])
124 self.assertEqual(vpr.punt.punt.l4.protocol,
125 pr['punt']['l4']['protocol'])
126 self.assertEqual(vpr.punt.punt.l4.af,
127 pr['punt']['l4']['af'])
128
129 def verify_exception(self, pr, vpr):
130 self.assertEqual(vpr.punt.type, pr['type'])
131 self.assertEqual(vpr.punt.punt.exception.id,
132 pr['punt']['exception']['id'])
133
Neale Rannsb538dd82019-05-21 06:54:54 -0700134 def verify_ip_proto(self, pr, vpr):
135 self.assertEqual(vpr.punt.type, pr['type'])
136 self.assertEqual(vpr.punt.punt.ip_proto.af,
137 pr['punt']['ip_proto']['af'])
138 self.assertEqual(vpr.punt.punt.ip_proto.protocol,
139 pr['punt']['ip_proto']['protocol'])
140
Neale Ranns50f0ac02019-05-15 02:13:37 -0700141 def verify_udp_pkts(self, rxs, n_rx, port):
142 n_match = 0
143 for rx in rxs:
144 self.assertTrue(rx.haslayer(UDP))
145 if rx[UDP].dport == port:
146 n_match += 1
147 self.assertEqual(n_match, n_rx)
148
149
150def set_port(pr, port):
151 pr['punt']['l4']['port'] = port
152 return pr
153
154
155def set_reason(pr, reason):
156 pr['punt']['exception']['id'] = reason
157 return pr
158
159
160def mk_vpp_cfg4():
161 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
162 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
163 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
164 punt_l4 = {
165 'type': pt_l4,
166 'punt': {
167 'l4': {
168 'af': af_ip4,
169 'protocol': udp_proto
170 }
171 }
172 }
173 return punt_l4
174
175
176def mk_vpp_cfg6():
177 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
178 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
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_ip6,
185 'protocol': udp_proto
186 }
187 }
188 }
189 return punt_l4
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100190
191
192class TestIP4PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700193 """ Punt Socket for IPv4 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100194
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800195 @classmethod
196 def setUpClass(cls):
197 super(TestIP4PuntSocket, cls).setUpClass()
198
199 @classmethod
200 def tearDownClass(cls):
201 super(TestIP4PuntSocket, cls).tearDownClass()
202
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100203 def setUp(self):
204 super(TestIP4PuntSocket, self).setUp()
205
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100206 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100207 i.config_ip4()
208 i.resolve_arp()
209
210 def tearDown(self):
211 super(TestIP4PuntSocket, self).tearDown()
212 for i in self.pg_interfaces:
213 i.unconfig_ip4()
214 i.admin_down()
215
216 def test_punt_socket_dump(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100217 """ Punt socket registration/deregistration"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100218
Neale Ranns50f0ac02019-05-15 02:13:37 -0700219 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
220 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
221 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
222
223 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100224 self.assertEqual(len(punts), 0)
225
226 #
227 # configure a punt socket
228 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700229 punt_l4 = mk_vpp_cfg4()
230
231 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
232 b"%s/socket_punt_1111" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800233 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700234 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
235 b"%s/socket_punt_2222" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800236 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700237 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100238 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700239 self.verify_port(set_port(punt_l4, 1111), punts[0])
240 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100241
242 #
243 # deregister a punt socket
244 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700245 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
246 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100247 self.assertEqual(len(punts), 1)
248
249 #
250 # configure a punt socket again
251 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700252 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
253 b"%s/socket_punt_1111" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800254 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700255 self.vapi.punt_socket_register(set_port(punt_l4, 3333),
256 b"%s/socket_punt_3333" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800257 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700258 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100259 self.assertEqual(len(punts), 3)
260
Neale Ranns50f0ac02019-05-15 02:13:37 -0700261 self.logger.info(self.vapi.cli("sh punt sock reg"))
262
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100263 #
264 # deregister all punt socket
265 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700266 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
267 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
268 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
269 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100270 self.assertEqual(len(punts), 0)
271
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100272 def test_punt_socket_traffic_single_port_single_socket(self):
273 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100274
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100275 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700276 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
277 punt_l4 = set_port(mk_vpp_cfg4(), port)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100278
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100279 p = (Ether(src=self.pg0.remote_mac,
280 dst=self.pg0.local_mac) /
281 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100282 UDP(sport=9876, dport=port) /
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100283 Raw('\xa5' * 100))
284
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100285 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100286
Neale Ranns50f0ac02019-05-15 02:13:37 -0700287 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100288 self.assertEqual(len(punts), 0)
289
290 #
291 # expect ICMP - port unreachable for all packets
292 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700293 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
294
295 for p in rx:
296 self.assertEqual(int(p[IP].proto), 1) # ICMP
297 self.assertEqual(int(p[ICMP].code), 3) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100298
299 #
300 # configure a punt socket
301 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800302 self.socket_client_create(b"%s/socket_%d" % (
303 six.ensure_binary(self.tempdir), port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700304 self.vapi.punt_socket_register(punt_l4, b"%s/socket_%d" % (
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800305 six.ensure_binary(self.tempdir), port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700306 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100307 self.assertEqual(len(punts), 1)
308
309 #
310 # expect punt socket and no packets on pg0
311 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700312 self.send_and_assert_no_replies(self.pg0, pkts)
313 rx = self.socket_client_close()
314 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100315
316 #
317 # remove punt socket. expect ICMP - port unreachable for all packets
318 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700319 self.vapi.punt_socket_deregister(punt_l4)
320 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100321 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100322
Neale Ranns50f0ac02019-05-15 02:13:37 -0700323 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
324 for p in rx:
325 self.assertEqual(int(p[IP].proto), 1) # ICMP
326 self.assertEqual(int(p[ICMP].code), 3) # unreachable
327
328 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100329 """ Punt socket traffic multi ports and multi sockets"""
330
Neale Ranns50f0ac02019-05-15 02:13:37 -0700331 punt_l4 = mk_vpp_cfg4()
332
333 # configuration for each UDP port
334 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100335
336 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700337 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100338 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700339 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100340 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700341 cfgs[port] = {}
342
343 pkt = (Ether(src=self.pg0.remote_mac,
344 dst=self.pg0.local_mac) /
345 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
346 UDP(sport=9876, dport=port) /
347 Raw('\xa5' * 100))
348 cfgs[port]['pkts'] = pkt * self.nr_packets
349 cfgs[port]['port'] = port
350 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
351
352 # configure punt sockets
353 cfgs[port]['sock'] = self.socket_client_create(
354 b"%s/socket_%d" % (six.ensure_binary(self.tempdir), port))
355 self.vapi.punt_socket_register(
356 cfgs[port]['vpp'],
357 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
358 port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100359
360 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700361 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100362 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700363 for cfg in cfgs.values():
364 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100365
366 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700367 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100368 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700369 for cfg in cfgs.values():
370 rx = cfg['sock'].close()
371 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
372 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100373
374 def test_punt_socket_traffic_multi_ports_single_socket(self):
375 """ Punt socket traffic multi ports and single socket"""
376
Neale Ranns50f0ac02019-05-15 02:13:37 -0700377 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
378 punt_l4 = mk_vpp_cfg4()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100379
380 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700381 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100382 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700383 pkts = []
384 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100385 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700386 pkt = (Ether(src=self.pg0.remote_mac,
387 dst=self.pg0.local_mac) /
388 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
389 UDP(sport=9876, dport=port) /
390 Raw('\xa5' * 100))
391 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100392
393 #
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100394 # configure a punt socket
395 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800396 self.socket_client_create(b"%s/socket_multi" %
397 six.ensure_binary(self.tempdir))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100398 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700399 self.vapi.punt_socket_register(set_port(punt_l4, p),
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800400 b"%s/socket_multi" %
401 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700402 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100403 self.assertEqual(len(punts), len(self.ports))
404
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100405 #
406 # expect punt socket and no packets on pg0
407 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700408 self.send_and_assert_no_replies(self.pg0, pkts)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100409 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700410 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100411
412 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700413 self.verify_udp_pkts(rx, self.nr_packets, p)
414 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
415 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100416 self.assertEqual(len(punts), 0)
417
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100418
419class TestIP6PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700420 """ Punt Socket for IPv6 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100421
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800422 @classmethod
423 def setUpClass(cls):
424 super(TestIP6PuntSocket, cls).setUpClass()
425
426 @classmethod
427 def tearDownClass(cls):
428 super(TestIP6PuntSocket, cls).tearDownClass()
429
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100430 def setUp(self):
431 super(TestIP6PuntSocket, self).setUp()
432
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100433 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100434 i.config_ip6()
435 i.resolve_ndp()
436
437 def tearDown(self):
438 super(TestIP6PuntSocket, self).tearDown()
439 for i in self.pg_interfaces:
440 i.unconfig_ip6()
441 i.admin_down()
442
443 def test_punt_socket_dump(self):
444 """ Punt socket registration """
445
Neale Ranns50f0ac02019-05-15 02:13:37 -0700446 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
447 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
448 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
449 #
450 # configure a punt socket
451 #
452 punt_l4 = {
453 'type': pt_l4,
454 'punt': {
455 'l4': {
456 'af': af_ip6,
457 'protocol': udp_proto
458 }
459 }
460 }
461
462 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100463 self.assertEqual(len(punts), 0)
464
465 #
466 # configure a punt socket
467 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700468 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
469 b"%s/socket_1111" %
470 six.ensure_binary(self.tempdir))
471 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
472 b"%s/socket_2222" %
473 six.ensure_binary(self.tempdir))
474 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100475 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700476 self.verify_port(set_port(punt_l4, 1111), punts[0])
477 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100478
479 #
480 # deregister a punt socket
481 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700482 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
483 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100484 self.assertEqual(len(punts), 1)
485
486 #
487 # configure a punt socket again
488 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700489 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
490 b"%s/socket_1111" %
491 six.ensure_binary(self.tempdir))
492 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100493 self.assertEqual(len(punts), 2)
494
495 #
496 # deregister all punt socket
497 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700498 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
499 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
500 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
501 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100502 self.assertEqual(len(punts), 0)
503
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100504 def test_punt_socket_traffic_single_port_single_socket(self):
505 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100506
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100507 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700508 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
509 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
510 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
511 punt_l4 = {
512 'type': pt_l4,
513 'punt': {
514 'l4': {
515 'af': af_ip6,
516 'protocol': udp_proto,
517 'port': port,
518 }
519 }
520 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100521
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100522 p = (Ether(src=self.pg0.remote_mac,
523 dst=self.pg0.local_mac) /
524 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100525 inet6.UDP(sport=9876, dport=port) /
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100526 Raw('\xa5' * 100))
527
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100528 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100529
Neale Ranns50f0ac02019-05-15 02:13:37 -0700530 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100531 self.assertEqual(len(punts), 0)
532
533 #
534 # expect ICMPv6 - destination unreachable for all packets
535 #
536 self.vapi.cli("clear trace")
537 self.pg0.add_stream(pkts)
538 self.pg_enable_capture(self.pg_interfaces)
539 self.pg_start()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100540 # FIXME - when punt socket deregister is implemented
541 # rx = self.pg0.get_capture(self.nr_packets)
542 # for p in rx:
543 # self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
544 # self.assertEqual(int(p[ICMPv6DestUnreach].code),4) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100545
546 #
547 # configure a punt socket
548 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800549 self.socket_client_create(b"%s/socket_%d" % (
550 six.ensure_binary(self.tempdir), port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700551 self.vapi.punt_socket_register(punt_l4, b"%s/socket_%d" % (
552 six.ensure_binary(self.tempdir), port))
553 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100554 self.assertEqual(len(punts), 1)
555
556 #
557 # expect punt socket and no packets on pg0
558 #
559 self.vapi.cli("clear errors")
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100560 self.vapi.cli("clear trace")
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100561 self.pg0.add_stream(pkts)
562 self.pg_enable_capture(self.pg_interfaces)
563 self.pg_start()
564 self.pg0.get_capture(0)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100565 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700566 rx = self.socket_client_close()
567 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100568
569 #
570 # remove punt socket. expect ICMP - dest. unreachable for all packets
571 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700572 self.vapi.punt_socket_deregister(punt_l4)
573 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100574 self.assertEqual(len(punts), 0)
575 self.pg0.add_stream(pkts)
576 self.pg_enable_capture(self.pg_interfaces)
577 self.pg_start()
578 # FIXME - when punt socket deregister is implemented
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100579 # self.pg0.get_capture(nr_packets)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100580
Neale Ranns50f0ac02019-05-15 02:13:37 -0700581 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100582 """ Punt socket traffic multi ports and multi sockets"""
583
Neale Ranns50f0ac02019-05-15 02:13:37 -0700584 punt_l4 = mk_vpp_cfg6()
585
586 # configuration for each UDP port
587 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100588
589 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700590 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100591 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700592 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100593 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700594 cfgs[port] = {}
595
596 pkt = (Ether(src=self.pg0.remote_mac,
597 dst=self.pg0.local_mac) /
598 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
599 UDP(sport=9876, dport=port) /
600 Raw('\xa5' * 100))
601 cfgs[port]['pkts'] = pkt * self.nr_packets
602 cfgs[port]['port'] = port
603 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
604
605 # configure punt sockets
606 cfgs[port]['sock'] = self.socket_client_create(
607 b"%s/socket_%d" % (six.ensure_binary(self.tempdir), port))
608 self.vapi.punt_socket_register(
609 cfgs[port]['vpp'],
610 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
611 port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100612
613 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700614 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100615 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700616 for cfg in cfgs.values():
617 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100618
619 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700620 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100621 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700622 for cfg in cfgs.values():
623 rx = cfg['sock'].close()
624 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
625 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100626
627 def test_punt_socket_traffic_multi_ports_single_socket(self):
628 """ Punt socket traffic multi ports and single socket"""
629
Neale Ranns50f0ac02019-05-15 02:13:37 -0700630 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
631 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
632 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
633 punt_l4 = {
634 'type': pt_l4,
635 'punt': {
636 'l4': {
637 'af': af_ip6,
638 'protocol': udp_proto,
639 }
640 }
641 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100642
643 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700644 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100645 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700646 pkts = []
647 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100648 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700649 pkt = (Ether(src=self.pg0.remote_mac,
650 dst=self.pg0.local_mac) /
651 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
652 UDP(sport=9876, dport=port) /
653 Raw('\xa5' * 100))
654 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100655
656 #
657 # no punt socket
658 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700659 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100660 self.assertEqual(len(punts), 0)
661
662 #
663 # configure a punt socket
664 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800665 self.socket_client_create(b"%s/socket_multi" %
666 six.ensure_binary(self.tempdir))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100667 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700668 self.vapi.punt_socket_register(set_port(punt_l4, p),
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800669 b"%s/socket_multi" %
Neale Ranns50f0ac02019-05-15 02:13:37 -0700670 six.ensure_binary(self.tempdir))
671 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100672 self.assertEqual(len(punts), len(self.ports))
673
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100674 #
675 # expect punt socket and no packets on pg0
676 #
677 self.vapi.cli("clear errors")
678 self.vapi.cli("clear trace")
679 self.pg0.add_stream(pkts)
680 self.pg_enable_capture(self.pg_interfaces)
681 self.pg_start()
682 self.pg0.get_capture(0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700683 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100684
685 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700686 self.verify_udp_pkts(rx, self.nr_packets, p)
687 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
688 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100689 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100690
Neale Ranns76b56492018-09-28 15:16:14 +0000691
Neale Ranns50f0ac02019-05-15 02:13:37 -0700692class TestExceptionPuntSocket(TestPuntSocket):
693 """ Punt Socket for Exceptions """
694
695 @classmethod
696 def setUpClass(cls):
697 super(TestExceptionPuntSocket, cls).setUpClass()
698
699 @classmethod
700 def tearDownClass(cls):
701 super(TestExceptionPuntSocket, cls).tearDownClass()
702
703 def setUp(self):
704 super(TestExceptionPuntSocket, self).setUp()
705
706 for i in self.pg_interfaces:
707 i.config_ip4()
708 i.resolve_arp()
709
710 def tearDown(self):
711 super(TestExceptionPuntSocket, self).tearDown()
712 for i in self.pg_interfaces:
713 i.unconfig_ip4()
714 i.admin_down()
715
716 def test_registration(self):
717 """ Punt socket registration/deregistration"""
718
719 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
720
721 punts = self.vapi.punt_socket_dump(type=pt_ex)
722 self.assertEqual(len(punts), 0)
723
724 #
725 # configure a punt socket
726 #
727 punt_ex = {
728 'type': pt_ex,
729 'punt': {
730 'exception': {}
731 }
732 }
733
734 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
735 b"%s/socket_punt_1" %
736 six.ensure_binary(self.tempdir))
737 self.vapi.punt_socket_register(set_reason(punt_ex, 2),
738 b"%s/socket_punt_2" %
739 six.ensure_binary(self.tempdir))
740 punts = self.vapi.punt_socket_dump(type=pt_ex)
741 self.assertEqual(len(punts), 2)
742 self.verify_exception(set_reason(punt_ex, 1), punts[0])
743 self.verify_exception(set_reason(punt_ex, 2), punts[1])
744
745 #
746 # deregister a punt socket
747 #
748 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
749 punts = self.vapi.punt_socket_dump(type=pt_ex)
750 self.assertEqual(len(punts), 1)
751
752 #
753 # configure a punt socket again
754 #
755 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
756 b"%s/socket_punt_1" %
757 six.ensure_binary(self.tempdir))
758 self.vapi.punt_socket_register(set_reason(punt_ex, 3),
759 b"%s/socket_punt_3" %
760 six.ensure_binary(self.tempdir))
761 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 Rannsa6bee0a2019-06-14 01:13:25 -0700797 # we need an IPSec tunnels for this to work otherwise ESP gets dropped
Neale Ranns50f0ac02019-05-15 02:13:37 -0700798 # due to unknown IP proto
799 #
800 VppIpsecTunInterface(self, self.pg0, 1000, 1000,
801 (VppEnum.vl_api_ipsec_crypto_alg_t.
802 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
803 "0123456701234567",
804 "0123456701234567",
805 (VppEnum.vl_api_ipsec_integ_alg_t.
806 IPSEC_API_INTEG_ALG_SHA1_96),
807 "0123456701234567",
808 "0123456701234567").add_vpp_config()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700809 VppIpsecTunInterface(self, self.pg0, 1001, 1001,
810 (VppEnum.vl_api_ipsec_crypto_alg_t.
811 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
812 "0123456701234567",
813 "0123456701234567",
814 (VppEnum.vl_api_ipsec_integ_alg_t.
815 IPSEC_API_INTEG_ALG_SHA1_96),
816 "0123456701234567",
817 "0123456701234567",
818 udp_encap=True).add_vpp_config()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700819
820 #
821 # we're dealing with IPSec tunnels punting for no-such-tunnel
822 # adn SPI=0
823 #
824 cfgs = dict()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700825 cfgs['ipsec4-no-such-tunnel'] = {'spi': 99, 'udp': False}
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700826 cfgs['ipsec4-spi-o-udp-0'] = {'spi': 0, 'udp': True}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700827
828 #
829 # find the VPP ID for these punt exception reasin
830 #
831 rs = self.vapi.punt_reason_dump()
832 for key in cfgs:
833 for r in rs:
834 if r.reason.name == key:
835 cfgs[key]['id'] = r.reason.id
836 cfgs[key]['vpp'] = copy.deepcopy(
837 set_reason(punt_ex,
838 cfgs[key]['id']))
839 break
840
841 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700842 # configure punt sockets
Neale Ranns50f0ac02019-05-15 02:13:37 -0700843 #
844 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700845 cfg['sock'] = self.socket_client_create(b"%s/socket_%d" % (
846 six.ensure_binary(self.tempdir), cfg['id']))
847 self.vapi.punt_socket_register(
848 cfg['vpp'],
849 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
850 cfg['id']))
851
852 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700853 # create packet streams for 'no-such-tunnel' exception
854 #
855 for cfg in cfgs.values():
856 pkt = (Ether(src=self.pg0.remote_mac,
857 dst=self.pg0.local_mac) /
858 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4))
859 if (cfg['udp']):
860 pkt = pkt / UDP(sport=666, dport=4500)
861 pkt = (pkt / ESP(spi=cfg['spi'], seq=3) /
862 Raw('\xa5' * 100))
863 cfg['pkts'] = [pkt]
864
865 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700866 # send packets for each SPI we expect to be punted
867 #
868 for cfg in cfgs.values():
869 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
870
871 #
872 # verify the punted packets arrived on the associated socket
873 #
874 for cfg in cfgs.values():
875 rx = cfg['sock'].close()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700876 self.verify_esp_pkts(rx, len(cfg['pkts']),
877 cfg['spi'], cfg['udp'])
878
879 #
880 # socket deregister
881 #
882 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700883 self.vapi.punt_socket_deregister(cfg['vpp'])
884
885
Neale Rannsb538dd82019-05-21 06:54:54 -0700886class TestIpProtoPuntSocket(TestPuntSocket):
887 """ Punt Socket for IP packets """
888
889 @classmethod
890 def setUpClass(cls):
891 super(TestIpProtoPuntSocket, cls).setUpClass()
892
893 @classmethod
894 def tearDownClass(cls):
895 super(TestIpProtoPuntSocket, cls).tearDownClass()
896
897 def setUp(self):
898 super(TestIpProtoPuntSocket, self).setUp()
899
900 for i in self.pg_interfaces:
901 i.config_ip4()
902 i.resolve_arp()
903
904 def tearDown(self):
905 super(TestIpProtoPuntSocket, self).tearDown()
906 for i in self.pg_interfaces:
907 i.unconfig_ip4()
908 i.admin_down()
909
910 def test_registration(self):
911 """ Punt socket registration/deregistration"""
912
913 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
914 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
915 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
916 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
917
918 punts = self.vapi.punt_socket_dump(type=pt_ip)
919 self.assertEqual(len(punts), 0)
920
921 #
922 # configure a punt socket
923 #
924 punt_ospf = {
925 'type': pt_ip,
926 'punt': {
927 'ip_proto': {
928 'af': af_ip4,
929 'protocol': proto_ospf
930 }
931 }
932 }
933 punt_eigrp = {
934 'type': pt_ip,
935 'punt': {
936 'ip_proto': {
937 'af': af_ip4,
938 'protocol': proto_eigrp
939 }
940 }
941 }
942
943 self.vapi.punt_socket_register(punt_ospf,
944 b"%s/socket_punt_1" %
945 six.ensure_binary(self.tempdir))
946 self.vapi.punt_socket_register(punt_eigrp,
947 b"%s/socket_punt_2" %
948 six.ensure_binary(self.tempdir))
949 self.logger.info(self.vapi.cli("sh punt sock reg ip"))
950 punts = self.vapi.punt_socket_dump(type=pt_ip)
951 self.assertEqual(len(punts), 2)
952 self.verify_ip_proto(punt_ospf, punts[0])
953 self.verify_ip_proto(punt_eigrp, punts[1])
954
955 #
956 # deregister a punt socket
957 #
958 self.vapi.punt_socket_deregister(punt_ospf)
959 punts = self.vapi.punt_socket_dump(type=pt_ip)
960 self.assertEqual(len(punts), 1)
961
962 #
963 # configure a punt socket again
964 #
965 self.vapi.punt_socket_register(punt_ospf,
966 b"%s/socket_punt_3" %
967 six.ensure_binary(self.tempdir))
968 punts = self.vapi.punt_socket_dump(type=pt_ip)
969 self.assertEqual(len(punts), 2)
970
971 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
972
973 #
974 # deregister all punt socket
975 #
976 self.vapi.punt_socket_deregister(punt_eigrp)
977 self.vapi.punt_socket_deregister(punt_ospf)
978 punts = self.vapi.punt_socket_dump(type=pt_ip)
979 self.assertEqual(len(punts), 0)
980
981 def verify_ospf_pkts(self, rxs, n_sent):
982 self.assertEqual(len(rxs), n_sent)
983 for rx in rxs:
984 self.assertTrue(rx.haslayer(OSPF_Hdr))
985
986 def test_traffic(self):
987 """ Punt socket traffic """
988
989 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
990 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
991 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
992
993 #
994 # configure a punt socket to capture OSPF packets
995 #
996 punt_ospf = {
997 'type': pt_ip,
998 'punt': {
999 'ip_proto': {
1000 'af': af_ip4,
1001 'protocol': proto_ospf
1002 }
1003 }
1004 }
1005
1006 #
1007 # create packet streams and configure a punt sockets
1008 #
1009 pkt = (Ether(src=self.pg0.remote_mac,
1010 dst=self.pg0.local_mac) /
1011 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1012 OSPF_Hdr() /
1013 OSPFv3_Hello())
1014 pkts = pkt * 7
1015
1016 sock = self.socket_client_create(b"%s/socket_1" % (
1017 six.ensure_binary(self.tempdir)))
1018 self.vapi.punt_socket_register(
1019 punt_ospf,
1020 b"%s/socket_1" % (six.ensure_binary(self.tempdir)))
1021
1022 #
1023 # send packets for each SPI we expect to be punted
1024 #
1025 self.send_and_assert_no_replies(self.pg0, pkts)
1026
1027 #
1028 # verify the punted packets arrived on the associated socket
1029 #
1030 rx = sock.close()
1031 self.verify_ospf_pkts(rx, len(pkts))
1032 self.vapi.punt_socket_deregister(punt_ospf)
1033
1034
Neale Ranns76b56492018-09-28 15:16:14 +00001035class TestPunt(VppTestCase):
Neale Rannsb538dd82019-05-21 06:54:54 -07001036 """ Exception Punt Test Case """
Neale Ranns76b56492018-09-28 15:16:14 +00001037
1038 @classmethod
1039 def setUpClass(cls):
1040 super(TestPunt, cls).setUpClass()
1041
1042 @classmethod
1043 def tearDownClass(cls):
1044 super(TestPunt, cls).tearDownClass()
1045
1046 def setUp(self):
1047 super(TestPunt, self).setUp()
1048
1049 self.create_pg_interfaces(range(4))
1050
1051 for i in self.pg_interfaces:
1052 i.admin_up()
1053 i.config_ip4()
1054 i.resolve_arp()
1055 i.config_ip6()
1056 i.resolve_ndp()
1057
1058 def tearDown(self):
1059 for i in self.pg_interfaces:
1060 i.unconfig_ip4()
1061 i.unconfig_ip6()
1062 i.ip6_disable()
1063 i.admin_down()
1064 super(TestPunt, self).tearDown()
1065
1066 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -07001067 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +00001068
1069 #
Neale Ranns719beb72019-07-10 07:10:25 +00001070 # dump the punt registered reasons
1071 # search for a few we know should be there
1072 #
1073 rs = self.vapi.punt_reason_dump()
1074
1075 reasons = ["ipsec6-no-such-tunnel",
1076 "ipsec4-no-such-tunnel",
1077 "ipsec4-spi-o-udp-0"]
1078
1079 for reason in reasons:
1080 found = False
1081 for r in rs:
1082 if r.reason.name == reason:
1083 found = True
1084 break
1085 self.assertTrue(found)
1086
1087 #
Neale Ranns76b56492018-09-28 15:16:14 +00001088 # Using the test CLI we will hook in a exception path to
1089 # send ACL deny packets out of pg0 and pg1.
1090 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1091 #
1092 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1093 [VppRoutePath(self.pg3.remote_ip4,
1094 self.pg3.sw_if_index)])
1095 ip_1_1_1_2.add_vpp_config()
1096 ip_1_2 = VppIpRoute(self, "1::2", 128,
1097 [VppRoutePath(self.pg3.remote_ip6,
1098 self.pg3.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001099 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns76b56492018-09-28 15:16:14 +00001100 ip_1_2.add_vpp_config()
1101
1102 p4 = (Ether(src=self.pg2.remote_mac,
1103 dst=self.pg2.local_mac) /
1104 IP(src="1.1.1.1", dst="1.1.1.2") /
1105 UDP(sport=1234, dport=1234) /
1106 Raw('\xa5' * 100))
1107 p6 = (Ether(src=self.pg2.remote_mac,
1108 dst=self.pg2.local_mac) /
1109 IPv6(src="1::1", dst="1::2") /
1110 UDP(sport=1234, dport=1234) /
1111 Raw('\xa5' * 100))
1112 self.send_and_expect(self.pg2, p4*1, self.pg3)
1113 self.send_and_expect(self.pg2, p6*1, self.pg3)
1114
1115 #
1116 # apply the punting features
1117 #
1118 self.vapi.cli("test punt pg2")
1119
1120 #
Neale Ranns719beb72019-07-10 07:10:25 +00001121 # dump the punt reasons to learn the IDs assigned
1122 #
1123 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v4"})
1124 r4 = rs[0].reason.id
1125 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v6"})
1126 r6 = rs[0].reason.id
1127
1128 #
Neale Ranns76b56492018-09-28 15:16:14 +00001129 # pkts now dropped
1130 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001131 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
1132 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001133
1134 #
1135 # Check state:
1136 # 1 - node error counters
1137 # 2 - per-reason counters
1138 # 2, 3 are the index of the assigned punt reason
1139 #
Ole Troan233e4682019-05-16 15:01:34 +02001140 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +00001141 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001142 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001143
1144 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001145 self.assertEqual(stats[0][r4]['packets'], NUM_PKTS)
1146 self.assertEqual(stats[0][r6]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001147
1148 #
1149 # use the test CLI to test a client that punts exception
1150 # packets out of pg0
1151 #
1152 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1153 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1154
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001155 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
1156 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001157
1158 #
1159 # check the packets come out IP unmodified but destined to pg0 host
1160 #
1161 for rx in rx4s:
1162 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1163 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1164 self.assertEqual(p4[IP].dst, rx[IP].dst)
1165 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1166 for rx in rx6s:
1167 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1168 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1169 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1170 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1171
1172 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001173 self.assertEqual(stats[0][r4]['packets'], 2*NUM_PKTS)
1174 self.assertEqual(stats[0][r6]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001175
1176 #
1177 # add another registration for the same reason to send packets
1178 # out of pg1
1179 #
1180 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1181 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1182
1183 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001184 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001185 self.pg_enable_capture(self.pg_interfaces)
1186 self.pg_start()
1187
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001188 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001189 for rx in rxd:
1190 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1191 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1192 self.assertEqual(p4[IP].dst, rx[IP].dst)
1193 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001194 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001195 for rx in rxd:
1196 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1197 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1198 self.assertEqual(p4[IP].dst, rx[IP].dst)
1199 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1200
1201 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001202 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001203 self.pg_enable_capture(self.pg_interfaces)
1204 self.pg_start()
1205
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001206 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001207 for rx in rxd:
1208 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1209 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1210 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1211 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001212 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001213 for rx in rxd:
1214 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1215 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1216 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1217 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1218
1219 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001220 self.assertEqual(stats[0][r4]['packets'], 3*NUM_PKTS)
1221 self.assertEqual(stats[0][r6]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001222
1223 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1224 self.logger.info(self.vapi.cli("show punt client"))
1225 self.logger.info(self.vapi.cli("show punt reason"))
1226 self.logger.info(self.vapi.cli("show punt stats"))
1227 self.logger.info(self.vapi.cli("show punt db"))
1228
Neale Ranns76b56492018-09-28 15:16:14 +00001229
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001230if __name__ == '__main__':
1231 unittest.main(testRunner=VppTestRunner)