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.c165
1 files changed, 69 insertions, 96 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 683c6532e6..84c9bd098e 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1515,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
*/
@@ -1525,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;
@@ -1641,13 +1665,30 @@ 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));
- /* Kernel supports nexthop objects */
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;
}
@@ -1695,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;
}
@@ -1737,7 +1754,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
break;
}
}
- if (setsrc && (cmd == RTM_NEWROUTE)) {
+ if (setsrc) {
if (family == AF_INET)
addattr_l(&req.n, sizeof(req), RTA_PREFSRC,
&src.ipv4, bytelen);
@@ -1763,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;
}
@@ -1815,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);
@@ -1990,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,
@@ -2076,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));
@@ -2111,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;
}