struct vrrp_defaults vd;
-const char *vrrp_state_names[3] = {
+const char *const vrrp_state_names[3] = {
[VRRP_STATE_INITIALIZE] = "Initialize",
[VRRP_STATE_MASTER] = "Master",
[VRRP_STATE_BACKUP] = "Backup",
};
-const char *vrrp_event_names[2] = {
+static const char *const vrrp_event_names[2] = {
[VRRP_EVENT_STARTUP] = "Startup",
[VRRP_EVENT_SHUTDOWN] = "Shutdown",
};
{
struct interface *p;
- if (!mvl_ifp || !mvl_ifp->link_ifindex
- || !vrrp_ifp_has_vrrp_mac(mvl_ifp))
+ if (!mvl_ifp || mvl_ifp->link_ifindex == 0
+ || !vrrp_ifp_has_vrrp_mac(mvl_ifp)) {
+ if (mvl_ifp && mvl_ifp->link_ifindex == 0)
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX
+ "Interface %s has no parent ifindex; disregarding",
+ mvl_ifp->name);
+ if (mvl_ifp && !vrrp_ifp_has_vrrp_mac(mvl_ifp))
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX
+ "Interface %s has a non-VRRP MAC; disregarding",
+ mvl_ifp->name);
return NULL;
+ }
p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
uint8_t vrid = mvl_ifp->hw_addr[5];
r = vr->v4;
/* Must not already be started */
start = r->fsm.state == VRRP_STATE_INITIALIZE;
+ whynot = (!start && !whynot) ? "Already running" : whynot;
/* Must have a parent interface */
start = start && (vr->ifp != NULL);
- whynot = (!start && !whynot) ? "No base interface" : NULL;
+ whynot = (!start && !whynot) ? "No base interface" : whynot;
#if 0
/* Parent interface must be up */
start = start && if_is_operative(vr->ifp);
+ start = (!start && !whynot) ? "Base interface inoperative" : whynot;
#endif
/* Parent interface must have at least one v4 */
- start = start && vr->ifp->connected->count > 1;
- whynot = (!start && !whynot) ? "No primary IPv4 address" : NULL;
+ start = start && connected_count_by_family(vr->ifp, AF_INET) > 0;
+ whynot = (!start && !whynot) ? "No primary IPv4 address" : whynot;
/* Must have a macvlan interface */
start = start && (r->mvl_ifp != NULL);
- whynot = (!start && !whynot) ? "No VRRP interface" : NULL;
+ whynot = (!start && !whynot) ? "No VRRP interface" : whynot;
#if 0
/* Macvlan interface must be admin up */
start = start && CHECK_FLAG(r->mvl_ifp->flags, IFF_UP);
+ start = (!start && !whynot) ? "Macvlan device admin down" : whynot;
#endif
/* Must have at least one VIP configured */
start = start && r->addrs->count > 0;
- whynot =
- (!start && !whynot) ? "No Virtual IP address configured" : NULL;
+ whynot = (!start && !whynot) ? "No Virtual IP address configured"
+ : whynot;
if (start)
vrrp_event(r, VRRP_EVENT_STARTUP);
else if (whynot)
"Refusing to start Virtual Router: %s",
vr->vrid, family2str(r->family), whynot);
+ whynot = NULL;
+
r = vr->v6;
/* Must not already be started */
start = r->fsm.state == VRRP_STATE_INITIALIZE;
+ whynot = (!start && !whynot) ? "Already running" : whynot;
/* Must not be v2 */
start = start && vr->version != 2;
- whynot = (!start && !whynot) ? "VRRPv2 does not support v6" : NULL;
+ whynot = (!start && !whynot) ? "VRRPv2 does not support v6" : whynot;
/* Must have a parent interface */
start = start && (vr->ifp != NULL);
- whynot = (!start && !whynot) ? "No base interface" : NULL;
+ whynot = (!start && !whynot) ? "No base interface" : whynot;
#if 0
/* Parent interface must be up */
start = start && if_is_operative(vr->ifp);
+ start = (!start && !whynot) ? "Base interface inoperative" : whynot;
#endif
/* Must have a macvlan interface */
start = start && (r->mvl_ifp != NULL);
- whynot = (!start && !whynot) ? "No VRRP interface" : NULL;
+ whynot = (!start && !whynot) ? "No VRRP interface" : whynot;
#if 0
/* Macvlan interface must be admin up */
start = start && CHECK_FLAG(r->mvl_ifp->flags, IFF_UP);
+ start = (!start && !whynot) ? "Macvlan device admin down" : whynot;
/* Macvlan interface must have a link local */
start = start && connected_get_linklocal(r->mvl_ifp);
whynot =
- (!start && !whynot) ? "No link local address configured" : NULL;
+ (!start && !whynot) ? "No link local address configured" : whynot;
/* Macvlan interface must have a v6 IP besides the link local */
- start = start && (r->mvl_ifp->connected->count >= 2);
+ start = start && (connected_count_by_family(r->mvl_ifp, AF_INET6) > 1);
whynot = (!start && !whynot)
- ? "No Virtual IP configured on macvlan device"
- : NULL;
+ ? "No Virtual IPv6 address configured on macvlan device"
+ : whynot;
#endif
/* Must have at least one VIP configured */
start = start && r->addrs->count > 0;
whynot =
- (!start && !whynot) ? "No Virtual IP address configured" : NULL;
+ (!start && !whynot) ? "No Virtual IP address configured" : whynot;
if (start)
vrrp_event(r, VRRP_EVENT_STARTUP);
else if (whynot)
return false;
}
-int vrrp_add_ip(struct vrrp_router *r, struct ipaddr *ip)
+int vrrp_add_ip(struct vrrp_vrouter *vr, struct ipaddr *ip)
{
- int af = (ip->ipa_type == IPADDR_V6) ? AF_INET6 : AF_INET;
+ struct vrrp_router *r = IS_IPADDR_V4(ip) ? vr->v4 : vr->v6;
+ int af = r->family;
assert(r->family == af);
assert(!(r->vr->version == 2 && ip->ipa_type == IPADDR_V6));
ip.ipa_type = IPADDR_V4;
ip.ipaddr_v4 = v4;
- return vrrp_add_ip(vr->v4, &ip);
+ return vrrp_add_ip(vr, &ip);
}
int vrrp_add_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6)
ip.ipa_type = IPADDR_V6;
ip.ipaddr_v6 = v6;
- return vrrp_add_ip(vr->v6, &ip);
+ return vrrp_add_ip(vr, &ip);
}
-int vrrp_del_ip(struct vrrp_router *r, struct ipaddr *ip)
+
+
+int vrrp_del_ip(struct vrrp_vrouter *vr, struct ipaddr *ip)
{
struct listnode *ln, *nn;
struct ipaddr *iter;
int ret = 0;
+ struct vrrp_router *r = IS_IPADDR_V4(ip) ? vr->v4 : vr->v6;
+
if (!vrrp_has_ip(r->vr, ip))
return 0;
ip.ipa_type = IPADDR_V6;
ip.ipaddr_v6 = v6;
- return vrrp_del_ip(vr->v6, &ip);
+ return vrrp_del_ip(vr, &ip);
}
int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4)
ip.ipa_type = IPADDR_V4;
ip.ipaddr_v4 = v4;
- return vrrp_del_ip(vr->v4, &ip);
+ return vrrp_del_ip(vr, &ip);
}
XFREE(MTYPE_VRRP_RTR, vr);
}
-struct vrrp_vrouter *vrrp_lookup(struct interface *ifp, uint8_t vrid)
+struct vrrp_vrouter *vrrp_lookup(const struct interface *ifp, uint8_t vrid)
{
struct vrrp_vrouter vr;
vr.vrid = vrid;
- vr.ifp = ifp;
+ vr.ifp = (struct interface *)ifp;
return hash_lookup(vrrp_vrouters_hash, &vr);
}
THREAD_OFF(r->t_adver_timer);
thread_add_timer_msec(
master, vrrp_adver_timer_expire, r,
- r->vr->advertisement_interval * 10,
+ r->vr->advertisement_interval * CS2MS,
&r->t_adver_timer);
} else if (pkt->hdr.priority > r->priority
|| ((pkt->hdr.priority == r->priority)
THREAD_OFF(r->t_master_down_timer);
thread_add_timer_msec(master,
vrrp_master_down_timer_expire, r,
- r->master_down_interval * 10,
+ r->master_down_interval * CS2MS,
&r->t_master_down_timer);
vrrp_change_state(r, VRRP_STATE_BACKUP);
} else {
THREAD_OFF(r->t_master_down_timer);
thread_add_timer_msec(
master, vrrp_master_down_timer_expire, r,
- r->skew_time * 10, &r->t_master_down_timer);
+ r->skew_time * CS2MS, &r->t_master_down_timer);
} else if (r->vr->preempt_mode == false
|| pkt->hdr.priority >= r->priority) {
if (r->vr->version == 3) {
THREAD_OFF(r->t_master_down_timer);
thread_add_timer_msec(master,
vrrp_master_down_timer_expire, r,
- r->master_down_interval * 10,
+ r->master_down_interval * CS2MS,
&r->t_master_down_timer);
} else if (r->vr->preempt_mode == true
&& pkt->hdr.priority < r->priority) {
int ret;
bool failed = false;
- frr_elevate_privs(&vrrp_privs)
- {
+ frr_with_privs(&vrrp_privs) {
r->sock_rx = socket(r->family, SOCK_RAW, IPPROTO_VRRP);
r->sock_tx = socket(r->family, SOCK_RAW, IPPROTO_VRRP);
}
setsockopt_ipv4_multicast_loop(r->sock_tx, 0);
/* Bind Rx socket to exact interface */
- frr_elevate_privs(&vrrp_privs)
- {
+ frr_with_privs(&vrrp_privs) {
ret = setsockopt(r->sock_rx, SOL_SOCKET,
SO_BINDTODEVICE, r->vr->ifp->name,
strlen(r->vr->ifp->name));
setsockopt_ipv6_multicast_loop(r->sock_tx, 0);
/* Bind Rx socket to exact interface */
- frr_elevate_privs(&vrrp_privs)
- {
+ frr_with_privs(&vrrp_privs) {
ret = setsockopt(r->sock_rx, SOL_SOCKET,
SO_BINDTODEVICE, r->vr->ifp->name,
strlen(r->vr->ifp->name));
r->ndisc_pending = false;
/* Disable ND Router Advertisements */
- if (r->family == AF_INET6)
+ if (r->family == AF_INET6 && r->mvl_ifp)
vrrp_zebra_radv_set(r, false);
}
-void (*vrrp_change_state_handlers[])(struct vrrp_router *vr) = {
+void (*const vrrp_change_state_handlers[])(struct vrrp_router *vr) = {
[VRRP_STATE_MASTER] = vrrp_change_state_master,
[VRRP_STATE_BACKUP] = vrrp_change_state_backup,
[VRRP_STATE_INITIALIZE] = vrrp_change_state_initialize,
/* Reset the Adver_Timer to Advertisement_Interval */
thread_add_timer_msec(master, vrrp_adver_timer_expire, r,
- r->vr->advertisement_interval * 10,
+ r->vr->advertisement_interval * CS2MS,
&r->t_adver_timer);
} else {
zlog_err(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
r->vr->vrid, family2str(r->family));
thread_add_timer_msec(master, vrrp_adver_timer_expire, r,
- r->vr->advertisement_interval * 10,
+ r->vr->advertisement_interval * CS2MS,
&r->t_adver_timer);
vrrp_change_state(r, VRRP_STATE_MASTER);
if (r->priority == VRRP_PRIO_MASTER) {
thread_add_timer_msec(master, vrrp_adver_timer_expire, r,
- r->vr->advertisement_interval * 10,
+ r->vr->advertisement_interval * CS2MS,
&r->t_adver_timer);
vrrp_change_state(r, VRRP_STATE_MASTER);
} else {
r->master_adver_interval = r->vr->advertisement_interval;
vrrp_recalculate_timers(r);
thread_add_timer_msec(master, vrrp_master_down_timer_expire, r,
- r->master_down_interval * 10,
+ r->master_down_interval * CS2MS,
&r->t_master_down_timer);
vrrp_change_state(r, VRRP_STATE_BACKUP);
}
THREAD_OFF(r->t_write);
/* Protodown macvlan */
- vrrp_zclient_send_interface_protodown(r->mvl_ifp, true);
+ if (r->mvl_ifp)
+ vrrp_zclient_send_interface_protodown(r->mvl_ifp, true);
/* Throw away our source address */
memset(&r->src, 0x00, sizeof(r->src));
return 0;
}
-static int (*vrrp_event_handlers[])(struct vrrp_router *r) = {
+static int (*const vrrp_event_handlers[])(struct vrrp_router *r) = {
[VRRP_EVENT_STARTUP] = vrrp_startup,
[VRRP_EVENT_SHUTDOWN] = vrrp_shutdown,
};
{
struct vrrp_vrouter *vr;
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX
+ "Searching for instances that could use interface %s",
+ mvl_ifp->name);
+
vr = vrrp_lookup_by_if_mvl(mvl_ifp);
if (vr) {
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX VRRP_LOGPFX_VRID
+ "<-- This instance can probably use interface %s",
+ vr->vrid, mvl_ifp->name);
+
if (mvl_ifp->hw_addr[4] == 0x01 && !vr->v4->mvl_ifp)
vrrp_attach_interface(vr->v4);
else if (mvl_ifp->hw_addr[4] == 0x02 && !vr->v6->mvl_ifp)
struct listnode *ln;
struct list *vrs;
+ vrrp_bind_pending(ifp);
+
vrs = vrrp_lookup_by_if_any(ifp);
for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) {
+ vrrp_check_start(vr);
+
if (vr->ifp == ifp || vr->v4->mvl_ifp == ifp
|| vr->v6->mvl_ifp == ifp) {
DEBUGD(&vrrp_dbg_auto,