From d1bf43c2aad54b68dcb217b2cb1e8c4f3b42cc55 Mon Sep 17 00:00:00 2001 From: Ole Troan Date: Thu, 16 Aug 2018 22:08:49 +0200 Subject: VPP-1392: VXLAN fails with IP fragmentation Not only is it wasteful to send all fragments back through ip4-lookup, but it doesn't work with tunnel mechanisms that don't have IP enabled on their payload side. Change-Id: Ic92d95982dddaa70969a2a6ea2f98edec7614425 Signed-off-by: Ole Troan (cherry picked from commit b3655e5592e3e8e48eb087632f3fa71915891a9f) --- src/vnet/ip/ip4_forward.c | 2 +- src/vnet/ip/ip6_forward.c | 2 +- src/vnet/ip/ip_frag.c | 2 ++ src/vnet/ip/ip_frag.h | 2 ++ test/test_vxlan.py | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index fd8559d9986..6343d2fae47 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -2062,7 +2062,7 @@ ip4_mtu_check (vlib_buffer_t * b, u16 packet_len, { /* IP fragmentation */ ip_frag_set_vnet_buffer (b, 0, adj_packet_bytes, - IP4_FRAG_NEXT_IP4_LOOKUP, 0); + IP4_FRAG_NEXT_IP4_REWRITE, 0); *next = IP4_REWRITE_NEXT_FRAGMENT; } } diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c index 41f5b151a09..0b3804dacbf 100644 --- a/src/vnet/ip/ip6_forward.c +++ b/src/vnet/ip/ip6_forward.c @@ -1567,7 +1567,7 @@ ip6_mtu_check (vlib_buffer_t * b, u16 packet_bytes, { /* IP fragmentation */ ip_frag_set_vnet_buffer (b, 0, adj_packet_bytes, - IP6_FRAG_NEXT_IP6_LOOKUP, 0); + IP6_FRAG_NEXT_IP6_REWRITE, 0); *next = IP6_REWRITE_NEXT_FRAGMENT; } else diff --git a/src/vnet/ip/ip_frag.c b/src/vnet/ip/ip_frag.c index 8d495af63ed..a31e8d91e73 100644 --- a/src/vnet/ip/ip_frag.c +++ b/src/vnet/ip/ip_frag.c @@ -573,6 +573,7 @@ VLIB_REGISTER_NODE (ip4_frag_node) = { .n_next_nodes = IP4_FRAG_N_NEXT, .next_nodes = { + [IP4_FRAG_NEXT_IP4_REWRITE] = "ip4-rewrite", [IP4_FRAG_NEXT_IP4_LOOKUP] = "ip4-lookup", [IP4_FRAG_NEXT_IP6_LOOKUP] = "ip6-lookup", [IP4_FRAG_NEXT_ICMP_ERROR] = "ip4-icmp-error", @@ -594,6 +595,7 @@ VLIB_REGISTER_NODE (ip6_frag_node) = { .n_next_nodes = IP6_FRAG_N_NEXT, .next_nodes = { + [IP6_FRAG_NEXT_IP6_REWRITE] = "ip6-rewrite", [IP6_FRAG_NEXT_IP4_LOOKUP] = "ip4-lookup", [IP6_FRAG_NEXT_IP6_LOOKUP] = "ip6-lookup", [IP6_FRAG_NEXT_DROP] = "ip6-drop" diff --git a/src/vnet/ip/ip_frag.h b/src/vnet/ip/ip_frag.h index 9d19299e2a5..ef5eb4c0543 100644 --- a/src/vnet/ip/ip_frag.h +++ b/src/vnet/ip/ip_frag.h @@ -48,6 +48,7 @@ extern vlib_node_registration_t ip6_frag_node; typedef enum { + IP4_FRAG_NEXT_IP4_REWRITE, IP4_FRAG_NEXT_IP4_LOOKUP, IP4_FRAG_NEXT_IP6_LOOKUP, IP4_FRAG_NEXT_ICMP_ERROR, @@ -59,6 +60,7 @@ typedef enum { IP6_FRAG_NEXT_IP4_LOOKUP, IP6_FRAG_NEXT_IP6_LOOKUP, + IP6_FRAG_NEXT_IP6_REWRITE, IP6_FRAG_NEXT_DROP, IP6_FRAG_N_NEXT } ip6_frag_next_t; diff --git a/test/test_vxlan.py b/test/test_vxlan.py index 1411dd6c026..3c824b5761a 100644 --- a/test/test_vxlan.py +++ b/test/test_vxlan.py @@ -6,11 +6,27 @@ import unittest from framework import VppTestCase, VppTestRunner from template_bd import BridgeDomain -from scapy.layers.l2 import Ether +from scapy.layers.l2 import Ether, Raw from scapy.layers.inet import IP, UDP from scapy.layers.vxlan import VXLAN from scapy.utils import atol +import StringIO + + +def reassemble(listoffragments): + buffer = StringIO.StringIO() + first = listoffragments[0] + buffer.seek(20) + for pkt in listoffragments: + buffer.seek(pkt[IP].frag*8) + buffer.write(pkt[IP].payload) + first.len = len(buffer.getvalue()) + 20 + first.flags = 0 + del(first.chksum) + header = str(first[IP])[:20] + return first[IP].__class__(header + buffer.getvalue()) + class TestVxlan(BridgeDomain, VppTestCase): """ VXLAN Test Case """ @@ -222,6 +238,35 @@ class TestVxlan(BridgeDomain, VppTestCase): super(TestVxlan, cls).tearDownClass() raise + def test_encap_big_packet(self): + """ Encapsulation test send big frame from pg1 + Verify receipt of encapsulated frames on pg0 + """ + + self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1500, 0, 0, 0]) + + 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('\xa5' * 1450)) + + self.pg1.add_stream([frame]) + + self.pg0.enable_capture() + + self.pg_start() + + # Pick first received frame and check if it's correctly encapsulated. + out = self.pg0.get_capture(2) + ether = out[0] + pkt = reassemble(out) + pkt = ether / pkt + self.check_encapsulation(pkt, self.single_tunnel_bd) + + payload = self.decapsulate(pkt) + # TODO: Scapy bug? + # self.assert_eq_pkts(payload, frame) + # Method to define VPP actions before tear down of the test case. # Overrides tearDown method in VppTestCase class. # @param self The object pointer. -- cgit 1.2.3-korg