blob: b305e08bf5c1f81b6df7a646921da0b1deab2faa [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}
826 cfgs['ipsec4-spi-0'] = {'spi': 0, 'udp': False}
827 cfgs['ipsec4-spi-o-udp-0'] = {'spi': 0, 'udp': True}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700828
829 #
830 # find the VPP ID for these punt exception reasin
831 #
832 rs = self.vapi.punt_reason_dump()
833 for key in cfgs:
834 for r in rs:
835 if r.reason.name == key:
836 cfgs[key]['id'] = r.reason.id
837 cfgs[key]['vpp'] = copy.deepcopy(
838 set_reason(punt_ex,
839 cfgs[key]['id']))
840 break
841
842 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700843 # configure punt sockets
Neale Ranns50f0ac02019-05-15 02:13:37 -0700844 #
845 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700846 cfg['sock'] = self.socket_client_create(b"%s/socket_%d" % (
847 six.ensure_binary(self.tempdir), cfg['id']))
848 self.vapi.punt_socket_register(
849 cfg['vpp'],
850 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
851 cfg['id']))
852
853 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700854 # create packet streams for 'no-such-tunnel' exception
855 #
856 for cfg in cfgs.values():
857 pkt = (Ether(src=self.pg0.remote_mac,
858 dst=self.pg0.local_mac) /
859 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4))
860 if (cfg['udp']):
861 pkt = pkt / UDP(sport=666, dport=4500)
862 pkt = (pkt / ESP(spi=cfg['spi'], seq=3) /
863 Raw('\xa5' * 100))
864 cfg['pkts'] = [pkt]
865
866 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700867 # send packets for each SPI we expect to be punted
868 #
869 for cfg in cfgs.values():
870 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
871
872 #
873 # verify the punted packets arrived on the associated socket
874 #
875 for cfg in cfgs.values():
876 rx = cfg['sock'].close()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700877 self.verify_esp_pkts(rx, len(cfg['pkts']),
878 cfg['spi'], cfg['udp'])
879
880 #
881 # socket deregister
882 #
883 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700884 self.vapi.punt_socket_deregister(cfg['vpp'])
885
886
Neale Rannsb538dd82019-05-21 06:54:54 -0700887class TestIpProtoPuntSocket(TestPuntSocket):
888 """ Punt Socket for IP packets """
889
890 @classmethod
891 def setUpClass(cls):
892 super(TestIpProtoPuntSocket, cls).setUpClass()
893
894 @classmethod
895 def tearDownClass(cls):
896 super(TestIpProtoPuntSocket, cls).tearDownClass()
897
898 def setUp(self):
899 super(TestIpProtoPuntSocket, self).setUp()
900
901 for i in self.pg_interfaces:
902 i.config_ip4()
903 i.resolve_arp()
904
905 def tearDown(self):
906 super(TestIpProtoPuntSocket, self).tearDown()
907 for i in self.pg_interfaces:
908 i.unconfig_ip4()
909 i.admin_down()
910
911 def test_registration(self):
912 """ Punt socket registration/deregistration"""
913
914 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
915 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
916 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
917 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
918
919 punts = self.vapi.punt_socket_dump(type=pt_ip)
920 self.assertEqual(len(punts), 0)
921
922 #
923 # configure a punt socket
924 #
925 punt_ospf = {
926 'type': pt_ip,
927 'punt': {
928 'ip_proto': {
929 'af': af_ip4,
930 'protocol': proto_ospf
931 }
932 }
933 }
934 punt_eigrp = {
935 'type': pt_ip,
936 'punt': {
937 'ip_proto': {
938 'af': af_ip4,
939 'protocol': proto_eigrp
940 }
941 }
942 }
943
944 self.vapi.punt_socket_register(punt_ospf,
945 b"%s/socket_punt_1" %
946 six.ensure_binary(self.tempdir))
947 self.vapi.punt_socket_register(punt_eigrp,
948 b"%s/socket_punt_2" %
949 six.ensure_binary(self.tempdir))
950 self.logger.info(self.vapi.cli("sh punt sock reg ip"))
951 punts = self.vapi.punt_socket_dump(type=pt_ip)
952 self.assertEqual(len(punts), 2)
953 self.verify_ip_proto(punt_ospf, punts[0])
954 self.verify_ip_proto(punt_eigrp, punts[1])
955
956 #
957 # deregister a punt socket
958 #
959 self.vapi.punt_socket_deregister(punt_ospf)
960 punts = self.vapi.punt_socket_dump(type=pt_ip)
961 self.assertEqual(len(punts), 1)
962
963 #
964 # configure a punt socket again
965 #
966 self.vapi.punt_socket_register(punt_ospf,
967 b"%s/socket_punt_3" %
968 six.ensure_binary(self.tempdir))
969 punts = self.vapi.punt_socket_dump(type=pt_ip)
970 self.assertEqual(len(punts), 2)
971
972 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
973
974 #
975 # deregister all punt socket
976 #
977 self.vapi.punt_socket_deregister(punt_eigrp)
978 self.vapi.punt_socket_deregister(punt_ospf)
979 punts = self.vapi.punt_socket_dump(type=pt_ip)
980 self.assertEqual(len(punts), 0)
981
982 def verify_ospf_pkts(self, rxs, n_sent):
983 self.assertEqual(len(rxs), n_sent)
984 for rx in rxs:
985 self.assertTrue(rx.haslayer(OSPF_Hdr))
986
987 def test_traffic(self):
988 """ Punt socket traffic """
989
990 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
991 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
992 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
993
994 #
995 # configure a punt socket to capture OSPF packets
996 #
997 punt_ospf = {
998 'type': pt_ip,
999 'punt': {
1000 'ip_proto': {
1001 'af': af_ip4,
1002 'protocol': proto_ospf
1003 }
1004 }
1005 }
1006
1007 #
1008 # create packet streams and configure a punt sockets
1009 #
1010 pkt = (Ether(src=self.pg0.remote_mac,
1011 dst=self.pg0.local_mac) /
1012 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1013 OSPF_Hdr() /
1014 OSPFv3_Hello())
1015 pkts = pkt * 7
1016
1017 sock = self.socket_client_create(b"%s/socket_1" % (
1018 six.ensure_binary(self.tempdir)))
1019 self.vapi.punt_socket_register(
1020 punt_ospf,
1021 b"%s/socket_1" % (six.ensure_binary(self.tempdir)))
1022
1023 #
1024 # send packets for each SPI we expect to be punted
1025 #
1026 self.send_and_assert_no_replies(self.pg0, pkts)
1027
1028 #
1029 # verify the punted packets arrived on the associated socket
1030 #
1031 rx = sock.close()
1032 self.verify_ospf_pkts(rx, len(pkts))
1033 self.vapi.punt_socket_deregister(punt_ospf)
1034
1035
Neale Ranns76b56492018-09-28 15:16:14 +00001036class TestPunt(VppTestCase):
Neale Rannsb538dd82019-05-21 06:54:54 -07001037 """ Exception Punt Test Case """
Neale Ranns76b56492018-09-28 15:16:14 +00001038
1039 @classmethod
1040 def setUpClass(cls):
1041 super(TestPunt, cls).setUpClass()
1042
1043 @classmethod
1044 def tearDownClass(cls):
1045 super(TestPunt, cls).tearDownClass()
1046
1047 def setUp(self):
1048 super(TestPunt, self).setUp()
1049
1050 self.create_pg_interfaces(range(4))
1051
1052 for i in self.pg_interfaces:
1053 i.admin_up()
1054 i.config_ip4()
1055 i.resolve_arp()
1056 i.config_ip6()
1057 i.resolve_ndp()
1058
1059 def tearDown(self):
1060 for i in self.pg_interfaces:
1061 i.unconfig_ip4()
1062 i.unconfig_ip6()
1063 i.ip6_disable()
1064 i.admin_down()
1065 super(TestPunt, self).tearDown()
1066
1067 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -07001068 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +00001069
1070 #
1071 # Using the test CLI we will hook in a exception path to
1072 # send ACL deny packets out of pg0 and pg1.
1073 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1074 #
1075 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1076 [VppRoutePath(self.pg3.remote_ip4,
1077 self.pg3.sw_if_index)])
1078 ip_1_1_1_2.add_vpp_config()
1079 ip_1_2 = VppIpRoute(self, "1::2", 128,
1080 [VppRoutePath(self.pg3.remote_ip6,
1081 self.pg3.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001082 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns76b56492018-09-28 15:16:14 +00001083 ip_1_2.add_vpp_config()
1084
1085 p4 = (Ether(src=self.pg2.remote_mac,
1086 dst=self.pg2.local_mac) /
1087 IP(src="1.1.1.1", dst="1.1.1.2") /
1088 UDP(sport=1234, dport=1234) /
1089 Raw('\xa5' * 100))
1090 p6 = (Ether(src=self.pg2.remote_mac,
1091 dst=self.pg2.local_mac) /
1092 IPv6(src="1::1", dst="1::2") /
1093 UDP(sport=1234, dport=1234) /
1094 Raw('\xa5' * 100))
1095 self.send_and_expect(self.pg2, p4*1, self.pg3)
1096 self.send_and_expect(self.pg2, p6*1, self.pg3)
1097
1098 #
1099 # apply the punting features
1100 #
1101 self.vapi.cli("test punt pg2")
1102
1103 #
1104 # pkts now dropped
1105 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001106 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
1107 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001108
1109 #
1110 # Check state:
1111 # 1 - node error counters
1112 # 2 - per-reason counters
1113 # 2, 3 are the index of the assigned punt reason
1114 #
Ole Troan233e4682019-05-16 15:01:34 +02001115 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +00001116 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001117 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001118
1119 stats = self.statistics.get_counter("/net/punt")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001120 self.assertEqual(stats[0][7]['packets'], NUM_PKTS)
1121 self.assertEqual(stats[0][8]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001122
1123 #
1124 # use the test CLI to test a client that punts exception
1125 # packets out of pg0
1126 #
1127 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1128 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1129
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001130 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
1131 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001132
1133 #
1134 # check the packets come out IP unmodified but destined to pg0 host
1135 #
1136 for rx in rx4s:
1137 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1138 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1139 self.assertEqual(p4[IP].dst, rx[IP].dst)
1140 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1141 for rx in rx6s:
1142 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1143 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1144 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1145 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1146
1147 stats = self.statistics.get_counter("/net/punt")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001148 self.assertEqual(stats[0][7]['packets'], 2*NUM_PKTS)
1149 self.assertEqual(stats[0][8]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001150
1151 #
1152 # add another registration for the same reason to send packets
1153 # out of pg1
1154 #
1155 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1156 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1157
1158 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001159 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001160 self.pg_enable_capture(self.pg_interfaces)
1161 self.pg_start()
1162
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001163 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001164 for rx in rxd:
1165 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1166 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1167 self.assertEqual(p4[IP].dst, rx[IP].dst)
1168 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001169 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001170 for rx in rxd:
1171 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1172 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1173 self.assertEqual(p4[IP].dst, rx[IP].dst)
1174 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1175
1176 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001177 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001178 self.pg_enable_capture(self.pg_interfaces)
1179 self.pg_start()
1180
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001181 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001182 for rx in rxd:
1183 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1184 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1185 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1186 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001187 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001188 for rx in rxd:
1189 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1190 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1191 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1192 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1193
1194 stats = self.statistics.get_counter("/net/punt")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001195 self.assertEqual(stats[0][7]['packets'], 3*NUM_PKTS)
1196 self.assertEqual(stats[0][8]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001197
1198 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1199 self.logger.info(self.vapi.cli("show punt client"))
1200 self.logger.info(self.vapi.cli("show punt reason"))
1201 self.logger.info(self.vapi.cli("show punt stats"))
1202 self.logger.info(self.vapi.cli("show punt db"))
1203
Neale Ranns50f0ac02019-05-15 02:13:37 -07001204 #
1205 # dump the punt registered reasons
1206 # search for a few we know should be there
1207 #
1208 rs = self.vapi.punt_reason_dump()
1209
1210 reasons = ["ipsec6-no-such-tunnel",
1211 "ipsec4-no-such-tunnel",
1212 "ipsec6-spi-0",
1213 "ipsec4-spi-0"]
1214
1215 for reason in reasons:
1216 found = False
1217 for r in rs:
1218 if r.reason.name == reason:
1219 found = True
1220 break
1221 self.assertTrue(found)
1222
Neale Ranns76b56492018-09-28 15:16:14 +00001223
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001224if __name__ == '__main__':
1225 unittest.main(testRunner=VppTestRunner)