diff options
| -rw-r--r-- | lib/vrf.c | 1 | ||||
| -rw-r--r-- | lib/vrf.h | 25 | ||||
| -rw-r--r-- | pimd/pim_igmp_mtrace.c | 10 | ||||
| -rw-r--r-- | vrrpd/vrrp.c | 55 | ||||
| -rw-r--r-- | vrrpd/vrrp_zebra.c | 4 |
5 files changed, 82 insertions, 13 deletions
@@ -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) { @@ -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); } |
