X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fip6-nd%2Fip6_ra.c;h=ffc02e813e223d2f283dc9e4d4b3f174efc62976;hb=HEAD;hp=769f9dabe5c02373e7b20f3bdd7c3a5b3f4c80f4;hpb=7249b90ab21c20138907e692dcb6032aea9e2f0f;p=vpp.git diff --git a/src/vnet/ip6-nd/ip6_ra.c b/src/vnet/ip6-nd/ip6_ra.c index 769f9dabe5c..ffc02e813e2 100644 --- a/src/vnet/ip6-nd/ip6_ra.c +++ b/src/vnet/ip6-nd/ip6_ra.c @@ -30,7 +30,6 @@ * The files contains the API and CLI code for managing IPv6 RAs */ -/* *INDENT-OFF* */ /* Router solicitation packet format for ethernet. */ typedef CLIB_PACKED (struct { @@ -51,7 +50,6 @@ typedef CLIB_PACKED (struct icmp6_neighbor_discovery_prefix_information_option_t prefix[0]; }) icmp6_router_advertisement_packet_t; -/* *INDENT-ON* */ #define DEF_MAX_RADV_INTERVAL 200 #define DEF_MIN_RADV_INTERVAL .75 * DEF_MAX_RADV_INTERVAL @@ -65,95 +63,6 @@ typedef CLIB_PACKED (struct #define MAX_DELAY_BETWEEN_RAS 1800 /* seconds */ #define MAX_RA_DELAY_TIME .5 /* seconds */ -/* advertised prefix option */ -typedef struct -{ - /* basic advertised information */ - ip6_address_t prefix; - u8 prefix_len; - int adv_on_link_flag; - int adv_autonomous_flag; - u32 adv_valid_lifetime_in_secs; - u32 adv_pref_lifetime_in_secs; - - /* advertised values are computed from these times if decrementing */ - f64 valid_lifetime_expires; - f64 pref_lifetime_expires; - - /* local information */ - int enabled; - int deprecated_prefix_flag; - int decrement_lifetime_flag; - -#define MIN_ADV_VALID_LIFETIME 7203 /* seconds */ -#define DEF_ADV_VALID_LIFETIME 2592000 -#define DEF_ADV_PREF_LIFETIME 604800 - - /* extensions are added here, mobile, DNS etc.. */ -} ip6_radv_prefix_t; - -typedef struct ip6_ra_t_ -{ - /* advertised config information, zero means unspecified */ - u8 curr_hop_limit; - int adv_managed_flag; - int adv_other_flag; - 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; - - /* local information */ - u32 sw_if_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_unicast; - int adv_link_layer_address; - int prefix_option; - int failed_device_check; - int ref_count; - - /* prefix option */ - ip6_radv_prefix_t *adv_prefixes_pool; - - /* Hash table mapping address to index in interface advertised prefix pool. */ - mhash_t address_to_prefix_index; - - f64 max_radv_interval; - f64 min_radv_interval; - f64 min_delay_between_radv; - f64 max_delay_between_radv; - f64 max_rtr_default_lifetime; - - f64 last_radv_time; - f64 last_multicast_time; - f64 next_multicast_time; - - - u32 initial_adverts_count; - f64 initial_adverts_interval; - u32 initial_adverts_sent; - - /* stats */ - u32 n_advertisements_sent; - u32 n_solicitations_rcvd; - u32 n_solicitations_dropped; - - /* router solicitations sending state */ - u8 keep_sending_rs; /* when true then next fields are valid */ - icmp6_send_router_solicitation_params_t params; - f64 sleep_interval; - f64 due_time; - u32 n_left; - f64 start_time; - vlib_buffer_t *buffer; - - u32 seed; - -} ip6_ra_t; - static ip6_link_delegate_id_t ip6_ra_delegate_id; static ip6_ra_t *ip6_ra_pool; @@ -191,7 +100,7 @@ ip6_ra_report_unregister (ip6_ra_report_notify_t fn) } } -static inline ip6_ra_t * +ip6_ra_t * ip6_ra_get_itf (u32 sw_if_index) { index_t rai; @@ -204,6 +113,28 @@ ip6_ra_get_itf (u32 sw_if_index) return (NULL); } +u8 +ip6_ra_adv_enabled (u32 sw_if_index) +{ + ip6_ra_t *ra; + + ra = ip6_ra_get_itf (sw_if_index); + + return ((ra != NULL) && (ra->send_radv != 0)); +} + +void +ip6_ra_itf_walk (ip6_ra_itf_walk_fn_t fn, void *ctx) +{ + ip6_ra_t *radv_info; + + pool_foreach (radv_info, ip6_ra_pool) + { + if (WALK_STOP == fn (radv_info->sw_if_index, ctx)) + break; + } +} + /* for "syslogging" - use elog for now */ #define foreach_log_level \ _ (DEBUG, "DEBUG") \ @@ -252,9 +183,10 @@ ip6_neighbor_syslog (vlib_main_t * vm, int priority, char *fmt, ...) { 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 = ELOG_DATA (vlib_get_elog_main (), e); + ed->s[0] = + elog_string (vlib_get_elog_main (), log_level_strings[priority]); + ed->s[1] = elog_string (vlib_get_elog_main (), (char *) what); } va_end (va); return; @@ -269,6 +201,9 @@ typedef enum ICMP6_ROUTER_SOLICITATION_N_NEXT, } icmp6_router_solicitation_or_advertisement_next_t; +/* + * Note: Both periodic RAs and solicited RS come through here. + */ static_always_inline uword icmp6_router_solicitation (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) @@ -369,9 +304,11 @@ icmp6_router_solicitation (vlib_main_t * vm, !is_unspecified && !is_link_local)) { ip_neighbor_learn_t learn = { - .type = IP46_TYPE_IP6, .sw_if_index = sw_if_index0, - .ip.ip6 = ip0->src_address, + .ip = { + .ip.ip6 = ip0->src_address, + .version = AF_IP6, + }, }; memcpy (&learn.mac, o0->ethernet_address, sizeof (learn.mac)); ip_neighbor_learn_dp (&learn); @@ -405,10 +342,9 @@ icmp6_router_solicitation (vlib_main_t * vm, radv_info = ip6_ra_get_itf (sw_if_index0); - error0 = ((!radv_info) ? - ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG : - error0); - + error0 = ((!radv_info || 0 == radv_info->send_radv) ? + ICMP6_ERROR_ROUTER_SOLICITATION_RADV_NOT_CONFIG : + error0); if (error0 == ICMP6_ERROR_NONE) { f64 now = vlib_time_now (vm); @@ -477,7 +413,7 @@ icmp6_router_solicitation (vlib_main_t * vm, /* copy ll address */ clib_memcpy (&h.ethernet_address[0], - eth_if0->address, 6); + ð_if0->address, 6); if (vlib_buffer_add_data (vm, &bi0, (void *) &h, @@ -520,9 +456,8 @@ icmp6_router_solicitation (vlib_main_t * vm, /* add advertised prefix options */ ip6_radv_prefix_t *pr_info; - /* *INDENT-OFF* */ - pool_foreach (pr_info, radv_info->adv_prefixes_pool, - ({ + pool_foreach (pr_info, radv_info->adv_prefixes_pool) + { if(pr_info->enabled && (!pr_info->decrement_lifetime_flag || (pr_info->pref_lifetime_expires >0))) @@ -585,8 +520,7 @@ icmp6_router_solicitation (vlib_main_t * vm, } } - })); - /* *INDENT-ON* */ + } /* add additional options before here */ @@ -630,10 +564,12 @@ icmp6_router_solicitation (vlib_main_t * vm, /* Reuse current MAC header, copy SMAC to DMAC and * interface MAC to SMAC */ vlib_buffer_reset (p0); + vlib_buffer_advance ( + p0, vnet_buffer (p0)->l2_hdr_offset); eth0 = vlib_buffer_get_current (p0); clib_memcpy (eth0->dst_address, eth0->src_address, 6); - clib_memcpy (eth0->src_address, eth_if0->address, + clib_memcpy (eth0->src_address, ð_if0->address, 6); next0 = is_dropped ? next0 : @@ -692,7 +628,6 @@ icmp6_router_solicitation (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip6_icmp_router_solicitation_node,static) = { .function = icmp6_router_solicitation, @@ -709,7 +644,6 @@ VLIB_REGISTER_NODE (ip6_icmp_router_solicitation_node,static) = [ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_TX] = "interface-output", }, }; -/* *INDENT-ON* */ /* validate advertised info for consistancy (see RFC-4861 section 6.2.7) - log any inconsistencies, packet will always be dropped */ static_always_inline uword @@ -1002,9 +936,8 @@ icmp6_router_advertisement (vlib_main_t * vm, prefix->prefix.fp_proto = FIB_PROTOCOL_IP6; /* look for matching prefix - if we our advertising it, it better be consistant */ - /* *INDENT-OFF* */ - pool_foreach (pr_info, radv_info->adv_prefixes_pool, - ({ + pool_foreach (pr_info, radv_info->adv_prefixes_pool) + { ip6_address_t mask; ip6_address_mask_from_width(&mask, pr_info->prefix_len); @@ -1032,8 +965,7 @@ icmp6_router_advertisement (vlib_main_t * vm, } } break; - })); - /* *INDENT-ON* */ + } break; } default: @@ -1067,7 +999,6 @@ icmp6_router_advertisement (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip6_icmp_router_advertisement_node,static) = { .function = icmp6_router_advertisement, @@ -1082,7 +1013,6 @@ VLIB_REGISTER_NODE (ip6_icmp_router_advertisement_node,static) = [0] = "ip6-drop", }, }; -/* *INDENT-ON* */ static inline f64 random_f64_from_to (f64 from, f64 to) @@ -1127,7 +1057,6 @@ create_buffer_for_rs (vlib_main_t * vm, ip6_ra_t * radv_info) } p0 = vlib_get_buffer (vm, bi0); - VLIB_BUFFER_TRACE_TRAJECTORY_INIT (p0); p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; vnet_buffer (p0)->sw_if_index[VLIB_RX] = sw_if_index; @@ -1219,6 +1148,9 @@ check_send_rs (vlib_main_t * vm, ip6_ra_t * radv_info, f64 current_time, next_index = ip6_rewrite_mcast_node.index; c0 = vlib_buffer_copy (vm, p0); + if (c0 == NULL) + return radv_info->keep_sending_rs; + ci0 = vlib_get_buffer_index (vm, c0); f = vlib_get_frame_to_node (vm, next_index); @@ -1270,14 +1202,12 @@ send_rs_process (vlib_main_t * vm, vlib_node_runtime_t * rt, do { due_time = current_time + 1e9; - /* *INDENT-OFF* */ - pool_foreach (radv_info, ip6_ra_pool, - ({ + pool_foreach (radv_info, ip6_ra_pool) + { if (check_send_rs (vm, radv_info, current_time, &dt) && (dt < due_time)) due_time = dt; - })); - /* *INDENT-ON* */ + } current_time = vlib_time_now (vm); } while (due_time < current_time); @@ -1288,13 +1218,11 @@ send_rs_process (vlib_main_t * vm, vlib_node_runtime_t * rt, return 0; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip6_rs_process_node) = { .function = send_rs_process, .type = VLIB_NODE_TYPE_PROCESS, .name = "ip6-rs-process", }; -/* *INDENT-ON* */ void icmp6_send_router_solicitation (vlib_main_t * vm, u32 sw_if_index, u8 stop, @@ -1382,9 +1310,6 @@ ip6_ra_link_enable (u32 sw_if_index) radv_info->initial_adverts_sent = radv_info->initial_adverts_count - 1; radv_info->initial_adverts_interval = MAX_INITIAL_RTR_ADVERT_INTERVAL; - /* deafult is to send */ - radv_info->send_radv = 1; - /* fill in delegate for this interface that will be needed later */ radv_info->adv_link_mtu = vnet_sw_interface_get_mtu (vnet_get_main (), sw_if_index, VNET_MTU_IP6); @@ -1405,12 +1330,10 @@ ip6_ra_delegate_disable (index_t rai) radv_info = pool_elt_at_index (ip6_ra_pool, rai); /* clean up prefix and MDP pools */ - /* *INDENT-OFF* */ pool_flush(p, radv_info->adv_prefixes_pool, ({ mhash_unset (&radv_info->address_to_prefix_index, &p->prefix, 0); })); - /* *INDENT-ON* */ pool_free (radv_info->adv_prefixes_pool); @@ -1432,12 +1355,10 @@ ip6_ra_update_secondary_radv_info (ip6_address_t * address, u8 prefix_len, ip6_address_mask_from_width (&mask, prefix_len); vec_reset_length (radv_indices); - /* *INDENT-OFF* */ - pool_foreach (radv_info, ip6_ra_pool, - ({ + pool_foreach (radv_info, ip6_ra_pool) + { vec_add1 (radv_indices, radv_info - ip6_ra_pool); - })); - /* *INDENT-ON* */ + } /* * If we have another customer for this prefix, @@ -1452,9 +1373,8 @@ ip6_ra_update_secondary_radv_info (ip6_address_t * address, u8 prefix_len, if (radv_info->sw_if_index == primary_sw_if_index) continue; - /* *INDENT-OFF* */ - pool_foreach (this_prefix, radv_info->adv_prefixes_pool, - ({ + pool_foreach (this_prefix, radv_info->adv_prefixes_pool) + { if (this_prefix->prefix_len == prefix_len && ip6_address_is_equal_masked (&this_prefix->prefix, address, &mask)) @@ -1474,8 +1394,7 @@ ip6_ra_update_secondary_radv_info (ip6_address_t * address, u8 prefix_len, if (rv != 0) clib_warning ("ip6_neighbor_ra_prefix returned %d", rv); } - })); - /* *INDENT-ON*/ + } } } @@ -1496,9 +1415,8 @@ ip6_ra_process_timer_event (vlib_main_t * vm, f64 now = vlib_time_now (vm); /* Interface ip6 radv info list */ - /* *INDENT-OFF* */ - pool_foreach (radv_info, ip6_ra_pool, - ({ + pool_foreach (radv_info, ip6_ra_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; @@ -1585,8 +1503,7 @@ ip6_ra_process_timer_event (vlib_main_t * vm, f = 0; } } - })); - /* *INDENT-ON* */ + } if (f) { @@ -1598,19 +1515,23 @@ ip6_ra_process_timer_event (vlib_main_t * vm, } static void -ip6_ra_handle_report (const ip6_ra_report_t * rap) +ip6_ra_handle_report (ip6_ra_report_t * rap) { u32 ii; vec_foreach_index (ii, ip6_ra_listeners) ip6_ra_listeners[ii] (rap); + vec_free (rap->prefixes); + clib_mem_free (rap); } static uword ip6_ra_event_process (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - ip6_ra_report_t *r, *rs; + ip6_ra_report_t *r; uword event_type; + uword *event_data = 0; + int i; /* init code here */ @@ -1618,9 +1539,9 @@ ip6_ra_event_process (vlib_main_t * vm, { vlib_process_wait_for_event_or_clock (vm, 1. /* seconds */ ); - rs = vlib_process_get_event_data (vm, &event_type); + event_type = vlib_process_get_events (vm, &event_data); - if (NULL == rs) + if (event_type == ~0) { /* No events found: timer expired. */ /* process interface list and send RAs as appropriate, update timer info */ @@ -1628,8 +1549,12 @@ ip6_ra_event_process (vlib_main_t * vm, } else { - vec_foreach (r, rs) ip6_ra_handle_report (r); - vec_reset_length (rs); + for (i = 0; i < vec_len (event_data); i++) + { + r = (void *) (event_data[i]); + ip6_ra_handle_report (r); + } + vec_reset_length (event_data); } } return frame->n_vectors; @@ -1637,8 +1562,10 @@ ip6_ra_event_process (vlib_main_t * vm, VLIB_REGISTER_NODE (ip6_ra_process_node) = { -.function = ip6_ra_event_process,.name = "ip6-ra-process",.type = - VLIB_NODE_TYPE_PROCESS,}; + .function = ip6_ra_event_process, + .name = "ip6-ra-process", + .type = VLIB_NODE_TYPE_PROCESS, +}; static void ip6_ra_signal_report (ip6_ra_report_t * r) @@ -1649,10 +1576,10 @@ ip6_ra_signal_report (ip6_ra_report_t * r) if (!vec_len (ip6_ra_listeners)) return; - q = vlib_process_signal_event_data (vm, - ip6_ra_process_node.index, - 0, 1, sizeof *q); + q = clib_mem_alloc (sizeof (*q)); *q = *r; + + vlib_process_signal_event (vm, ip6_ra_process_node.index, 0, (uword) q); } static int @@ -1680,6 +1607,9 @@ ip6_ra_config (vlib_main_t * vm, u32 sw_if_index, if (!radv_info) return (VNET_API_ERROR_IP6_NOT_ENABLED); + /* Start off believing that we're going to send radv's */ + radv_info->send_radv = 1; + if ((max_interval != 0) && (min_interval == 0)) min_interval = .75 * max_interval; @@ -2005,8 +1935,7 @@ ip6_ra_cmd (vlib_main_t * vm, } else { - error = unformat_parse_error (line_input); - goto done; + break; } } @@ -2098,14 +2027,12 @@ format_ip6_ra (u8 * s, va_list * args) indent += 2; - /* *INDENT-OFF* */ - pool_foreach (p, radv_info->adv_prefixes_pool, - ({ + pool_foreach (p, radv_info->adv_prefixes_pool) + { s = format (s, "%Uprefix %U, length %d\n", format_white_space, indent+2, format_ip6_address, &p->prefix, p->prefix_len); - })); - /* *INDENT-ON* */ + } s = format (s, "%UMTU is %d\n", format_white_space, indent, radv_info->adv_link_mtu); @@ -2151,7 +2078,6 @@ format_ip6_ra (u8 * s, va_list * args) return (s); } - /*? * This command is used to configure the neighbor discovery * parameters on a given interface. Use the 'show ip6 interface' @@ -2159,9 +2085,16 @@ format_ip6_ra (u8 * s, va_list * args) * on a given interface. This command has three formats: * * - * Format 1 - Router Advertisement Options: (Only one can be entered in a single command) + * Format 1 - Router Advertisement Options: (Only one can be entered in + * a single command) * - * 'ip6 nd [no] [ra-managed-config-flag] | [ra-other-config-flag] | [ra-suppress] | [ra-suppress-link-layer] | [ra-send-unicast] | [ra-lifetime ] | [ra-initial ] | [ra-interval []] | [ra-cease]' + * @clistart + * ip6 nd [no] [ra-managed-config-flag] | + * [ra-other-config-flag] | [ra-suppress] | [ra-suppress-link-layer] | + * [ra-send-unicast] | [ra-lifetime ] | + * [ra-initial ] | + * [ra-interval []] | [ra-cease] + * @cliend * * Where: * @@ -2187,7 +2120,7 @@ format_ip6_ra (u8 * s, va_list * args) * and the 'no' option returns it to this default state. * * [no] ra-send-unicast - Use the source address of the - * router-solicitation message if availiable. The default is to use + * router-solicitation message if available. The default is to use * multicast address of all nodes, and the 'no' option returns * it to this default state. * @@ -2218,63 +2151,69 @@ format_ip6_ra (u8 * s, va_list * args) * * Format 2 - Prefix Options: * - * 'ip6 nd [no] prefix / [ | infinite] [no-advertise] [off-link] [no-autoconfig] [no-onlink]' + * @clistart + * ip6 nd [no] prefix / + * [ | infinite] [no-advertise] [off-link] + * [no-autoconfig] [no-onlink] + * @cliend * * Where: * * no - All additional flags are ignored and the prefix is deleted. * - * - '' is the - * length of time in seconds during what the prefix is valid for the purpose of - * on-link determination. Range is 7203 to 2592000 seconds and default is 2592000 - * seconds (30 days). '' is the prefered-lifetime and is the - * length of time in seconds during what addresses generated from the prefix remain - * preferred. Range is 0 to 604800 seconds and default is 604800 seconds (7 days). + * - '' is + * the length of time in seconds during what the prefix is valid for the + * purpose of on-link determination. Range is 7203 to 2592000 seconds and + * default is 2592000 seconds (30 days). '' is the + * preferred-lifetime and is the length of time in seconds during what + * addresses generated from the prefix remain preferred. Range is 0 to 604800 + * seconds and default is 604800 seconds (7 days). * - * infinite - Both '' and '<' - * are inifinte, no timeout. + * infinite - Both '' and + * '' are infinite, no timeout. * * no-advertise - Do not send full router address in prefix * advertisement. Default is to advertise (i.e. - This flag is off by default). * - * off-link - Prefix is off-link, clear L-bit in packet. Default is on-link - * (i.e. - This flag is off and L-bit in packet is set by default and this prefix can - * be used for on-link determination). 'no-onlink' also controls the L-bit. + * off-link - Prefix is off-link, clear L-bit in packet. Default is + * on-link (i.e. - This flag is off and L-bit in packet is set by default + * and this prefix can be used for on-link determination). 'no-onlink' + * also controls the L-bit. * - * no-autoconfig - Do not use prefix for autoconfiguration, clear A-bit in packet. - * Default is autoconfig (i.e. - This flag is off and A-bit in packet is set by default. + * no-autoconfig - Do not use prefix for autoconfiguration, clear + * A-bit in packet. Default is autoconfig (i.e. - This flag is off and A-bit + * in packet is set by default. * - * no-onlink - Do not use prefix for onlink determination, clear L-bit in packet. - * Default is on-link (i.e. - This flag is off and L-bit in packet is set by default and - * this prefix can be used for on-link determination). 'off-link' also controls - * the L-bit. + * no-onlink - Do not use prefix for onlink determination, clear L-bit + * in packet. Default is on-link (i.e. - This flag is off and L-bit in packet + * is set by default and this prefix can be used for on-link determination). + * 'off-link' also controls the L-bit. * * * Format 3: - Default of Prefix: * - * 'ip6 nd [no] prefix / default' + * @cliexcmd{ip6 nd [no] prefix / default} * - * When a new prefix is added (or existing one is being overwritten) default - * uses default values for the prefix. If no is used, the default - * is ignored and the prefix is deleted. + * When a new prefix is added (or existing one is being overwritten) + * default uses default values for the prefix. If no is + * used, the default is ignored and the prefix is deleted. * * * @cliexpar * Example of how set a router advertisement option: * @cliexcmd{ip6 nd GigabitEthernet2/0/0 ra-interval 100 20} * Example of how to add a prefix: - * @cliexcmd{ip6 nd GigabitEthernet2/0/0 prefix fe80::fe:28ff:fe9c:75b3/64 infinite no-advertise} + * @cliexcmd{ip6 nd GigabitEthernet2/0/0 prefix fe80::fe:28ff:fe9c:75b3/64 + * infinite no-advertise} * Example of how to delete a prefix: * @cliexcmd{ip6 nd GigabitEthernet2/0/0 no prefix fe80::fe:28ff:fe9c:75b3/64} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (ip6_nd_command, static) = { .path = "ip6 nd", .short_help = "ip6 nd ...", .function = ip6_ra_cmd, }; -/* *INDENT-ON* */ /** * VFT for registering as a delegate to an IP6 link @@ -2300,12 +2239,10 @@ ip6_ra_init (vlib_main_t * vm) return (NULL); } -/* *INDENT-OFF* */ VLIB_INIT_FUNCTION (ip6_ra_init) = { .runs_after = VLIB_INITS("icmp6_init"), }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON