summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/vrf.c1
-rw-r--r--lib/vrf.h25
-rw-r--r--pimd/pim_igmp_mtrace.c10
-rw-r--r--vrrpd/vrrp.c55
-rw-r--r--vrrpd/vrrp_zebra.c4
5 files changed, 82 insertions, 13 deletions
diff --git a/lib/vrf.c b/lib/vrf.c
index 6ca6482e08..c3a94224ee 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -555,7 +555,6 @@ void vrf_terminate(void)
}
}
-/* Create a socket for the VRF. */
int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
const char *interfacename)
{
diff --git a/lib/vrf.h b/lib/vrf.h
index ca253e58a3..1d87576f78 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -218,13 +218,36 @@ extern void vrf_terminate(void);
* or call network operations
*/
-/* Create a socket serving for the given VRF */
+/*
+ * Create a new socket associated with a VRF.
+ *
+ * This is a wrapper that ensures correct behavior when using namespace VRFs.
+ * In the namespace case, the socket is created within the namespace. In the
+ * non-namespace case, this is equivalent to socket().
+ *
+ * If name is provided, this is provided to vrf_bind() to bind the socket to
+ * the VRF. This is only relevant when using VRF-lite.
+ *
+ * Summary:
+ * - Namespace: pass vrf_id but not name
+ * - VRF-lite: pass vrf_id and name of VRF device to bind to
+ * - VRF-lite, no binding: pass vrf_id but not name, or just use socket()
+ */
extern int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
const char *name);
extern int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
const char *name);
+/*
+ * Binds a socket to a VRF device.
+ *
+ * If name is null, the socket is not bound, irrespective of any other
+ * arguments.
+ *
+ * name should be the name of the VRF device. vrf_id should be the
+ * corresponding vrf_id (the ifindex of the device).
+ */
extern int vrf_bind(vrf_id_t vrf_id, int fd, const char *name);
/* VRF ioctl operations */
diff --git a/pimd/pim_igmp_mtrace.c b/pimd/pim_igmp_mtrace.c
index 0758e2f784..695d04c7c2 100644
--- a/pimd/pim_igmp_mtrace.c
+++ b/pimd/pim_igmp_mtrace.c
@@ -864,6 +864,16 @@ int igmp_mtrace_recv_response(struct igmp_sock *igmp, struct ip *ip_hdr,
pim_ifp = ifp->info;
pim = pim_ifp->pim;
+ if (igmp_msg_len < (int)sizeof(struct igmp_mtrace)) {
+ if (PIM_DEBUG_MTRACE)
+ zlog_warn(
+ "Recv mtrace packet from %s on %s: too short,"
+ " len=%d, min=%zu",
+ from_str, ifp->name, igmp_msg_len,
+ sizeof(struct igmp_mtrace));
+ return -1;
+ }
+
mtracep = (struct igmp_mtrace *)igmp_msg;
recv_checksum = mtracep->checksum;
diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c
index 42bb154f98..2acf985893 100644
--- a/vrrpd/vrrp.c
+++ b/vrrpd/vrrp.c
@@ -211,7 +211,16 @@ static struct vrrp_vrouter *vrrp_lookup_by_if_mvl(struct interface *mvl_ifp)
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);
@@ -525,8 +534,9 @@ static bool vrrp_attach_interface(struct vrrp_router *r)
/* 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
@@ -1048,6 +1058,8 @@ done:
*
* 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
@@ -1074,8 +1086,10 @@ static int vrrp_socket(struct vrrp_router *r)
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) {
@@ -1088,6 +1102,27 @@ static int vrrp_socket(struct vrrp_router *r)
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 */
@@ -1722,7 +1757,7 @@ vrrp_autoconfig_autocreate(struct interface *mvl_ifp)
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;
@@ -1999,11 +2034,13 @@ int vrrp_autoconfig(void)
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;
}
diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c
index a6c575f8da..000672a080 100644
--- a/vrrpd/vrrp_zebra.c
+++ b/vrrpd/vrrp_zebra.c
@@ -175,7 +175,7 @@ void vrrp_zebra_radv_set(struct vrrp_router *r, bool enable)
"Requesting Zebra to turn router advertisements %s for %s",
r->vr->vrid, enable ? "on" : "off", r->mvl_ifp->name);
- zclient_send_interface_radv_req(zclient, VRF_DEFAULT, r->mvl_ifp,
+ zclient_send_interface_radv_req(zclient, r->mvl_ifp->vrf_id, r->mvl_ifp,
enable, VRRP_RADV_INT);
}
@@ -185,7 +185,7 @@ int vrrp_zclient_send_interface_protodown(struct interface *ifp, bool down)
VRRP_LOGPFX "Requesting Zebra to set %s protodown %s", ifp->name,
down ? "on" : "off");
- return zclient_send_interface_protodown(zclient, VRF_DEFAULT, ifp,
+ return zclient_send_interface_protodown(zclient, ifp->vrf_id, ifp,
down);
}