ip: punt socket - take the tags in Ethernet header into consideration
The punt socket code rewinds the current_data pointer by sizeof (ethernet_header_t), which is incorrect if the header is tagged - resulting in truncated destination MAC address. Use ethernet_buffer_header_size() instead, which takes tags into account. Also add the unittest that verifies the issue and the fix. Type: fix Change-Id: I6352a174df144ca1e4230390c126f4b698724ebc Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
This commit is contained in:
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <vnet/ethernet/ethernet.h>
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/ip/punt.h>
|
||||
#include <vlib/unix/unix.h>
|
||||
@ -339,7 +340,7 @@ punt_socket_inline (vlib_main_t * vm,
|
||||
iov->iov_len = sizeof (packetdesc);
|
||||
|
||||
/** VLIB buffer chain -> Unix iovec(s). */
|
||||
vlib_buffer_advance (b, -(sizeof (ethernet_header_t)));
|
||||
vlib_buffer_advance (b, -ethernet_buffer_header_size (b));
|
||||
vec_add2 (ptd->iovecs, iov, 1);
|
||||
iov->iov_base = b->data + b->current_data;
|
||||
iov->iov_len = l = b->current_length;
|
||||
|
@ -21,6 +21,7 @@ from re import compile
|
||||
import scapy.compat
|
||||
from scapy.packet import Raw
|
||||
from scapy.layers.l2 import Ether
|
||||
from scapy.layers.l2 import Dot1Q
|
||||
from scapy.layers.inet import IP, UDP, ICMP
|
||||
from scapy.layers.ipsec import ESP
|
||||
import scapy.layers.inet6 as inet6
|
||||
@ -28,6 +29,7 @@ from scapy.layers.inet6 import IPv6, ICMPv6DestUnreach
|
||||
from scapy.contrib.ospf import OSPF_Hdr, OSPFv3_Hello
|
||||
from framework import tag_fixme_vpp_workers
|
||||
from framework import VppTestCase, VppTestRunner
|
||||
from vpp_sub_interface import VppSubInterface, VppDot1QSubint
|
||||
|
||||
from vpp_ip import DpoProto
|
||||
from vpp_ip_route import VppIpRoute, VppRoutePath
|
||||
@ -1015,6 +1017,86 @@ class TestIpProtoPuntSocket(TestPuntSocket):
|
||||
self.vapi.punt_socket_deregister(punt_ospf)
|
||||
|
||||
|
||||
class TestDot1QPuntSocket(TestPuntSocket):
|
||||
"""Punt Socket for 802.1Q (dot1q)"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestDot1QPuntSocket, self).setUp()
|
||||
|
||||
for i in self.pg_interfaces:
|
||||
i.admin_up()
|
||||
i.config_ip4()
|
||||
i.resolve_arp()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestDot1QPuntSocket, self).tearDown()
|
||||
for i in self.pg_interfaces:
|
||||
i.unconfig_ip4()
|
||||
i.admin_down()
|
||||
|
||||
def test_dot1q_header_punt(self):
|
||||
"""Punt socket traffic with Dot1q header"""
|
||||
|
||||
port = self.ports[0]
|
||||
pt_l4 = VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4
|
||||
punt_l4 = set_port(mk_vpp_cfg4(), port)
|
||||
|
||||
# VLAN ID
|
||||
vlan_id = 100
|
||||
|
||||
# Create a subinterface with the VLAN ID
|
||||
subif = VppDot1QSubint(self, self.pg0, vlan_id)
|
||||
subif.admin_up()
|
||||
subif.config_ip4()
|
||||
|
||||
# Configure an IP address on the subinterface
|
||||
subif_ip4 = subif.local_ip4
|
||||
|
||||
p = (
|
||||
Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
|
||||
/ Dot1Q(vlan=vlan_id)
|
||||
/ IP(src=self.pg0.remote_ip4, dst=subif_ip4)
|
||||
/ UDP(sport=9876, dport=port)
|
||||
/ Raw(b"\xa5" * 100)
|
||||
)
|
||||
|
||||
pkts = p * self.nr_packets
|
||||
|
||||
# Expect ICMP - port unreachable for all packets
|
||||
rx = self.send_and_expect_some(self.pg0, pkts, self.pg0)
|
||||
|
||||
for p in rx:
|
||||
self.assertEqual(int(p[IP].proto), 1) # ICMP
|
||||
self.assertEqual(int(p[ICMP].code), 3) # unreachable
|
||||
|
||||
# Configure a punt socket
|
||||
self.socket_client_create("%s/socket_%d" % (self.tempdir, port))
|
||||
self.vapi.punt_socket_register(punt_l4, "%s/socket_%d" % (self.tempdir, port))
|
||||
punts = self.vapi.punt_socket_dump(type=pt_l4)
|
||||
self.assertEqual(len(punts), 1)
|
||||
|
||||
# Expect punt socket and no packets on pg0
|
||||
self.send_and_assert_no_replies(self.pg0, pkts)
|
||||
rx = self.socket_client_close()
|
||||
self.logger.info("RXPKT")
|
||||
self.logger.info(rx)
|
||||
self.verify_udp_pkts(rx, len(pkts), port)
|
||||
for pkt in rx:
|
||||
self.assertEqual(pkt[Ether].src, self.pg0.remote_mac)
|
||||
self.assertEqual(pkt[Ether].dst, self.pg0.local_mac)
|
||||
self.assertEqual(pkt[Dot1Q].vlan, 100)
|
||||
|
||||
# Remove punt socket. Expect ICMP - port unreachable for all packets
|
||||
self.vapi.punt_socket_deregister(punt_l4)
|
||||
punts = self.vapi.punt_socket_dump(type=pt_l4)
|
||||
self.assertEqual(len(punts), 0)
|
||||
|
||||
rx = self.send_and_expect_some(self.pg0, pkts, self.pg0)
|
||||
for p in rx:
|
||||
self.assertEqual(int(p[IP].proto), 1) # ICMP
|
||||
self.assertEqual(int(p[ICMP].code), 3) # unreachable
|
||||
|
||||
|
||||
@tag_fixme_vpp_workers
|
||||
class TestPunt(VppTestCase):
|
||||
"""Exception Punt Test Case"""
|
||||
|
Reference in New Issue
Block a user