vrrp: set up multicast for both address families 08/28908/4
authorMatthew Smith <mgsmith@netgate.com>
Wed, 16 Sep 2020 21:41:26 +0000 (16:41 -0500)
committerMatthew Smith <mgsmith@netgate.com>
Mon, 21 Sep 2020 15:12:49 +0000 (15:12 +0000)
Type: fix

When a VR is added, multicast accept routes are added which allow
inbound packets sent to the VRRP group address on the interface of the
VR so advertisements from peers can be received. If this is the first
VR added, also add a local forward route for the VRRP group address so
the packets will be processed by the VRRP input nodes.

When deciding whether to add/delete the local forward route, the total
number of VRs configured was being checked. If there are no VRs
configured initially and a VR is added for IPv4, this check would
correctly see that this was the first VR and add an IPv4 route. If an
IPv6 VR was configured subsequently, this check would find that a VR
was already configured and incorrectly decide that no route needed to
be added and IPv6 VRRP advertisements from peers would be dropped
as a result. The opposite would occur if you first added an IPv6 VR
followed by adding an IPv4 VR - whichever address family was added
first would work correctly and the other one would not work.

Since a route is needed for each address family, check on the per
address family count of VRs when deciding whether to add/delete the
local forward route instead of checking on the global count of VRs.

Change-Id: I851a7ef8a4f9e4e370d08b0832284a13387eb083
Signed-off-by: Matthew Smith <mgsmith@netgate.com>
src/plugins/vrrp/vrrp.c

index eb988d3..37ee9ec 100644 (file)
@@ -382,8 +382,10 @@ static int
 vrrp_intf_enable_disable_mcast (u8 enable, u32 sw_if_index, u8 is_ipv6)
 {
   vrrp_main_t *vrm = &vrrp_main;
+  vrrp_vr_t *vr;
   vrrp_intf_t *intf;
   u32 fib_index;
+  u32 n_vrs = 0;
   const mfib_prefix_t *vrrp_prefix;
   fib_protocol_t proto;
   vnet_link_t link_type;
@@ -418,9 +420,18 @@ vrrp_intf_enable_disable_mcast (u8 enable, u32 sw_if_index, u8 is_ipv6)
   via_itf.frp_proto = fib_proto_to_dpo (proto);
   fib_index = mfib_table_get_index_for_sw_if_index (proto, sw_if_index);
 
+  /* *INDENT-OFF* */
+  pool_foreach (vr, vrm->vrs,
+  ({
+    if (vrrp_vr_is_ipv6 (vr) == is_ipv6)
+      n_vrs++;
+  }));
+  /* *INDENT-ON* */
+
   if (enable)
     {
-      if (pool_elts (vrm->vrs) == 1)
+      /* If this is the first VR configured, add the local mcast routes */
+      if (n_vrs == 1)
        mfib_table_entry_path_update (fib_index, vrrp_prefix, MFIB_SOURCE_API,
                                      &for_us);
 
@@ -431,7 +442,8 @@ vrrp_intf_enable_disable_mcast (u8 enable, u32 sw_if_index, u8 is_ipv6)
     }
   else
     {
-      if (pool_elts (vrm->vrs) == 0)
+      /* Remove mcast local routes if this is the last VR being deleted */
+      if (n_vrs == 0)
        mfib_table_entry_path_remove (fib_index, vrrp_prefix, MFIB_SOURCE_API,
                                      &for_us);