mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-04 13:31:48 +00:00
bgpd: program mac-ip routes in matching vrfs
Signed-off-by: Mitesh Kanjariya <mitesh@cumulusnetworks.com>
This commit is contained in:
parent
10ebe1ab54
commit
d3135ba31d
282
bgpd/bgp_evpn.c
282
bgpd/bgp_evpn.c
@ -782,6 +782,95 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
bgp_info_delete(rn, old_local);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the best path for an EVPN route. Install/update best path in zebra,
|
||||
* if appropriate.
|
||||
*/
|
||||
static int evpn_vrf_route_select_install(struct bgp *bgp_vrf,
|
||||
struct bgp_node *rn,
|
||||
struct prefix *p,
|
||||
afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
struct bgp_info *old_select, *new_select;
|
||||
struct bgp_info_pair old_and_new;
|
||||
int ret = 0;
|
||||
|
||||
/* Compute the best path. */
|
||||
bgp_best_selection(bgp_vrf, rn, &bgp_vrf->maxpaths[afi][safi],
|
||||
&old_and_new, afi, safi);
|
||||
old_select = old_and_new.old;
|
||||
new_select = old_and_new.new;
|
||||
|
||||
/* If the best path hasn't changed - see if there is still something to
|
||||
* update
|
||||
* to zebra RIB.
|
||||
*/
|
||||
if (old_select && old_select == new_select
|
||||
&& old_select->type == ZEBRA_ROUTE_BGP
|
||||
&& old_select->sub_type == BGP_ROUTE_NORMAL
|
||||
&& !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
|
||||
&& !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED)
|
||||
&& !bgp_vrf->addpath_tx_used[afi][safi]) {
|
||||
if (bgp_zebra_has_route_changed(rn, old_select))
|
||||
bgp_zebra_announce(rn, p, old_select, bgp_vrf,
|
||||
afi, safi);
|
||||
UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG);
|
||||
bgp_zebra_clear_route_change_flags(rn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If the user did a "clear" this flag will be set */
|
||||
UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
|
||||
|
||||
/* bestpath has changed; update relevant fields and install or uninstall
|
||||
* into the zebra RIB.
|
||||
*/
|
||||
if (old_select || new_select)
|
||||
bgp_bump_version(rn);
|
||||
|
||||
if (old_select)
|
||||
bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED);
|
||||
if (new_select) {
|
||||
bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED);
|
||||
bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED);
|
||||
UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG);
|
||||
}
|
||||
|
||||
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
|
||||
&& new_select->sub_type == BGP_ROUTE_NORMAL) {
|
||||
bgp_zebra_announce(rn, p, new_select, bgp_vrf,
|
||||
afi, safi);
|
||||
|
||||
/* If an old best existed and it was a "local" route, the only
|
||||
* reason
|
||||
* it would be supplanted is due to MAC mobility procedures. So,
|
||||
* we
|
||||
* need to do an implicit delete and withdraw that route from
|
||||
* peers.
|
||||
*/
|
||||
/*if (old_select && old_select->peer == bgp_vrf->peer_self
|
||||
&& old_select->type == ZEBRA_ROUTE_BGP
|
||||
&& old_select->sub_type == BGP_ROUTE_STATIC) {
|
||||
//evpn_delete_old_local_route(bgp, vpn, rn, old_select);
|
||||
}*/ //TODO_MITESH: probably not needed for vrf routes, think!!
|
||||
} else {
|
||||
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
|
||||
&& old_select->sub_type == BGP_ROUTE_NORMAL) {
|
||||
bgp_zebra_withdraw(p, old_select, safi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear any route change flags. */
|
||||
bgp_zebra_clear_route_change_flags(rn);
|
||||
|
||||
/* Reap old select bgp_info, if it has been removed */
|
||||
if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED))
|
||||
bgp_info_reap(rn, old_select);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the best path for an EVPN route. Install/update best path in zebra,
|
||||
* if appropriate.
|
||||
@ -1418,6 +1507,88 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
return update_routes_for_vni(bgp, vpn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Install route entry into the VRF routing table and invoke route selection.
|
||||
*/
|
||||
static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
|
||||
struct prefix_evpn *evp,
|
||||
struct bgp_info *parent_ri)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct attr *attr_new;
|
||||
int ret;
|
||||
struct prefix p;
|
||||
struct prefix *pp = &p;
|
||||
afi_t afi = 0;
|
||||
safi_t safi = 0;
|
||||
|
||||
memset(pp, 0, sizeof(struct prefix));
|
||||
ip_prefix_from_type2_prefix(evp, pp);
|
||||
|
||||
/* Create (or fetch) route within the VRF. */
|
||||
/* NOTE: There is no RD here. */
|
||||
if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
|
||||
afi = AFI_IP;
|
||||
safi = SAFI_UNICAST;
|
||||
rn = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
|
||||
} else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
|
||||
afi = AFI_IP6;
|
||||
safi = SAFI_UNICAST;
|
||||
rn = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
|
||||
} else
|
||||
return 0;
|
||||
|
||||
/* Check if route entry is already present. */
|
||||
for (ri = rn->info; ri; ri = ri->next)
|
||||
if (ri->extra
|
||||
&& (struct bgp_info *)ri->extra->parent == parent_ri)
|
||||
break;
|
||||
|
||||
if (!ri) {
|
||||
/* Add (or update) attribute to hash. */
|
||||
attr_new = bgp_attr_intern(parent_ri->attr);
|
||||
|
||||
/* Create new route with its attribute. */
|
||||
ri = info_make(parent_ri->type, parent_ri->sub_type, 0,
|
||||
parent_ri->peer, attr_new, rn);
|
||||
SET_FLAG(ri->flags, BGP_INFO_VALID);
|
||||
bgp_info_extra_get(ri);
|
||||
ri->extra->parent = parent_ri;
|
||||
if (parent_ri->extra)
|
||||
memcpy(&ri->extra->label, &parent_ri->extra->label,
|
||||
BGP_LABEL_BYTES);
|
||||
bgp_info_add(rn, ri);
|
||||
} else {
|
||||
if (attrhash_cmp(ri->attr, parent_ri->attr)
|
||||
&& !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
|
||||
bgp_unlock_node(rn);
|
||||
return 0;
|
||||
}
|
||||
/* The attribute has changed. */
|
||||
/* Add (or update) attribute to hash. */
|
||||
attr_new = bgp_attr_intern(parent_ri->attr);
|
||||
|
||||
/* Restore route, if needed. */
|
||||
if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
|
||||
bgp_info_restore(rn, ri);
|
||||
|
||||
/* Mark if nexthop has changed. */
|
||||
if (!IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop))
|
||||
SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED);
|
||||
|
||||
/* Unintern existing, set to new. */
|
||||
bgp_attr_unintern(&ri->attr);
|
||||
ri->attr = attr_new;
|
||||
ri->uptime = bgp_clock();
|
||||
}
|
||||
|
||||
/* Perform route selection and update zebra, if required. */
|
||||
ret = evpn_vrf_route_select_install(bgp_vrf, rn, pp, afi, safi);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Install route entry into the VNI routing table and invoke route selection.
|
||||
*/
|
||||
@ -1484,6 +1655,61 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Uninstall route entry from the VRF routing table and send message
|
||||
* to zebra, if appropriate.
|
||||
*/
|
||||
static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
|
||||
struct prefix_evpn *evp,
|
||||
struct bgp_info *parent_ri)
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
int ret;
|
||||
struct prefix p;
|
||||
struct prefix *pp = &p;
|
||||
afi_t afi = 0;
|
||||
safi_t safi = 0;
|
||||
|
||||
memset(pp, 0, sizeof(struct prefix));
|
||||
ip_prefix_from_type2_prefix(evp, pp);
|
||||
|
||||
/* Locate route within the VRF. */
|
||||
/* NOTE: There is no RD here. */
|
||||
if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
|
||||
afi = AFI_IP;
|
||||
safi = SAFI_UNICAST;
|
||||
rn = bgp_node_lookup(bgp_vrf->rib[afi][safi], pp);
|
||||
} else {
|
||||
afi = AFI_IP6;
|
||||
safi = SAFI_UNICAST;
|
||||
rn = bgp_node_lookup(bgp_vrf->rib[afi][safi], pp);
|
||||
}
|
||||
|
||||
if (!rn)
|
||||
return 0;
|
||||
|
||||
/* Find matching route entry. */
|
||||
for (ri = rn->info; ri; ri = ri->next)
|
||||
if (ri->extra
|
||||
&& (struct bgp_info *)ri->extra->parent == parent_ri)
|
||||
break;
|
||||
|
||||
if (!ri)
|
||||
return 0;
|
||||
|
||||
/* Mark entry for deletion */
|
||||
bgp_info_delete(rn, ri);
|
||||
|
||||
/* Perform route selection and update zebra, if required. */
|
||||
ret = evpn_vrf_route_select_install(bgp_vrf, rn, pp, afi, safi);
|
||||
|
||||
/* Unlock route node. */
|
||||
bgp_unlock_node(rn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Uninstall route entry from the VNI routing table and send message
|
||||
* to zebra, if appropriate.
|
||||
@ -1706,6 +1932,45 @@ static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Install or uninstall route in matching VRFs (list).
|
||||
*/
|
||||
static int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi,
|
||||
safi_t safi, struct prefix_evpn *evp,
|
||||
struct bgp_info *ri,
|
||||
struct list *vrfs, int install)
|
||||
{
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
struct bgp *bgp_vrf;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
/* Only type-2 routes go into a VRF */
|
||||
if (!(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE))
|
||||
return 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(vrfs, node, nnode, bgp_vrf)) {
|
||||
int ret;
|
||||
|
||||
if (install)
|
||||
ret = install_evpn_route_entry_in_vrf(bgp_vrf,
|
||||
evp, ri);
|
||||
else
|
||||
ret = uninstall_evpn_route_entry_in_vrf(bgp_vrf,
|
||||
evp, ri);
|
||||
|
||||
if (ret) {
|
||||
zlog_err("%u: Failed to %s prefix %s in VRF %s",
|
||||
bgp_def->vrf_id,
|
||||
install ? "install" : "uninstall",
|
||||
prefix2str(evp, buf, sizeof(buf)),
|
||||
vrf_id_to_name(bgp_vrf->vrf_id));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Install or uninstall route in matching VNIs (list).
|
||||
*/
|
||||
@ -1777,7 +2042,8 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
u_char type, sub_type;
|
||||
struct ecommunity_val *eval;
|
||||
struct ecommunity_val eval_tmp;
|
||||
struct irt_node *irt;
|
||||
struct irt_node *irt; /* import rt for l2vni */
|
||||
struct vrf_irt_node *vrf_irt; /* import rt for l3vni */
|
||||
|
||||
/* Only deal with RTs */
|
||||
pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
|
||||
@ -1788,12 +2054,18 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
if (sub_type != ECOMMUNITY_ROUTE_TARGET)
|
||||
continue;
|
||||
|
||||
/* Are we interested in this RT? */
|
||||
/* Import route into matching l2-vnis */
|
||||
irt = lookup_import_rt(bgp, eval);
|
||||
if (irt && irt->vnis)
|
||||
install_uninstall_route_in_vnis(bgp, afi, safi, evp, ri,
|
||||
irt->vnis, import);
|
||||
|
||||
/* Import route into matching l3-vnis (vrfs) */
|
||||
vrf_irt = lookup_vrf_import_rt(eval);
|
||||
if (vrf_irt && vrf_irt->vrfs)
|
||||
install_uninstall_route_in_vrfs(bgp, afi, safi, evp, ri,
|
||||
vrf_irt->vrfs, import);
|
||||
|
||||
/* Also check for non-exact match. In this, we mask out the AS
|
||||
* and
|
||||
* only check on the local-admin sub-field. This is to
|
||||
@ -1801,16 +2073,22 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
* VNI as the RT for EBGP peering too.
|
||||
*/
|
||||
irt = NULL;
|
||||
vrf_irt = NULL;
|
||||
if (type == ECOMMUNITY_ENCODE_AS
|
||||
|| type == ECOMMUNITY_ENCODE_AS4
|
||||
|| type == ECOMMUNITY_ENCODE_IP) {
|
||||
memcpy(&eval_tmp, eval, ECOMMUNITY_SIZE);
|
||||
mask_ecom_global_admin(&eval_tmp, eval);
|
||||
irt = lookup_import_rt(bgp, &eval_tmp);
|
||||
vrf_irt = lookup_vrf_import_rt(&eval_tmp);
|
||||
}
|
||||
if (irt && irt->vnis)
|
||||
install_uninstall_route_in_vnis(bgp, afi, safi, evp, ri,
|
||||
irt->vnis, import);
|
||||
if (vrf_irt && vrf_irt->vrfs)
|
||||
install_uninstall_route_in_vrfs(bgp, afi, safi, evp,
|
||||
ri, vrf_irt->vrfs,
|
||||
import);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -258,6 +258,25 @@ static inline void encode_mac_mobility_extcomm(int static_mac, u_int32_t seq,
|
||||
eval->val[7] = seq & 0xff;
|
||||
}
|
||||
|
||||
static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
|
||||
struct prefix *ip)
|
||||
{
|
||||
memset(ip, 0, sizeof(struct prefix));
|
||||
if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
|
||||
ip->family = AF_INET;
|
||||
ip->prefixlen = IPV4_MAX_BITLEN;
|
||||
memcpy(&(ip->u.prefix4),
|
||||
&(evp->prefix.ip.ip),
|
||||
IPV4_MAX_BYTELEN);
|
||||
} else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
|
||||
ip->family = AF_INET6;
|
||||
ip->prefixlen = IPV6_MAX_BITLEN;
|
||||
memcpy(&(ip->u.prefix6),
|
||||
&(evp->prefix.ip.ip),
|
||||
IPV6_MAX_BYTELEN);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
|
||||
struct ethaddr *mac,
|
||||
struct ipaddr *ip)
|
||||
|
@ -411,6 +411,52 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
|
||||
json_object_object_add(json, "exportRts", json_export_rtl);
|
||||
}
|
||||
|
||||
static void evpn_show_vrf_routes(struct vty *vty,
|
||||
struct bgp *bgp_vrf)
|
||||
{
|
||||
struct bgp *bgp_def = NULL;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
int header = 1;
|
||||
u_int32_t prefix_cnt, path_cnt;
|
||||
|
||||
prefix_cnt = path_cnt = 0;
|
||||
bgp_def = bgp_get_default();
|
||||
if (!bgp_def)
|
||||
return;
|
||||
|
||||
for (rn = bgp_table_top(bgp_vrf->rib[AFI_L2VPN][SAFI_EVPN]); rn;
|
||||
rn = bgp_route_next(rn)) {
|
||||
char prefix_str[BUFSIZ];
|
||||
|
||||
bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
|
||||
sizeof(prefix_str));
|
||||
|
||||
if (rn->info) {
|
||||
/* Overall header/legend displayed once. */
|
||||
if (header) {
|
||||
bgp_evpn_show_route_header(vty, bgp_def, NULL);
|
||||
header = 0;
|
||||
}
|
||||
prefix_cnt++;
|
||||
}
|
||||
|
||||
/* For EVPN, the prefix is displayed for each path (to fit in
|
||||
* with code that already exists).
|
||||
*/
|
||||
for (ri = rn->info; ri; ri = ri->next) {
|
||||
route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, NULL);
|
||||
path_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (prefix_cnt == 0)
|
||||
vty_out(vty, "No EVPN prefixes exist for this VRF");
|
||||
else
|
||||
vty_out(vty, "\nDisplayed %u prefixes (%u paths)",
|
||||
prefix_cnt, path_cnt);
|
||||
}
|
||||
|
||||
static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
|
||||
struct vty *vty, struct in_addr vtep_ip,
|
||||
json_object *json)
|
||||
@ -2640,6 +2686,33 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display per-VRF EVPN routing table.
|
||||
*/
|
||||
DEFUN(show_bgp_l2vpn_evpn_route_vrf, show_bgp_l2vpn_evpn_route_vrf_cmd,
|
||||
"show bgp l2vpn evpn route vrf VRFNAME",
|
||||
SHOW_STR
|
||||
BGP_STR
|
||||
L2VPN_HELP_STR
|
||||
EVPN_HELP_STR
|
||||
"EVPN route information\n"
|
||||
"VRF\n"
|
||||
"VRF Name\n")
|
||||
{
|
||||
int vrf_idx = 6;
|
||||
char *vrf_name = NULL;
|
||||
struct bgp *bgp_vrf = NULL;
|
||||
|
||||
vrf_name = argv[vrf_idx]->arg;
|
||||
bgp_vrf = bgp_lookup_by_name(vrf_name);
|
||||
if (!bgp_vrf)
|
||||
return CMD_WARNING;
|
||||
|
||||
evpn_show_vrf_routes(vty, bgp_vrf);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display per-VNI EVPN routing table.
|
||||
*/
|
||||
@ -3697,6 +3770,7 @@ void bgp_ethernetvpn_init(void)
|
||||
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
|
||||
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
|
||||
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
|
||||
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vrf_cmd);
|
||||
install_element(VIEW_NODE,
|
||||
&show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
|
||||
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
|
||||
|
@ -1015,6 +1015,12 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
if (info->sub_type == BGP_ROUTE_AGGREGATE)
|
||||
zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
|
||||
|
||||
/* If it is an EVPN route mark as such.
|
||||
* Currently presence of rmac in attr denotes
|
||||
* this is an EVPN type-2 route */
|
||||
if (!is_zero_mac(&(info->attr->rmac)))
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_EVPN_TYPE2_ROUTE);
|
||||
|
||||
if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
|
||||
|| info->sub_type == BGP_ROUTE_AGGREGATE) {
|
||||
SET_FLAG(api.flags, ZEBRA_FLAG_IBGP);
|
||||
@ -1072,7 +1078,13 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||
|
||||
api_nh = &api.nexthops[valid_nh_count];
|
||||
api_nh->gate.ipv4 = *nexthop;
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4;
|
||||
|
||||
/* EVPN type-2 routes are
|
||||
programmed as onlink on l3-vni SVI */
|
||||
if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_TYPE2_ROUTE))
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
|
||||
else
|
||||
api_nh->type = NEXTHOP_TYPE_IPV4;
|
||||
} else {
|
||||
ifindex_t ifindex;
|
||||
struct in6_addr *nexthop;
|
||||
|
@ -409,6 +409,7 @@ extern const char *zserv_command_string(unsigned int command);
|
||||
#define ZEBRA_FLAG_STATIC 0x40
|
||||
#define ZEBRA_FLAG_SCOPE_LINK 0x100
|
||||
#define ZEBRA_FLAG_FIB_OVERRIDE 0x200
|
||||
#define ZEBRA_FLAG_EVPN_TYPE2_ROUTE 0x400
|
||||
/* ZEBRA_FLAG_BLACKHOLE was 0x04 */
|
||||
/* ZEBRA_FLAG_REJECT was 0x80 */
|
||||
|
||||
|
@ -259,7 +259,8 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
|
||||
/*Pending: need to think if null ifp here is ok during bootup?
|
||||
There was a crash because ifp here was coming to be NULL */
|
||||
if (ifp)
|
||||
if (connected_is_unnumbered(ifp)) {
|
||||
if (connected_is_unnumbered(ifp) ||
|
||||
CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_TYPE2_ROUTE)) {
|
||||
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
|
||||
}
|
||||
|
||||
|
@ -6084,3 +6084,15 @@ void zebra_vxlan_ns_disable(struct zebra_ns *zns)
|
||||
{
|
||||
hash_free(zns->l3vni_table);
|
||||
}
|
||||
|
||||
/* get the l3vni svi ifindex */
|
||||
ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
|
||||
{
|
||||
zebra_l3vni_t *zl3vni = NULL;
|
||||
|
||||
zl3vni = zl3vni_from_vrf(vrf_id);
|
||||
if (!zl3vni || !is_l3vni_oper_up(zl3vni))
|
||||
return 0;
|
||||
|
||||
return zl3vni->svi_if->ifindex;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ is_evpn_enabled()
|
||||
|
||||
#define VNI_STR_LEN 32
|
||||
|
||||
extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id);
|
||||
extern int zebra_vxlan_vrf_delete(struct zebra_vrf *);
|
||||
extern void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
|
||||
vni_t vni, u_char use_json);
|
||||
|
@ -1149,6 +1149,7 @@ static int zread_route_add(struct zserv *client, u_short length,
|
||||
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
|
||||
for (i = 0; i < api.nexthop_num; i++) {
|
||||
api_nh = &api.nexthops[i];
|
||||
ifindex_t ifindex = 0;
|
||||
|
||||
switch (api_nh->type) {
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
@ -1160,9 +1161,16 @@ static int zread_route_add(struct zserv *client, u_short length,
|
||||
re, &api_nh->gate.ipv4, NULL);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
if (CHECK_FLAG(api.flags,
|
||||
ZEBRA_FLAG_EVPN_TYPE2_ROUTE)) {
|
||||
ifindex =
|
||||
get_l3vni_svi_ifindex(zvrf_id(zvrf));
|
||||
} else {
|
||||
ifindex = api_nh->ifindex;
|
||||
}
|
||||
nexthop = route_entry_nexthop_ipv4_ifindex_add(
|
||||
re, &api_nh->gate.ipv4, NULL,
|
||||
api_nh->ifindex);
|
||||
ifindex);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
nexthop = route_entry_nexthop_ipv6_add(
|
||||
|
Loading…
Reference in New Issue
Block a user