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));
+}
+
/* for "syslogging" - use elog for now */
#define foreach_log_level \
_ (DEBUG, "DEBUG") \
{
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;
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)
if (PREDICT_TRUE (error0 == ICMP6_ERROR_NONE && o0 != 0 &&
!is_unspecified && !is_link_local))
{
+ /* *INDENT-OFF* */
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,
+ },
};
+ /* *INDENT-ON* */
memcpy (&learn.mac, o0->ethernet_address, sizeof (learn.mac));
ip_neighbor_learn_dp (&learn);
}
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);
/* 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,
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)))
}
h.unused = 0;
- clib_warning ("Prefix %U valid %u preferred %u",
- format_ip6_address, &pr_info->prefix,
- clib_net_to_host_u32 (h.valid_time),
- clib_net_to_host_u32 (h.preferred_time));
+ /* Handy for debugging, but too noisy... */
+ if (0 && CLIB_DEBUG > 0)
+ clib_warning
+ ("send RA for prefix %U/%d "
+ "sw_if_index %d valid %u preferred %u",
+ format_ip6_address, &pr_info->prefix,
+ pr_info->prefix_len, sw_if_index0,
+ clib_net_to_host_u32 (h.valid_time),
+ clib_net_to_host_u32 (h.preferred_time));
if (h.valid_time == 0)
- clib_warning ("WARNING: valid_time 0!!!");
+ clib_warning ("BUG: send RA with valid_time 0");
clib_memcpy(&h.dst_address, &pr_info->prefix, sizeof(ip6_address_t));
}
}
- }));
+ }
/* *INDENT-ON* */
/* add additional options before here */
/* 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 :
/* 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);
}
}
break;
- }));
+ }
/* *INDENT-ON* */
break;
}
}
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;
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);
{
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);
}
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);
pool_put (ip6_ra_pool, radv_info);
}
+void
+ip6_ra_update_secondary_radv_info (ip6_address_t * address, u8 prefix_len,
+ u32 primary_sw_if_index,
+ u32 valid_time, u32 preferred_time)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ static u32 *radv_indices;
+ ip6_ra_t *radv_info;
+ int i;
+ ip6_address_t mask;
+ ip6_address_mask_from_width (&mask, prefix_len);
+
+ vec_reset_length (radv_indices);
+ /* *INDENT-OFF* */
+ 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,
+ * tell the RA code about it...
+ */
+ for (i = 0; i < vec_len (radv_indices); i++)
+ {
+ ip6_radv_prefix_t *this_prefix;
+ radv_info = pool_elt_at_index (ip6_ra_pool, radv_indices[i]);
+
+ /* We already took care of these timers... */
+ if (radv_info->sw_if_index == primary_sw_if_index)
+ continue;
+
+ /* *INDENT-OFF* */
+ 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))
+ {
+ int rv = ip6_ra_prefix (vm,
+ radv_info->sw_if_index,
+ address,
+ prefix_len,
+ 0 /* use_default */,
+ valid_time,
+ preferred_time,
+ 0 /* no_advertise */,
+ 0 /* off_link */,
+ 0 /* no_autoconfig */,
+ 0 /* no_onlink */,
+ 0 /* is_no */);
+ if (rv != 0)
+ clib_warning ("ip6_neighbor_ra_prefix returned %d", rv);
+ }
+ }
+ /* *INDENT-ON*/
+ }
+}
+
/* send a RA or update the timer info etc.. */
static uword
ip6_ra_process_timer_event (vlib_main_t * 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;
f = 0;
}
}
- }));
+ }
/* *INDENT-ON* */
if (f)
}
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 */
{
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 */
}
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;
}
+/* *INDENT-OFF* */
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,
+};
+/* *INDENT-ON* */
static void
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
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;
unformat_ip6_address, &ip6_addr, &addr_len))
{
add_radv_info = 0;
- break;
}
else if (unformat (line_input, "ra-managed-config-flag"))
{
managed = 1;
- break;
}
else if (unformat (line_input, "ra-other-config-flag"))
{
other = 1;
- break;
}
else if (unformat (line_input, "ra-suppress") ||
unformat (line_input, "ra-surpress"))
{
suppress = 1;
- break;
}
else if (unformat (line_input, "ra-suppress-link-layer") ||
unformat (line_input, "ra-surpress-link-layer"))
{
suppress_ll_option = 1;
- break;
}
else if (unformat (line_input, "ra-send-unicast"))
{
send_unicast = 1;
- break;
}
else if (unformat (line_input, "ra-lifetime"))
{
goto done;
}
use_lifetime = 1;
- break;
}
else if (unformat (line_input, "ra-initial"))
{
error = unformat_parse_error (line_input);
goto done;
}
- break;
}
else if (unformat (line_input, "ra-interval"))
{
if (!unformat (line_input, "%d", &ra_min_interval))
ra_min_interval = 0;
- break;
}
else if (unformat (line_input, "ra-cease"))
{
cease = 1;
- break;
}
else
{
- error = unformat_parse_error (line_input);
- goto done;
+ break;
}
}
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",
return (s);
}
-
/*?
* This command is used to configure the neighbor discovery
* parameters on a given interface. Use the '<em>show ip6 interface</em>'
* on a given interface. This command has three formats:
*
*
- * <b>Format 1 - Router Advertisement Options:</b> (Only one can be entered in a single command)
+ * <b>Format 1 - Router Advertisement Options:</b> (Only one can be entered in
+ * a single command)
*
- * '<em><b>ip6 nd <interface> [no] [ra-managed-config-flag] | [ra-other-config-flag] | [ra-suppress] | [ra-suppress-link-layer] | [ra-send-unicast] | [ra-lifetime <lifetime>] | [ra-initial <cnt> <interval>] | [ra-interval <max-interval> [<min-interval>]] | [ra-cease]</b></em>'
+ * @clistart
+ * ip6 nd <interface> [no] [ra-managed-config-flag] |
+ * [ra-other-config-flag] | [ra-suppress] | [ra-suppress-link-layer] |
+ * [ra-send-unicast] | [ra-lifetime <lifetime>] |
+ * [ra-initial <cnt> <interval>] |
+ * [ra-interval <max-interval> [<min-interval>]] | [ra-cease]
+ * @cliend
*
* Where:
*
* and the '<em>no</em>' option returns it to this default state.
*
* <em>[no] ra-send-unicast</em> - 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 '<em>no</em>' option returns
* it to this default state.
*
*
* <b>Format 2 - Prefix Options:</b>
*
- * '<em><b>ip6 nd <interface> [no] prefix <ip6-address>/<width> [<valid-lifetime> <pref-lifetime> | infinite] [no-advertise] [off-link] [no-autoconfig] [no-onlink]</b></em>'
+ * @clistart
+ * ip6 nd <interface> [no] prefix <ip6-address>/<width>
+ * [<valid-lifetime> <pref-lifetime> | infinite] [no-advertise] [off-link]
+ * [no-autoconfig] [no-onlink]
+ * @cliend
*
* Where:
*
* <em>no</em> - All additional flags are ignored and the prefix is deleted.
*
- * <em><valid-lifetime> <pref-lifetime></em> - '<em><valid-lifetime></em>' 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). '<em><pref-lifetime></em>' 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).
+ * <em><valid-lifetime> <pref-lifetime></em> - '<em><valid-lifetime></em>' 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). '<em><pref-lifetime></em>' 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).
*
- * <em>infinite</em> - Both '<em><valid-lifetime></em>' and '<em><<pref-lifetime></em>'
- * are inifinte, no timeout.
+ * <em>infinite</em> - Both '<em><valid-lifetime></em>' and
+ * '<em><pref-lifetime></em>' are infinite, no timeout.
*
* <em>no-advertise</em> - Do not send full router address in prefix
* advertisement. Default is to advertise (i.e. - This flag is off by default).
*
- * <em>off-link</em> - 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). '<em>no-onlink</em>' also controls the L-bit.
+ * <em>off-link</em> - 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). '<em>no-onlink</em>'
+ * also controls the L-bit.
*
- * <em>no-autoconfig</em> - 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.
+ * <em>no-autoconfig</em> - 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.
*
- * <em>no-onlink</em> - 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). '<em>off-link</em>' also controls
- * the L-bit.
+ * <em>no-onlink</em> - 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).
+ * '<em>off-link</em>' also controls the L-bit.
*
*
* <b>Format 3: - Default of Prefix:</b>
*
- * '<em><b>ip6 nd <interface> [no] prefix <ip6-address>/<width> default</b></em>'
+ * @cliexcmd{ip6 nd <interface> [no] prefix <ip6-address>/<width> default}
*
- * When a new prefix is added (or existing one is being overwritten) <em>default</em>
- * uses default values for the prefix. If <em>no</em> is used, the <em>default</em>
- * is ignored and the prefix is deleted.
+ * When a new prefix is added (or existing one is being overwritten)
+ * <em>default</em> uses default values for the prefix. If <em>no</em> is
+ * used, the <em>default</em> 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}
?*/