diff options
-rw-r--r-- | src/plugins/flowprobe/node.c | 12 | ||||
-rw-r--r-- | test/test_flowprobe.py | 75 |
2 files changed, 82 insertions, 5 deletions
diff --git a/src/plugins/flowprobe/node.c b/src/plugins/flowprobe/node.c index 274ea388ccd..22bb6cea80a 100644 --- a/src/plugins/flowprobe/node.c +++ b/src/plugins/flowprobe/node.c @@ -384,9 +384,11 @@ add_to_flow_record_state (vlib_main_t *vm, vlib_node_runtime_t *node, flowprobe_record_t flags = fm->context[which].flags; bool collect_ip4 = false, collect_ip6 = false; ASSERT (b); - ethernet_header_t *eth = ethernet_buffer_get_header (b); + ethernet_header_t *eth = (direction == FLOW_DIRECTION_TX) ? + vlib_buffer_get_current (b) : + ethernet_buffer_get_header (b); u16 ethertype = clib_net_to_host_u16 (eth->type); - u16 l2_hdr_sz = sizeof (ethernet_header_t); + u16 l3_hdr_offset = (u8 *) eth - b->data + sizeof (ethernet_header_t); /* *INDENT-OFF* */ flowprobe_key_t k = {}; /* *INDENT-ON* */ @@ -423,13 +425,13 @@ add_to_flow_record_state (vlib_main_t *vm, vlib_node_runtime_t *node, while (clib_net_to_host_u16 (ethv->type) == ETHERNET_TYPE_VLAN) { ethv++; - l2_hdr_sz += sizeof (ethernet_vlan_header_tv_t); + l3_hdr_offset += sizeof (ethernet_vlan_header_tv_t); } k.ethertype = ethertype = clib_net_to_host_u16 ((ethv)->type); } if (collect_ip6 && ethertype == ETHERNET_TYPE_IP6) { - ip6 = (ip6_header_t *) (b->data + l2_hdr_sz); + ip6 = (ip6_header_t *) (b->data + l3_hdr_offset); if (flags & FLOW_RECORD_L3) { k.src_address.as_u64[0] = ip6->src_address.as_u64[0]; @@ -448,7 +450,7 @@ add_to_flow_record_state (vlib_main_t *vm, vlib_node_runtime_t *node, } if (collect_ip4 && ethertype == ETHERNET_TYPE_IP4) { - ip4 = (ip4_header_t *) (b->data + l2_hdr_sz); + ip4 = (ip4_header_t *) (b->data + l3_hdr_offset); if (flags & FLOW_RECORD_L3) { k.src_address.ip4.as_u32 = ip4->src_address.as_u32; diff --git a/test/test_flowprobe.py b/test/test_flowprobe.py index 28ddff8a65e..ca2bbb53cbc 100644 --- a/test/test_flowprobe.py +++ b/test/test_flowprobe.py @@ -30,6 +30,7 @@ from vpp_ip_route import VppIpRoute, VppRoutePath from vpp_papi.macaddress import mac_ntop from socket import inet_ntop from vpp_papi import VppEnum +from vpp_sub_interface import VppDot1ADSubint TMPL_COMMON_FIELD_COUNT = 6 @@ -40,6 +41,9 @@ TMPL_L4_FIELD_COUNT = 3 IPFIX_TCP_FLAGS_ID = 6 IPFIX_SRC_TRANS_PORT_ID = 7 IPFIX_DST_TRANS_PORT_ID = 11 +IPFIX_SRC_IP4_ADDR_ID = 8 +IPFIX_DST_IP4_ADDR_ID = 12 +IPFIX_FLOW_DIRECTION_ID = 61 TCP_F_FIN = 0x01 TCP_F_SYN = 0x02 @@ -1230,6 +1234,77 @@ class DatapathTx(MethodHolder, DatapathTestsHolder): intf3 = "pg6" direction = "tx" + def test_rewritten_traffic(self): + """Rewritten traffic (from subif to ipfix if)""" + self.pg_enable_capture(self.pg_interfaces) + self.pkts = [] + + # prepare a sub-interface + subif = VppDot1ADSubint(self, self.pg7, 0, 300, 400) + subif.admin_up() + subif.config_ip4() + + # enable ip4 datapath for an interface + ipfix = VppCFLOW( + test=self, + intf="pg8", + datapath="ip4", + layer="l2 l3 l4", + direction=self.direction, + ) + ipfix.add_vpp_config() + + # template packet should arrive immediately + ipfix_decoder = IPFIXDecoder() + templates = ipfix.verify_templates(ipfix_decoder, count=1) + + # forward some traffic through the ipfix interface + route = VppIpRoute( + self, + "9.0.0.0", + 24, + [VppRoutePath(self.pg8.remote_ip4, self.pg8.sw_if_index)], + ) + route.add_vpp_config() + + # prepare an IPv4 packet (subif => ipfix interface) + pkt = ( + Ether(src=subif.remote_mac, dst=self.pg7.local_mac) + / IP(src=subif.remote_ip4, dst="9.0.0.1") + / UDP(sport=1234, dport=4321) + / Raw(b"\xa5" * 123) + ) + self.pkts = [ + subif.add_dot1ad_layer(pkt, 300, 400), + ] + + # send the packet + capture = self.send_packets(self.pg7, self.pg8) + + # wait for a flow and verify it + self.vapi.ipfix_flush() + cflow = self.wait_for_cflow_packet(self.collector, templates[0]) + self.verify_cflow_data(ipfix_decoder, capture, cflow) + self.verify_cflow_data_detail( + ipfix_decoder, + capture, + cflow, + { + IPFIX_SRC_IP4_ADDR_ID: "src_ip", + IPFIX_DST_IP4_ADDR_ID: "dst_ip", + IPFIX_SRC_TRANS_PORT_ID: "sport", + IPFIX_DST_TRANS_PORT_ID: "dport", + IPFIX_FLOW_DIRECTION_ID: (self.direction == "tx"), + }, + ) + + self.collector.get_capture(2) + + # cleanup + route.remove_vpp_config() + subif.remove_vpp_config() + ipfix.remove_vpp_config() + @tag_fixme_vpp_workers class DatapathRx(MethodHolder, DatapathTestsHolder): |