blob: 28c17daa08af02ab27625655f4e701d6e0b475f7 [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
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -080025import six
Pavel Kotuceke88865d2018-11-28 07:42:11 +010026from framework import VppTestCase, VppTestRunner
27
Neale Ranns76b56492018-09-28 15:16:14 +000028from vpp_ip import DpoProto
29from vpp_ip_route import VppIpRoute, VppRoutePath
Neale Ranns50f0ac02019-05-15 02:13:37 -070030from vpp_papi import VppEnum
31from vpp_ipsec_tun_interface import VppIpsecTunInterface
Neale Ranns76b56492018-09-28 15:16:14 +000032
Paul Vinciguerra4271c972019-05-14 13:25:49 -040033NUM_PKTS = 67
34
Pavel Kotuceke88865d2018-11-28 07:42:11 +010035
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010036class serverSocketThread(threading.Thread):
37 """ Socket server thread"""
38
Neale Ranns50f0ac02019-05-15 02:13:37 -070039 def __init__(self, threadID, sockName):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010040 threading.Thread.__init__(self)
41 self.threadID = threadID
42 self.sockName = sockName
43 self.sock = None
Neale Ranns50f0ac02019-05-15 02:13:37 -070044 self.rx_pkts = []
45
46 def rx_packets(self):
47 # Wait for some packets on socket
48 while True:
49 data = self.sock.recv(65536)
50
51 # punt socket metadata
52 # packet_desc = data[0:8]
53
54 # Ethernet
55 self.rx_pkts.append(Ether(data[8:]))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010056
57 def run(self):
58 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
59 try:
60 os.unlink(self.sockName)
61 except:
62 pass
Neale Ranns50f0ac02019-05-15 02:13:37 -070063 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
64 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010065 self.sock.bind(self.sockName)
66
Neale Ranns50f0ac02019-05-15 02:13:37 -070067 self.rx_packets()
68
69 def close(self):
70 self.sock.close()
71 return self.rx_pkts
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010072
73
Pavel Kotuceke88865d2018-11-28 07:42:11 +010074class TestPuntSocket(VppTestCase):
75 """ Punt Socket """
76
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010077 ports = [1111, 2222, 3333, 4444]
78 sock_servers = list()
Neale Ranns50f0ac02019-05-15 02:13:37 -070079 nr_packets = 3
Pavel Kotuceke88865d2018-11-28 07:42:11 +010080
81 @classmethod
Paul Vinciguerra8d991d92019-01-25 14:05:48 -080082 def setUpClass(cls):
83 super(TestPuntSocket, cls).setUpClass()
84
85 @classmethod
86 def tearDownClass(cls):
87 super(TestPuntSocket, cls).tearDownClass()
88
89 @classmethod
Pavel Kotuceke88865d2018-11-28 07:42:11 +010090 def setUpConstants(cls):
Ole Troana45dc072018-12-21 16:04:22 +010091 cls.extra_vpp_punt_config = [
92 "punt", "{", "socket", cls.tempdir+"/socket_punt", "}"]
Pavel Kotuceke88865d2018-11-28 07:42:11 +010093 super(TestPuntSocket, cls).setUpConstants()
94
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010095 def setUp(self):
96 super(TestPuntSocket, self).setUp()
97 random.seed()
Pavel Kotuceke88865d2018-11-28 07:42:11 +010098
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010099 self.create_pg_interfaces(range(2))
100 for i in self.pg_interfaces:
101 i.admin_up()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100102
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100103 def tearDown(self):
104 del self.sock_servers[:]
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800105 super(TestPuntSocket, self).tearDown()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100106
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100107 def socket_client_create(self, sock_name, id=None):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700108 thread = serverSocketThread(id, sock_name)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100109 self.sock_servers.append(thread)
110 thread.start()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700111 return thread
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100112
113 def socket_client_close(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700114 rx_pkts = []
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100115 for thread in self.sock_servers:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700116 rx_pkts += thread.close()
117 return rx_pkts
118
119 def verify_port(self, pr, vpr):
120 self.assertEqual(vpr.punt.type, pr['type'])
121 self.assertEqual(vpr.punt.punt.l4.port,
122 pr['punt']['l4']['port'])
123 self.assertEqual(vpr.punt.punt.l4.protocol,
124 pr['punt']['l4']['protocol'])
125 self.assertEqual(vpr.punt.punt.l4.af,
126 pr['punt']['l4']['af'])
127
128 def verify_exception(self, pr, vpr):
129 self.assertEqual(vpr.punt.type, pr['type'])
130 self.assertEqual(vpr.punt.punt.exception.id,
131 pr['punt']['exception']['id'])
132
133 def verify_udp_pkts(self, rxs, n_rx, port):
134 n_match = 0
135 for rx in rxs:
136 self.assertTrue(rx.haslayer(UDP))
137 if rx[UDP].dport == port:
138 n_match += 1
139 self.assertEqual(n_match, n_rx)
140
141
142def set_port(pr, port):
143 pr['punt']['l4']['port'] = port
144 return pr
145
146
147def set_reason(pr, reason):
148 pr['punt']['exception']['id'] = reason
149 return pr
150
151
152def mk_vpp_cfg4():
153 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
154 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
155 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
156 punt_l4 = {
157 'type': pt_l4,
158 'punt': {
159 'l4': {
160 'af': af_ip4,
161 'protocol': udp_proto
162 }
163 }
164 }
165 return punt_l4
166
167
168def mk_vpp_cfg6():
169 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
170 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
171 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
172 punt_l4 = {
173 'type': pt_l4,
174 'punt': {
175 'l4': {
176 'af': af_ip6,
177 'protocol': udp_proto
178 }
179 }
180 }
181 return punt_l4
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100182
183
184class TestIP4PuntSocket(TestPuntSocket):
185 """ Punt Socket for IPv4 """
186
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800187 @classmethod
188 def setUpClass(cls):
189 super(TestIP4PuntSocket, cls).setUpClass()
190
191 @classmethod
192 def tearDownClass(cls):
193 super(TestIP4PuntSocket, cls).tearDownClass()
194
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100195 def setUp(self):
196 super(TestIP4PuntSocket, self).setUp()
197
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100198 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100199 i.config_ip4()
200 i.resolve_arp()
201
202 def tearDown(self):
203 super(TestIP4PuntSocket, self).tearDown()
204 for i in self.pg_interfaces:
205 i.unconfig_ip4()
206 i.admin_down()
207
208 def test_punt_socket_dump(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100209 """ Punt socket registration/deregistration"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100210
Neale Ranns50f0ac02019-05-15 02:13:37 -0700211 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
212 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
213 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
214
215 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100216 self.assertEqual(len(punts), 0)
217
218 #
219 # configure a punt socket
220 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700221 punt_l4 = mk_vpp_cfg4()
222
223 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
224 b"%s/socket_punt_1111" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800225 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700226 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
227 b"%s/socket_punt_2222" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800228 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700229 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100230 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700231 self.verify_port(set_port(punt_l4, 1111), punts[0])
232 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100233
234 #
235 # deregister a punt socket
236 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700237 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
238 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100239 self.assertEqual(len(punts), 1)
240
241 #
242 # configure a punt socket again
243 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700244 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
245 b"%s/socket_punt_1111" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800246 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700247 self.vapi.punt_socket_register(set_port(punt_l4, 3333),
248 b"%s/socket_punt_3333" %
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800249 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700250 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100251 self.assertEqual(len(punts), 3)
252
Neale Ranns50f0ac02019-05-15 02:13:37 -0700253 self.logger.info(self.vapi.cli("sh punt sock reg"))
254
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100255 #
256 # deregister all punt socket
257 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700258 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
259 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
260 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
261 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100262 self.assertEqual(len(punts), 0)
263
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100264 def test_punt_socket_traffic_single_port_single_socket(self):
265 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100266
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100267 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700268 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
269 punt_l4 = set_port(mk_vpp_cfg4(), port)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100270
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100271 p = (Ether(src=self.pg0.remote_mac,
272 dst=self.pg0.local_mac) /
273 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100274 UDP(sport=9876, dport=port) /
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100275 Raw('\xa5' * 100))
276
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100277 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100278
Neale Ranns50f0ac02019-05-15 02:13:37 -0700279 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100280 self.assertEqual(len(punts), 0)
281
282 #
283 # expect ICMP - port unreachable for all packets
284 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700285 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
286
287 for p in rx:
288 self.assertEqual(int(p[IP].proto), 1) # ICMP
289 self.assertEqual(int(p[ICMP].code), 3) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100290
291 #
292 # configure a punt socket
293 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800294 self.socket_client_create(b"%s/socket_%d" % (
295 six.ensure_binary(self.tempdir), port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700296 self.vapi.punt_socket_register(punt_l4, b"%s/socket_%d" % (
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800297 six.ensure_binary(self.tempdir), port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700298 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100299 self.assertEqual(len(punts), 1)
300
301 #
302 # expect punt socket and no packets on pg0
303 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700304 self.send_and_assert_no_replies(self.pg0, pkts)
305 rx = self.socket_client_close()
306 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100307
308 #
309 # remove punt socket. expect ICMP - port unreachable for all packets
310 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700311 self.vapi.punt_socket_deregister(punt_l4)
312 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100313 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100314
Neale Ranns50f0ac02019-05-15 02:13:37 -0700315 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
316 for p in rx:
317 self.assertEqual(int(p[IP].proto), 1) # ICMP
318 self.assertEqual(int(p[ICMP].code), 3) # unreachable
319
320 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100321 """ Punt socket traffic multi ports and multi sockets"""
322
Neale Ranns50f0ac02019-05-15 02:13:37 -0700323 punt_l4 = mk_vpp_cfg4()
324
325 # configuration for each UDP port
326 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100327
328 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700329 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100330 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700331 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100332 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700333 cfgs[port] = {}
334
335 pkt = (Ether(src=self.pg0.remote_mac,
336 dst=self.pg0.local_mac) /
337 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
338 UDP(sport=9876, dport=port) /
339 Raw('\xa5' * 100))
340 cfgs[port]['pkts'] = pkt * self.nr_packets
341 cfgs[port]['port'] = port
342 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
343
344 # configure punt sockets
345 cfgs[port]['sock'] = self.socket_client_create(
346 b"%s/socket_%d" % (six.ensure_binary(self.tempdir), port))
347 self.vapi.punt_socket_register(
348 cfgs[port]['vpp'],
349 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
350 port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100351
352 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700353 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100354 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700355 for cfg in cfgs.values():
356 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100357
358 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700359 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100360 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700361 for cfg in cfgs.values():
362 rx = cfg['sock'].close()
363 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
364 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100365
366 def test_punt_socket_traffic_multi_ports_single_socket(self):
367 """ Punt socket traffic multi ports and single socket"""
368
Neale Ranns50f0ac02019-05-15 02:13:37 -0700369 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
370 punt_l4 = mk_vpp_cfg4()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100371
372 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700373 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100374 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700375 pkts = []
376 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100377 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700378 pkt = (Ether(src=self.pg0.remote_mac,
379 dst=self.pg0.local_mac) /
380 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
381 UDP(sport=9876, dport=port) /
382 Raw('\xa5' * 100))
383 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100384
385 #
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100386 # configure a punt socket
387 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800388 self.socket_client_create(b"%s/socket_multi" %
389 six.ensure_binary(self.tempdir))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100390 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700391 self.vapi.punt_socket_register(set_port(punt_l4, p),
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800392 b"%s/socket_multi" %
393 six.ensure_binary(self.tempdir))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700394 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100395 self.assertEqual(len(punts), len(self.ports))
396
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100397 #
398 # expect punt socket and no packets on pg0
399 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700400 self.send_and_assert_no_replies(self.pg0, pkts)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100401 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700402 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100403
404 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700405 self.verify_udp_pkts(rx, self.nr_packets, p)
406 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
407 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100408 self.assertEqual(len(punts), 0)
409
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100410
411class TestIP6PuntSocket(TestPuntSocket):
412 """ Punt Socket for IPv6"""
413
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800414 @classmethod
415 def setUpClass(cls):
416 super(TestIP6PuntSocket, cls).setUpClass()
417
418 @classmethod
419 def tearDownClass(cls):
420 super(TestIP6PuntSocket, cls).tearDownClass()
421
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100422 def setUp(self):
423 super(TestIP6PuntSocket, self).setUp()
424
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100425 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100426 i.config_ip6()
427 i.resolve_ndp()
428
429 def tearDown(self):
430 super(TestIP6PuntSocket, self).tearDown()
431 for i in self.pg_interfaces:
432 i.unconfig_ip6()
433 i.admin_down()
434
435 def test_punt_socket_dump(self):
436 """ Punt socket registration """
437
Neale Ranns50f0ac02019-05-15 02:13:37 -0700438 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
439 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
440 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
441 #
442 # configure a punt socket
443 #
444 punt_l4 = {
445 'type': pt_l4,
446 'punt': {
447 'l4': {
448 'af': af_ip6,
449 'protocol': udp_proto
450 }
451 }
452 }
453
454 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100455 self.assertEqual(len(punts), 0)
456
457 #
458 # configure a punt socket
459 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700460 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
461 b"%s/socket_1111" %
462 six.ensure_binary(self.tempdir))
463 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
464 b"%s/socket_2222" %
465 six.ensure_binary(self.tempdir))
466 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100467 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700468 self.verify_port(set_port(punt_l4, 1111), punts[0])
469 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100470
471 #
472 # deregister a punt socket
473 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700474 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
475 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100476 self.assertEqual(len(punts), 1)
477
478 #
479 # configure a punt socket again
480 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700481 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
482 b"%s/socket_1111" %
483 six.ensure_binary(self.tempdir))
484 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100485 self.assertEqual(len(punts), 2)
486
487 #
488 # deregister all punt socket
489 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700490 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
491 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
492 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
493 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100494 self.assertEqual(len(punts), 0)
495
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100496 def test_punt_socket_traffic_single_port_single_socket(self):
497 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100498
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100499 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700500 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
501 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
502 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
503 punt_l4 = {
504 'type': pt_l4,
505 'punt': {
506 'l4': {
507 'af': af_ip6,
508 'protocol': udp_proto,
509 'port': port,
510 }
511 }
512 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100513
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100514 p = (Ether(src=self.pg0.remote_mac,
515 dst=self.pg0.local_mac) /
516 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100517 inet6.UDP(sport=9876, dport=port) /
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100518 Raw('\xa5' * 100))
519
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100520 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100521
Neale Ranns50f0ac02019-05-15 02:13:37 -0700522 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100523 self.assertEqual(len(punts), 0)
524
525 #
526 # expect ICMPv6 - destination unreachable for all packets
527 #
528 self.vapi.cli("clear trace")
529 self.pg0.add_stream(pkts)
530 self.pg_enable_capture(self.pg_interfaces)
531 self.pg_start()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100532 # FIXME - when punt socket deregister is implemented
533 # rx = self.pg0.get_capture(self.nr_packets)
534 # for p in rx:
535 # self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
536 # self.assertEqual(int(p[ICMPv6DestUnreach].code),4) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100537
538 #
539 # configure a punt socket
540 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800541 self.socket_client_create(b"%s/socket_%d" % (
542 six.ensure_binary(self.tempdir), port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700543 self.vapi.punt_socket_register(punt_l4, b"%s/socket_%d" % (
544 six.ensure_binary(self.tempdir), port))
545 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100546 self.assertEqual(len(punts), 1)
547
548 #
549 # expect punt socket and no packets on pg0
550 #
551 self.vapi.cli("clear errors")
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100552 self.vapi.cli("clear trace")
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100553 self.pg0.add_stream(pkts)
554 self.pg_enable_capture(self.pg_interfaces)
555 self.pg_start()
556 self.pg0.get_capture(0)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100557 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700558 rx = self.socket_client_close()
559 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100560
561 #
562 # remove punt socket. expect ICMP - dest. unreachable for all packets
563 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700564 self.vapi.punt_socket_deregister(punt_l4)
565 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100566 self.assertEqual(len(punts), 0)
567 self.pg0.add_stream(pkts)
568 self.pg_enable_capture(self.pg_interfaces)
569 self.pg_start()
570 # FIXME - when punt socket deregister is implemented
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100571 # self.pg0.get_capture(nr_packets)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100572
Neale Ranns50f0ac02019-05-15 02:13:37 -0700573 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100574 """ Punt socket traffic multi ports and multi sockets"""
575
Neale Ranns50f0ac02019-05-15 02:13:37 -0700576 punt_l4 = mk_vpp_cfg6()
577
578 # configuration for each UDP port
579 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100580
581 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700582 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100583 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700584 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100585 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700586 cfgs[port] = {}
587
588 pkt = (Ether(src=self.pg0.remote_mac,
589 dst=self.pg0.local_mac) /
590 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
591 UDP(sport=9876, dport=port) /
592 Raw('\xa5' * 100))
593 cfgs[port]['pkts'] = pkt * self.nr_packets
594 cfgs[port]['port'] = port
595 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
596
597 # configure punt sockets
598 cfgs[port]['sock'] = self.socket_client_create(
599 b"%s/socket_%d" % (six.ensure_binary(self.tempdir), port))
600 self.vapi.punt_socket_register(
601 cfgs[port]['vpp'],
602 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
603 port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100604
605 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700606 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100607 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700608 for cfg in cfgs.values():
609 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100610
611 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700612 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100613 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700614 for cfg in cfgs.values():
615 rx = cfg['sock'].close()
616 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
617 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100618
619 def test_punt_socket_traffic_multi_ports_single_socket(self):
620 """ Punt socket traffic multi ports and single socket"""
621
Neale Ranns50f0ac02019-05-15 02:13:37 -0700622 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
623 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
624 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
625 punt_l4 = {
626 'type': pt_l4,
627 'punt': {
628 'l4': {
629 'af': af_ip6,
630 'protocol': udp_proto,
631 }
632 }
633 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100634
635 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700636 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100637 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700638 pkts = []
639 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100640 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700641 pkt = (Ether(src=self.pg0.remote_mac,
642 dst=self.pg0.local_mac) /
643 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
644 UDP(sport=9876, dport=port) /
645 Raw('\xa5' * 100))
646 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100647
648 #
649 # no punt socket
650 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700651 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100652 self.assertEqual(len(punts), 0)
653
654 #
655 # configure a punt socket
656 #
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800657 self.socket_client_create(b"%s/socket_multi" %
658 six.ensure_binary(self.tempdir))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100659 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700660 self.vapi.punt_socket_register(set_port(punt_l4, p),
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -0800661 b"%s/socket_multi" %
Neale Ranns50f0ac02019-05-15 02:13:37 -0700662 six.ensure_binary(self.tempdir))
663 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100664 self.assertEqual(len(punts), len(self.ports))
665
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100666 #
667 # expect punt socket and no packets on pg0
668 #
669 self.vapi.cli("clear errors")
670 self.vapi.cli("clear trace")
671 self.pg0.add_stream(pkts)
672 self.pg_enable_capture(self.pg_interfaces)
673 self.pg_start()
674 self.pg0.get_capture(0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700675 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100676
677 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700678 self.verify_udp_pkts(rx, self.nr_packets, p)
679 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
680 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100681 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100682
Neale Ranns76b56492018-09-28 15:16:14 +0000683
Neale Ranns50f0ac02019-05-15 02:13:37 -0700684class TestExceptionPuntSocket(TestPuntSocket):
685 """ Punt Socket for Exceptions """
686
687 @classmethod
688 def setUpClass(cls):
689 super(TestExceptionPuntSocket, cls).setUpClass()
690
691 @classmethod
692 def tearDownClass(cls):
693 super(TestExceptionPuntSocket, cls).tearDownClass()
694
695 def setUp(self):
696 super(TestExceptionPuntSocket, self).setUp()
697
698 for i in self.pg_interfaces:
699 i.config_ip4()
700 i.resolve_arp()
701
702 def tearDown(self):
703 super(TestExceptionPuntSocket, self).tearDown()
704 for i in self.pg_interfaces:
705 i.unconfig_ip4()
706 i.admin_down()
707
708 def test_registration(self):
709 """ Punt socket registration/deregistration"""
710
711 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
712
713 punts = self.vapi.punt_socket_dump(type=pt_ex)
714 self.assertEqual(len(punts), 0)
715
716 #
717 # configure a punt socket
718 #
719 punt_ex = {
720 'type': pt_ex,
721 'punt': {
722 'exception': {}
723 }
724 }
725
726 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
727 b"%s/socket_punt_1" %
728 six.ensure_binary(self.tempdir))
729 self.vapi.punt_socket_register(set_reason(punt_ex, 2),
730 b"%s/socket_punt_2" %
731 six.ensure_binary(self.tempdir))
732 punts = self.vapi.punt_socket_dump(type=pt_ex)
733 self.assertEqual(len(punts), 2)
734 self.verify_exception(set_reason(punt_ex, 1), punts[0])
735 self.verify_exception(set_reason(punt_ex, 2), punts[1])
736
737 #
738 # deregister a punt socket
739 #
740 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
741 punts = self.vapi.punt_socket_dump(type=pt_ex)
742 self.assertEqual(len(punts), 1)
743
744 #
745 # configure a punt socket again
746 #
747 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
748 b"%s/socket_punt_1" %
749 six.ensure_binary(self.tempdir))
750 self.vapi.punt_socket_register(set_reason(punt_ex, 3),
751 b"%s/socket_punt_3" %
752 six.ensure_binary(self.tempdir))
753 punts = self.vapi.punt_socket_dump(type=pt_ex)
754 self.assertEqual(len(punts), 3)
755
756 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
757
758 #
759 # deregister all punt socket
760 #
761 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
762 self.vapi.punt_socket_deregister(set_reason(punt_ex, 2))
763 self.vapi.punt_socket_deregister(set_reason(punt_ex, 3))
764 punts = self.vapi.punt_socket_dump(type=pt_ex)
765 self.assertEqual(len(punts), 0)
766
767 def verify_esp_pkts(self, rxs, n_sent, spi):
768 self.assertEqual(len(rxs), n_sent)
769 for rx in rxs:
770 self.assertTrue(rx.haslayer(ESP))
771 self.assertEqual(rx[ESP].spi, spi)
772
773 def test_traffic(self):
774 """ Punt socket traffic """
775
776 port = self.ports[0]
777 pt_ex = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_EXCEPTION
778 punt_ex = {
779 'type': pt_ex,
780 'punt': {
781 'exception': {}
782 }
783 }
784
785 #
786 # we need an IPSec tunnel for this to work otherwise ESP gets dropped
787 # due to unknown IP proto
788 #
789 VppIpsecTunInterface(self, self.pg0, 1000, 1000,
790 (VppEnum.vl_api_ipsec_crypto_alg_t.
791 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
792 "0123456701234567",
793 "0123456701234567",
794 (VppEnum.vl_api_ipsec_integ_alg_t.
795 IPSEC_API_INTEG_ALG_SHA1_96),
796 "0123456701234567",
797 "0123456701234567").add_vpp_config()
798
799 #
800 # we're dealing with IPSec tunnels punting for no-such-tunnel
801 # adn SPI=0
802 #
803 cfgs = dict()
804 cfgs['ipsec4-no-such-tunnel'] = {'spi': 99}
805 cfgs['ipsec4-spi-0'] = {'spi': 0}
806
807 #
808 # find the VPP ID for these punt exception reasin
809 #
810 rs = self.vapi.punt_reason_dump()
811 for key in cfgs:
812 for r in rs:
813 if r.reason.name == key:
814 cfgs[key]['id'] = r.reason.id
815 cfgs[key]['vpp'] = copy.deepcopy(
816 set_reason(punt_ex,
817 cfgs[key]['id']))
818 break
819
820 #
821 # create packet streams and configure a punt sockets
822 #
823 for cfg in cfgs.values():
824 pkt = (Ether(src=self.pg0.remote_mac,
825 dst=self.pg0.local_mac) /
826 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
827 ESP(spi=cfg['spi'], seq=3) /
828 Raw('\xa5' * 100))
829 cfg['pkts'] = pkt * self.nr_packets
830
831 cfg['sock'] = self.socket_client_create(b"%s/socket_%d" % (
832 six.ensure_binary(self.tempdir), cfg['id']))
833 self.vapi.punt_socket_register(
834 cfg['vpp'],
835 b"%s/socket_%d" % (six.ensure_binary(self.tempdir),
836 cfg['id']))
837
838 #
839 # send packets for each SPI we expect to be punted
840 #
841 for cfg in cfgs.values():
842 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
843
844 #
845 # verify the punted packets arrived on the associated socket
846 #
847 for cfg in cfgs.values():
848 rx = cfg['sock'].close()
849 self.verify_esp_pkts(rx, len(cfg['pkts']), cfg['spi'])
850 self.vapi.punt_socket_deregister(cfg['vpp'])
851
852
Neale Ranns76b56492018-09-28 15:16:14 +0000853class TestPunt(VppTestCase):
854 """ Punt Test Case """
855
856 @classmethod
857 def setUpClass(cls):
858 super(TestPunt, cls).setUpClass()
859
860 @classmethod
861 def tearDownClass(cls):
862 super(TestPunt, cls).tearDownClass()
863
864 def setUp(self):
865 super(TestPunt, self).setUp()
866
867 self.create_pg_interfaces(range(4))
868
869 for i in self.pg_interfaces:
870 i.admin_up()
871 i.config_ip4()
872 i.resolve_arp()
873 i.config_ip6()
874 i.resolve_ndp()
875
876 def tearDown(self):
877 for i in self.pg_interfaces:
878 i.unconfig_ip4()
879 i.unconfig_ip6()
880 i.ip6_disable()
881 i.admin_down()
882 super(TestPunt, self).tearDown()
883
884 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700885 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +0000886
887 #
888 # Using the test CLI we will hook in a exception path to
889 # send ACL deny packets out of pg0 and pg1.
890 # the ACL is src,dst = 1.1.1.1,1.1.1.2
891 #
892 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
893 [VppRoutePath(self.pg3.remote_ip4,
894 self.pg3.sw_if_index)])
895 ip_1_1_1_2.add_vpp_config()
896 ip_1_2 = VppIpRoute(self, "1::2", 128,
897 [VppRoutePath(self.pg3.remote_ip6,
898 self.pg3.sw_if_index,
899 proto=DpoProto.DPO_PROTO_IP6)],
900 is_ip6=1)
901 ip_1_2.add_vpp_config()
902
903 p4 = (Ether(src=self.pg2.remote_mac,
904 dst=self.pg2.local_mac) /
905 IP(src="1.1.1.1", dst="1.1.1.2") /
906 UDP(sport=1234, dport=1234) /
907 Raw('\xa5' * 100))
908 p6 = (Ether(src=self.pg2.remote_mac,
909 dst=self.pg2.local_mac) /
910 IPv6(src="1::1", dst="1::2") /
911 UDP(sport=1234, dport=1234) /
912 Raw('\xa5' * 100))
913 self.send_and_expect(self.pg2, p4*1, self.pg3)
914 self.send_and_expect(self.pg2, p6*1, self.pg3)
915
916 #
917 # apply the punting features
918 #
919 self.vapi.cli("test punt pg2")
920
921 #
922 # pkts now dropped
923 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400924 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
925 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +0000926
927 #
928 # Check state:
929 # 1 - node error counters
930 # 2 - per-reason counters
931 # 2, 3 are the index of the assigned punt reason
932 #
Ole Troan233e4682019-05-16 15:01:34 +0200933 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +0000934 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400935 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +0000936
937 stats = self.statistics.get_counter("/net/punt")
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400938 self.assertEqual(stats[0][7]['packets'], NUM_PKTS)
939 self.assertEqual(stats[0][8]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +0000940
941 #
942 # use the test CLI to test a client that punts exception
943 # packets out of pg0
944 #
945 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
946 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
947
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400948 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
949 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +0000950
951 #
952 # check the packets come out IP unmodified but destined to pg0 host
953 #
954 for rx in rx4s:
955 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
956 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
957 self.assertEqual(p4[IP].dst, rx[IP].dst)
958 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
959 for rx in rx6s:
960 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
961 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
962 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
963 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
964
965 stats = self.statistics.get_counter("/net/punt")
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400966 self.assertEqual(stats[0][7]['packets'], 2*NUM_PKTS)
967 self.assertEqual(stats[0][8]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +0000968
969 #
970 # add another registration for the same reason to send packets
971 # out of pg1
972 #
973 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
974 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
975
976 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400977 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +0000978 self.pg_enable_capture(self.pg_interfaces)
979 self.pg_start()
980
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400981 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +0000982 for rx in rxd:
983 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
984 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
985 self.assertEqual(p4[IP].dst, rx[IP].dst)
986 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400987 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +0000988 for rx in rxd:
989 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
990 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
991 self.assertEqual(p4[IP].dst, rx[IP].dst)
992 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
993
994 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400995 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +0000996 self.pg_enable_capture(self.pg_interfaces)
997 self.pg_start()
998
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400999 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001000 for rx in rxd:
1001 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1002 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1003 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1004 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001005 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001006 for rx in rxd:
1007 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1008 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1009 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1010 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1011
1012 stats = self.statistics.get_counter("/net/punt")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001013 self.assertEqual(stats[0][7]['packets'], 3*NUM_PKTS)
1014 self.assertEqual(stats[0][8]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001015
1016 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1017 self.logger.info(self.vapi.cli("show punt client"))
1018 self.logger.info(self.vapi.cli("show punt reason"))
1019 self.logger.info(self.vapi.cli("show punt stats"))
1020 self.logger.info(self.vapi.cli("show punt db"))
1021
Neale Ranns50f0ac02019-05-15 02:13:37 -07001022 #
1023 # dump the punt registered reasons
1024 # search for a few we know should be there
1025 #
1026 rs = self.vapi.punt_reason_dump()
1027
1028 reasons = ["ipsec6-no-such-tunnel",
1029 "ipsec4-no-such-tunnel",
1030 "ipsec6-spi-0",
1031 "ipsec4-spi-0"]
1032
1033 for reason in reasons:
1034 found = False
1035 for r in rs:
1036 if r.reason.name == reason:
1037 found = True
1038 break
1039 self.assertTrue(found)
1040
Neale Ranns76b56492018-09-28 15:16:14 +00001041
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001042if __name__ == '__main__':
1043 unittest.main(testRunner=VppTestRunner)