#include "prefix.h"
#include "mpls.h"
+#include "vxlan.h"
#ifdef __cplusplus
extern "C" {
? (type) \
: ((type) | 1)
+enum nh_encap_type {
+ NET_VXLAN = 100, /* value copied from FPM_NH_ENCAP_VXLAN. */
+};
+
/* Nexthop structure. */
struct nexthop {
struct nexthop *next;
* 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 */
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__);
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__);
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);
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;
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,
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,
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);
*/
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);
}
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);
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);
#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"
struct ethaddr mac;
struct in_addr vtep_ip;
bool is_sticky;
-
};
/*
struct zebra_ns *zns;
struct zebra_vrf *zvrf;
struct nexthop *nexthop;
+ zebra_l3vni_t *zl3vni;
if (!ctx || !rn || !re)
goto done;
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) {