vxlan: improve to use the hardware offload
Type: improvement
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
Change-Id: Ic0fa4f83048a280a7d1b04198c0f903798562d2d
diff --git a/src/vnet/vxlan/encap.c b/src/vnet/vxlan/encap.c
index 476e0f2..0961a27 100644
--- a/src/vnet/vxlan/encap.c
+++ b/src/vnet/vxlan/encap.c
@@ -68,9 +68,8 @@
#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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
{
/* 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_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* */