diff options
-rw-r--r-- | src/vnet/gso/hdr_offset_parser.h | 2 | ||||
-rw-r--r-- | src/vnet/interface_output.c | 10 | ||||
-rw-r--r-- | src/vnet/interface_output.h | 54 | ||||
-rw-r--r-- | src/vnet/ip/ip4_forward.c | 12 | ||||
-rw-r--r-- | src/vnet/ip/ip6_forward.c | 9 | ||||
-rw-r--r-- | src/vnet/pg/input.c | 29 | ||||
-rw-r--r-- | test/test_gso.py | 4 | ||||
-rw-r--r-- | test/test_vxlan.py | 3 | ||||
-rw-r--r-- | test/test_vxlan6.py | 35 | ||||
-rw-r--r-- | test/test_vxlan_gbp.py | 3 | ||||
-rw-r--r-- | test/test_vxlan_gpe.py | 2 |
11 files changed, 85 insertions, 78 deletions
diff --git a/src/vnet/gso/hdr_offset_parser.h b/src/vnet/gso/hdr_offset_parser.h index b194333e780..8fa5cad56d1 100644 --- a/src/vnet/gso/hdr_offset_parser.h +++ b/src/vnet/gso/hdr_offset_parser.h @@ -376,7 +376,7 @@ vnet_generic_outer_header_parser_inline (vlib_buffer_t * b0, u16 ethertype = 0; u16 l2hdr_sz = 0; - ASSERT (is_ip4 ^ is_ip6); + ASSERT (!(is_ip4 && is_ip6)); if (is_l2) { diff --git a/src/vnet/interface_output.c b/src/vnet/interface_output.c index 8e3d53ab76f..f9490f34f6a 100644 --- a/src/vnet/interface_output.c +++ b/src/vnet/interface_output.c @@ -344,22 +344,22 @@ vnet_interface_output_node_inline (vlib_main_t * vm, vnet_calc_checksums_inline (vm, b[0], b[0]->flags & VNET_BUFFER_F_IS_IP4, - b[0]->flags & VNET_BUFFER_F_IS_IP6, 1 /* with gso */ ); + b[0]->flags & VNET_BUFFER_F_IS_IP6); if (b[1]->flags & vnet_buffer_offload_flags) vnet_calc_checksums_inline (vm, b[1], b[1]->flags & VNET_BUFFER_F_IS_IP4, - b[1]->flags & VNET_BUFFER_F_IS_IP6, 1 /* with gso */ ); + b[1]->flags & VNET_BUFFER_F_IS_IP6); if (b[2]->flags & vnet_buffer_offload_flags) vnet_calc_checksums_inline (vm, b[2], b[2]->flags & VNET_BUFFER_F_IS_IP4, - b[2]->flags & VNET_BUFFER_F_IS_IP6, 1 /* with gso */ ); + b[2]->flags & VNET_BUFFER_F_IS_IP6); if (b[3]->flags & vnet_buffer_offload_flags) vnet_calc_checksums_inline (vm, b[3], b[3]->flags & VNET_BUFFER_F_IS_IP4, - b[3]->flags & VNET_BUFFER_F_IS_IP6, 1 /* with gso */ ); + b[3]->flags & VNET_BUFFER_F_IS_IP6); } } b += 4; @@ -410,7 +410,7 @@ vnet_interface_output_node_inline (vlib_main_t * vm, vnet_calc_checksums_inline (vm, b[0], b[0]->flags & VNET_BUFFER_F_IS_IP4, - b[0]->flags & VNET_BUFFER_F_IS_IP6, 1 /* with gso */ ); + b[0]->flags & VNET_BUFFER_F_IS_IP6); } b += 1; } diff --git a/src/vnet/interface_output.h b/src/vnet/interface_output.h index c408fca9ca9..4b082b314ad 100644 --- a/src/vnet/interface_output.h +++ b/src/vnet/interface_output.h @@ -82,59 +82,29 @@ vnet_calc_ip6_checksums (vlib_main_t * vm, vlib_buffer_t * b, static_always_inline void vnet_calc_checksums_inline (vlib_main_t * vm, vlib_buffer_t * b, - int is_ip4, int is_ip6, int with_gso) + int is_ip4, int is_ip6) { ip4_header_t *ip4; ip6_header_t *ip6; tcp_header_t *th; udp_header_t *uh; - if (with_gso) - { - generic_header_offset_t gho = { 0 }; - vnet_generic_header_offset_parser (b, &gho, 1 /* l2 */ , is_ip4, - is_ip6); - - ASSERT (gho.gho_flags ^ (GHO_F_IP4 | GHO_F_IP6)); - - vnet_get_inner_header (b, &gho); - - ip4 = (ip4_header_t *) - (vlib_buffer_get_current (b) + gho.l3_hdr_offset); - ip6 = (ip6_header_t *) - (vlib_buffer_get_current (b) + gho.l3_hdr_offset); - th = (tcp_header_t *) (vlib_buffer_get_current (b) + gho.l4_hdr_offset); - uh = (udp_header_t *) (vlib_buffer_get_current (b) + gho.l4_hdr_offset); + ASSERT (!(is_ip4 && is_ip6)); - if (gho.gho_flags & GHO_F_IP4) - { - vnet_calc_ip4_checksums (vm, b, ip4, th, uh); - } - else if (gho.gho_flags & GHO_F_IP6) - { - vnet_calc_ip6_checksums (vm, b, ip6, th, uh); - } + ip4 = (ip4_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset); + ip6 = (ip6_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset); + th = (tcp_header_t *) (b->data + vnet_buffer (b)->l4_hdr_offset); + uh = (udp_header_t *) (b->data + vnet_buffer (b)->l4_hdr_offset); - vnet_get_outer_header (b, &gho); + if (is_ip4) + { + vnet_calc_ip4_checksums (vm, b, ip4, th, uh); } - else + else if (is_ip6) { - ASSERT (!(is_ip4 && is_ip6)); - - ip4 = (ip4_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset); - ip6 = (ip6_header_t *) (b->data + vnet_buffer (b)->l3_hdr_offset); - th = (tcp_header_t *) (b->data + vnet_buffer (b)->l4_hdr_offset); - uh = (udp_header_t *) (b->data + vnet_buffer (b)->l4_hdr_offset); - - if (is_ip4) - { - vnet_calc_ip4_checksums (vm, b, ip4, th, uh); - } - if (is_ip6) - { - vnet_calc_ip6_checksums (vm, b, ip6, th, uh); - } + vnet_calc_ip6_checksums (vm, b, ip6, th, uh); } + b->flags &= ~VNET_BUFFER_F_OFFLOAD_TCP_CKSUM; b->flags &= ~VNET_BUFFER_F_OFFLOAD_UDP_CKSUM; b->flags &= ~VNET_BUFFER_F_OFFLOAD_IP_CKSUM; diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index b76da0a248b..0fa9da22c93 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -2241,8 +2241,7 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, next[0] = next_index; if (is_midchain) vnet_calc_checksums_inline (vm, b[0], 1 /* is_ip4 */ , - 0 /* is_ip6 */ , - 0 /* with gso */ ); + 0 /* is_ip6 */ ); } else { @@ -2267,8 +2266,7 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, next[1] = next_index; if (is_midchain) vnet_calc_checksums_inline (vm, b[1], 1 /* is_ip4 */ , - 0 /* is_ip6 */ , - 0 /* with gso */ ); + 0 /* is_ip6 */ ); } else { @@ -2419,8 +2417,7 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, if (is_midchain) { vnet_calc_checksums_inline (vm, b[0], 1 /* is_ip4 */ , - 0 /* is_ip6 */ , - 0 /* with gso */ ); + 0 /* is_ip6 */ ); /* Guess we are only writing on ipv4 header. */ vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip4_header_t)); @@ -2527,8 +2524,7 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, { /* this acts on the packet that is about to be encapped */ vnet_calc_checksums_inline (vm, b[0], 1 /* is_ip4 */ , - 0 /* is_ip6 */ , - 0 /* with gso */ ); + 0 /* is_ip6 */ ); /* Guess we are only writing on ipv4 header. */ vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip4_header_t)); diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c index e4d8fc0ea88..d6ef8c842e7 100644 --- a/src/vnet/ip/ip6_forward.c +++ b/src/vnet/ip/ip6_forward.c @@ -1936,11 +1936,9 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, /* before we paint on the next header, update the L4 * checksums if required, since there's no offload on a tunnel */ vnet_calc_checksums_inline (vm, p0, 0 /* is_ip4 */ , - 1 /* is_ip6 */ , - 0 /* with gso */ ); + 1 /* is_ip6 */ ); vnet_calc_checksums_inline (vm, p1, 0 /* is_ip4 */ , - 1 /* is_ip6 */ , - 0 /* with gso */ ); + 1 /* is_ip6 */ ); /* Guess we are only writing on ipv6 header. */ vnet_rewrite_two_headers (adj0[0], adj1[0], @@ -2036,8 +2034,7 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, if (is_midchain) { vnet_calc_checksums_inline (vm, p0, 0 /* is_ip4 */ , - 1 /* is_ip6 */ , - 0 /* with gso */ ); + 1 /* is_ip6 */ ); /* Guess we are only writing on ip6 header. */ vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip6_header_t)); diff --git a/src/vnet/pg/input.c b/src/vnet/pg/input.c index 8ba3b361894..483add0b5f3 100644 --- a/src/vnet/pg/input.c +++ b/src/vnet/pg/input.c @@ -1530,10 +1530,9 @@ pg_input_trace (pg_main_t * pg, } static_always_inline void -fill_gso_buffer_flags (vlib_main_t * vm, u32 * buffers, u32 n_buffers, - u32 packet_data_size) +fill_buffer_offload_flags (vlib_main_t * vm, u32 * buffers, u32 n_buffers, + int gso_enabled, u32 gso_size) { - for (int i = 0; i < n_buffers; i++) { vlib_buffer_t *b0 = vlib_get_buffer (vm, buffers[i]); @@ -1586,16 +1585,21 @@ fill_gso_buffer_flags (vlib_main_t * vm, u32 * buffers, u32 n_buffers, VNET_BUFFER_F_L3_HDR_OFFSET_VALID | VNET_BUFFER_F_L4_HDR_OFFSET_VALID); } + if (l4_proto == IP_PROTOCOL_TCP) { - b0->flags |= (VNET_BUFFER_F_OFFLOAD_TCP_CKSUM | VNET_BUFFER_F_GSO); + b0->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM; tcp_header_t *tcp = (tcp_header_t *) (vlib_buffer_get_current (b0) + vnet_buffer (b0)->l4_hdr_offset); - l4_hdr_sz = tcp_header_bytes (tcp); tcp->checksum = 0; - vnet_buffer2 (b0)->gso_l4_hdr_sz = l4_hdr_sz; - vnet_buffer2 (b0)->gso_size = packet_data_size; + if (gso_enabled) + { + b0->flags |= VNET_BUFFER_F_GSO; + l4_hdr_sz = tcp_header_bytes (tcp); + vnet_buffer2 (b0)->gso_l4_hdr_sz = l4_hdr_sz; + vnet_buffer2 (b0)->gso_size = gso_size; + } } else if (l4_proto == IP_PROTOCOL_UDP) { @@ -1603,7 +1607,6 @@ fill_gso_buffer_flags (vlib_main_t * vm, u32 * buffers, u32 n_buffers, udp_header_t *udp = (udp_header_t *) (vlib_buffer_get_current (b0) + vnet_buffer (b0)->l4_hdr_offset); - vnet_buffer2 (b0)->gso_l4_hdr_sz = sizeof (*udp); udp->checksum = 0; } } @@ -1700,8 +1703,14 @@ pg_generate_packets (vlib_node_runtime_t * node, vnet_buffer (b)->feature_arc_index = feature_arc_index; } - if (pi->gso_enabled) - fill_gso_buffer_flags (vm, to_next, n_this_frame, pi->gso_size); + if (pi->gso_enabled || + (s->buffer_flags & (VNET_BUFFER_F_OFFLOAD_TCP_CKSUM | + VNET_BUFFER_F_OFFLOAD_UDP_CKSUM | + VNET_BUFFER_F_OFFLOAD_IP_CKSUM))) + { + fill_buffer_offload_flags (vm, to_next, n_this_frame, + pi->gso_enabled, pi->gso_size); + } n_trace = vlib_get_trace_count (vm, node); if (n_trace > 0) diff --git a/test/test_gso.py b/test/test_gso.py index 29a54eb396f..7189104a859 100644 --- a/test/test_gso.py +++ b/test/test_gso.py @@ -444,7 +444,7 @@ class TestGSO(VppTestCase): 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.assert_udp_checksum_valid(rx) + self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner)) @@ -474,7 +474,7 @@ class TestGSO(VppTestCase): 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.assert_udp_checksum_valid(rx) + self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner)) diff --git a/test/test_vxlan.py b/test/test_vxlan.py index 1793e494251..54d0c2d4a59 100644 --- a/test/test_vxlan.py +++ b/test/test_vxlan.py @@ -80,7 +80,8 @@ class TestVxlan(BridgeDomain, VppTestCase): # Verify UDP destination port is VXLAN 4789, source UDP port could be # arbitrary. self.assertEqual(pkt[UDP].dport, type(self).dport) - # TODO: checksum check + # Verify UDP checksum + self.assert_udp_checksum_valid(pkt) # Verify VNI self.assertEqual(pkt[VXLAN].vni, vni) diff --git a/test/test_vxlan6.py b/test/test_vxlan6.py index 3a11ea91db1..d9e2d8159d1 100644 --- a/test/test_vxlan6.py +++ b/test/test_vxlan6.py @@ -6,7 +6,8 @@ from framework import VppTestCase, VppTestRunner from template_bd import BridgeDomain from scapy.layers.l2 import Ether -from scapy.layers.inet6 import IPv6, UDP +from scapy.packet import Raw +from scapy.layers.inet6 import IP, IPv6, UDP from scapy.layers.vxlan import VXLAN import util @@ -80,7 +81,8 @@ class TestVxlan6(BridgeDomain, VppTestCase): # Verify UDP destination port is VXLAN 4789, source UDP port could be # arbitrary. self.assertEqual(pkt[UDP].dport, type(self).dport) - # TODO: checksum check + # Verify UDP checksum + self.assert_udp_checksum_valid(pkt, ignore_zero_checksum=False) # Verify VNI self.assertEqual(pkt[VXLAN].vni, vni) @@ -190,6 +192,35 @@ class TestVxlan6(BridgeDomain, VppTestCase): self.logger.info(self.vapi.cli("show bridge-domain 3 detail")) self.logger.info(self.vapi.cli("show vxlan tunnel")) + def test_encap_fragmented_packet(self): + """ Encapsulation test send fragments from pg1 + Verify receipt of encapsulated frames on pg0 + """ + + frame = (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') / + IP(src='4.3.2.1', dst='1.2.3.4') / + UDP(sport=20000, dport=10000) / + Raw(b'\xa5' * 1000)) + + frags = util.fragment_rfc791(frame, 400) + + self.pg1.add_stream(frags) + + self.pg0.enable_capture() + + self.pg_start() + + out = self.pg0.get_capture(3) + + payload = [] + for pkt in out: + payload.append(self.decapsulate(pkt)) + self.check_encapsulation(pkt, self.single_tunnel_vni) + + reassembled = util.reassemble4(payload) + + self.assertEqual(Ether(raw(frame))[IP], reassembled[IP]) + if __name__ == '__main__': unittest.main(testRunner=VppTestRunner) diff --git a/test/test_vxlan_gbp.py b/test/test_vxlan_gbp.py index 79eb23d45a4..f332aced7d8 100644 --- a/test/test_vxlan_gbp.py +++ b/test/test_vxlan_gbp.py @@ -80,7 +80,8 @@ class TestVxlanGbp(VppTestCase): # Verify UDP destination port is VXLAN GBP 48879, source UDP port could # be arbitrary. self.assertEqual(pkt[UDP].dport, type(self).dport) - # TODO: checksum check + # Verify UDP checksum + self.assert_udp_checksum_valid(pkt) # Verify VNI # pkt.show() self.assertEqual(pkt[VXLAN].vni, vni) diff --git a/test/test_vxlan_gpe.py b/test/test_vxlan_gpe.py index 5c3ac16640c..c5d6bf07f7c 100644 --- a/test/test_vxlan_gpe.py +++ b/test/test_vxlan_gpe.py @@ -80,6 +80,8 @@ class TestVxlanGpe(BridgeDomain, VppTestCase): # Verify UDP destination port is VXLAN-GPE 4790, source UDP port # could be arbitrary. self.assertEqual(pkt[UDP].dport, type(self).dport) + # Verify UDP checksum + self.assert_udp_checksum_valid(pkt) # Verify VNI self.assertEqual(pkt[VXLAN].vni, vni) |