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.c261
1 files changed, 117 insertions, 144 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 2cc520bbce..84c9bd098e 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -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,
@@ -1176,9 +1177,8 @@ 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,
+ " 5549: _netlink_route_build_singlepath() (%s): %pFX nexthop via %s %s if %u(%u)",
+ routedesc, p, ipv4_ll_buf, label_buf,
nexthop->ifindex, nexthop->vrf_id);
return;
}
@@ -1202,9 +1202,8 @@ 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),
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u(%u)",
+ routedesc, p, inet_ntoa(nexthop->gate.ipv4),
label_buf, nexthop->ifindex, nexthop->vrf_id);
}
@@ -1225,9 +1224,8 @@ 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),
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u(%u)",
+ routedesc, p, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex, nexthop->vrf_id);
}
@@ -1251,9 +1249,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(%u)",
+ routedesc, p, nexthop->ifindex,
+ nexthop->vrf_id);
}
}
@@ -1273,12 +1271,11 @@ 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];
@@ -1350,9 +1347,8 @@ 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,
+ " 5549: netlink_route_build_multipath() (%s): %pFX nexthop via %s %s if %u",
+ routedesc, p, ipv4_ll_buf, label_buf,
nexthop->ifindex);
return;
}
@@ -1369,9 +1365,8 @@ 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),
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u",
+ routedesc, p, inet_ntoa(nexthop->gate.ipv4),
label_buf, nexthop->ifindex);
}
if (nexthop->type == NEXTHOP_TYPE_IPV6
@@ -1387,9 +1382,8 @@ 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),
+ "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u",
+ routedesc, p, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex);
}
@@ -1410,16 +1404,16 @@ 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",
+ routedesc, p, nexthop->ifindex);
}
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,
@@ -1430,23 +1424,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);
}
@@ -1520,6 +1515,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
*/
@@ -1530,7 +1549,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;
@@ -1647,8 +1666,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;
}
@@ -1696,32 +1736,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;
}
@@ -1732,13 +1748,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);
@@ -1764,32 +1780,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;
}
@@ -1802,8 +1793,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) {
@@ -1816,7 +1807,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);
@@ -1991,6 +1982,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,
@@ -2077,14 +2074,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:
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: ID (%u): %pNHv (%u) %s ",
+ __func__, id, nh, nh->vrf_id,
+ label_buf);
- snprintfrr(buf, sizeof(buf), "%pNHv", nh);
- zlog_debug("%s: ID (%u): %s (%u) %s ", __func__,
- id, buf, nh->vrf_id, label_buf);
- }
}
req.nhm.nh_protocol = zebra2proto(dplane_ctx_get_nhe_type(ctx));
@@ -2112,43 +2108,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;
}
@@ -2677,7 +2649,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;
}
@@ -2691,8 +2663,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))
@@ -3466,6 +3439,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;
@@ -3552,8 +3526,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++;
@@ -3593,9 +3566,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);
}
}