X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fbonding%2Fnode.c;h=66de1e4dd8069c40d0e01229e8f75bee80ce89ca;hb=HEAD;hp=df2da5c66fcd220855aceb44d42832c37201807f;hpb=5e5adb310c5ac19209d3d9fb03094c01b2a29610;p=vpp.git diff --git a/src/vnet/bonding/node.c b/src/vnet/bonding/node.c index df2da5c66fc..66de1e4dd80 100644 --- a/src/vnet/bonding/node.c +++ b/src/vnet/bonding/node.c @@ -21,11 +21,14 @@ #include #include +#ifndef CLIB_MARCH_VARIANT bond_main_t bond_main; +#endif /* CLIB_MARCH_VARIANT */ #define foreach_bond_input_error \ _(NONE, "no error") \ _(IF_DOWN, "interface down") \ + _(PASSIVE_IF, "traffic received on passive interface") \ _(PASS_THRU, "pass through (CDP, LLDP, slow protocols)") typedef enum @@ -36,7 +39,6 @@ typedef enum BOND_INPUT_N_ERROR, } bond_input_error_t; -#ifndef CLIB_MULTIARCH_VARIANT static char *bond_input_error_strings[] = { #define _(n,s) s, foreach_bond_input_error @@ -60,14 +62,12 @@ format_bond_input_trace (u8 * s, va_list * args) return s; } -#endif - typedef enum { BOND_INPUT_NEXT_DROP, BOND_INPUT_N_NEXT, -} l2output_next_t; +} bond_output_next_t; static_always_inline u8 packet_is_cdp (ethernet_header_t * eth) @@ -85,14 +85,17 @@ packet_is_cdp (ethernet_header_t * eth) (snap->oui[2] == 0x0C))); } -static inline u32 +static inline void bond_sw_if_idx_rewrite (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_buffer_t * b, u32 bond_sw_if_index) + vlib_buffer_t * b, u32 bond_sw_if_index, + u32 * n_rx_packets, u32 * n_rx_bytes) { u16 *ethertype_p, ethertype; ethernet_vlan_header_t *vlan; ethernet_header_t *eth = (ethernet_header_t *) vlib_buffer_get_current (b); + (*n_rx_packets)++; + *n_rx_bytes += b->current_length; ethertype = clib_mem_unaligned (ð->type, u16); if (!ethernet_frame_is_tagged (ntohs (ethertype))) { @@ -103,7 +106,7 @@ bond_sw_if_idx_rewrite (vlib_main_t * vm, vlib_node_runtime_t * node, { /* Change the physical interface to bond interface */ vnet_buffer (b)->sw_if_index[VLIB_RX] = bond_sw_if_index; - return 1; + return; } } else @@ -123,70 +126,87 @@ bond_sw_if_idx_rewrite (vlib_main_t * vm, vlib_node_runtime_t * node, { /* Change the physical interface to bond interface */ vnet_buffer (b)->sw_if_index[VLIB_RX] = bond_sw_if_index; - return 1; + return; } } vlib_error_count (vm, node->node_index, BOND_INPUT_ERROR_PASS_THRU, 1); - return 0; + return; } static inline void bond_update_next (vlib_main_t * vm, vlib_node_runtime_t * node, - u32 * last_slave_sw_if_index, u32 slave_sw_if_index, - u32 packet_count, + u32 * last_member_sw_if_index, u32 member_sw_if_index, u32 * bond_sw_if_index, vlib_buffer_t * b, u32 * next_index, vlib_error_t * error) { - u16 thread_index = vlib_get_thread_index (); - slave_if_t *sif; + member_if_t *mif; bond_if_t *bif; - if (PREDICT_TRUE (*last_slave_sw_if_index == slave_sw_if_index)) - return; + *next_index = BOND_INPUT_NEXT_DROP; + *error = 0; - if (packet_count) - vlib_increment_simple_counter (vnet_main.interface_main.sw_if_counters + - VNET_INTERFACE_COUNTER_RX, thread_index, - *last_slave_sw_if_index, packet_count); + if (PREDICT_TRUE (*last_member_sw_if_index == member_sw_if_index)) + goto next; - *last_slave_sw_if_index = slave_sw_if_index; - *next_index = BOND_INPUT_NEXT_DROP; + *last_member_sw_if_index = member_sw_if_index; - sif = bond_get_slave_by_sw_if_index (slave_sw_if_index); - ASSERT (sif); + mif = bond_get_member_by_sw_if_index (member_sw_if_index); + ALWAYS_ASSERT (mif); - bif = bond_get_master_by_dev_instance (sif->bif_dev_instance); + bif = bond_get_bond_if_by_dev_instance (mif->bif_dev_instance); - ASSERT (bif); - ASSERT (vec_len (bif->slaves)); + ALWAYS_ASSERT (bif); + ASSERT (vec_len (bif->members)); - if (PREDICT_TRUE (bif->admin_up == 0)) + if (PREDICT_FALSE (bif->admin_up == 0)) { - *bond_sw_if_index = slave_sw_if_index; + *bond_sw_if_index = member_sw_if_index; *error = node->errors[BOND_INPUT_ERROR_IF_DOWN]; } + if (PREDICT_FALSE ((bif->mode == BOND_MODE_ACTIVE_BACKUP) && + vec_len (bif->active_members) && + (member_sw_if_index != bif->active_members[0]))) + { + *bond_sw_if_index = member_sw_if_index; + *error = node->errors[BOND_INPUT_ERROR_PASSIVE_IF]; + return; + } + *bond_sw_if_index = bif->sw_if_index; - *error = 0; - vnet_feature_next ( /* not used */ 0, next_index, b); + +next: + vnet_feature_next (next_index, b); +} + +static_always_inline void +bond_update_next_x4 (vlib_buffer_t * b0, vlib_buffer_t * b1, + vlib_buffer_t * b2, vlib_buffer_t * b3) +{ + u32 tmp0, tmp1, tmp2, tmp3; + + tmp0 = tmp1 = tmp2 = tmp3 = BOND_INPUT_NEXT_DROP; + vnet_feature_next (&tmp0, b0); + vnet_feature_next (&tmp1, b1); + vnet_feature_next (&tmp2, b2); + vnet_feature_next (&tmp3, b3); } -uword CLIB_CPU_OPTIMIZED -CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +VLIB_NODE_FN (bond_input_node) (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) { - u16 thread_index = vlib_get_thread_index (); + u16 thread_index = vm->thread_index; u32 *from, n_left; vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; u32 sw_if_indices[VLIB_FRAME_SIZE], *sw_if_index; u16 nexts[VLIB_FRAME_SIZE], *next; - u32 last_slave_sw_if_index = ~0; + u32 last_member_sw_if_index = ~0; u32 bond_sw_if_index = 0; vlib_error_t error = 0; u32 next_index = 0; - u32 cnt = 0; + u32 n_rx_bytes = 0, n_rx_packets = 0; /* Vector of buffer / pkt indices we're supposed to process */ from = vlib_frame_vector_args (frame); @@ -206,14 +226,10 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm, /* Prefetch next iteration */ if (PREDICT_TRUE (n_left >= 16)) { - CLIB_PREFETCH (vlib_buffer_get_current (b[8]), - CLIB_CACHE_LINE_BYTES, LOAD); - CLIB_PREFETCH (vlib_buffer_get_current (b[9]), - CLIB_CACHE_LINE_BYTES, LOAD); - CLIB_PREFETCH (vlib_buffer_get_current (b[10]), - CLIB_CACHE_LINE_BYTES, LOAD); - CLIB_PREFETCH (vlib_buffer_get_current (b[11]), - CLIB_CACHE_LINE_BYTES, LOAD); + vlib_prefetch_buffer_data (b[8], LOAD); + vlib_prefetch_buffer_data (b[9], LOAD); + vlib_prefetch_buffer_data (b[10], LOAD); + vlib_prefetch_buffer_data (b[11], LOAD); vlib_prefetch_buffer_header (b[12], LOAD); vlib_prefetch_buffer_header (b[13], LOAD); @@ -226,13 +242,29 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm, sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_RX]; sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_RX]; - x |= sw_if_index[0] ^ last_slave_sw_if_index; - x |= sw_if_index[1] ^ last_slave_sw_if_index; - x |= sw_if_index[2] ^ last_slave_sw_if_index; - x |= sw_if_index[3] ^ last_slave_sw_if_index; + x |= sw_if_index[0] ^ last_member_sw_if_index; + x |= sw_if_index[1] ^ last_member_sw_if_index; + x |= sw_if_index[2] ^ last_member_sw_if_index; + x |= sw_if_index[3] ^ last_member_sw_if_index; if (PREDICT_TRUE (x == 0)) { + /* + * Optimize to call update_next only if there is a feature arc + * after bond-input. Test feature count greater than 1 because + * bond-input itself is a feature arc for this member interface. + */ + ASSERT ((vnet_buffer (b[0])->feature_arc_index == + vnet_buffer (b[1])->feature_arc_index) && + (vnet_buffer (b[0])->feature_arc_index == + vnet_buffer (b[2])->feature_arc_index) && + (vnet_buffer (b[0])->feature_arc_index == + vnet_buffer (b[3])->feature_arc_index)); + if (PREDICT_FALSE (vnet_get_feature_count + (vnet_buffer (b[0])->feature_arc_index, + last_member_sw_if_index) > 1)) + bond_update_next_x4 (b[0], b[1], b[2], b[3]); + next[0] = next[1] = next[2] = next[3] = next_index; if (next_index == BOND_INPUT_NEXT_DROP) { @@ -243,61 +275,59 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm, } else { - cnt += - bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index); - cnt += - bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index); - cnt += - bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index); - cnt += - bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index); + bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index, + &n_rx_packets, &n_rx_bytes); + bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index, + &n_rx_packets, &n_rx_bytes); + bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index, + &n_rx_packets, &n_rx_bytes); + bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index, + &n_rx_packets, &n_rx_bytes); } } else { - - bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[0], - cnt, &bond_sw_if_index, b[0], &next_index, - &error); + bond_update_next (vm, node, &last_member_sw_if_index, + sw_if_index[0], &bond_sw_if_index, b[0], + &next_index, &error); next[0] = next_index; if (next_index == BOND_INPUT_NEXT_DROP) b[0]->error = error; else - cnt += bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index); + bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index, + &n_rx_packets, &n_rx_bytes); - bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[1], - cnt, &bond_sw_if_index, b[1], &next_index, - &error); + bond_update_next (vm, node, &last_member_sw_if_index, + sw_if_index[1], &bond_sw_if_index, b[1], + &next_index, &error); next[1] = next_index; if (next_index == BOND_INPUT_NEXT_DROP) b[1]->error = error; else - cnt += bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index); + bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index, + &n_rx_packets, &n_rx_bytes); - bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[2], - cnt, &bond_sw_if_index, b[2], &next_index, - &error); + bond_update_next (vm, node, &last_member_sw_if_index, + sw_if_index[2], &bond_sw_if_index, b[2], + &next_index, &error); next[2] = next_index; if (next_index == BOND_INPUT_NEXT_DROP) b[2]->error = error; else - cnt += bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index); + bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index, + &n_rx_packets, &n_rx_bytes); - bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[3], - cnt, &bond_sw_if_index, b[3], &next_index, - &error); + bond_update_next (vm, node, &last_member_sw_if_index, + sw_if_index[3], &bond_sw_if_index, b[3], + &next_index, &error); next[3] = next_index; if (next_index == BOND_INPUT_NEXT_DROP) b[3]->error = error; else - cnt += bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index); + bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index, + &n_rx_packets, &n_rx_bytes); } - VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]); - VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[1]); - VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[2]); - VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[3]); - /* next */ n_left -= 4; b += 4; @@ -308,15 +338,14 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm, while (n_left) { sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX]; - bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[0], - cnt, &bond_sw_if_index, b[0], &next_index, &error); + bond_update_next (vm, node, &last_member_sw_if_index, sw_if_index[0], + &bond_sw_if_index, b[0], &next_index, &error); next[0] = next_index; if (next_index == BOND_INPUT_NEXT_DROP) b[0]->error = error; else - bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index); - - VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]); + bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index, + &n_rx_packets, &n_rx_bytes); /* next */ n_left -= 1; @@ -330,35 +359,30 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm, n_left = frame->n_vectors; /* number of packets to process */ b = bufs; sw_if_index = sw_if_indices; - next = nexts; bond_packet_trace_t *t0; - uword n_trace = vlib_get_trace_count (vm, node); - while (n_left && n_trace) + while (n_left) { if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED)) { - vlib_trace_buffer (vm, node, next[0], b[0], - 0 /* follow_chain */ ); - vlib_set_trace_count (vm, node, --n_trace); t0 = vlib_add_trace (vm, node, b[0], sizeof (*t0)); t0->sw_if_index = sw_if_index[0]; - clib_memcpy (&t0->ethernet, vlib_buffer_get_current (b[0]), - sizeof (ethernet_header_t)); + clib_memcpy_fast (&t0->ethernet, vlib_buffer_get_current (b[0]), + sizeof (ethernet_header_t)); t0->bond_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_RX]; } /* next */ n_left--; b++; sw_if_index++; - next++; } } /* increase rx counters */ - vlib_increment_simple_counter - (vnet_main.interface_main.sw_if_counters + - VNET_INTERFACE_COUNTER_RX, thread_index, bond_sw_if_index, cnt); + vlib_increment_combined_counter + (vnet_main.interface_main.combined_sw_if_counters + + VNET_INTERFACE_COUNTER_RX, thread_index, bond_sw_if_index, n_rx_packets, + n_rx_bytes); vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors); vlib_node_increment_counter (vm, bond_input_node.index, @@ -367,16 +391,13 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm, return frame->n_vectors; } -#ifndef CLIB_MULTIARCH_VARIANT static clib_error_t * bond_input_init (vlib_main_t * vm) { return 0; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (bond_input_node) = { - .function = bond_input_fn, .name = "bond-input", .vector_size = sizeof (u32), .format_buffer = format_ethernet_header_with_length, @@ -391,20 +412,6 @@ VLIB_REGISTER_NODE (bond_input_node) = { } }; -#if __x86_64__ -vlib_node_function_t __clib_weak bond_input_fn_avx512; -vlib_node_function_t __clib_weak bond_input_fn_avx2; -static void __clib_constructor -bond_input_multiarch_select (void) -{ - if (bond_input_fn_avx512 && clib_cpu_supports_avx512f ()) - bond_input_node.function = bond_input_fn_avx512; - else if (bond_input_fn_avx2 && clib_cpu_supports_avx2 ()) - bond_input_node.function = bond_input_fn_avx2; -} -#endif - - VLIB_INIT_FUNCTION (bond_input_init); VNET_FEATURE_INIT (bond_input, static) = @@ -413,33 +420,27 @@ VNET_FEATURE_INIT (bond_input, static) = .node_name = "bond-input", .runs_before = VNET_FEATURES ("ethernet-input"), }; -/* *INDENT-ON* */ static clib_error_t * bond_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) { bond_main_t *bm = &bond_main; - slave_if_t *sif; + member_if_t *mif; vlib_main_t *vm = bm->vlib_main; - sif = bond_get_slave_by_sw_if_index (sw_if_index); - if (sif) + mif = bond_get_member_by_sw_if_index (sw_if_index); + if (mif) { - sif->port_enabled = flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP; - if (sif->port_enabled == 0) - { - if (sif->lacp_enabled == 0) - { - bond_disable_collecting_distributing (vm, sif); - } - } + if (mif->lacp_enabled) + return 0; + + /* port_enabled is both admin up and hw link up */ + mif->port_enabled = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) && + vnet_sw_interface_is_link_up (vnm, sw_if_index)); + if (mif->port_enabled == 0) + bond_disable_collecting_distributing (vm, mif); else - { - if (sif->lacp_enabled == 0) - { - bond_enable_collecting_distributing (vm, sif); - } - } + bond_enable_collecting_distributing (vm, mif); } return 0; @@ -451,35 +452,31 @@ static clib_error_t * bond_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) { bond_main_t *bm = &bond_main; - slave_if_t *sif; + member_if_t *mif; vnet_sw_interface_t *sw; vlib_main_t *vm = bm->vlib_main; sw = vnet_get_hw_sw_interface (vnm, hw_if_index); - sif = bond_get_slave_by_sw_if_index (sw->sw_if_index); - if (sif) + mif = bond_get_member_by_sw_if_index (sw->sw_if_index); + if (mif) { - if (!(flags & VNET_HW_INTERFACE_FLAG_LINK_UP)) - { - if (sif->lacp_enabled == 0) - { - bond_disable_collecting_distributing (vm, sif); - } - } + if (mif->lacp_enabled) + return 0; + + /* port_enabled is both admin up and hw link up */ + mif->port_enabled = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) && + vnet_sw_interface_is_admin_up (vnm, + sw->sw_if_index)); + if (mif->port_enabled == 0) + bond_disable_collecting_distributing (vm, mif); else - { - if (sif->lacp_enabled == 0) - { - bond_enable_collecting_distributing (vm, sif); - } - } + bond_enable_collecting_distributing (vm, mif); } return 0; } VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (bond_hw_interface_up_down); -#endif /* * fd.io coding-style-patch-verification: ON