summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c4
-rw-r--r--lib/vrf.c1
-rw-r--r--lib/vrf.h25
-rw-r--r--pimd/pim_cmd.c147
-rw-r--r--pimd/pim_igmp_mtrace.c10
-rw-r--r--vrrpd/vrrp.c55
-rw-r--r--vrrpd/vrrp_zebra.c4
7 files changed, 113 insertions, 133 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 331c0ece2d..fe7a80ccf2 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -2905,7 +2905,9 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
/* Nexthop AFI */
if (afi == AFI_IP
- && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
+ && (safi == SAFI_UNICAST ||
+ safi == SAFI_LABELED_UNICAST ||
+ safi == SAFI_MULTICAST))
nh_afi = peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : AFI_IP;
else
nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
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_cmd.c b/pimd/pim_cmd.c
index 5c192a9fcd..d165cca086 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -7873,55 +7873,7 @@ DEFUN(interface_no_ip_pim_boundary_oil,
DEFUN (interface_ip_mroute,
interface_ip_mroute_cmd,
- "ip mroute INTERFACE A.B.C.D",
- IP_STR
- "Add multicast route\n"
- "Outgoing interface name\n"
- "Group address\n")
-{
- VTY_DECLVAR_CONTEXT(interface, iif);
- struct pim_interface *pim_ifp;
- struct pim_instance *pim;
- int idx_interface = 2;
- int idx_ipv4 = 3;
- struct interface *oif;
- const char *oifname;
- const char *grp_str;
- struct in_addr grp_addr;
- struct in_addr src_addr;
- int result;
-
- PIM_GET_PIM_INTERFACE(pim_ifp, iif);
- pim = pim_ifp->pim;
-
- oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname, pim->vrf_id);
- if (!oif) {
- vty_out(vty, "No such interface name %s\n", oifname);
- return CMD_WARNING;
- }
-
- grp_str = argv[idx_ipv4]->arg;
- result = inet_pton(AF_INET, grp_str, &grp_addr);
- if (result <= 0) {
- vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
- errno, safe_strerror(errno));
- return CMD_WARNING;
- }
-
- src_addr.s_addr = INADDR_ANY;
-
- if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) {
- vty_out(vty, "Failed to add route\n");
- return CMD_WARNING;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (interface_ip_mroute_source,
- interface_ip_mroute_source_cmd,
- "ip mroute INTERFACE A.B.C.D A.B.C.D",
+ "ip mroute INTERFACE A.B.C.D [A.B.C.D]",
IP_STR
"Add multicast route\n"
"Outgoing interface name\n"
@@ -7933,7 +7885,6 @@ DEFUN (interface_ip_mroute_source,
struct pim_instance *pim;
int idx_interface = 2;
int idx_ipv4 = 3;
- int idx_ipv4_2 = 4;
struct interface *oif;
const char *oifname;
const char *grp_str;
@@ -7960,16 +7911,21 @@ DEFUN (interface_ip_mroute_source,
return CMD_WARNING;
}
- src_str = argv[idx_ipv4_2]->arg;
- result = inet_pton(AF_INET, src_str, &src_addr);
- if (result <= 0) {
- vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
- errno, safe_strerror(errno));
- return CMD_WARNING;
- }
+ if (argc == (idx_ipv4 + 1)) {
+ src_addr.s_addr = INADDR_ANY;
+ }
+ else {
+ src_str = argv[idx_ipv4 + 1]->arg;
+ result = inet_pton(AF_INET, src_str, &src_addr);
+ if (result <= 0) {
+ vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
+ errno, safe_strerror(errno));
+ return CMD_WARNING;
+ }
+ }
if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) {
- vty_out(vty, "Failed to add route\n");
+ vty_out(vty, "Failed to add static mroute\n");
return CMD_WARNING;
}
@@ -7978,56 +7934,7 @@ DEFUN (interface_ip_mroute_source,
DEFUN (interface_no_ip_mroute,
interface_no_ip_mroute_cmd,
- "no ip mroute INTERFACE A.B.C.D",
- NO_STR
- IP_STR
- "Add multicast route\n"
- "Outgoing interface name\n"
- "Group Address\n")
-{
- VTY_DECLVAR_CONTEXT(interface, iif);
- struct pim_interface *pim_ifp;
- struct pim_instance *pim;
- int idx_interface = 3;
- int idx_ipv4 = 4;
- struct interface *oif;
- const char *oifname;
- const char *grp_str;
- struct in_addr grp_addr;
- struct in_addr src_addr;
- int result;
-
- PIM_GET_PIM_INTERFACE(pim_ifp, iif);
- pim = pim_ifp->pim;
-
- oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname, pim->vrf_id);
- if (!oif) {
- vty_out(vty, "No such interface name %s\n", oifname);
- return CMD_WARNING;
- }
-
- grp_str = argv[idx_ipv4]->arg;
- result = inet_pton(AF_INET, grp_str, &grp_addr);
- if (result <= 0) {
- vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
- errno, safe_strerror(errno));
- return CMD_WARNING;
- }
-
- src_addr.s_addr = INADDR_ANY;
-
- if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) {
- vty_out(vty, "Failed to remove route\n");
- return CMD_WARNING;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (interface_no_ip_mroute_source,
- interface_no_ip_mroute_source_cmd,
- "no ip mroute INTERFACE A.B.C.D A.B.C.D",
+ "no ip mroute INTERFACE A.B.C.D [A.B.C.D]",
NO_STR
IP_STR
"Add multicast route\n"
@@ -8040,7 +7947,6 @@ DEFUN (interface_no_ip_mroute_source,
struct pim_instance *pim;
int idx_interface = 3;
int idx_ipv4 = 4;
- int idx_ipv4_2 = 5;
struct interface *oif;
const char *oifname;
const char *grp_str;
@@ -8067,16 +7973,21 @@ DEFUN (interface_no_ip_mroute_source,
return CMD_WARNING;
}
- src_str = argv[idx_ipv4_2]->arg;
- result = inet_pton(AF_INET, src_str, &src_addr);
- if (result <= 0) {
- vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
- errno, safe_strerror(errno));
- return CMD_WARNING;
- }
+ if (argc == (idx_ipv4 + 1)) {
+ src_addr.s_addr = INADDR_ANY;
+ }
+ else {
+ src_str = argv[idx_ipv4 + 1]->arg;
+ result = inet_pton(AF_INET, src_str, &src_addr);
+ if (result <= 0) {
+ vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
+ errno, safe_strerror(errno));
+ return CMD_WARNING;
+ }
+ }
if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) {
- vty_out(vty, "Failed to remove route\n");
+ vty_out(vty, "Failed to remove static mroute\n");
return CMD_WARNING;
}
@@ -10547,9 +10458,7 @@ void pim_cmd_init(void)
// Static mroutes NEB
install_element(INTERFACE_NODE, &interface_ip_mroute_cmd);
- install_element(INTERFACE_NODE, &interface_ip_mroute_source_cmd);
install_element(INTERFACE_NODE, &interface_no_ip_mroute_cmd);
- install_element(INTERFACE_NODE, &interface_no_ip_mroute_source_cmd);
install_element(VIEW_NODE, &show_ip_igmp_interface_cmd);
install_element(VIEW_NODE, &show_ip_igmp_interface_vrf_all_cmd);
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);
}