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.c46
1 files changed, 42 insertions, 4 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 06da711303..7ca4425dc8 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1528,11 +1528,28 @@ static bool nexthop_set_src(const struct nexthop *nexthop, int family,
return false;
}
+static void netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen,
+ struct nexthop *nh)
+{
+ struct rtattr *nest;
+
+ switch (nh->nh_encap_type) {
+ case NET_VXLAN:
+ addattr_l(n, nlen, RTA_ENCAP_TYPE, &nh->nh_encap_type,
+ sizeof(uint16_t));
+
+ nest = addattr_nest(n, nlen, RTA_ENCAP);
+ addattr32(n, nlen, 0 /* VXLAN_VNI */, nh->nh_encap.vni);
+ addattr_nest_end(n, nest);
+ break;
+ }
+}
+
/*
* Routing table change via netlink interface, using a dataplane context object
*/
ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
- uint8_t *data, size_t datalen)
+ uint8_t *data, size_t datalen, bool fpm)
{
int bytelen;
struct nexthop *nexthop = NULL;
@@ -1744,7 +1761,16 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
nexthop_num++;
break;
}
+
+ /*
+ * Add encapsulation information when installing via
+ * FPM.
+ */
+ if (fpm)
+ netlink_route_nexthop_encap(&req->n, datalen,
+ nexthop);
}
+
if (setsrc) {
if (p->family == AF_INET)
addattr_l(&req->n, datalen, RTA_PREFSRC,
@@ -1796,7 +1822,16 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
setsrc = 1;
}
}
+
+ /*
+ * Add encapsulation information when installing via
+ * FPM.
+ */
+ if (fpm)
+ netlink_route_nexthop_encap(&req->n, datalen,
+ nexthop);
}
+
if (setsrc) {
if (p->family == AF_INET)
addattr_l(&req->n, datalen, RTA_PREFSRC,
@@ -2149,7 +2184,8 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
if (RSYSTEM_ROUTE(dplane_ctx_get_type(ctx)) &&
!RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx))) {
netlink_route_multipath(RTM_DELROUTE, ctx,
- nl_pkt, sizeof(nl_pkt));
+ nl_pkt, sizeof(nl_pkt),
+ false);
netlink_talk_info(netlink_talk_filter,
(struct nlmsghdr *)nl_pkt,
dplane_ctx_get_ns(ctx), 0);
@@ -2169,7 +2205,8 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
*/
if (!RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx))) {
netlink_route_multipath(RTM_DELROUTE, ctx,
- nl_pkt, sizeof(nl_pkt));
+ nl_pkt, sizeof(nl_pkt),
+ false);
netlink_talk_info(netlink_talk_filter,
(struct nlmsghdr *)nl_pkt,
dplane_ctx_get_ns(ctx), 0);
@@ -2182,7 +2219,8 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
}
if (!RSYSTEM_ROUTE(dplane_ctx_get_type(ctx))) {
- netlink_route_multipath(cmd, ctx, nl_pkt, sizeof(nl_pkt));
+ netlink_route_multipath(cmd, ctx, nl_pkt, sizeof(nl_pkt),
+ false);
ret = netlink_talk_info(netlink_talk_filter,
(struct nlmsghdr *)nl_pkt,
dplane_ctx_get_ns(ctx), 0);