gso: add support for IP-IP
Type: feature Change-Id: I37752af8496e0042a1da91124f3d94216b39ff11 Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
This commit is contained in:

committed by
Neale Ranns

parent
5ec6a4ea44
commit
84f91fa9c5
@ -168,13 +168,15 @@ virtio_free_used_device_desc (vlib_main_t * vm, virtio_vring_t * vring,
|
||||
}
|
||||
|
||||
static_always_inline void
|
||||
set_checksum_offsets (vlib_buffer_t * b, struct virtio_net_hdr_v1 *hdr)
|
||||
set_checksum_offsets (vlib_buffer_t * b, struct virtio_net_hdr_v1 *hdr,
|
||||
int is_l2)
|
||||
{
|
||||
if (b->flags & VNET_BUFFER_F_IS_IP4)
|
||||
{
|
||||
ip4_header_t *ip4;
|
||||
generic_header_offset_t gho = { 0 };
|
||||
vnet_generic_header_offset_parser (b, &gho);
|
||||
vnet_generic_header_offset_parser (b, &gho, is_l2, 1 /* ip4 */ ,
|
||||
0 /* ip6 */ );
|
||||
hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
|
||||
hdr->csum_start = gho.l4_hdr_offset; // 0x22;
|
||||
if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)
|
||||
@ -198,7 +200,8 @@ set_checksum_offsets (vlib_buffer_t * b, struct virtio_net_hdr_v1 *hdr)
|
||||
else if (b->flags & VNET_BUFFER_F_IS_IP6)
|
||||
{
|
||||
generic_header_offset_t gho = { 0 };
|
||||
vnet_generic_header_offset_parser (b, &gho);
|
||||
vnet_generic_header_offset_parser (b, &gho, is_l2, 0 /* ip4 */ ,
|
||||
1 /* ip6 */ );
|
||||
hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
|
||||
hdr->csum_start = gho.l4_hdr_offset; // 0x36;
|
||||
if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)
|
||||
@ -213,13 +216,14 @@ set_checksum_offsets (vlib_buffer_t * b, struct virtio_net_hdr_v1 *hdr)
|
||||
}
|
||||
|
||||
static_always_inline void
|
||||
set_gso_offsets (vlib_buffer_t * b, struct virtio_net_hdr_v1 *hdr)
|
||||
set_gso_offsets (vlib_buffer_t * b, struct virtio_net_hdr_v1 *hdr, int is_l2)
|
||||
{
|
||||
if (b->flags & VNET_BUFFER_F_IS_IP4)
|
||||
{
|
||||
ip4_header_t *ip4;
|
||||
generic_header_offset_t gho = { 0 };
|
||||
vnet_generic_header_offset_parser (b, &gho);
|
||||
vnet_generic_header_offset_parser (b, &gho, is_l2, 1 /* ip4 */ ,
|
||||
0 /* ip6 */ );
|
||||
hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
|
||||
hdr->gso_size = vnet_buffer2 (b)->gso_size;
|
||||
hdr->hdr_len = gho.hdr_sz;
|
||||
@ -238,7 +242,8 @@ set_gso_offsets (vlib_buffer_t * b, struct virtio_net_hdr_v1 *hdr)
|
||||
else if (b->flags & VNET_BUFFER_F_IS_IP6)
|
||||
{
|
||||
generic_header_offset_t gho = { 0 };
|
||||
vnet_generic_header_offset_parser (b, &gho);
|
||||
vnet_generic_header_offset_parser (b, &gho, is_l2, 0 /* ip4 */ ,
|
||||
1 /* ip6 */ );
|
||||
hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
|
||||
hdr->gso_size = vnet_buffer2 (b)->gso_size;
|
||||
hdr->hdr_len = gho.hdr_sz;
|
||||
@ -260,13 +265,14 @@ add_buffer_to_slot (vlib_main_t * vm, virtio_if_t * vif,
|
||||
d = &vring->desc[next];
|
||||
vlib_buffer_t *b = vlib_get_buffer (vm, bi);
|
||||
struct virtio_net_hdr_v1 *hdr = vlib_buffer_get_current (b) - hdr_sz;
|
||||
int is_l2 = (vif->type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_PCI));
|
||||
|
||||
clib_memset (hdr, 0, hdr_sz);
|
||||
|
||||
if (b->flags & VNET_BUFFER_F_GSO)
|
||||
{
|
||||
if (do_gso)
|
||||
set_gso_offsets (b, hdr);
|
||||
set_gso_offsets (b, hdr, is_l2);
|
||||
else
|
||||
{
|
||||
virtio_interface_drop_inline (vm, node_index, &bi, 1,
|
||||
@ -278,7 +284,7 @@ add_buffer_to_slot (vlib_main_t * vm, virtio_if_t * vif,
|
||||
VNET_BUFFER_F_OFFLOAD_UDP_CKSUM))
|
||||
{
|
||||
if (csum_offload)
|
||||
set_checksum_offsets (b, hdr);
|
||||
set_checksum_offsets (b, hdr, is_l2);
|
||||
else
|
||||
{
|
||||
virtio_interface_drop_inline (vm, node_index, &bi, 1,
|
||||
|
@ -237,7 +237,11 @@ vhost_user_handle_tx_offload (vhost_user_intf_t * vui, vlib_buffer_t * b,
|
||||
virtio_net_hdr_t * hdr)
|
||||
{
|
||||
generic_header_offset_t gho = { 0 };
|
||||
vnet_generic_header_offset_parser (b, &gho);
|
||||
int is_ip4 = b->flags & VNET_BUFFER_F_IS_IP4;
|
||||
int is_ip6 = b->flags & VNET_BUFFER_F_IS_IP6;
|
||||
|
||||
ASSERT (!(is_ip4 && is_ip6));
|
||||
vnet_generic_header_offset_parser (b, &gho, 1 /* l2 */ , is_ip4, is_ip6);
|
||||
if (b->flags & VNET_BUFFER_F_OFFLOAD_IP_CKSUM)
|
||||
{
|
||||
ip4_header_t *ip4;
|
||||
@ -272,13 +276,13 @@ vhost_user_handle_tx_offload (vhost_user_intf_t * vui, vlib_buffer_t * b,
|
||||
{
|
||||
if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)
|
||||
{
|
||||
if ((b->flags & VNET_BUFFER_F_IS_IP4) &&
|
||||
if (is_ip4 &&
|
||||
(vui->features & (1ULL << FEAT_VIRTIO_NET_F_GUEST_TSO4)))
|
||||
{
|
||||
hdr->gso_size = vnet_buffer2 (b)->gso_size;
|
||||
hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
|
||||
}
|
||||
else if ((b->flags & VNET_BUFFER_F_IS_IP6) &&
|
||||
else if (is_ip6 &&
|
||||
(vui->features & (1ULL << FEAT_VIRTIO_NET_F_GUEST_TSO6)))
|
||||
{
|
||||
hdr->gso_size = vnet_buffer2 (b)->gso_size;
|
||||
|
@ -5,9 +5,11 @@ features:
|
||||
- Basic GSO support
|
||||
- GSO for VLAN tagged packets
|
||||
- GSO for VXLAN tunnel
|
||||
- GSO for IP-IP tunnel
|
||||
- GSO for IPSec tunnel
|
||||
- Provide inline function to get header offsets
|
||||
description: "Generic Segmentation Offload"
|
||||
missing:
|
||||
- Thorough Testing, IPIP, GRE, Geneve, IPSec
|
||||
- Thorough Testing, GRE, Geneve
|
||||
state: experimental
|
||||
properties: [API, CLI]
|
||||
|
@ -26,30 +26,6 @@ gso_main_t gso_main;
|
||||
int
|
||||
vnet_sw_interface_gso_enable_disable (u32 sw_if_index, u8 enable)
|
||||
{
|
||||
ethernet_interface_t *eif;
|
||||
vnet_sw_interface_t *si;
|
||||
ethernet_main_t *em;
|
||||
vnet_main_t *vnm;
|
||||
|
||||
vnm = vnet_get_main ();
|
||||
em = ðernet_main;
|
||||
si = vnet_get_sw_interface (vnm, sw_if_index);
|
||||
|
||||
/*
|
||||
* only ethernet HW interfaces are supported at this time
|
||||
*/
|
||||
if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
|
||||
{
|
||||
return (VNET_API_ERROR_INVALID_VALUE);
|
||||
}
|
||||
|
||||
eif = ethernet_get_interface (em, si->hw_if_index);
|
||||
|
||||
if (!eif)
|
||||
{
|
||||
return (VNET_API_ERROR_FEATURE_DISABLED);
|
||||
}
|
||||
|
||||
vnet_feature_enable_disable ("ip4-output", "gso-ip4", sw_if_index, enable,
|
||||
0, 0);
|
||||
vnet_feature_enable_disable ("ip6-output", "gso-ip6", sw_if_index, enable,
|
||||
|
@ -36,7 +36,8 @@
|
||||
_( 8, VXLAN_TUNNEL) \
|
||||
_( 9, GRE_TUNNEL) \
|
||||
_( 10, IPIP_TUNNEL) \
|
||||
_( 11, GENEVE_TUNNEL)
|
||||
_( 11, IPIP6_TUNNEL) \
|
||||
_( 12, GENEVE_TUNNEL)
|
||||
|
||||
typedef enum gho_flag_t_
|
||||
{
|
||||
@ -45,9 +46,10 @@ typedef enum gho_flag_t_
|
||||
#undef _
|
||||
} gho_flag_t;
|
||||
|
||||
#define GHO_F_TUNNEL (GHO_F_VXLAN_TUNNEL | \
|
||||
GHO_F_GENEVE_TUNNEL | \
|
||||
GHO_F_IPIP_TUNNEL | \
|
||||
#define GHO_F_TUNNEL (GHO_F_VXLAN_TUNNEL | \
|
||||
GHO_F_GENEVE_TUNNEL | \
|
||||
GHO_F_IPIP_TUNNEL | \
|
||||
GHO_F_IPIP6_TUNNEL | \
|
||||
GHO_F_GRE_TUNNEL)
|
||||
|
||||
#define GHO_F_OUTER_HDR (GHO_F_OUTER_IP4 | \
|
||||
@ -173,11 +175,77 @@ static_always_inline void
|
||||
vnet_ipip_inner_header_parser_inline (vlib_buffer_t * b0,
|
||||
generic_header_offset_t * gho)
|
||||
{
|
||||
/* not supported yet */
|
||||
if ((gho->gho_flags & GHO_F_IPIP_TUNNEL) == 0)
|
||||
if ((gho->gho_flags & (GHO_F_IPIP_TUNNEL | GHO_F_IPIP6_TUNNEL)) == 0)
|
||||
return;
|
||||
|
||||
ASSERT (0);
|
||||
u8 l4_proto = 0;
|
||||
u8 l4_hdr_sz = 0;
|
||||
|
||||
gho->outer_l2_hdr_offset = gho->l2_hdr_offset;
|
||||
gho->outer_l3_hdr_offset = gho->l3_hdr_offset;
|
||||
gho->outer_l4_hdr_offset = gho->l4_hdr_offset;
|
||||
gho->outer_l4_hdr_sz = gho->l4_hdr_sz;
|
||||
gho->outer_hdr_sz = gho->hdr_sz;
|
||||
|
||||
gho->l2_hdr_offset = 0;
|
||||
gho->l3_hdr_offset = 0;
|
||||
gho->l4_hdr_offset = 0;
|
||||
gho->l4_hdr_sz = 0;
|
||||
gho->hdr_sz = 0;
|
||||
|
||||
if (gho->gho_flags & GHO_F_IP4)
|
||||
{
|
||||
gho->gho_flags |= GHO_F_OUTER_IP4;
|
||||
}
|
||||
else if (gho->gho_flags & GHO_F_IP6)
|
||||
{
|
||||
gho->gho_flags |= GHO_F_OUTER_IP6;
|
||||
}
|
||||
|
||||
gho->gho_flags &= ~GHO_F_INNER_HDR;
|
||||
|
||||
vnet_get_inner_header (b0, gho);
|
||||
|
||||
gho->l2_hdr_offset = b0->current_data;
|
||||
gho->l3_hdr_offset = 0;
|
||||
|
||||
if (PREDICT_TRUE (gho->gho_flags & GHO_F_IPIP_TUNNEL))
|
||||
{
|
||||
ip4_header_t *ip4 = (ip4_header_t *) vlib_buffer_get_current (b0);
|
||||
gho->l4_hdr_offset = ip4_header_bytes (ip4);
|
||||
l4_proto = ip4->protocol;
|
||||
gho->gho_flags |= GHO_F_IP4;
|
||||
}
|
||||
else if (PREDICT_TRUE (gho->gho_flags & GHO_F_IPIP6_TUNNEL))
|
||||
{
|
||||
ip6_header_t *ip6 = (ip6_header_t *) vlib_buffer_get_current (b0);
|
||||
/* FIXME IPv6 EH traversal */
|
||||
gho->l4_hdr_offset = sizeof (ip6_header_t);
|
||||
l4_proto = ip6->protocol;
|
||||
gho->gho_flags |= GHO_F_IP6;
|
||||
}
|
||||
if (l4_proto == IP_PROTOCOL_TCP)
|
||||
{
|
||||
tcp_header_t *tcp = (tcp_header_t *) (vlib_buffer_get_current (b0) +
|
||||
gho->l4_hdr_offset);
|
||||
l4_hdr_sz = tcp_header_bytes (tcp);
|
||||
|
||||
gho->gho_flags |= GHO_F_TCP;
|
||||
|
||||
}
|
||||
else if (l4_proto == IP_PROTOCOL_UDP)
|
||||
{
|
||||
udp_header_t *udp = (udp_header_t *) (vlib_buffer_get_current (b0) +
|
||||
gho->l4_hdr_offset);
|
||||
l4_hdr_sz = sizeof (*udp);
|
||||
|
||||
gho->gho_flags |= GHO_F_UDP;
|
||||
}
|
||||
|
||||
gho->l4_hdr_sz = l4_hdr_sz;
|
||||
gho->hdr_sz += gho->l4_hdr_offset + l4_hdr_sz;
|
||||
|
||||
vnet_get_outer_header (b0, gho);
|
||||
}
|
||||
|
||||
static_always_inline void
|
||||
@ -290,7 +358,7 @@ vnet_generic_inner_header_parser_inline (vlib_buffer_t * b0,
|
||||
|
||||
if (gho->gho_flags & GHO_F_VXLAN_TUNNEL)
|
||||
vnet_vxlan_inner_header_parser_inline (b0, gho);
|
||||
else if (gho->gho_flags & GHO_F_IPIP_TUNNEL)
|
||||
else if (gho->gho_flags & (GHO_F_IPIP_TUNNEL | GHO_F_IPIP6_TUNNEL))
|
||||
vnet_ipip_inner_header_parser_inline (b0, gho);
|
||||
else if (gho->gho_flags & GHO_F_GRE_TUNNEL)
|
||||
vnet_gre_inner_header_parser_inline (b0, gho);
|
||||
@ -300,33 +368,44 @@ vnet_generic_inner_header_parser_inline (vlib_buffer_t * b0,
|
||||
|
||||
static_always_inline void
|
||||
vnet_generic_outer_header_parser_inline (vlib_buffer_t * b0,
|
||||
generic_header_offset_t * gho)
|
||||
generic_header_offset_t * gho,
|
||||
int is_l2, int is_ip4, int is_ip6)
|
||||
{
|
||||
u8 l4_proto = 0;
|
||||
u8 l4_hdr_sz = 0;
|
||||
u16 ethertype = 0;
|
||||
u16 l2hdr_sz = 0;
|
||||
|
||||
ethernet_header_t *eh = (ethernet_header_t *) vlib_buffer_get_current (b0);
|
||||
u16 ethertype = clib_net_to_host_u16 (eh->type);
|
||||
u16 l2hdr_sz = sizeof (ethernet_header_t);
|
||||
ASSERT (is_ip4 ^ is_ip6);
|
||||
|
||||
if (ethernet_frame_is_tagged (ethertype))
|
||||
if (is_l2)
|
||||
{
|
||||
ethernet_vlan_header_t *vlan = (ethernet_vlan_header_t *) (eh + 1);
|
||||
ethernet_header_t *eh =
|
||||
(ethernet_header_t *) vlib_buffer_get_current (b0);
|
||||
ethertype = clib_net_to_host_u16 (eh->type);
|
||||
l2hdr_sz = sizeof (ethernet_header_t);
|
||||
|
||||
ethertype = clib_net_to_host_u16 (vlan->type);
|
||||
l2hdr_sz += sizeof (*vlan);
|
||||
if (ethertype == ETHERNET_TYPE_VLAN)
|
||||
if (ethernet_frame_is_tagged (ethertype))
|
||||
{
|
||||
vlan++;
|
||||
ethernet_vlan_header_t *vlan = (ethernet_vlan_header_t *) (eh + 1);
|
||||
|
||||
ethertype = clib_net_to_host_u16 (vlan->type);
|
||||
l2hdr_sz += sizeof (*vlan);
|
||||
if (ethertype == ETHERNET_TYPE_VLAN)
|
||||
{
|
||||
vlan++;
|
||||
ethertype = clib_net_to_host_u16 (vlan->type);
|
||||
l2hdr_sz += sizeof (*vlan);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
l2hdr_sz = vnet_buffer (b0)->ip.save_rewrite_length;
|
||||
|
||||
gho->l2_hdr_offset = b0->current_data;
|
||||
gho->l3_hdr_offset = l2hdr_sz;
|
||||
|
||||
if (PREDICT_TRUE (ethertype == ETHERNET_TYPE_IP4))
|
||||
if (PREDICT_TRUE (is_ip4))
|
||||
{
|
||||
ip4_header_t *ip4 =
|
||||
(ip4_header_t *) (vlib_buffer_get_current (b0) + l2hdr_sz);
|
||||
@ -334,7 +413,7 @@ vnet_generic_outer_header_parser_inline (vlib_buffer_t * b0,
|
||||
l4_proto = ip4->protocol;
|
||||
gho->gho_flags |= GHO_F_IP4;
|
||||
}
|
||||
else if (PREDICT_TRUE (ethertype == ETHERNET_TYPE_IP6))
|
||||
else if (PREDICT_TRUE (is_ip6))
|
||||
{
|
||||
ip6_header_t *ip6 =
|
||||
(ip6_header_t *) (vlib_buffer_get_current (b0) + l2hdr_sz);
|
||||
@ -369,12 +448,16 @@ vnet_generic_outer_header_parser_inline (vlib_buffer_t * b0,
|
||||
gho->gho_flags |= GHO_F_GENEVE_TUNNEL;
|
||||
}
|
||||
}
|
||||
else if ((l4_proto == IP_PROTOCOL_IP_IN_IP)
|
||||
|| (l4_proto == IP_PROTOCOL_IPV6))
|
||||
else if (l4_proto == IP_PROTOCOL_IP_IN_IP)
|
||||
{
|
||||
l4_hdr_sz = 0;
|
||||
gho->gho_flags |= GHO_F_IPIP_TUNNEL;
|
||||
}
|
||||
else if (l4_proto == IP_PROTOCOL_IPV6)
|
||||
{
|
||||
l4_hdr_sz = 0;
|
||||
gho->gho_flags |= GHO_F_IPIP6_TUNNEL;
|
||||
}
|
||||
else if (l4_proto == IP_PROTOCOL_GRE)
|
||||
{
|
||||
l4_hdr_sz = 0;
|
||||
@ -387,9 +470,10 @@ vnet_generic_outer_header_parser_inline (vlib_buffer_t * b0,
|
||||
|
||||
static_always_inline void
|
||||
vnet_generic_header_offset_parser (vlib_buffer_t * b0,
|
||||
generic_header_offset_t * gho)
|
||||
generic_header_offset_t * gho, int is_l2,
|
||||
int is_ip4, int is_ip6)
|
||||
{
|
||||
vnet_generic_outer_header_parser_inline (b0, gho);
|
||||
vnet_generic_outer_header_parser_inline (b0, gho, is_l2, is_ip4, is_ip6);
|
||||
|
||||
if (gho->gho_flags & GHO_F_TUNNEL)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -92,7 +92,8 @@ vnet_calc_checksums_inline (vlib_main_t * vm, vlib_buffer_t * b,
|
||||
if (with_gso)
|
||||
{
|
||||
generic_header_offset_t gho = { 0 };
|
||||
vnet_generic_header_offset_parser (b, &gho);
|
||||
vnet_generic_header_offset_parser (b, &gho, 1 /* l2 */ , is_ip4,
|
||||
is_ip6);
|
||||
|
||||
ASSERT (gho.gho_flags ^ (GHO_F_IP4 | GHO_F_IP6));
|
||||
|
||||
|
205
test/test_gso.py
205
test/test_gso.py
@ -22,6 +22,7 @@ from vpp_object import VppObject
|
||||
from vpp_interface import VppInterface
|
||||
from vpp_ip import DpoProto
|
||||
from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto
|
||||
from vpp_ipip_tun_interface import VppIpIpTunInterface
|
||||
from vpp_vxlan_tunnel import VppVxlanTunnel
|
||||
from socket import AF_INET, AF_INET6, inet_pton
|
||||
from util import reassemble4
|
||||
@ -67,12 +68,15 @@ class TestGSO(VppTestCase):
|
||||
self.vxlan = VppVxlanTunnel(self, src=self.pg0.local_ip4,
|
||||
dst=self.pg0.remote_ip4,
|
||||
vni=self.single_tunnel_bd)
|
||||
self.vxlan.add_vpp_config()
|
||||
|
||||
self.vxlan2 = VppVxlanTunnel(self, src=self.pg0.local_ip6,
|
||||
dst=self.pg0.remote_ip6,
|
||||
vni=self.single_tunnel_bd)
|
||||
self.vxlan2.add_vpp_config()
|
||||
|
||||
self.ipip4 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip4,
|
||||
self.pg0.remote_ip4)
|
||||
self.ipip6 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip6,
|
||||
self.pg0.remote_ip6)
|
||||
|
||||
def tearDown(self):
|
||||
super(TestGSO, self).tearDown()
|
||||
@ -286,6 +290,11 @@ class TestGSO(VppTestCase):
|
||||
# create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2
|
||||
# into BD.
|
||||
#
|
||||
|
||||
#
|
||||
# enable ipv4/vxlan
|
||||
#
|
||||
self.vxlan.add_vpp_config()
|
||||
self.vapi.sw_interface_set_l2_bridge(
|
||||
rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd)
|
||||
self.vapi.sw_interface_set_l2_bridge(
|
||||
@ -300,7 +309,6 @@ class TestGSO(VppTestCase):
|
||||
TCP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 65200))
|
||||
|
||||
self.pg0.enable_capture()
|
||||
rxs = self.send_and_expect(self.pg2, [p45], self.pg0, 45)
|
||||
size = 0
|
||||
for rx in rxs:
|
||||
@ -325,7 +333,6 @@ class TestGSO(VppTestCase):
|
||||
TCP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 65200))
|
||||
|
||||
self.pg0.enable_capture()
|
||||
rxs = self.send_and_expect(self.pg2, [p65], self.pg0, 45)
|
||||
size = 0
|
||||
for rx in rxs:
|
||||
@ -350,6 +357,7 @@ class TestGSO(VppTestCase):
|
||||
#
|
||||
# enable ipv6/vxlan
|
||||
#
|
||||
self.vxlan2.add_vpp_config()
|
||||
self.vapi.sw_interface_set_l2_bridge(
|
||||
rx_sw_if_index=self.vxlan2.sw_if_index,
|
||||
bd_id=self.single_tunnel_bd)
|
||||
@ -362,7 +370,6 @@ class TestGSO(VppTestCase):
|
||||
TCP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 65200))
|
||||
|
||||
self.pg0.enable_capture()
|
||||
rxs = self.send_and_expect(self.pg2, [p46], self.pg0, 45)
|
||||
size = 0
|
||||
for rx in rxs:
|
||||
@ -387,7 +394,6 @@ class TestGSO(VppTestCase):
|
||||
TCP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 65200))
|
||||
|
||||
self.pg0.enable_capture()
|
||||
rxs = self.send_and_expect(self.pg2, [p66], self.pg0, 45)
|
||||
size = 0
|
||||
for rx in rxs:
|
||||
@ -404,5 +410,192 @@ class TestGSO(VppTestCase):
|
||||
size += inner[IPv6].plen - 20
|
||||
self.assertEqual(size, 65200)
|
||||
|
||||
#
|
||||
# disable ipv4/vxlan
|
||||
#
|
||||
self.vxlan2.remove_vpp_config()
|
||||
|
||||
def test_gso_ipip(self):
|
||||
""" GSO IPIP test """
|
||||
self.logger.info(self.vapi.cli("sh int addr"))
|
||||
#
|
||||
# Send jumbo frame with gso enabled only on input interface and
|
||||
# create IPIP tunnel on VPP pg0.
|
||||
#
|
||||
self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index)
|
||||
|
||||
#
|
||||
# enable ipip4
|
||||
#
|
||||
self.ipip4.add_vpp_config()
|
||||
|
||||
# Set interface up and enable IP on it
|
||||
self.ipip4.admin_up()
|
||||
self.ipip4.set_unnumbered(self.pg0.sw_if_index)
|
||||
|
||||
# Add IPv4 routes via tunnel interface
|
||||
self.ip4_via_ip4_tunnel = VppIpRoute(
|
||||
self, "172.16.10.0", 24,
|
||||
[VppRoutePath("0.0.0.0",
|
||||
self.ipip4.sw_if_index,
|
||||
proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
|
||||
self.ip4_via_ip4_tunnel.add_vpp_config()
|
||||
|
||||
#
|
||||
# IPv4/IPv4 - IPIP
|
||||
#
|
||||
p47 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
|
||||
IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
|
||||
TCP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 65200))
|
||||
|
||||
rxs = self.send_and_expect(self.pg2, [p47], self.pg0, 45)
|
||||
size = 0
|
||||
for rx in rxs:
|
||||
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
|
||||
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
|
||||
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
|
||||
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
|
||||
self.assertEqual(rx[IP].proto, 4) # ipencap
|
||||
inner = rx[IP].payload
|
||||
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
|
||||
self.assertEqual(inner[IP].dst, "172.16.10.3")
|
||||
size += inner[IP].len - 20 - 20
|
||||
self.assertEqual(size, 65200)
|
||||
|
||||
self.ip6_via_ip4_tunnel = VppIpRoute(
|
||||
self, "fd01:10::", 64,
|
||||
[VppRoutePath("::",
|
||||
self.ipip4.sw_if_index,
|
||||
proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
|
||||
self.ip6_via_ip4_tunnel.add_vpp_config()
|
||||
#
|
||||
# IPv4/IPv6 - IPIP
|
||||
#
|
||||
p67 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
|
||||
IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
|
||||
TCP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 65200))
|
||||
|
||||
rxs = self.send_and_expect(self.pg2, [p67], self.pg0, 45)
|
||||
size = 0
|
||||
for rx in rxs:
|
||||
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
|
||||
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
|
||||
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
|
||||
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
|
||||
self.assertEqual(rx[IP].proto, 41) # ipv6
|
||||
inner = rx[IP].payload
|
||||
self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
|
||||
self.assertEqual(inner[IPv6].dst, "fd01:10::3")
|
||||
size += inner[IPv6].plen - 20
|
||||
self.assertEqual(size, 65200)
|
||||
|
||||
#
|
||||
# Send jumbo frame with gso enabled only on input interface and
|
||||
# create IPIP tunnel on VPP pg0. Enable gso feature node on ipip
|
||||
# tunnel - IPSec use case
|
||||
#
|
||||
self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, 0)
|
||||
self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index)
|
||||
|
||||
rxs = self.send_and_expect(self.pg2, [p47], self.pg0, 45)
|
||||
size = 0
|
||||
for rx in rxs:
|
||||
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
|
||||
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
|
||||
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
|
||||
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
|
||||
self.assertEqual(rx[IP].proto, 4) # ipencap
|
||||
inner = rx[IP].payload
|
||||
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
|
||||
self.assertEqual(inner[IP].dst, "172.16.10.3")
|
||||
size += inner[IP].len - 20 - 20
|
||||
self.assertEqual(size, 65200)
|
||||
|
||||
#
|
||||
# disable ipip4
|
||||
#
|
||||
self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index, 0)
|
||||
self.ip4_via_ip4_tunnel.remove_vpp_config()
|
||||
self.ip6_via_ip4_tunnel.remove_vpp_config()
|
||||
self.ipip4.remove_vpp_config()
|
||||
|
||||
#
|
||||
# enable ipip6
|
||||
#
|
||||
self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index)
|
||||
self.ipip6.add_vpp_config()
|
||||
|
||||
# Set interface up and enable IP on it
|
||||
self.ipip6.admin_up()
|
||||
self.ipip6.set_unnumbered(self.pg0.sw_if_index)
|
||||
|
||||
# Add IPv4 routes via tunnel interface
|
||||
self.ip4_via_ip6_tunnel = VppIpRoute(
|
||||
self, "172.16.10.0", 24,
|
||||
[VppRoutePath("0.0.0.0",
|
||||
self.ipip6.sw_if_index,
|
||||
proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
|
||||
self.ip4_via_ip6_tunnel.add_vpp_config()
|
||||
|
||||
#
|
||||
# IPv6/IPv4 - IPIP
|
||||
#
|
||||
p48 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
|
||||
IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
|
||||
TCP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 65200))
|
||||
|
||||
rxs = self.send_and_expect(self.pg2, [p48], self.pg0, 45)
|
||||
size = 0
|
||||
for rx in rxs:
|
||||
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
|
||||
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
|
||||
self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
|
||||
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
|
||||
self.assertEqual(ipv6nh[rx[IPv6].nh], "IP")
|
||||
inner = rx[IPv6].payload
|
||||
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
|
||||
self.assertEqual(inner[IP].dst, "172.16.10.3")
|
||||
size += inner[IP].len - 20 - 20
|
||||
self.assertEqual(size, 65200)
|
||||
|
||||
self.ip6_via_ip6_tunnel = VppIpRoute(
|
||||
self, "fd01:10::", 64,
|
||||
[VppRoutePath("::",
|
||||
self.ipip6.sw_if_index,
|
||||
proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
|
||||
self.ip6_via_ip6_tunnel.add_vpp_config()
|
||||
|
||||
#
|
||||
# IPv6/IPv6 - IPIP
|
||||
#
|
||||
p68 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
|
||||
IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
|
||||
TCP(sport=1234, dport=1234) /
|
||||
Raw(b'\xa5' * 65200))
|
||||
|
||||
rxs = self.send_and_expect(self.pg2, [p68], self.pg0, 45)
|
||||
size = 0
|
||||
for rx in rxs:
|
||||
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
|
||||
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
|
||||
self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
|
||||
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
|
||||
self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6")
|
||||
inner = rx[IPv6].payload
|
||||
self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
|
||||
self.assertEqual(inner[IPv6].dst, "fd01:10::3")
|
||||
size += inner[IPv6].plen - 20
|
||||
self.assertEqual(size, 65200)
|
||||
|
||||
#
|
||||
# disable ipip6
|
||||
#
|
||||
self.ip4_via_ip6_tunnel.remove_vpp_config()
|
||||
self.ip6_via_ip6_tunnel.remove_vpp_config()
|
||||
self.ipip6.remove_vpp_config()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=VppTestRunner)
|
||||
|
Reference in New Issue
Block a user