return NULL;
}
- p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
+ p = if_lookup_by_index(mvl_ifp->link_ifindex, mvl_ifp->vrf_id);
+
+ if (!p) {
+ DEBUGD(&vrrp_dbg_zebra,
+ VRRP_LOGPFX
+ "Tried to lookup interface %d, parent of %s, but it doesn't exist",
+ mvl_ifp->link_ifindex, mvl_ifp->name);
+ return NULL;
+ }
+
uint8_t vrid = mvl_ifp->hw_addr[5];
return vrrp_lookup(p, vrid);
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);
}
/* Search for existing interface with computed MAC address */
struct interface **ifps;
- size_t ifps_cnt = if_lookup_by_hwaddr(
- r->vmac.octet, sizeof(r->vmac.octet), &ifps, VRF_DEFAULT);
+ size_t ifps_cnt =
+ if_lookup_by_hwaddr(r->vmac.octet, sizeof(r->vmac.octet), &ifps,
+ r->vr->ifp->vrf_id);
/*
* Filter to only those macvlan interfaces whose parent is the base
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);
}
*
* This function:
* - Creates two sockets, one for Tx, one for Rx
+ * - Binds the Tx socket to the macvlan device, if necessary (VRF case)
+ * - Binds the Rx socket to the base interface
* - Joins the Rx socket to the appropriate VRRP multicast group
* - Sets the Tx socket to set the TTL (v4) or Hop Limit (v6) field to 255 for
* all transmitted IPvX packets
bool failed = false;
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);
+ r->sock_rx = vrf_socket(r->family, SOCK_RAW, IPPROTO_VRRP,
+ r->vr->ifp->vrf_id, NULL);
+ r->sock_tx = vrf_socket(r->family, SOCK_RAW, IPPROTO_VRRP,
+ r->vr->ifp->vrf_id, NULL);
}
if (r->sock_rx < 0 || r->sock_tx < 0) {
goto done;
}
+ /*
+ * Bind Tx socket to macvlan device - necessary for VRF support,
+ * otherwise the kernel will select the vrf device
+ */
+ if (r->vr->ifp->vrf_id != VRF_DEFAULT) {
+ frr_with_privs (&vrrp_privs) {
+ ret = setsockopt(r->sock_tx, SOL_SOCKET,
+ SO_BINDTODEVICE, r->mvl_ifp->name,
+ strlen(r->mvl_ifp->name));
+ }
+
+ if (ret < 0) {
+ zlog_warn(
+ VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
+ "Failed to bind Tx socket to macvlan device '%s'",
+ r->vr->vrid, family2str(r->family),
+ r->mvl_ifp->name);
+ failed = true;
+ goto done;
+ }
+ }
/* Configure sockets */
if (r->family == AF_INET) {
/* Set Tx socket to always Tx with TTL set to 255 */
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);
}
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));
struct interface *p;
struct vrrp_vrouter *vr;
- p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT);
+ p = if_lookup_by_index(mvl_ifp->link_ifindex, mvl_ifp->vrf_id);
if (!p)
return NULL;
if (!vrrp_autoconfig_is_on)
return 0;
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct vrf *vrf;
struct interface *ifp;
- FOR_ALL_INTERFACES (vrf, ifp)
- vrrp_autoconfig_if_add(ifp);
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ FOR_ALL_INTERFACES (vrf, ifp)
+ vrrp_autoconfig_if_add(ifp);
+ }
return 0;
}
/* Other ------------------------------------------------------------------- */
-int vrrp_config_write_interface(struct vty *vty)
-{
- struct list *vrs = hash_to_list(vrrp_vrouters_hash);
- struct listnode *ln, *ipln;
- struct vrrp_vrouter *vr;
- int writes = 0;
-
- for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) {
- vty_frame(vty, "interface %s\n", vr->ifp->name);
- ++writes;
-
- vty_out(vty, " vrrp %" PRIu8 "%s\n", vr->vrid,
- vr->version == 2 ? " version 2" : "");
- ++writes;
-
- if (vr->shutdown != vd.shutdown && ++writes)
- vty_out(vty, " %svrrp %" PRIu8 " shutdown\n",
- vr->shutdown ? "" : "no ", vr->vrid);
-
- if (vr->preempt_mode != vd.preempt_mode && ++writes)
- vty_out(vty, " %svrrp %" PRIu8 " preempt\n",
- vr->preempt_mode ? "" : "no ", vr->vrid);
-
- if (vr->accept_mode != vd.accept_mode && ++writes)
- vty_out(vty, " %svrrp %" PRIu8 " accept\n",
- vr->accept_mode ? "" : "no ", vr->vrid);
-
- if (vr->advertisement_interval != vd.advertisement_interval
- && ++writes)
- vty_out(vty,
- " vrrp %" PRIu8
- " advertisement-interval %d\n",
- vr->vrid, vr->advertisement_interval * CS2MS);
-
- if (vr->priority != vd.priority && ++writes)
- vty_out(vty, " vrrp %" PRIu8 " priority %" PRIu8 "\n",
- vr->vrid, vr->priority);
-
- struct ipaddr *ip;
-
- for (ALL_LIST_ELEMENTS_RO(vr->v4->addrs, ipln, ip)) {
- char ipbuf[INET6_ADDRSTRLEN];
-
- ipaddr2str(ip, ipbuf, sizeof(ipbuf));
- vty_out(vty, " vrrp %" PRIu8 " ip %s\n", vr->vrid,
- ipbuf);
- ++writes;
- }
-
- for (ALL_LIST_ELEMENTS_RO(vr->v6->addrs, ipln, ip)) {
- char ipbuf[INET6_ADDRSTRLEN];
-
- ipaddr2str(ip, ipbuf, sizeof(ipbuf));
- vty_out(vty, " vrrp %" PRIu8 " ipv6 %s\n", vr->vrid,
- ipbuf);
- ++writes;
- }
- vty_endframe(vty, "!\n");
- }
-
- list_delete(&vrs);
-
- return writes;
-}
-
int vrrp_config_write_global(struct vty *vty)
{
unsigned int writes = 0;
vty_out(vty, "vrrp autoconfigure%s\n",
vrrp_autoconfig_version == 2 ? " version 2" : "");
+ /* FIXME: needs to be udpated for full YANG conversion. */
if (vd.priority != VRRP_DEFAULT_PRIORITY && ++writes)
vty_out(vty, "vrrp default priority %" PRIu8 "\n", vd.priority);
void vrrp_init(void)
{
/* Set default defaults */
- vd.priority = VRRP_DEFAULT_PRIORITY;
- vd.advertisement_interval = VRRP_DEFAULT_ADVINT;
- vd.preempt_mode = VRRP_DEFAULT_PREEMPT;
- vd.accept_mode = VRRP_DEFAULT_ACCEPT;
+ vd.version = yang_get_default_uint8("%s/version", VRRP_XPATH_FULL);
+ vd.priority = yang_get_default_uint8("%s/priority", VRRP_XPATH_FULL);
+ vd.advertisement_interval = yang_get_default_uint16(
+ "%s/advertisement-interval", VRRP_XPATH_FULL);
+ vd.preempt_mode = yang_get_default_bool("%s/preempt", VRRP_XPATH_FULL);
+ vd.accept_mode =
+ yang_get_default_bool("%s/accept-mode", VRRP_XPATH_FULL);
vd.shutdown = VRRP_DEFAULT_SHUTDOWN;
vrrp_autoconfig_version = 3;