blob: 0b4585a15c7961d00ad985f1e5fe05f1228d1277 [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()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +000080 # FIXME: nr_packets > 3 results in failure
81 # nr_packets = 3 makes the test unstable
82 nr_packets = 2
Pavel Kotuceke88865d2018-11-28 07:42:11 +010083
84 @classmethod
Paul Vinciguerra8d991d92019-01-25 14:05:48 -080085 def setUpClass(cls):
86 super(TestPuntSocket, cls).setUpClass()
87
88 @classmethod
89 def tearDownClass(cls):
90 super(TestPuntSocket, cls).tearDownClass()
91
92 @classmethod
Pavel Kotuceke88865d2018-11-28 07:42:11 +010093 def setUpConstants(cls):
Ole Troana45dc072018-12-21 16:04:22 +010094 cls.extra_vpp_punt_config = [
95 "punt", "{", "socket", cls.tempdir+"/socket_punt", "}"]
Pavel Kotuceke88865d2018-11-28 07:42:11 +010096 super(TestPuntSocket, cls).setUpConstants()
97
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010098 def setUp(self):
99 super(TestPuntSocket, self).setUp()
100 random.seed()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100101
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100102 self.create_pg_interfaces(range(2))
103 for i in self.pg_interfaces:
104 i.admin_up()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100105
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100106 def tearDown(self):
107 del self.sock_servers[:]
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800108 super(TestPuntSocket, self).tearDown()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100109
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100110 def socket_client_create(self, sock_name, id=None):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700111 thread = serverSocketThread(id, sock_name)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100112 self.sock_servers.append(thread)
113 thread.start()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700114 return thread
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100115
116 def socket_client_close(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700117 rx_pkts = []
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100118 for thread in self.sock_servers:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700119 rx_pkts += thread.close()
120 return rx_pkts
121
122 def verify_port(self, pr, vpr):
123 self.assertEqual(vpr.punt.type, pr['type'])
124 self.assertEqual(vpr.punt.punt.l4.port,
125 pr['punt']['l4']['port'])
126 self.assertEqual(vpr.punt.punt.l4.protocol,
127 pr['punt']['l4']['protocol'])
128 self.assertEqual(vpr.punt.punt.l4.af,
129 pr['punt']['l4']['af'])
130
131 def verify_exception(self, pr, vpr):
132 self.assertEqual(vpr.punt.type, pr['type'])
133 self.assertEqual(vpr.punt.punt.exception.id,
134 pr['punt']['exception']['id'])
135
Neale Rannsb538dd82019-05-21 06:54:54 -0700136 def verify_ip_proto(self, pr, vpr):
137 self.assertEqual(vpr.punt.type, pr['type'])
138 self.assertEqual(vpr.punt.punt.ip_proto.af,
139 pr['punt']['ip_proto']['af'])
140 self.assertEqual(vpr.punt.punt.ip_proto.protocol,
141 pr['punt']['ip_proto']['protocol'])
142
Neale Ranns50f0ac02019-05-15 02:13:37 -0700143 def verify_udp_pkts(self, rxs, n_rx, port):
144 n_match = 0
145 for rx in rxs:
146 self.assertTrue(rx.haslayer(UDP))
147 if rx[UDP].dport == port:
148 n_match += 1
149 self.assertEqual(n_match, n_rx)
150
151
152def set_port(pr, port):
153 pr['punt']['l4']['port'] = port
154 return pr
155
156
157def set_reason(pr, reason):
158 pr['punt']['exception']['id'] = reason
159 return pr
160
161
162def mk_vpp_cfg4():
163 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
164 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
165 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
166 punt_l4 = {
167 'type': pt_l4,
168 'punt': {
169 'l4': {
170 'af': af_ip4,
171 'protocol': udp_proto
172 }
173 }
174 }
175 return punt_l4
176
177
178def mk_vpp_cfg6():
179 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
180 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
181 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
182 punt_l4 = {
183 'type': pt_l4,
184 'punt': {
185 'l4': {
186 'af': af_ip6,
187 'protocol': udp_proto
188 }
189 }
190 }
191 return punt_l4
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100192
193
194class TestIP4PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700195 """ Punt Socket for IPv4 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100196
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800197 @classmethod
198 def setUpClass(cls):
199 super(TestIP4PuntSocket, cls).setUpClass()
200
201 @classmethod
202 def tearDownClass(cls):
203 super(TestIP4PuntSocket, cls).tearDownClass()
204
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100205 def setUp(self):
206 super(TestIP4PuntSocket, self).setUp()
207
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100208 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100209 i.config_ip4()
210 i.resolve_arp()
211
212 def tearDown(self):
213 super(TestIP4PuntSocket, self).tearDown()
214 for i in self.pg_interfaces:
215 i.unconfig_ip4()
216 i.admin_down()
217
218 def test_punt_socket_dump(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100219 """ Punt socket registration/deregistration"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100220
Neale Ranns50f0ac02019-05-15 02:13:37 -0700221 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
222 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
223 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
224
225 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100226 self.assertEqual(len(punts), 0)
227
228 #
229 # configure a punt socket
230 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700231 punt_l4 = mk_vpp_cfg4()
232
233 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
234 b"%s/socket_punt_1111" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800235 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700236 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
237 b"%s/socket_punt_2222" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800238 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700239 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100240 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700241 self.verify_port(set_port(punt_l4, 1111), punts[0])
242 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100243
244 #
245 # deregister a punt socket
246 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700247 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
248 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100249 self.assertEqual(len(punts), 1)
250
251 #
252 # configure a punt socket again
253 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700254 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
255 b"%s/socket_punt_1111" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800256 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700257 self.vapi.punt_socket_register(set_port(punt_l4, 3333),
258 b"%s/socket_punt_3333" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800259 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700260 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100261 self.assertEqual(len(punts), 3)
262
Neale Ranns50f0ac02019-05-15 02:13:37 -0700263 self.logger.info(self.vapi.cli("sh punt sock reg"))
264
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100265 #
266 # deregister all punt socket
267 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700268 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
269 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
270 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
271 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100272 self.assertEqual(len(punts), 0)
273
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100274 def test_punt_socket_traffic_single_port_single_socket(self):
275 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100276
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100277 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700278 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
279 punt_l4 = set_port(mk_vpp_cfg4(), port)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100280
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100281 p = (Ether(src=self.pg0.remote_mac,
282 dst=self.pg0.local_mac) /
283 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100284 UDP(sport=9876, dport=port) /
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100285 Raw('\xa5' * 100))
286
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100287 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100288
Neale Ranns50f0ac02019-05-15 02:13:37 -0700289 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100290 self.assertEqual(len(punts), 0)
291
292 #
293 # expect ICMP - port unreachable for all packets
294 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700295 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
296
297 for p in rx:
298 self.assertEqual(int(p[IP].proto), 1) # ICMP
299 self.assertEqual(int(p[ICMP].code), 3) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100300
301 #
302 # configure a punt socket
303 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800304 self.socket_client_create(b"%s/socket_%d" % (
305 six.ensure_binary(self.tempdir), port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700306 self.vapi.punt_socket_register(punt_l4, b"%s/socket_%d" % (
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800307 six.ensure_binary(self.tempdir), port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700308 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100309 self.assertEqual(len(punts), 1)
310
311 #
312 # expect punt socket and no packets on pg0
313 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700314 self.send_and_assert_no_replies(self.pg0, pkts)
315 rx = self.socket_client_close()
316 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100317
318 #
319 # remove punt socket. expect ICMP - port unreachable for all packets
320 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700321 self.vapi.punt_socket_deregister(punt_l4)
322 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100323 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100324
Neale Ranns50f0ac02019-05-15 02:13:37 -0700325 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
326 for p in rx:
327 self.assertEqual(int(p[IP].proto), 1) # ICMP
328 self.assertEqual(int(p[ICMP].code), 3) # unreachable
329
330 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100331 """ Punt socket traffic multi ports and multi sockets"""
332
Neale Ranns50f0ac02019-05-15 02:13:37 -0700333 punt_l4 = mk_vpp_cfg4()
334
335 # configuration for each UDP port
336 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100337
338 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700339 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100340 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700341 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100342 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700343 cfgs[port] = {}
344
345 pkt = (Ether(src=self.pg0.remote_mac,
346 dst=self.pg0.local_mac) /
347 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
348 UDP(sport=9876, dport=port) /
349 Raw('\xa5' * 100))
350 cfgs[port]['pkts'] = pkt * self.nr_packets
351 cfgs[port]['port'] = port
352 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
353
354 # configure punt sockets
355 cfgs[port]['sock'] = self.socket_client_create(
356 b"%s/socket_%d" % (six.ensure_binary(self.tempdir), port))
357 self.vapi.punt_socket_register(
358 cfgs[port]['vpp'],
359 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
360 port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100361
362 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700363 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100364 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700365 for cfg in cfgs.values():
366 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100367
368 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700369 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100370 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700371 for cfg in cfgs.values():
372 rx = cfg['sock'].close()
373 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
374 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100375
376 def test_punt_socket_traffic_multi_ports_single_socket(self):
377 """ Punt socket traffic multi ports and single socket"""
378
Neale Ranns50f0ac02019-05-15 02:13:37 -0700379 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
380 punt_l4 = mk_vpp_cfg4()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100381
382 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700383 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100384 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700385 pkts = []
386 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100387 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700388 pkt = (Ether(src=self.pg0.remote_mac,
389 dst=self.pg0.local_mac) /
390 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
391 UDP(sport=9876, dport=port) /
392 Raw('\xa5' * 100))
393 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100394
395 #
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100396 # configure a punt socket
397 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800398 self.socket_client_create(b"%s/socket_multi" %
399 six.ensure_binary(self.tempdir))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100400 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700401 self.vapi.punt_socket_register(set_port(punt_l4, p),
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800402 b"%s/socket_multi" %
403 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700404 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100405 self.assertEqual(len(punts), len(self.ports))
406
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100407 #
408 # expect punt socket and no packets on pg0
409 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700410 self.send_and_assert_no_replies(self.pg0, pkts)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100411 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700412 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100413
414 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700415 self.verify_udp_pkts(rx, self.nr_packets, p)
416 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
417 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100418 self.assertEqual(len(punts), 0)
419
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100420
421class TestIP6PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700422 """ Punt Socket for IPv6 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100423
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800424 @classmethod
425 def setUpClass(cls):
426 super(TestIP6PuntSocket, cls).setUpClass()
427
428 @classmethod
429 def tearDownClass(cls):
430 super(TestIP6PuntSocket, cls).tearDownClass()
431
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100432 def setUp(self):
433 super(TestIP6PuntSocket, self).setUp()
434
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100435 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100436 i.config_ip6()
437 i.resolve_ndp()
438
439 def tearDown(self):
440 super(TestIP6PuntSocket, self).tearDown()
441 for i in self.pg_interfaces:
442 i.unconfig_ip6()
443 i.admin_down()
444
445 def test_punt_socket_dump(self):
446 """ Punt socket registration """
447
Neale Ranns50f0ac02019-05-15 02:13:37 -0700448 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
449 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
450 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
451 #
452 # configure a punt socket
453 #
454 punt_l4 = {
455 'type': pt_l4,
456 'punt': {
457 'l4': {
458 'af': af_ip6,
459 'protocol': udp_proto
460 }
461 }
462 }
463
464 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100465 self.assertEqual(len(punts), 0)
466
467 #
468 # configure a punt socket
469 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700470 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
471 b"%s/socket_1111" %
472 six.ensure_binary(self.tempdir))
473 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
474 b"%s/socket_2222" %
475 six.ensure_binary(self.tempdir))
476 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100477 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700478 self.verify_port(set_port(punt_l4, 1111), punts[0])
479 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100480
481 #
482 # deregister a punt socket
483 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700484 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
485 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100486 self.assertEqual(len(punts), 1)
487
488 #
489 # configure a punt socket again
490 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700491 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
492 b"%s/socket_1111" %
493 six.ensure_binary(self.tempdir))
494 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100495 self.assertEqual(len(punts), 2)
496
497 #
498 # deregister all punt socket
499 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700500 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
501 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
502 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
503 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100504 self.assertEqual(len(punts), 0)
505
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100506 def test_punt_socket_traffic_single_port_single_socket(self):
507 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100508
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100509 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700510 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
511 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
512 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
513 punt_l4 = {
514 'type': pt_l4,
515 'punt': {
516 'l4': {
517 'af': af_ip6,
518 'protocol': udp_proto,
519 'port': port,
520 }
521 }
522 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100523
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100524 p = (Ether(src=self.pg0.remote_mac,
525 dst=self.pg0.local_mac) /
526 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100527 inet6.UDP(sport=9876, dport=port) /
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100528 Raw('\xa5' * 100))
529
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100530 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100531
Neale Ranns50f0ac02019-05-15 02:13:37 -0700532 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100533 self.assertEqual(len(punts), 0)
534
535 #
536 # expect ICMPv6 - destination unreachable for all packets
537 #
538 self.vapi.cli("clear trace")
539 self.pg0.add_stream(pkts)
540 self.pg_enable_capture(self.pg_interfaces)
541 self.pg_start()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100542 # FIXME - when punt socket deregister is implemented
543 # rx = self.pg0.get_capture(self.nr_packets)
544 # for p in rx:
545 # self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
546 # self.assertEqual(int(p[ICMPv6DestUnreach].code),4) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100547
548 #
549 # configure a punt socket
550 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800551 self.socket_client_create(b"%s/socket_%d" % (
552 six.ensure_binary(self.tempdir), port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700553 self.vapi.punt_socket_register(punt_l4, b"%s/socket_%d" % (
554 six.ensure_binary(self.tempdir), port))
555 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100556 self.assertEqual(len(punts), 1)
557
558 #
559 # expect punt socket and no packets on pg0
560 #
561 self.vapi.cli("clear errors")
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100562 self.vapi.cli("clear trace")
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100563 self.pg0.add_stream(pkts)
564 self.pg_enable_capture(self.pg_interfaces)
565 self.pg_start()
566 self.pg0.get_capture(0)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100567 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700568 rx = self.socket_client_close()
569 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100570
571 #
572 # remove punt socket. expect ICMP - dest. unreachable for all packets
573 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700574 self.vapi.punt_socket_deregister(punt_l4)
575 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100576 self.assertEqual(len(punts), 0)
577 self.pg0.add_stream(pkts)
578 self.pg_enable_capture(self.pg_interfaces)
579 self.pg_start()
580 # FIXME - when punt socket deregister is implemented
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100581 # self.pg0.get_capture(nr_packets)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100582
Neale Ranns50f0ac02019-05-15 02:13:37 -0700583 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100584 """ Punt socket traffic multi ports and multi sockets"""
585
Neale Ranns50f0ac02019-05-15 02:13:37 -0700586 punt_l4 = mk_vpp_cfg6()
587
588 # configuration for each UDP port
589 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100590
591 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700592 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100593 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700594 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100595 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700596 cfgs[port] = {}
597
598 pkt = (Ether(src=self.pg0.remote_mac,
599 dst=self.pg0.local_mac) /
600 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
601 UDP(sport=9876, dport=port) /
602 Raw('\xa5' * 100))
603 cfgs[port]['pkts'] = pkt * self.nr_packets
604 cfgs[port]['port'] = port
605 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
606
607 # configure punt sockets
608 cfgs[port]['sock'] = self.socket_client_create(
609 b"%s/socket_%d" % (six.ensure_binary(self.tempdir), port))
610 self.vapi.punt_socket_register(
611 cfgs[port]['vpp'],
612 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
613 port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100614
615 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700616 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100617 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700618 for cfg in cfgs.values():
619 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100620
621 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700622 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100623 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700624 for cfg in cfgs.values():
625 rx = cfg['sock'].close()
626 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
627 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100628
629 def test_punt_socket_traffic_multi_ports_single_socket(self):
630 """ Punt socket traffic multi ports and single socket"""
631
Neale Ranns50f0ac02019-05-15 02:13:37 -0700632 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
633 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
634 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
635 punt_l4 = {
636 'type': pt_l4,
637 'punt': {
638 'l4': {
639 'af': af_ip6,
640 'protocol': udp_proto,
641 }
642 }
643 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100644
645 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700646 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100647 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700648 pkts = []
649 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100650 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700651 pkt = (Ether(src=self.pg0.remote_mac,
652 dst=self.pg0.local_mac) /
653 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
654 UDP(sport=9876, dport=port) /
655 Raw('\xa5' * 100))
656 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100657
658 #
659 # no punt socket
660 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700661 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100662 self.assertEqual(len(punts), 0)
663
664 #
665 # configure a punt socket
666 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800667 self.socket_client_create(b"%s/socket_multi" %
668 six.ensure_binary(self.tempdir))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100669 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700670 self.vapi.punt_socket_register(set_port(punt_l4, p),
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800671 b"%s/socket_multi" %
Neale Ranns50f0ac02019-05-15 02:13:37 -0700672 six.ensure_binary(self.tempdir))
673 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100674 self.assertEqual(len(punts), len(self.ports))
675
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100676 #
677 # expect punt socket and no packets on pg0
678 #
679 self.vapi.cli("clear errors")
680 self.vapi.cli("clear trace")
681 self.pg0.add_stream(pkts)
682 self.pg_enable_capture(self.pg_interfaces)
683 self.pg_start()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +0000684 # give a chance to punt socket to collect all packets
685 self.sleep(1)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100686 self.pg0.get_capture(0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700687 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100688
689 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700690 self.verify_udp_pkts(rx, self.nr_packets, p)
691 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
692 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100693 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100694
Neale Ranns76b56492018-09-28 15:16:14 +0000695
Neale Ranns50f0ac02019-05-15 02:13:37 -0700696class TestExceptionPuntSocket(TestPuntSocket):
697 """ Punt Socket for Exceptions """
698
699 @classmethod
700 def setUpClass(cls):
701 super(TestExceptionPuntSocket, cls).setUpClass()
702
703 @classmethod
704 def tearDownClass(cls):
705 super(TestExceptionPuntSocket, cls).tearDownClass()
706
707 def setUp(self):
708 super(TestExceptionPuntSocket, self).setUp()
709
710 for i in self.pg_interfaces:
711 i.config_ip4()
712 i.resolve_arp()
713
714 def tearDown(self):
715 super(TestExceptionPuntSocket, self).tearDown()
716 for i in self.pg_interfaces:
717 i.unconfig_ip4()
718 i.admin_down()
719
720 def test_registration(self):
721 """ Punt socket registration/deregistration"""
722
723 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
724
725 punts = self.vapi.punt_socket_dump(type=pt_ex)
726 self.assertEqual(len(punts), 0)
727
728 #
729 # configure a punt socket
730 #
731 punt_ex = {
732 'type': pt_ex,
733 'punt': {
734 'exception': {}
735 }
736 }
737
738 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
739 b"%s/socket_punt_1" %
740 six.ensure_binary(self.tempdir))
741 self.vapi.punt_socket_register(set_reason(punt_ex, 2),
742 b"%s/socket_punt_2" %
743 six.ensure_binary(self.tempdir))
744 punts = self.vapi.punt_socket_dump(type=pt_ex)
745 self.assertEqual(len(punts), 2)
746 self.verify_exception(set_reason(punt_ex, 1), punts[0])
747 self.verify_exception(set_reason(punt_ex, 2), punts[1])
748
749 #
750 # deregister a punt socket
751 #
752 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
753 punts = self.vapi.punt_socket_dump(type=pt_ex)
754 self.assertEqual(len(punts), 1)
755
756 #
757 # configure a punt socket again
758 #
759 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
760 b"%s/socket_punt_1" %
761 six.ensure_binary(self.tempdir))
762 self.vapi.punt_socket_register(set_reason(punt_ex, 3),
763 b"%s/socket_punt_3" %
764 six.ensure_binary(self.tempdir))
765 punts = self.vapi.punt_socket_dump(type=pt_ex)
766 self.assertEqual(len(punts), 3)
767
768 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
769
770 #
771 # deregister all punt socket
772 #
773 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
774 self.vapi.punt_socket_deregister(set_reason(punt_ex, 2))
775 self.vapi.punt_socket_deregister(set_reason(punt_ex, 3))
776 punts = self.vapi.punt_socket_dump(type=pt_ex)
777 self.assertEqual(len(punts), 0)
778
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700779 def verify_esp_pkts(self, rxs, n_sent, spi, has_udp):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700780 self.assertEqual(len(rxs), n_sent)
781 for rx in rxs:
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700782 self.assertTrue(rx.haslayer(IP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700783 self.assertTrue(rx.haslayer(ESP))
784 self.assertEqual(rx[ESP].spi, spi)
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700785 if has_udp:
786 self.assertTrue(rx.haslayer(UDP))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700787
788 def test_traffic(self):
789 """ Punt socket traffic """
790
791 port = self.ports[0]
792 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
793 punt_ex = {
794 'type': pt_ex,
795 'punt': {
796 'exception': {}
797 }
798 }
799
800 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700801 # we need an IPSec tunnels for this to work otherwise ESP gets dropped
Neale Ranns50f0ac02019-05-15 02:13:37 -0700802 # due to unknown IP proto
803 #
804 VppIpsecTunInterface(self, self.pg0, 1000, 1000,
805 (VppEnum.vl_api_ipsec_crypto_alg_t.
806 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
807 "0123456701234567",
808 "0123456701234567",
809 (VppEnum.vl_api_ipsec_integ_alg_t.
810 IPSEC_API_INTEG_ALG_SHA1_96),
811 "0123456701234567",
812 "0123456701234567").add_vpp_config()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700813 VppIpsecTunInterface(self, self.pg0, 1001, 1001,
814 (VppEnum.vl_api_ipsec_crypto_alg_t.
815 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
816 "0123456701234567",
817 "0123456701234567",
818 (VppEnum.vl_api_ipsec_integ_alg_t.
819 IPSEC_API_INTEG_ALG_SHA1_96),
820 "0123456701234567",
821 "0123456701234567",
822 udp_encap=True).add_vpp_config()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700823
824 #
825 # we're dealing with IPSec tunnels punting for no-such-tunnel
826 # adn SPI=0
827 #
828 cfgs = dict()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700829 cfgs['ipsec4-no-such-tunnel'] = {'spi': 99, 'udp': False}
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700830 cfgs['ipsec4-spi-o-udp-0'] = {'spi': 0, 'udp': True}
Neale Ranns50f0ac02019-05-15 02:13:37 -0700831
832 #
833 # find the VPP ID for these punt exception reasin
834 #
835 rs = self.vapi.punt_reason_dump()
836 for key in cfgs:
837 for r in rs:
838 if r.reason.name == key:
839 cfgs[key]['id'] = r.reason.id
840 cfgs[key]['vpp'] = copy.deepcopy(
841 set_reason(punt_ex,
842 cfgs[key]['id']))
843 break
844
845 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700846 # configure punt sockets
Neale Ranns50f0ac02019-05-15 02:13:37 -0700847 #
848 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700849 cfg['sock'] = self.socket_client_create(b"%s/socket_%d" % (
850 six.ensure_binary(self.tempdir), cfg['id']))
851 self.vapi.punt_socket_register(
852 cfg['vpp'],
853 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
854 cfg['id']))
855
856 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700857 # create packet streams for 'no-such-tunnel' exception
858 #
859 for cfg in cfgs.values():
860 pkt = (Ether(src=self.pg0.remote_mac,
861 dst=self.pg0.local_mac) /
862 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4))
863 if (cfg['udp']):
864 pkt = pkt / UDP(sport=666, dport=4500)
865 pkt = (pkt / ESP(spi=cfg['spi'], seq=3) /
866 Raw('\xa5' * 100))
867 cfg['pkts'] = [pkt]
868
869 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700870 # send packets for each SPI we expect to be punted
871 #
872 for cfg in cfgs.values():
873 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
874
875 #
876 # verify the punted packets arrived on the associated socket
877 #
878 for cfg in cfgs.values():
879 rx = cfg['sock'].close()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700880 self.verify_esp_pkts(rx, len(cfg['pkts']),
881 cfg['spi'], cfg['udp'])
882
883 #
884 # socket deregister
885 #
886 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700887 self.vapi.punt_socket_deregister(cfg['vpp'])
888
889
Neale Rannsb538dd82019-05-21 06:54:54 -0700890class TestIpProtoPuntSocket(TestPuntSocket):
891 """ Punt Socket for IP packets """
892
893 @classmethod
894 def setUpClass(cls):
895 super(TestIpProtoPuntSocket, cls).setUpClass()
896
897 @classmethod
898 def tearDownClass(cls):
899 super(TestIpProtoPuntSocket, cls).tearDownClass()
900
901 def setUp(self):
902 super(TestIpProtoPuntSocket, self).setUp()
903
904 for i in self.pg_interfaces:
905 i.config_ip4()
906 i.resolve_arp()
907
908 def tearDown(self):
909 super(TestIpProtoPuntSocket, self).tearDown()
910 for i in self.pg_interfaces:
911 i.unconfig_ip4()
912 i.admin_down()
913
914 def test_registration(self):
915 """ Punt socket registration/deregistration"""
916
917 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
918 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
919 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
920 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
921
922 punts = self.vapi.punt_socket_dump(type=pt_ip)
923 self.assertEqual(len(punts), 0)
924
925 #
926 # configure a punt socket
927 #
928 punt_ospf = {
929 'type': pt_ip,
930 'punt': {
931 'ip_proto': {
932 'af': af_ip4,
933 'protocol': proto_ospf
934 }
935 }
936 }
937 punt_eigrp = {
938 'type': pt_ip,
939 'punt': {
940 'ip_proto': {
941 'af': af_ip4,
942 'protocol': proto_eigrp
943 }
944 }
945 }
946
947 self.vapi.punt_socket_register(punt_ospf,
948 b"%s/socket_punt_1" %
949 six.ensure_binary(self.tempdir))
950 self.vapi.punt_socket_register(punt_eigrp,
951 b"%s/socket_punt_2" %
952 six.ensure_binary(self.tempdir))
953 self.logger.info(self.vapi.cli("sh punt sock reg ip"))
954 punts = self.vapi.punt_socket_dump(type=pt_ip)
955 self.assertEqual(len(punts), 2)
956 self.verify_ip_proto(punt_ospf, punts[0])
957 self.verify_ip_proto(punt_eigrp, punts[1])
958
959 #
960 # deregister a punt socket
961 #
962 self.vapi.punt_socket_deregister(punt_ospf)
963 punts = self.vapi.punt_socket_dump(type=pt_ip)
964 self.assertEqual(len(punts), 1)
965
966 #
967 # configure a punt socket again
968 #
969 self.vapi.punt_socket_register(punt_ospf,
970 b"%s/socket_punt_3" %
971 six.ensure_binary(self.tempdir))
972 punts = self.vapi.punt_socket_dump(type=pt_ip)
973 self.assertEqual(len(punts), 2)
974
975 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
976
977 #
978 # deregister all punt socket
979 #
980 self.vapi.punt_socket_deregister(punt_eigrp)
981 self.vapi.punt_socket_deregister(punt_ospf)
982 punts = self.vapi.punt_socket_dump(type=pt_ip)
983 self.assertEqual(len(punts), 0)
984
985 def verify_ospf_pkts(self, rxs, n_sent):
986 self.assertEqual(len(rxs), n_sent)
987 for rx in rxs:
988 self.assertTrue(rx.haslayer(OSPF_Hdr))
989
990 def test_traffic(self):
991 """ Punt socket traffic """
992
993 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
994 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
995 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
996
997 #
998 # configure a punt socket to capture OSPF packets
999 #
1000 punt_ospf = {
1001 'type': pt_ip,
1002 'punt': {
1003 'ip_proto': {
1004 'af': af_ip4,
1005 'protocol': proto_ospf
1006 }
1007 }
1008 }
1009
1010 #
1011 # create packet streams and configure a punt sockets
1012 #
1013 pkt = (Ether(src=self.pg0.remote_mac,
1014 dst=self.pg0.local_mac) /
1015 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1016 OSPF_Hdr() /
1017 OSPFv3_Hello())
1018 pkts = pkt * 7
1019
1020 sock = self.socket_client_create(b"%s/socket_1" % (
1021 six.ensure_binary(self.tempdir)))
1022 self.vapi.punt_socket_register(
1023 punt_ospf,
1024 b"%s/socket_1" % (six.ensure_binary(self.tempdir)))
1025
1026 #
1027 # send packets for each SPI we expect to be punted
1028 #
1029 self.send_and_assert_no_replies(self.pg0, pkts)
1030
1031 #
1032 # verify the punted packets arrived on the associated socket
1033 #
1034 rx = sock.close()
1035 self.verify_ospf_pkts(rx, len(pkts))
1036 self.vapi.punt_socket_deregister(punt_ospf)
1037
1038
Neale Ranns76b56492018-09-28 15:16:14 +00001039class TestPunt(VppTestCase):
Neale Rannsb538dd82019-05-21 06:54:54 -07001040 """ Exception Punt Test Case """
Neale Ranns76b56492018-09-28 15:16:14 +00001041
1042 @classmethod
1043 def setUpClass(cls):
1044 super(TestPunt, cls).setUpClass()
1045
1046 @classmethod
1047 def tearDownClass(cls):
1048 super(TestPunt, cls).tearDownClass()
1049
1050 def setUp(self):
1051 super(TestPunt, self).setUp()
1052
1053 self.create_pg_interfaces(range(4))
1054
1055 for i in self.pg_interfaces:
1056 i.admin_up()
1057 i.config_ip4()
1058 i.resolve_arp()
1059 i.config_ip6()
1060 i.resolve_ndp()
1061
1062 def tearDown(self):
1063 for i in self.pg_interfaces:
1064 i.unconfig_ip4()
1065 i.unconfig_ip6()
1066 i.ip6_disable()
1067 i.admin_down()
1068 super(TestPunt, self).tearDown()
1069
1070 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -07001071 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +00001072
1073 #
Neale Ranns719beb72019-07-10 07:10:25 +00001074 # dump the punt registered reasons
1075 # search for a few we know should be there
1076 #
1077 rs = self.vapi.punt_reason_dump()
1078
1079 reasons = ["ipsec6-no-such-tunnel",
1080 "ipsec4-no-such-tunnel",
1081 "ipsec4-spi-o-udp-0"]
1082
1083 for reason in reasons:
1084 found = False
1085 for r in rs:
1086 if r.reason.name == reason:
1087 found = True
1088 break
1089 self.assertTrue(found)
1090
1091 #
Neale Ranns76b56492018-09-28 15:16:14 +00001092 # Using the test CLI we will hook in a exception path to
1093 # send ACL deny packets out of pg0 and pg1.
1094 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1095 #
1096 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1097 [VppRoutePath(self.pg3.remote_ip4,
1098 self.pg3.sw_if_index)])
1099 ip_1_1_1_2.add_vpp_config()
1100 ip_1_2 = VppIpRoute(self, "1::2", 128,
1101 [VppRoutePath(self.pg3.remote_ip6,
1102 self.pg3.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001103 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns76b56492018-09-28 15:16:14 +00001104 ip_1_2.add_vpp_config()
1105
1106 p4 = (Ether(src=self.pg2.remote_mac,
1107 dst=self.pg2.local_mac) /
1108 IP(src="1.1.1.1", dst="1.1.1.2") /
1109 UDP(sport=1234, dport=1234) /
1110 Raw('\xa5' * 100))
1111 p6 = (Ether(src=self.pg2.remote_mac,
1112 dst=self.pg2.local_mac) /
1113 IPv6(src="1::1", dst="1::2") /
1114 UDP(sport=1234, dport=1234) /
1115 Raw('\xa5' * 100))
1116 self.send_and_expect(self.pg2, p4*1, self.pg3)
1117 self.send_and_expect(self.pg2, p6*1, self.pg3)
1118
1119 #
1120 # apply the punting features
1121 #
1122 self.vapi.cli("test punt pg2")
1123
1124 #
Neale Ranns719beb72019-07-10 07:10:25 +00001125 # dump the punt reasons to learn the IDs assigned
1126 #
1127 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v4"})
1128 r4 = rs[0].reason.id
1129 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v6"})
1130 r6 = rs[0].reason.id
1131
1132 #
Neale Ranns76b56492018-09-28 15:16:14 +00001133 # pkts now dropped
1134 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001135 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
1136 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001137
1138 #
1139 # Check state:
1140 # 1 - node error counters
1141 # 2 - per-reason counters
1142 # 2, 3 are the index of the assigned punt reason
1143 #
Ole Troan233e4682019-05-16 15:01:34 +02001144 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +00001145 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001146 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001147
1148 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001149 self.assertEqual(stats[0][r4]['packets'], NUM_PKTS)
1150 self.assertEqual(stats[0][r6]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001151
1152 #
1153 # use the test CLI to test a client that punts exception
1154 # packets out of pg0
1155 #
1156 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1157 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1158
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001159 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
1160 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001161
1162 #
1163 # check the packets come out IP unmodified but destined to pg0 host
1164 #
1165 for rx in rx4s:
1166 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1167 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1168 self.assertEqual(p4[IP].dst, rx[IP].dst)
1169 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1170 for rx in rx6s:
1171 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1172 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1173 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1174 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1175
1176 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001177 self.assertEqual(stats[0][r4]['packets'], 2*NUM_PKTS)
1178 self.assertEqual(stats[0][r6]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001179
1180 #
1181 # add another registration for the same reason to send packets
1182 # out of pg1
1183 #
1184 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1185 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1186
1187 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001188 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001189 self.pg_enable_capture(self.pg_interfaces)
1190 self.pg_start()
1191
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001192 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001193 for rx in rxd:
1194 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1195 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1196 self.assertEqual(p4[IP].dst, rx[IP].dst)
1197 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001198 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001199 for rx in rxd:
1200 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1201 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1202 self.assertEqual(p4[IP].dst, rx[IP].dst)
1203 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1204
1205 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001206 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001207 self.pg_enable_capture(self.pg_interfaces)
1208 self.pg_start()
1209
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001210 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001211 for rx in rxd:
1212 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1213 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1214 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1215 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001216 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001217 for rx in rxd:
1218 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1219 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1220 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1221 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1222
1223 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001224 self.assertEqual(stats[0][r4]['packets'], 3*NUM_PKTS)
1225 self.assertEqual(stats[0][r6]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001226
1227 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1228 self.logger.info(self.vapi.cli("show punt client"))
1229 self.logger.info(self.vapi.cli("show punt reason"))
1230 self.logger.info(self.vapi.cli("show punt stats"))
1231 self.logger.info(self.vapi.cli("show punt db"))
1232
Neale Ranns76b56492018-09-28 15:16:14 +00001233
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001234if __name__ == '__main__':
1235 unittest.main(testRunner=VppTestRunner)