From ffc6bdcd38b8209050671d3d86f943c37887a7b7 Mon Sep 17 00:00:00 2001 From: Nathan Skrzypczak Date: Mon, 1 Feb 2021 17:13:59 +0100 Subject: devices: af-packet gso mtu Type: fix Set the GSO flag when buffer length exceeds the linux mtu. Don't listen for mtu changes on linux side for now. This also fixes a TX issue, as we only search for valid frames on tx to the extent of n_left, we might stay stuck. Change-Id: Idf0bdd88990254a614962c2f7bc3e0292ccfd61a Signed-off-by: Nathan Skrzypczak --- src/vnet/devices/af_packet/node.c | 50 ++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 16 deletions(-) (limited to 'src/vnet/devices/af_packet/node.c') diff --git a/src/vnet/devices/af_packet/node.c b/src/vnet/devices/af_packet/node.c index d444b3b6eea..f4db6399a57 100644 --- a/src/vnet/devices/af_packet/node.c +++ b/src/vnet/devices/af_packet/node.c @@ -109,7 +109,15 @@ buffer_add_to_chain (vlib_main_t * vm, u32 bi, u32 first_bi, u32 prev_bi) } static_always_inline void -mark_tcp_udp_cksum_calc (vlib_buffer_t * b) +fill_gso_buffer_flags (vlib_buffer_t *b, u32 gso_size, u8 l4_hdr_sz) +{ + b->flags |= VNET_BUFFER_F_GSO; + vnet_buffer2 (b)->gso_size = gso_size; + vnet_buffer2 (b)->gso_l4_hdr_sz = l4_hdr_sz; +} + +static_always_inline void +mark_tcp_udp_cksum_calc (vlib_buffer_t *b, u8 *l4_hdr_sz) { ethernet_header_t *eth = vlib_buffer_get_current (b); if (clib_net_to_host_u16 (eth->type) == ETHERNET_TYPE_IP4) @@ -120,18 +128,20 @@ mark_tcp_udp_cksum_calc (vlib_buffer_t * b) if (ip4->protocol == IP_PROTOCOL_TCP) { b->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM; - ((tcp_header_t - *) (vlib_buffer_get_current (b) + - sizeof (ethernet_header_t) + - ip4_header_bytes (ip4)))->checksum = 0; + tcp_header_t *tcp = (tcp_header_t *) (vlib_buffer_get_current (b) + + sizeof (ethernet_header_t) + + ip4_header_bytes (ip4)); + tcp->checksum = 0; + *l4_hdr_sz = tcp_header_bytes (tcp); } else if (ip4->protocol == IP_PROTOCOL_UDP) { b->flags |= VNET_BUFFER_F_OFFLOAD_UDP_CKSUM; - ((udp_header_t - *) (vlib_buffer_get_current (b) + - sizeof (ethernet_header_t) + - ip4_header_bytes (ip4)))->checksum = 0; + udp_header_t *udp = (udp_header_t *) (vlib_buffer_get_current (b) + + sizeof (ethernet_header_t) + + ip4_header_bytes (ip4)); + udp->checksum = 0; + *l4_hdr_sz = sizeof (*udp); } vnet_buffer (b)->l3_hdr_offset = sizeof (ethernet_header_t); vnet_buffer (b)->l4_hdr_offset = @@ -156,16 +166,20 @@ mark_tcp_udp_cksum_calc (vlib_buffer_t * b) if (ip6->protocol == IP_PROTOCOL_TCP) { b->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM; - ((tcp_header_t - *) (vlib_buffer_get_current (b) + - sizeof (ethernet_header_t) + ip6_hdr_len))->checksum = 0; + tcp_header_t *tcp = + (tcp_header_t *) (vlib_buffer_get_current (b) + + sizeof (ethernet_header_t) + ip6_hdr_len); + tcp->checksum = 0; + *l4_hdr_sz = tcp_header_bytes (tcp); } else if (ip6->protocol == IP_PROTOCOL_UDP) { b->flags |= VNET_BUFFER_F_OFFLOAD_UDP_CKSUM; - ((udp_header_t - *) (vlib_buffer_get_current (b) + - sizeof (ethernet_header_t) + ip6_hdr_len))->checksum = 0; + udp_header_t *udp = + (udp_header_t *) (vlib_buffer_get_current (b) + + sizeof (ethernet_header_t) + ip6_hdr_len); + udp->checksum = 0; + *l4_hdr_sz = sizeof (*udp); } vnet_buffer (b)->l3_hdr_offset = sizeof (ethernet_header_t); vnet_buffer (b)->l4_hdr_offset = @@ -221,6 +235,7 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, u32 data_len = tph->tp_snaplen; u32 offset = 0; u32 bi0 = 0, first_bi0 = 0, prev_bi0; + u8 l4_hdr_sz = 0; while (data_len) { @@ -275,7 +290,10 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, first_bi0 = bi0; first_b0 = vlib_get_buffer (vm, first_bi0); if (tph->tp_status & TP_STATUS_CSUMNOTREADY) - mark_tcp_udp_cksum_calc (first_b0); + mark_tcp_udp_cksum_calc (first_b0, &l4_hdr_sz); + if (tph->tp_snaplen > apif->host_mtu) + fill_gso_buffer_flags (first_b0, apif->host_mtu, + l4_hdr_sz); } else buffer_add_to_chain (vm, bi0, first_bi0, prev_bi0); -- cgit 1.2.3-korg