From c7b430406cb572e318c5b7b805fd98bdae0d680a Mon Sep 17 00:00:00 2001 From: John Lo Date: Fri, 13 Apr 2018 16:46:22 -0400 Subject: [PATCH] Implement ip_probe_neighbor API Add API support similar to VPP CLI "ip probe-neighbor" except API call is asynch and will not wait, as the CLI does, for address resolution of probed neighbor. The API client can use the APIs want_ip4_arp_events or want_ip6_nd_events to get notified of the desired address resolution event. Change-Id: Ieab58abe75b5cc7f5185b3b91418b6362f8992d3 Signed-off-by: John Lo --- src/vat/api_format.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++- src/vnet/ip/ip.api | 41 ++++++++++++++++++++++++++-------- src/vnet/ip/ip_api.c | 31 ++++++++++++++++++++++++++ src/vpp/api/custom_dump.c | 16 +++++++++++++ 4 files changed, 135 insertions(+), 10 deletions(-) diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 019d095c40a..ceb074ccfe2 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -5569,6 +5569,7 @@ _(l2_interface_efp_filter_reply) \ _(l2_interface_vlan_tag_rewrite_reply) \ _(modify_vhost_user_if_reply) \ _(delete_vhost_user_if_reply) \ +_(ip_probe_neighbor_reply) \ _(want_ip4_arp_events_reply) \ _(want_ip6_nd_events_reply) \ _(want_l2_macs_events_reply) \ @@ -5811,9 +5812,10 @@ _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply) \ _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply) \ _(SHOW_VERSION_REPLY, show_version_reply) \ _(L2_FIB_TABLE_DETAILS, l2_fib_table_details) \ -_(VXLAN_GPE_ADD_DEL_TUNNEL_REPLY, vxlan_gpe_add_del_tunnel_reply) \ +_(VXLAN_GPE_ADD_DEL_TUNNEL_REPLY, vxlan_gpe_add_del_tunnel_reply) \ _(VXLAN_GPE_TUNNEL_DETAILS, vxlan_gpe_tunnel_details) \ _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply) \ +_(IP_PROBE_NEIGHBOR_REPLY, ip_probe_neighbor_reply) \ _(WANT_IP4_ARP_EVENTS_REPLY, want_ip4_arp_events_reply) \ _(IP4_ARP_EVENT, ip4_arp_event) \ _(WANT_IP6_ND_EVENTS_REPLY, want_ip6_nd_events_reply) \ @@ -14462,6 +14464,58 @@ api_interface_name_renumber (vat_main_t * vam) return ret; } +static int +api_ip_probe_neighbor (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ip_probe_neighbor_t *mp; + u8 int_set = 0; + u8 adr_set = 0; + u8 is_ipv6 = 0; + u8 dst_adr[16]; + u32 sw_if_index; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + int_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + int_set = 1; + else if (unformat (i, "address %U", unformat_ip4_address, dst_adr)) + adr_set = 1; + else if (unformat (i, "address %U", unformat_ip6_address, dst_adr)) + { + adr_set = 1; + is_ipv6 = 1; + } + else + break; + } + + if (int_set == 0) + { + errmsg ("missing interface"); + return -99; + } + + if (adr_set == 0) + { + errmsg ("missing addresses"); + return -99; + } + + M (IP_PROBE_NEIGHBOR, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->is_ipv6 = is_ipv6; + clib_memcpy (mp->dst_address, dst_adr, sizeof (dst_adr)); + + S (mp); + W (ret); + return ret; +} + static int api_want_ip4_arp_events (vat_main_t * vam) { @@ -23403,6 +23457,7 @@ _(interface_name_renumber, \ _(input_acl_set_interface, \ " | sw_if_index [ip4-table ] [ip6-table ]\n" \ " [l2-table ] [del]") \ +_(ip_probe_neighbor, "( | sw_if_index ) address ") \ _(want_ip4_arp_events, "address [del]") \ _(want_ip6_nd_events, "address [del]") \ _(want_l2_macs_events, "[disable] [learn-limit ] [scan-delay ] [max-entries ]") \ diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index 2ca2f56c58b..38024926ab7 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -19,7 +19,7 @@ called through a shared memory interface. */ -option version = "1.2.0"; +option version = "1.2.2"; import "vnet/fib/fib_types.api"; /** \brief Add / del table request @@ -650,12 +650,31 @@ autoreply define ip_source_and_port_range_check_interface_add_del u32 udp_out_vrf_id; }; -/** \brief Register for ip4 arp resolution events +/** \brief IP probe neighbor address on an interface by sending an + ARP request (for IP4) or ICMP6 Neighbor Solicitation (for IP6) + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param sw_if_index - interface index + @param dst_address - target IP address to send IP addr resolution request + @param is_ipv6 - [1|0] to indicate if address family is IPv[6|4] +*/ +autoreply define ip_probe_neighbor +{ + u32 client_index; + u32 context; + u32 sw_if_index; + u8 dst_address[16]; + u8 is_ipv6; +}; + +/** \brief Register for IP4 ARP resolution event on receing ARP reply or + MAC/IP info from ARP requests in L2 BDs @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param enable_disable - 1 => register for events, 0 => cancel registration @param pid - sender's pid - @param address - the exact ip4 address of interest + @param address - exact IP4 address of interested arp resolution event, or + 0 to get MAC/IP info from ARP requests in BDs */ autoreply define want_ip4_arp_events { @@ -666,13 +685,14 @@ autoreply define want_ip4_arp_events u32 address; }; -/** \brief Tell client about an ip4 arp resolution event +/** \brief Tell client about an IP4 ARP resolution event or + MAC/IP info from ARP requests in L2 BDs @param client_index - opaque cookie to identify the sender @param address - the exact ip4 address of interest @param pid - client pid registered to receive notification @param sw_if_index - interface which received ARP packet @param new_mac - the new mac address - @param mac_ip - 0: resolution event, 1: mac/ip binding in bd + @param mac_ip - 0: ARP resolution event, 1: MAC/IP info from L2 BDs */ define ip4_arp_event { @@ -689,12 +709,14 @@ service { events ip4_arp_event; }; -/** \brief Register for ip6 nd resolution events +/** \brief Register for IP6 ND resolution event on recieving NA reply + MAC/IP info from ICMP6 Neighbor Solicitation in L2 BDs @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @param enable_disable - 1 => register for events, 0 => cancel registration @param pid - sender's pid - @param address - the exact ip6 address of interest + @param address - the exact IP6 address of interested ND resolution event, or + 0 to get MAC/IP info from ICMP6 NS in L2 BDs. */ autoreply define want_ip6_nd_events { @@ -705,13 +727,14 @@ autoreply define want_ip6_nd_events u8 address[16]; }; -/** \brief Tell client about an ip6 nd resolution or mac/ip event +/** \brief Tell client about an IP6 ND resolution or + MAC/IP info from ICMP6 Neighbor Solicitation in L2 BDs. @param client_index - opaque cookie to identify the sender @param pid - client pid registered to receive notification @param sw_if_index - interface which received ARP packet @param address - the exact ip6 address of interest @param new_mac - the new mac address - @param mac_ip - 0: resolution event, 1: mac/ip binding in bd + @param mac_ip - 0: ND resolution event, 1: MAC/IP info from L2 BDs */ define ip6_nd_event { diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index 0b0a7a949e0..69ff719f3b9 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -76,6 +76,7 @@ _(IP_ADDRESS_DUMP, ip_address_dump) \ _(IP_DUMP, ip_dump) \ _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \ _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit) \ +_(IP_PROBE_NEIGHBOR, ip_probe_neighbor) \ _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events) \ _(WANT_IP6_ND_EVENTS, want_ip6_nd_events) \ _(WANT_IP6_RA_EVENTS, want_ip6_ra_events) \ @@ -2684,6 +2685,36 @@ static void REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY); } +static void +vl_api_ip_probe_neighbor_t_handler (vl_api_ip_probe_neighbor_t * mp) +{ + int rv = 0; + vlib_main_t *vm = vlib_get_main (); + vl_api_ip_probe_neighbor_reply_t *rmp; + clib_error_t *error; + + VALIDATE_SW_IF_INDEX (mp); + + u32 sw_if_index = ntohl (mp->sw_if_index); + + if (mp->is_ipv6) + error = ip6_probe_neighbor (vm, (ip6_address_t *) mp->dst_address, + sw_if_index); + else + error = ip4_probe_neighbor (vm, (ip4_address_t *) mp->dst_address, + sw_if_index); + + if (error) + { + clib_error_report (error); + rv = clib_error_get_code (error); + } + + BAD_SW_IF_INDEX_LABEL; + + REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY); +} + static int ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp) { diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c index ded6e7de337..9989bdc2c35 100644 --- a/src/vpp/api/custom_dump.c +++ b/src/vpp/api/custom_dump.c @@ -1996,6 +1996,21 @@ static void *vl_api_interface_name_renumber_t_print FINISH; } +static void *vl_api_ip_probe_neighbor_t_print + (vl_api_ip_probe_neighbor_t * mp, void *handle) +{ + u8 *s; + + s = format (0, "SCRIPT: ip_probe_neighbor "); + s = format (s, "sw_if_index %d ", ntohl (mp->sw_if_index)); + if (mp->is_ipv6) + s = format (s, "address %U ", format_ip6_address, &mp->dst_address); + else + s = format (s, "address %U ", format_ip4_address, &mp->dst_address); + + FINISH; +} + static void *vl_api_want_ip4_arp_events_t_print (vl_api_want_ip4_arp_events_t * mp, void *handle) { @@ -3515,6 +3530,7 @@ _(L2_FIB_TABLE_DUMP, l2_fib_table_dump) \ _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel) \ _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump) \ _(INTERFACE_NAME_RENUMBER, interface_name_renumber) \ +_(IP_PROBE_NEIGHBOR, ip_probe_neighbor) \ _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events) \ _(WANT_IP6_ND_EVENTS, want_ip6_nd_events) \ _(WANT_L2_MACS_EVENTS, want_l2_macs_events) \ -- 2.16.6