From f2a0ba3a507d08201c0f5b499e65d5c019c98124 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 13 Jan 2020 16:34:03 -0300 Subject: [PATCH] zebra: data plane FPM add support RMAC VNI Store VNI information in the data plane context so we can use it to build the FPM netlink update with that information later. Signed-off-by: Rafael Zalamena --- lib/nexthop.h | 11 +++++++++++ zebra/dplane_fpm_nl.c | 8 ++++---- zebra/rt_netlink.c | 46 +++++++++++++++++++++++++++++++++++++++---- zebra/rt_netlink.h | 3 ++- zebra/zebra_dplane.c | 21 +++++++++++++++++--- 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/lib/nexthop.h b/lib/nexthop.h index c4e88dd844..9b71262589 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -25,6 +25,7 @@ #include "prefix.h" #include "mpls.h" +#include "vxlan.h" #ifdef __cplusplus extern "C" { @@ -60,6 +61,10 @@ enum blackhole_type { ? (type) \ : ((type) | 1) +enum nh_encap_type { + NET_VXLAN = 100, /* value copied from FPM_NH_ENCAP_VXLAN. */ +}; + /* Nexthop structure. */ struct nexthop { struct nexthop *next; @@ -123,6 +128,12 @@ struct nexthop { * only meaningful if the HAS_BACKUP flag is set. */ uint8_t backup_idx; + + /* Encapsulation information. */ + enum nh_encap_type nh_encap_type; + union { + vni_t vni; + } nh_encap; }; /* Backup index value is limited */ diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c index 7d78b534f8..4b8948b71c 100644 --- a/zebra/dplane_fpm_nl.c +++ b/zebra/dplane_fpm_nl.c @@ -626,7 +626,7 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx) case DPLANE_OP_ROUTE_UPDATE: case DPLANE_OP_ROUTE_DELETE: rv = netlink_route_multipath(RTM_DELROUTE, ctx, nl_buf, - sizeof(nl_buf)); + sizeof(nl_buf), true); if (rv <= 0) { zlog_debug("%s: netlink_route_multipath failed", __func__); @@ -643,7 +643,7 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx) case DPLANE_OP_ROUTE_INSTALL: rv = netlink_route_multipath(RTM_NEWROUTE, ctx, &nl_buf[nl_buf_len], - sizeof(nl_buf) - nl_buf_len); + sizeof(nl_buf) - nl_buf_len, true); if (rv <= 0) { zlog_debug("%s: netlink_route_multipath failed", __func__); @@ -829,8 +829,8 @@ static void fpm_enqueue_rmac_table(struct hash_backet *backet, void *arg) dplane_ctx_reset(fra->ctx); dplane_ctx_set_op(fra->ctx, DPLANE_OP_MAC_INSTALL); dplane_mac_init(fra->ctx, fra->zl3vni->vxlan_if, - zif->brslave_info.br_if, vid, &zrmac->macaddr, - zrmac->fwd_info.r_vtep_ip, sticky); + zif->brslave_info.br_if, vid, + &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, sticky); if (fpm_nl_enqueue(fra->fnc, fra->ctx) == -1) { thread_add_timer(zrouter.master, fpm_rmac_send, fra->fnc, 1, &fra->fnc->t_rmacwalk); 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); diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 15ef43c538..d6a993e78a 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -67,7 +67,8 @@ void rt_netlink_init(void); extern int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx); extern 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); extern ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, uint8_t *data, size_t datalen); diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index e3eeecefc4..abbd136948 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -32,6 +32,7 @@ #include "zebra/zebra_memory.h" #include "zebra/zebra_router.h" #include "zebra/zebra_dplane.h" +#include "zebra/zebra_vxlan_private.h" #include "zebra/rt.h" #include "zebra/debug.h" @@ -178,7 +179,6 @@ struct dplane_mac_info { struct ethaddr mac; struct in_addr vtep_ip; bool is_sticky; - }; /* @@ -1535,6 +1535,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, struct zebra_ns *zns; struct zebra_vrf *zvrf; struct nexthop *nexthop; + zebra_l3vni_t *zl3vni; if (!ctx || !rn || !re) goto done; @@ -1584,10 +1585,24 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, re->nhe->backup_info->nhe->nhg.nexthop, NULL); } - /* Ensure that the dplane nexthops' flags are clear. */ - for (ALL_NEXTHOPS(ctx->u.rinfo.zd_ng, nexthop)) + /* + * Ensure that the dplane nexthops' flags are clear and copy + * encapsulation information. + */ + for (ALL_NEXTHOPS(ctx->u.rinfo.zd_ng, nexthop)) { UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + /* Check for available encapsulations. */ + if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) + continue; + + zl3vni = zl3vni_from_vrf(nexthop->vrf_id); + if (zl3vni && is_l3vni_oper_up(zl3vni)) { + nexthop->nh_encap_type = NET_VXLAN; + nexthop->nh_encap.vni = zl3vni->vni; + } + } + /* Don't need some info when capturing a system notification */ if (op == DPLANE_OP_SYS_ROUTE_ADD || op == DPLANE_OP_SYS_ROUTE_DELETE) { -- 2.39.5