diff options
-rw-r--r-- | src/vnet/gre/gre.c | 18 | ||||
-rw-r--r-- | src/vnet/gre/packet.h | 3 | ||||
-rw-r--r-- | test/patches/scapy-2.3.3/gre-layers.patch | 30 | ||||
-rw-r--r-- | test/test_span.py | 72 |
4 files changed, 112 insertions, 11 deletions
diff --git a/src/vnet/gre/gre.c b/src/vnet/gre/gre.c index 75b11017e50..2918f3541fd 100644 --- a/src/vnet/gre/gre.c +++ b/src/vnet/gre/gre.c @@ -410,10 +410,10 @@ gre_interface_tx (vlib_main_t * vm, vlib_buffer_advance (b0, -sizeof (erspan_t2_t)); erspan_t2_t *h0 = vlib_buffer_get_current (b0); u32 seq_num = clib_smp_atomic_add (>0->gre_sn->seq_num, 1); - u64 ver1 = clib_host_to_net_u64 (0x1000000000000000); + u64 hdr = clib_host_to_net_u64 (ERSPAN_HDR2); h0->seq_num = clib_host_to_net_u32 (seq_num); - h0->t2_u64 = ver1; /* all 0's except ver=1 */ - h0->t2.cos_en_t_session = + h0->t2_u64 = hdr; + h0->t2.cos_en_t_session |= clib_host_to_net_u16 (gt0->session_id); } if (PREDICT_FALSE (gt1->type == GRE_TUNNEL_TYPE_ERSPAN)) @@ -422,10 +422,10 @@ gre_interface_tx (vlib_main_t * vm, vlib_buffer_advance (b1, -sizeof (erspan_t2_t)); erspan_t2_t *h1 = vlib_buffer_get_current (b1); u32 seq_num = clib_smp_atomic_add (>1->gre_sn->seq_num, 1); - u64 ver1 = clib_host_to_net_u64 (0x1000000000000000); + u64 hdr = clib_host_to_net_u64 (ERSPAN_HDR2); h1->seq_num = clib_host_to_net_u32 (seq_num); - h1->t2_u64 = ver1; /* all 0's except ver=1 */ - h1->t2.cos_en_t_session = + h1->t2_u64 = hdr; + h1->t2.cos_en_t_session |= clib_host_to_net_u16 (gt1->session_id); } @@ -481,10 +481,10 @@ gre_interface_tx (vlib_main_t * vm, vlib_buffer_advance (b0, -sizeof (erspan_t2_t)); erspan_t2_t *h0 = vlib_buffer_get_current (b0); u32 seq_num = clib_smp_atomic_add (>0->gre_sn->seq_num, 1); - u64 ver1 = clib_host_to_net_u64 (0x1000000000000000); + u64 hdr = clib_host_to_net_u64 (ERSPAN_HDR2); h0->seq_num = clib_host_to_net_u32 (seq_num); - h0->t2_u64 = ver1; /* all 0's except ver=1 */ - h0->t2.cos_en_t_session = + h0->t2_u64 = hdr; + h0->t2.cos_en_t_session |= clib_host_to_net_u16 (gt0->session_id); } diff --git a/src/vnet/gre/packet.h b/src/vnet/gre/packet.h index 034a611eda3..bbd67d565c5 100644 --- a/src/vnet/gre/packet.h +++ b/src/vnet/gre/packet.h @@ -160,6 +160,9 @@ typedef CLIB_PACKED (struct { /* *INDENT-ON* */ +/* u64 template for ERSPAN type 2 header with both EN bits set */ +#define ERSPAN_HDR2 0x1000180000000000ul + #endif /* included_vnet_gre_packet_h */ /* diff --git a/test/patches/scapy-2.3.3/gre-layers.patch b/test/patches/scapy-2.3.3/gre-layers.patch index 605a705b0f7..6090050fc5f 100644 --- a/test/patches/scapy-2.3.3/gre-layers.patch +++ b/test/patches/scapy-2.3.3/gre-layers.patch @@ -14,12 +14,40 @@ diff --git a/scapy/layers/l2.py b/scapy/layers/l2.py index 4f491d2..661a5da 100644 --- a/scapy/layers/l2.py +++ b/scapy/layers/l2.py -@@ -628,7 +628,7 @@ bind_layers( CookedLinux, EAPOL, proto=34958) +@@ -570,6 +570,20 @@ + return getmacbyip(l3.pdst) + conf.neighbor.register_l3(Ether, ARP, l2_register_l3_arp) + ++ ++class ERSPAN(Packet): ++ name = "ERSPAN" ++ fields_desc = [ BitField("ver",0,4), ++ BitField("vlan",0,12), ++ BitField("cos",0,3), ++ BitField("en",0,2), ++ BitField("t",0,1), ++ BitField("session_id",0,10), ++ BitField("reserved",0,12), ++ BitField("index",0,20), ++ ] ++ ++ + class GRErouting(Packet): + name = "GRE routing informations" + fields_desc = [ ShortField("address_family",0), +@@ -628,12 +642,14 @@ bind_layers( CookedLinux, EAPOL, proto=34958) bind_layers( GRE, LLC, proto=122) bind_layers( GRE, Dot1Q, proto=33024) bind_layers( GRE, Dot1AD, type=0x88a8) -bind_layers( GRE, Ether, proto=1) +bind_layers( GRE, Ether, proto=0x6558) ++bind_layers( GRE, ERSPAN, proto=0x88be, seqnum_present=1) bind_layers( GRE, ARP, proto=2054) bind_layers( GRE, EAPOL, proto=34958) bind_layers( GRE, GRErouting, { "routing_present" : 1 } ) + bind_layers( GRErouting, conf.raw_layer,{ "address_family" : 0, "SRE_len" : 0 }) + bind_layers( GRErouting, GRErouting, { } ) ++bind_layers( ERSPAN, Ether) + bind_layers( EAPOL, EAP, type=0) + bind_layers(EAP, EAP_TLS, type=13) + bind_layers(EAP, EAP_FAST, type=43) diff --git a/test/test_span.py b/test/test_span.py index a77c98334b4..021eed83177 100644 --- a/test/test_span.py +++ b/test/test_span.py @@ -3,7 +3,7 @@ import unittest from scapy.packet import Raw -from scapy.layers.l2 import Ether, Dot1Q, GRE +from scapy.layers.l2 import Ether, Dot1Q, GRE, ERSPAN from scapy.layers.inet import IP, UDP from scapy.layers.vxlan import VXLAN @@ -102,6 +102,27 @@ class TestSpan(VppTestCase): return pkt[GRE].payload + def decap_erspan(self, pkt, session): + """ + Decapsulate the original payload frame by removing ERSPAN header + """ + self.assertEqual(pkt[Ether].src, self.pg2.local_mac) + self.assertEqual(pkt[Ether].dst, self.pg2.remote_mac) + + self.assertEqual(pkt[IP].src, self.pg2.local_ip4) + self.assertEqual(pkt[IP].dst, self.pg2.remote_ip4) + + self.assertEqual(pkt[ERSPAN].ver, 1) + self.assertEqual(pkt[ERSPAN].vlan, 0) + self.assertEqual(pkt[ERSPAN].cos, 0) + self.assertEqual(pkt[ERSPAN].en, 3) + self.assertEqual(pkt[ERSPAN].t, 0) + self.assertEqual(pkt[ERSPAN].session_id, session) + self.assertEqual(pkt[ERSPAN].reserved, 0) + self.assertEqual(pkt[ERSPAN].index, 0) + + return pkt[ERSPAN].payload + def decap_vxlan(self, pkt): """ Decapsulate the original payload frame by removing VXLAN header @@ -245,6 +266,54 @@ class TestSpan(VppTestCase): self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0) self.verify_capture(pg1_pkts, pg2_pkts) + def test_span_l2_rx_dst_gre_erspan(self): + """ SPAN l2 rx mirror into gre-erspan """ + + self.sub_if.admin_up() + + gre_if = VppGreInterface(self, self.pg2.local_ip4, + self.pg2.remote_ip4, + type=2, + session=543) + + gre_if.add_vpp_config() + gre_if.admin_up() + + self.bridge(gre_if.sw_if_index) + # Create bi-directional cross-connects between pg0 and pg1 + self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=1) + + # Create incoming packet streams for packet-generator interfaces + pkts = self.create_stream( + self.pg0, self.pg_if_packet_sizes, do_dot1=True) + self.pg0.add_stream(pkts) + + # Enable SPAN on pg0 sub if (mirrored to gre-erspan) + self.vapi.sw_interface_span_enable_disable( + self.sub_if.sw_if_index, gre_if.sw_if_index, is_l2=1) + + # Enable packet capturing and start packet sending + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + # Verify packets outgoing packet streams on mirrored interface (pg2) + n_pkts = len(pkts) + pg1_pkts = self.pg1.get_capture(n_pkts) + pg2_pkts = self.pg2.get_capture(n_pkts) + + def decap(p): return self.decap_erspan(p, session=543) + pg2_decaped = [decap(p) for p in pg2_pkts] + + self.bridge(gre_if.sw_if_index, is_add=0) + + # Disable SPAN on pg0 sub if + self.vapi.sw_interface_span_enable_disable( + self.sub_if.sw_if_index, gre_if.sw_if_index, state=0, is_l2=1) + gre_if.remove_vpp_config() + self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0) + + self.verify_capture(pg1_pkts, pg2_decaped) + def test_span_l2_rx_dst_gre_subif_vtr(self): """ SPAN l2 rx mirror into gre-subif+vtr """ @@ -270,6 +339,7 @@ class TestSpan(VppTestCase): self.pg0, self.pg_if_packet_sizes, do_dot1=True) self.pg0.add_stream(pkts) + # Enable SPAN on pg0 sub if (mirrored to gre sub if) self.vapi.sw_interface_span_enable_disable( self.sub_if.sw_if_index, gre_sub_if.sw_if_index, is_l2=1) |