diff options
Diffstat (limited to 'vnet/vnet/ip/ip6_neighbor.c')
-rw-r--r-- | vnet/vnet/ip/ip6_neighbor.c | 3605 |
1 files changed, 1919 insertions, 1686 deletions
diff --git a/vnet/vnet/ip/ip6_neighbor.c b/vnet/vnet/ip/ip6_neighbor.c index 15b3f764..432e09bb 100644 --- a/vnet/vnet/ip/ip6_neighbor.c +++ b/vnet/vnet/ip/ip6_neighbor.c @@ -36,7 +36,8 @@ #define ETHER_MAC_ADDR_LEN 6 /* advertised prefix option */ -typedef struct { +typedef struct +{ /* basic advertised information */ ip6_address_t prefix; u8 prefix_len; @@ -47,12 +48,12 @@ typedef struct { /* advertised values are computed from these times if decrementing */ f64 valid_lifetime_expires; - f64 pref_lifetime_expires; - + f64 pref_lifetime_expires; + /* local information */ int enabled; int deprecated_prefix_flag; - int decrement_lifetime_flag; + int decrement_lifetime_flag; #define MIN_ADV_VALID_LIFETIME 7203 /* seconds */ #define DEF_ADV_VALID_LIFETIME 2592000 @@ -62,7 +63,8 @@ typedef struct { } ip6_radv_prefix_t; -typedef struct { +typedef struct +{ /* group information */ u8 type; ip6_address_t mcast_address; @@ -71,31 +73,32 @@ typedef struct { } ip6_mldp_group_t; /* configured router advertisement information per ipv6 interface */ -typedef struct { +typedef struct +{ /* advertised config information, zero means unspecified */ - u8 curr_hop_limit; + u8 curr_hop_limit; int adv_managed_flag; int adv_other_flag; - u16 adv_router_lifetime_in_sec; + u16 adv_router_lifetime_in_sec; u32 adv_neighbor_reachable_time_in_msec; u32 adv_time_in_msec_between_retransmitted_neighbor_solicitations; /* mtu option */ u32 adv_link_mtu; - + /* source link layer option */ - u8 link_layer_address[8]; - u8 link_layer_addr_len; + u8 link_layer_address[8]; + u8 link_layer_addr_len; /* prefix option */ - ip6_radv_prefix_t * adv_prefixes_pool; + ip6_radv_prefix_t *adv_prefixes_pool; /* Hash table mapping address to index in interface advertised prefix pool. */ mhash_t address_to_prefix_index; /* MLDP group information */ - ip6_mldp_group_t * mldp_group_pool; + ip6_mldp_group_t *mldp_group_pool; /* Hash table mapping address to index in mldp address pool. */ mhash_t address_to_mldp_index; @@ -103,8 +106,8 @@ typedef struct { /* local information */ u32 sw_if_index; u32 fib_index; - int send_radv; /* radv on/off on this interface - set by config */ - int cease_radv; /* we are ceasing to send - set byf config */ + int send_radv; /* radv on/off on this interface - set by config */ + int cease_radv; /* we are ceasing to send - set byf config */ int send_unicast; int adv_link_layer_address; int prefix_option; @@ -116,7 +119,7 @@ typedef struct { adj_index_t all_nodes_adj_index; adj_index_t all_routers_adj_index; adj_index_t all_mldv2_routers_adj_index; - + /* timing information */ #define DEF_MAX_RADV_INTERVAL 200 #define DEF_MIN_RADV_INTERVAL .75 * DEF_MAX_RADV_INTERVAL @@ -124,11 +127,11 @@ typedef struct { #define DEF_DEF_RTR_LIFETIME 3 * DEF_MAX_RADV_INTERVAL #define MAX_DEF_RTR_LIFETIME 9000 -#define MAX_INITIAL_RTR_ADVERT_INTERVAL 16 /* seconds */ -#define MAX_INITIAL_RTR_ADVERTISEMENTS 3 /*transmissions */ -#define MIN_DELAY_BETWEEN_RAS 3 /* seconds */ -#define MAX_DELAY_BETWEEN_RAS 1800 /* seconds */ -#define MAX_RA_DELAY_TIME .5 /* seconds */ +#define MAX_INITIAL_RTR_ADVERT_INTERVAL 16 /* seconds */ +#define MAX_INITIAL_RTR_ADVERTISEMENTS 3 /*transmissions */ +#define MIN_DELAY_BETWEEN_RAS 3 /* seconds */ +#define MAX_DELAY_BETWEEN_RAS 1800 /* seconds */ +#define MAX_RA_DELAY_TIME .5 /* seconds */ f64 max_radv_interval; f64 min_radv_interval; @@ -142,7 +145,7 @@ typedef struct { u32 initial_adverts_count; - f64 initial_adverts_interval; + f64 initial_adverts_interval; u32 initial_adverts_sent; /* stats */ @@ -156,38 +159,40 @@ typedef struct { } ip6_radv_t; -typedef struct { +typedef struct +{ u32 next_index; uword node_index; uword type_opaque; uword data; /* Used for nd event notification only */ - void * data_callback; + void *data_callback; u32 pid; } pending_resolution_t; -typedef struct { +typedef struct +{ /* Hash tables mapping name to opcode. */ - uword * opcode_by_name; + uword *opcode_by_name; /* lite beer "glean" adjacency handling */ mhash_t pending_resolutions_by_address; - pending_resolution_t * pending_resolutions; + pending_resolution_t *pending_resolutions; /* Mac address change notification */ mhash_t mac_changes_by_address; - pending_resolution_t * mac_changes; + pending_resolution_t *mac_changes; - u32 * neighbor_input_next_index_by_hw_if_index; + u32 *neighbor_input_next_index_by_hw_if_index; - ip6_neighbor_t * neighbor_pool; + ip6_neighbor_t *neighbor_pool; mhash_t neighbor_index_by_key; - u32 * if_radv_pool_index_by_sw_if_index; + u32 *if_radv_pool_index_by_sw_if_index; - ip6_radv_t * if_radv_pool; + ip6_radv_t *if_radv_pool; /* Neighbor attack mitigation */ u32 limit_neighbor_cache_size; @@ -196,59 +201,63 @@ typedef struct { } ip6_neighbor_main_t; static ip6_neighbor_main_t ip6_neighbor_main; -static ip6_address_t ip6a_zero; /* ip6 address 0 */ +static ip6_address_t ip6a_zero; /* ip6 address 0 */ -static u8 * format_ip6_neighbor_ip6_entry (u8 * s, va_list * va) +static u8 * +format_ip6_neighbor_ip6_entry (u8 * s, va_list * va) { - vlib_main_t * vm = va_arg (*va, vlib_main_t *); - ip6_neighbor_t * n = va_arg (*va, ip6_neighbor_t *); - vnet_main_t * vnm = vnet_get_main(); - vnet_sw_interface_t * si; - u8 * flags = 0; + vlib_main_t *vm = va_arg (*va, vlib_main_t *); + ip6_neighbor_t *n = va_arg (*va, ip6_neighbor_t *); + vnet_main_t *vnm = vnet_get_main (); + vnet_sw_interface_t *si; + u8 *flags = 0; - if (! n) - return format (s, "%=12s%=20s%=6s%=20s%=40s", "Time", "Address", "Flags", "Link layer", "Interface"); + if (!n) + return format (s, "%=12s%=20s%=6s%=20s%=40s", "Time", "Address", "Flags", + "Link layer", "Interface"); if (n->flags & IP6_NEIGHBOR_FLAG_DYNAMIC) - flags = format(flags, "D"); + flags = format (flags, "D"); if (n->flags & IP6_NEIGHBOR_FLAG_STATIC) - flags = format(flags, "S"); + flags = format (flags, "S"); 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, format_ip6_address, &n->key.ip6_address, - flags ? (char *)flags : "", + flags ? (char *) flags : "", format_ethernet_address, n->link_layer_address, format_vnet_sw_interface_name, vnm, si); - vec_free(flags); + vec_free (flags); return s; } static clib_error_t * ip6_neighbor_sw_interface_up_down (vnet_main_t * vnm, - u32 sw_if_index, - u32 flags) + u32 sw_if_index, u32 flags) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - ip6_neighbor_t * n; - - if (! (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)) + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + ip6_neighbor_t *n; + + if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)) { - u32 i, * to_delete = 0; + u32 i, *to_delete = 0; - pool_foreach (n, nm->neighbor_pool, ({ + /* *INDENT-OFF* */ + pool_foreach (n, nm->neighbor_pool, + ({ if (n->key.sw_if_index == sw_if_index) vec_add1 (to_delete, n - nm->neighbor_pool); })); + /* *INDENT-ON* */ for (i = 0; i < vec_len (to_delete); i++) { n = pool_elt_at_index (nm->neighbor_pool, to_delete[i]); mhash_unset (&nm->neighbor_index_by_key, &n->key, 0); - fib_table_entry_delete_index (n->fib_entry_index, FIB_SOURCE_ADJ); + fib_table_entry_delete_index (n->fib_entry_index, FIB_SOURCE_ADJ); pool_put (nm->neighbor_pool, n); } @@ -260,12 +269,13 @@ ip6_neighbor_sw_interface_up_down (vnet_main_t * vnm, VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ip6_neighbor_sw_interface_up_down); -static void unset_random_neighbor_entry (void) +static void +unset_random_neighbor_entry (void) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - vnet_main_t * vnm = vnet_get_main(); - vlib_main_t * vm = vnm->vlib_main; - ip6_neighbor_t * e; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + vnet_main_t *vnm = vnet_get_main (); + vlib_main_t *vm = vnm->vlib_main; + ip6_neighbor_t *e; u32 index; index = pool_next_index (nm->neighbor_pool, nm->neighbor_delete_rotor); @@ -283,14 +293,15 @@ static void unset_random_neighbor_entry (void) return; e = pool_elt_at_index (nm->neighbor_pool, index); - + vnet_unset_ip6_ethernet_neighbor (vm, e->key.sw_if_index, - &e->key.ip6_address, - e->link_layer_address, - ETHER_MAC_ADDR_LEN); + &e->key.ip6_address, + e->link_layer_address, + ETHER_MAC_ADDR_LEN); } -typedef struct { +typedef struct +{ u8 is_add; u8 is_static; u8 link_layer_address[6]; @@ -298,66 +309,64 @@ typedef struct { ip6_address_t addr; } ip6_neighbor_set_unset_rpc_args_t; -static void ip6_neighbor_set_unset_rpc_callback -( ip6_neighbor_set_unset_rpc_args_t * a); +static void ip6_neighbor_set_unset_rpc_callback + (ip6_neighbor_set_unset_rpc_args_t * a); -static void set_unset_ip6_neighbor_rpc -(vlib_main_t * vm, - u32 sw_if_index, - ip6_address_t * a, - u8 *link_layer_addreess, - int is_add, int is_static) +static void set_unset_ip6_neighbor_rpc + (vlib_main_t * vm, + u32 sw_if_index, + ip6_address_t * a, u8 * link_layer_addreess, int is_add, int is_static) { ip6_neighbor_set_unset_rpc_args_t args; void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); - + args.sw_if_index = sw_if_index; args.is_add = is_add; args.is_static = is_static; clib_memcpy (&args.addr, a, sizeof (*a)); clib_memcpy (args.link_layer_address, link_layer_addreess, 6); - + vl_api_rpc_call_main_thread (ip6_neighbor_set_unset_rpc_callback, - (u8 *) &args, sizeof (args)); + (u8 *) & args, sizeof (args)); } static void -ip6_nbr_probe (ip_adjacency_t *adj) -{ - icmp6_neighbor_solicitation_header_t * h; - vnet_main_t * vnm = vnet_get_main(); - ip6_main_t * im = &ip6_main; - ip_interface_address_t * ia; - ip6_address_t * dst, *src; - vnet_hw_interface_t * hi; - vnet_sw_interface_t * si; - vlib_buffer_t * b; +ip6_nbr_probe (ip_adjacency_t * adj) +{ + icmp6_neighbor_solicitation_header_t *h; + vnet_main_t *vnm = vnet_get_main (); + ip6_main_t *im = &ip6_main; + ip_interface_address_t *ia; + ip6_address_t *dst, *src; + vnet_hw_interface_t *hi; + vnet_sw_interface_t *si; + vlib_buffer_t *b; int bogus_length; - vlib_main_t * vm; + vlib_main_t *vm; u32 bi = 0; - vm = vlib_get_main(); + vm = vlib_get_main (); - si = vnet_get_sw_interface(vnm, adj->rewrite_header.sw_if_index); + si = vnet_get_sw_interface (vnm, adj->rewrite_header.sw_if_index); dst = &adj->sub_type.nbr.next_hop.ip6; if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)) { return; } - src = ip6_interface_address_matching_destination(im, dst, - adj->rewrite_header.sw_if_index, - &ia); - if (! src) + src = ip6_interface_address_matching_destination (im, dst, + adj->rewrite_header. + sw_if_index, &ia); + if (!src) { return; } - h = vlib_packet_template_get_packet(vm, - &im->discover_neighbor_packet_template, - &bi); + h = vlib_packet_template_get_packet (vm, + &im->discover_neighbor_packet_template, + &bi); - hi = vnet_get_sup_hw_interface(vnm, adj->rewrite_header.sw_if_index); + hi = vnet_get_sup_hw_interface (vnm, adj->rewrite_header.sw_if_index); h->ip.dst_address.as_u8[13] = dst->as_u8[13]; h->ip.dst_address.as_u8[14] = dst->as_u8[14]; @@ -366,28 +375,26 @@ ip6_nbr_probe (ip_adjacency_t *adj) h->neighbor.target_address = dst[0]; clib_memcpy (h->link_layer_option.ethernet_address, - hi->hw_address, - vec_len(hi->hw_address)); + hi->hw_address, vec_len (hi->hw_address)); h->neighbor.icmp.checksum = - ip6_tcp_udp_icmp_compute_checksum(vm, 0, &h->ip, &bogus_length); - ASSERT(bogus_length == 0); + ip6_tcp_udp_icmp_compute_checksum (vm, 0, &h->ip, &bogus_length); + ASSERT (bogus_length == 0); b = vlib_get_buffer (vm, bi); vnet_buffer (b)->sw_if_index[VLIB_RX] = - vnet_buffer (b)->sw_if_index[VLIB_TX] = - adj->rewrite_header.sw_if_index; + vnet_buffer (b)->sw_if_index[VLIB_TX] = adj->rewrite_header.sw_if_index; /* Add encapsulation string for software interface (e.g. ethernet header). */ - vnet_rewrite_one_header(adj[0], h, sizeof (ethernet_header_t)); - vlib_buffer_advance(b, -adj->rewrite_header.data_bytes); + vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t)); + vlib_buffer_advance (b, -adj->rewrite_header.data_bytes); { - vlib_frame_t * f = vlib_get_frame_to_node(vm, hi->output_node_index); - u32 * to_next = vlib_frame_vector_args(f); - to_next[0] = bi; - f->n_vectors = 1; - vlib_put_frame_to_node(vm, hi->output_node_index, f); + vlib_frame_t *f = vlib_get_frame_to_node (vm, hi->output_node_index); + u32 *to_next = vlib_frame_vector_args (f); + to_next[0] = bi; + f->n_vectors = 1; + vlib_put_frame_to_node (vm, hi->output_node_index, f); } } @@ -397,22 +404,22 @@ ip6_nd_mk_complete (adj_index_t ai, ip6_neighbor_t * nbr) adj_nbr_update_rewrite (ai, ADJ_NBR_REWRITE_FLAG_COMPLETE, ethernet_build_rewrite (vnet_get_main (), nbr->key.sw_if_index, - adj_get_link_type(ai), + adj_get_link_type (ai), nbr->link_layer_address)); } static void ip6_nd_mk_incomplete (adj_index_t ai) { - ip_adjacency_t *adj = adj_get(ai); + ip_adjacency_t *adj = adj_get (ai); - adj_nbr_update_rewrite ( - ai, - ADJ_NBR_REWRITE_FLAG_INCOMPLETE, - ethernet_build_rewrite (vnet_get_main (), - adj->rewrite_header.sw_if_index, - adj_get_link_type(ai), - VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST)); + adj_nbr_update_rewrite (ai, + ADJ_NBR_REWRITE_FLAG_INCOMPLETE, + ethernet_build_rewrite (vnet_get_main (), + adj->rewrite_header. + sw_if_index, + adj_get_link_type (ai), + VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST)); } #define IP6_NBR_MK_KEY(k, sw_if_index, addr) \ @@ -423,20 +430,20 @@ ip6_nd_mk_incomplete (adj_index_t ai) } static ip6_neighbor_t * -ip6_nd_find (u32 sw_if_index, - const ip6_address_t * addr) +ip6_nd_find (u32 sw_if_index, const ip6_address_t * addr) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - ip6_neighbor_t * n = NULL; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + ip6_neighbor_t *n = NULL; ip6_neighbor_key_t k; uword *p; - IP6_NBR_MK_KEY(k, sw_if_index, addr); + IP6_NBR_MK_KEY (k, sw_if_index, addr); p = mhash_get (&nm->neighbor_index_by_key, &k); - if (p) { - n = pool_elt_at_index (nm->neighbor_pool, p[0]); - } + if (p) + { + n = pool_elt_at_index (nm->neighbor_pool, p[0]); + } return (n); } @@ -460,9 +467,7 @@ ip6_nd_mk_incomplete_walk (adj_index_t ai, void *ctx) } void -ip6_ethernet_update_adjacency (vnet_main_t * vnm, - u32 sw_if_index, - u32 ai) +ip6_ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai) { ip6_neighbor_t *nbr; ip_adjacency_t *adj; @@ -503,24 +508,24 @@ ip6_ethernet_update_adjacency (vnet_main_t * vnm, int vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, - u32 sw_if_index, - ip6_address_t * a, - u8 * link_layer_address, - uword n_bytes_link_layer_address, - int is_static) + u32 sw_if_index, + ip6_address_t * a, + u8 * link_layer_address, + uword n_bytes_link_layer_address, + int is_static) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; ip6_neighbor_key_t k; - ip6_neighbor_t * n = 0; - int make_new_nd_cache_entry=1; - uword * p; + ip6_neighbor_t *n = 0; + int make_new_nd_cache_entry = 1; + uword *p; u32 next_index; - pending_resolution_t * pr, * mc; + pending_resolution_t *pr, *mc; - if (os_get_cpu_number()) + 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); return 0; } @@ -529,66 +534,55 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, k.pad = 0; p = mhash_get (&nm->neighbor_index_by_key, &k); - if (p) { - n = pool_elt_at_index (nm->neighbor_pool, p[0]); - /* Refuse to over-write static neighbor entry. */ - if (!is_static && - (n->flags & IP6_NEIGHBOR_FLAG_STATIC)) - return -2; - make_new_nd_cache_entry = 0; - } + if (p) + { + n = pool_elt_at_index (nm->neighbor_pool, p[0]); + /* Refuse to over-write static neighbor entry. */ + if (!is_static && (n->flags & IP6_NEIGHBOR_FLAG_STATIC)) + return -2; + make_new_nd_cache_entry = 0; + } - if (make_new_nd_cache_entry) { + if (make_new_nd_cache_entry) + { fib_prefix_t pfx = { - .fp_len = 128, - .fp_proto = FIB_PROTOCOL_IP6, - .fp_addr = { - .ip6 = k.ip6_address, - }, + .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); - n->key = k; - - clib_memcpy (n->link_layer_address, - link_layer_address, - n_bytes_link_layer_address); - - /* - * 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); - } + pool_get (nm->neighbor_pool, n); + mhash_set (&nm->neighbor_index_by_key, &k, n - nm->neighbor_pool, + /* old value */ 0); + n->key = k; + + clib_memcpy (n->link_layer_address, + link_layer_address, n_bytes_link_layer_address); + + /* + * 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); + } else - { - /* - * prevent a DoS attack from the data-plane that - * spams us with no-op updates to the MAC address - */ - if (0 == memcmp(n->link_layer_address, - link_layer_address, - n_bytes_link_layer_address)) - return -1; - - clib_memcpy (n->link_layer_address, - link_layer_address, - n_bytes_link_layer_address); - } + { + /* + * prevent a DoS attack from the data-plane that + * spams us with no-op updates to the MAC address + */ + if (0 == memcmp (n->link_layer_address, + link_layer_address, n_bytes_link_layer_address)) + return -1; + + clib_memcpy (n->link_layer_address, + link_layer_address, n_bytes_link_layer_address); + } /* Update time stamp and flags. */ n->cpu_time_last_updated = clib_cpu_time_now (); @@ -598,24 +592,22 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, n->flags |= IP6_NEIGHBOR_FLAG_DYNAMIC; adj_nbr_walk_nh6 (sw_if_index, - &n->key.ip6_address, - ip6_nd_mk_complete_walk, n); + &n->key.ip6_address, ip6_nd_mk_complete_walk, n); /* Customer(s) waiting for this address to be resolved? */ p = mhash_get (&nm->pending_resolutions_by_address, a); if (p) { next_index = p[0]; - - while (next_index != (u32)~0) - { + + while (next_index != (u32) ~ 0) + { pr = pool_elt_at_index (nm->pending_resolutions, next_index); vlib_process_signal_event (vm, pr->node_index, - pr->type_opaque, - pr->data); + pr->type_opaque, pr->data); next_index = pr->next_index; pool_put (nm->pending_resolutions, pr); - } + } mhash_unset (&nm->pending_resolutions_by_address, a, 0); } @@ -626,26 +618,26 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, { next_index = p[0]; - while (next_index != (u32)~0) - { - int (*fp)(u32, u8 *, u32, ip6_address_t *); - int rv = 1; - mc = pool_elt_at_index (nm->mac_changes, next_index); - fp = mc->data_callback; - - /* Call the user's data callback, return 1 to suppress dup events */ - if (fp) - rv = (*fp)(mc->data, link_layer_address, sw_if_index, &ip6a_zero); - /* - * Signal the resolver process, as long as the user - * says they want to be notified - */ - if (rv == 0) - vlib_process_signal_event (vm, mc->node_index, - mc->type_opaque, - mc->data); - next_index = mc->next_index; - } + while (next_index != (u32) ~ 0) + { + int (*fp) (u32, u8 *, u32, ip6_address_t *); + int rv = 1; + mc = pool_elt_at_index (nm->mac_changes, next_index); + fp = mc->data_callback; + + /* Call the user's data callback, return 1 to suppress dup events */ + if (fp) + rv = + (*fp) (mc->data, link_layer_address, sw_if_index, &ip6a_zero); + /* + * Signal the resolver process, as long as the user + * says they want to be notified + */ + if (rv == 0) + vlib_process_signal_event (vm, mc->node_index, + mc->type_opaque, mc->data); + next_index = mc->next_index; + } } return 0; @@ -653,71 +645,69 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm, int vnet_unset_ip6_ethernet_neighbor (vlib_main_t * vm, - u32 sw_if_index, - ip6_address_t * a, - u8 * link_layer_address, - uword n_bytes_link_layer_address) + u32 sw_if_index, + ip6_address_t * a, + u8 * link_layer_address, + uword n_bytes_link_layer_address) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; ip6_neighbor_key_t k; - ip6_neighbor_t * n; - uword * p; + ip6_neighbor_t *n; + uword *p; int rv = 0; - if (os_get_cpu_number()) + if (os_get_cpu_number ()) { set_unset_ip6_neighbor_rpc (vm, sw_if_index, a, link_layer_address, - 0 /* unset */, 0); + 0 /* unset */ , 0); return 0; } k.sw_if_index = sw_if_index; k.ip6_address = a[0]; k.pad = 0; - + p = mhash_get (&nm->neighbor_index_by_key, &k); if (p == 0) { rv = -1; goto out; } - + n = pool_elt_at_index (nm->neighbor_pool, p[0]); mhash_unset (&nm->neighbor_index_by_key, &n->key, 0); adj_nbr_walk_nh6 (sw_if_index, - &n->key.ip6_address, - ip6_nd_mk_incomplete_walk, - NULL); + &n->key.ip6_address, ip6_nd_mk_incomplete_walk, NULL); - fib_table_entry_delete_index (n->fib_entry_index, FIB_SOURCE_ADJ); + fib_table_entry_delete_index (n->fib_entry_index, FIB_SOURCE_ADJ); pool_put (nm->neighbor_pool, n); - - out: + +out: return rv; } -static void ip6_neighbor_set_unset_rpc_callback -( ip6_neighbor_set_unset_rpc_args_t * a) +static void ip6_neighbor_set_unset_rpc_callback + (ip6_neighbor_set_unset_rpc_args_t * a) { - 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); + 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); else - vnet_unset_ip6_ethernet_neighbor (vm, a->sw_if_index, &a->addr, - a->link_layer_address, 6); + vnet_unset_ip6_ethernet_neighbor (vm, a->sw_if_index, &a->addr, + a->link_layer_address, 6); } static int ip6_neighbor_sort (void *a1, void *a2) { - vnet_main_t * vnm = vnet_get_main(); - ip6_neighbor_t * n1 = a1, * n2 = a2; + vnet_main_t *vnm = vnet_get_main (); + ip6_neighbor_t *n1 = a1, *n2 = a2; int cmp; - cmp = vnet_sw_interface_compare (vnm, n1->key.sw_if_index, - n2->key.sw_if_index); - if (! cmp) + cmp = vnet_sw_interface_compare (vnm, n1->key.sw_if_index, + n2->key.sw_if_index); + if (!cmp) cmp = ip6_address_compare (&n1->key.ip6_address, &n2->key.ip6_address); return cmp; } @@ -725,11 +715,12 @@ ip6_neighbor_sort (void *a1, void *a2) ip6_neighbor_t * ip6_neighbors_entries (u32 sw_if_index) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; ip6_neighbor_t *n, *ns = 0; /* *INDENT-OFF* */ - pool_foreach (n, nm->neighbor_pool, ({ + pool_foreach (n, nm->neighbor_pool, + ({ if (sw_if_index != ~0 && n->key.sw_if_index != sw_if_index) continue; vec_add1 (ns, n[0]); @@ -743,12 +734,11 @@ ip6_neighbors_entries (u32 sw_if_index) static clib_error_t * show_ip6_neighbors (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) + unformat_input_t * input, vlib_cli_command_t * cmd) { - vnet_main_t * vnm = vnet_get_main(); - ip6_neighbor_t * n, * ns; - clib_error_t * error = 0; + vnet_main_t *vnm = vnet_get_main (); + ip6_neighbor_t *n, *ns; + clib_error_t *error = 0; u32 sw_if_index; /* Filter entries by interface if given. */ @@ -759,8 +749,9 @@ show_ip6_neighbors (vlib_main_t * vm, if (ns) { vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, 0); - vec_foreach (n, ns) { - vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, n); + vec_foreach (n, ns) + { + vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, n); } vec_free (ns); } @@ -798,10 +789,9 @@ VLIB_CLI_COMMAND (show_ip6_neighbors_command, static) = { static clib_error_t * set_ip6_neighbor (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) + unformat_input_t * input, vlib_cli_command_t * cmd) { - vnet_main_t * vnm = vnet_get_main(); + vnet_main_t *vnm = vnet_get_main (); ip6_address_t addr; u8 mac_address[6]; int addr_valid = 0; @@ -809,32 +799,33 @@ set_ip6_neighbor (vlib_main_t * vm, int is_static = 0; u32 sw_if_index; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { /* intfc, ip6-address, mac-address */ if (unformat (input, "%U %U %U", - unformat_vnet_sw_interface, vnm, &sw_if_index, - unformat_ip6_address, &addr, - unformat_ethernet_address, mac_address)) - addr_valid = 1; + unformat_vnet_sw_interface, vnm, &sw_if_index, + unformat_ip6_address, &addr, + unformat_ethernet_address, mac_address)) + addr_valid = 1; else if (unformat (input, "delete") || unformat (input, "del")) - is_del = 1; + is_del = 1; else if (unformat (input, "static")) - is_static = 1; + is_static = 1; else - break; + break; } if (!addr_valid) return clib_error_return (0, "Missing interface, ip6 or hw address"); - + if (!is_del) vnet_set_ip6_ethernet_neighbor (vm, sw_if_index, &addr, - mac_address, sizeof(mac_address), is_static); + mac_address, sizeof (mac_address), + is_static); else vnet_unset_ip6_ethernet_neighbor (vm, sw_if_index, &addr, - mac_address, sizeof(mac_address)); + mac_address, sizeof (mac_address)); return 0; } @@ -851,14 +842,16 @@ set_ip6_neighbor (vlib_main_t * vm, * @cliexcmd{set ip6 neighbor del GigabitEthernet2/0/0 ::1:1:c:0:9 02:fe:e4:45:27:5b} ?*/ /* *INDENT-OFF* */ -VLIB_CLI_COMMAND (set_ip6_neighbor_command, static) = { +VLIB_CLI_COMMAND (set_ip6_neighbor_command, static) = +{ .path = "set ip6 neighbor", .function = set_ip6_neighbor, .short_help = "set ip6 neighbor [del] <interface> <ip6-address> <mac-address> [static]", }; /* *INDENT-ON* */ -typedef enum { +typedef enum +{ ICMP6_NEIGHBOR_SOLICITATION_NEXT_DROP, ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY, ICMP6_NEIGHBOR_SOLICITATION_N_NEXT, @@ -870,25 +863,26 @@ icmp6_neighbor_solicitation_or_advertisement (vlib_main_t * vm, vlib_frame_t * frame, uword is_solicitation) { - vnet_main_t * vnm = vnet_get_main(); - ip6_main_t * im = &ip6_main; + vnet_main_t *vnm = vnet_get_main (); + ip6_main_t *im = &ip6_main; uword n_packets = frame->n_vectors; - u32 * from, * to_next; + u32 *from, *to_next; u32 n_left_from, n_left_to_next, next_index, n_advertisements_sent; icmp6_neighbor_discovery_option_type_t option_type; - vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip6_icmp_input_node.index); + vlib_node_runtime_t *error_node = + vlib_node_get_runtime (vm, ip6_icmp_input_node.index); int bogus_length; from = vlib_frame_vector_args (frame); n_left_from = n_packets; next_index = node->cached_next_index; - + if (node->flags & VLIB_NODE_FLAG_TRACE) vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors, /* stride */ 1, sizeof (icmp6_input_trace_t)); - option_type = + option_type = (is_solicitation ? ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address : ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address); @@ -900,139 +894,153 @@ icmp6_neighbor_solicitation_or_advertisement (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { - vlib_buffer_t * p0; - ip6_header_t * ip0; - icmp6_neighbor_solicitation_or_advertisement_header_t * h0; - icmp6_neighbor_discovery_ethernet_link_layer_address_option_t * o0; + vlib_buffer_t *p0; + ip6_header_t *ip0; + icmp6_neighbor_solicitation_or_advertisement_header_t *h0; + icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *o0; u32 bi0, options_len0, sw_if_index0, next0, error0; - u32 ip6_sadd_link_local, ip6_sadd_unspecified; - int is_rewrite0; - u32 ni0; - + u32 ip6_sadd_link_local, ip6_sadd_unspecified; + int is_rewrite0; + u32 ni0; + bi0 = to_next[0] = from[0]; from += 1; to_next += 1; n_left_from -= 1; n_left_to_next -= 1; - + p0 = vlib_get_buffer (vm, bi0); ip0 = vlib_buffer_get_current (p0); h0 = ip6_next_header (ip0); - options_len0 = clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]); + options_len0 = + clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]); error0 = ICMP6_ERROR_NONE; sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; - ip6_sadd_link_local = ip6_address_is_link_local_unicast(&ip0->src_address); - ip6_sadd_unspecified = ip6_address_is_unspecified (&ip0->src_address); + ip6_sadd_link_local = + ip6_address_is_link_local_unicast (&ip0->src_address); + ip6_sadd_unspecified = + ip6_address_is_unspecified (&ip0->src_address); /* Check that source address is unspecified, link-local or else on-link. */ if (!ip6_sadd_unspecified && !ip6_sadd_link_local) { u32 src_adj_index0 = ip6_src_lookup_for_packet (im, p0, ip0); - if (ADJ_INDEX_INVALID != src_adj_index0) - { - ip_adjacency_t * adj0 = ip_get_adjacency (&im->lookup_main, src_adj_index0); - - /* Allow all realistic-looking rewrite adjacencies to pass */ - ni0 = adj0->lookup_next_index; - is_rewrite0 = (ni0 >= IP_LOOKUP_NEXT_ARP) && - (ni0 < IP6_LOOKUP_N_NEXT); - - error0 = ((adj0->rewrite_header.sw_if_index != sw_if_index0 - || ! is_rewrite0) - ? ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_NOT_ON_LINK - : error0); - } - else - { - error0 = ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_NOT_ON_LINK; - } - } - + if (ADJ_INDEX_INVALID != src_adj_index0) + { + ip_adjacency_t *adj0 = + ip_get_adjacency (&im->lookup_main, src_adj_index0); + + /* Allow all realistic-looking rewrite adjacencies to pass */ + ni0 = adj0->lookup_next_index; + is_rewrite0 = (ni0 >= IP_LOOKUP_NEXT_ARP) && + (ni0 < IP6_LOOKUP_N_NEXT); + + error0 = ((adj0->rewrite_header.sw_if_index != sw_if_index0 + || !is_rewrite0) + ? + ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_NOT_ON_LINK + : error0); + } + else + { + error0 = + ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_NOT_ON_LINK; + } + } + o0 = (void *) (h0 + 1); o0 = ((options_len0 == 8 && o0->header.type == option_type && o0->header.n_data_u64s == 1) ? o0 : 0); /* If src address unspecified or link local, donot learn neighbor MAC */ - if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 && - !ip6_sadd_unspecified && !ip6_sadd_link_local)) - { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - if (nm->limit_neighbor_cache_size && - pool_elts (nm->neighbor_pool) >= nm->limit_neighbor_cache_size) - unset_random_neighbor_entry(); - vnet_set_ip6_ethernet_neighbor ( - vm, sw_if_index0, - is_solicitation ? &ip0->src_address : &h0->target_address, - o0->ethernet_address, sizeof (o0->ethernet_address), 0); - } + if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 && + !ip6_sadd_unspecified && !ip6_sadd_link_local)) + { + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + if (nm->limit_neighbor_cache_size && + pool_elts (nm->neighbor_pool) >= + nm->limit_neighbor_cache_size) + unset_random_neighbor_entry (); + vnet_set_ip6_ethernet_neighbor (vm, sw_if_index0, + is_solicitation ? + &ip0->src_address : + &h0->target_address, + o0->ethernet_address, + sizeof (o0->ethernet_address), + 0); + } if (is_solicitation && error0 == ICMP6_ERROR_NONE) { /* Check that target address is local to this router. */ - fib_node_index_t fei; + fib_node_index_t fei; u32 fib_index; - fib_index = ip6_fib_table_get_index_for_sw_if_index(sw_if_index0); + fib_index = + ip6_fib_table_get_index_for_sw_if_index (sw_if_index0); if (~0 == fib_index) - { + { error0 = ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_UNKNOWN; } else - { - fei = ip6_fib_table_lookup_exact_match(fib_index, - &h0->target_address, - 128); + { + fei = ip6_fib_table_lookup_exact_match (fib_index, + &h0->target_address, + 128); - if (FIB_NODE_INDEX_INVALID == fei || + if (FIB_NODE_INDEX_INVALID == fei || !(FIB_ENTRY_FLAG_LOCAL & - fib_entry_get_flags_for_source(fei, FIB_SOURCE_INTERFACE))) + fib_entry_get_flags_for_source (fei, + FIB_SOURCE_INTERFACE))) { - error0 = ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_UNKNOWN; + error0 = + ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_UNKNOWN; } } } if (is_solicitation) - next0 = (error0 != ICMP6_ERROR_NONE - ? ICMP6_NEIGHBOR_SOLICITATION_NEXT_DROP - : ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY); + next0 = (error0 != ICMP6_ERROR_NONE + ? ICMP6_NEIGHBOR_SOLICITATION_NEXT_DROP + : ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY); else { - next0 = 0; - error0 = error0 == ICMP6_ERROR_NONE ? - ICMP6_ERROR_NEIGHBOR_ADVERTISEMENTS_RX : error0; + next0 = 0; + error0 = error0 == ICMP6_ERROR_NONE ? + ICMP6_ERROR_NEIGHBOR_ADVERTISEMENTS_RX : error0; } if (is_solicitation && error0 == ICMP6_ERROR_NONE) { - vnet_sw_interface_t * sw_if0; - ethernet_interface_t * eth_if0; - ethernet_header_t *eth0; + vnet_sw_interface_t *sw_if0; + ethernet_interface_t *eth_if0; + ethernet_header_t *eth0; - /* dst address is either source address or the all-nodes mcast addr */ - if(!ip6_sadd_unspecified) - ip0->dst_address = ip0->src_address; + /* dst address is either source address or the all-nodes mcast addr */ + if (!ip6_sadd_unspecified) + ip0->dst_address = ip0->src_address; else - ip6_set_reserved_multicast_address(&ip0->dst_address, - IP6_MULTICAST_SCOPE_link_local, - IP6_MULTICAST_GROUP_ID_all_hosts); + ip6_set_reserved_multicast_address (&ip0->dst_address, + IP6_MULTICAST_SCOPE_link_local, + IP6_MULTICAST_GROUP_ID_all_hosts); ip0->src_address = h0->target_address; - ip0->hop_limit = 255; + ip0->hop_limit = 255; h0->icmp.type = ICMP6_neighbor_advertisement; sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0); ASSERT (sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE); - eth_if0 = ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); + eth_if0 = + ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); if (eth_if0 && o0) { - clib_memcpy (o0->ethernet_address, eth_if0->address, 6); - o0->header.type = - ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address; + clib_memcpy (o0->ethernet_address, eth_if0->address, 6); + o0->header.type = + ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address; } h0->advertisement_flags = clib_host_to_net_u32 @@ -1040,27 +1048,27 @@ icmp6_neighbor_solicitation_or_advertisement (vlib_main_t * vm, | ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE); h0->icmp.checksum = 0; - h0->icmp.checksum = - ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip0, - &bogus_length); - ASSERT(bogus_length == 0); - - /* Reuse current MAC header, copy SMAC to DMAC and - * interface MAC to SMAC */ - vlib_buffer_advance(p0, - ethernet_buffer_header_size(p0)); - eth0 = vlib_buffer_get_current(p0); - clib_memcpy(eth0->dst_address, eth0->src_address, 6); - if (eth_if0) - clib_memcpy(eth0->src_address, eth_if0->address, 6); - - /* Setup input and output sw_if_index for packet */ - ASSERT(vnet_buffer(p0)->sw_if_index[VLIB_RX] == sw_if_index0); - vnet_buffer(p0)->sw_if_index[VLIB_TX] = sw_if_index0; - vnet_buffer(p0)->sw_if_index[VLIB_RX] = - vnet_main.local_interface_sw_if_index; + h0->icmp.checksum = + ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip0, + &bogus_length); + ASSERT (bogus_length == 0); + + /* Reuse current MAC header, copy SMAC to DMAC and + * interface MAC to SMAC */ + vlib_buffer_advance (p0, -ethernet_buffer_header_size (p0)); + eth0 = vlib_buffer_get_current (p0); + clib_memcpy (eth0->dst_address, eth0->src_address, 6); + if (eth_if0) + clib_memcpy (eth0->src_address, eth_if0->address, 6); + + /* Setup input and output sw_if_index for packet */ + ASSERT (vnet_buffer (p0)->sw_if_index[VLIB_RX] == sw_if_index0); + vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0; + vnet_buffer (p0)->sw_if_index[VLIB_RX] = + vnet_main.local_interface_sw_if_index; n_advertisements_sent++; - } + } p0->error = error_node->errors[error0]; @@ -1073,7 +1081,9 @@ icmp6_neighbor_solicitation_or_advertisement (vlib_main_t * vm, } /* Account for advertisements sent. */ - vlib_error_count (vm, error_node->node_index, ICMP6_ERROR_NEIGHBOR_ADVERTISEMENTS_TX, n_advertisements_sent); + vlib_error_count (vm, error_node->node_index, + ICMP6_ERROR_NEIGHBOR_ADVERTISEMENTS_TX, + n_advertisements_sent); return frame->n_vectors; } @@ -1089,51 +1099,54 @@ icmp6_neighbor_solicitation_or_advertisement (vlib_main_t * vm, _ (ALERT, "ALERT") \ _ (EMERG, "EMERGENCY") -typedef enum { +typedef enum +{ #define _(f,s) LOG_##f, foreach_log_level #undef _ } log_level_t; -static char * log_level_strings[] = { +static char *log_level_strings[] = { #define _(f,s) s, foreach_log_level #undef _ }; -static int logmask = 1 << LOG_DEBUG; +static int logmask = 1 << LOG_DEBUG; static void -ip6_neighbor_syslog(vlib_main_t *vm, int priority, char * fmt, ...) +ip6_neighbor_syslog (vlib_main_t * vm, int priority, char *fmt, ...) { /* just use elog for now */ u8 *what; va_list va; - if( (priority > LOG_EMERG) || - !(logmask & (1 << priority))) - return; + if ((priority > LOG_EMERG) || !(logmask & (1 << priority))) + return; va_start (va, fmt); - if(fmt) + if (fmt) { what = va_format (0, fmt, &va); - ELOG_TYPE_DECLARE (e) = { - .format = "ip6 nd: (%s): %s", - .format_args = "T4T4", - }; - struct { u32 s[2]; } * ed; + ELOG_TYPE_DECLARE (e) = + { + .format = "ip6 nd: (%s): %s",.format_args = "T4T4",}; + struct + { + u32 s[2]; + } *ed; ed = ELOG_DATA (&vm->elog_main, e); - ed->s[0] = elog_string(&vm->elog_main, log_level_strings[priority]); - ed->s[1] = elog_string(&vm->elog_main, (char *)what); + ed->s[0] = elog_string (&vm->elog_main, log_level_strings[priority]); + ed->s[1] = elog_string (&vm->elog_main, (char *) what); } va_end (va); return; } /* ipv6 neighbor discovery - router advertisements */ -typedef enum { +typedef enum +{ ICMP6_ROUTER_SOLICITATION_NEXT_DROP, ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_RW, ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_TX, @@ -1141,27 +1154,27 @@ typedef enum { } icmp6_router_solicitation_or_advertisement_next_t; static_always_inline uword -icmp6_router_solicitation(vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +icmp6_router_solicitation (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) { - vnet_main_t * vnm = vnet_get_main(); - ip6_main_t * im = &ip6_main; - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + vnet_main_t *vnm = vnet_get_main (); + ip6_main_t *im = &ip6_main; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; uword n_packets = frame->n_vectors; - u32 * from, * to_next; + u32 *from, *to_next; u32 n_left_from, n_left_to_next, next_index; - u32 n_advertisements_sent = 0; + u32 n_advertisements_sent = 0; int bogus_length; icmp6_neighbor_discovery_option_type_t option_type; - vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip6_icmp_input_node.index); + vlib_node_runtime_t *error_node = + vlib_node_get_runtime (vm, ip6_icmp_input_node.index); from = vlib_frame_vector_args (frame); n_left_from = n_packets; next_index = node->cached_next_index; - + if (node->flags & VLIB_NODE_FLAG_TRACE) vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors, /* stride */ 1, @@ -1173,19 +1186,19 @@ icmp6_router_solicitation(vlib_main_t * vm, while (n_left_from > 0) { vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - + while (n_left_from > 0 && n_left_to_next > 0) { - vlib_buffer_t * p0; - ip6_header_t * ip0; + vlib_buffer_t *p0; + ip6_header_t *ip0; ip6_radv_t *radv_info = 0; - icmp6_neighbor_discovery_header_t * h0; - icmp6_neighbor_discovery_ethernet_link_layer_address_option_t * o0; - + icmp6_neighbor_discovery_header_t *h0; + icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *o0; + u32 bi0, options_len0, sw_if_index0, next0, error0; - u32 is_solicitation = 1, is_dropped = 0; - u32 is_unspecified, is_link_local; + u32 is_solicitation = 1, is_dropped = 0; + u32 is_unspecified, is_link_local; bi0 = to_next[0] = from[0]; @@ -1193,17 +1206,19 @@ icmp6_router_solicitation(vlib_main_t * vm, to_next += 1; n_left_from -= 1; n_left_to_next -= 1; - + p0 = vlib_get_buffer (vm, bi0); ip0 = vlib_buffer_get_current (p0); h0 = ip6_next_header (ip0); - options_len0 = clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]); - is_unspecified = ip6_address_is_unspecified (&ip0->src_address); - is_link_local = ip6_address_is_link_local_unicast (&ip0->src_address); + options_len0 = + clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]); + is_unspecified = ip6_address_is_unspecified (&ip0->src_address); + is_link_local = + ip6_address_is_link_local_unicast (&ip0->src_address); error0 = ICMP6_ERROR_NONE; sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; - + /* check if solicitation (not from nd_timer node) */ if (ip6_address_is_unspecified (&ip0->dst_address)) is_solicitation = 0; @@ -1213,85 +1228,97 @@ icmp6_router_solicitation(vlib_main_t * vm, { u32 src_adj_index0 = ip6_src_lookup_for_packet (im, p0, ip0); - if (ADJ_INDEX_INVALID != src_adj_index0) - { - ip_adjacency_t * adj0 = ip_get_adjacency (&im->lookup_main, - src_adj_index0); - - error0 = (adj0->rewrite_header.sw_if_index != sw_if_index0 - ? ICMP6_ERROR_ROUTER_SOLICITATION_SOURCE_NOT_ON_LINK - : error0); - } - else - { - error0 = ICMP6_ERROR_ROUTER_SOLICITATION_SOURCE_NOT_ON_LINK; - } - } - + if (ADJ_INDEX_INVALID != src_adj_index0) + { + ip_adjacency_t *adj0 = ip_get_adjacency (&im->lookup_main, + src_adj_index0); + + error0 = (adj0->rewrite_header.sw_if_index != sw_if_index0 + ? + ICMP6_ERROR_ROUTER_SOLICITATION_SOURCE_NOT_ON_LINK + : error0); + } + else + { + error0 = ICMP6_ERROR_ROUTER_SOLICITATION_SOURCE_NOT_ON_LINK; + } + } + /* check for source LL option and process */ o0 = (void *) (h0 + 1); o0 = ((options_len0 == 8 && o0->header.type == option_type - && o0->header.n_data_u64s == 1) - ? o0 - : 0); - + && o0->header.n_data_u64s == 1) ? o0 : 0); + /* if src address unspecified IGNORE any options */ - if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 && - !is_unspecified && !is_link_local)) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - if (nm->limit_neighbor_cache_size && - pool_elts (nm->neighbor_pool) >= nm->limit_neighbor_cache_size) - unset_random_neighbor_entry(); - - vnet_set_ip6_ethernet_neighbor (vm, sw_if_index0, - &ip0->src_address, - o0->ethernet_address, - sizeof (o0->ethernet_address), 0); - } - + if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 && + !is_unspecified && !is_link_local)) + { + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + if (nm->limit_neighbor_cache_size && + pool_elts (nm->neighbor_pool) >= + nm->limit_neighbor_cache_size) + unset_random_neighbor_entry (); + + vnet_set_ip6_ethernet_neighbor (vm, sw_if_index0, + &ip0->src_address, + o0->ethernet_address, + sizeof (o0->ethernet_address), + 0); + } + /* default is to drop */ next0 = ICMP6_ROUTER_SOLICITATION_NEXT_DROP; - + if (error0 == ICMP6_ERROR_NONE) { - vnet_sw_interface_t * sw_if0; - ethernet_interface_t * eth_if0; - u32 adj_index0; + vnet_sw_interface_t *sw_if0; + ethernet_interface_t *eth_if0; + u32 adj_index0; sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0); ASSERT (sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE); - eth_if0 = ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); + eth_if0 = + ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); /* only support ethernet interface type for now */ - error0 = (!eth_if0) ? ICMP6_ERROR_ROUTER_SOLICITATION_UNSUPPORTED_INTF : error0; + error0 = + (!eth_if0) ? ICMP6_ERROR_ROUTER_SOLICITATION_UNSUPPORTED_INTF + : error0; if (error0 == ICMP6_ERROR_NONE) { u32 ri; /* adjust the sizeof the buffer to just include the ipv6 header */ - p0->current_length -= (options_len0 + sizeof(icmp6_neighbor_discovery_header_t)); + p0->current_length -= + (options_len0 + + sizeof (icmp6_neighbor_discovery_header_t)); /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index0, ~0); + vec_validate_init_empty + (nm->if_radv_pool_index_by_sw_if_index, sw_if_index0, ~0); ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index0]; - if(ri != ~0) - radv_info = pool_elt_at_index (nm->if_radv_pool, ri); - - error0 = ((!radv_info) ? ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG : error0); + if (ri != ~0) + radv_info = pool_elt_at_index (nm->if_radv_pool, ri); + + error0 = + ((!radv_info) ? + ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG : + error0); if (error0 == ICMP6_ERROR_NONE) { f64 now = vlib_time_now (vm); /* for solicited adverts - need to rate limit */ - if(is_solicitation) + if (is_solicitation) { - if( (now - radv_info->last_radv_time) < MIN_DELAY_BETWEEN_RAS ) - is_dropped = 1; + if ((now - radv_info->last_radv_time) < + MIN_DELAY_BETWEEN_RAS) + is_dropped = 1; else radv_info->last_radv_time = now; } @@ -1302,181 +1329,223 @@ icmp6_router_solicitation(vlib_main_t * vm, rh.icmp.type = ICMP6_router_advertisement; rh.icmp.code = 0; rh.icmp.checksum = 0; - - rh.current_hop_limit = radv_info->curr_hop_limit; - rh.router_lifetime_in_sec = clib_host_to_net_u16(radv_info->adv_router_lifetime_in_sec); - rh.time_in_msec_between_retransmitted_neighbor_solicitations = - clib_host_to_net_u32(radv_info->adv_time_in_msec_between_retransmitted_neighbor_solicitations); - rh.neighbor_reachable_time_in_msec = - clib_host_to_net_u32(radv_info->adv_neighbor_reachable_time_in_msec); - - rh.flags = (radv_info->adv_managed_flag) ? ICMP6_ROUTER_DISCOVERY_FLAG_ADDRESS_CONFIG_VIA_DHCP : 0; - rh.flags |= ( (radv_info->adv_other_flag) ? ICMP6_ROUTER_DISCOVERY_FLAG_OTHER_CONFIG_VIA_DHCP : 0); - - u16 payload_length = sizeof(icmp6_router_advertisement_header_t); + rh.current_hop_limit = radv_info->curr_hop_limit; + rh.router_lifetime_in_sec = + clib_host_to_net_u16 + (radv_info->adv_router_lifetime_in_sec); + rh. + time_in_msec_between_retransmitted_neighbor_solicitations + = + clib_host_to_net_u32 (radv_info-> + adv_time_in_msec_between_retransmitted_neighbor_solicitations); + rh.neighbor_reachable_time_in_msec = + clib_host_to_net_u32 (radv_info-> + adv_neighbor_reachable_time_in_msec); + + rh.flags = + (radv_info->adv_managed_flag) ? + ICMP6_ROUTER_DISCOVERY_FLAG_ADDRESS_CONFIG_VIA_DHCP : + 0; + rh.flags |= + ((radv_info->adv_other_flag) ? + ICMP6_ROUTER_DISCOVERY_FLAG_OTHER_CONFIG_VIA_DHCP : + 0); + + + u16 payload_length = + sizeof (icmp6_router_advertisement_header_t); vlib_buffer_add_data (vm, p0->free_list_index, bi0, - (void *)&rh, sizeof(icmp6_router_advertisement_header_t)); + (void *) &rh, + sizeof + (icmp6_router_advertisement_header_t)); - if(radv_info->adv_link_layer_address) + if (radv_info->adv_link_layer_address) { - icmp6_neighbor_discovery_ethernet_link_layer_address_option_t h; + icmp6_neighbor_discovery_ethernet_link_layer_address_option_t + h; - h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address; + h.header.type = + ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address; h.header.n_data_u64s = 1; /* copy ll address */ - clib_memcpy(&h.ethernet_address[0], eth_if0->address, 6); + clib_memcpy (&h.ethernet_address[0], + eth_if0->address, 6); vlib_buffer_add_data (vm, p0->free_list_index, bi0, - (void *)&h, sizeof(icmp6_neighbor_discovery_ethernet_link_layer_address_option_t)); + (void *) &h, + sizeof + (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t)); - payload_length += sizeof(icmp6_neighbor_discovery_ethernet_link_layer_address_option_t); + payload_length += + sizeof + (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t); } - + /* add MTU option */ - if(radv_info->adv_link_mtu) + if (radv_info->adv_link_mtu) { icmp6_neighbor_discovery_mtu_option_t h; h.unused = 0; - h.mtu = clib_host_to_net_u32(radv_info->adv_link_mtu); + h.mtu = + clib_host_to_net_u32 (radv_info->adv_link_mtu); h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_mtu; h.header.n_data_u64s = 1; - - payload_length += sizeof( icmp6_neighbor_discovery_mtu_option_t); + + payload_length += + sizeof (icmp6_neighbor_discovery_mtu_option_t); vlib_buffer_add_data (vm, p0->free_list_index, bi0, - (void *)&h, sizeof(icmp6_neighbor_discovery_mtu_option_t)); + (void *) &h, + sizeof + (icmp6_neighbor_discovery_mtu_option_t)); } - - /* add advertised prefix options */ - ip6_radv_prefix_t *pr_info; - - pool_foreach (pr_info, radv_info->adv_prefixes_pool, ({ - if(pr_info->enabled && - (!pr_info->decrement_lifetime_flag || (pr_info->pref_lifetime_expires >0))) - { - /* advertise this prefix */ - icmp6_neighbor_discovery_prefix_information_option_t h; - - h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_prefix_information; - h.header.n_data_u64s = (sizeof(icmp6_neighbor_discovery_prefix_information_option_t) >> 3); - - h.dst_address_length = pr_info->prefix_len; - - h.flags = (pr_info->adv_on_link_flag) ? ICMP6_NEIGHBOR_DISCOVERY_PREFIX_INFORMATION_FLAG_ON_LINK : 0; - h.flags |= (pr_info->adv_autonomous_flag) ? ICMP6_NEIGHBOR_DISCOVERY_PREFIX_INFORMATION_AUTO : 0; - - if(radv_info->cease_radv && pr_info->deprecated_prefix_flag) - { - h.valid_time = clib_host_to_net_u32(MIN_ADV_VALID_LIFETIME); - h.preferred_time = 0; - } - else - { - if(pr_info->decrement_lifetime_flag) - { - pr_info->adv_valid_lifetime_in_secs = ((pr_info->valid_lifetime_expires > now)) ? - (pr_info->valid_lifetime_expires - now) : 0; - - pr_info->adv_pref_lifetime_in_secs = ((pr_info->pref_lifetime_expires > now)) ? - (pr_info->pref_lifetime_expires - now) : 0; - } - - h.valid_time = clib_host_to_net_u32(pr_info->adv_valid_lifetime_in_secs); - h.preferred_time = clib_host_to_net_u32(pr_info->adv_pref_lifetime_in_secs) ; - } - h.unused = 0; - - clib_memcpy(&h.dst_address, &pr_info->prefix, sizeof(ip6_address_t)); - - payload_length += sizeof( icmp6_neighbor_discovery_prefix_information_option_t); - - vlib_buffer_add_data (vm, - p0->free_list_index, - bi0, - (void *)&h, sizeof(icmp6_neighbor_discovery_prefix_information_option_t)); - - } - })); + /* add advertised prefix options */ + ip6_radv_prefix_t *pr_info; + + /* *INDENT-OFF* */ + pool_foreach (pr_info, radv_info->adv_prefixes_pool, + ({ + if(pr_info->enabled && + (!pr_info->decrement_lifetime_flag + || (pr_info->pref_lifetime_expires >0))) + { + /* advertise this prefix */ + icmp6_neighbor_discovery_prefix_information_option_t h; + + h.header.type = ICMP6_NEIGHBOR_DISCOVERY_OPTION_prefix_information; + h.header.n_data_u64s = (sizeof(icmp6_neighbor_discovery_prefix_information_option_t) >> 3); + + h.dst_address_length = pr_info->prefix_len; + + h.flags = (pr_info->adv_on_link_flag) ? ICMP6_NEIGHBOR_DISCOVERY_PREFIX_INFORMATION_FLAG_ON_LINK : 0; + h.flags |= (pr_info->adv_autonomous_flag) ? ICMP6_NEIGHBOR_DISCOVERY_PREFIX_INFORMATION_AUTO : 0; + + if(radv_info->cease_radv && pr_info->deprecated_prefix_flag) + { + h.valid_time = clib_host_to_net_u32(MIN_ADV_VALID_LIFETIME); + h.preferred_time = 0; + } + else + { + if(pr_info->decrement_lifetime_flag) + { + pr_info->adv_valid_lifetime_in_secs = ((pr_info->valid_lifetime_expires > now)) ? + (pr_info->valid_lifetime_expires - now) : 0; + + pr_info->adv_pref_lifetime_in_secs = ((pr_info->pref_lifetime_expires > now)) ? + (pr_info->pref_lifetime_expires - now) : 0; + } + + h.valid_time = clib_host_to_net_u32(pr_info->adv_valid_lifetime_in_secs); + h.preferred_time = clib_host_to_net_u32(pr_info->adv_pref_lifetime_in_secs) ; + } + h.unused = 0; + + clib_memcpy(&h.dst_address, &pr_info->prefix, sizeof(ip6_address_t)); + + payload_length += sizeof( icmp6_neighbor_discovery_prefix_information_option_t); + + vlib_buffer_add_data (vm, + p0->free_list_index, + bi0, + (void *)&h, sizeof(icmp6_neighbor_discovery_prefix_information_option_t)); + + } + })); + /* *INDENT-ON* */ /* add additional options before here */ /* finish building the router advertisement... */ - if(!is_unspecified && radv_info->send_unicast) + if (!is_unspecified && radv_info->send_unicast) { ip0->dst_address = ip0->src_address; } else - { - /* target address is all-nodes mcast addr */ - ip6_set_reserved_multicast_address(&ip0->dst_address, - IP6_MULTICAST_SCOPE_link_local, - IP6_MULTICAST_GROUP_ID_all_hosts); + { + /* target address is all-nodes mcast addr */ + ip6_set_reserved_multicast_address + (&ip0->dst_address, + IP6_MULTICAST_SCOPE_link_local, + IP6_MULTICAST_GROUP_ID_all_hosts); } - + /* source address MUST be the link-local address */ ip0->src_address = radv_info->link_local_address; - + ip0->hop_limit = 255; - ip0->payload_length = clib_host_to_net_u16 (payload_length); - - icmp6_router_advertisement_header_t * rh0 = (icmp6_router_advertisement_header_t *)(ip0 + 1); - rh0->icmp.checksum = - ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip0, - &bogus_length); - ASSERT(bogus_length == 0); - + ip0->payload_length = + clib_host_to_net_u16 (payload_length); + + icmp6_router_advertisement_header_t *rh0 = + (icmp6_router_advertisement_header_t *) (ip0 + 1); + rh0->icmp.checksum = + ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip0, + &bogus_length); + ASSERT (bogus_length == 0); + /* setup output if and adjacency */ - vnet_buffer (p0)->sw_if_index[VLIB_RX] = + vnet_buffer (p0)->sw_if_index[VLIB_RX] = vnet_main.local_interface_sw_if_index; - - if (is_solicitation) - { - ethernet_header_t *eth0; - /* Reuse current MAC header, copy SMAC to DMAC and - * interface MAC to SMAC */ - vlib_buffer_reset (p0); - eth0 = vlib_buffer_get_current(p0); - clib_memcpy(eth0->dst_address, eth0->src_address, 6); - clib_memcpy(eth0->src_address, eth_if0->address, 6); - next0 = is_dropped ? - next0 : ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_TX; - vnet_buffer(p0)->sw_if_index[VLIB_TX] = sw_if_index0; - } - else - { - adj_index0 = radv_info->all_nodes_adj_index; - if (adj_index0 == 0) - error0 = ICMP6_ERROR_DST_LOOKUP_MISS; - else - { - ip_adjacency_t * adj0 = ip_get_adjacency (&im->lookup_main, adj_index0); - error0 = - ((adj0->rewrite_header.sw_if_index != sw_if_index0 - || adj0->lookup_next_index != IP_LOOKUP_NEXT_REWRITE) - ? ICMP6_ERROR_ROUTER_SOLICITATION_DEST_UNKNOWN - : error0); - next0 = is_dropped ? - next0 : ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_RW; - vnet_buffer (p0)->ip.adj_index[VLIB_TX] = adj_index0; - } - } - p0->flags |= VNET_BUFFER_LOCALLY_ORIGINATED; - - radv_info->n_solicitations_dropped += is_dropped; - radv_info->n_solicitations_rcvd += is_solicitation; - - if((error0 == ICMP6_ERROR_NONE) && !is_dropped) + + if (is_solicitation) + { + ethernet_header_t *eth0; + /* Reuse current MAC header, copy SMAC to DMAC and + * interface MAC to SMAC */ + vlib_buffer_reset (p0); + eth0 = vlib_buffer_get_current (p0); + clib_memcpy (eth0->dst_address, eth0->src_address, + 6); + clib_memcpy (eth0->src_address, eth_if0->address, + 6); + next0 = + is_dropped ? next0 : + ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_TX; + vnet_buffer (p0)->sw_if_index[VLIB_TX] = + sw_if_index0; + } + else + { + adj_index0 = radv_info->all_nodes_adj_index; + if (adj_index0 == 0) + error0 = ICMP6_ERROR_DST_LOOKUP_MISS; + else + { + ip_adjacency_t *adj0 = + ip_get_adjacency (&im->lookup_main, + adj_index0); + error0 = + ((adj0->rewrite_header.sw_if_index != + sw_if_index0 + || adj0->lookup_next_index != + IP_LOOKUP_NEXT_REWRITE) ? + ICMP6_ERROR_ROUTER_SOLICITATION_DEST_UNKNOWN + : error0); + next0 = + is_dropped ? next0 : + ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_RW; + vnet_buffer (p0)->ip.adj_index[VLIB_TX] = + adj_index0; + } + } + p0->flags |= VNET_BUFFER_LOCALLY_ORIGINATED; + + radv_info->n_solicitations_dropped += is_dropped; + radv_info->n_solicitations_rcvd += is_solicitation; + + if ((error0 == ICMP6_ERROR_NONE) && !is_dropped) { radv_info->n_advertisements_sent++; n_advertisements_sent++; @@ -1487,43 +1556,45 @@ icmp6_router_solicitation(vlib_main_t * vm, p0->error = error_node->errors[error0]; - if(error0 != ICMP6_ERROR_NONE) + if (error0 != ICMP6_ERROR_NONE) vlib_error_count (vm, error_node->node_index, error0, 1); - + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); - + } - + vlib_put_next_frame (vm, node, next_index, n_left_to_next); } /* Account for router advertisements sent. */ - vlib_error_count (vm, error_node->node_index, ICMP6_ERROR_ROUTER_ADVERTISEMENTS_TX, n_advertisements_sent); + vlib_error_count (vm, error_node->node_index, + ICMP6_ERROR_ROUTER_ADVERTISEMENTS_TX, + n_advertisements_sent); return frame->n_vectors; } /* validate advertised info for consistancy (see RFC-4861 section 6.2.7) - log any inconsistencies, packet will always be dropped */ static_always_inline uword -icmp6_router_advertisement(vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +icmp6_router_advertisement (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) { - vnet_main_t * vnm = vnet_get_main(); - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + vnet_main_t *vnm = vnet_get_main (); + ip6_neighbor_main_t *nm = &ip6_neighbor_main; uword n_packets = frame->n_vectors; - u32 * from, * to_next; + u32 *from, *to_next; u32 n_left_from, n_left_to_next, next_index; u32 n_advertisements_rcvd = 0; - vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip6_icmp_input_node.index); + vlib_node_runtime_t *error_node = + vlib_node_get_runtime (vm, ip6_icmp_input_node.index); from = vlib_frame_vector_args (frame); n_left_from = n_packets; next_index = node->cached_next_index; - + if (node->flags & VLIB_NODE_FLAG_TRACE) vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors, /* stride */ 1, @@ -1532,13 +1603,13 @@ icmp6_router_advertisement(vlib_main_t * vm, while (n_left_from > 0) { vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - + while (n_left_from > 0 && n_left_to_next > 0) { - vlib_buffer_t * p0; - ip6_header_t * ip0; + vlib_buffer_t *p0; + ip6_header_t *ip0; ip6_radv_t *radv_info = 0; - icmp6_router_advertisement_header_t * h0; + icmp6_router_advertisement_header_t *h0; u32 bi0, options_len0, sw_if_index0, next0, error0; bi0 = to_next[0] = from[0]; @@ -1547,196 +1618,252 @@ icmp6_router_advertisement(vlib_main_t * vm, to_next += 1; n_left_from -= 1; n_left_to_next -= 1; - + p0 = vlib_get_buffer (vm, bi0); ip0 = vlib_buffer_get_current (p0); h0 = ip6_next_header (ip0); - options_len0 = clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]); + options_len0 = + clib_net_to_host_u16 (ip0->payload_length) - sizeof (h0[0]); error0 = ICMP6_ERROR_NONE; sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; - /* Check that source address is link-local*/ - error0 = (!ip6_address_is_link_local_unicast (&ip0->src_address)) ? + /* Check that source address is link-local */ + error0 = (!ip6_address_is_link_local_unicast (&ip0->src_address)) ? ICMP6_ERROR_ROUTER_ADVERTISEMENT_SOURCE_NOT_LINK_LOCAL : error0; /* default is to drop */ next0 = ICMP6_ROUTER_SOLICITATION_NEXT_DROP; - + n_advertisements_rcvd++; if (error0 == ICMP6_ERROR_NONE) { - vnet_sw_interface_t * sw_if0; - ethernet_interface_t * eth_if0; - + vnet_sw_interface_t *sw_if0; + ethernet_interface_t *eth_if0; + sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index0); ASSERT (sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE); - eth_if0 = ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); + eth_if0 = + ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); /* only support ethernet interface type for now */ - error0 = (!eth_if0) ? ICMP6_ERROR_ROUTER_SOLICITATION_UNSUPPORTED_INTF : error0; + error0 = + (!eth_if0) ? ICMP6_ERROR_ROUTER_SOLICITATION_UNSUPPORTED_INTF + : error0; if (error0 == ICMP6_ERROR_NONE) { u32 ri; /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index0, ~0); + vec_validate_init_empty + (nm->if_radv_pool_index_by_sw_if_index, sw_if_index0, ~0); ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index0]; - if(ri != ~0) - radv_info = pool_elt_at_index (nm->if_radv_pool, ri); - - error0 = ((!radv_info) ? ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG : error0); + if (ri != ~0) + radv_info = pool_elt_at_index (nm->if_radv_pool, ri); + + error0 = + ((!radv_info) ? + ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG : + error0); if (error0 == ICMP6_ERROR_NONE) { /* validate advertised information */ - if((h0->current_hop_limit && radv_info->curr_hop_limit) && - (h0->current_hop_limit != radv_info->curr_hop_limit)) + if ((h0->current_hop_limit && radv_info->curr_hop_limit) + && (h0->current_hop_limit != + radv_info->curr_hop_limit)) { - ip6_neighbor_syslog(vm, LOG_WARNING, - "our AdvCurHopLimit on %U doesn't agree with %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address); + ip6_neighbor_syslog (vm, LOG_WARNING, + "our AdvCurHopLimit on %U doesn't agree with %U", + format_vnet_sw_if_index_name, + vnm, sw_if_index0, + format_ip6_address, + &ip0->src_address); } - if((h0->flags & ICMP6_ROUTER_DISCOVERY_FLAG_ADDRESS_CONFIG_VIA_DHCP) != - radv_info->adv_managed_flag) + if ((h0->flags & + ICMP6_ROUTER_DISCOVERY_FLAG_ADDRESS_CONFIG_VIA_DHCP) + != radv_info->adv_managed_flag) { - ip6_neighbor_syslog(vm, LOG_WARNING, - "our AdvManagedFlag on %U doesn't agree with %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address); + ip6_neighbor_syslog (vm, LOG_WARNING, + "our AdvManagedFlag on %U doesn't agree with %U", + format_vnet_sw_if_index_name, + vnm, sw_if_index0, + format_ip6_address, + &ip0->src_address); } - if((h0->flags & ICMP6_ROUTER_DISCOVERY_FLAG_OTHER_CONFIG_VIA_DHCP) != - radv_info->adv_other_flag) + if ((h0->flags & + ICMP6_ROUTER_DISCOVERY_FLAG_OTHER_CONFIG_VIA_DHCP) + != radv_info->adv_other_flag) { - ip6_neighbor_syslog(vm, LOG_WARNING, - "our AdvOtherConfigFlag on %U doesn't agree with %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address); + ip6_neighbor_syslog (vm, LOG_WARNING, + "our AdvOtherConfigFlag on %U doesn't agree with %U", + format_vnet_sw_if_index_name, + vnm, sw_if_index0, + format_ip6_address, + &ip0->src_address); } - if((h0->time_in_msec_between_retransmitted_neighbor_solicitations && - radv_info->adv_time_in_msec_between_retransmitted_neighbor_solicitations) && - (h0->time_in_msec_between_retransmitted_neighbor_solicitations != - clib_host_to_net_u32(radv_info->adv_time_in_msec_between_retransmitted_neighbor_solicitations))) + if ((h0-> + time_in_msec_between_retransmitted_neighbor_solicitations + && radv_info-> + adv_time_in_msec_between_retransmitted_neighbor_solicitations) + && (h0-> + time_in_msec_between_retransmitted_neighbor_solicitations + != + clib_host_to_net_u32 (radv_info-> + adv_time_in_msec_between_retransmitted_neighbor_solicitations))) { - ip6_neighbor_syslog(vm, LOG_WARNING, - "our AdvRetransTimer on %U doesn't agree with %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address); + ip6_neighbor_syslog (vm, LOG_WARNING, + "our AdvRetransTimer on %U doesn't agree with %U", + format_vnet_sw_if_index_name, + vnm, sw_if_index0, + format_ip6_address, + &ip0->src_address); } - if((h0->neighbor_reachable_time_in_msec && - radv_info->adv_neighbor_reachable_time_in_msec) && - (h0->neighbor_reachable_time_in_msec != - clib_host_to_net_u32(radv_info->adv_neighbor_reachable_time_in_msec))) + if ((h0->neighbor_reachable_time_in_msec && + radv_info->adv_neighbor_reachable_time_in_msec) && + (h0->neighbor_reachable_time_in_msec != + clib_host_to_net_u32 + (radv_info->adv_neighbor_reachable_time_in_msec))) { - ip6_neighbor_syslog(vm, LOG_WARNING, - "our AdvReachableTime on %U doesn't agree with %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address); + ip6_neighbor_syslog (vm, LOG_WARNING, + "our AdvReachableTime on %U doesn't agree with %U", + format_vnet_sw_if_index_name, + vnm, sw_if_index0, + format_ip6_address, + &ip0->src_address); } /* check for MTU or prefix options or .. */ - u8 * opt_hdr = (u8 *)(h0 + 1); - while( options_len0 > 0) + u8 *opt_hdr = (u8 *) (h0 + 1); + while (options_len0 > 0) { - icmp6_neighbor_discovery_option_header_t *o0 = ( icmp6_neighbor_discovery_option_header_t *)opt_hdr; + icmp6_neighbor_discovery_option_header_t *o0 = + (icmp6_neighbor_discovery_option_header_t *) + opt_hdr; int opt_len = o0->n_data_u64s << 3; - icmp6_neighbor_discovery_option_type_t option_type = o0->type; + icmp6_neighbor_discovery_option_type_t option_type = + o0->type; - if(options_len0 < 2) + if (options_len0 < 2) { - ip6_neighbor_syslog(vm, LOG_ERR, - "malformed RA packet on %U from %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address); + ip6_neighbor_syslog (vm, LOG_ERR, + "malformed RA packet on %U from %U", + format_vnet_sw_if_index_name, + vnm, sw_if_index0, + format_ip6_address, + &ip0->src_address); break; } - if(opt_len == 0) + if (opt_len == 0) { - ip6_neighbor_syslog(vm, LOG_ERR, - " zero length option in RA on %U from %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address); + ip6_neighbor_syslog (vm, LOG_ERR, + " zero length option in RA on %U from %U", + format_vnet_sw_if_index_name, + vnm, sw_if_index0, + format_ip6_address, + &ip0->src_address); break; } - else if( opt_len > options_len0) + else if (opt_len > options_len0) { - ip6_neighbor_syslog(vm, LOG_ERR, - "option length in RA packet greater than total length on %U from %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address); + ip6_neighbor_syslog (vm, LOG_ERR, + "option length in RA packet greater than total length on %U from %U", + format_vnet_sw_if_index_name, + vnm, sw_if_index0, + format_ip6_address, + &ip0->src_address); break; } options_len0 -= opt_len; opt_hdr += opt_len; - switch(option_type) + switch (option_type) { case ICMP6_NEIGHBOR_DISCOVERY_OPTION_mtu: - { + { icmp6_neighbor_discovery_mtu_option_t *h = - (icmp6_neighbor_discovery_mtu_option_t *)(o0); + (icmp6_neighbor_discovery_mtu_option_t + *) (o0); - if(opt_len < sizeof(*h)) + if (opt_len < sizeof (*h)) break; - if((h->mtu && radv_info->adv_link_mtu) && - (h->mtu != clib_host_to_net_u32(radv_info->adv_link_mtu))) + if ((h->mtu && radv_info->adv_link_mtu) && + (h->mtu != + clib_host_to_net_u32 + (radv_info->adv_link_mtu))) { - ip6_neighbor_syslog(vm, LOG_WARNING, - "our AdvLinkMTU on %U doesn't agree with %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0, format_ip6_address, &ip0->src_address); + ip6_neighbor_syslog (vm, LOG_WARNING, + "our AdvLinkMTU on %U doesn't agree with %U", + format_vnet_sw_if_index_name, + vnm, sw_if_index0, + format_ip6_address, + &ip0->src_address); } } break; - + case ICMP6_NEIGHBOR_DISCOVERY_OPTION_prefix_information: { - icmp6_neighbor_discovery_prefix_information_option_t *h = - (icmp6_neighbor_discovery_prefix_information_option_t *)(o0); - + icmp6_neighbor_discovery_prefix_information_option_t + * h = + (icmp6_neighbor_discovery_prefix_information_option_t + *) (o0); + /* validate advertised prefix options */ - ip6_radv_prefix_t *pr_info; + ip6_radv_prefix_t *pr_info; u32 preferred, valid; - if(opt_len < sizeof(*h)) + if (opt_len < sizeof (*h)) break; - preferred = clib_net_to_host_u32(h->preferred_time); - valid = clib_net_to_host_u32(h->valid_time); + preferred = + clib_net_to_host_u32 (h->preferred_time); + valid = clib_net_to_host_u32 (h->valid_time); /* look for matching prefix - if we our advertising it, it better be consistant */ - pool_foreach (pr_info, radv_info->adv_prefixes_pool, ({ - - ip6_address_t mask; - ip6_address_mask_from_width(&mask, pr_info->prefix_len); - - if(pr_info->enabled && - (pr_info->prefix_len == h->dst_address_length) && - ip6_address_is_equal_masked (&pr_info->prefix, &h->dst_address, &mask)) - { - /* found it */ - if(!pr_info->decrement_lifetime_flag && - valid != pr_info->adv_valid_lifetime_in_secs) - { - ip6_neighbor_syslog(vm, LOG_WARNING, - "our ADV validlifetime on %U for %U does not agree with %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0,format_ip6_address, &pr_info->prefix, - format_ip6_address, &h->dst_address); - } - if(!pr_info->decrement_lifetime_flag && - preferred != pr_info->adv_pref_lifetime_in_secs) - { - ip6_neighbor_syslog(vm, LOG_WARNING, - "our ADV preferredlifetime on %U for %U does not agree with %U", - format_vnet_sw_if_index_name, vnm, sw_if_index0,format_ip6_address, &pr_info->prefix, - format_ip6_address, &h->dst_address); - } - } - break; - })); + /* *INDENT-OFF* */ + pool_foreach (pr_info, radv_info->adv_prefixes_pool, + ({ + + ip6_address_t mask; + ip6_address_mask_from_width(&mask, pr_info->prefix_len); + + if(pr_info->enabled && + (pr_info->prefix_len == h->dst_address_length) && + ip6_address_is_equal_masked (&pr_info->prefix, &h->dst_address, &mask)) + { + /* found it */ + if(!pr_info->decrement_lifetime_flag && + valid != pr_info->adv_valid_lifetime_in_secs) + { + ip6_neighbor_syslog(vm, LOG_WARNING, + "our ADV validlifetime on %U for %U does not agree with %U", + format_vnet_sw_if_index_name, vnm, sw_if_index0,format_ip6_address, &pr_info->prefix, + format_ip6_address, &h->dst_address); + } + if(!pr_info->decrement_lifetime_flag && + preferred != pr_info->adv_pref_lifetime_in_secs) + { + ip6_neighbor_syslog(vm, LOG_WARNING, + "our ADV preferredlifetime on %U for %U does not agree with %U", + format_vnet_sw_if_index_name, vnm, sw_if_index0,format_ip6_address, &pr_info->prefix, + format_ip6_address, &h->dst_address); + } + } + break; + })); + /* *INDENT-ON* */ break; } default: @@ -1750,19 +1877,21 @@ icmp6_router_advertisement(vlib_main_t * vm, p0->error = error_node->errors[error0]; - if(error0 != ICMP6_ERROR_NONE) + if (error0 != ICMP6_ERROR_NONE) vlib_error_count (vm, error_node->node_index, error0, 1); - + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); } - + vlib_put_next_frame (vm, node, next_index, n_left_to_next); } /* Account for router advertisements sent. */ - vlib_error_count (vm, error_node->node_index, ICMP6_ERROR_ROUTER_ADVERTISEMENTS_RX, n_advertisements_rcvd); + vlib_error_count (vm, error_node->node_index, + ICMP6_ERROR_ROUTER_ADVERTISEMENTS_RX, + n_advertisements_rcvd); return frame->n_vectors; } @@ -1770,257 +1899,275 @@ icmp6_router_advertisement(vlib_main_t * vm, /* create and initialize router advertisement parameters with default values for this intfc */ static u32 ip6_neighbor_sw_interface_add_del (vnet_main_t * vnm, - u32 sw_if_index, - u32 is_add) + u32 sw_if_index, u32 is_add) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - ip6_radv_t * a= 0; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + ip6_radv_t *a = 0; u32 ri = ~0; - vnet_sw_interface_t * sw_if0; - ethernet_interface_t * eth_if0 = 0; + vnet_sw_interface_t *sw_if0; + ethernet_interface_t *eth_if0 = 0; /* lookup radv container - ethernet interfaces only */ sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index); - if(sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE) + if (sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE) eth_if0 = ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); - if(!eth_if0) + if (!eth_if0) return ri; - - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); + + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, + ~0); ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - if(ri != ~0) + if (ri != ~0) { a = pool_elt_at_index (nm->if_radv_pool, ri); - if(!is_add) + if (!is_add) { - u32 i, * to_delete = 0; - ip6_radv_prefix_t *p; + u32 i, *to_delete = 0; + ip6_radv_prefix_t *p; ip6_mldp_group_t *m; - + /* remove adjacencies */ - adj_unlock(a->all_nodes_adj_index); - adj_unlock(a->all_routers_adj_index); - adj_unlock(a->all_mldv2_routers_adj_index); - + adj_unlock (a->all_nodes_adj_index); + adj_unlock (a->all_routers_adj_index); + adj_unlock (a->all_mldv2_routers_adj_index); + /* clean up prefix_pool */ - pool_foreach (p, a->adv_prefixes_pool, ({ - vec_add1 (to_delete, p - a->adv_prefixes_pool); - })); - + /* *INDENT-OFF* */ + pool_foreach (p, a->adv_prefixes_pool, + ({ + vec_add1 (to_delete, p - a->adv_prefixes_pool); + })); + /* *INDENT-ON* */ + for (i = 0; i < vec_len (to_delete); i++) { p = pool_elt_at_index (a->adv_prefixes_pool, to_delete[i]); mhash_unset (&a->address_to_prefix_index, &p->prefix, 0); pool_put (a->adv_prefixes_pool, p); } - + vec_free (to_delete); to_delete = 0; - + /* clean up mldp group pool */ - pool_foreach (m, a->mldp_group_pool, ({ - vec_add1 (to_delete, m - a->mldp_group_pool); - })); - + /* *INDENT-OFF* */ + pool_foreach (m, a->mldp_group_pool, + ({ + vec_add1 (to_delete, m - a->mldp_group_pool); + })); + /* *INDENT-ON* */ + for (i = 0; i < vec_len (to_delete); i++) { m = pool_elt_at_index (a->mldp_group_pool, to_delete[i]); mhash_unset (&a->address_to_mldp_index, &m->mcast_address, 0); pool_put (a->mldp_group_pool, m); } - + vec_free (to_delete); - - pool_put (nm->if_radv_pool, a); + + pool_put (nm->if_radv_pool, a); nm->if_radv_pool_index_by_sw_if_index[sw_if_index] = ~0; ri = ~0; } } - else - { - if(is_add) - { - vnet_hw_interface_t * hw_if0; - - hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index); - - pool_get (nm->if_radv_pool, a); - - ri = a - nm->if_radv_pool; - nm->if_radv_pool_index_by_sw_if_index[sw_if_index] = ri; - - /* initialize default values (most of which are zero) */ - memset (a, 0, sizeof (a[0])); - - a->sw_if_index = sw_if_index; - a->fib_index = ~0; - a->max_radv_interval = DEF_MAX_RADV_INTERVAL; - a->min_radv_interval = DEF_MIN_RADV_INTERVAL; - a->curr_hop_limit = DEF_CURR_HOP_LIMIT; - a->adv_router_lifetime_in_sec = DEF_DEF_RTR_LIFETIME; - - a->adv_link_layer_address = 1; /* send ll address source address option */ - - a->min_delay_between_radv = MIN_DELAY_BETWEEN_RAS; - a->max_delay_between_radv = MAX_DELAY_BETWEEN_RAS; - a->max_rtr_default_lifetime = MAX_DEF_RTR_LIFETIME; - a->seed = (u32) clib_cpu_time_now(); - (void) random_u32 (&a->seed); - a->randomizer = clib_cpu_time_now(); - (void) random_u64 (&a->randomizer); - - a->initial_adverts_count = MAX_INITIAL_RTR_ADVERTISEMENTS ; - a->initial_adverts_sent = a->initial_adverts_count-1; - a->initial_adverts_interval = MAX_INITIAL_RTR_ADVERT_INTERVAL; - - /* deafult is to send */ - a->send_radv = 1; - - /* fill in radv_info for this interface that will be needed later */ - a->adv_link_mtu = hw_if0->max_l3_packet_bytes[VLIB_RX]; - - clib_memcpy (a->link_layer_address, eth_if0->address, 6); - - /* fill in default link-local address (this may be overridden) */ - ip6_link_local_address_from_ethernet_address (&a->link_local_address, eth_if0->address); - a->link_local_prefix_len = 64; - - mhash_init (&a->address_to_prefix_index, sizeof (uword), sizeof (ip6_address_t)); - mhash_init (&a->address_to_mldp_index, sizeof (uword), sizeof (ip6_address_t)); - - { - u8 link_layer_address[6] = - {0x33, 0x33, 0x00, 0x00, 0x00, IP6_MULTICAST_GROUP_ID_all_hosts}; - - a->all_nodes_adj_index = adj_rewrite_add_and_lock(FIB_PROTOCOL_IP6, - VNET_LINK_IP6, - sw_if_index, - link_layer_address); - } - - { - u8 link_layer_address[6] = - {0x33, 0x33, 0x00, 0x00, 0x00, IP6_MULTICAST_GROUP_ID_all_routers}; - - a->all_routers_adj_index = adj_rewrite_add_and_lock(FIB_PROTOCOL_IP6, - VNET_LINK_IP6, - sw_if_index, - link_layer_address); - } - - { - u8 link_layer_address[6] = - {0x33, 0x33, 0x00, 0x00, 0x00, IP6_MULTICAST_GROUP_ID_mldv2_routers}; - - a->all_mldv2_routers_adj_index = - adj_rewrite_add_and_lock(FIB_PROTOCOL_IP6, + else + { + if (is_add) + { + vnet_hw_interface_t *hw_if0; + + hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index); + + pool_get (nm->if_radv_pool, a); + + ri = a - nm->if_radv_pool; + nm->if_radv_pool_index_by_sw_if_index[sw_if_index] = ri; + + /* initialize default values (most of which are zero) */ + memset (a, 0, sizeof (a[0])); + + a->sw_if_index = sw_if_index; + a->fib_index = ~0; + a->max_radv_interval = DEF_MAX_RADV_INTERVAL; + a->min_radv_interval = DEF_MIN_RADV_INTERVAL; + a->curr_hop_limit = DEF_CURR_HOP_LIMIT; + a->adv_router_lifetime_in_sec = DEF_DEF_RTR_LIFETIME; + + a->adv_link_layer_address = 1; /* send ll address source address option */ + + a->min_delay_between_radv = MIN_DELAY_BETWEEN_RAS; + a->max_delay_between_radv = MAX_DELAY_BETWEEN_RAS; + a->max_rtr_default_lifetime = MAX_DEF_RTR_LIFETIME; + a->seed = (u32) clib_cpu_time_now (); + (void) random_u32 (&a->seed); + a->randomizer = clib_cpu_time_now (); + (void) random_u64 (&a->randomizer); + + a->initial_adverts_count = MAX_INITIAL_RTR_ADVERTISEMENTS; + a->initial_adverts_sent = a->initial_adverts_count - 1; + a->initial_adverts_interval = MAX_INITIAL_RTR_ADVERT_INTERVAL; + + /* deafult is to send */ + a->send_radv = 1; + + /* fill in radv_info for this interface that will be needed later */ + a->adv_link_mtu = hw_if0->max_l3_packet_bytes[VLIB_RX]; + + clib_memcpy (a->link_layer_address, eth_if0->address, 6); + + /* fill in default link-local address (this may be overridden) */ + ip6_link_local_address_from_ethernet_address + (&a->link_local_address, eth_if0->address); + a->link_local_prefix_len = 64; + + mhash_init (&a->address_to_prefix_index, sizeof (uword), + sizeof (ip6_address_t)); + mhash_init (&a->address_to_mldp_index, sizeof (uword), + sizeof (ip6_address_t)); + + { + u8 link_layer_address[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, + IP6_MULTICAST_GROUP_ID_all_hosts + }; + + a->all_nodes_adj_index = + adj_rewrite_add_and_lock (FIB_PROTOCOL_IP6, VNET_LINK_IP6, + sw_if_index, link_layer_address); + } + + { + u8 link_layer_address[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, + IP6_MULTICAST_GROUP_ID_all_routers + }; + + a->all_routers_adj_index = + adj_rewrite_add_and_lock (FIB_PROTOCOL_IP6, VNET_LINK_IP6, + sw_if_index, link_layer_address); + } + + { + u8 link_layer_address[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, + IP6_MULTICAST_GROUP_ID_mldv2_routers + }; + + a->all_mldv2_routers_adj_index = + adj_rewrite_add_and_lock (FIB_PROTOCOL_IP6, VNET_LINK_IP6, - sw_if_index, - link_layer_address); - } - - /* add multicast groups we will always be reporting */ - ip6_address_t addr; - ip6_mldp_group_t *mcast_group_info; - - ip6_set_reserved_multicast_address (&addr, - IP6_MULTICAST_SCOPE_link_local, - IP6_MULTICAST_GROUP_ID_all_hosts); - - /* lookup mldp info for this interface */ - - uword * p = mhash_get (&a->address_to_mldp_index, &addr); - mcast_group_info = p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0; - - /* add address */ - if(!mcast_group_info) - { - /* add */ - u32 mi; - pool_get (a->mldp_group_pool, mcast_group_info); - - mi = mcast_group_info - a->mldp_group_pool; - mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ 0); - - mcast_group_info->type = 4; - mcast_group_info->mcast_source_address_pool = 0; - mcast_group_info->num_sources = 0; - clib_memcpy(&mcast_group_info->mcast_address, &addr, sizeof(ip6_address_t)); - } - - ip6_set_reserved_multicast_address (&addr, - IP6_MULTICAST_SCOPE_link_local, - IP6_MULTICAST_GROUP_ID_all_routers); - - p = mhash_get (&a->address_to_mldp_index, &addr); - mcast_group_info = p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0; - - if(!mcast_group_info) - { - /* add */ - u32 mi; - pool_get (a->mldp_group_pool, mcast_group_info); - - mi = mcast_group_info - a->mldp_group_pool; - mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ 0); - - mcast_group_info->type = 4; - mcast_group_info->mcast_source_address_pool = 0; - mcast_group_info->num_sources = 0; - clib_memcpy(&mcast_group_info->mcast_address, &addr, sizeof(ip6_address_t)); - } - - ip6_set_reserved_multicast_address (&addr, - IP6_MULTICAST_SCOPE_link_local, - IP6_MULTICAST_GROUP_ID_mldv2_routers); - - p = mhash_get (&a->address_to_mldp_index, &addr); - mcast_group_info = p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0; - - if(!mcast_group_info) - { - /* add */ - u32 mi; - pool_get (a->mldp_group_pool, mcast_group_info); - - mi = mcast_group_info - a->mldp_group_pool; - mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ 0); - - mcast_group_info->type = 4; - mcast_group_info->mcast_source_address_pool = 0; - mcast_group_info->num_sources = 0; - clib_memcpy(&mcast_group_info->mcast_address, &addr, sizeof(ip6_address_t)); - } - } - } - return ri; + sw_if_index, link_layer_address); + } + + /* add multicast groups we will always be reporting */ + ip6_address_t addr; + ip6_mldp_group_t *mcast_group_info; + + ip6_set_reserved_multicast_address (&addr, + IP6_MULTICAST_SCOPE_link_local, + IP6_MULTICAST_GROUP_ID_all_hosts); + + /* lookup mldp info for this interface */ + + uword *p = mhash_get (&a->address_to_mldp_index, &addr); + mcast_group_info = + p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0; + + /* add address */ + if (!mcast_group_info) + { + /* add */ + u32 mi; + pool_get (a->mldp_group_pool, mcast_group_info); + + mi = mcast_group_info - a->mldp_group_pool; + mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ + 0); + + mcast_group_info->type = 4; + mcast_group_info->mcast_source_address_pool = 0; + mcast_group_info->num_sources = 0; + clib_memcpy (&mcast_group_info->mcast_address, &addr, + sizeof (ip6_address_t)); + } + + ip6_set_reserved_multicast_address (&addr, + IP6_MULTICAST_SCOPE_link_local, + IP6_MULTICAST_GROUP_ID_all_routers); + + p = mhash_get (&a->address_to_mldp_index, &addr); + mcast_group_info = + p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0; + + if (!mcast_group_info) + { + /* add */ + u32 mi; + pool_get (a->mldp_group_pool, mcast_group_info); + + mi = mcast_group_info - a->mldp_group_pool; + mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ + 0); + + mcast_group_info->type = 4; + mcast_group_info->mcast_source_address_pool = 0; + mcast_group_info->num_sources = 0; + clib_memcpy (&mcast_group_info->mcast_address, &addr, + sizeof (ip6_address_t)); + } + + ip6_set_reserved_multicast_address (&addr, + IP6_MULTICAST_SCOPE_link_local, + IP6_MULTICAST_GROUP_ID_mldv2_routers); + + p = mhash_get (&a->address_to_mldp_index, &addr); + mcast_group_info = + p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0; + + if (!mcast_group_info) + { + /* add */ + u32 mi; + pool_get (a->mldp_group_pool, mcast_group_info); + + mi = mcast_group_info - a->mldp_group_pool; + mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ + 0); + + mcast_group_info->type = 4; + mcast_group_info->mcast_source_address_pool = 0; + mcast_group_info->num_sources = 0; + clib_memcpy (&mcast_group_info->mcast_address, &addr, + sizeof (ip6_address_t)); + } + } + } + return ri; } /* send an mldpv2 report */ static void -ip6_neighbor_send_mldpv2_report(u32 sw_if_index) +ip6_neighbor_send_mldpv2_report (u32 sw_if_index) { - vnet_main_t * vnm = vnet_get_main(); - vlib_main_t * vm = vnm->vlib_main; - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - vnet_sw_interface_t * sw_if0; - ethernet_interface_t * eth_if0; + vnet_main_t *vnm = vnet_get_main (); + vlib_main_t *vm = vnm->vlib_main; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + vnet_sw_interface_t *sw_if0; + ethernet_interface_t *eth_if0; u32 ri; int bogus_length; - ip6_radv_t *radv_info; + ip6_radv_t *radv_info; u16 payload_length; - vlib_buffer_t * b0; - ip6_header_t * ip0; - u32 * to_next; - vlib_frame_t * f; + vlib_buffer_t *b0; + ip6_header_t *ip0; + u32 *to_next; + vlib_frame_t *f; u32 bo0; u32 n_to_alloc = 1; u32 n_allocated; - + icmp6_multicast_listener_report_header_t *rh0; icmp6_multicast_listener_report_packet_t *rp0; @@ -2032,19 +2179,20 @@ ip6_neighbor_send_mldpv2_report(u32 sw_if_index) return; /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); - + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, + ~0); + ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - - if(ri == ~0) + + if (ri == ~0) return; - + /* send report now - build a mldpv2 report packet */ - n_allocated = vlib_buffer_alloc_from_free_list(vm, - &bo0, - n_to_alloc, - VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX); - if (PREDICT_FALSE(n_allocated == 0)) + n_allocated = vlib_buffer_alloc_from_free_list (vm, + &bo0, + n_to_alloc, + VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX); + if (PREDICT_FALSE (n_allocated == 0)) { clib_warning ("buffer allocation failure"); return; @@ -2053,36 +2201,37 @@ ip6_neighbor_send_mldpv2_report(u32 sw_if_index) b0 = vlib_get_buffer (vm, bo0); /* adjust the sizeof the buffer to just include the ipv6 header */ - b0->current_length = sizeof(icmp6_multicast_listener_report_packet_t); + b0->current_length = sizeof (icmp6_multicast_listener_report_packet_t); - payload_length = sizeof(icmp6_multicast_listener_report_header_t); + payload_length = sizeof (icmp6_multicast_listener_report_header_t); b0->error = ICMP6_ERROR_NONE; rp0 = vlib_buffer_get_current (b0); - ip0 = (ip6_header_t *)&rp0-> ip; - rh0 = (icmp6_multicast_listener_report_header_t *)&rp0-> report_hdr; - - memset (rp0 , 0x0, sizeof (icmp6_multicast_listener_report_packet_t)); - - ip0->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6 << 28); - - ip0->protocol = IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS; + ip0 = (ip6_header_t *) & rp0->ip; + rh0 = (icmp6_multicast_listener_report_header_t *) & rp0->report_hdr; + + memset (rp0, 0x0, sizeof (icmp6_multicast_listener_report_packet_t)); + + ip0->ip_version_traffic_class_and_flow_label = + clib_host_to_net_u32 (0x6 << 28); + + ip0->protocol = IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS; /* for DEBUG - vnet driver won't seem to emit router alerts */ /* ip0->protocol = IP_PROTOCOL_ICMP6; */ ip0->hop_limit = 1; - + rh0->icmp.type = ICMP6_multicast_listener_report_v2; - + /* source address MUST be the link-local address */ - radv_info = pool_elt_at_index (nm->if_radv_pool, ri); - ip0->src_address = radv_info->link_local_address; + radv_info = pool_elt_at_index (nm->if_radv_pool, ri); + ip0->src_address = radv_info->link_local_address; /* destination is all mldpv2 routers */ - ip6_set_reserved_multicast_address(&ip0->dst_address, - IP6_MULTICAST_SCOPE_link_local, - IP6_MULTICAST_GROUP_ID_mldv2_routers); - + ip6_set_reserved_multicast_address (&ip0->dst_address, + IP6_MULTICAST_SCOPE_link_local, + IP6_MULTICAST_GROUP_ID_mldv2_routers); + /* add reports here */ ip6_mldp_group_t *m; int num_addr_records = 0; @@ -2091,66 +2240,69 @@ ip6_neighbor_send_mldpv2_report(u32 sw_if_index) /* fill in the hop-by-hop extension header (router alert) info */ rh0->ext_hdr.next_hdr = IP_PROTOCOL_ICMP6; rh0->ext_hdr.n_data_u64s = 0; - + rh0->alert.type = IP6_MLDP_ALERT_TYPE; rh0->alert.len = 2; rh0->alert.value = 0; - + rh0->pad.type = 1; rh0->pad.len = 0; - + rh0->icmp.checksum = 0; - pool_foreach (m, radv_info->mldp_group_pool, ({ + /* *INDENT-OFF* */ + pool_foreach (m, radv_info->mldp_group_pool, + ({ + rr.type = m->type; + rr.aux_data_len_u32s = 0; + rr.num_sources = clib_host_to_net_u16 (m->num_sources); + clib_memcpy(&rr.mcast_addr, &m->mcast_address, sizeof(ip6_address_t)); - rr.type = m->type; - rr.aux_data_len_u32s = 0; - rr.num_sources = clib_host_to_net_u16 (m->num_sources); - clib_memcpy(&rr.mcast_addr, &m->mcast_address, sizeof(ip6_address_t)); + num_addr_records++; - num_addr_records++; + vlib_buffer_add_data + (vm, b0->free_list_index, bo0, + (void *)&rr, sizeof(icmp6_multicast_address_record_t)); - vlib_buffer_add_data (vm, - b0->free_list_index, - bo0, - (void *)&rr, sizeof(icmp6_multicast_address_record_t)); - - payload_length += sizeof( icmp6_multicast_address_record_t); - })); + payload_length += sizeof( icmp6_multicast_address_record_t); + })); + /* *INDENT-ON* */ rh0->rsvd = 0; - rh0->num_addr_records = clib_host_to_net_u16(num_addr_records); - + rh0->num_addr_records = clib_host_to_net_u16 (num_addr_records); + /* update lengths */ ip0->payload_length = clib_host_to_net_u16 (payload_length); - rh0->icmp.checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, - &bogus_length); - ASSERT(bogus_length == 0); + rh0->icmp.checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, + &bogus_length); + ASSERT (bogus_length == 0); - /* + /* * OK to override w/ no regard for actual FIB, because * ip6-rewrite only looks at the adjacency. */ - vnet_buffer (b0)->sw_if_index[VLIB_RX] = + vnet_buffer (b0)->sw_if_index[VLIB_RX] = vnet_main.local_interface_sw_if_index; - - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = + + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = radv_info->all_mldv2_routers_adj_index; b0->flags |= VNET_BUFFER_LOCALLY_ORIGINATED; - vlib_node_t * node = vlib_get_node_by_name (vm, (u8 *) "ip6-rewrite"); - + vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "ip6-rewrite"); + f = vlib_get_frame_to_node (vm, node->index); to_next = vlib_frame_vector_args (f); to_next[0] = bo0; f->n_vectors = 1; - + vlib_put_frame_to_node (vm, node->index, f); return; } -VLIB_REGISTER_NODE (ip6_icmp_router_solicitation_node,static) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_icmp_router_solicitation_node,static) = +{ .function = icmp6_router_solicitation, .name = "icmp6-router-solicitation", @@ -2165,135 +2317,136 @@ VLIB_REGISTER_NODE (ip6_icmp_router_solicitation_node,static) = { [ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_TX] = "interface-output", }, }; +/* *INDENT-ON* */ /* send a RA or update the timer info etc.. */ static uword ip6_neighbor_process_timer_event (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) + vlib_node_runtime_t * node, + vlib_frame_t * frame) { - vnet_main_t * vnm = vnet_get_main(); - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - ip6_radv_t *radv_info; - vlib_frame_t * f = 0; + vnet_main_t *vnm = vnet_get_main (); + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + ip6_radv_t *radv_info; + vlib_frame_t *f = 0; u32 n_this_frame = 0; u32 n_left_to_next = 0; - u32 * to_next = 0; - u32 bo0; - icmp6_router_solicitation_header_t * h0; - vlib_buffer_t * b0; + u32 *to_next = 0; + u32 bo0; + icmp6_router_solicitation_header_t *h0; + vlib_buffer_t *b0; f64 now = vlib_time_now (vm); /* Interface ip6 radv info list */ - pool_foreach (radv_info, nm->if_radv_pool, ({ + /* *INDENT-OFF* */ + pool_foreach (radv_info, nm->if_radv_pool, + ({ + if( !vnet_sw_interface_is_admin_up (vnm, radv_info->sw_if_index)) + { + radv_info->initial_adverts_sent = radv_info->initial_adverts_count-1; + radv_info->next_multicast_time = now; + radv_info->last_multicast_time = now; + radv_info->last_radv_time = 0; + radv_info->all_routers_mcast = 0; + continue; + } - if( !vnet_sw_interface_is_admin_up (vnm, radv_info->sw_if_index)) - { - radv_info->initial_adverts_sent = radv_info->initial_adverts_count-1; - radv_info->next_multicast_time = now; - radv_info->last_multicast_time = now; - radv_info->last_radv_time = 0; - radv_info->all_routers_mcast = 0; - continue; - } + /* Make sure that we've joined the all-routers multicast group */ + if(!radv_info->all_routers_mcast) + { + /* send MDLP_REPORT_EVENT message */ + ip6_neighbor_send_mldpv2_report(radv_info->sw_if_index); + radv_info->all_routers_mcast = 1; + } - /* Make sure that we've joined the all-routers multicast group */ - if(!radv_info->all_routers_mcast) - { - /* send MDLP_REPORT_EVENT message */ - ip6_neighbor_send_mldpv2_report(radv_info->sw_if_index); - radv_info->all_routers_mcast = 1; - } + /* is it time to send a multicast RA on this interface? */ + if(radv_info->send_radv && (now >= radv_info->next_multicast_time)) + { + u32 n_to_alloc = 1; + u32 n_allocated; + + f64 rfn = (radv_info->max_radv_interval - radv_info->min_radv_interval) * + random_f64 (&radv_info->seed) + radv_info->min_radv_interval; + + /* multicast send - compute next multicast send time */ + if( radv_info->initial_adverts_sent > 0) + { + radv_info->initial_adverts_sent--; + if(rfn > radv_info-> initial_adverts_interval) + rfn = radv_info-> initial_adverts_interval; + + /* check to see if we are ceasing to send */ + if( radv_info->initial_adverts_sent == 0) + if(radv_info->cease_radv) + radv_info->send_radv = 0; + } - /* is it time to send a multicast RA on this interface? */ - if(radv_info->send_radv && (now >= radv_info->next_multicast_time)) - { - u32 n_to_alloc = 1; - u32 n_allocated; - - f64 rfn = (radv_info->max_radv_interval - radv_info->min_radv_interval) * - random_f64 (&radv_info->seed) + radv_info->min_radv_interval; - - /* multicast send - compute next multicast send time */ - if( radv_info->initial_adverts_sent > 0) - { - radv_info->initial_adverts_sent--; - if(rfn > radv_info-> initial_adverts_interval) - rfn = radv_info-> initial_adverts_interval; - - /* check to see if we are ceasing to send */ - if( radv_info->initial_adverts_sent == 0) - if(radv_info->cease_radv) - radv_info->send_radv = 0; - } - - radv_info->next_multicast_time = rfn + now; - radv_info->last_multicast_time = now; - - /* send advert now - build a "solicted" router advert with unspecified source address */ - n_allocated = vlib_buffer_alloc_from_free_list(vm, - &bo0, - n_to_alloc, - VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX); - - if (PREDICT_FALSE(n_allocated == 0)) - { - clib_warning ("buffer allocation failure"); - continue; - } - b0 = vlib_get_buffer (vm, bo0); - b0->current_length = sizeof( icmp6_router_solicitation_header_t); - b0->error = ICMP6_ERROR_NONE; - vnet_buffer (b0)->sw_if_index[VLIB_RX] = radv_info->sw_if_index; - - h0 = vlib_buffer_get_current (b0); - - memset (h0, 0, sizeof (icmp6_router_solicitation_header_t)); - - h0->ip.ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6 << 28); - h0->ip.payload_length = clib_host_to_net_u16 (sizeof (icmp6_router_solicitation_header_t) - - STRUCT_OFFSET_OF (icmp6_router_solicitation_header_t, neighbor)); - h0->ip.protocol = IP_PROTOCOL_ICMP6; - h0->ip.hop_limit = 255; - - /* set src/dst address as "unspecified" this marks this packet as internally generated rather than recieved */ - h0->ip.src_address.as_u64[0] = 0; - h0->ip.src_address.as_u64[1] = 0; - - h0->ip.dst_address.as_u64[0] = 0; - h0->ip.dst_address.as_u64[1] = 0; - - h0->neighbor.icmp.type = ICMP6_router_solicitation; - - if (PREDICT_FALSE(f == 0)) - { - f = vlib_get_frame_to_node (vm, ip6_icmp_router_solicitation_node.index); - to_next = vlib_frame_vector_args (f); - n_left_to_next = VLIB_FRAME_SIZE; - n_this_frame = 0; - } - - n_this_frame++; - n_left_to_next--; - to_next[0] = bo0; - to_next += 1; - - if (PREDICT_FALSE(n_left_to_next == 0)) - { - f->n_vectors = n_this_frame; - vlib_put_frame_to_node (vm, ip6_icmp_router_solicitation_node.index, f); - f = 0; - } - } - })); + radv_info->next_multicast_time = rfn + now; + radv_info->last_multicast_time = now; + + /* send advert now - build a "solicted" router advert with unspecified source address */ + n_allocated = vlib_buffer_alloc_from_free_list + (vm, &bo0, n_to_alloc, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX); + + if (PREDICT_FALSE(n_allocated == 0)) + { + clib_warning ("buffer allocation failure"); + continue; + } + b0 = vlib_get_buffer (vm, bo0); + b0->current_length = sizeof( icmp6_router_solicitation_header_t); + b0->error = ICMP6_ERROR_NONE; + vnet_buffer (b0)->sw_if_index[VLIB_RX] = radv_info->sw_if_index; + + h0 = vlib_buffer_get_current (b0); + + memset (h0, 0, sizeof (icmp6_router_solicitation_header_t)); + + h0->ip.ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6 << 28); + h0->ip.payload_length = clib_host_to_net_u16 (sizeof (icmp6_router_solicitation_header_t) + - STRUCT_OFFSET_OF (icmp6_router_solicitation_header_t, neighbor)); + h0->ip.protocol = IP_PROTOCOL_ICMP6; + h0->ip.hop_limit = 255; + + /* set src/dst address as "unspecified" this marks this packet as internally generated rather than recieved */ + h0->ip.src_address.as_u64[0] = 0; + h0->ip.src_address.as_u64[1] = 0; + + h0->ip.dst_address.as_u64[0] = 0; + h0->ip.dst_address.as_u64[1] = 0; + + h0->neighbor.icmp.type = ICMP6_router_solicitation; + + if (PREDICT_FALSE(f == 0)) + { + f = vlib_get_frame_to_node (vm, ip6_icmp_router_solicitation_node.index); + to_next = vlib_frame_vector_args (f); + n_left_to_next = VLIB_FRAME_SIZE; + n_this_frame = 0; + } + + n_this_frame++; + n_left_to_next--; + to_next[0] = bo0; + to_next += 1; + + if (PREDICT_FALSE(n_left_to_next == 0)) + { + f->n_vectors = n_this_frame; + vlib_put_frame_to_node (vm, ip6_icmp_router_solicitation_node.index, f); + f = 0; + } + } + })); + /* *INDENT-ON* */ if (f) { - ASSERT(n_this_frame); + ASSERT (n_this_frame); f->n_vectors = n_this_frame; vlib_put_frame_to_node (vm, ip6_icmp_router_solicitation_node.index, f); } - return 0; + return 0; } static uword @@ -2302,36 +2455,37 @@ ip6_icmp_neighbor_discovery_event_process (vlib_main_t * vm, vlib_frame_t * frame) { uword event_type; - ip6_icmp_neighbor_discovery_event_data_t * event_data; + ip6_icmp_neighbor_discovery_event_data_t *event_data; /* init code here */ - + while (1) { - vlib_process_wait_for_event_or_clock (vm, 1. /* seconds */); + vlib_process_wait_for_event_or_clock (vm, 1. /* seconds */ ); - event_data = vlib_process_get_event_data (vm, &event_type); + event_data = vlib_process_get_event_data (vm, &event_type); - if(!event_data) + if (!event_data) { /* No events found: timer expired. */ /* process interface list and send RAs as appropriate, update timer info */ - ip6_neighbor_process_timer_event (vm, node, frame); + ip6_neighbor_process_timer_event (vm, node, frame); } else { - switch (event_type) { + switch (event_type) + { + + case ICMP6_ND_EVENT_INIT: + break; + + case ~0: + break; + + default: + ASSERT (0); + } - case ICMP6_ND_EVENT_INIT: - break; - - case ~0: - break; - - default: - ASSERT (0); - } - if (event_data) _vec_len (event_data) = 0; } @@ -2339,7 +2493,9 @@ ip6_icmp_neighbor_discovery_event_process (vlib_main_t * vm, return frame->n_vectors; } -VLIB_REGISTER_NODE (ip6_icmp_router_advertisement_node,static) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_icmp_router_advertisement_node,static) = +{ .function = icmp6_router_advertisement, .name = "icmp6-router-advertisement", @@ -2352,6 +2508,7 @@ VLIB_REGISTER_NODE (ip6_icmp_router_advertisement_node,static) = { [0] = "error-drop", }, }; +/* *INDENT-ON* */ vlib_node_registration_t ip6_icmp_neighbor_discovery_event_node = { @@ -2362,17 +2519,26 @@ vlib_node_registration_t ip6_icmp_neighbor_discovery_event_node = { static uword icmp6_neighbor_solicitation (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ return icmp6_neighbor_solicitation_or_advertisement (vm, node, frame, /* is_solicitation */ 1); } + vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + return icmp6_neighbor_solicitation_or_advertisement (vm, node, frame, + /* is_solicitation */ + 1); +} static uword icmp6_neighbor_advertisement (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) -{ return icmp6_neighbor_solicitation_or_advertisement (vm, node, frame, /* is_solicitation */ 0); } +{ + return icmp6_neighbor_solicitation_or_advertisement (vm, node, frame, + /* is_solicitation */ + 0); +} -VLIB_REGISTER_NODE (ip6_icmp_neighbor_solicitation_node,static) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_icmp_neighbor_solicitation_node,static) = +{ .function = icmp6_neighbor_solicitation, .name = "icmp6-neighbor-solicitation", @@ -2386,8 +2552,11 @@ VLIB_REGISTER_NODE (ip6_icmp_neighbor_solicitation_node,static) = { [ICMP6_NEIGHBOR_SOLICITATION_NEXT_REPLY] = "interface-output", }, }; +/* *INDENT-ON* */ -VLIB_REGISTER_NODE (ip6_icmp_neighbor_advertisement_node,static) = { +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip6_icmp_neighbor_advertisement_node,static) = +{ .function = icmp6_neighbor_advertisement, .name = "icmp6-neighbor-advertisement", @@ -2400,277 +2569,307 @@ VLIB_REGISTER_NODE (ip6_icmp_neighbor_advertisement_node,static) = { [0] = "error-drop", }, }; +/* *INDENT-ON* */ -/* API support functions */ +/* API support functions */ int -ip6_neighbor_ra_config(vlib_main_t * vm, u32 sw_if_index, - u8 suppress, u8 managed, u8 other, - u8 ll_option, u8 send_unicast, u8 cease, - u8 use_lifetime, u32 lifetime, - u32 initial_count, u32 initial_interval, - u32 max_interval, u32 min_interval, - u8 is_no) -{ - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - int error; +ip6_neighbor_ra_config (vlib_main_t * vm, u32 sw_if_index, + u8 suppress, u8 managed, u8 other, + u8 ll_option, u8 send_unicast, u8 cease, + u8 use_lifetime, u32 lifetime, + u32 initial_count, u32 initial_interval, + u32 max_interval, u32 min_interval, u8 is_no) +{ + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + int error; u32 ri; /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, + ~0); ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - error = (ri != ~0) ? 0 : VNET_API_ERROR_INVALID_SW_IF_INDEX; + error = (ri != ~0) ? 0 : VNET_API_ERROR_INVALID_SW_IF_INDEX; - if(!error) + if (!error) { - ip6_radv_t * radv_info; - radv_info = pool_elt_at_index (nm->if_radv_pool, ri); - - if((max_interval != 0) && (min_interval ==0)) - min_interval = .75 * max_interval; - - max_interval = (max_interval != 0) ? ( (is_no) ? DEF_MAX_RADV_INTERVAL : max_interval) : radv_info->max_radv_interval; - min_interval = (min_interval != 0) ? ( (is_no) ? DEF_MIN_RADV_INTERVAL : min_interval) : radv_info->min_radv_interval; - lifetime = (use_lifetime != 0) ? ( (is_no) ? DEF_DEF_RTR_LIFETIME : lifetime) : radv_info->adv_router_lifetime_in_sec; - - if(lifetime) + ip6_radv_t *radv_info; + radv_info = pool_elt_at_index (nm->if_radv_pool, ri); + + if ((max_interval != 0) && (min_interval == 0)) + min_interval = .75 * max_interval; + + max_interval = + (max_interval != + 0) ? ((is_no) ? DEF_MAX_RADV_INTERVAL : max_interval) : + radv_info->max_radv_interval; + min_interval = + (min_interval != + 0) ? ((is_no) ? DEF_MIN_RADV_INTERVAL : min_interval) : + radv_info->min_radv_interval; + lifetime = + (use_lifetime != + 0) ? ((is_no) ? DEF_DEF_RTR_LIFETIME : lifetime) : + radv_info->adv_router_lifetime_in_sec; + + if (lifetime) { - if(lifetime > MAX_DEF_RTR_LIFETIME) + if (lifetime > MAX_DEF_RTR_LIFETIME) lifetime = MAX_DEF_RTR_LIFETIME; - - if(lifetime <= max_interval) - return VNET_API_ERROR_INVALID_VALUE; + + if (lifetime <= max_interval) + return VNET_API_ERROR_INVALID_VALUE; } - - if(min_interval != 0) + + if (min_interval != 0) { - if((min_interval > .75 * max_interval) || - (min_interval < 3)) - return VNET_API_ERROR_INVALID_VALUE; + if ((min_interval > .75 * max_interval) || (min_interval < 3)) + return VNET_API_ERROR_INVALID_VALUE; } - if((initial_count > MAX_INITIAL_RTR_ADVERTISEMENTS) || - (initial_interval > MAX_INITIAL_RTR_ADVERT_INTERVAL)) - return VNET_API_ERROR_INVALID_VALUE; - - /* - if "flag" is set and is_no is true then restore default value else set value corresponding to "flag" - if "flag" is clear don't change corresponding value - */ - radv_info->send_radv = (suppress != 0) ? ( (is_no != 0) ? 1 : 0 ) : radv_info->send_radv; - radv_info->adv_managed_flag = ( managed != 0) ? ( (is_no) ? 0 : 1) : radv_info->adv_managed_flag; - radv_info->adv_other_flag = (other != 0) ? ( (is_no) ? 0: 1) : radv_info->adv_other_flag; - radv_info->adv_link_layer_address = ( ll_option != 0) ? ( (is_no) ? 1 : 0) : radv_info->adv_link_layer_address; - radv_info->send_unicast = (send_unicast != 0) ? ( (is_no) ? 0 : 1) : radv_info->send_unicast; - radv_info->cease_radv = ( cease != 0) ? ( (is_no) ? 0 : 1) : radv_info->cease_radv; - - radv_info->min_radv_interval = min_interval; + if ((initial_count > MAX_INITIAL_RTR_ADVERTISEMENTS) || + (initial_interval > MAX_INITIAL_RTR_ADVERT_INTERVAL)) + return VNET_API_ERROR_INVALID_VALUE; + + /* + if "flag" is set and is_no is true then restore default value else set value corresponding to "flag" + if "flag" is clear don't change corresponding value + */ + radv_info->send_radv = + (suppress != 0) ? ((is_no != 0) ? 1 : 0) : radv_info->send_radv; + radv_info->adv_managed_flag = + (managed != 0) ? ((is_no) ? 0 : 1) : radv_info->adv_managed_flag; + radv_info->adv_other_flag = + (other != 0) ? ((is_no) ? 0 : 1) : radv_info->adv_other_flag; + radv_info->adv_link_layer_address = + (ll_option != + 0) ? ((is_no) ? 1 : 0) : radv_info->adv_link_layer_address; + radv_info->send_unicast = + (send_unicast != 0) ? ((is_no) ? 0 : 1) : radv_info->send_unicast; + radv_info->cease_radv = + (cease != 0) ? ((is_no) ? 0 : 1) : radv_info->cease_radv; + + radv_info->min_radv_interval = min_interval; radv_info->max_radv_interval = max_interval; radv_info->adv_router_lifetime_in_sec = lifetime; - radv_info->initial_adverts_count = - (initial_count != 0) ? ( (is_no) ? MAX_INITIAL_RTR_ADVERTISEMENTS : initial_count) : radv_info->initial_adverts_count ; - radv_info->initial_adverts_interval = - (initial_interval != 0) ? ( (is_no) ? MAX_INITIAL_RTR_ADVERT_INTERVAL : initial_interval) : radv_info->initial_adverts_interval; + radv_info->initial_adverts_count = + (initial_count != + 0) ? ((is_no) ? MAX_INITIAL_RTR_ADVERTISEMENTS : initial_count) : + radv_info->initial_adverts_count; + radv_info->initial_adverts_interval = + (initial_interval != + 0) ? ((is_no) ? MAX_INITIAL_RTR_ADVERT_INTERVAL : initial_interval) : + radv_info->initial_adverts_interval; /* restart */ - if((cease != 0) && (is_no)) - radv_info-> send_radv = 1; + if ((cease != 0) && (is_no)) + radv_info->send_radv = 1; - radv_info->initial_adverts_sent = radv_info->initial_adverts_count -1; - radv_info->next_multicast_time = vlib_time_now (vm); + radv_info->initial_adverts_sent = radv_info->initial_adverts_count - 1; + radv_info->next_multicast_time = vlib_time_now (vm); radv_info->last_multicast_time = vlib_time_now (vm); - radv_info->last_radv_time = 0; + radv_info->last_radv_time = 0; } - return(error); + return (error); } int -ip6_neighbor_ra_prefix(vlib_main_t * vm, u32 sw_if_index, - ip6_address_t *prefix_addr, u8 prefix_len, - u8 use_default, u32 val_lifetime, u32 pref_lifetime, - u8 no_advertise, u8 off_link, u8 no_autoconfig, u8 no_onlink, - u8 is_no) +ip6_neighbor_ra_prefix (vlib_main_t * vm, u32 sw_if_index, + ip6_address_t * prefix_addr, u8 prefix_len, + u8 use_default, u32 val_lifetime, u32 pref_lifetime, + u8 no_advertise, u8 off_link, u8 no_autoconfig, + u8 no_onlink, u8 is_no) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; int error; - + u32 ri; /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); - + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, + ~0); + ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; error = (ri != ~0) ? 0 : VNET_API_ERROR_INVALID_SW_IF_INDEX; - - if(!error) + + if (!error) { f64 now = vlib_time_now (vm); - ip6_radv_t * radv_info; - radv_info = pool_elt_at_index (nm->if_radv_pool, ri); + ip6_radv_t *radv_info; + radv_info = pool_elt_at_index (nm->if_radv_pool, ri); /* prefix info add, delete or update */ - ip6_radv_prefix_t * prefix; - + ip6_radv_prefix_t *prefix; + /* lookup prefix info for this address on this interface */ - uword * p = mhash_get (&radv_info->address_to_prefix_index, prefix_addr); - + uword *p = mhash_get (&radv_info->address_to_prefix_index, prefix_addr); + prefix = p ? pool_elt_at_index (radv_info->adv_prefixes_pool, p[0]) : 0; - if(is_no) + if (is_no) { /* delete */ - if(!prefix) - return VNET_API_ERROR_INVALID_VALUE; /* invalid prefix */ - - if(prefix->prefix_len != prefix_len) + if (!prefix) + return VNET_API_ERROR_INVALID_VALUE; /* invalid prefix */ + + if (prefix->prefix_len != prefix_len) return VNET_API_ERROR_INVALID_VALUE_2; - /* FIXME - Should the DP do this or the CP ?*/ + /* FIXME - Should the DP do this or the CP ? */ /* do specific delete processing here before returning */ /* try to remove from routing table */ - mhash_unset (&radv_info->address_to_prefix_index, prefix_addr,/* old_value */ 0); + mhash_unset (&radv_info->address_to_prefix_index, prefix_addr, + /* old_value */ 0); pool_put (radv_info->adv_prefixes_pool, prefix); - radv_info->initial_adverts_sent = radv_info->initial_adverts_count -1; - radv_info->next_multicast_time = vlib_time_now (vm); + radv_info->initial_adverts_sent = + radv_info->initial_adverts_count - 1; + radv_info->next_multicast_time = vlib_time_now (vm); radv_info->last_multicast_time = vlib_time_now (vm); - radv_info->last_radv_time = 0; - return(error); + radv_info->last_radv_time = 0; + return (error); } /* adding or changing */ - if(!prefix) + if (!prefix) { /* add */ u32 pi; pool_get (radv_info->adv_prefixes_pool, prefix); pi = prefix - radv_info->adv_prefixes_pool; - mhash_set (&radv_info->address_to_prefix_index, prefix_addr, pi, /* old_value */ 0); - - memset(prefix, 0x0, sizeof(ip6_radv_prefix_t)); - + mhash_set (&radv_info->address_to_prefix_index, prefix_addr, pi, + /* old_value */ 0); + + memset (prefix, 0x0, sizeof (ip6_radv_prefix_t)); + prefix->prefix_len = prefix_len; - clib_memcpy(&prefix->prefix, prefix_addr, sizeof(ip6_address_t)); - + clib_memcpy (&prefix->prefix, prefix_addr, sizeof (ip6_address_t)); + /* initialize default values */ - prefix->adv_on_link_flag = 1; /* L bit set */ - prefix->adv_autonomous_flag = 1; /* A bit set */ - prefix->adv_valid_lifetime_in_secs = DEF_ADV_VALID_LIFETIME; + prefix->adv_on_link_flag = 1; /* L bit set */ + prefix->adv_autonomous_flag = 1; /* A bit set */ + prefix->adv_valid_lifetime_in_secs = DEF_ADV_VALID_LIFETIME; prefix->adv_pref_lifetime_in_secs = DEF_ADV_PREF_LIFETIME; prefix->enabled = 1; prefix->decrement_lifetime_flag = 1; prefix->deprecated_prefix_flag = 1; - if(off_link == 0) + if (off_link == 0) { - /* FIXME - Should the DP do this or the CP ?*/ + /* FIXME - Should the DP do this or the CP ? */ /* insert prefix into routing table as a connected prefix */ } - if(use_default) + if (use_default) goto restart; } else { - - if(prefix->prefix_len != prefix_len) + + if (prefix->prefix_len != prefix_len) return VNET_API_ERROR_INVALID_VALUE_2; - if(off_link != 0) + if (off_link != 0) { - /* FIXME - Should the DP do this or the CP ?*/ + /* FIXME - Should the DP do this or the CP ? */ /* remove from routing table if already there */ - } + } } - if((val_lifetime == ~0) || (pref_lifetime == ~0)) + if ((val_lifetime == ~0) || (pref_lifetime == ~0)) { - prefix->adv_valid_lifetime_in_secs = ~0; + prefix->adv_valid_lifetime_in_secs = ~0; prefix->adv_pref_lifetime_in_secs = ~0; prefix->decrement_lifetime_flag = 0; } else { - prefix->adv_valid_lifetime_in_secs = val_lifetime;; - prefix->adv_pref_lifetime_in_secs = pref_lifetime; + prefix->adv_valid_lifetime_in_secs = val_lifetime;; + prefix->adv_pref_lifetime_in_secs = pref_lifetime; } - + /* copy remaining */ prefix->enabled = !(no_advertise != 0); prefix->adv_on_link_flag = !((off_link != 0) || (no_onlink != 0)); prefix->adv_autonomous_flag = !(no_autoconfig != 0); - restart: + restart: /* restart */ /* fill in the expiration times */ - prefix->valid_lifetime_expires = now + prefix->adv_valid_lifetime_in_secs; + prefix->valid_lifetime_expires = + now + prefix->adv_valid_lifetime_in_secs; prefix->pref_lifetime_expires = now + prefix->adv_pref_lifetime_in_secs; - - radv_info->initial_adverts_sent = radv_info->initial_adverts_count -1; - radv_info->next_multicast_time = vlib_time_now (vm); + + radv_info->initial_adverts_sent = radv_info->initial_adverts_count - 1; + radv_info->next_multicast_time = vlib_time_now (vm); radv_info->last_multicast_time = vlib_time_now (vm); - radv_info->last_radv_time = 0; + radv_info->last_radv_time = 0; } - return(error); + return (error); } clib_error_t * -ip6_neighbor_cmd(vlib_main_t * vm, unformat_input_t * main_input, vlib_cli_command_t * cmd) +ip6_neighbor_cmd (vlib_main_t * vm, unformat_input_t * main_input, + vlib_cli_command_t * cmd) { - vnet_main_t * vnm = vnet_get_main(); - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - clib_error_t * error = 0; + vnet_main_t *vnm = vnet_get_main (); + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + clib_error_t *error = 0; u8 is_no = 0; - u8 suppress = 0, managed = 0, other = 0; - u8 suppress_ll_option = 0, send_unicast = 0, cease= 0; + u8 suppress = 0, managed = 0, other = 0; + u8 suppress_ll_option = 0, send_unicast = 0, cease = 0; u8 use_lifetime = 0; - u32 sw_if_index, ra_lifetime = 0, ra_initial_count = 0, ra_initial_interval = 0; - u32 ra_max_interval = 0 , ra_min_interval = 0; + u32 sw_if_index, ra_lifetime = 0, ra_initial_count = + 0, ra_initial_interval = 0; + u32 ra_max_interval = 0, ra_min_interval = 0; - unformat_input_t _line_input, * line_input = &_line_input; - vnet_sw_interface_t * sw_if0; + unformat_input_t _line_input, *line_input = &_line_input; + vnet_sw_interface_t *sw_if0; int add_radv_info = 1; - __attribute__((unused)) ip6_radv_t * radv_info = 0; + __attribute__ ((unused)) ip6_radv_t *radv_info = 0; ip6_address_t ip6_addr; u32 addr_len; - + /* Get a line of input. */ - if (! unformat_user (main_input, unformat_line_input, line_input)) + if (!unformat_user (main_input, unformat_line_input, line_input)) return 0; /* get basic radv info for this interface */ - if(unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + if (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { - if (unformat_user (line_input, + if (unformat_user (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index)) { u32 ri; - ethernet_interface_t * eth_if0 = 0; - + ethernet_interface_t *eth_if0 = 0; + sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index); - if(sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE) - eth_if0 = ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); - - if(!eth_if0) + if (sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE) + eth_if0 = + ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); + + if (!eth_if0) { - error = clib_error_return (0, "Interface must be of ethernet type"); + error = + clib_error_return (0, "Interface must be of ethernet type"); goto done; } - + /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); - + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, + sw_if_index, ~0); + ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - - if(ri != ~0) + + if (ri != ~0) { - radv_info = pool_elt_at_index (nm->if_radv_pool, ri); + radv_info = pool_elt_at_index (nm->if_radv_pool, ri); } else { @@ -2691,10 +2890,9 @@ ip6_neighbor_cmd(vlib_main_t * vm, unformat_input_t * main_input, vlib_cli_comma while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "no")) - is_no = 1; - else if(unformat (line_input, "prefix %U/%d", - unformat_ip6_address, &ip6_addr, - &addr_len)) + is_no = 1; + else if (unformat (line_input, "prefix %U/%d", + unformat_ip6_address, &ip6_addr, &addr_len)) { add_radv_info = 0; break; @@ -2710,13 +2908,13 @@ ip6_neighbor_cmd(vlib_main_t * vm, unformat_input_t * main_input, vlib_cli_comma break; } else if (unformat (line_input, "ra-suppress") || - unformat (line_input, "ra-surpress")) + unformat (line_input, "ra-surpress")) { suppress = 1; break; } else if (unformat (line_input, "ra-suppress-link-layer") || - unformat (line_input, "ra-surpress-link-layer")) + unformat (line_input, "ra-surpress-link-layer")) { suppress_ll_option = 1; break; @@ -2729,70 +2927,70 @@ ip6_neighbor_cmd(vlib_main_t * vm, unformat_input_t * main_input, vlib_cli_comma else if (unformat (line_input, "ra-lifetime")) { if (!unformat (line_input, "%d", &ra_lifetime)) - return(error = unformat_parse_error (line_input)); + return (error = unformat_parse_error (line_input)); use_lifetime = 1; break; - } + } else if (unformat (line_input, "ra-initial")) { - if (!unformat (line_input, "%d %d", &ra_initial_count, &ra_initial_interval)) - return(error = unformat_parse_error (line_input)); + if (!unformat + (line_input, "%d %d", &ra_initial_count, &ra_initial_interval)) + return (error = unformat_parse_error (line_input)); break; } else if (unformat (line_input, "ra-interval")) { if (!unformat (line_input, "%d", &ra_max_interval)) - return(error = unformat_parse_error (line_input)); + return (error = unformat_parse_error (line_input)); if (!unformat (line_input, "%d", &ra_min_interval)) ra_min_interval = 0; break; } - else if(unformat (line_input, "ra-cease")) + else if (unformat (line_input, "ra-cease")) { cease = 1; break; } else - return(unformat_parse_error (line_input)); + return (unformat_parse_error (line_input)); } - if(add_radv_info) + if (add_radv_info) { - ip6_neighbor_ra_config(vm, sw_if_index, - suppress, managed, other, - suppress_ll_option, send_unicast, cease, - use_lifetime, ra_lifetime, - ra_initial_count, ra_initial_interval, - ra_max_interval, ra_min_interval, - is_no); + ip6_neighbor_ra_config (vm, sw_if_index, + suppress, managed, other, + suppress_ll_option, send_unicast, cease, + use_lifetime, ra_lifetime, + ra_initial_count, ra_initial_interval, + ra_max_interval, ra_min_interval, is_no); } else { - u32 valid_lifetime_in_secs = 0; + u32 valid_lifetime_in_secs = 0; u32 pref_lifetime_in_secs = 0; u8 use_prefix_default_values = 0; - u8 no_advertise = 0; - u8 off_link= 0; + u8 no_advertise = 0; + u8 off_link = 0; u8 no_autoconfig = 0; - u8 no_onlink= 0; + u8 no_onlink = 0; /* get the rest of the command */ - while(unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { - if(unformat (line_input, "default")) + if (unformat (line_input, "default")) { use_prefix_default_values = 1; break; } - else if(unformat (line_input, "infinite")) + else if (unformat (line_input, "infinite")) { - valid_lifetime_in_secs = ~0; + valid_lifetime_in_secs = ~0; pref_lifetime_in_secs = ~0; break; } - else if(unformat (line_input, "%d %d", &valid_lifetime_in_secs, - &pref_lifetime_in_secs)) + else if (unformat (line_input, "%d %d", &valid_lifetime_in_secs, + &pref_lifetime_in_secs)) break; else break; @@ -2803,104 +3001,103 @@ ip6_neighbor_cmd(vlib_main_t * vm, unformat_input_t * main_input, vlib_cli_comma while (!use_prefix_default_values && unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { - if(unformat (line_input, "no-advertise")) + if (unformat (line_input, "no-advertise")) no_advertise = 1; - else if(unformat (line_input, "off-link")) + else if (unformat (line_input, "off-link")) off_link = 1; - else if(unformat (line_input, "no-autoconfig")) + else if (unformat (line_input, "no-autoconfig")) no_autoconfig = 1; - else if(unformat (line_input, "no-onlink")) + else if (unformat (line_input, "no-onlink")) no_onlink = 1; else - return(unformat_parse_error (line_input)); + return (unformat_parse_error (line_input)); } - - ip6_neighbor_ra_prefix(vm, sw_if_index, - &ip6_addr, addr_len, - use_prefix_default_values, - valid_lifetime_in_secs, - pref_lifetime_in_secs, - no_advertise, - off_link, - no_autoconfig, - no_onlink, - is_no); + + ip6_neighbor_ra_prefix (vm, sw_if_index, + &ip6_addr, addr_len, + use_prefix_default_values, + valid_lifetime_in_secs, + pref_lifetime_in_secs, + no_advertise, + off_link, no_autoconfig, no_onlink, is_no); } unformat_free (line_input); - - done: + +done: return error; } static void -ip6_print_addrs(vlib_main_t * vm, - u32 *addrs) +ip6_print_addrs (vlib_main_t * vm, u32 * addrs) { - ip_lookup_main_t * lm = &ip6_main.lookup_main; + ip_lookup_main_t *lm = &ip6_main.lookup_main; u32 i; for (i = 0; i < vec_len (addrs); i++) { - ip_interface_address_t * a = pool_elt_at_index(lm->if_address_pool, addrs[i]); - ip6_address_t * address = ip_interface_address_get_address (lm, a); + ip_interface_address_t *a = + pool_elt_at_index (lm->if_address_pool, addrs[i]); + ip6_address_t *address = ip_interface_address_get_address (lm, a); vlib_cli_output (vm, "\t\t%U/%d", - format_ip6_address, address, - a->address_length); + format_ip6_address, address, a->address_length); } } static clib_error_t * show_ip6_interface_cmd (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) + unformat_input_t * input, vlib_cli_command_t * cmd) { - vnet_main_t * vnm = vnet_get_main(); - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - clib_error_t * error = 0; + vnet_main_t *vnm = vnet_get_main (); + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + clib_error_t *error = 0; u32 sw_if_index; sw_if_index = ~0; - if (unformat_user (input, - unformat_vnet_sw_interface, vnm, &sw_if_index)) + if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index)) { u32 ri; - + /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); - + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, + sw_if_index, ~0); + ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - - if(ri != ~0) + + if (ri != ~0) { - ip_lookup_main_t * lm = &ip6_main.lookup_main; - ip6_radv_t * radv_info; - radv_info = pool_elt_at_index (nm->if_radv_pool, ri); + ip_lookup_main_t *lm = &ip6_main.lookup_main; + ip6_radv_t *radv_info; + radv_info = pool_elt_at_index (nm->if_radv_pool, ri); - vlib_cli_output (vm, "%U is admin %s\n", format_vnet_sw_interface_name, vnm, + vlib_cli_output (vm, "%U is admin %s\n", + format_vnet_sw_interface_name, vnm, vnet_get_sw_interface (vnm, sw_if_index), - (vnet_sw_interface_is_admin_up (vnm, sw_if_index) ? "up" : "down")); - + (vnet_sw_interface_is_admin_up (vnm, sw_if_index) ? + "up" : "down")); + u32 ai; u32 *link_scope = 0, *global_scope = 0; u32 *local_scope = 0, *unknown_scope = 0; - ip_interface_address_t * a; + ip_interface_address_t *a; - vec_validate_init_empty (lm->if_address_pool_index_by_sw_if_index, sw_if_index, ~0); + vec_validate_init_empty (lm->if_address_pool_index_by_sw_if_index, + sw_if_index, ~0); ai = lm->if_address_pool_index_by_sw_if_index[sw_if_index]; - while (ai != (u32)~0) + while (ai != (u32) ~ 0) { - a = pool_elt_at_index(lm->if_address_pool, ai); - ip6_address_t * address = ip_interface_address_get_address (lm, a); + a = pool_elt_at_index (lm->if_address_pool, ai); + ip6_address_t *address = + ip_interface_address_get_address (lm, a); if (ip6_address_is_link_local_unicast (address)) vec_add1 (link_scope, ai); - else if(ip6_address_is_global_unicast (address)) + else if (ip6_address_is_global_unicast (address)) vec_add1 (global_scope, ai); - else if(ip6_address_is_local_unicast (address)) + else if (ip6_address_is_local_unicast (address)) vec_add1 (local_scope, ai); else vec_add1 (unknown_scope, ai); @@ -2908,48 +3105,55 @@ show_ip6_interface_cmd (vlib_main_t * vm, ai = a->next_this_sw_interface; } - if (vec_len (link_scope)) - { - vlib_cli_output (vm, "\tLink-local address(es):\n"); - ip6_print_addrs (vm, link_scope); - vec_free (link_scope); - } - - if (vec_len (local_scope)) - { - vlib_cli_output (vm, "\tLocal unicast address(es):\n"); - ip6_print_addrs (vm, local_scope); - vec_free (local_scope); - } - - if (vec_len (global_scope)) - { - vlib_cli_output (vm, "\tGlobal unicast address(es):\n"); - ip6_print_addrs (vm, global_scope); - vec_free (global_scope); - } - - if (vec_len (unknown_scope)) - { - vlib_cli_output (vm, "\tOther-scope address(es):\n"); - ip6_print_addrs (vm, unknown_scope); - vec_free (unknown_scope); - } + if (vec_len (link_scope)) + { + vlib_cli_output (vm, "\tLink-local address(es):\n"); + ip6_print_addrs (vm, link_scope); + vec_free (link_scope); + } + + if (vec_len (local_scope)) + { + vlib_cli_output (vm, "\tLocal unicast address(es):\n"); + ip6_print_addrs (vm, local_scope); + vec_free (local_scope); + } + + if (vec_len (global_scope)) + { + vlib_cli_output (vm, "\tGlobal unicast address(es):\n"); + ip6_print_addrs (vm, global_scope); + vec_free (global_scope); + } + + if (vec_len (unknown_scope)) + { + vlib_cli_output (vm, "\tOther-scope address(es):\n"); + ip6_print_addrs (vm, unknown_scope); + vec_free (unknown_scope); + } vlib_cli_output (vm, "\tJoined group address(es):\n"); ip6_mldp_group_t *m; - pool_foreach (m, radv_info->mldp_group_pool, ({ - vlib_cli_output (vm, "\t\t%U\n", format_ip6_address, &m->mcast_address); - })); + /* *INDENT-OFF* */ + pool_foreach (m, radv_info->mldp_group_pool, + ({ + vlib_cli_output (vm, "\t\t%U\n", format_ip6_address, + &m->mcast_address); + })); + /* *INDENT-ON* */ vlib_cli_output (vm, "\tAdvertised Prefixes:\n"); - ip6_radv_prefix_t * p; - pool_foreach (p, radv_info->adv_prefixes_pool, ({ - vlib_cli_output (vm, "\t\tprefix %U, length %d\n", - format_ip6_address, &p->prefix, p->prefix_len); - })); - - vlib_cli_output (vm, "\tMTU is %d\n", radv_info->adv_link_mtu); + ip6_radv_prefix_t *p; + /* *INDENT-OFF* */ + pool_foreach (p, radv_info->adv_prefixes_pool, + ({ + vlib_cli_output (vm, "\t\tprefix %U, length %d\n", + format_ip6_address, &p->prefix, p->prefix_len); + })); + /* *INDENT-ON* */ + + vlib_cli_output (vm, "\tMTU is %d\n", radv_info->adv_link_mtu); vlib_cli_output (vm, "\tICMP error messages are unlimited\n"); vlib_cli_output (vm, "\tICMP redirects are disabled\n"); vlib_cli_output (vm, "\tICMP unreachables are not sent\n"); @@ -2957,20 +3161,29 @@ show_ip6_interface_cmd (vlib_main_t * vm, //vlib_cli_output (vm, "\tND reachable time is %d milliseconds\n",); vlib_cli_output (vm, "\tND advertised reachable time is %d\n", radv_info->adv_neighbor_reachable_time_in_msec); - vlib_cli_output (vm, "\tND advertised retransmit interval is %d (msec)\n", - radv_info->adv_time_in_msec_between_retransmitted_neighbor_solicitations); + vlib_cli_output (vm, + "\tND advertised retransmit interval is %d (msec)\n", + radv_info-> + adv_time_in_msec_between_retransmitted_neighbor_solicitations); u32 ra_interval = radv_info->max_radv_interval; u32 ra_interval_min = radv_info->min_radv_interval; - vlib_cli_output (vm, "\tND router advertisements are sent every %d seconds (min interval is %d)\n", + vlib_cli_output (vm, + "\tND router advertisements are sent every %d seconds (min interval is %d)\n", ra_interval, ra_interval_min); - vlib_cli_output (vm, "\tND router advertisements live for %d seconds\n", + vlib_cli_output (vm, + "\tND router advertisements live for %d seconds\n", radv_info->adv_router_lifetime_in_sec); - vlib_cli_output (vm, "\tHosts %s stateless autoconfig for addresses\n", - (radv_info->adv_managed_flag) ? "use" :" don't use"); - vlib_cli_output (vm, "\tND router advertisements sent %d\n", radv_info->n_advertisements_sent); - vlib_cli_output (vm, "\tND router solicitations received %d\n", radv_info->n_solicitations_rcvd); - vlib_cli_output (vm, "\tND router solicitations dropped %d\n", radv_info->n_solicitations_dropped); + vlib_cli_output (vm, + "\tHosts %s stateless autoconfig for addresses\n", + (radv_info->adv_managed_flag) ? "use" : + " don't use"); + vlib_cli_output (vm, "\tND router advertisements sent %d\n", + radv_info->n_advertisements_sent); + vlib_cli_output (vm, "\tND router solicitations received %d\n", + radv_info->n_solicitations_rcvd); + vlib_cli_output (vm, "\tND router solicitations dropped %d\n", + radv_info->n_solicitations_dropped); } else { @@ -3019,7 +3232,8 @@ show_ip6_interface_cmd (vlib_main_t * vm, * @cliexend ?*/ /* *INDENT-OFF* */ -VLIB_CLI_COMMAND (show_ip6_interface_command, static) = { +VLIB_CLI_COMMAND (show_ip6_interface_command, static) = +{ .path = "show ip6 interface", .function = show_ip6_interface_cmd, .short_help = "show ip6 interface <interface>", @@ -3027,133 +3241,141 @@ VLIB_CLI_COMMAND (show_ip6_interface_command, static) = { /* *INDENT-ON* */ clib_error_t * -disable_ip6_interface(vlib_main_t * vm, - u32 sw_if_index) +disable_ip6_interface (vlib_main_t * vm, u32 sw_if_index) { - clib_error_t * error = 0; - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + clib_error_t *error = 0; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; u32 ri; /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, + ~0); ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - + /* if not created - do nothing */ - if(ri != ~0) + if (ri != ~0) { - vnet_main_t * vnm = vnet_get_main(); - ip6_radv_t * radv_info; - - radv_info = pool_elt_at_index (nm->if_radv_pool, ri); + vnet_main_t *vnm = vnet_get_main (); + ip6_radv_t *radv_info; + + radv_info = pool_elt_at_index (nm->if_radv_pool, ri); /* check radv_info ref count for other ip6 addresses on this interface */ - if(radv_info->ref_count == 0 ) + if (radv_info->ref_count == 0) { /* essentially "disables" ipv6 on this interface */ error = ip6_add_del_interface_address (vm, sw_if_index, - &radv_info->link_local_address, - radv_info->link_local_prefix_len, - 1 /* is_del */); - - ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, 0/* is_add */); + &radv_info-> + link_local_address, + radv_info-> + link_local_prefix_len, + 1 /* is_del */ ); + + ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, + 0 /* is_add */ ); } } return error; } int -ip6_interface_enabled(vlib_main_t * vm, - u32 sw_if_index) +ip6_interface_enabled (vlib_main_t * vm, u32 sw_if_index) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - u32 ri = ~0; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + u32 ri = ~0; - /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); + /* look up the radv_t information for this interface */ + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, + ~0); - ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; + ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - return ri != ~0; + return ri != ~0; } -clib_error_t * -enable_ip6_interface(vlib_main_t * vm, - u32 sw_if_index) +clib_error_t * +enable_ip6_interface (vlib_main_t * vm, u32 sw_if_index) { - clib_error_t * error = 0; - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + clib_error_t *error = 0; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; u32 ri; int is_add = 1; /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); - + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, + ~0); + ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - + /* if not created yet */ - if(ri == ~0) + if (ri == ~0) { - vnet_main_t * vnm = vnet_get_main(); - vnet_sw_interface_t * sw_if0; - + vnet_main_t *vnm = vnet_get_main (); + vnet_sw_interface_t *sw_if0; + sw_if0 = vnet_get_sup_sw_interface (vnm, sw_if_index); - if(sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE) + if (sw_if0->type == VNET_SW_INTERFACE_TYPE_HARDWARE) { - ethernet_interface_t * eth_if0; + ethernet_interface_t *eth_if0; - eth_if0 = ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); - if(eth_if0) + eth_if0 = + ethernet_get_interface (ðernet_main, sw_if0->hw_if_index); + if (eth_if0) { /* create radv_info. for this interface. This holds all the info needed for router adverts */ - ri = ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, is_add); + ri = + ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, is_add); - if(ri != ~0) + if (ri != ~0) { - ip6_radv_t * radv_info; + ip6_radv_t *radv_info; ip6_address_t link_local_address; - radv_info = pool_elt_at_index (nm->if_radv_pool, ri); + radv_info = pool_elt_at_index (nm->if_radv_pool, ri); - ip6_link_local_address_from_ethernet_mac_address (&link_local_address, - eth_if0->address); + ip6_link_local_address_from_ethernet_mac_address + (&link_local_address, eth_if0->address); sw_if0 = vnet_get_sw_interface (vnm, sw_if_index); - if(sw_if0->type == VNET_SW_INTERFACE_TYPE_SUB) + if (sw_if0->type == VNET_SW_INTERFACE_TYPE_SUB) { /* make up an interface id */ md5_context_t m; u8 digest[16]; - + link_local_address.as_u64[0] = radv_info->randomizer; - + md5_init (&m); md5_add (&m, &link_local_address, 16); - md5_finish (&m, digest); - - clib_memcpy(&link_local_address, digest, 16); - + md5_finish (&m, digest); + + clib_memcpy (&link_local_address, digest, 16); + radv_info->randomizer = link_local_address.as_u64[0]; - - link_local_address.as_u64[0] = clib_host_to_net_u64 (0xFE80000000000000ULL); + + link_local_address.as_u64[0] = + clib_host_to_net_u64 (0xFE80000000000000ULL); /* clear u bit */ link_local_address.as_u8[8] &= 0xfd; } - + /* essentially "enables" ipv6 on this interface */ error = ip6_add_del_interface_address (vm, sw_if_index, &link_local_address, - 128 /* address width */, - 0 /* is_del */); - - if(error) - ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, !is_add); + 128 + /* address width */ , + 0 /* is_del */ ); + + if (error) + ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, + !is_add); else { - radv_info->link_local_address = link_local_address; - radv_info->link_local_prefix_len = 64; + radv_info->link_local_address = link_local_address; + radv_info->link_local_prefix_len = 64; } } - } + } } } return error; @@ -3161,26 +3383,24 @@ enable_ip6_interface(vlib_main_t * vm, static clib_error_t * enable_ip6_interface_cmd (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) + unformat_input_t * input, vlib_cli_command_t * cmd) { - vnet_main_t * vnm = vnet_get_main(); - clib_error_t * error = 0; + vnet_main_t *vnm = vnet_get_main (); + clib_error_t *error = 0; u32 sw_if_index; sw_if_index = ~0; - if (unformat_user (input, - unformat_vnet_sw_interface, vnm, &sw_if_index)) + if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index)) { - enable_ip6_interface(vm, sw_if_index); + enable_ip6_interface (vm, sw_if_index); + } + else + { + error = clib_error_return (0, "unknown interface\n'", + format_unformat_error, input); + } - else - { - error = clib_error_return (0, "unknown interface\n'", - format_unformat_error, input); - - } return error; } @@ -3192,7 +3412,8 @@ enable_ip6_interface_cmd (vlib_main_t * vm, * @cliexcmd{enable ip6 interface GigabitEthernet2/0/0} ?*/ /* *INDENT-OFF* */ -VLIB_CLI_COMMAND (enable_ip6_interface_command, static) = { +VLIB_CLI_COMMAND (enable_ip6_interface_command, static) = +{ .path = "enable ip6 interface", .function = enable_ip6_interface_cmd, .short_help = "enable ip6 interface <interface>", @@ -3201,26 +3422,24 @@ VLIB_CLI_COMMAND (enable_ip6_interface_command, static) = { static clib_error_t * disable_ip6_interface_cmd (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) + unformat_input_t * input, vlib_cli_command_t * cmd) { - vnet_main_t * vnm = vnet_get_main(); - clib_error_t * error = 0; + vnet_main_t *vnm = vnet_get_main (); + clib_error_t *error = 0; u32 sw_if_index; sw_if_index = ~0; - if (unformat_user (input, - unformat_vnet_sw_interface, vnm, &sw_if_index)) + if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index)) { - error = disable_ip6_interface(vm, sw_if_index); + error = disable_ip6_interface (vm, sw_if_index); + } + else + { + error = clib_error_return (0, "unknown interface\n'", + format_unformat_error, input); + } - else - { - error = clib_error_return (0, "unknown interface\n'", - format_unformat_error, input); - - } return error; } @@ -3232,7 +3451,8 @@ disable_ip6_interface_cmd (vlib_main_t * vm, * @cliexcmd{disable ip6 interface GigabitEthernet2/0/0} ?*/ /* *INDENT-OFF* */ -VLIB_CLI_COMMAND (disable_ip6_interface_command, static) = { +VLIB_CLI_COMMAND (disable_ip6_interface_command, static) = +{ .path = "disable ip6 interface", .function = disable_ip6_interface_cmd, .short_help = "disable ip6 interface <interface>", @@ -3355,7 +3575,8 @@ VLIB_CLI_COMMAND (disable_ip6_interface_command, static) = { * @cliexcmd{ip6 nd GigabitEthernet2/0/0 no prefix fe80::fe:28ff:fe9c:75b3/64} ?*/ /* *INDENT-OFF* */ -VLIB_CLI_COMMAND (ip6_nd_command, static) = { +VLIB_CLI_COMMAND (ip6_nd_command, static) = +{ .path = "ip6 nd", .short_help = "ip6 nd <interface> ...", .function = ip6_neighbor_cmd, @@ -3363,53 +3584,53 @@ VLIB_CLI_COMMAND (ip6_nd_command, static) = { /* *INDENT-ON* */ clib_error_t * -set_ip6_link_local_address(vlib_main_t * vm, - u32 sw_if_index, - ip6_address_t *address, - u8 address_length) +set_ip6_link_local_address (vlib_main_t * vm, + u32 sw_if_index, + ip6_address_t * address, u8 address_length) { - clib_error_t * error = 0; - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + clib_error_t *error = 0; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; u32 ri; - ip6_radv_t * radv_info; - vnet_main_t * vnm = vnet_get_main(); + ip6_radv_t *radv_info; + vnet_main_t *vnm = vnet_get_main (); - if( !ip6_address_is_link_local_unicast (address)) + if (!ip6_address_is_link_local_unicast (address)) { vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_LINK_LOCAL; - return(error = clib_error_return (0, "address not link-local", - format_unformat_error)); + return (error = clib_error_return (0, "address not link-local", + format_unformat_error)); } /* call enable ipv6 */ - enable_ip6_interface(vm, sw_if_index); - + enable_ip6_interface (vm, sw_if_index); + ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - - if(ri != ~0) + + if (ri != ~0) { - radv_info = pool_elt_at_index (nm->if_radv_pool, ri); + radv_info = pool_elt_at_index (nm->if_radv_pool, ri); /* save if link local address (overwrite default) */ - + /* delete the old one */ error = ip6_add_del_interface_address (vm, sw_if_index, &radv_info->link_local_address, - radv_info->link_local_prefix_len /* address width */, - 1 /* is_del */); - - if(!error) + radv_info->link_local_prefix_len + /* address width */ , + 1 /* is_del */ ); + + if (!error) { /* add the new one */ error = ip6_add_del_interface_address (vm, sw_if_index, - address , - address_length /* address width */, - 0/* is_del */); - - if(!error) + address, address_length + /* address width */ , + 0 /* is_del */ ); + + if (!error) { radv_info->link_local_address = *address; - radv_info->link_local_prefix_len = address_length; + radv_info->link_local_prefix_len = address_length; } } } @@ -3421,36 +3642,31 @@ set_ip6_link_local_address(vlib_main_t * vm, } return error; } - + clib_error_t * set_ip6_link_local_address_cmd (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - vnet_main_t * vnm = vnet_get_main(); - clib_error_t * error = 0; + vnet_main_t *vnm = vnet_get_main (); + clib_error_t *error = 0; u32 sw_if_index; ip6_address_t ip6_addr; u32 addr_len = 0; - - if (unformat_user (input, - unformat_vnet_sw_interface, vnm, &sw_if_index)) + + if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index)) { /* get the rest of the command */ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if(unformat (input, "%U/%d", - unformat_ip6_address, &ip6_addr, - &addr_len)) + if (unformat (input, "%U/%d", + unformat_ip6_address, &ip6_addr, &addr_len)) break; else - return(unformat_parse_error (input)); + return (unformat_parse_error (input)); } } - error = set_ip6_link_local_address(vm, - sw_if_index, - &ip6_addr, - addr_len); + error = set_ip6_link_local_address (vm, sw_if_index, &ip6_addr, addr_len); return error; } @@ -3465,7 +3681,8 @@ set_ip6_link_local_address_cmd (vlib_main_t * vm, * @cliexcmd{set ip6 link-local address GigabitEthernet2/0/0 FE80::AB8/64} ?*/ /* *INDENT-OFF* */ -VLIB_CLI_COMMAND (set_ip6_link_local_address_command, static) = { +VLIB_CLI_COMMAND (set_ip6_link_local_address_command, static) = +{ .path = "set ip6 link-local address", .short_help = "set ip6 link-local address <interface> <ip6-address>/<width>", .function = set_ip6_link_local_address_cmd, @@ -3479,60 +3696,63 @@ ip6_neighbor_add_del_interface_address (ip6_main_t * im, u32 sw_if_index, ip6_address_t * address, u32 address_length, - u32 if_address_index, - u32 is_delete) + u32 if_address_index, u32 is_delete) { - vnet_main_t * vnm = vnet_get_main(); - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + vnet_main_t *vnm = vnet_get_main (); + ip6_neighbor_main_t *nm = &ip6_neighbor_main; u32 ri; - vlib_main_t * vm = vnm->vlib_main; - ip6_radv_t * radv_info; + vlib_main_t *vm = vnm->vlib_main; + ip6_radv_t *radv_info; ip6_address_t a; - ip6_mldp_group_t *mcast_group_info; + ip6_mldp_group_t *mcast_group_info; /* create solicited node multicast address for this interface adddress */ ip6_set_solicited_node_multicast_address (&a, 0); - + a.as_u8[0xd] = address->as_u8[0xd]; a.as_u8[0xe] = address->as_u8[0xe]; a.as_u8[0xf] = address->as_u8[0xf]; - - if(!is_delete) + + if (!is_delete) { /* try to create radv_info - does nothing if ipv6 already enabled */ - enable_ip6_interface(vm, sw_if_index); + enable_ip6_interface (vm, sw_if_index); /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, + sw_if_index, ~0); ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - if(ri != ~0) + if (ri != ~0) { /* get radv_info */ radv_info = pool_elt_at_index (nm->if_radv_pool, ri); /* add address */ - if( !ip6_address_is_link_local_unicast (address)) + if (!ip6_address_is_link_local_unicast (address)) radv_info->ref_count++; /* lookup prefix info for this address on this interface */ - uword * p = mhash_get (&radv_info->address_to_mldp_index, &a); - mcast_group_info = p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0; + uword *p = mhash_get (&radv_info->address_to_mldp_index, &a); + mcast_group_info = + p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0; /* add -solicted node multicast address */ - if(!mcast_group_info) + if (!mcast_group_info) { /* add */ u32 mi; pool_get (radv_info->mldp_group_pool, mcast_group_info); - + mi = mcast_group_info - radv_info->mldp_group_pool; - mhash_set (&radv_info->address_to_mldp_index, &a, mi, /* old_value */ 0); - + mhash_set (&radv_info->address_to_mldp_index, &a, mi, + /* old_value */ 0); + mcast_group_info->type = 4; mcast_group_info->mcast_source_address_pool = 0; mcast_group_info->num_sources = 0; - clib_memcpy(&mcast_group_info->mcast_address, &a, sizeof(ip6_address_t)); - } + clib_memcpy (&mcast_group_info->mcast_address, &a, + sizeof (ip6_address_t)); + } } } else @@ -3540,20 +3760,23 @@ ip6_neighbor_add_del_interface_address (ip6_main_t * im, /* delete */ /* look up the radv_t information for this interface */ - vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, sw_if_index, ~0); + vec_validate_init_empty (nm->if_radv_pool_index_by_sw_if_index, + sw_if_index, ~0); ri = nm->if_radv_pool_index_by_sw_if_index[sw_if_index]; - if(ri != ~0) + if (ri != ~0) { /* get radv_info */ radv_info = pool_elt_at_index (nm->if_radv_pool, ri); /* lookup prefix info for this address on this interface */ - uword * p = mhash_get (&radv_info->address_to_mldp_index, &a); - mcast_group_info = p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0; - - if(mcast_group_info) + uword *p = mhash_get (&radv_info->address_to_mldp_index, &a); + mcast_group_info = + p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0; + + if (mcast_group_info) { - mhash_unset (&radv_info->address_to_mldp_index, &a,/* old_value */ 0); + mhash_unset (&radv_info->address_to_mldp_index, &a, + /* old_value */ 0); pool_put (radv_info->mldp_group_pool, mcast_group_info); } @@ -3561,41 +3784,47 @@ ip6_neighbor_add_del_interface_address (ip6_main_t * im, radv_info->all_routers_mcast = 0; /* add address */ - if( !ip6_address_is_link_local_unicast (address)) + if (!ip6_address_is_link_local_unicast (address)) radv_info->ref_count--; } } } -clib_error_t *ip6_set_neighbor_limit (u32 neighbor_limit) +clib_error_t * +ip6_set_neighbor_limit (u32 neighbor_limit) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; nm->limit_neighbor_cache_size = neighbor_limit; return 0; } -static clib_error_t * ip6_neighbor_init (vlib_main_t * vm) +static clib_error_t * +ip6_neighbor_init (vlib_main_t * vm) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - ip6_main_t * im = &ip6_main; - + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + ip6_main_t *im = &ip6_main; + mhash_init (&nm->neighbor_index_by_key, /* value size */ sizeof (uword), /* key size */ sizeof (ip6_neighbor_key_t)); - icmp6_register_type (vm, ICMP6_neighbor_solicitation, ip6_icmp_neighbor_solicitation_node.index); - icmp6_register_type (vm, ICMP6_neighbor_advertisement, ip6_icmp_neighbor_advertisement_node.index); - icmp6_register_type (vm, ICMP6_router_solicitation, ip6_icmp_router_solicitation_node.index); - icmp6_register_type (vm, ICMP6_router_advertisement, ip6_icmp_router_advertisement_node.index); + icmp6_register_type (vm, ICMP6_neighbor_solicitation, + ip6_icmp_neighbor_solicitation_node.index); + icmp6_register_type (vm, ICMP6_neighbor_advertisement, + ip6_icmp_neighbor_advertisement_node.index); + icmp6_register_type (vm, ICMP6_router_solicitation, + ip6_icmp_router_solicitation_node.index); + icmp6_register_type (vm, ICMP6_router_advertisement, + ip6_icmp_router_advertisement_node.index); /* handler node for ip6 neighbor discovery events and timers */ vlib_register_node (vm, &ip6_icmp_neighbor_discovery_event_node); /* add call backs */ - ip6_add_del_interface_address_callback_t cb; - memset(&cb, 0x0, sizeof(ip6_add_del_interface_address_callback_t)); - + ip6_add_del_interface_address_callback_t cb; + memset (&cb, 0x0, sizeof (ip6_add_del_interface_address_callback_t)); + /* when an interface address changes... */ cb.function = ip6_neighbor_add_del_interface_address; cb.function_opaque = 0; @@ -3614,8 +3843,8 @@ static clib_error_t * ip6_neighbor_init (vlib_main_t * vm) #if 0 /* $$$$ Hack fix for today */ - vec_validate_init_empty - (im->discover_neighbor_next_index_by_hw_if_index, 32, 0 /* drop */); + vec_validate_init_empty + (im->discover_neighbor_next_index_by_hw_if_index, 32, 0 /* drop */ ); #endif return 0; @@ -3624,17 +3853,17 @@ static clib_error_t * ip6_neighbor_init (vlib_main_t * vm) VLIB_INIT_FUNCTION (ip6_neighbor_init); -void vnet_register_ip6_neighbor_resolution_event (vnet_main_t * vnm, - void * address_arg, - uword node_index, - uword type_opaque, - uword data) +void +vnet_register_ip6_neighbor_resolution_event (vnet_main_t * vnm, + void *address_arg, + uword node_index, + uword type_opaque, uword data) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - ip6_address_t * address = address_arg; - uword * p; - pending_resolution_t * pr; - + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + ip6_address_t *address = address_arg; + uword *p; + pending_resolution_t *pr; + pool_get (nm->pending_resolutions, pr); pr->next_index = ~0; @@ -3649,26 +3878,25 @@ void vnet_register_ip6_neighbor_resolution_event (vnet_main_t * vnm, pr->next_index = p[0]; mhash_unset (&nm->pending_resolutions_by_address, address, 0); } - - mhash_set (&nm->pending_resolutions_by_address, address, - pr - nm->pending_resolutions, 0 /* old value */); + + mhash_set (&nm->pending_resolutions_by_address, address, + pr - nm->pending_resolutions, 0 /* old value */ ); } -int vnet_add_del_ip6_nd_change_event (vnet_main_t * vnm, - void * data_callback, - u32 pid, - void * address_arg, - uword node_index, - uword type_opaque, - uword data, - int is_add) -{ - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - ip6_address_t * address = address_arg; - uword * p; - pending_resolution_t * mc; - void (*fp)(u32, u8 *) = data_callback; - +int +vnet_add_del_ip6_nd_change_event (vnet_main_t * vnm, + void *data_callback, + u32 pid, + void *address_arg, + uword node_index, + uword type_opaque, uword data, int is_add) +{ + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + ip6_address_t *address = address_arg; + uword *p; + pending_resolution_t *mc; + void (*fp) (u32, u8 *) = data_callback; + if (is_add) { pool_get (nm->mac_changes, mc); @@ -3679,83 +3907,80 @@ int vnet_add_del_ip6_nd_change_event (vnet_main_t * vnm, mc->data = data; mc->data_callback = data_callback; mc->pid = pid; - + p = mhash_get (&nm->mac_changes_by_address, address); if (p) - { - /* Insert new resolution at the head of the list */ - mc->next_index = p[0]; - mhash_unset (&nm->mac_changes_by_address, address, 0); - } - - mhash_set (&nm->mac_changes_by_address, address, + { + /* Insert new resolution at the head of the list */ + mc->next_index = p[0]; + mhash_unset (&nm->mac_changes_by_address, address, 0); + } + + mhash_set (&nm->mac_changes_by_address, address, mc - nm->mac_changes, 0); return 0; } else { u32 index; - pending_resolution_t * mc_last = 0; + pending_resolution_t *mc_last = 0; p = mhash_get (&nm->mac_changes_by_address, address); if (p == 0) - return VNET_API_ERROR_NO_SUCH_ENTRY; + return VNET_API_ERROR_NO_SUCH_ENTRY; index = p[0]; - while (index != (u32)~0) - { - mc = pool_elt_at_index (nm->mac_changes, index); - if (mc->node_index == node_index && - mc->type_opaque == type_opaque && - mc->pid == pid) - { - /* Clients may need to clean up pool entries, too */ - if (fp) - (*fp)(mc->data, 0 /* no new mac addrs */); - if (index == p[0]) - { + while (index != (u32) ~ 0) + { + mc = pool_elt_at_index (nm->mac_changes, index); + if (mc->node_index == node_index && + mc->type_opaque == type_opaque && mc->pid == pid) + { + /* Clients may need to clean up pool entries, too */ + if (fp) + (*fp) (mc->data, 0 /* no new mac addrs */ ); + if (index == p[0]) + { mhash_unset (&nm->mac_changes_by_address, address, 0); - if (mc->next_index != ~0) - mhash_set (&nm->mac_changes_by_address, address, + if (mc->next_index != ~0) + mhash_set (&nm->mac_changes_by_address, address, mc->next_index, 0); - pool_put (nm->mac_changes, mc); - return 0; - } - else - { - ASSERT(mc_last); - mc_last->next_index = mc->next_index; - pool_put (nm->mac_changes, mc); - return 0; - } - } - mc_last = mc; - index = mc->next_index; - } - + pool_put (nm->mac_changes, mc); + return 0; + } + else + { + ASSERT (mc_last); + mc_last->next_index = mc->next_index; + pool_put (nm->mac_changes, mc); + return 0; + } + } + mc_last = mc; + index = mc->next_index; + } + return VNET_API_ERROR_NO_SUCH_ENTRY; } } -int vnet_ip6_nd_term (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_buffer_t * p0, - ethernet_header_t * eth, - ip6_header_t * ip, - u32 sw_if_index, - u16 bd_index, - u8 shg) -{ - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - icmp6_neighbor_solicitation_or_advertisement_header_t * ndh; - pending_resolution_t * mc; +int +vnet_ip6_nd_term (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_buffer_t * p0, + ethernet_header_t * eth, + ip6_header_t * ip, u32 sw_if_index, u16 bd_index, u8 shg) +{ + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + icmp6_neighbor_solicitation_or_advertisement_header_t *ndh; + pending_resolution_t *mc; uword *p; ndh = ip6_next_header (ip); if (ndh->icmp.type != ICMP6_neighbor_solicitation && ndh->icmp.type != ICMP6_neighbor_advertisement) - return 0; + return 0; if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && (p0->flags & VLIB_BUFFER_IS_TRACED))) @@ -3767,69 +3992,68 @@ int vnet_ip6_nd_term (vlib_main_t * vm, /* Check if anyone want ND events for L2 BDs */ p = mhash_get (&nm->mac_changes_by_address, &ip6a_zero); - if (p && shg == 0 && /* Only SHG 0 interface which is more likely local */ + if (p && shg == 0 && /* Only SHG 0 interface which is more likely local */ !ip6_address_is_link_local_unicast (&ip->src_address)) - { + { u32 next_index = p[0]; - while (next_index != (u32)~0) - { - int (*fp)(u32, u8 *, u32, ip6_address_t *); + while (next_index != (u32) ~ 0) + { + int (*fp) (u32, u8 *, u32, ip6_address_t *); int rv = 1; mc = pool_elt_at_index (nm->mac_changes, next_index); fp = mc->data_callback; /* Call the callback, return 1 to suppress dup events */ - if (fp) rv = (*fp)(mc->data, - eth->src_address, - sw_if_index, - &ip->src_address); + if (fp) + rv = (*fp) (mc->data, + eth->src_address, sw_if_index, &ip->src_address); /* Signal the resolver process */ if (rv == 0) - vlib_process_signal_event (vm, mc->node_index, - mc->type_opaque, - mc->data); + vlib_process_signal_event (vm, mc->node_index, + mc->type_opaque, mc->data); next_index = mc->next_index; - } + } } /* Check if MAC entry exsist for solicited target IP */ if (ndh->icmp.type == ICMP6_neighbor_solicitation) { - icmp6_neighbor_discovery_ethernet_link_layer_address_option_t * opt; + icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *opt; l2_bridge_domain_t *bd_config; - u8 * macp; + u8 *macp; opt = (void *) (ndh + 1); - if ((opt->header.type != + if ((opt->header.type != ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address) || (opt->header.n_data_u64s != 1)) - return 0; /* source link layer address option not present */ - + return 0; /* source link layer address option not present */ + bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index); - macp = (u8 *) hash_get_mem (bd_config->mac_by_ip6, &ndh->target_address); + macp = + (u8 *) hash_get_mem (bd_config->mac_by_ip6, &ndh->target_address); if (macp) - { /* found ip-mac entry, generate eighbor advertisement response */ + { /* found ip-mac entry, generate eighbor advertisement response */ int bogus_length; - vlib_node_runtime_t * error_node = - vlib_node_get_runtime (vm, ip6_icmp_input_node.index); + vlib_node_runtime_t *error_node = + vlib_node_get_runtime (vm, ip6_icmp_input_node.index); ip->dst_address = ip->src_address; ip->src_address = ndh->target_address; ip->hop_limit = 255; opt->header.type = - ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address; + ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address; clib_memcpy (opt->ethernet_address, macp, 6); ndh->icmp.type = ICMP6_neighbor_advertisement; ndh->advertisement_flags = clib_host_to_net_u32 - (ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED | - ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE); + (ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED | + ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE); ndh->icmp.checksum = 0; - ndh->icmp.checksum = ip6_tcp_udp_icmp_compute_checksum(vm, p0, ip, - &bogus_length); - clib_memcpy(eth->dst_address, eth->src_address, 6); - clib_memcpy(eth->src_address, macp, 6); - vlib_error_count (vm, error_node->node_index, + ndh->icmp.checksum = + ip6_tcp_udp_icmp_compute_checksum (vm, p0, ip, &bogus_length); + clib_memcpy (eth->dst_address, eth->src_address, 6); + clib_memcpy (eth->src_address, macp, 6); + vlib_error_count (vm, error_node->node_index, ICMP6_ERROR_NEIGHBOR_ADVERTISEMENTS_TX, 1); - return 1; - } + return 1; + } } return 0; @@ -3839,17 +4063,26 @@ int vnet_ip6_nd_term (vlib_main_t * vm, void ethernet_ndp_change_mac (vlib_main_t * vm, u32 sw_if_index) { - ip6_neighbor_main_t * nm = &ip6_neighbor_main; - ip6_neighbor_t * n; + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + ip6_neighbor_t *n; /* *INDENT-OFF* */ - pool_foreach (n, nm->neighbor_pool, ({ + pool_foreach (n, nm->neighbor_pool, + ({ if (n->key.sw_if_index == sw_if_index) - { + { adj_nbr_walk_nh6 (sw_if_index, &n->key.ip6_address, ip6_nd_mk_complete_walk, n); - } + } })); /* *INDENT-ON* */ } + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ |