blob: c0c635079771cbef37acb090ebad07fe3d5bf8ce [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Pavel Kotuceke88865d2018-11-28 07:42:11 +01002import 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
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +01009import fcntl
10import time
11
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010012from struct import unpack, unpack_from
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -080013
14try:
15 import unittest2 as unittest
16except ImportError:
17 import unittest
18
Pavel Kotuceke88865d2018-11-28 07:42:11 +010019from util import ppp, ppc
20from re import compile
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070021import scapy.compat
Pavel Kotuceke88865d2018-11-28 07:42:11 +010022from scapy.packet import Raw
23from scapy.layers.l2 import Ether
24from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns50f0ac02019-05-15 02:13:37 -070025from scapy.layers.ipsec import ESP
Paul Vinciguerra22ab6f72019-03-07 17:55:33 -080026import scapy.layers.inet6 as inet6
Pavel Kotuceke88865d2018-11-28 07:42:11 +010027from scapy.layers.inet6 import IPv6, ICMPv6DestUnreach
Neale Rannsb538dd82019-05-21 06:54:54 -070028from scapy.contrib.ospf import OSPF_Hdr, OSPFv3_Hello
Pavel Kotuceke88865d2018-11-28 07:42:11 +010029from framework import VppTestCase, VppTestRunner
30
Neale Ranns76b56492018-09-28 15:16:14 +000031from vpp_ip import DpoProto
32from vpp_ip_route import VppIpRoute, VppRoutePath
Neale Ranns50f0ac02019-05-15 02:13:37 -070033from vpp_papi import VppEnum
34from vpp_ipsec_tun_interface import VppIpsecTunInterface
Neale Ranns76b56492018-09-28 15:16:14 +000035
Paul Vinciguerra4271c972019-05-14 13:25:49 -040036NUM_PKTS = 67
37
Pavel Kotuceke88865d2018-11-28 07:42:11 +010038
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010039class serverSocketThread(threading.Thread):
40 """ Socket server thread"""
41
Neale Ranns50f0ac02019-05-15 02:13:37 -070042 def __init__(self, threadID, sockName):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010043 threading.Thread.__init__(self)
44 self.threadID = threadID
45 self.sockName = sockName
46 self.sock = None
Neale Ranns50f0ac02019-05-15 02:13:37 -070047 self.rx_pkts = []
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010048 self.keep_running = True
Neale Ranns50f0ac02019-05-15 02:13:37 -070049
50 def rx_packets(self):
51 # Wait for some packets on socket
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010052 while self.keep_running:
53 try:
54 data = self.sock.recv(65536)
Neale Ranns50f0ac02019-05-15 02:13:37 -070055
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010056 # punt socket metadata
57 # packet_desc = data[0:8]
Neale Ranns50f0ac02019-05-15 02:13:37 -070058
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010059 # Ethernet
60 self.rx_pkts.append(Ether(data[8:]))
61 except IOError as e:
62 if e.errno == 11:
63 # nothing to receive, sleep a little
64 time.sleep(0.1)
65 pass
66 else:
67 raise
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010068
69 def run(self):
70 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
71 try:
72 os.unlink(self.sockName)
73 except:
74 pass
Neale Ranns50f0ac02019-05-15 02:13:37 -070075 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
76 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010077 fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010078 self.sock.bind(self.sockName)
79
Neale Ranns50f0ac02019-05-15 02:13:37 -070080 self.rx_packets()
81
82 def close(self):
83 self.sock.close()
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +010084 self.keep_running = False
Neale Ranns50f0ac02019-05-15 02:13:37 -070085 return self.rx_pkts
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010086
87
Pavel Kotuceke88865d2018-11-28 07:42:11 +010088class TestPuntSocket(VppTestCase):
89 """ Punt Socket """
90
Pavel Kotucek9edb83a2018-12-11 16:57:25 +010091 ports = [1111, 2222, 3333, 4444]
92 sock_servers = list()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +000093 # FIXME: nr_packets > 3 results in failure
94 # nr_packets = 3 makes the test unstable
95 nr_packets = 2
Pavel Kotuceke88865d2018-11-28 07:42:11 +010096
97 @classmethod
Paul Vinciguerra8d991d92019-01-25 14:05:48 -080098 def setUpClass(cls):
99 super(TestPuntSocket, cls).setUpClass()
100
101 @classmethod
102 def tearDownClass(cls):
103 super(TestPuntSocket, cls).tearDownClass()
104
105 @classmethod
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100106 def setUpConstants(cls):
Ole Troana45dc072018-12-21 16:04:22 +0100107 cls.extra_vpp_punt_config = [
108 "punt", "{", "socket", cls.tempdir+"/socket_punt", "}"]
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100109 super(TestPuntSocket, cls).setUpConstants()
110
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100111 def setUp(self):
112 super(TestPuntSocket, self).setUp()
113 random.seed()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100114
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100115 self.create_pg_interfaces(range(2))
116 for i in self.pg_interfaces:
117 i.admin_up()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100118
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100119 def tearDown(self):
120 del self.sock_servers[:]
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800121 super(TestPuntSocket, self).tearDown()
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100122
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100123 def socket_client_create(self, sock_name, id=None):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700124 thread = serverSocketThread(id, sock_name)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100125 self.sock_servers.append(thread)
126 thread.start()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700127 return thread
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100128
129 def socket_client_close(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -0700130 rx_pkts = []
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100131 for thread in self.sock_servers:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700132 rx_pkts += thread.close()
Andrew Yourtchenko3f8c8712019-11-05 19:38:08 +0100133 thread.join()
Neale Ranns50f0ac02019-05-15 02:13:37 -0700134 return rx_pkts
135
136 def verify_port(self, pr, vpr):
137 self.assertEqual(vpr.punt.type, pr['type'])
138 self.assertEqual(vpr.punt.punt.l4.port,
139 pr['punt']['l4']['port'])
140 self.assertEqual(vpr.punt.punt.l4.protocol,
141 pr['punt']['l4']['protocol'])
142 self.assertEqual(vpr.punt.punt.l4.af,
143 pr['punt']['l4']['af'])
144
145 def verify_exception(self, pr, vpr):
146 self.assertEqual(vpr.punt.type, pr['type'])
147 self.assertEqual(vpr.punt.punt.exception.id,
148 pr['punt']['exception']['id'])
149
Neale Rannsb538dd82019-05-21 06:54:54 -0700150 def verify_ip_proto(self, pr, vpr):
151 self.assertEqual(vpr.punt.type, pr['type'])
152 self.assertEqual(vpr.punt.punt.ip_proto.af,
153 pr['punt']['ip_proto']['af'])
154 self.assertEqual(vpr.punt.punt.ip_proto.protocol,
155 pr['punt']['ip_proto']['protocol'])
156
Neale Ranns50f0ac02019-05-15 02:13:37 -0700157 def verify_udp_pkts(self, rxs, n_rx, port):
158 n_match = 0
159 for rx in rxs:
160 self.assertTrue(rx.haslayer(UDP))
161 if rx[UDP].dport == port:
162 n_match += 1
163 self.assertEqual(n_match, n_rx)
164
165
166def set_port(pr, port):
167 pr['punt']['l4']['port'] = port
168 return pr
169
170
171def set_reason(pr, reason):
172 pr['punt']['exception']['id'] = reason
173 return pr
174
175
176def mk_vpp_cfg4():
177 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
178 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
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_ip4,
185 'protocol': udp_proto
186 }
187 }
188 }
189 return punt_l4
190
191
192def mk_vpp_cfg6():
193 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
194 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
195 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
196 punt_l4 = {
197 'type': pt_l4,
198 'punt': {
199 'l4': {
200 'af': af_ip6,
201 'protocol': udp_proto
202 }
203 }
204 }
205 return punt_l4
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100206
207
208class TestIP4PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700209 """ Punt Socket for IPv4 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100210
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800211 @classmethod
212 def setUpClass(cls):
213 super(TestIP4PuntSocket, cls).setUpClass()
214
215 @classmethod
216 def tearDownClass(cls):
217 super(TestIP4PuntSocket, cls).tearDownClass()
218
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100219 def setUp(self):
220 super(TestIP4PuntSocket, self).setUp()
221
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100222 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100223 i.config_ip4()
224 i.resolve_arp()
225
226 def tearDown(self):
227 super(TestIP4PuntSocket, self).tearDown()
228 for i in self.pg_interfaces:
229 i.unconfig_ip4()
230 i.admin_down()
231
232 def test_punt_socket_dump(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100233 """ Punt socket registration/deregistration"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100234
Neale Ranns50f0ac02019-05-15 02:13:37 -0700235 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
236 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
237 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
238
239 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100240 self.assertEqual(len(punts), 0)
241
242 #
243 # configure a punt socket
244 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700245 punt_l4 = mk_vpp_cfg4()
246
247 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200248 "%s/socket_punt_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700249 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
Ole Troan9cd8f332019-10-18 15:57:56 +0200250 "%s/socket_punt_2222" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700251 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100252 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700253 self.verify_port(set_port(punt_l4, 1111), punts[0])
254 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100255
256 #
257 # deregister a punt socket
258 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700259 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
260 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100261 self.assertEqual(len(punts), 1)
262
263 #
264 # configure a punt socket again
265 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700266 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200267 "%s/socket_punt_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700268 self.vapi.punt_socket_register(set_port(punt_l4, 3333),
Ole Troan9cd8f332019-10-18 15:57:56 +0200269 "%s/socket_punt_3333" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700270 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100271 self.assertEqual(len(punts), 3)
272
Neale Ranns50f0ac02019-05-15 02:13:37 -0700273 self.logger.info(self.vapi.cli("sh punt sock reg"))
274
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100275 #
276 # deregister all punt socket
277 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700278 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
279 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
280 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
281 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100282 self.assertEqual(len(punts), 0)
283
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100284 def test_punt_socket_traffic_single_port_single_socket(self):
285 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100286
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100287 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700288 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
289 punt_l4 = set_port(mk_vpp_cfg4(), port)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100290
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100291 p = (Ether(src=self.pg0.remote_mac,
292 dst=self.pg0.local_mac) /
293 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100294 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200295 Raw(b'\xa5' * 100))
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100296
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100297 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100298
Neale Ranns50f0ac02019-05-15 02:13:37 -0700299 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100300 self.assertEqual(len(punts), 0)
301
302 #
303 # expect ICMP - port unreachable for all packets
304 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700305 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
306
307 for p in rx:
308 self.assertEqual(int(p[IP].proto), 1) # ICMP
309 self.assertEqual(int(p[ICMP].code), 3) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100310
311 #
312 # configure a punt socket
313 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200314 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
315 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" %
316 (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700317 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100318 self.assertEqual(len(punts), 1)
319
320 #
321 # expect punt socket and no packets on pg0
322 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700323 self.send_and_assert_no_replies(self.pg0, pkts)
324 rx = self.socket_client_close()
325 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100326
327 #
328 # remove punt socket. expect ICMP - port unreachable for all packets
329 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700330 self.vapi.punt_socket_deregister(punt_l4)
331 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100332 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100333
Neale Ranns50f0ac02019-05-15 02:13:37 -0700334 rx = self.send_and_expect(self.pg0, pkts, self.pg0)
335 for p in rx:
336 self.assertEqual(int(p[IP].proto), 1) # ICMP
337 self.assertEqual(int(p[ICMP].code), 3) # unreachable
338
339 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100340 """ Punt socket traffic multi ports and multi sockets"""
341
Neale Ranns50f0ac02019-05-15 02:13:37 -0700342 punt_l4 = mk_vpp_cfg4()
343
344 # configuration for each UDP port
345 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100346
347 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700348 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100349 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700350 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100351 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700352 cfgs[port] = {}
353
354 pkt = (Ether(src=self.pg0.remote_mac,
355 dst=self.pg0.local_mac) /
356 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
357 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200358 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700359 cfgs[port]['pkts'] = pkt * self.nr_packets
360 cfgs[port]['port'] = port
361 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
362
363 # configure punt sockets
364 cfgs[port]['sock'] = self.socket_client_create(
Ole Troan9cd8f332019-10-18 15:57:56 +0200365 "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700366 self.vapi.punt_socket_register(
367 cfgs[port]['vpp'],
Ole Troan9cd8f332019-10-18 15:57:56 +0200368 "%s/socket_%d" % (self.tempdir, port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100369
370 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700371 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100372 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700373 for cfg in cfgs.values():
374 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100375
376 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700377 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100378 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700379 for cfg in cfgs.values():
380 rx = cfg['sock'].close()
381 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
382 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100383
384 def test_punt_socket_traffic_multi_ports_single_socket(self):
385 """ Punt socket traffic multi ports and single socket"""
386
Neale Ranns50f0ac02019-05-15 02:13:37 -0700387 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
388 punt_l4 = mk_vpp_cfg4()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100389
390 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700391 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100392 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700393 pkts = []
394 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100395 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700396 pkt = (Ether(src=self.pg0.remote_mac,
397 dst=self.pg0.local_mac) /
398 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
399 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200400 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700401 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100402
403 #
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100404 # configure a punt socket
405 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200406 self.socket_client_create("%s/socket_multi" % self.tempdir)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100407 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700408 self.vapi.punt_socket_register(set_port(punt_l4, p),
Ole Troan9cd8f332019-10-18 15:57:56 +0200409 "%s/socket_multi" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700410 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100411 self.assertEqual(len(punts), len(self.ports))
412
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100413 #
414 # expect punt socket and no packets on pg0
415 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700416 self.send_and_assert_no_replies(self.pg0, pkts)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100417 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700418 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100419
420 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700421 self.verify_udp_pkts(rx, self.nr_packets, p)
422 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
423 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100424 self.assertEqual(len(punts), 0)
425
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100426
427class TestIP6PuntSocket(TestPuntSocket):
Neale Rannsb538dd82019-05-21 06:54:54 -0700428 """ Punt Socket for IPv6 UDP """
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100429
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800430 @classmethod
431 def setUpClass(cls):
432 super(TestIP6PuntSocket, cls).setUpClass()
433
434 @classmethod
435 def tearDownClass(cls):
436 super(TestIP6PuntSocket, cls).tearDownClass()
437
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100438 def setUp(self):
439 super(TestIP6PuntSocket, self).setUp()
440
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100441 for i in self.pg_interfaces:
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100442 i.config_ip6()
443 i.resolve_ndp()
444
445 def tearDown(self):
446 super(TestIP6PuntSocket, self).tearDown()
447 for i in self.pg_interfaces:
448 i.unconfig_ip6()
449 i.admin_down()
450
451 def test_punt_socket_dump(self):
452 """ Punt socket registration """
453
Neale Ranns50f0ac02019-05-15 02:13:37 -0700454 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
455 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
456 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
457 #
458 # configure a punt socket
459 #
460 punt_l4 = {
461 'type': pt_l4,
462 'punt': {
463 'l4': {
464 'af': af_ip6,
465 'protocol': udp_proto
466 }
467 }
468 }
469
470 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100471 self.assertEqual(len(punts), 0)
472
473 #
474 # configure a punt socket
475 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700476 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200477 "%s/socket_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700478 self.vapi.punt_socket_register(set_port(punt_l4, 2222),
Ole Troan9cd8f332019-10-18 15:57:56 +0200479 "%s/socket_2222" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700480 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100481 self.assertEqual(len(punts), 2)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700482 self.verify_port(set_port(punt_l4, 1111), punts[0])
483 self.verify_port(set_port(punt_l4, 2222), punts[1])
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100484
485 #
486 # deregister a punt socket
487 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700488 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
489 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100490 self.assertEqual(len(punts), 1)
491
492 #
493 # configure a punt socket again
494 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700495 self.vapi.punt_socket_register(set_port(punt_l4, 1111),
Ole Troan9cd8f332019-10-18 15:57:56 +0200496 "%s/socket_1111" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700497 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100498 self.assertEqual(len(punts), 2)
499
500 #
501 # deregister all punt socket
502 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700503 self.vapi.punt_socket_deregister(set_port(punt_l4, 1111))
504 self.vapi.punt_socket_deregister(set_port(punt_l4, 2222))
505 self.vapi.punt_socket_deregister(set_port(punt_l4, 3333))
506 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100507 self.assertEqual(len(punts), 0)
508
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100509 def test_punt_socket_traffic_single_port_single_socket(self):
510 """ Punt socket traffic single port single socket"""
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100511
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100512 port = self.ports[0]
Neale Ranns50f0ac02019-05-15 02:13:37 -0700513 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
514 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
515 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
516 punt_l4 = {
517 'type': pt_l4,
518 'punt': {
519 'l4': {
520 'af': af_ip6,
521 'protocol': udp_proto,
522 'port': port,
523 }
524 }
525 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100526
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100527 p = (Ether(src=self.pg0.remote_mac,
528 dst=self.pg0.local_mac) /
529 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100530 inet6.UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200531 Raw(b'\xa5' * 100))
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100532
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100533 pkts = p * self.nr_packets
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100534
Neale Ranns50f0ac02019-05-15 02:13:37 -0700535 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100536 self.assertEqual(len(punts), 0)
537
538 #
539 # expect ICMPv6 - destination unreachable for all packets
540 #
541 self.vapi.cli("clear trace")
542 self.pg0.add_stream(pkts)
543 self.pg_enable_capture(self.pg_interfaces)
544 self.pg_start()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100545 # FIXME - when punt socket deregister is implemented
546 # rx = self.pg0.get_capture(self.nr_packets)
547 # for p in rx:
548 # self.assertEqual(int(p[IPv6].nh), 58) # ICMPv6
549 # self.assertEqual(int(p[ICMPv6DestUnreach].code),4) # unreachable
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100550
551 #
552 # configure a punt socket
553 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200554 self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
555 self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" %
556 (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700557 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100558 self.assertEqual(len(punts), 1)
559
560 #
561 # expect punt socket and no packets on pg0
562 #
563 self.vapi.cli("clear errors")
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100564 self.vapi.cli("clear trace")
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100565 self.pg0.add_stream(pkts)
566 self.pg_enable_capture(self.pg_interfaces)
567 self.pg_start()
568 self.pg0.get_capture(0)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100569 self.logger.info(self.vapi.cli("show trace"))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700570 rx = self.socket_client_close()
571 self.verify_udp_pkts(rx, len(pkts), port)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100572
573 #
574 # remove punt socket. expect ICMP - dest. unreachable for all packets
575 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700576 self.vapi.punt_socket_deregister(punt_l4)
577 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100578 self.assertEqual(len(punts), 0)
579 self.pg0.add_stream(pkts)
580 self.pg_enable_capture(self.pg_interfaces)
581 self.pg_start()
582 # FIXME - when punt socket deregister is implemented
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100583 # self.pg0.get_capture(nr_packets)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100584
Neale Ranns50f0ac02019-05-15 02:13:37 -0700585 def test_punt_socket_traffic_multi_ports_multi_sockets(self):
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100586 """ Punt socket traffic multi ports and multi sockets"""
587
Neale Ranns50f0ac02019-05-15 02:13:37 -0700588 punt_l4 = mk_vpp_cfg6()
589
590 # configuration for each UDP port
591 cfgs = dict()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100592
593 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700594 # create stream of packets for each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100595 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700596 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100597 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700598 cfgs[port] = {}
599
600 pkt = (Ether(src=self.pg0.remote_mac,
601 dst=self.pg0.local_mac) /
602 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
603 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200604 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700605 cfgs[port]['pkts'] = pkt * self.nr_packets
606 cfgs[port]['port'] = port
607 cfgs[port]['vpp'] = copy.deepcopy(set_port(punt_l4, port))
608
609 # configure punt sockets
610 cfgs[port]['sock'] = self.socket_client_create(
Ole Troan9cd8f332019-10-18 15:57:56 +0200611 "%s/socket_%d" % (self.tempdir, port))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700612 self.vapi.punt_socket_register(
613 cfgs[port]['vpp'],
Ole Troan9cd8f332019-10-18 15:57:56 +0200614 "%s/socket_%d" % (self.tempdir, port))
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100615
616 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700617 # send the packets that get punted
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100618 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700619 for cfg in cfgs.values():
620 self.send_and_assert_no_replies(self.pg0, cfg['pkts'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100621
622 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700623 # test that we got the excepted packets on the expected socket
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100624 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700625 for cfg in cfgs.values():
626 rx = cfg['sock'].close()
627 self.verify_udp_pkts(rx, len(cfg['pkts']), cfg['port'])
628 self.vapi.punt_socket_deregister(cfg['vpp'])
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100629
630 def test_punt_socket_traffic_multi_ports_single_socket(self):
631 """ Punt socket traffic multi ports and single socket"""
632
Neale Ranns50f0ac02019-05-15 02:13:37 -0700633 pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
634 af_ip6 = VppEnum.vl_api_address_family_t.ADDRESS_IP6
635 udp_proto = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP
636 punt_l4 = {
637 'type': pt_l4,
638 'punt': {
639 'l4': {
640 'af': af_ip6,
641 'protocol': udp_proto,
642 }
643 }
644 }
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100645
646 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700647 # create stream of packets with each port
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100648 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700649 pkts = []
650 for port in self.ports:
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100651 # choose port from port list
Neale Ranns50f0ac02019-05-15 02:13:37 -0700652 pkt = (Ether(src=self.pg0.remote_mac,
653 dst=self.pg0.local_mac) /
654 IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
655 UDP(sport=9876, dport=port) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200656 Raw(b'\xa5' * 100))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700657 pkts += pkt * self.nr_packets
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100658
659 #
660 # no punt socket
661 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700662 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100663 self.assertEqual(len(punts), 0)
664
665 #
666 # configure a punt socket
667 #
Ole Troan9cd8f332019-10-18 15:57:56 +0200668 self.socket_client_create("%s/socket_multi" % 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),
Ole Troan9cd8f332019-10-18 15:57:56 +0200671 "%s/socket_multi" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700672 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100673 self.assertEqual(len(punts), len(self.ports))
674
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100675 #
676 # expect punt socket and no packets on pg0
677 #
678 self.vapi.cli("clear errors")
679 self.vapi.cli("clear trace")
680 self.pg0.add_stream(pkts)
681 self.pg_enable_capture(self.pg_interfaces)
682 self.pg_start()
Andrew Yourtchenkocb265c62019-07-25 10:03:51 +0000683 # give a chance to punt socket to collect all packets
684 self.sleep(1)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100685 self.pg0.get_capture(0)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700686 rx = self.socket_client_close()
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100687
688 for p in self.ports:
Neale Ranns50f0ac02019-05-15 02:13:37 -0700689 self.verify_udp_pkts(rx, self.nr_packets, p)
690 self.vapi.punt_socket_deregister(set_port(punt_l4, p))
691 punts = self.vapi.punt_socket_dump(type=pt_l4)
Pavel Kotucek9edb83a2018-12-11 16:57:25 +0100692 self.assertEqual(len(punts), 0)
Pavel Kotuceke88865d2018-11-28 07:42:11 +0100693
Neale Ranns76b56492018-09-28 15:16:14 +0000694
Neale Ranns50f0ac02019-05-15 02:13:37 -0700695class TestExceptionPuntSocket(TestPuntSocket):
696 """ Punt Socket for Exceptions """
697
698 @classmethod
699 def setUpClass(cls):
700 super(TestExceptionPuntSocket, cls).setUpClass()
701
702 @classmethod
703 def tearDownClass(cls):
704 super(TestExceptionPuntSocket, cls).tearDownClass()
705
706 def setUp(self):
707 super(TestExceptionPuntSocket, self).setUp()
708
Neale Ranns12989b52019-09-26 16:20:19 +0000709 self.create_pg_interfaces(range(2))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700710 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),
Ole Troan9cd8f332019-10-18 15:57:56 +0200739 "%s/socket_punt_1" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700740 self.vapi.punt_socket_register(set_reason(punt_ex, 2),
Ole Troan9cd8f332019-10-18 15:57:56 +0200741 "%s/socket_punt_2" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700742 punts = self.vapi.punt_socket_dump(type=pt_ex)
743 self.assertEqual(len(punts), 2)
744 self.verify_exception(set_reason(punt_ex, 1), punts[0])
745 self.verify_exception(set_reason(punt_ex, 2), punts[1])
746
747 #
748 # deregister a punt socket
749 #
750 self.vapi.punt_socket_deregister(set_reason(punt_ex, 1))
751 punts = self.vapi.punt_socket_dump(type=pt_ex)
752 self.assertEqual(len(punts), 1)
753
754 #
755 # configure a punt socket again
756 #
757 self.vapi.punt_socket_register(set_reason(punt_ex, 1),
Ole Troan9cd8f332019-10-18 15:57:56 +0200758 "%s/socket_punt_1" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700759 self.vapi.punt_socket_register(set_reason(punt_ex, 3),
Ole Troan9cd8f332019-10-18 15:57:56 +0200760 "%s/socket_punt_3" % self.tempdir)
Neale Ranns50f0ac02019-05-15 02:13:37 -0700761 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),
Ole Troan9cd8f332019-10-18 15:57:56 +0200803 b"0123456701234567",
804 b"0123456701234567",
Neale Ranns50f0ac02019-05-15 02:13:37 -0700805 (VppEnum.vl_api_ipsec_integ_alg_t.
806 IPSEC_API_INTEG_ALG_SHA1_96),
Ole Troan9cd8f332019-10-18 15:57:56 +0200807 b"0123456701234567",
808 b"0123456701234567").add_vpp_config()
Neale Ranns12989b52019-09-26 16:20:19 +0000809 VppIpsecTunInterface(self, self.pg1, 1000, 1000,
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700810 (VppEnum.vl_api_ipsec_crypto_alg_t.
811 IPSEC_API_CRYPTO_ALG_AES_CBC_128),
Ole Troan9cd8f332019-10-18 15:57:56 +0200812 b"0123456701234567",
813 b"0123456701234567",
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700814 (VppEnum.vl_api_ipsec_integ_alg_t.
815 IPSEC_API_INTEG_ALG_SHA1_96),
Ole Troan9cd8f332019-10-18 15:57:56 +0200816 b"0123456701234567",
817 b"0123456701234567",
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700818 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 Ranns12989b52019-09-26 16:20:19 +0000825 cfgs['ipsec4-no-such-tunnel'] = {'spi': 99,
826 'udp': False,
827 'itf': self.pg0}
828 cfgs['ipsec4-spi-o-udp-0'] = {'spi': 0,
829 'udp': True,
830 'itf': self.pg1}
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():
Ole Troan9cd8f332019-10-18 15:57:56 +0200849 cfg['sock'] = self.socket_client_create("%s/socket_%d" %
850 (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700851 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +0200852 cfg['vpp'], "%s/socket_%d" % (self.tempdir, cfg['id']))
Neale Ranns50f0ac02019-05-15 02:13:37 -0700853
854 #
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700855 # create packet streams for 'no-such-tunnel' exception
856 #
857 for cfg in cfgs.values():
Neale Ranns12989b52019-09-26 16:20:19 +0000858 pkt = (Ether(src=cfg['itf'].remote_mac,
859 dst=cfg['itf'].local_mac) /
860 IP(src=cfg['itf'].remote_ip4,
861 dst=cfg['itf'].local_ip4))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700862 if (cfg['udp']):
863 pkt = pkt / UDP(sport=666, dport=4500)
864 pkt = (pkt / ESP(spi=cfg['spi'], seq=3) /
Ole Troan9cd8f332019-10-18 15:57:56 +0200865 Raw(b'\xa5' * 100))
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700866 cfg['pkts'] = [pkt]
867
868 #
Neale Ranns50f0ac02019-05-15 02:13:37 -0700869 # send packets for each SPI we expect to be punted
870 #
871 for cfg in cfgs.values():
Neale Ranns12989b52019-09-26 16:20:19 +0000872 self.send_and_assert_no_replies(cfg['itf'], cfg['pkts'])
Neale Ranns50f0ac02019-05-15 02:13:37 -0700873
874 #
875 # verify the punted packets arrived on the associated socket
876 #
877 for cfg in cfgs.values():
878 rx = cfg['sock'].close()
Neale Rannsa6bee0a2019-06-14 01:13:25 -0700879 self.verify_esp_pkts(rx, len(cfg['pkts']),
880 cfg['spi'], cfg['udp'])
881
882 #
883 # socket deregister
884 #
885 for cfg in cfgs.values():
Neale Ranns50f0ac02019-05-15 02:13:37 -0700886 self.vapi.punt_socket_deregister(cfg['vpp'])
887
888
Neale Rannsb538dd82019-05-21 06:54:54 -0700889class TestIpProtoPuntSocket(TestPuntSocket):
890 """ Punt Socket for IP packets """
891
892 @classmethod
893 def setUpClass(cls):
894 super(TestIpProtoPuntSocket, cls).setUpClass()
895
896 @classmethod
897 def tearDownClass(cls):
898 super(TestIpProtoPuntSocket, cls).tearDownClass()
899
900 def setUp(self):
901 super(TestIpProtoPuntSocket, self).setUp()
902
903 for i in self.pg_interfaces:
904 i.config_ip4()
905 i.resolve_arp()
906
907 def tearDown(self):
908 super(TestIpProtoPuntSocket, self).tearDown()
909 for i in self.pg_interfaces:
910 i.unconfig_ip4()
911 i.admin_down()
912
913 def test_registration(self):
914 """ Punt socket registration/deregistration"""
915
916 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
917 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
918 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
919 proto_eigrp = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_EIGRP
920
921 punts = self.vapi.punt_socket_dump(type=pt_ip)
922 self.assertEqual(len(punts), 0)
923
924 #
925 # configure a punt socket
926 #
927 punt_ospf = {
928 'type': pt_ip,
929 'punt': {
930 'ip_proto': {
931 'af': af_ip4,
932 'protocol': proto_ospf
933 }
934 }
935 }
936 punt_eigrp = {
937 'type': pt_ip,
938 'punt': {
939 'ip_proto': {
940 'af': af_ip4,
941 'protocol': proto_eigrp
942 }
943 }
944 }
945
946 self.vapi.punt_socket_register(punt_ospf,
Ole Troan9cd8f332019-10-18 15:57:56 +0200947 "%s/socket_punt_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700948 self.vapi.punt_socket_register(punt_eigrp,
Ole Troan9cd8f332019-10-18 15:57:56 +0200949 "%s/socket_punt_2" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700950 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,
Ole Troan9cd8f332019-10-18 15:57:56 +0200967 "%s/socket_punt_3" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -0700968 punts = self.vapi.punt_socket_dump(type=pt_ip)
969 self.assertEqual(len(punts), 2)
970
971 self.logger.info(self.vapi.cli("sh punt sock reg exception"))
972
973 #
974 # deregister all punt socket
975 #
976 self.vapi.punt_socket_deregister(punt_eigrp)
977 self.vapi.punt_socket_deregister(punt_ospf)
978 punts = self.vapi.punt_socket_dump(type=pt_ip)
979 self.assertEqual(len(punts), 0)
980
981 def verify_ospf_pkts(self, rxs, n_sent):
982 self.assertEqual(len(rxs), n_sent)
983 for rx in rxs:
984 self.assertTrue(rx.haslayer(OSPF_Hdr))
985
986 def test_traffic(self):
987 """ Punt socket traffic """
988
989 af_ip4 = VppEnum.vl_api_address_family_t.ADDRESS_IP4
990 pt_ip = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_IP_PROTO
991 proto_ospf = VppEnum.vl_api_ip_proto_t.IP_API_PROTO_OSPF
992
993 #
994 # configure a punt socket to capture OSPF packets
995 #
996 punt_ospf = {
997 'type': pt_ip,
998 'punt': {
999 'ip_proto': {
1000 'af': af_ip4,
1001 'protocol': proto_ospf
1002 }
1003 }
1004 }
1005
1006 #
1007 # create packet streams and configure a punt sockets
1008 #
1009 pkt = (Ether(src=self.pg0.remote_mac,
1010 dst=self.pg0.local_mac) /
1011 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
1012 OSPF_Hdr() /
1013 OSPFv3_Hello())
1014 pkts = pkt * 7
1015
Ole Troan9cd8f332019-10-18 15:57:56 +02001016 sock = self.socket_client_create("%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001017 self.vapi.punt_socket_register(
Ole Troan9cd8f332019-10-18 15:57:56 +02001018 punt_ospf, "%s/socket_1" % self.tempdir)
Neale Rannsb538dd82019-05-21 06:54:54 -07001019
1020 #
1021 # send packets for each SPI we expect to be punted
1022 #
1023 self.send_and_assert_no_replies(self.pg0, pkts)
1024
1025 #
1026 # verify the punted packets arrived on the associated socket
1027 #
1028 rx = sock.close()
1029 self.verify_ospf_pkts(rx, len(pkts))
1030 self.vapi.punt_socket_deregister(punt_ospf)
1031
1032
Neale Ranns76b56492018-09-28 15:16:14 +00001033class TestPunt(VppTestCase):
Neale Rannsb538dd82019-05-21 06:54:54 -07001034 """ Exception Punt Test Case """
Neale Ranns76b56492018-09-28 15:16:14 +00001035
1036 @classmethod
1037 def setUpClass(cls):
1038 super(TestPunt, cls).setUpClass()
1039
1040 @classmethod
1041 def tearDownClass(cls):
1042 super(TestPunt, cls).tearDownClass()
1043
1044 def setUp(self):
1045 super(TestPunt, self).setUp()
1046
1047 self.create_pg_interfaces(range(4))
1048
1049 for i in self.pg_interfaces:
1050 i.admin_up()
1051 i.config_ip4()
1052 i.resolve_arp()
1053 i.config_ip6()
1054 i.resolve_ndp()
1055
1056 def tearDown(self):
1057 for i in self.pg_interfaces:
1058 i.unconfig_ip4()
1059 i.unconfig_ip6()
1060 i.ip6_disable()
1061 i.admin_down()
1062 super(TestPunt, self).tearDown()
1063
1064 def test_punt(self):
Neale Ranns50f0ac02019-05-15 02:13:37 -07001065 """ Exception Path testing """
Neale Ranns76b56492018-09-28 15:16:14 +00001066
1067 #
Neale Ranns719beb72019-07-10 07:10:25 +00001068 # dump the punt registered reasons
1069 # search for a few we know should be there
1070 #
1071 rs = self.vapi.punt_reason_dump()
1072
1073 reasons = ["ipsec6-no-such-tunnel",
1074 "ipsec4-no-such-tunnel",
1075 "ipsec4-spi-o-udp-0"]
1076
1077 for reason in reasons:
1078 found = False
1079 for r in rs:
1080 if r.reason.name == reason:
1081 found = True
1082 break
1083 self.assertTrue(found)
1084
1085 #
Neale Ranns76b56492018-09-28 15:16:14 +00001086 # Using the test CLI we will hook in a exception path to
1087 # send ACL deny packets out of pg0 and pg1.
1088 # the ACL is src,dst = 1.1.1.1,1.1.1.2
1089 #
1090 ip_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32,
1091 [VppRoutePath(self.pg3.remote_ip4,
1092 self.pg3.sw_if_index)])
1093 ip_1_1_1_2.add_vpp_config()
1094 ip_1_2 = VppIpRoute(self, "1::2", 128,
1095 [VppRoutePath(self.pg3.remote_ip6,
1096 self.pg3.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001097 proto=DpoProto.DPO_PROTO_IP6)])
Neale Ranns76b56492018-09-28 15:16:14 +00001098 ip_1_2.add_vpp_config()
1099
1100 p4 = (Ether(src=self.pg2.remote_mac,
1101 dst=self.pg2.local_mac) /
1102 IP(src="1.1.1.1", dst="1.1.1.2") /
1103 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001104 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001105 p6 = (Ether(src=self.pg2.remote_mac,
1106 dst=self.pg2.local_mac) /
1107 IPv6(src="1::1", dst="1::2") /
1108 UDP(sport=1234, dport=1234) /
Ole Troan9cd8f332019-10-18 15:57:56 +02001109 Raw(b'\xa5' * 100))
Neale Ranns76b56492018-09-28 15:16:14 +00001110 self.send_and_expect(self.pg2, p4*1, self.pg3)
1111 self.send_and_expect(self.pg2, p6*1, self.pg3)
1112
1113 #
1114 # apply the punting features
1115 #
1116 self.vapi.cli("test punt pg2")
1117
1118 #
Neale Ranns719beb72019-07-10 07:10:25 +00001119 # dump the punt reasons to learn the IDs assigned
1120 #
1121 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v4"})
1122 r4 = rs[0].reason.id
1123 rs = self.vapi.punt_reason_dump(reason={'name': "reason-v6"})
1124 r6 = rs[0].reason.id
1125
1126 #
Neale Ranns76b56492018-09-28 15:16:14 +00001127 # pkts now dropped
1128 #
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001129 self.send_and_assert_no_replies(self.pg2, p4*NUM_PKTS)
1130 self.send_and_assert_no_replies(self.pg2, p6*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001131
1132 #
1133 # Check state:
1134 # 1 - node error counters
1135 # 2 - per-reason counters
1136 # 2, 3 are the index of the assigned punt reason
1137 #
Ole Troan233e4682019-05-16 15:01:34 +02001138 stats = self.statistics.get_err_counter(
Neale Ranns76b56492018-09-28 15:16:14 +00001139 "/err/punt-dispatch/No registrations")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001140 self.assertEqual(stats, 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001141
1142 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001143 self.assertEqual(stats[0][r4]['packets'], NUM_PKTS)
1144 self.assertEqual(stats[0][r6]['packets'], NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001145
1146 #
1147 # use the test CLI to test a client that punts exception
1148 # packets out of pg0
1149 #
1150 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip4)
1151 self.vapi.cli("test punt pg0 %s" % self.pg0.remote_ip6)
1152
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001153 rx4s = self.send_and_expect(self.pg2, p4*NUM_PKTS, self.pg0)
1154 rx6s = self.send_and_expect(self.pg2, p6*NUM_PKTS, self.pg0)
Neale Ranns76b56492018-09-28 15:16:14 +00001155
1156 #
1157 # check the packets come out IP unmodified but destined to pg0 host
1158 #
1159 for rx in rx4s:
1160 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1161 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1162 self.assertEqual(p4[IP].dst, rx[IP].dst)
1163 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1164 for rx in rx6s:
1165 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1166 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1167 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1168 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1169
1170 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001171 self.assertEqual(stats[0][r4]['packets'], 2*NUM_PKTS)
1172 self.assertEqual(stats[0][r6]['packets'], 2*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001173
1174 #
1175 # add another registration for the same reason to send packets
1176 # out of pg1
1177 #
1178 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip4)
1179 self.vapi.cli("test punt pg1 %s" % self.pg1.remote_ip6)
1180
1181 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001182 self.pg2.add_stream(p4 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001183 self.pg_enable_capture(self.pg_interfaces)
1184 self.pg_start()
1185
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001186 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001187 for rx in rxd:
1188 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1189 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1190 self.assertEqual(p4[IP].dst, rx[IP].dst)
1191 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001192 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001193 for rx in rxd:
1194 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1195 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1196 self.assertEqual(p4[IP].dst, rx[IP].dst)
1197 self.assertEqual(p4[IP].ttl, rx[IP].ttl)
1198
1199 self.vapi.cli("clear trace")
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001200 self.pg2.add_stream(p6 * NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001201 self.pg_enable_capture(self.pg_interfaces)
1202 self.pg_start()
1203
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001204 rxd = self.pg0.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001205 for rx in rxd:
1206 self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
1207 self.assertEqual(rx[Ether].src, self.pg0.local_mac)
1208 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1209 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001210 rxd = self.pg1.get_capture(NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001211 for rx in rxd:
1212 self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
1213 self.assertEqual(rx[Ether].src, self.pg1.local_mac)
1214 self.assertEqual(p6[IPv6].dst, rx[IPv6].dst)
1215 self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim)
1216
1217 stats = self.statistics.get_counter("/net/punt")
Neale Ranns719beb72019-07-10 07:10:25 +00001218 self.assertEqual(stats[0][r4]['packets'], 3*NUM_PKTS)
1219 self.assertEqual(stats[0][r6]['packets'], 3*NUM_PKTS)
Neale Ranns76b56492018-09-28 15:16:14 +00001220
1221 self.logger.info(self.vapi.cli("show vlib graph punt-dispatch"))
1222 self.logger.info(self.vapi.cli("show punt client"))
1223 self.logger.info(self.vapi.cli("show punt reason"))
1224 self.logger.info(self.vapi.cli("show punt stats"))
1225 self.logger.info(self.vapi.cli("show punt db"))
1226
Neale Ranns76b56492018-09-28 15:16:14 +00001227
Pavel Kotuceke88865d2018-11-28 07:42:11 +01001228if __name__ == '__main__':
1229 unittest.main(testRunner=VppTestRunner)