aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Smith <mgsmith@netgate.com>2022-11-05 18:33:08 +0000
committerDave Barach <openvpp@barachs.net>2022-11-06 12:48:15 +0000
commitce1ff6a9b1ab2c4ab74165b26c92c2d551f53cf8 (patch)
treed8eaeb827bee743bc71e3a6f82c6f2ab70c2cad6
parentf094ce7653917b8c331a79c088ef63ea2679c40d (diff)
ip6-nd: set router flag on NA if appropriate
Type: fix The router flag on a neighbor advertisement can be used by neighbors to detect that a router has changed to a host (RFC 4861 section 4.4). If a neighbor adds routes after receiving a router advertisement sent by VPP and subsequently receives a neighbor advertisement sent by VPP, it may remove any routes it added based on the RA if the NA does not have the router flag set. It appears that this is how windows behaves. When sending a neighbor advertisement, set the router flag if sending RAs is enabled on the interface. Signed-off-by: Matthew Smith <mgsmith@netgate.com> Change-Id: I1f3e42bbd8ea1a4c116b1ce5a8273652d4cd763d
-rw-r--r--src/vnet/ip6-nd/ip6_nd_inline.h8
-rw-r--r--src/vnet/ip6-nd/ip6_ra.c10
-rw-r--r--src/vnet/ip6-nd/ip6_ra.h2
3 files changed, 19 insertions, 1 deletions
diff --git a/src/vnet/ip6-nd/ip6_nd_inline.h b/src/vnet/ip6-nd/ip6_nd_inline.h
index 5e8b9d6e4c0..c959c94ed1d 100644
--- a/src/vnet/ip6-nd/ip6_nd_inline.h
+++ b/src/vnet/ip6-nd/ip6_nd_inline.h
@@ -23,6 +23,7 @@
#include <vnet/ip/icmp46_packet.h>
#include <vnet/ip/ip6.h>
#include <vnet/ip-neighbor/ip_neighbor_types.h>
+#include <vnet/ip6-nd/ip6_ra.h>
typedef enum
{
@@ -71,6 +72,13 @@ icmp6_send_neighbor_advertisement (
clib_host_to_net_u32 (ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED |
ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE);
+ /* if sending RAs is enabled, the "router" flag should be set,
+ * otherwise, neighbors may believe we have changed from a router
+ * to a host - RFC 4861 section 4.4 */
+ if (ip6_ra_adv_enabled (sw_if_index0))
+ icmp6_nsa->advertisement_flags |=
+ clib_host_to_net_u32 (ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER);
+
icmp6_nsa->icmp.checksum = 0;
icmp6_nsa->icmp.checksum =
ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6_h, &bogus_length);
diff --git a/src/vnet/ip6-nd/ip6_ra.c b/src/vnet/ip6-nd/ip6_ra.c
index 8cd7ab9e905..65b7cf09983 100644
--- a/src/vnet/ip6-nd/ip6_ra.c
+++ b/src/vnet/ip6-nd/ip6_ra.c
@@ -204,6 +204,16 @@ 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));
+}
+
/* for "syslogging" - use elog for now */
#define foreach_log_level \
_ (DEBUG, "DEBUG") \
diff --git a/src/vnet/ip6-nd/ip6_ra.h b/src/vnet/ip6-nd/ip6_ra.h
index d09e8c0c975..c5012477d80 100644
--- a/src/vnet/ip6-nd/ip6_ra.h
+++ b/src/vnet/ip6-nd/ip6_ra.h
@@ -82,7 +82,7 @@ extern void ip6_ra_update_secondary_radv_info (ip6_address_t * address,
u32 primary_sw_if_index,
u32 valid_time,
u32 preferred_time);
-
+extern u8 ip6_ra_adv_enabled (u32 sw_if_index);
#endif /* included_ip6_neighbor_h */
/*