summaryrefslogtreecommitdiff
path: root/zebra/rt_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r--zebra/rt_netlink.c568
1 files changed, 273 insertions, 295 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index e40bf45f59..b6224b3da9 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -718,14 +718,15 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
if (IS_ZEBRA_DEBUG_KERNEL) {
char buf[PREFIX_STRLEN];
char buf2[PREFIX_STRLEN];
- zlog_debug("%s %s%s%s vrf %u(%u) metric: %d Admin Distance: %d",
- nl_msg_type_to_str(h->nlmsg_type),
- prefix2str(&p, buf, sizeof(buf)),
- src_p.prefixlen ? " from " : "",
- src_p.prefixlen
- ? prefix2str(&src_p, buf2, sizeof(buf2))
- : "",
- vrf_id, table, metric, distance);
+ zlog_debug(
+ "%s %s%s%s vrf %s(%u) table_id: %u metric: %d Admin Distance: %d",
+ nl_msg_type_to_str(h->nlmsg_type),
+ prefix2str(&p, buf, sizeof(buf)),
+ src_p.prefixlen ? " from " : "",
+ src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2))
+ : "",
+ vrf_id_to_name(vrf_id), vrf_id, table, metric,
+ distance);
}
afi_t afi = AFI_IP;
@@ -911,9 +912,8 @@ static int netlink_route_change_read_multicast(struct nlmsghdr *h,
ifp = if_lookup_by_index(iif, vrf);
zlog_debug(
"MCAST VRF: %s(%d) %s (%s,%s) IIF: %s(%d) OIF: %s jiffies: %lld",
- (zvrf ? zvrf->vrf->name : "Unknown"), vrf,
- nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf,
- ifp ? ifp->name : "Unknown", iif, oif_list,
+ zvrf_name(zvrf), vrf, nl_msg_type_to_str(h->nlmsg_type),
+ sbuf, gbuf, ifp ? ifp->name : "Unknown", iif, oif_list,
m->lastused);
}
return 0;
@@ -1111,7 +1111,8 @@ static int build_label_stack(struct mpls_label_stack *nh_label,
* @param nlmsg: nlmsghdr structure to fill in.
* @param req_size: The size allocated for the message.
*/
-static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
+static void _netlink_route_build_singlepath(const struct prefix *p,
+ const char *routedesc, int bytelen,
const struct nexthop *nexthop,
struct nlmsghdr *nlmsg,
struct rtmsg *rtmsg,
@@ -1121,9 +1122,12 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
mpls_lse_t out_lse[MPLS_MAX_LABELS];
char label_buf[256];
int num_labels = 0;
+ struct vrf *vrf;
assert(nexthop);
+ vrf = vrf_lookup_by_id(nexthop->vrf_id);
+
/*
* label_buf is *only* currently used within debugging.
* As such when we assign it we are guarding it inside
@@ -1176,10 +1180,10 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- " 5549: _netlink_route_build_singlepath() (%s): "
- "nexthop via %s %s if %u(%u)",
- routedesc, ipv4_ll_buf, label_buf,
- nexthop->ifindex, nexthop->vrf_id);
+ " 5549: _netlink_route_build_singlepath() (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
+ routedesc, p, ipv4_ll_buf, label_buf,
+ nexthop->ifindex, VRF_LOGNAME(vrf),
+ nexthop->vrf_id);
return;
}
@@ -1202,10 +1206,10 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u(%u)",
- routedesc, inet_ntoa(nexthop->gate.ipv4),
- label_buf, nexthop->ifindex, nexthop->vrf_id);
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
+ routedesc, p, inet_ntoa(nexthop->gate.ipv4),
+ label_buf, nexthop->ifindex, VRF_LOGNAME(vrf),
+ nexthop->vrf_id);
}
if (nexthop->type == NEXTHOP_TYPE_IPV6
@@ -1225,10 +1229,10 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u(%u)",
- routedesc, inet6_ntoa(nexthop->gate.ipv6),
- label_buf, nexthop->ifindex, nexthop->vrf_id);
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
+ routedesc, p, inet6_ntoa(nexthop->gate.ipv6),
+ label_buf, nexthop->ifindex, VRF_LOGNAME(vrf),
+ nexthop->vrf_id);
}
/*
@@ -1251,9 +1255,9 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via if %u(%u)",
- routedesc, nexthop->ifindex, nexthop->vrf_id);
+ "netlink_route_multipath() (%s): %pFX nexthop via if %u vrf %s(%u)",
+ routedesc, p, nexthop->ifindex,
+ VRF_LOGNAME(vrf), nexthop->vrf_id);
}
}
@@ -1273,16 +1277,16 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
* @param src: pointer pointing to a location where
* the prefsrc should be stored.
*/
-static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
- const struct nexthop *nexthop,
- struct rtattr *rta,
- struct rtnexthop *rtnh,
- struct rtmsg *rtmsg,
- const union g_addr **src)
+static void
+_netlink_route_build_multipath(const struct prefix *p, const char *routedesc,
+ int bytelen, const struct nexthop *nexthop,
+ struct rtattr *rta, struct rtnexthop *rtnh,
+ struct rtmsg *rtmsg, const union g_addr **src)
{
mpls_lse_t out_lse[MPLS_MAX_LABELS];
char label_buf[256];
int num_labels = 0;
+ struct vrf *vrf;
rtnh->rtnh_len = sizeof(*rtnh);
rtnh->rtnh_flags = 0;
@@ -1291,6 +1295,8 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
assert(nexthop);
+ vrf = vrf_lookup_by_id(nexthop->vrf_id);
+
/*
* label_buf is *only* currently used within debugging.
* As such when we assign it we are guarding it inside
@@ -1340,6 +1346,8 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
bytelen);
rtnh->rtnh_len += sizeof(struct rtattr) + bytelen;
rtnh->rtnh_ifindex = nexthop->ifindex;
+ if (nexthop->weight)
+ rtnh->rtnh_hops = nexthop->weight - 1;
if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY)
*src = &nexthop->rmap_src;
@@ -1348,10 +1356,10 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- " 5549: netlink_route_build_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc, ipv4_ll_buf, label_buf,
- nexthop->ifindex);
+ " 5549: netlink_route_build_multipath() (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
+ routedesc, p, ipv4_ll_buf, label_buf,
+ nexthop->ifindex, VRF_LOGNAME(vrf),
+ nexthop->vrf_id);
return;
}
@@ -1367,10 +1375,10 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc, inet_ntoa(nexthop->gate.ipv4),
- label_buf, nexthop->ifindex);
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
+ routedesc, p, inet_ntoa(nexthop->gate.ipv4),
+ label_buf, nexthop->ifindex, VRF_LOGNAME(vrf),
+ nexthop->vrf_id);
}
if (nexthop->type == NEXTHOP_TYPE_IPV6
|| nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
@@ -1385,10 +1393,10 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via %s %s if %u",
- routedesc, inet6_ntoa(nexthop->gate.ipv6),
- label_buf, nexthop->ifindex);
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u vrf %s(%u)",
+ routedesc, p, inet6_ntoa(nexthop->gate.ipv6),
+ label_buf, nexthop->ifindex, VRF_LOGNAME(vrf),
+ nexthop->vrf_id);
}
/*
@@ -1408,16 +1416,17 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "netlink_route_multipath() (%s): "
- "nexthop via if %u",
- routedesc, nexthop->ifindex);
+ "netlink_route_multipath() (%s): %pFX nexthop via if %u vrf %s(%u)",
+ routedesc, p, nexthop->ifindex,
+ VRF_LOGNAME(vrf), nexthop->vrf_id);
}
if (nexthop->weight)
rtnh->rtnh_hops = nexthop->weight - 1;
}
-static inline void _netlink_mpls_build_singlepath(const char *routedesc,
+static inline void _netlink_mpls_build_singlepath(const struct prefix *p,
+ const char *routedesc,
const zebra_nhlfe_t *nhlfe,
struct nlmsghdr *nlmsg,
struct rtmsg *rtmsg,
@@ -1428,23 +1437,24 @@ static inline void _netlink_mpls_build_singlepath(const char *routedesc,
family = NHLFE_FAMILY(nhlfe);
bytelen = (family == AF_INET ? 4 : 16);
- _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop,
+ _netlink_route_build_singlepath(p, routedesc, bytelen, nhlfe->nexthop,
nlmsg, rtmsg, req_size, cmd);
}
static inline void
-_netlink_mpls_build_multipath(const char *routedesc, const zebra_nhlfe_t *nhlfe,
- struct rtattr *rta, struct rtnexthop *rtnh,
- struct rtmsg *rtmsg, const union g_addr **src)
+_netlink_mpls_build_multipath(const struct prefix *p, const char *routedesc,
+ const zebra_nhlfe_t *nhlfe, struct rtattr *rta,
+ struct rtnexthop *rtnh, struct rtmsg *rtmsg,
+ const union g_addr **src)
{
int bytelen;
uint8_t family;
family = NHLFE_FAMILY(nhlfe);
bytelen = (family == AF_INET ? 4 : 16);
- _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, rta,
- rtnh, rtmsg, src);
+ _netlink_route_build_multipath(p, routedesc, bytelen, nhlfe->nexthop,
+ rta, rtnh, rtmsg, src);
}
@@ -1464,9 +1474,9 @@ static void _netlink_route_debug(int cmd, const struct prefix *p,
if (IS_ZEBRA_DEBUG_KERNEL) {
char buf[PREFIX_STRLEN];
zlog_debug(
- "netlink_route_multipath(): %s %s vrf %u(%u)",
+ "netlink_route_multipath(): %s %s vrf %s(%u) table_id: %u",
nl_msg_type_to_str(cmd),
- prefix2str(p, buf, sizeof(buf)),
+ prefix2str(p, buf, sizeof(buf)), vrf_id_to_name(vrfid),
vrfid, tableid);
}
}
@@ -1518,6 +1528,30 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
0);
}
+static bool nexthop_set_src(const struct nexthop *nexthop, int family,
+ union g_addr *src)
+{
+ if (family == AF_INET) {
+ if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY) {
+ src->ipv4 = nexthop->rmap_src.ipv4;
+ return true;
+ } else if (nexthop->src.ipv4.s_addr != INADDR_ANY) {
+ src->ipv4 = nexthop->src.ipv4;
+ return true;
+ }
+ } else if (family == AF_INET6) {
+ if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) {
+ src->ipv6 = nexthop->rmap_src.ipv6;
+ return true;
+ } else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) {
+ src->ipv6 = nexthop->src.ipv6;
+ return true;
+ }
+ }
+
+ return false;
+}
+
/*
* Routing table change via netlink interface, using a dataplane context object
*/
@@ -1528,7 +1562,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
unsigned int nexthop_num;
int family;
const char *routedesc;
- int setsrc = 0;
+ bool setsrc = false;
union g_addr src;
const struct prefix *p, *src_p;
uint32_t table_id;
@@ -1645,8 +1679,29 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
if (kernel_nexthops_supported()) {
/* Kernel supports nexthop objects */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "netlink_route_multipath(): %pFX nhg_id is %u",
+ p, dplane_ctx_get_nhe_id(ctx));
addattr32(&req.n, sizeof(req), RTA_NH_ID,
dplane_ctx_get_nhe_id(ctx));
+
+ /* Have to determine src still */
+ for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
+ if (setsrc)
+ break;
+
+ setsrc = nexthop_set_src(nexthop, family, &src);
+ }
+
+ if (setsrc) {
+ if (family == AF_INET)
+ addattr_l(&req.n, sizeof(req), RTA_PREFSRC,
+ &src.ipv4, bytelen);
+ else if (family == AF_INET6)
+ addattr_l(&req.n, sizeof(req), RTA_PREFSRC,
+ &src.ipv6, bytelen);
+ }
goto skip;
}
@@ -1694,32 +1749,8 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
if (setsrc)
continue;
- if (family == AF_INET) {
- if (nexthop->rmap_src.ipv4.s_addr
- != 0) {
- src.ipv4 =
- nexthop->rmap_src.ipv4;
- setsrc = 1;
- } else if (nexthop->src.ipv4.s_addr
- != 0) {
- src.ipv4 =
- nexthop->src.ipv4;
- setsrc = 1;
- }
- } else if (family == AF_INET6) {
- if (!IN6_IS_ADDR_UNSPECIFIED(
- &nexthop->rmap_src.ipv6)) {
- src.ipv6 =
- nexthop->rmap_src.ipv6;
- setsrc = 1;
- } else if (
- !IN6_IS_ADDR_UNSPECIFIED(
- &nexthop->src.ipv6)) {
- src.ipv6 =
- nexthop->src.ipv6;
- setsrc = 1;
- }
- }
+ setsrc = nexthop_set_src(nexthop, family, &src);
+
continue;
}
@@ -1730,13 +1761,13 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
: "single-path";
_netlink_route_build_singlepath(
- routedesc, bytelen, nexthop, &req.n,
+ p, routedesc, bytelen, nexthop, &req.n,
&req.r, sizeof(req), cmd);
nexthop_num++;
break;
}
}
- if (setsrc && (cmd == RTM_NEWROUTE)) {
+ if (setsrc) {
if (family == AF_INET)
addattr_l(&req.n, sizeof(req), RTA_PREFSRC,
&src.ipv4, bytelen);
@@ -1762,32 +1793,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
if (setsrc)
continue;
- if (family == AF_INET) {
- if (nexthop->rmap_src.ipv4.s_addr
- != 0) {
- src.ipv4 =
- nexthop->rmap_src.ipv4;
- setsrc = 1;
- } else if (nexthop->src.ipv4.s_addr
- != 0) {
- src.ipv4 =
- nexthop->src.ipv4;
- setsrc = 1;
- }
- } else if (family == AF_INET6) {
- if (!IN6_IS_ADDR_UNSPECIFIED(
- &nexthop->rmap_src.ipv6)) {
- src.ipv6 =
- nexthop->rmap_src.ipv6;
- setsrc = 1;
- } else if (
- !IN6_IS_ADDR_UNSPECIFIED(
- &nexthop->src.ipv6)) {
- src.ipv6 =
- nexthop->src.ipv6;
- setsrc = 1;
- }
- }
+ setsrc = nexthop_set_src(nexthop, family, &src);
continue;
}
@@ -1800,8 +1806,8 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
nexthop_num++;
_netlink_route_build_multipath(
- routedesc, bytelen, nexthop, rta, rtnh,
- &req.r, &src1);
+ p, routedesc, bytelen, nexthop, rta,
+ rtnh, &req.r, &src1);
rtnh = RTNH_NEXT(rtnh);
if (!setsrc && src1) {
@@ -1814,7 +1820,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
}
}
}
- if (setsrc && (cmd == RTM_NEWROUTE)) {
+ if (setsrc) {
if (family == AF_INET)
addattr_l(&req.n, sizeof(req), RTA_PREFSRC,
&src.ipv4, bytelen);
@@ -1989,6 +1995,12 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx)
addattr32(&req.n, req_size, NHA_ID, id);
if (cmd == RTM_NEWNEXTHOP) {
+ /*
+ * We distinguish between a "group", which is a collection
+ * of ids, and a singleton nexthop with an id. The
+ * group is installed as an id that just refers to a list of
+ * other ids.
+ */
if (dplane_ctx_get_nhe_nh_grp_count(ctx))
_netlink_nexthop_build_group(
&req.n, req_size, id,
@@ -2075,14 +2087,13 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx)
}
}
- nexthop_done:
- if (IS_ZEBRA_DEBUG_KERNEL) {
- char buf[NEXTHOP_STRLEN];
+nexthop_done:
- snprintfrr(buf, sizeof(buf), "%pNHv", nh);
- zlog_debug("%s: ID (%u): %s (%u) %s ", __func__,
- id, buf, nh->vrf_id, label_buf);
- }
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: ID (%u): %pNHv vrf %s(%u) %s ",
+ __func__, id, nh,
+ vrf_id_to_name(nh->vrf_id),
+ nh->vrf_id, label_buf);
}
req.nhm.nh_protocol = zebra2proto(dplane_ctx_get_nhe_type(ctx));
@@ -2110,43 +2121,19 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx)
*/
enum zebra_dplane_result kernel_nexthop_update(struct zebra_dplane_ctx *ctx)
{
+ enum dplane_op_e op;
int cmd = 0;
int ret = 0;
- switch (dplane_ctx_get_op(ctx)) {
- case DPLANE_OP_NH_DELETE:
- cmd = RTM_DELNEXTHOP;
- break;
- case DPLANE_OP_NH_INSTALL:
- case DPLANE_OP_NH_UPDATE:
+ op = dplane_ctx_get_op(ctx);
+ if (op == DPLANE_OP_NH_INSTALL || op == DPLANE_OP_NH_UPDATE)
cmd = RTM_NEWNEXTHOP;
- break;
- case DPLANE_OP_ROUTE_INSTALL:
- case DPLANE_OP_ROUTE_UPDATE:
- case DPLANE_OP_ROUTE_DELETE:
- case DPLANE_OP_ROUTE_NOTIFY:
- case DPLANE_OP_LSP_INSTALL:
- case DPLANE_OP_LSP_UPDATE:
- case DPLANE_OP_LSP_DELETE:
- case DPLANE_OP_LSP_NOTIFY:
- case DPLANE_OP_PW_INSTALL:
- case DPLANE_OP_PW_UNINSTALL:
- case DPLANE_OP_SYS_ROUTE_ADD:
- case DPLANE_OP_SYS_ROUTE_DELETE:
- case DPLANE_OP_ADDR_INSTALL:
- case DPLANE_OP_ADDR_UNINSTALL:
- case DPLANE_OP_MAC_INSTALL:
- case DPLANE_OP_MAC_DELETE:
- case DPLANE_OP_NEIGH_INSTALL:
- case DPLANE_OP_NEIGH_UPDATE:
- case DPLANE_OP_NEIGH_DELETE:
- case DPLANE_OP_VTEP_ADD:
- case DPLANE_OP_VTEP_DELETE:
- case DPLANE_OP_NONE:
- flog_err(
- EC_ZEBRA_NHG_FIB_UPDATE,
- "Context received for kernel nexthop update with incorrect OP code (%u)",
- dplane_ctx_get_op(ctx));
+ else if (op == DPLANE_OP_NH_DELETE)
+ cmd = RTM_DELNEXTHOP;
+ else {
+ flog_err(EC_ZEBRA_NHG_FIB_UPDATE,
+ "Context received for kernel nexthop update with incorrect OP code (%u)",
+ op);
return ZEBRA_DPLANE_REQUEST_FAILURE;
}
@@ -2535,12 +2522,28 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
addr, lla, llalen, ns_id);
}
-/*
- * Add remote VTEP to the flood list for this VxLAN interface (VNI). This
- * is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
+/**
+ * netlink_update_neigh_ctx_internal() - Common helper api for evpn
+ * neighbor updates using dataplane context object.
+ * @ctx: Dataplane context
+ * @cmd: Netlink command (RTM_NEWNEIGH or RTM_DELNEIGH)
+ * @mac: A neighbor cache link layer address
+ * @ip: A neighbor cache n/w layer destination address
+ * @replace_obj: Whether NEW request should replace existing object or
+ * add to the end of the list
+ * @family: AF_* netlink family
+ * @type: RTN_* route type
+ * @flags: NTF_* flags
+ * @state: NUD_* states
+ *
+ * Return: Result status
*/
-static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
- int cmd)
+static int netlink_update_neigh_ctx_internal(const struct zebra_dplane_ctx *ctx,
+ int cmd, const struct ethaddr *mac,
+ const struct ipaddr *ip,
+ bool replace_obj, uint8_t family,
+ uint8_t type, uint8_t flags,
+ uint16_t state)
{
uint8_t protocol = RTPROT_ZEBRA;
struct {
@@ -2548,34 +2551,62 @@ static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
struct ndmsg ndm;
char buf[256];
} req;
- uint8_t dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
- const struct ipaddr *addr;
+ int ipa_len;
+ enum dplane_op_e op;
memset(&req, 0, sizeof(req));
+ op = dplane_ctx_get_op(ctx);
+
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
req.n.nlmsg_flags = NLM_F_REQUEST;
if (cmd == RTM_NEWNEIGH)
- req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND);
+ req.n.nlmsg_flags |=
+ NLM_F_CREATE
+ | (replace_obj ? NLM_F_REPLACE : NLM_F_APPEND);
req.n.nlmsg_type = cmd;
- req.ndm.ndm_family = PF_BRIDGE;
- req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT;
- req.ndm.ndm_flags |= NTF_SELF; /* Handle by "self", not "master" */
-
+ req.ndm.ndm_family = family;
+ req.ndm.ndm_type = type;
+ req.ndm.ndm_state = state;
+ req.ndm.ndm_flags = flags;
+ req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
addattr_l(&req.n, sizeof(req),
NDA_PROTOCOL, &protocol, sizeof(protocol));
- addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6);
- req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
+ if (mac)
+ addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
- addr = dplane_ctx_neigh_get_ipaddr(ctx);
+ ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
+ addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
+
+ if (op == DPLANE_OP_MAC_INSTALL || op == DPLANE_OP_MAC_DELETE) {
+ vlanid_t vid = dplane_ctx_mac_get_vlan(ctx);
- addattr_l(&req.n, sizeof(req), NDA_DST, &(addr->ipaddr_v4), 4);
+ if (vid > 0)
+ addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
+
+ addattr32(&req.n, sizeof(req), NDA_MASTER,
+ dplane_ctx_mac_get_br_ifindex(ctx));
+ }
return netlink_talk_info(netlink_talk_filter, &req.n,
dplane_ctx_get_ns(ctx), 0);
}
+/*
+ * Add remote VTEP to the flood list for this VxLAN interface (VNI). This
+ * is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
+ */
+static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
+ int cmd)
+{
+ struct ethaddr dst_mac = {.octet = {0}};
+
+ return netlink_update_neigh_ctx_internal(
+ ctx, cmd, &dst_mac, dplane_ctx_neigh_get_ipaddr(ctx), false,
+ PF_BRIDGE, 0, NTF_SELF, (NUD_NOARP | NUD_PERMANENT));
+}
+
#ifndef NDA_RTA
#define NDA_RTA(r) \
((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
@@ -2675,7 +2706,7 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (filter_vlan && vid != filter_vlan) {
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("\tFiltered due to filter vlan: %d",
+ zlog_debug(" Filtered due to filter vlan: %d",
filter_vlan);
return 0;
}
@@ -2689,8 +2720,9 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
/* Drop "permanent" entries. */
if (ndm->ndm_state & NUD_PERMANENT) {
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("\tDropping entry because of NUD_PERMANENT");
- return 0;
+ zlog_debug(
+ " Dropping entry because of NUD_PERMANENT");
+ return 0;
}
if (IS_ZEBRA_IF_VXLAN(ifp))
@@ -2862,10 +2894,12 @@ static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns,
addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("%s: Tx family %s IF %s(%u) MAC %s vid %u", __func__,
- nl_family_to_str(req.ndm.ndm_family), br_if->name,
- br_if->ifindex,
- prefix_mac2str(mac, buf, sizeof(buf)), vid);
+ zlog_debug(
+ "%s: Tx family %s IF %s(%u) vrf %s(%u) MAC %s vid %u",
+ __func__, nl_family_to_str(req.ndm.ndm_family),
+ br_if->name, br_if->ifindex,
+ vrf_id_to_name(br_if->vrf_id), br_if->vrf_id,
+ prefix_mac2str(mac, buf, sizeof(buf)), vid);
return netlink_request(&zns->netlink_cmd, &req.n);
}
@@ -2896,92 +2930,50 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
/*
* Netlink-specific handler for MAC updates using dataplane context object.
*/
-static enum zebra_dplane_result
-netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx)
+static int netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, int cmd)
{
- uint8_t protocol = RTPROT_ZEBRA;
- struct {
- struct nlmsghdr n;
- struct ndmsg ndm;
- char buf[256];
- } req;
- int ret;
- int dst_alen;
- int vid_present = 0;
- int cmd;
- struct in_addr vtep_ip;
+ struct ipaddr vtep_ip;
vlanid_t vid;
+ uint8_t flags;
+ uint16_t state;
- if (dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL)
- cmd = RTM_NEWNEIGH;
- else
- cmd = RTM_DELNEIGH;
-
- memset(&req, 0, sizeof(req));
-
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- if (cmd == RTM_NEWNEIGH)
- req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
- req.n.nlmsg_type = cmd;
- req.ndm.ndm_family = AF_BRIDGE;
- req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
- req.ndm.ndm_state = NUD_REACHABLE;
+ flags = (NTF_SELF | NTF_MASTER);
+ state = NUD_REACHABLE;
if (dplane_ctx_mac_is_sticky(ctx))
- req.ndm.ndm_state |= NUD_NOARP;
+ state |= NUD_NOARP;
else
- req.ndm.ndm_flags |= NTF_EXT_LEARNED;
-
- addattr_l(&req.n, sizeof(req),
- NDA_PROTOCOL, &protocol, sizeof(protocol));
- addattr_l(&req.n, sizeof(req), NDA_LLADDR,
- dplane_ctx_mac_get_addr(ctx), 6);
- req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
-
- dst_alen = 4; // TODO: hardcoded
- vtep_ip = *(dplane_ctx_mac_get_vtep_ip(ctx));
- addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
+ flags |= NTF_EXT_LEARNED;
- vid = dplane_ctx_mac_get_vlan(ctx);
-
- if (vid > 0) {
- addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
- vid_present = 1;
- }
- addattr32(&req.n, sizeof(req), NDA_MASTER,
- dplane_ctx_mac_get_br_ifindex(ctx));
+ vtep_ip.ipaddr_v4 = *(dplane_ctx_mac_get_vtep_ip(ctx));
+ SET_IPADDR_V4(&vtep_ip);
if (IS_ZEBRA_DEBUG_KERNEL) {
char ipbuf[PREFIX_STRLEN];
char buf[ETHER_ADDR_STRLEN];
- char dst_buf[PREFIX_STRLEN + 10];
char vid_buf[20];
- if (vid_present)
+ vid = dplane_ctx_mac_get_vlan(ctx);
+ if (vid > 0)
snprintf(vid_buf, sizeof(vid_buf), " VLAN %u", vid);
else
vid_buf[0] = '\0';
- inet_ntop(AF_INET, &vtep_ip, ipbuf, sizeof(ipbuf));
- snprintf(dst_buf, sizeof(dst_buf), " dst %s", ipbuf);
- prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf, sizeof(buf));
+ const struct ethaddr *mac = dplane_ctx_mac_get_addr(ctx);
- zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
- nl_msg_type_to_str(cmd),
- nl_family_to_str(req.ndm.ndm_family),
+ zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s dst %s",
+ nl_msg_type_to_str(cmd), nl_family_to_str(AF_BRIDGE),
dplane_ctx_get_ifname(ctx),
dplane_ctx_get_ifindex(ctx), vid_buf,
dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "",
- buf, dst_buf);
+ prefix_mac2str(mac, buf, sizeof(buf)),
+ ipaddr2str(&vtep_ip, ipbuf, sizeof(ipbuf)));
}
- ret = netlink_talk_info(netlink_talk_filter, &req.n,
- dplane_ctx_get_ns(ctx), 0);
- if (ret == 0)
- return ZEBRA_DPLANE_REQUEST_SUCCESS;
- else
- return ZEBRA_DPLANE_REQUEST_FAILURE;
+ return netlink_update_neigh_ctx_internal(
+ ctx, cmd, dplane_ctx_mac_get_addr(ctx),
+ dplane_ctx_neigh_get_ipaddr(ctx), true, AF_BRIDGE, 0, flags,
+ state);
}
/*
@@ -3023,6 +3015,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
struct interface *link_if;
struct ethaddr mac;
struct ipaddr ip;
+ struct vrf *vrf;
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
int mac_present = 0;
@@ -3037,6 +3030,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (!ifp || !ifp->info)
return 0;
+ vrf = vrf_lookup_by_id(ifp->vrf_id);
zif = (struct zebra_if *)ifp->info;
/* Parse attributes and extract fields of interest. */
@@ -3044,10 +3038,10 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
if (!tb[NDA_DST]) {
- zlog_debug("%s family %s IF %s(%u) - no DST",
+ zlog_debug("%s family %s IF %s(%u) vrf %s(%u) - no DST",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex);
+ ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id);
return 0;
}
@@ -3099,12 +3093,13 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu",
+ "%s family %s IF %s(%u) vrf %s(%u) - LLADDR is not MAC, len %lu",
nl_msg_type_to_str(
h->nlmsg_type),
nl_family_to_str(
ndm->ndm_family),
ifp->name, ndm->ndm_ifindex,
+ VRF_LOGNAME(vrf), ifp->vrf_id,
(unsigned long)RTA_PAYLOAD(
tb[NDA_LLADDR]));
return 0;
@@ -3119,10 +3114,10 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
+ "Rx %s family %s IF %s(%u) vrf %s(%u) IP %s MAC %s state 0x%x flags 0x%x",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex,
+ ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id,
ipaddr2str(&ip, buf2, sizeof(buf2)),
mac_present
? prefix_mac2str(&mac, buf, sizeof(buf))
@@ -3144,10 +3139,10 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
}
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Rx %s family %s IF %s(%u) IP %s",
+ zlog_debug("Rx %s family %s IF %s(%u) vrf %s(%u) IP %s",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex,
+ ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id,
ipaddr2str(&ip, buf2, sizeof(buf2)));
/* Process the delete - it may result in re-adding the neighbor if it is
@@ -3301,9 +3296,10 @@ int netlink_neigh_read_specific_ip(struct ipaddr *ip,
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("%s: neigh request IF %s(%u) IP %s vrf_id %u",
+ zlog_debug("%s: neigh request IF %s(%u) IP %s vrf %s(%u)",
__func__, vlan_if->name, vlan_if->ifindex,
- ipaddr2str(ip, buf, sizeof(buf)), vlan_if->vrf_id);
+ ipaddr2str(ip, buf, sizeof(buf)),
+ vrf_id_to_name(vlan_if->vrf_id), vlan_if->vrf_id);
ret = netlink_request_specific_neigh_in_vlan(zns, RTM_GETNEIGH, ip,
vlan_if->ifindex);
@@ -3361,21 +3357,11 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
int cmd)
{
- uint8_t protocol = RTPROT_ZEBRA;
- struct {
- struct nlmsghdr n;
- struct ndmsg ndm;
- char buf[256];
- } req;
- int ipa_len;
- char buf[INET6_ADDRSTRLEN];
- char buf2[ETHER_ADDR_STRLEN];
const struct ipaddr *ip;
const struct ethaddr *mac;
uint8_t flags;
uint16_t state;
-
- memset(&req, 0, sizeof(req));
+ uint8_t family;
ip = dplane_ctx_neigh_get_ipaddr(ctx);
mac = dplane_ctx_neigh_get_mac(ctx);
@@ -3385,37 +3371,23 @@ static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
flags = neigh_flags_to_netlink(dplane_ctx_neigh_get_flags(ctx));
state = neigh_state_to_netlink(dplane_ctx_neigh_get_state(ctx));
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST;
- if (cmd == RTM_NEWNEIGH)
- req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
- req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
- req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
- req.ndm.ndm_state = state;
- req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
- req.ndm.ndm_type = RTN_UNICAST;
- req.ndm.ndm_flags = flags;
+ family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6;
- addattr_l(&req.n, sizeof(req),
- NDA_PROTOCOL, &protocol, sizeof(protocol));
- ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
- addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
- if (mac)
- addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ char buf[INET6_ADDRSTRLEN];
+ char buf2[ETHER_ADDR_STRLEN];
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x state 0x%x",
- nl_msg_type_to_str(cmd),
- nl_family_to_str(req.ndm.ndm_family),
- dplane_ctx_get_ifname(ctx),
- dplane_ctx_get_ifindex(ctx),
- ipaddr2str(ip, buf, sizeof(buf)),
- mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
- : "null",
- flags, state);
+ zlog_debug(
+ "Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x state 0x%x",
+ nl_msg_type_to_str(cmd), nl_family_to_str(family),
+ dplane_ctx_get_ifname(ctx), dplane_ctx_get_ifindex(ctx),
+ ipaddr2str(ip, buf, sizeof(buf)),
+ mac ? prefix_mac2str(mac, buf2, sizeof(buf2)) : "null",
+ flags, state);
+ }
- return netlink_talk_info(netlink_talk_filter, &req.n,
- dplane_ctx_get_ns(ctx), 0);
+ return netlink_update_neigh_ctx_internal(
+ ctx, cmd, mac, ip, true, family, RTN_UNICAST, flags, state);
}
/*
@@ -3423,7 +3395,13 @@ static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
*/
enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
{
- return netlink_macfdb_update_ctx(ctx);
+ int cmd = dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL
+ ? RTM_NEWNEIGH
+ : RTM_DELNEIGH;
+ int ret = netlink_macfdb_update_ctx(ctx, cmd);
+
+ return (ret == 0 ? ZEBRA_DPLANE_REQUEST_SUCCESS
+ : ZEBRA_DPLANE_REQUEST_FAILURE);
}
enum zebra_dplane_result kernel_neigh_update_ctx(struct zebra_dplane_ctx *ctx)
@@ -3464,6 +3442,7 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
unsigned int nexthop_num;
const char *routedesc;
int route_type;
+ struct prefix p = {0};
struct {
struct nlmsghdr n;
@@ -3550,8 +3529,7 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
NEXTHOP_FLAG_FIB)))) {
/* Add the gateway */
_netlink_mpls_build_singlepath(
- routedesc, nhlfe,
- &req.n, &req.r,
+ &p, routedesc, nhlfe, &req.n, &req.r,
sizeof(req), cmd);
nexthop_num++;
@@ -3591,9 +3569,9 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
nexthop_num++;
/* Build the multipath */
- _netlink_mpls_build_multipath(routedesc, nhlfe,
- rta, rtnh, &req.r,
- &src1);
+ _netlink_mpls_build_multipath(&p, routedesc,
+ nhlfe, rta, rtnh,
+ &req.r, &src1);
rtnh = RTNH_NEXT(rtnh);
}
}