summaryrefslogtreecommitdiffstats
path: root/src/plugins/vrrp/vrrp.c
diff options
context:
space:
mode:
authorMatthew Smith <mgsmith@netgate.com>2020-06-15 10:58:23 -0500
committerDamjan Marion <dmarion@me.com>2020-06-27 10:23:04 +0000
commitd352bf8276f33f33e4af5e8a7b85dad8187f531d (patch)
tree6823fffc02ffcecd5c24a03cd145b6f2d8792c01 /src/plugins/vrrp/vrrp.c
parenta4611b85b58155fc3abbe2a7f16bd98e1a3dc39d (diff)
vrrp: backup processes priority 255 advertisement
Type: fix When accept mode is enabled, a backup VR will configure the VR virtual addresses locally and respond to packets sent to those addresses. This did not work when the primary VR is the address owner and sends advertisements using the virtual address as the source address. It also did not work when NAT was configured on the interface with the virtual address as the NAT pool address. In both cases, advertisements from other VRs would arrive and be dropped because they appeared to be spoofed - the source address would be an address that is configured as an interface address on the instance receiving it. When accept mode is enabled for a VR and the VR enters the master state, add an input feature on ip[46]-multicast for the interface which looks for VRRP advertisements, figures out whether they are for a VR which is configured with accept mode and is in the master state and kicks them straight to the VRRP nodes to avoid dropping them. Change-Id: I240ba1ee0b3fd6d693de729698c1181dc71bb08b Signed-off-by: Matthew Smith <mgsmith@netgate.com>
Diffstat (limited to 'src/plugins/vrrp/vrrp.c')
-rw-r--r--src/plugins/vrrp/vrrp.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/plugins/vrrp/vrrp.c b/src/plugins/vrrp/vrrp.c
index 13cdba6f5e7..564cdb0551f 100644
--- a/src/plugins/vrrp/vrrp.c
+++ b/src/plugins/vrrp/vrrp.c
@@ -140,7 +140,10 @@ vrrp_vr_transition_intf (vrrp_vr_t * vr, vrrp_vr_state_t new_state)
{
vrrp_intf_t *intf;
const char *arc_name = 0, *node_name = 0;
+ const char *mc_arc_name = 0, *mc_node_name = 0;
u8 is_ipv6 = vrrp_vr_is_ipv6 (vr);
+ u32 *vr_index;
+ int n_master_accept = 0;
/* only need to do something if entering or leaving master state */
if ((vr->runtime.state != VRRP_VR_STATE_MASTER) &&
@@ -151,14 +154,19 @@ vrrp_vr_transition_intf (vrrp_vr_t * vr, vrrp_vr_state_t new_state)
{
arc_name = "ip6-local";
node_name = "vrrp6-nd-input";
+ mc_arc_name = "ip6-multicast";
+ mc_node_name = "vrrp6-accept-owner-input";
}
else
{
arc_name = "arp";
node_name = "vrrp4-arp-input";
+ mc_arc_name = "ip4-multicast";
+ mc_node_name = "vrrp4-accept-owner-input";
}
intf = vrrp_intf_get (vr->config.sw_if_index);
+
if (new_state == VRRP_VR_STATE_MASTER)
{
intf->n_master_vrs[is_ipv6]++;
@@ -175,6 +183,30 @@ vrrp_vr_transition_intf (vrrp_vr_t * vr, vrrp_vr_state_t new_state)
if (intf->n_master_vrs[is_ipv6])
intf->n_master_vrs[is_ipv6]--;
}
+
+ /* accept mode enabled, count the other master VRs w/ accept mode on intf */
+ if (vrrp_vr_accept_mode_enabled (vr))
+ {
+ vec_foreach (vr_index, intf->vr_indices[is_ipv6])
+ {
+ vrrp_vr_t *intf_vr = vrrp_vr_lookup_index (*vr_index);
+
+ if (intf_vr == vr)
+ continue;
+
+ if (vrrp_vr_accept_mode_enabled (intf_vr) &&
+ (intf_vr->runtime.state == VRRP_VR_STATE_MASTER))
+ n_master_accept++;
+ }
+
+ /* If no others, enable or disable the feature based on new state */
+ if (!n_master_accept)
+ vnet_feature_enable_disable (mc_arc_name, mc_node_name,
+ vr->config.sw_if_index,
+ (new_state == VRRP_VR_STATE_MASTER),
+ NULL, 0);
+ }
+
}
/* If accept mode enabled, add/remove VR addresses from interface */
@@ -310,7 +342,7 @@ vrrp_vr_transition (vrrp_vr_t * vr, vrrp_vr_state_t new_state, void *data)
/* add/delete virtual IP addrs if accept_mode is true */
vrrp_vr_transition_addrs (vr, new_state);
- /* enable/disable arp/ND input features if necessary */
+ /* enable/disable input features if necessary */
vrrp_vr_transition_intf (vr, new_state);
/* add/delete virtual MAC address on NIC if necessary */