X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fethernet%2Fnode.c;h=4ef575a85fc13d58a9503070ad183db102f1d914;hb=a58dae61aea7e781a27ce65462dd38ab55e8599c;hp=3c4330e6225a0ff1ff1e8ab395b81eb6ab96dfec;hpb=8bf80a3ddae7733925a757cb1710e25776eea01c;p=vpp.git diff --git a/src/vnet/ethernet/node.c b/src/vnet/ethernet/node.c index 3c4330e6225..4ef575a85fc 100644 --- a/src/vnet/ethernet/node.c +++ b/src/vnet/ethernet/node.c @@ -44,7 +44,7 @@ #include #include #include -#include +#include #define foreach_ethernet_input_next \ _ (PUNT, "error-punt") \ @@ -204,7 +204,8 @@ ethernet_input_inline_dmac_check (vnet_hw_interface_t * hi, // vlan table lookups and vlan header parsing. Check the most specific // matches first. static_always_inline void -identify_subint (vnet_hw_interface_t * hi, +identify_subint (ethernet_main_t * em, + vnet_hw_interface_t * hi, vlib_buffer_t * b0, u32 match_flags, main_intf_t * main_intf, @@ -213,6 +214,7 @@ identify_subint (vnet_hw_interface_t * hi, u32 * new_sw_if_index, u8 * error0, u32 * is_l2) { u32 matched; + ethernet_interface_t *ei = ethernet_get_interface (em, hi->hw_if_index); matched = eth_identify_subint (hi, match_flags, main_intf, vlan_intf, qinq_intf, new_sw_if_index, error0, is_l2); @@ -220,28 +222,27 @@ identify_subint (vnet_hw_interface_t * hi, if (matched) { // Perform L3 my-mac filter - // A unicast packet arriving on an L3 interface must have a dmac matching the interface mac. - // This is required for promiscuous mode, else we will forward packets we aren't supposed to. - if (!(*is_l2)) + // A unicast packet arriving on an L3 interface must have a dmac + // matching the interface mac. If interface has STATUS_L3 bit set + // mac filter is already done. + if ((!*is_l2) && ei && + (!(ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3))) { u64 dmacs[2]; u8 dmacs_bad[2]; ethernet_header_t *e0; - ethernet_interface_t *ei0; e0 = (void *) (b0->data + vnet_buffer (b0)->l2_hdr_offset); dmacs[0] = *(u64 *) e0; - ei0 = ethernet_get_interface (ðernet_main, hi->hw_if_index); - if (ei0 && vec_len (ei0->secondary_addrs)) + if (vec_len (ei->secondary_addrs)) ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad, - 1 /* n_packets */ , ei0, - 1 /* have_sec_dmac */ ); + 1 /* n_packets */, ei, + 1 /* have_sec_dmac */); else ethernet_input_inline_dmac_check (hi, dmacs, dmacs_bad, - 1 /* n_packets */ , ei0, - 0 /* have_sec_dmac */ ); - + 1 /* n_packets */, ei, + 0 /* have_sec_dmac */); if (dmacs_bad[0]) *error0 = ETHERNET_ERROR_L3_MAC_MISMATCH; } @@ -692,9 +693,11 @@ ethernet_input_inline_dmac_check (vnet_hw_interface_t * hi, u32 n_packets, ethernet_interface_t * ei, u8 have_sec_dmac) { - u64 hwaddr = (*(u64 *) hi->hw_address) & DMAC_MASK; + u64 hwaddr = ei->address.as_u64; u8 bad = 0; + ASSERT (0 == ei->address.zero); + dmacs_bad[0] = is_dmac_bad (dmacs[0], hwaddr); dmacs_bad[1] = ((n_packets > 1) & is_dmac_bad (dmacs[1], hwaddr)); @@ -702,11 +705,12 @@ ethernet_input_inline_dmac_check (vnet_hw_interface_t * hi, if (PREDICT_FALSE (bad && have_sec_dmac)) { - mac_address_t *sec_addr; + ethernet_interface_address_t *sec_addr; vec_foreach (sec_addr, ei->secondary_addrs) { - hwaddr = (*(u64 *) sec_addr) & DMAC_MASK; + ASSERT (0 == sec_addr->zero); + hwaddr = sec_addr->as_u64; bad = (eth_input_sec_dmac_check_x1 (hwaddr, dmacs, dmacs_bad) | eth_input_sec_dmac_check_x1 (hwaddr, dmacs + 1, @@ -724,12 +728,14 @@ eth_input_process_frame_dmac_check (vnet_hw_interface_t * hi, u32 n_packets, ethernet_interface_t * ei, u8 have_sec_dmac) { - u64 hwaddr = (*(u64 *) hi->hw_address) & DMAC_MASK; + u64 hwaddr = ei->address.as_u64; u64 *dmac = dmacs; u8 *dmac_bad = dmacs_bad; u32 bad = 0; i32 n_left = n_packets; + ASSERT (0 == ei->address.zero); + #ifdef CLIB_HAVE_VEC256 while (n_left > 0) { @@ -758,15 +764,17 @@ eth_input_process_frame_dmac_check (vnet_hw_interface_t * hi, if (have_sec_dmac && bad) { - mac_address_t *addr; + ethernet_interface_address_t *addr; vec_foreach (addr, ei->secondary_addrs) { - u64 hwaddr = ((u64 *) addr)[0] & DMAC_MASK; + u64 hwaddr = addr->as_u64; i32 n_left = n_packets; u64 *dmac = dmacs; u8 *dmac_bad = dmacs_bad; + ASSERT (0 == addr->zero); + bad = 0; while (n_left > 0) @@ -1085,29 +1093,35 @@ eth_input_single_int (vlib_main_t * vm, vlib_node_runtime_t * node, subint_config_t *subint0 = &intf0->untagged_subint; int main_is_l3 = (subint0->flags & SUBINT_CONFIG_L2) == 0; - int promisc = (ei->flags & ETHERNET_INTERFACE_FLAG_ACCEPT_ALL) != 0; + int int_is_l3 = ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3; if (main_is_l3) { - /* main interface is L3, we dont expect tagged packets and interface - is not in promisc node, so we dont't need to check DMAC */ - int is_l3 = 1; - - if (promisc == 0) - eth_input_process_frame (vm, node, hi, from, n_pkts, is_l3, - ip4_cksum_ok, 0); + if (int_is_l3 || /* DMAC filter already done by NIC */ + ((hi->l2_if_count != 0) && (hi->l3_if_count == 0))) + { /* All L2 usage - DMAC check not needed */ + eth_input_process_frame (vm, node, hi, from, n_pkts, + /*is_l3 */ 1, ip4_cksum_ok, 0); + } else - /* subinterfaces and promisc mode so DMAC check is needed */ - eth_input_process_frame (vm, node, hi, from, n_pkts, is_l3, - ip4_cksum_ok, 1); + { /* DMAC check needed for L3 */ + eth_input_process_frame (vm, node, hi, from, n_pkts, + /*is_l3 */ 1, ip4_cksum_ok, 1); + } return; } else { - /* untagged packets are treated as L2 */ - int is_l3 = 0; - eth_input_process_frame (vm, node, hi, from, n_pkts, is_l3, - ip4_cksum_ok, 1); + if (hi->l3_if_count == 0) + { /* All L2 usage - DMAC check not needed */ + eth_input_process_frame (vm, node, hi, from, n_pkts, + /*is_l3 */ 0, ip4_cksum_ok, 0); + } + else + { /* DMAC check needed for L3 */ + eth_input_process_frame (vm, node, hi, from, n_pkts, + /*is_l3 */ 0, ip4_cksum_ok, 1); + } return; } } @@ -1116,6 +1130,7 @@ static_always_inline void ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { + vnet_main_t *vnm = vnet_get_main (); u32 *from, n_left; if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) { @@ -1144,48 +1159,22 @@ ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node, } /* rx pcap capture if enabled */ - if (PREDICT_FALSE (vlib_global_main.pcap.pcap_rx_enable)) + if (PREDICT_FALSE (vnm->pcap.pcap_rx_enable)) { u32 bi0; - vnet_pcap_t *pp = &vlib_global_main.pcap; + vnet_pcap_t *pp = &vnm->pcap; from = vlib_frame_vector_args (from_frame); n_left = from_frame->n_vectors; while (n_left > 0) { - int classify_filter_result; vlib_buffer_t *b0; bi0 = from[0]; from++; n_left--; b0 = vlib_get_buffer (vm, bi0); - if (pp->filter_classify_table_index != ~0) - { - classify_filter_result = - vnet_is_packet_traced_inline - (b0, pp->filter_classify_table_index, 0 /* full classify */ ); - if (classify_filter_result) - pcap_add_buffer (&pp->pcap_main, vm, bi0, - pp->max_bytes_per_pkt); - continue; - } - - if (pp->pcap_sw_if_index == 0 || - pp->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX]) - { - vnet_main_t *vnm = vnet_get_main (); - vnet_hw_interface_t *hi = - vnet_get_sup_hw_interface - (vnm, vnet_buffer (b0)->sw_if_index[VLIB_RX]); - - /* Capture pkt if not filtered, or if filter hits */ - if (hi->trace_classify_table_index == ~0 || - vnet_is_packet_traced_inline - (b0, hi->trace_classify_table_index, - 0 /* full classify */ )) - pcap_add_buffer (&pp->pcap_main, vm, bi0, - pp->max_bytes_per_pkt); - } + if (vnet_is_packet_pcaped (pp, b0, ~0)) + pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt); } } } @@ -1325,6 +1314,9 @@ ethernet_input_inline (vlib_main_t * vm, } else { + if (ei && (ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3)) + goto skip_dmac_check01; + dmacs[0] = *(u64 *) e0; dmacs[1] = *(u64 *) e1; @@ -1346,6 +1338,7 @@ ethernet_input_inline (vlib_main_t * vm, if (dmacs_bad[1]) error1 = ETHERNET_ERROR_L3_MAC_MISMATCH; + skip_dmac_check01: vlib_buffer_advance (b0, sizeof (ethernet_header_t)); determine_next_node (em, variant, 0, type0, b0, &error0, &next0); @@ -1389,14 +1382,16 @@ ethernet_input_inline (vlib_main_t * vm, &hi1, &main_intf1, &vlan_intf1, &qinq_intf1); - identify_subint (hi0, + identify_subint (em, + hi0, b0, match_flags0, main_intf0, vlan_intf0, qinq_intf0, &new_sw_if_index0, &error0, &is_l20); - identify_subint (hi1, + identify_subint (em, + hi1, b1, match_flags1, main_intf1, @@ -1509,7 +1504,7 @@ ethernet_input_inline (vlib_main_t * vm, if (n_left_from > 1) { vlib_prefetch_buffer_header (b[1], STORE); - CLIB_PREFETCH (b[1]->data, CLIB_CACHE_LINE_BYTES, LOAD); + clib_prefetch_load (b[1]->data); } bi0 = from[0]; @@ -1563,24 +1558,27 @@ ethernet_input_inline (vlib_main_t * vm, } else { - dmacs[0] = *(u64 *) e0; + if (ei && ei->flags & ETHERNET_INTERFACE_FLAG_STATUS_L3) + goto skip_dmac_check0; - if (ei && vec_len (ei->secondary_addrs)) - ethernet_input_inline_dmac_check (hi, dmacs, - dmacs_bad, - 1 /* n_packets */ , - ei, - 1 /* have_sec_dmac */ ); - else - ethernet_input_inline_dmac_check (hi, dmacs, - dmacs_bad, - 1 /* n_packets */ , - ei, - 0 /* have_sec_dmac */ ); + dmacs[0] = *(u64 *) e0; - if (dmacs_bad[0]) - error0 = ETHERNET_ERROR_L3_MAC_MISMATCH; + if (ei) + { + if (vec_len (ei->secondary_addrs)) + ethernet_input_inline_dmac_check ( + hi, dmacs, dmacs_bad, 1 /* n_packets */, ei, + 1 /* have_sec_dmac */); + else + ethernet_input_inline_dmac_check ( + hi, dmacs, dmacs_bad, 1 /* n_packets */, ei, + 0 /* have_sec_dmac */); + + if (dmacs_bad[0]) + error0 = ETHERNET_ERROR_L3_MAC_MISMATCH; + } + skip_dmac_check0: vlib_buffer_advance (b0, sizeof (ethernet_header_t)); determine_next_node (em, variant, 0, type0, b0, &error0, &next0); @@ -1605,7 +1603,8 @@ ethernet_input_inline (vlib_main_t * vm, &hi0, &main_intf0, &vlan_intf0, &qinq_intf0); - identify_subint (hi0, + identify_subint (em, + hi0, b0, match_flags0, main_intf0, @@ -1896,7 +1895,7 @@ ethernet_sw_interface_get_config (vnet_main_t * vnm, } else { - // a specific outer + specifc innner vlan id, a common case + // a specific outer + specific innner vlan id, a common case // get the qinq table if (vlan_table->vlans[si->sub.eth.outer_vlan_id].qinqs == 0) @@ -1928,14 +1927,14 @@ static clib_error_t * ethernet_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) { subint_config_t *subint; - u32 dummy_flags; - u32 dummy_unsup; + u32 placeholder_flags; + u32 placeholder_unsup; clib_error_t *error = 0; // Find the config for this subinterface subint = - ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags, - &dummy_unsup); + ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags, + &placeholder_unsup); if (subint == 0) { @@ -1959,8 +1958,8 @@ void ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm, u32 sw_if_index, u32 l2) { subint_config_t *subint; - u32 dummy_flags; - u32 dummy_unsup; + u32 placeholder_flags; + u32 placeholder_unsup; int is_port; vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index); @@ -1968,8 +1967,8 @@ ethernet_sw_interface_set_l2_mode (vnet_main_t * vnm, u32 sw_if_index, u32 l2) // Find the config for this subinterface subint = - ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags, - &dummy_unsup); + ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags, + &placeholder_unsup); if (subint == 0) { @@ -2009,13 +2008,13 @@ ethernet_sw_interface_set_l2_mode_noport (vnet_main_t * vnm, u32 sw_if_index, u32 l2) { subint_config_t *subint; - u32 dummy_flags; - u32 dummy_unsup; + u32 placeholder_flags; + u32 placeholder_unsup; /* Find the config for this subinterface */ subint = - ethernet_sw_interface_get_config (vnm, sw_if_index, &dummy_flags, - &dummy_unsup); + ethernet_sw_interface_get_config (vnm, sw_if_index, &placeholder_flags, + &placeholder_unsup); if (subint == 0) { @@ -2235,6 +2234,17 @@ next_by_ethertype_register (next_by_ethertype_t * l3_next, return 0; } +void +ethernet_setup_node (vlib_main_t *vm, u32 node_index) +{ + vlib_node_t *n = vlib_get_node (vm, node_index); + pg_node_t *pn = pg_get_node (node_index); + + n->format_buffer = format_ethernet_header_with_length; + n->unformat_buffer = unformat_ethernet_header; + pn->unformat_edit = unformat_pg_ethernet_header; +} + void ethernet_input_init (vlib_main_t * vm, ethernet_main_t * em) {