diff options
author | Matthew Smith <mgsmith@netgate.com> | 2020-06-15 10:58:23 -0500 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2020-06-27 10:23:04 +0000 |
commit | d352bf8276f33f33e4af5e8a7b85dad8187f531d (patch) | |
tree | 6823fffc02ffcecd5c24a03cd145b6f2d8792c01 /src/plugins/vrrp/vrrp.c | |
parent | a4611b85b58155fc3abbe2a7f16bd98e1a3dc39d (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.c | 34 |
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 */ |