zebra: add ability to set retransmit timer for IPv6 RAs

Reported by testing agency that rfc 4861 section 6.2.1 states
that all implementations must have a configuration knob to change
the setting of the advertised retransmit timer sent in RA packets.
This fix adds that capability.

Ticket: CM-29199
Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
This commit is contained in:
Don Slice 2020-04-28 11:54:14 +00:00
parent f6be730827
commit b19ac878be

View File

@ -265,7 +265,7 @@ static void rtadv_send_packet(int sock, struct interface *ifp,
rtadv->nd_ra_router_lifetime =
(stop == RA_SUPPRESS) ? htons(0) : htons(pkt_RouterLifetime);
rtadv->nd_ra_reachable = htonl(zif->rtadv.AdvReachableTime);
rtadv->nd_ra_retransmit = htonl(0);
rtadv->nd_ra_retransmit = htonl(zif->rtadv.AdvRetransTimer);
len = sizeof(struct nd_router_advert);
@ -679,9 +679,8 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
ifp->name, ifp->ifindex, addr_str);
}
if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer)
&& (ntohl(radvert->nd_ra_retransmit)
!= (unsigned int)zif->rtadv.AdvRetransTimer)) {
if ((ntohl(radvert->nd_ra_retransmit)
!= (unsigned int)zif->rtadv.AdvRetransTimer)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
"%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
@ -1282,6 +1281,53 @@ DEFPY (no_ipv6_nd_ra_hop_limit,
return CMD_SUCCESS;
}
DEFPY (ipv6_nd_ra_retrans_interval,
ipv6_nd_ra_retrans_interval_cmd,
"ipv6 nd ra-retrans-interval (0-4294967295)$interval",
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Advertisement Retransmit Interval\n"
"Advertisement Retransmit Interval in msec\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
if (if_is_loopback(ifp)
|| CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
vty_out(vty,
"Cannot configure IPv6 Router Advertisements on loopback interface\n");
return CMD_WARNING_CONFIG_FAILED;
}
zif->rtadv.AdvRetransTimer = interval;
return CMD_SUCCESS;
}
DEFPY (no_ipv6_nd_ra_retrans_interval,
no_ipv6_nd_ra_retrans_interval_cmd,
"no ipv6 nd ra-retrans-interval [(0-4294967295)]",
NO_STR
"Interface IPv6 config commands\n"
"Neighbor discovery\n"
"Advertisement Retransmit Interval\n"
"Advertisement Retransmit Interval in msec\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
if (if_is_loopback(ifp)
|| CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) {
vty_out(vty,
"Cannot remove IPv6 Router Advertisements on loopback interface\n");
return CMD_WARNING_CONFIG_FAILED;
}
zif->rtadv.AdvRetransTimer = 0;
return CMD_SUCCESS;
}
DEFUN (ipv6_nd_suppress_ra,
ipv6_nd_suppress_ra_cmd,
"ipv6 nd suppress-ra",
@ -2227,7 +2273,7 @@ static int nd_dump_vty(struct vty *vty, struct interface *ifp)
" ND advertised reachable time is %d milliseconds\n",
rtadv->AdvReachableTime);
vty_out(vty,
" ND advertised retransmit interval is %d milliseconds\n",
" ND advertised retransmit interval is %u milliseconds\n",
rtadv->AdvRetransTimer);
vty_out(vty, " ND advertised hop-count limit is %d hops\n",
rtadv->AdvCurHopLimit);
@ -2322,6 +2368,10 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
if (!zif->rtadv.UseFastRexmit)
vty_out(vty, " no ipv6 nd ra-fast-retrans\n");
if (zif->rtadv.AdvRetransTimer != 0)
vty_out(vty, " ipv6 nd ra-retrans-interval %u\n",
zif->rtadv.AdvRetransTimer);
if (zif->rtadv.AdvCurHopLimit != RTADV_DEFAULT_HOPLIMIT)
vty_out(vty, " ipv6 nd ra-hop-limit %d\n",
zif->rtadv.AdvCurHopLimit);
@ -2494,6 +2544,8 @@ void rtadv_cmd_init(void)
install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
install_element(INTERFACE_NODE, &no_ipv6_nd_ra_retrans_interval_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_ra_hop_limit_cmd);
install_element(INTERFACE_NODE, &no_ipv6_nd_ra_hop_limit_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);