ip6-nd: support dump/details for IPv6 RA
Type: improvement With this change, add support for dumping IPv6 Router Advertisements details on a per-interface basis (or all). Also, cover that with a test. Signed-off-by: Alexander Chernavin <achernavin@netgate.com> Change-Id: I89fa93439d33cc36252377f27187b18b3d30a1d4
This commit is contained in:

committed by
Neale Ranns

parent
02dfd29634
commit
3b28fd7306
@ -20,7 +20,7 @@
|
||||
called through a shared memory interface.
|
||||
*/
|
||||
|
||||
option version = "1.0.0";
|
||||
option version = "1.1.0";
|
||||
|
||||
import "vnet/ip/ip_types.api";
|
||||
import "vnet/interface_types.api";
|
||||
@ -106,6 +106,134 @@ autoreply define sw_interface_ip6nd_ra_prefix
|
||||
u32 pref_lifetime;
|
||||
};
|
||||
|
||||
/** \brief IPv6 Router Advertisements prefix entry
|
||||
@param prefix - prefix to advertise
|
||||
@param onlink_flag - if true, the prefix can be used for on-link
|
||||
determination
|
||||
@param autonomous_flag - if true, the prefix can be used for stateless
|
||||
address configuration
|
||||
@param val_lifetime - valid lifetime in seconds (0xffffffff represents
|
||||
infinity)
|
||||
@param pref_lifetime - preferred lifetime in seconds (0xffffffff represents
|
||||
infinity)
|
||||
@param valid_lifetime_expires - number of seconds in which valid lifetime
|
||||
expires (zero means never, negative value
|
||||
means expired this number of seconds ago)
|
||||
@param pref_lifetime_expires - number of seconds in which preferred
|
||||
lifetime expires (zero means never, negative
|
||||
value means expired this number of seconds
|
||||
ago)
|
||||
@param decrement_lifetime_flag - if true, decrement valid lifetime and
|
||||
preferred lifetime
|
||||
@param no_advertise - if true, the prefix will not be advertised
|
||||
*/
|
||||
typedef ip6nd_ra_prefix
|
||||
{
|
||||
vl_api_prefix_t prefix;
|
||||
bool onlink_flag;
|
||||
bool autonomous_flag;
|
||||
u32 val_lifetime;
|
||||
u32 pref_lifetime;
|
||||
f64 valid_lifetime_expires;
|
||||
f64 pref_lifetime_expires;
|
||||
bool decrement_lifetime_flag;
|
||||
bool no_advertise;
|
||||
};
|
||||
|
||||
/** \brief Dump IPv6 Router Advertisements details on a per-interface basis
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param sw_if_index - interface index to use as a filter (0xffffffff
|
||||
represents all interfaces)
|
||||
*/
|
||||
define sw_interface_ip6nd_ra_dump
|
||||
{
|
||||
option in_progress;
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
option vat_help = "[(<if-name>|sw_if_index <if-idx>)]";
|
||||
};
|
||||
|
||||
/** \brief Details on IPv6 Router Advertisements for a single interface
|
||||
@param context - returned sender context, to match reply w/ request
|
||||
@param sw_if_index - interface index the details are belong to
|
||||
@param cur_hop_limit - current hop limit
|
||||
@param adv_managed_flag - if true, enable DHCP for address
|
||||
@param adv_other_flag - if true, Enable DHCP for other information
|
||||
@param adv_router_lifetime - lifetime associated with the default router in
|
||||
seconds (zero indicates that the router is not
|
||||
a default router)
|
||||
@param adv_neighbor_reachable_time - number of milliseconds within which a
|
||||
neighbor is assumed to be reachable
|
||||
(zero means unspecified)
|
||||
@param adv_retransmit_interval - number of milliseconds between
|
||||
retransmitted Neighbor Solicitation
|
||||
messages (zero means unspecified)
|
||||
@param adv_link_mtu - MTU that all the nodes on a link use
|
||||
@param send_radv - if true, send periodic Router Advertisements
|
||||
@param cease_radv - if true, cease to send periodic Router Advertisements
|
||||
@param send_unicast - if true, destination address of a Router
|
||||
Advertisement message will use the source address of
|
||||
the Router Solicitation message (when available).
|
||||
Otherwise, multicast address will be used
|
||||
@param adv_link_layer_address - if true, add link layer address option
|
||||
@param max_radv_interval - maximum time in seconds allowed between sending
|
||||
unsolicited multicast Router Advertisements
|
||||
@param min_radv_interval - minimum time in seconds allowed between sending
|
||||
unsolicited multicast Router Advertisements
|
||||
@param last_radv_time - number of seconds since the last time a solicited
|
||||
Router Advertisement message was sent (zero means
|
||||
never)
|
||||
@param last_multicast_time - number of seconds since the last time a
|
||||
multicast Router Advertisements message was
|
||||
sent (zero means never)
|
||||
@param next_multicast_time - number of seconds within which next time a
|
||||
multicast Router Advertisement message will be
|
||||
sent (zero means never)
|
||||
@param initial_adverts_count - number of initial Router Advertisement
|
||||
messages to send
|
||||
@param initial_adverts_interval - number of seconds between initial Router
|
||||
Advertisement messages
|
||||
@param initial_adverts_sent - if true, all initial Router Advertisement
|
||||
messages were sent
|
||||
@param n_advertisements_sent - number of Router Advertisements sent
|
||||
@param n_solicitations_rcvd - number of Router Solicitations received
|
||||
@param n_solicitations_dropped - number of Router Solicitations dropped
|
||||
@param n_prefixes - number of prefix entries
|
||||
@param prefixes - array of prefix entries
|
||||
*/
|
||||
define sw_interface_ip6nd_ra_details
|
||||
{
|
||||
option in_progress;
|
||||
u32 context;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
u8 cur_hop_limit;
|
||||
bool adv_managed_flag;
|
||||
bool adv_other_flag;
|
||||
u16 adv_router_lifetime;
|
||||
u32 adv_neighbor_reachable_time;
|
||||
u32 adv_retransmit_interval;
|
||||
u32 adv_link_mtu;
|
||||
bool send_radv;
|
||||
bool cease_radv;
|
||||
bool send_unicast;
|
||||
bool adv_link_layer_address;
|
||||
f64 max_radv_interval;
|
||||
f64 min_radv_interval;
|
||||
f64 last_radv_time;
|
||||
f64 last_multicast_time;
|
||||
f64 next_multicast_time;
|
||||
u32 initial_adverts_count;
|
||||
f64 initial_adverts_interval;
|
||||
bool initial_adverts_sent;
|
||||
u32 n_advertisements_sent;
|
||||
u32 n_solicitations_rcvd;
|
||||
u32 n_solicitations_dropped;
|
||||
u32 n_prefixes;
|
||||
vl_api_ip6nd_ra_prefix_t prefixes[n_prefixes];
|
||||
};
|
||||
|
||||
/** \brief IPv6 ND (mirror) proxy
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
|
@ -221,6 +221,175 @@ static void
|
||||
REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
|
||||
}
|
||||
|
||||
static void
|
||||
ip6_radv_prefix_encode (f64 now, const ip6_radv_prefix_t *in,
|
||||
vl_api_ip6nd_ra_prefix_t *out)
|
||||
{
|
||||
fib_prefix_t in_ip6_pfx = {
|
||||
.fp_addr = {
|
||||
.ip6 = in->prefix,
|
||||
},
|
||||
.fp_len = in->prefix_len,
|
||||
.fp_proto = FIB_PROTOCOL_IP6,
|
||||
};
|
||||
|
||||
ip_prefix_encode (&in_ip6_pfx, &out->prefix);
|
||||
|
||||
out->onlink_flag = in->adv_on_link_flag;
|
||||
out->autonomous_flag = in->adv_autonomous_flag;
|
||||
out->val_lifetime = htonl (in->adv_valid_lifetime_in_secs);
|
||||
out->pref_lifetime = htonl (in->adv_pref_lifetime_in_secs);
|
||||
|
||||
if (in->adv_valid_lifetime_in_secs != ~0)
|
||||
{
|
||||
out->valid_lifetime_expires =
|
||||
clib_host_to_net_f64 (in->valid_lifetime_expires - now);
|
||||
}
|
||||
|
||||
if (in->adv_pref_lifetime_in_secs != ~0)
|
||||
{
|
||||
out->pref_lifetime_expires =
|
||||
clib_host_to_net_f64 (in->pref_lifetime_expires - now);
|
||||
}
|
||||
|
||||
out->decrement_lifetime_flag = in->decrement_lifetime_flag;
|
||||
out->no_advertise = (in->enabled == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
send_sw_interface_ip6nd_ra_details (vl_api_registration_t *reg, u32 context,
|
||||
ip6_ra_t *radv_info)
|
||||
{
|
||||
vl_api_sw_interface_ip6nd_ra_details_t *rmp = 0;
|
||||
vl_api_ip6nd_ra_prefix_t *api_radv_pfx;
|
||||
u32 n_prefixes = pool_elts (radv_info->adv_prefixes_pool);
|
||||
ip6_radv_prefix_t *radv_pfx;
|
||||
u32 msg_size = sizeof (*rmp) + n_prefixes * sizeof (*api_radv_pfx);
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
f64 now = vlib_time_now (vm);
|
||||
|
||||
rmp = vl_msg_api_alloc (msg_size);
|
||||
if (!rmp)
|
||||
return;
|
||||
clib_memset (rmp, 0, msg_size);
|
||||
rmp->_vl_msg_id =
|
||||
ntohs (VL_API_SW_INTERFACE_IP6ND_RA_DETAILS + REPLY_MSG_ID_BASE);
|
||||
rmp->context = context;
|
||||
|
||||
rmp->sw_if_index = htonl (radv_info->sw_if_index);
|
||||
rmp->cur_hop_limit = radv_info->curr_hop_limit;
|
||||
rmp->adv_managed_flag = radv_info->adv_managed_flag;
|
||||
rmp->adv_other_flag = radv_info->adv_other_flag;
|
||||
rmp->adv_router_lifetime = htons (radv_info->adv_router_lifetime_in_sec);
|
||||
rmp->adv_neighbor_reachable_time =
|
||||
htonl (radv_info->adv_neighbor_reachable_time_in_msec);
|
||||
rmp->adv_retransmit_interval = htonl (
|
||||
radv_info->adv_time_in_msec_between_retransmitted_neighbor_solicitations);
|
||||
rmp->adv_link_mtu = htonl (radv_info->adv_link_mtu);
|
||||
rmp->send_radv = radv_info->send_radv;
|
||||
rmp->cease_radv = radv_info->cease_radv;
|
||||
rmp->send_unicast = radv_info->send_unicast;
|
||||
rmp->adv_link_layer_address = radv_info->adv_link_layer_address;
|
||||
rmp->max_radv_interval = clib_host_to_net_f64 (radv_info->max_radv_interval);
|
||||
rmp->min_radv_interval = clib_host_to_net_f64 (radv_info->min_radv_interval);
|
||||
|
||||
if (radv_info->last_radv_time > 0.0)
|
||||
{
|
||||
rmp->last_radv_time =
|
||||
clib_host_to_net_f64 (now - radv_info->last_radv_time);
|
||||
}
|
||||
|
||||
if ((radv_info->next_multicast_time - radv_info->last_multicast_time) > 0.0)
|
||||
{
|
||||
rmp->last_multicast_time =
|
||||
clib_host_to_net_f64 (now - radv_info->last_multicast_time);
|
||||
rmp->next_multicast_time =
|
||||
clib_host_to_net_f64 (radv_info->next_multicast_time - now);
|
||||
}
|
||||
|
||||
rmp->initial_adverts_count = htonl (radv_info->initial_adverts_count);
|
||||
rmp->initial_adverts_interval =
|
||||
clib_host_to_net_f64 (radv_info->initial_adverts_interval);
|
||||
rmp->initial_adverts_sent = (radv_info->initial_adverts_sent == 0);
|
||||
rmp->n_advertisements_sent = htonl (radv_info->n_advertisements_sent);
|
||||
rmp->n_solicitations_rcvd = htonl (radv_info->n_solicitations_rcvd);
|
||||
rmp->n_solicitations_dropped = htonl (radv_info->n_solicitations_dropped);
|
||||
rmp->n_prefixes = htonl (n_prefixes);
|
||||
|
||||
api_radv_pfx = rmp->prefixes;
|
||||
pool_foreach (radv_pfx, radv_info->adv_prefixes_pool)
|
||||
{
|
||||
ip6_radv_prefix_encode (now, radv_pfx, api_radv_pfx);
|
||||
|
||||
api_radv_pfx++;
|
||||
}
|
||||
|
||||
vl_api_send_msg (reg, (u8 *) rmp);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 *sw_if_indices;
|
||||
} api_dump_ip6_ra_itf_walk_ctx_t;
|
||||
|
||||
static walk_rc_t
|
||||
api_dump_ip6_ra_itf_walk_fn (u32 sw_if_index, void *arg)
|
||||
{
|
||||
api_dump_ip6_ra_itf_walk_ctx_t *ctx = arg;
|
||||
|
||||
vec_add1 (ctx->sw_if_indices, sw_if_index);
|
||||
|
||||
return (WALK_CONTINUE);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_sw_interface_ip6nd_ra_dump_t_handler (
|
||||
vl_api_sw_interface_ip6nd_ra_dump_t *mp)
|
||||
{
|
||||
vl_api_registration_t *reg;
|
||||
u32 sw_if_index;
|
||||
ip6_ra_t *radv_info;
|
||||
|
||||
reg = vl_api_client_index_to_registration (mp->client_index);
|
||||
if (!reg)
|
||||
return;
|
||||
|
||||
sw_if_index = ntohl (mp->sw_if_index);
|
||||
|
||||
if (sw_if_index == INDEX_INVALID)
|
||||
{
|
||||
/* dump all interfaces */
|
||||
|
||||
api_dump_ip6_ra_itf_walk_ctx_t ctx = {
|
||||
.sw_if_indices = NULL,
|
||||
};
|
||||
u32 *sw_if_i;
|
||||
|
||||
ip6_ra_itf_walk (api_dump_ip6_ra_itf_walk_fn, &ctx);
|
||||
|
||||
vec_foreach (sw_if_i, ctx.sw_if_indices)
|
||||
{
|
||||
radv_info = ip6_ra_get_itf (*sw_if_i);
|
||||
if (radv_info != NULL)
|
||||
{
|
||||
send_sw_interface_ip6nd_ra_details (reg, mp->context, radv_info);
|
||||
}
|
||||
}
|
||||
|
||||
vec_free (ctx.sw_if_indices);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* dump a single interface */
|
||||
|
||||
radv_info = ip6_ra_get_itf (sw_if_index);
|
||||
if (radv_info != NULL)
|
||||
{
|
||||
send_sw_interface_ip6nd_ra_details (reg, mp->context, radv_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_ip6nd_send_router_solicitation_t_handler
|
||||
(vl_api_ip6nd_send_router_solicitation_t * mp)
|
||||
|
@ -325,6 +325,63 @@ api_ip6nd_proxy_enable_disable (vat_main_t *vam)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
api_sw_interface_ip6nd_ra_dump (vat_main_t *vam)
|
||||
{
|
||||
unformat_input_t *i = vam->input;
|
||||
vl_api_sw_interface_ip6nd_ra_dump_t *mp;
|
||||
vl_api_control_ping_t *mp_ping;
|
||||
u32 sw_if_index = ~0;
|
||||
int ret;
|
||||
|
||||
/* Parse args required to build the message */
|
||||
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
|
||||
;
|
||||
else if (unformat (i, "sw_if_index %u", &sw_if_index))
|
||||
;
|
||||
else
|
||||
{
|
||||
clib_warning ("parse error '%U'", format_unformat_error, i);
|
||||
return -99;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct the API message */
|
||||
M (SW_INTERFACE_IP6ND_RA_DUMP, mp);
|
||||
mp->sw_if_index = ntohl (sw_if_index);
|
||||
|
||||
/* Send it */
|
||||
S (mp);
|
||||
|
||||
/* Use control ping for synchronization */
|
||||
PING (&ip6_nd_test_main, mp_ping);
|
||||
S (mp_ping);
|
||||
|
||||
/* Wait for a reply... */
|
||||
W (ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_sw_interface_ip6nd_ra_details_t_handler (
|
||||
vl_api_sw_interface_ip6nd_ra_details_t *mp)
|
||||
{
|
||||
vat_main_t *vam = ip6_nd_test_main.vat_main;
|
||||
u32 sw_if_index;
|
||||
u8 send_radv;
|
||||
|
||||
/* Read the message */
|
||||
sw_if_index = ntohl (mp->sw_if_index);
|
||||
send_radv = mp->send_radv;
|
||||
|
||||
/* Print it */
|
||||
print (vam->ofp, "sw_if_index: %u, send_radv: %s", sw_if_index,
|
||||
(send_radv ? "on" : "off"));
|
||||
}
|
||||
|
||||
#include <ip6-nd/ip6_nd.api_test.c>
|
||||
|
||||
/*
|
||||
|
@ -65,95 +65,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 +102,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;
|
||||
@ -214,6 +125,18 @@ ip6_ra_adv_enabled (u32 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") \
|
||||
|
@ -21,6 +21,105 @@
|
||||
|
||||
#include <vnet/fib/fib_types.h>
|
||||
|
||||
/* 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
|
||||
{
|
||||
u32 irt;
|
||||
u32 mrt;
|
||||
u32 mrc;
|
||||
u32 mrd;
|
||||
} icmp6_send_router_solicitation_params_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;
|
||||
|
||||
extern ip6_ra_t *ip6_ra_get_itf (u32 sw_if_index);
|
||||
|
||||
extern int ip6_ra_config (vlib_main_t * vm, u32 sw_if_index,
|
||||
u8 suppress, u8 managed, u8 other,
|
||||
u8 ll_option, u8 send_unicast, u8 cease,
|
||||
@ -35,13 +134,9 @@ extern int ip6_ra_prefix (vlib_main_t * vm, u32 sw_if_index,
|
||||
u8 off_link, u8 no_autoconfig,
|
||||
u8 no_onlink, u8 is_no);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 irt;
|
||||
u32 mrt;
|
||||
u32 mrc;
|
||||
u32 mrd;
|
||||
} icmp6_send_router_solicitation_params_t;
|
||||
typedef walk_rc_t (*ip6_ra_itf_walk_fn_t) (u32 sw_if_index, void *ctx);
|
||||
|
||||
extern void ip6_ra_itf_walk (ip6_ra_itf_walk_fn_t fn, void *ctx);
|
||||
|
||||
extern void icmp6_send_router_solicitation (vlib_main_t * vm,
|
||||
u32 sw_if_index,
|
||||
|
@ -779,6 +779,85 @@ class TestIPv6(TestIPv6ND):
|
||||
rx = rx[0]
|
||||
self.validate_ra(intf, rx, dst_ip, src_ip=src_ip, pi_opt=opt)
|
||||
|
||||
def test_ip6_ra_dump(self):
|
||||
"""IPv6 RA dump"""
|
||||
|
||||
# Dump IPv6 RA for all interfaces
|
||||
ip6_ra_dump = self.vapi.sw_interface_ip6nd_ra_dump(sw_if_index=0xFFFFFFFF)
|
||||
self.assertEqual(len(ip6_ra_dump), len(self.interfaces))
|
||||
|
||||
for ip6_ra in ip6_ra_dump:
|
||||
self.assertFalse(ip6_ra.send_radv)
|
||||
self.assertEqual(ip6_ra.n_prefixes, 0)
|
||||
self.assertEqual(len(ip6_ra.prefixes), 0)
|
||||
self.assertEqual(ip6_ra.last_radv_time, 0.0)
|
||||
self.assertEqual(ip6_ra.last_multicast_time, 0.0)
|
||||
self.assertEqual(ip6_ra.next_multicast_time, 0.0)
|
||||
self.assertEqual(ip6_ra.n_advertisements_sent, 0)
|
||||
self.assertEqual(ip6_ra.n_solicitations_rcvd, 0)
|
||||
self.assertEqual(ip6_ra.n_solicitations_dropped, 0)
|
||||
|
||||
# Enable sending IPv6 RA for an interface
|
||||
self.pg0.ip6_ra_config(no=1, suppress=1)
|
||||
|
||||
# Add IPv6 RA prefixes for the interface
|
||||
pfx0 = IPv6Network(
|
||||
"%s/%s" % (self.pg0.local_ip6, self.pg0.local_ip6_prefix_len), strict=False
|
||||
)
|
||||
pfx1 = IPv6Network("fafa::/96")
|
||||
self.pg0.ip6_ra_prefix(pfx0, off_link=0, no_autoconfig=0)
|
||||
self.pg0.ip6_ra_prefix(pfx1, off_link=1, no_autoconfig=1)
|
||||
|
||||
# Wait for multicast IPv6 RA
|
||||
self.sleep(1)
|
||||
|
||||
# Dump IPv6 RA for the interface
|
||||
ip6_ra_dump = self.vapi.sw_interface_ip6nd_ra_dump(
|
||||
sw_if_index=self.pg0.sw_if_index
|
||||
)
|
||||
self.assertEqual(len(ip6_ra_dump), 1)
|
||||
ip6_ra = ip6_ra_dump[0]
|
||||
|
||||
self.assertEqual(ip6_ra.sw_if_index, self.pg0.sw_if_index)
|
||||
self.assertTrue(ip6_ra.send_radv)
|
||||
self.assertEqual(ip6_ra.n_prefixes, 2)
|
||||
self.assertEqual(len(ip6_ra.prefixes), 2)
|
||||
self.assertEqual(ip6_ra.last_radv_time, 0.0)
|
||||
self.assertGreater(ip6_ra.last_multicast_time, 0.0)
|
||||
self.assertGreater(ip6_ra.next_multicast_time, 0.0)
|
||||
self.assertGreater(ip6_ra.n_advertisements_sent, 0)
|
||||
self.assertEqual(ip6_ra.n_solicitations_rcvd, 0)
|
||||
self.assertEqual(ip6_ra.n_solicitations_dropped, 0)
|
||||
|
||||
self.assertEqual(ip6_ra.prefixes[0].prefix, pfx0)
|
||||
self.assertTrue(ip6_ra.prefixes[0].onlink_flag)
|
||||
self.assertTrue(ip6_ra.prefixes[0].autonomous_flag)
|
||||
self.assertFalse(ip6_ra.prefixes[0].no_advertise)
|
||||
|
||||
self.assertEqual(ip6_ra.prefixes[1].prefix, pfx1)
|
||||
self.assertFalse(ip6_ra.prefixes[1].onlink_flag)
|
||||
self.assertFalse(ip6_ra.prefixes[1].autonomous_flag)
|
||||
self.assertFalse(ip6_ra.prefixes[1].no_advertise)
|
||||
|
||||
# Reset sending IPv6 RA for the interface
|
||||
self.pg0.ip6_ra_config(suppress=1)
|
||||
|
||||
# Remove IPv6 RA prefixes for the interface
|
||||
self.pg0.ip6_ra_prefix(pfx0, is_no=1)
|
||||
self.pg0.ip6_ra_prefix(pfx1, is_no=1)
|
||||
|
||||
# Dump IPv6 RA for the interface
|
||||
ip6_ra_dump = self.vapi.sw_interface_ip6nd_ra_dump(
|
||||
sw_if_index=self.pg0.sw_if_index
|
||||
)
|
||||
self.assertEqual(len(ip6_ra_dump), 1)
|
||||
ip6_ra = ip6_ra_dump[0]
|
||||
|
||||
self.assertEqual(ip6_ra.sw_if_index, self.pg0.sw_if_index)
|
||||
self.assertFalse(ip6_ra.send_radv)
|
||||
self.assertEqual(ip6_ra.n_prefixes, 0)
|
||||
self.assertEqual(len(ip6_ra.prefixes), 0)
|
||||
|
||||
def test_rs(self):
|
||||
"""IPv6 Router Solicitation Exceptions
|
||||
|
||||
|
Reference in New Issue
Block a user