mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-04 13:31:48 +00:00
zebra: nhg resolution handler for d-vni
Add code in the nhg resolution path for determining if Downstream VNI is in play. This is the only place in all of zebra where we should be arbitrarily setting the ifindex/labels since this is where new nhgs are created/destroyed. If something changes, it must happen here. We determine if D-VNI is being used by matching the carried label (VNI) on the nexthop with the vrf VNI from the route. If they do not match, we can assume this is a D-VNI labeled nexthop. We loop through all of the group to see if any are D-VNI. If even one is, we must treat them all as such. Otherwise, fallback to traditional EVPN route handling and remove all the labels. If they are going to be treated as D-VNI we retain the labels and verify the underlying VRF vxlan interface is a Single VXlan Device. If it is not, we cannot use D-VNI. If it is, continue on. The VNI label will encapped via LWTUNNEL and sent to the kernel. Signed-off-by: Stephen Worley <sworley@nvidia.com>
This commit is contained in:
parent
b260197de9
commit
b991a37262
@ -44,6 +44,7 @@
|
||||
#include "zebra/interface.h"
|
||||
#include "zebra/zapi_msg.h"
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zebra_vxlan.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(ZEBRA, NHG, "Nexthop Group Entry");
|
||||
DEFINE_MTYPE_STATIC(ZEBRA, NHG_CONNECTED, "Nexthop Group Connected");
|
||||
@ -1922,10 +1923,42 @@ static bool nexthop_valid_resolve(const struct nexthop *nexthop,
|
||||
}
|
||||
|
||||
/*
|
||||
* When resolving a recursive nexthop, capture backup nexthop(s) also
|
||||
* so they can be conveyed through the dataplane to the FIB. We'll look
|
||||
* at the backups in the resolving nh 'nexthop' and its nhe, and copy them
|
||||
* into the route's resolved nh 'resolved' and its nhe 'nhe'.
|
||||
* Downstream VNI and Single VXlan device check.
|
||||
*
|
||||
* If it has nexthop VNI labels at this point it must be D-VNI allocated
|
||||
* and all the nexthops have to be on an SVD.
|
||||
*
|
||||
* If SVD is not available, mark as inactive.
|
||||
*/
|
||||
static bool nexthop_set_evpn_dvni_svd(vrf_id_t re_vrf_id,
|
||||
struct nexthop *nexthop)
|
||||
{
|
||||
if (!is_vrf_l3vni_svd_backed(re_vrf_id)) {
|
||||
if (IS_ZEBRA_DEBUG_NHG_DETAIL) {
|
||||
struct vrf *vrf = vrf_lookup_by_id(re_vrf_id);
|
||||
|
||||
zlog_debug(
|
||||
"nexthop %pNHv D-VNI but route's vrf %s(%u) doesn't use SVD",
|
||||
nexthop, VRF_LOGNAME(vrf), re_vrf_id);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nexthop->ifindex = get_l3vni_vxlan_ifindex(re_vrf_id);
|
||||
nexthop->vrf_id = 0;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
|
||||
zlog_debug("nexthop %pNHv using SVD", nexthop);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a nexthop we need to properly recursively resolve
|
||||
* the route. As such, do a table lookup to find and match
|
||||
* if at all possible. Set the nexthop->ifindex and resolved_id
|
||||
* as appropriate
|
||||
*/
|
||||
static int resolve_backup_nexthops(const struct nexthop *nexthop,
|
||||
const struct nhg_hash_entry *nhe,
|
||||
@ -2195,6 +2228,12 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
|
||||
* sure the nexthop's interface is known and is operational.
|
||||
*/
|
||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) {
|
||||
/* DVNI/SVD Checks for EVPN routes */
|
||||
if (nexthop->nh_label &&
|
||||
nexthop->nh_label_type == ZEBRA_LSP_EVPN &&
|
||||
!nexthop_set_evpn_dvni_svd(vrf_id, nexthop))
|
||||
return 0;
|
||||
|
||||
ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
|
||||
if (!ifp) {
|
||||
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
|
||||
@ -2706,6 +2745,47 @@ done:
|
||||
return valid;
|
||||
}
|
||||
|
||||
/* Checks if the first nexthop is EVPN. If not, early return.
|
||||
*
|
||||
* This is used to determine if there is a mismatch between l3VNI
|
||||
* of the route's vrf and the nexthops in use's VNI labels.
|
||||
*
|
||||
* If there is a mismatch, we keep the labels as these MUST be DVNI nexthops.
|
||||
*
|
||||
* IF there is no mismatch, we remove the labels and handle the routes as
|
||||
* we have traditionally with evpn.
|
||||
*/
|
||||
static bool nexthop_list_set_evpn_dvni(struct route_entry *re,
|
||||
struct nexthop_group *nhg)
|
||||
{
|
||||
struct nexthop *nexthop;
|
||||
vni_t re_vrf_vni;
|
||||
vni_t nh_vni;
|
||||
bool use_dvni = false;
|
||||
|
||||
nexthop = nhg->nexthop;
|
||||
|
||||
if (!nexthop->nh_label || nexthop->nh_label_type != ZEBRA_LSP_EVPN)
|
||||
return false;
|
||||
|
||||
re_vrf_vni = get_l3vni_vni(re->vrf_id);
|
||||
|
||||
for (; nexthop; nexthop = nexthop->next) {
|
||||
nh_vni = label2vni(&nexthop->nh_label->label[0]);
|
||||
|
||||
if (nh_vni != re_vrf_vni)
|
||||
use_dvni = true;
|
||||
}
|
||||
|
||||
/* Using traditional way, no VNI encap - remove labels */
|
||||
if (!use_dvni) {
|
||||
for (nexthop = nhg->nexthop; nexthop; nexthop = nexthop->next)
|
||||
nexthop_del_labels(nexthop);
|
||||
}
|
||||
|
||||
return use_dvni;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a list of nexthops, given an nhe, determining
|
||||
* whether each one is ACTIVE/installable at this time.
|
||||
@ -2721,12 +2801,16 @@ static uint32_t nexthop_list_active_update(struct route_node *rn,
|
||||
uint32_t counter = 0;
|
||||
struct nexthop *nexthop;
|
||||
struct nexthop_group *nhg = &nhe->nhg;
|
||||
bool vni_removed = false;
|
||||
|
||||
nexthop = nhg->nexthop;
|
||||
|
||||
/* Init recursive nh mtu */
|
||||
re->nexthop_mtu = 0;
|
||||
|
||||
/* Handler for dvni evpn nexthops. Has to be done at nhg level */
|
||||
vni_removed = !nexthop_list_set_evpn_dvni(re, nhg);
|
||||
|
||||
/* Process nexthops one-by-one */
|
||||
for ( ; nexthop; nexthop = nexthop->next) {
|
||||
|
||||
@ -2773,7 +2857,8 @@ static uint32_t nexthop_list_active_update(struct route_node *rn,
|
||||
&& nexthop->type < NEXTHOP_TYPE_BLACKHOLE)
|
||||
&& !(IPV6_ADDR_SAME(&prev_src.ipv6,
|
||||
&nexthop->rmap_src.ipv6)))
|
||||
|| CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED))
|
||||
|| CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED)
|
||||
|| vni_removed)
|
||||
SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user