summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohsin Kazmi <sykazmi@cisco.com>2021-06-17 17:29:27 +0000
committerDamjan Marion <dmarion@me.com>2021-09-16 10:43:56 +0000
commit4fd9f10c4535724fd52b05d703fb56a33edc1138 (patch)
treec116ed9e18d6143701a449af2aab963a10a54dce
parent64dd1720e5fd6f0cd9b029a5bc312e7264ac7d24 (diff)
vxlan: improve to use the hardware offload
Type: improvement Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com> Change-Id: Ic0fa4f83048a280a7d1b04198c0f903798562d2d
-rw-r--r--src/vnet/gso/node.c3
-rw-r--r--src/vnet/ip/ip4_forward.c3
-rw-r--r--src/vnet/vxlan/encap.c127
3 files changed, 49 insertions, 84 deletions
diff --git a/src/vnet/gso/node.c b/src/vnet/gso/node.c
index 5e793a5cffd..037f800afdf 100644
--- a/src/vnet/gso/node.c
+++ b/src/vnet/gso/node.c
@@ -799,7 +799,8 @@ vnet_gso_inline (vlib_main_t * vm,
hi = vnet_get_sup_hw_interface (vnm,
vnet_buffer (b)->sw_if_index[VLIB_TX]);
- if (hi->caps & VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO)
+ if (hi->caps & (VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO |
+ VNET_HW_INTERFACE_CAP_SUPPORTS_VXLAN_TNL_GSO))
return vnet_gso_node_inline (vm, node, frame, vnm, hi,
is_l2, is_ip4, is_ip6,
/* do_segmentation */ 0);
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index 35aff63e736..5cd5e418fd6 100644
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -2044,7 +2044,8 @@ ip4_ttl_and_checksum_check (vlib_buffer_t * b, ip4_header_t * ip, u16 * next,
/* Verify checksum. */
ASSERT (ip4_header_checksum_is_valid (ip) ||
- (vnet_buffer (b)->oflags & VNET_BUFFER_OFFLOAD_F_IP_CKSUM));
+ (vnet_buffer (b)->oflags & VNET_BUFFER_OFFLOAD_F_IP_CKSUM) ||
+ (vnet_buffer (b)->oflags & VNET_BUFFER_OFFLOAD_F_OUTER_IP_CKSUM));
}
always_inline uword
diff --git a/src/vnet/vxlan/encap.c b/src/vnet/vxlan/encap.c
index 476e0f2b3b7..0961a27942d 100644
--- a/src/vnet/vxlan/encap.c
+++ b/src/vnet/vxlan/encap.c
@@ -68,9 +68,8 @@ format_vxlan_encap_trace (u8 * s, va_list * args)
#endif
always_inline uword
-vxlan_encap_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * from_frame, u8 is_ip4, u8 csum_offload)
+vxlan_encap_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *from_frame, u8 is_ip4)
{
u32 n_left_from, next_index, *from, *to_next;
vxlan_main_t *vxm = &vxlan_main;
@@ -98,18 +97,11 @@ vxlan_encap_inline (vlib_main_t * vm,
u8 const underlay_hdr_len = is_ip4 ?
sizeof (ip4_vxlan_header_t) : sizeof (ip6_vxlan_header_t);
u16 const l3_len = is_ip4 ? sizeof (ip4_header_t) : sizeof (ip6_header_t);
- u32 const csum_flags =
- is_ip4 ? VNET_BUFFER_F_IS_IP4 | VNET_BUFFER_F_L3_HDR_OFFSET_VALID |
- VNET_BUFFER_F_L4_HDR_OFFSET_VALID :
- VNET_BUFFER_F_IS_IP6 | VNET_BUFFER_F_L3_HDR_OFFSET_VALID |
- VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
u32 const outer_packet_csum_offload_flags =
- is_ip4 ? VNET_BUFFER_OFFLOAD_F_IP_CKSUM | VNET_BUFFER_OFFLOAD_F_UDP_CKSUM :
- VNET_BUFFER_OFFLOAD_F_UDP_CKSUM;
- u32 const inner_packet_removed_flags =
- VNET_BUFFER_F_IS_IP4 | VNET_BUFFER_F_IS_IP6 |
- VNET_BUFFER_F_L2_HDR_OFFSET_VALID | VNET_BUFFER_F_L3_HDR_OFFSET_VALID |
- VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
+ is_ip4 ? (VNET_BUFFER_OFFLOAD_F_OUTER_IP_CKSUM |
+ VNET_BUFFER_OFFLOAD_F_TNL_VXLAN) :
+ (VNET_BUFFER_OFFLOAD_F_OUTER_UDP_CKSUM |
+ VNET_BUFFER_OFFLOAD_F_TNL_VXLAN);
vlib_get_buffers (vm, from, bufs, n_left_from);
@@ -143,30 +135,6 @@ vxlan_encap_inline (vlib_main_t * vm,
vlib_buffer_t *b1 = b[1];
b += 2;
- u32 or_flags = b0->flags | b1->flags;
- if (csum_offload && (or_flags & VNET_BUFFER_F_OFFLOAD))
- {
- /* Only calculate the non-GSO packet csum offload */
- if ((b0->flags & VNET_BUFFER_F_GSO) == 0)
- {
- vnet_calc_checksums_inline (vm, b0,
- b0->flags &
- VNET_BUFFER_F_IS_IP4,
- b0->flags &
- VNET_BUFFER_F_IS_IP6);
- b0->flags &= ~inner_packet_removed_flags;
- }
- if ((b1->flags & VNET_BUFFER_F_GSO) == 0)
- {
- vnet_calc_checksums_inline (vm, b1,
- b1->flags &
- VNET_BUFFER_F_IS_IP4,
- b1->flags &
- VNET_BUFFER_F_IS_IP6);
- b1->flags &= ~inner_packet_removed_flags;
- }
- }
-
u32 flow_hash0 = vnet_l2_compute_flow_hash (b0);
u32 flow_hash1 = vnet_l2_compute_flow_hash (b1);
@@ -279,38 +247,55 @@ vxlan_encap_inline (vlib_main_t * vm,
udp1->length = payload_l1;
udp1->src_port = flow_hash1;
- if (csum_offload)
+ if (b0->flags & VNET_BUFFER_F_OFFLOAD)
{
- b0->flags |= csum_flags;
- vnet_buffer (b0)->l3_hdr_offset = l3_0 - b0->data;
- vnet_buffer (b0)->l4_hdr_offset = (u8 *) udp0 - b0->data;
+ vnet_buffer2 (b0)->outer_l3_hdr_offset = l3_0 - b0->data;
+ vnet_buffer2 (b0)->outer_l4_hdr_offset = (u8 *) udp0 - b0->data;
vnet_buffer_offload_flags_set (b0,
outer_packet_csum_offload_flags);
- b1->flags |= csum_flags;
- vnet_buffer (b1)->l3_hdr_offset = l3_1 - b1->data;
- vnet_buffer (b1)->l4_hdr_offset = (u8 *) udp1 - b1->data;
- vnet_buffer_offload_flags_set (b1,
- outer_packet_csum_offload_flags);
}
- /* IPv4 UDP checksum only if checksum offload is used */
+ /* IPv4 checksum only */
else if (is_ip4)
{
ip_csum_t sum0 = ip4_0->checksum;
sum0 = ip_csum_update (sum0, 0, ip4_0->length, ip4_header_t,
- length /* changed member */ );
+ length /* changed member */);
if (PREDICT_FALSE (ip4_0_tos))
{
sum0 = ip_csum_update (sum0, 0, ip4_0_tos, ip4_header_t,
- tos /* changed member */ );
+ tos /* changed member */);
}
ip4_0->checksum = ip_csum_fold (sum0);
+ }
+ /* IPv6 UDP checksum is mandatory */
+ else
+ {
+ int bogus = 0;
+
+ udp0->checksum =
+ ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip6_0, &bogus);
+ ASSERT (bogus == 0);
+ if (udp0->checksum == 0)
+ udp0->checksum = 0xffff;
+ }
+
+ if (b1->flags & VNET_BUFFER_F_OFFLOAD)
+ {
+ vnet_buffer2 (b1)->outer_l3_hdr_offset = l3_1 - b1->data;
+ vnet_buffer2 (b1)->outer_l4_hdr_offset = (u8 *) udp1 - b1->data;
+ vnet_buffer_offload_flags_set (b1,
+ outer_packet_csum_offload_flags);
+ }
+ /* IPv4 checksum only */
+ else if (is_ip4)
+ {
ip_csum_t sum1 = ip4_1->checksum;
sum1 = ip_csum_update (sum1, 0, ip4_1->length, ip4_header_t,
- length /* changed member */ );
+ length /* changed member */);
if (PREDICT_FALSE (ip4_1_tos))
{
sum1 = ip_csum_update (sum1, 0, ip4_1_tos, ip4_header_t,
- tos /* changed member */ );
+ tos /* changed member */);
}
ip4_1->checksum = ip_csum_fold (sum1);
}
@@ -319,11 +304,6 @@ vxlan_encap_inline (vlib_main_t * vm,
{
int bogus = 0;
- udp0->checksum = ip6_tcp_udp_icmp_compute_checksum
- (vm, b0, ip6_0, &bogus);
- ASSERT (bogus == 0);
- if (udp0->checksum == 0)
- udp0->checksum = 0xffff;
udp1->checksum = ip6_tcp_udp_icmp_compute_checksum
(vm, b1, ip6_1, &bogus);
ASSERT (bogus == 0);
@@ -381,20 +361,6 @@ vxlan_encap_inline (vlib_main_t * vm,
vlib_buffer_t *b0 = b[0];
b += 1;
- if (csum_offload && (b0->flags & VNET_BUFFER_F_OFFLOAD))
- {
- /* Only calculate the non-GSO packet csum offload */
- if ((b0->flags & VNET_BUFFER_F_GSO) == 0)
- {
- vnet_calc_checksums_inline (vm, b0,
- b0->flags &
- VNET_BUFFER_F_IS_IP4,
- b0->flags &
- VNET_BUFFER_F_IS_IP6);
- b0->flags &= ~inner_packet_removed_flags;
- }
- }
-
u32 flow_hash0 = vnet_l2_compute_flow_hash (b0);
/* Get next node index and adj index from tunnel next_dpo */
@@ -458,24 +424,23 @@ vxlan_encap_inline (vlib_main_t * vm,
udp0->length = payload_l0;
udp0->src_port = flow_hash0;
- if (csum_offload)
+ if (b0->flags & VNET_BUFFER_F_OFFLOAD)
{
- b0->flags |= csum_flags;
- vnet_buffer (b0)->l3_hdr_offset = l3_0 - b0->data;
- vnet_buffer (b0)->l4_hdr_offset = (u8 *) udp0 - b0->data;
+ vnet_buffer2 (b0)->outer_l3_hdr_offset = l3_0 - b0->data;
+ vnet_buffer2 (b0)->outer_l4_hdr_offset = (u8 *) udp0 - b0->data;
vnet_buffer_offload_flags_set (b0,
outer_packet_csum_offload_flags);
}
- /* IPv4 UDP checksum only if checksum offload is used */
+ /* IPv4 checksum only */
else if (is_ip4)
{
ip_csum_t sum0 = ip4_0->checksum;
sum0 = ip_csum_update (sum0, 0, ip4_0->length, ip4_header_t,
- length /* changed member */ );
+ length /* changed member */);
if (PREDICT_FALSE (ip4_0_tos))
{
sum0 = ip_csum_update (sum0, 0, ip4_0_tos, ip4_header_t,
- tos /* changed member */ );
+ tos /* changed member */);
}
ip4_0->checksum = ip_csum_fold (sum0);
}
@@ -527,8 +492,7 @@ VLIB_NODE_FN (vxlan4_encap_node) (vlib_main_t * vm,
{
/* Disable chksum offload as setup overhead in tx node is not worthwhile
for ip4 header checksum only, unless udp checksum is also required */
- return vxlan_encap_inline (vm, node, from_frame, /* is_ip4 */ 1,
- /* csum_offload */ 0);
+ return vxlan_encap_inline (vm, node, from_frame, /* is_ip4 */ 1);
}
VLIB_NODE_FN (vxlan6_encap_node) (vlib_main_t * vm,
@@ -536,8 +500,7 @@ VLIB_NODE_FN (vxlan6_encap_node) (vlib_main_t * vm,
vlib_frame_t * from_frame)
{
/* Enable checksum offload for ip6 as udp checksum is mandatory, */
- return vxlan_encap_inline (vm, node, from_frame, /* is_ip4 */ 0,
- /* csum_offload */ 1);
+ return vxlan_encap_inline (vm, node, from_frame, /* is_ip4 */ 0);
}
/* *INDENT-OFF* */