From 0b6a857d85df97e887de7aaf00fd6bd2dae39bf8 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Wed, 30 Oct 2019 17:34:14 +0000 Subject: ip: Fragmentation fixes Type: fix if the packet is about to be fragmented, then don't call any of the actions that expect the rewrite to have been written. 1) don't double count packets thru the adjacency (original & fragments) 2) don't double decrement the TTL for fragments 3) return to ip4-midchain post ip-frag if that's where we started. 4) only run midchain/mcast fixups if not fragmenting (if no errors) Change-Id: Ib2866787a42713ee5871b87b597d8f74b901044b Signed-off-by: Neale Ranns --- test/test_ip4.py | 11 +++++++++++ test/test_ipip.py | 25 +++++++++++++++++++++---- test/test_mtu.py | 3 +-- test/vpp_neighbor.py | 1 + 4 files changed, 34 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/test_ip4.py b/test/test_ip4.py index 831685150a2..a043be8b922 100644 --- a/test/test_ip4.py +++ b/test/test_ip4.py @@ -21,6 +21,7 @@ from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \ from vpp_ip import VppIpAddress from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint from vpp_papi import VppEnum +from vpp_neighbor import VppNeighbor NUM_PKTS = 67 @@ -1918,12 +1919,19 @@ class TestIPv4Frag(VppTestCase): def test_frag_large_packets(self): """ Fragmentation of large packets """ + self.vapi.cli("adjacency counters enable") + p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) / IP(src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) / UDP(sport=1234, dport=5678) / Raw()) self.extend_packet(p, 6000, "abcde") saved_payload = p[Raw].load + nbr = VppNeighbor(self, + self.dst_if.sw_if_index, + self.dst_if.remote_mac, + self.dst_if.remote_ip4).add_vpp_config() + # Force fragmentation by setting MTU of output interface # lower than packet size self.vapi.sw_interface_set_mtu(self.dst_if.sw_if_index, @@ -1937,6 +1945,9 @@ class TestIPv4Frag(VppTestCase): # cannot be larger then VPP buffer size (which is 2048) packets = self.dst_if.get_capture(3) + # we should show 3 packets thru the neighbor + self.assertEqual(3, nbr.get_stats()['packets']) + # Assume VPP sends the fragments in order payload = b'' for p in packets: diff --git a/test/test_ipip.py b/test/test_ipip.py index 1887417a5e0..a259a5d18fa 100644 --- a/test/test_ipip.py +++ b/test/test_ipip.py @@ -2,7 +2,7 @@ """IP{4,6} over IP{v,6} tunnel functional tests""" import unittest -from scapy.layers.inet6 import IPv6, Ether, IP, UDP, IPv6ExtHdrFragment +from scapy.layers.inet6 import IPv6, Ether, IP, UDP, IPv6ExtHdrFragment, Raw from scapy.all import fragment, fragment6, RandShort, defragment6 from framework import VppTestCase, VppTestRunner from vpp_ip import DpoProto @@ -81,7 +81,7 @@ class TestIPIP(VppTestCase): p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) p_ip6 = IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=42) p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42) - p_payload = UDP(sport=1234, dport=1234) + p_payload = UDP(sport=1234, dport=1234) / Raw(b'X' * 100) # IPv4 transport rv = ipip_add_tunnel(self, @@ -121,6 +121,7 @@ class TestIPIP(VppTestCase): rx = self.send_and_expect(self.pg0, p6 * 10, self.pg1) for p in rx: self.validate(p[1], p6_reply) + self.assert_packet_checksums_valid(p) # IPv4 in to IPv4 tunnel p4 = (p_ether / p_ip4 / p_payload) @@ -134,6 +135,7 @@ class TestIPIP(VppTestCase): rx = self.send_and_expect(self.pg0, p4 * 10, self.pg1) for p in rx: self.validate(p[1], p4_reply) + self.assert_packet_checksums_valid(p) # Decapsulation p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) @@ -147,6 +149,7 @@ class TestIPIP(VppTestCase): rx = self.send_and_expect(self.pg1, p4 * 10, self.pg0) for p in rx: self.validate(p[1], p4_reply) + self.assert_packet_checksums_valid(p) err = self.statistics.get_err_counter( '/err/ipip4-input/packets decapsulated') @@ -161,6 +164,7 @@ class TestIPIP(VppTestCase): rx = self.send_and_expect(self.pg1, p6 * 10, self.pg0) for p in rx: self.validate(p[1], p6_reply) + self.assert_packet_checksums_valid(p) err = self.statistics.get_err_counter( '/err/ipip4-input/packets decapsulated') @@ -222,7 +226,6 @@ class TestIPIP(VppTestCase): self.pg_start() rx = self.pg0.get_capture(6) reass_pkt = reassemble4(rx) - p4_reply.ttl -= 1 p4_reply.id = 256 self.validate(reass_pkt, p4_reply) @@ -233,10 +236,24 @@ class TestIPIP(VppTestCase): self.pg_start() rx = self.pg0.get_capture(2) reass_pkt = reassemble4(rx) - p4_reply.ttl -= 1 p4_reply.id = 512 self.validate(reass_pkt, p4_reply) + # send large packets through the tunnel, expect them to be fragmented + self.vapi.sw_interface_set_mtu(sw_if_index, [600, 0, 0, 0]) + + p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / + IP(src="1.2.3.4", dst="130.67.0.1", tos=42) / + UDP(sport=1234, dport=1234) / Raw(b'Q' * 1000)) + rx = self.send_and_expect(self.pg0, p4 * 15, self.pg1, 30) + inners = [] + for p in rx: + inners.append(p[IP].payload) + reass_pkt = reassemble4(inners) + for p in reass_pkt: + self.assert_packet_checksums_valid(p) + self.assertEqual(p[IP].ttl, 63) + def test_ipip_create(self): """ ipip create / delete interface test """ rv = ipip_add_tunnel(self, '1.2.3.4', '2.3.4.5') diff --git a/test/test_mtu.py b/test/test_mtu.py index 568a147a9a4..c18ef9f4cdf 100644 --- a/test/test_mtu.py +++ b/test/test_mtu.py @@ -101,7 +101,6 @@ class TestMTU(VppTestCase): dst=self.pg0.remote_ip4, ttl=254, len=576, id=0) / p_icmp4 / p_ip4 / p_payload) - icmp4_reply[1].ttl -= 1 n = icmp4_reply.__class__(icmp4_reply) s = bytes(icmp4_reply) icmp4_reply = s[0:576] @@ -118,7 +117,7 @@ class TestMTU(VppTestCase): p4 = p_ether / p_ip4 / p_payload p4.flags = 0 p4_reply = p_ip4 / p_payload - p4_reply.ttl = 62 # check this + p4_reply.ttl = p_ip4.ttl - 1 p4_reply.flags = 0 p4_reply.id = 256 self.pg_enable_capture() diff --git a/test/vpp_neighbor.py b/test/vpp_neighbor.py index eb9635fd603..f906c2a5af3 100644 --- a/test/vpp_neighbor.py +++ b/test/vpp_neighbor.py @@ -58,6 +58,7 @@ class VppNeighbor(VppObject): flags=self.flags) self.stats_index = r.stats_index self._test.registry.register(self, self._test.logger) + return self def remove_vpp_config(self): self._test.vapi.ip_neighbor_add_del( -- cgit 1.2.3-korg