X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fbfd%2Fbfd_udp.c;h=0a9106e78e5964e611c056e8cdf733ff58209143;hb=cbe25aab3be72154f2c706c39eeba6a77f34450f;hp=041e5840e0b866408371146b8997dc6db7ad7bbf;hpb=6434430fd593840e463fff0acb8f6b1676fa7bba;p=vpp.git diff --git a/src/vnet/bfd/bfd_udp.c b/src/vnet/bfd/bfd_udp.c index 041e5840e0b..0a9106e78e5 100644 --- a/src/vnet/bfd/bfd_udp.c +++ b/src/vnet/bfd/bfd_udp.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -59,8 +60,16 @@ typedef struct u32 ip4_rewrite_idx; /* node index of "ip6-rewrite" node */ u32 ip6_rewrite_idx; + /* node index of "ip4-midchain" node */ + u32 ip4_midchain_idx; + /* node index of "ip6-midchain" node */ + u32 ip6_midchain_idx; /* log class */ vlib_log_class_t log_class; + /* number of active udp4 sessions */ + u32 udp4_sessions_count; + /* number of active udp6 sessions */ + u32 udp6_sessions_count; } bfd_udp_main_t; static vlib_node_registration_t bfd_udp4_input_node; @@ -74,7 +83,7 @@ vnet_api_error_t bfd_udp_set_echo_source (u32 sw_if_index) { vnet_sw_interface_t *sw_if = - vnet_get_sw_interface_safe (bfd_udp_main.vnet_main, sw_if_index); + vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index); if (sw_if) { bfd_udp_main.echo_source_sw_if_index = sw_if_index; @@ -106,8 +115,8 @@ bfd_udp_is_echo_available (bfd_transport_e transport) * pick an unused address from that subnet */ vnet_sw_interface_t *sw_if = - vnet_get_sw_interface_safe (bfd_udp_main.vnet_main, - bfd_udp_main.echo_source_sw_if_index); + vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, + bfd_udp_main.echo_source_sw_if_index); if (sw_if && sw_if->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) { if (BFD_TRANSPORT_UDP4 == transport) @@ -375,8 +384,14 @@ bfd_create_frame_to_next_node (vlib_main_t * vm, u32 bi, u32 next_node) int bfd_udp_calc_next_node (const struct bfd_session_s *bs, u32 * next_node) { + vnet_main_t *vnm = vnet_get_main (); const bfd_udp_session_t *bus = &bs->udp; ip_adjacency_t *adj = adj_get (bus->adj_index); + + /* don't try to send the buffer if the interface is not up */ + if (!vnet_sw_interface_is_up (vnm, bus->key.sw_if_index)) + return 0; + switch (adj->lookup_next_index) { case IP_LOOKUP_NEXT_ARP: @@ -401,6 +416,17 @@ bfd_udp_calc_next_node (const struct bfd_session_s *bs, u32 * next_node) return 1; } break; + case IP_LOOKUP_NEXT_MIDCHAIN: + switch (bs->transport) + { + case BFD_TRANSPORT_UDP4: + *next_node = bfd_udp_main.ip4_midchain_idx; + return 1; + case BFD_TRANSPORT_UDP6: + *next_node = bfd_udp_main.ip6_midchain_idx; + return 1; + } + break; default: /* drop */ break; @@ -457,8 +483,8 @@ bfd_udp_key_init (bfd_udp_key_t * key, u32 sw_if_index, } static vnet_api_error_t -bfd_udp_add_session_internal (bfd_udp_main_t * bum, u32 sw_if_index, - u32 desired_min_tx_usec, +bfd_udp_add_session_internal (vlib_main_t * vm, bfd_udp_main_t * bum, + u32 sw_if_index, u32 desired_min_tx_usec, u32 required_min_rx_usec, u8 detect_mult, const ip46_address_t * local_addr, const ip46_address_t * peer_addr, @@ -503,6 +529,14 @@ bfd_udp_add_session_internal (bfd_udp_main_t * bum, u32 sw_if_index, BFD_DBG ("adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, VNET_LINK_IP4, %U, %d) " "returns %d", format_ip46_address, &key->peer_addr, IP46_TYPE_ANY, key->sw_if_index, bus->adj_index); + ++bum->udp4_sessions_count; + if (1 == bum->udp4_sessions_count) + { + udp_register_dst_port (vm, UDP_DST_PORT_bfd4, + bfd_udp4_input_node.index, 1); + udp_register_dst_port (vm, UDP_DST_PORT_bfd_echo4, + bfd_udp_echo4_input_node.index, 1); + } } else { @@ -512,6 +546,14 @@ bfd_udp_add_session_internal (bfd_udp_main_t * bum, u32 sw_if_index, BFD_DBG ("adj_nbr_add_or_lock(FIB_PROTOCOL_IP6, VNET_LINK_IP6, %U, %d) " "returns %d", format_ip46_address, &key->peer_addr, IP46_TYPE_ANY, key->sw_if_index, bus->adj_index); + ++bum->udp6_sessions_count; + if (1 == bum->udp6_sessions_count) + { + udp_register_dst_port (vm, UDP_DST_PORT_bfd6, + bfd_udp6_input_node.index, 0); + udp_register_dst_port (vm, UDP_DST_PORT_bfd_echo6, + bfd_udp_echo6_input_node.index, 0); + } } *bs_out = bs; return bfd_session_set_params (bum->bfd_main, bs, desired_min_tx_usec, @@ -525,7 +567,7 @@ bfd_udp_validate_api_input (u32 sw_if_index, { bfd_udp_main_t *bum = &bfd_udp_main; vnet_sw_interface_t *sw_if = - vnet_get_sw_interface_safe (bfd_udp_main.vnet_main, sw_if_index); + vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index); u8 local_ip_valid = 0; ip_interface_address_t *ia = NULL; if (!sw_if) @@ -567,21 +609,35 @@ bfd_udp_validate_api_input (u32 sw_if_index, "IP family mismatch (local is ipv6, peer is ipv4)"); return VNET_API_ERROR_INVALID_ARGUMENT; } - ip6_main_t *im = &ip6_main; - /* *INDENT-OFF* */ - foreach_ip_interface_address ( - &im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({ - ip6_address_t *x = - ip_interface_address_get_address (&im->lookup_main, ia); - if (local_addr->ip6.as_u64[0] == x->as_u64[0] && - local_addr->ip6.as_u64[1] == x->as_u64[1]) - { - /* valid address for this interface */ - local_ip_valid = 1; - break; - } - })); - /* *INDENT-ON* */ + + if (ip6_address_is_link_local_unicast (&local_addr->ip6)) + { + const ip6_address_t *ll_addr; + ll_addr = ip6_get_link_local_address (sw_if_index); + if (ip6_address_is_equal (ll_addr, &local_addr->ip6)) + { + /* valid address for this interface */ + local_ip_valid = 1; + } + } + else + { + ip6_main_t *im = &ip6_main; + /* *INDENT-OFF* */ + foreach_ip_interface_address ( + &im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({ + ip6_address_t *x = + ip_interface_address_get_address (&im->lookup_main, ia); + if (local_addr->ip6.as_u64[0] == x->as_u64[0] && + local_addr->ip6.as_u64[1] == x->as_u64[1]) + { + /* valid address for this interface */ + local_ip_valid = 1; + break; + } + })); + /* *INDENT-ON* */ + } } if (!local_ip_valid) @@ -654,12 +710,31 @@ bfd_api_verify_common (u32 sw_if_index, u32 desired_min_tx_usec, } static void -bfd_udp_del_session_internal (bfd_session_t * bs) +bfd_udp_del_session_internal (vlib_main_t * vm, bfd_session_t * bs) { bfd_udp_main_t *bum = &bfd_udp_main; BFD_DBG ("free bfd-udp session, bs_idx=%d", bs->bs_idx); mhash_unset (&bum->bfd_session_idx_by_bfd_key, &bs->udp.key, NULL); adj_unlock (bs->udp.adj_index); + switch (bs->transport) + { + case BFD_TRANSPORT_UDP4: + --bum->udp4_sessions_count; + if (!bum->udp4_sessions_count) + { + udp_unregister_dst_port (vm, UDP_DST_PORT_bfd4, 1); + udp_unregister_dst_port (vm, UDP_DST_PORT_bfd_echo4, 1); + } + break; + case BFD_TRANSPORT_UDP6: + --bum->udp6_sessions_count; + if (!bum->udp6_sessions_count) + { + udp_unregister_dst_port (vm, UDP_DST_PORT_bfd6, 0); + udp_unregister_dst_port (vm, UDP_DST_PORT_bfd_echo6, 0); + } + break; + } bfd_put_session (bum->bfd_main, bs); } @@ -681,8 +756,8 @@ bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr, if (!rv) { rv = - bfd_udp_add_session_internal (&bfd_udp_main, sw_if_index, - desired_min_tx_usec, + bfd_udp_add_session_internal (vlib_get_main (), &bfd_udp_main, + sw_if_index, desired_min_tx_usec, required_min_rx_usec, detect_mult, local_addr, peer_addr, &bs); } @@ -698,7 +773,7 @@ bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr, #endif if (rv) { - bfd_udp_del_session_internal (bs); + bfd_udp_del_session_internal (vlib_get_main (), bs); } } if (!rv) @@ -753,7 +828,7 @@ bfd_udp_del_session (u32 sw_if_index, bfd_unlock (bm); return rv; } - bfd_udp_del_session_internal (bs); + bfd_udp_del_session_internal (vlib_get_main (), bs); bfd_unlock (bm); return 0; } @@ -837,6 +912,7 @@ typedef enum BFD_UDP_INPUT_NEXT_NORMAL, BFD_UDP_INPUT_NEXT_REPLY_ARP, BFD_UDP_INPUT_NEXT_REPLY_REWRITE, + BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN, BFD_UDP_INPUT_N_NEXT, } bfd_udp_input_next_t; @@ -863,6 +939,14 @@ typedef enum BFD_UDP_N_ERROR, } bfd_udp_error_t; +typedef enum +{ + BFD_UDP_ECHO_INPUT_NEXT_NORMAL, + BFD_UDP_ECHO_INPUT_NEXT_REPLY_ARP, + BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE, + BFD_UDP_ECHO_INPUT_N_NEXT, +} bfd_udp_echo_input_next_t; + /* Packet counters - BFD ECHO packets */ #define foreach_bfd_udp_echo_error(F) \ F (NONE, "good bfd echo packets (processed)") \ @@ -1261,6 +1345,9 @@ bfd_udp_input (vlib_main_t * vm, vlib_node_runtime_t * rt, case IP_LOOKUP_NEXT_REWRITE: next0 = BFD_UDP_INPUT_NEXT_REPLY_REWRITE; break; + case IP_LOOKUP_NEXT_MIDCHAIN: + next0 = BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN; + break; default: /* drop */ break; @@ -1304,6 +1391,7 @@ VLIB_REGISTER_NODE (bfd_udp4_input_node, static) = { [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop", [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip4-arp", [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup", + [BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN] = "ip4-midchain", }, }; /* *INDENT-ON* */ @@ -1332,6 +1420,7 @@ VLIB_REGISTER_NODE (bfd_udp6_input_node, static) = { [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop", [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor", [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup", + [BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN] = "ip6-midchain", }, }; /* *INDENT-ON* */ @@ -1375,7 +1464,7 @@ bfd_udp_echo_input (vlib_main_t * vm, vlib_node_runtime_t * rt, if (bfd_consume_echo_pkt (bfd_udp_main.bfd_main, b0)) { b0->error = rt->errors[BFD_UDP_ERROR_NONE]; - next0 = BFD_UDP_INPUT_NEXT_NORMAL; + next0 = BFD_UDP_ECHO_INPUT_NEXT_NORMAL; } else { @@ -1391,7 +1480,7 @@ bfd_udp_echo_input (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_node_increment_counter (vm, bfd_udp_echo4_input_node.index, b0->error, 1); } - next0 = BFD_UDP_INPUT_NEXT_REPLY_REWRITE; + next0 = BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE; } bfd_unlock (bm); @@ -1442,12 +1531,12 @@ VLIB_REGISTER_NODE (bfd_udp_echo4_input_node, static) = { .format_trace = bfd_echo_input_format_trace, - .n_next_nodes = BFD_UDP_INPUT_N_NEXT, + .n_next_nodes = BFD_UDP_ECHO_INPUT_N_NEXT, .next_nodes = { - [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop", - [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip4-arp", - [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup", + [BFD_UDP_ECHO_INPUT_NEXT_NORMAL] = "error-drop", + [BFD_UDP_ECHO_INPUT_NEXT_REPLY_ARP] = "ip4-arp", + [BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup", }, }; /* *INDENT-ON* */ @@ -1471,12 +1560,12 @@ VLIB_REGISTER_NODE (bfd_udp_echo6_input_node, static) = { .format_trace = bfd_echo_input_format_trace, - .n_next_nodes = BFD_UDP_INPUT_N_NEXT, + .n_next_nodes = BFD_UDP_ECHO_INPUT_N_NEXT, .next_nodes = { - [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop", - [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor", - [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup", + [BFD_UDP_ECHO_INPUT_NEXT_NORMAL] = "error-drop", + [BFD_UDP_ECHO_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor", + [BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup", }, }; @@ -1511,7 +1600,7 @@ bfd_udp_sw_if_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_create) "removal of sw_if_index=%u forces removal of bfd session " "with bs_idx=%u", sw_if_index, (*bs)->bs_idx); bfd_session_set_flags (*bs, 0); - bfd_udp_del_session_internal (*bs); + bfd_udp_del_session_internal (vlib_get_main (), *bs); } return 0; } @@ -1524,16 +1613,12 @@ VNET_SW_INTERFACE_ADD_DEL_FUNCTION (bfd_udp_sw_if_add_del); static clib_error_t * bfd_udp_init (vlib_main_t * vm) { + bfd_udp_main.udp4_sessions_count = 0; + bfd_udp_main.udp6_sessions_count = 0; mhash_init (&bfd_udp_main.bfd_session_idx_by_bfd_key, sizeof (uword), sizeof (bfd_udp_key_t)); bfd_udp_main.bfd_main = &bfd_main; bfd_udp_main.vnet_main = vnet_get_main (); - udp_register_dst_port (vm, UDP_DST_PORT_bfd4, bfd_udp4_input_node.index, 1); - udp_register_dst_port (vm, UDP_DST_PORT_bfd6, bfd_udp6_input_node.index, 0); - udp_register_dst_port (vm, UDP_DST_PORT_bfd_echo4, - bfd_udp_echo4_input_node.index, 1); - udp_register_dst_port (vm, UDP_DST_PORT_bfd_echo6, - bfd_udp_echo6_input_node.index, 0); vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "ip4-arp"); ASSERT (node); bfd_udp_main.ip4_arp_idx = node->index; @@ -1546,6 +1631,12 @@ bfd_udp_init (vlib_main_t * vm) node = vlib_get_node_by_name (vm, (u8 *) "ip6-rewrite"); ASSERT (node); bfd_udp_main.ip6_rewrite_idx = node->index; + node = vlib_get_node_by_name (vm, (u8 *) "ip4-midchain"); + ASSERT (node); + bfd_udp_main.ip4_midchain_idx = node->index; + node = vlib_get_node_by_name (vm, (u8 *) "ip6-midchain"); + ASSERT (node); + bfd_udp_main.ip6_midchain_idx = node->index; bfd_udp_main.log_class = vlib_log_register_class ("bfd", "udp"); vlib_log_debug (bfd_udp_main.log_class, "initialized");