From b3b2de71ceea0cc7ce18f89cc8180ed4a42e355d Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Wed, 8 Mar 2017 05:17:22 -0800 Subject: IMplementation for option to not create a FIB table entry when adding a neighbor entry Change-Id: I952039e101031ee6a06e63f4c73d8eb359423e1a Signed-off-by: Neale Ranns --- src/vnet/ethernet/arp.c | 61 +++++++++++++++++++++++++----------------- src/vnet/ethernet/arp_packet.h | 11 +++++--- src/vnet/ethernet/ethernet.h | 3 ++- src/vnet/ip/ip6_neighbor.c | 59 +++++++++++++++++++++++++--------------- src/vnet/ip/ip6_neighbor.h | 14 +++++++--- src/vnet/ip/ip_api.c | 6 +++-- 6 files changed, 98 insertions(+), 56 deletions(-) (limited to 'src/vnet') diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index 222415b0..d8ae8443 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -100,6 +100,7 @@ typedef struct u32 sw_if_index; ethernet_arp_ip4_over_ethernet_address_t a; int is_static; + int is_no_fib_entry; int flags; #define ETHERNET_ARP_ARGS_REMOVE (1<<0) #define ETHERNET_ARP_ARGS_FLUSH (1<<1) @@ -254,6 +255,9 @@ format_ethernet_arp_ip4_entry (u8 * s, va_list * va) if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC) flags = format (flags, "D"); + if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_NO_FIB_ENTRY) + flags = format (flags, "N"); + s = format (s, "%=12U%=16U%=6s%=20U%=24U", format_vlib_cpu_time, vnm->vlib_main, e->cpu_time_last_updated, format_ip4_address, &e->ip4_address, @@ -525,6 +529,7 @@ vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm, ethernet_arp_interface_t *arp_int; int is_static = args->is_static; u32 sw_if_index = args->sw_if_index; + int is_no_fib_entry = args->is_no_fib_entry; vec_validate (am->ethernet_arp_by_sw_if_index, sw_if_index); @@ -546,16 +551,6 @@ vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm, if (make_new_arp_cache_entry) { - fib_prefix_t pfx = { - .fp_len = 32, - .fp_proto = FIB_PROTOCOL_IP4, - .fp_addr = { - .ip4 = a->ip4, - } - , - }; - u32 fib_index; - pool_get (am->ip4_entry_pool, e); if (NULL == arp_int->arp_entries) @@ -570,17 +565,25 @@ vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm, clib_memcpy (e->ethernet_address, a->ethernet, sizeof (e->ethernet_address)); - fib_index = ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index); - e->fib_entry_index = - fib_table_entry_update_one_path (fib_index, - &pfx, - FIB_SOURCE_ADJ, - FIB_ENTRY_FLAG_ATTACHED, - FIB_PROTOCOL_IP4, - &pfx.fp_addr, - e->sw_if_index, - ~0, - 1, NULL, FIB_ROUTE_PATH_FLAG_NONE); + if (!is_no_fib_entry) + { + fib_prefix_t pfx = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr.ip4 = a->ip4, + }; + u32 fib_index; + + fib_index = + ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index); + e->fib_entry_index = + fib_table_entry_update_one_path (fib_index, &pfx, FIB_SOURCE_ADJ, + FIB_ENTRY_FLAG_ATTACHED, + FIB_PROTOCOL_IP4, &pfx.fp_addr, + e->sw_if_index, ~0, 1, NULL, + FIB_ROUTE_PATH_FLAG_NONE); + e->flags |= ETHERNET_ARP_IP4_ENTRY_FLAG_NO_FIB_ENTRY; + } } else { @@ -1142,7 +1145,7 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index0, &arp0->ip4_over_ethernet[0], - 0 /* is_static */ ); + 0 /* is_static */ , 0); error0 = ETHERNET_ARP_ERROR_l3_src_address_learned; } @@ -1658,6 +1661,8 @@ arp_entry_free (ethernet_arp_interface_t * eai, ethernet_arp_ip4_entry_t * e) { ethernet_arp_main_t *am = ðernet_arp_main; + /* it's safe to delete the ADJ source on the FIB entry, even if it + * was added */ fib_table_entry_delete_index (e->fib_entry_index, FIB_SOURCE_ADJ); hash_unset (eai->arp_entries, e->ip4_address.as_u32); pool_put (am->ip4_entry_pool, e); @@ -1828,13 +1833,15 @@ increment_ip4_and_mac_address (ethernet_arp_ip4_over_ethernet_address_t * a) int vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm, - u32 sw_if_index, void *a_arg, int is_static) + u32 sw_if_index, void *a_arg, + int is_static, int is_no_fib_entry) { ethernet_arp_ip4_over_ethernet_address_t *a = a_arg; vnet_arp_set_ip4_over_ethernet_rpc_args_t args; args.sw_if_index = sw_if_index; args.is_static = is_static; + args.is_no_fib_entry = is_no_fib_entry; args.flags = 0; clib_memcpy (&args.a, a, sizeof (*a)); @@ -1931,6 +1938,7 @@ ip_arp_add_del_command_fn (vlib_main_t * vm, u32 fib_index = 0; u32 fib_id; int is_static = 0; + int is_no_fib_entry = 0; int is_proxy = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) @@ -1948,6 +1956,9 @@ ip_arp_add_del_command_fn (vlib_main_t * vm, else if (unformat (input, "static")) is_static = 1; + else if (unformat (input, "no-fib-entry")) + is_no_fib_entry = 1; + else if (unformat (input, "count %d", &count)) ; @@ -1991,7 +2002,7 @@ ip_arp_add_del_command_fn (vlib_main_t * vm, 1 /* type */ , 0 /* data */ ); vnet_arp_set_ip4_over_ethernet - (vnm, sw_if_index, &addr, is_static); + (vnm, sw_if_index, &addr, is_static, is_no_fib_entry); vlib_process_wait_for_event (vm); event_type = vlib_process_get_events (vm, &event_data); @@ -2046,7 +2057,7 @@ ip_arp_add_del_command_fn (vlib_main_t * vm, VLIB_CLI_COMMAND (ip_arp_add_del_command, static) = { .path = "set ip arp", .short_help = - "set ip arp [del] [static] [count ] [fib-id ] [proxy - ]", + "set ip arp [del] [static] [no-fib-entry] [count ] [fib-id ] [proxy - ]", .function = ip_arp_add_del_command_fn, }; /* *INDENT-ON* */ diff --git a/src/vnet/ethernet/arp_packet.h b/src/vnet/ethernet/arp_packet.h index e762ffa4..17e64f43 100644 --- a/src/vnet/ethernet/arp_packet.h +++ b/src/vnet/ethernet/arp_packet.h @@ -140,6 +140,13 @@ typedef struct }; } ethernet_arp_header_t; +typedef enum ethernet_arp_entry_flags_t_ +{ + ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC = (1 << 0), + ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC = (1 << 1), + ETHERNET_ARP_IP4_ENTRY_FLAG_NO_FIB_ENTRY = (1 << 2), +} __attribute__ ((packed)) ethernet_arp_entry_flags_t; + typedef struct { u32 sw_if_index; @@ -147,9 +154,7 @@ typedef struct u8 ethernet_address[6]; - u16 flags; -#define ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC (1 << 0) -#define ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC (1 << 1) + ethernet_arp_entry_flags_t flags; u64 cpu_time_last_updated; diff --git a/src/vnet/ethernet/ethernet.h b/src/vnet/ethernet/ethernet.h index ba84c69c..dcc656a7 100644 --- a/src/vnet/ethernet/ethernet.h +++ b/src/vnet/ethernet/ethernet.h @@ -403,7 +403,8 @@ void ethernet_set_rx_redirect (vnet_main_t * vnm, vnet_hw_interface_t * hi, int vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm, - u32 sw_if_index, void *a_arg, int is_static); + u32 sw_if_index, void *a_arg, + int is_static, int is_no_fib_entry); int vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm, diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c index 715891b8..8d355ab2 100644 --- a/src/vnet/ip/ip6_neighbor.c +++ b/src/vnet/ip/ip6_neighbor.c @@ -235,6 +235,9 @@ format_ip6_neighbor_ip6_entry (u8 * s, va_list * va) if (n->flags & IP6_NEIGHBOR_FLAG_STATIC) flags = format (flags, "S"); + if (n->flags & IP6_NEIGHBOR_FLAG_NO_FIB_ENTRY) + flags = format (flags, "N"); + si = vnet_get_sw_interface (vnm, n->key.sw_if_index); s = format (s, "%=12U%=20U%=6s%=20U%=40U", format_vlib_cpu_time, vm, n->cpu_time_last_updated, @@ -317,6 +320,7 @@ typedef struct { u8 is_add; u8 is_static; + u8 is_no_fib_entry; u8 link_layer_address[6]; u32 sw_if_index; ip6_address_t addr; @@ -328,7 +332,8 @@ static void ip6_neighbor_set_unset_rpc_callback static void set_unset_ip6_neighbor_rpc (vlib_main_t * vm, u32 sw_if_index, - ip6_address_t * a, u8 * link_layer_address, int is_add, int is_static) + ip6_address_t * a, u8 * link_layer_address, int is_add, int is_static, + int is_no_fib_entry) { ip6_neighbor_set_unset_rpc_args_t args; void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); @@ -336,6 +341,7 @@ static void set_unset_ip6_neighbor_rpc args.sw_if_index = sw_if_index; args.is_add = is_add; args.is_static = is_static; + args.is_no_fib_entry = is_no_fib_entry; clib_memcpy (&args.addr, a, sizeof (*a)); if (NULL != link_layer_address) clib_memcpy (args.link_layer_address, link_layer_address, 6); @@ -565,7 +571,7 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, ip6_address_t * a, u8 * link_layer_address, uword n_bytes_link_layer_address, - int is_static) + int is_static, int is_no_fib_entry) { ip6_neighbor_main_t *nm = &ip6_neighbor_main; ip6_neighbor_key_t k; @@ -578,7 +584,8 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, if (os_get_cpu_number ()) { set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address, - 1 /* set new neighbor */ , is_static); + 1 /* set new neighbor */ , is_static, + is_no_fib_entry); return 0; } @@ -598,16 +605,6 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, if (make_new_nd_cache_entry) { - fib_prefix_t pfx = { - .fp_len = 128, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = k.ip6_address, - } - , - }; - u32 fib_index; - pool_get (nm->neighbor_pool, n); mhash_set (&nm->neighbor_index_by_key, &k, n - nm->neighbor_pool, /* old value */ 0); @@ -619,9 +616,25 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, /* * create the adj-fib. the entry in the FIB table for and to the peer. */ - fib_index = ip6_main.fib_index_by_sw_if_index[n->key.sw_if_index]; - n->fib_entry_index = fib_table_entry_update_one_path (fib_index, &pfx, FIB_SOURCE_ADJ, FIB_ENTRY_FLAG_NONE, FIB_PROTOCOL_IP6, &pfx.fp_addr, n->key.sw_if_index, ~0, 1, NULL, // no label stack - FIB_ROUTE_PATH_FLAG_NONE); + if (!is_no_fib_entry) + { + fib_prefix_t pfx = { + .fp_len = 128, + .fp_proto = FIB_PROTOCOL_IP6, + .fp_addr.ip6 = k.ip6_address, + }; + u32 fib_index; + + fib_index = ip6_main.fib_index_by_sw_if_index[n->key.sw_if_index]; + n->fib_entry_index = + fib_table_entry_update_one_path (fib_index, &pfx, + FIB_SOURCE_ADJ, + FIB_ENTRY_FLAG_NONE, + FIB_PROTOCOL_IP6, &pfx.fp_addr, + n->key.sw_if_index, ~0, 1, NULL, + FIB_ROUTE_PATH_FLAG_NONE); + n->flags |= IP6_NEIGHBOR_FLAG_NO_FIB_ENTRY; + } } else { @@ -712,7 +725,7 @@ vnet_unset_ip6_ethernet_neighbor (vlib_main_t * vm, if (os_get_cpu_number ()) { set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address, - 0 /* unset */ , 0); + 0 /* unset */ , 0, 0); return 0; } @@ -746,7 +759,8 @@ static void ip6_neighbor_set_unset_rpc_callback vlib_main_t *vm = vlib_get_main (); if (a->is_add) vnet_set_ip6_ethernet_neighbor (vm, a->sw_if_index, &a->addr, - a->link_layer_address, 6, a->is_static); + a->link_layer_address, 6, a->is_static, + a->is_no_fib_entry); else vnet_unset_ip6_ethernet_neighbor (vm, a->sw_if_index, &a->addr, a->link_layer_address, 6); @@ -850,6 +864,7 @@ set_ip6_neighbor (vlib_main_t * vm, int addr_valid = 0; int is_del = 0; int is_static = 0; + int is_no_fib_entry = 0; u32 sw_if_index; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) @@ -865,6 +880,8 @@ set_ip6_neighbor (vlib_main_t * vm, is_del = 1; else if (unformat (input, "static")) is_static = 1; + else if (unformat (input, "no-fib-entry")) + is_no_fib_entry = 1; else break; } @@ -875,7 +892,7 @@ set_ip6_neighbor (vlib_main_t * vm, if (!is_del) vnet_set_ip6_ethernet_neighbor (vm, sw_if_index, &addr, mac_address, sizeof (mac_address), - is_static); + is_static, is_no_fib_entry); else vnet_unset_ip6_ethernet_neighbor (vm, sw_if_index, &addr, mac_address, sizeof (mac_address)); @@ -1023,7 +1040,7 @@ icmp6_neighbor_solicitation_or_advertisement (vlib_main_t * vm, &h0->target_address, o0->ethernet_address, sizeof (o0->ethernet_address), - 0); + 0, 0); } if (is_solicitation && error0 == ICMP6_ERROR_NONE) @@ -1338,7 +1355,7 @@ icmp6_router_solicitation (vlib_main_t * vm, &ip0->src_address, o0->ethernet_address, sizeof (o0->ethernet_address), - 0); + 0, 0); } /* default is to drop */ diff --git a/src/vnet/ip/ip6_neighbor.h b/src/vnet/ip/ip6_neighbor.h index 3d256316..ef1e84c2 100644 --- a/src/vnet/ip/ip6_neighbor.h +++ b/src/vnet/ip/ip6_neighbor.h @@ -28,13 +28,18 @@ typedef struct u32 pad; } ip6_neighbor_key_t; +typedef enum ip6_neighbor_flags_t_ +{ + IP6_NEIGHBOR_FLAG_STATIC = (1 << 0), + IP6_NEIGHBOR_FLAG_DYNAMIC = (1 << 1), + IP6_NEIGHBOR_FLAG_NO_FIB_ENTRY = (1 << 2), +} __attribute__ ((packed)) ip6_neighbor_flags_t; + typedef struct { ip6_neighbor_key_t key; u8 link_layer_address[8]; - u16 flags; -#define IP6_NEIGHBOR_FLAG_STATIC (1 << 0) -#define IP6_NEIGHBOR_FLAG_DYNAMIC (2 << 0) + ip6_neighbor_flags_t flags; u64 cpu_time_last_updated; fib_node_index_t fib_entry_index; } ip6_neighbor_t; @@ -69,7 +74,8 @@ extern int vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, ip6_address_t * a, u8 * link_layer_address, uword n_bytes_link_layer_address, - int is_static); + int is_static, + int is_no_fib_entry); extern int vnet_unset_ip6_ethernet_neighbor (vlib_main_t * vm, u32 sw_if_index, diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index 0ca058ab..e3a1fee8 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -655,7 +655,8 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, rv = vnet_set_ip6_ethernet_neighbor (vm, ntohl (mp->sw_if_index), (ip6_address_t *) (mp->dst_address), - mp->mac_address, sizeof (mp->mac_address), mp->is_static); + mp->mac_address, sizeof (mp->mac_address), mp->is_static, + mp->is_no_adj_fib); else rv = vnet_unset_ip6_ethernet_neighbor (vm, ntohl (mp->sw_if_index), @@ -671,7 +672,8 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, if (mp->is_add) rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), - &a, mp->is_static); + &a, mp->is_static, + mp->is_no_adj_fib); else rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a); -- cgit 1.2.3-korg