mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-01-04 22:08:37 +00:00
bgpd: advertise/withdraw type-5 routes upon user config
CLI config for enabling/disabling type-5 routes
router bgp <as> vrf <vrf>
address-family l2vpn evpn
[no] advertise <ipv4|ipv6|both>
loop through all the routes in VRF instance and advertise/withdraw
all ip routes as type-5 routes in default instance.
Signed-off-by: Mitesh Kanjariya <mitesh@cumulusnetworks.com>
This commit is contained in:
parent
b67a60d2cf
commit
342dd0c623
263
bgpd/bgp_evpn.c
263
bgpd/bgp_evpn.c
@ -601,6 +601,52 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
return zclient_send_message(zclient);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build extended communities for EVPN prefix route.
|
||||
*/
|
||||
static void build_evpn_type5_route_extcomm(struct bgp *bgp_vrf,
|
||||
struct attr *attr)
|
||||
{
|
||||
struct ecommunity ecom_encap;
|
||||
struct ecommunity ecom_rmac;
|
||||
struct ecommunity_val eval;
|
||||
struct ecommunity_val eval_rmac;
|
||||
bgp_encap_types tnl_type;
|
||||
struct listnode *node, *nnode;
|
||||
struct ecommunity *ecom;
|
||||
struct list *vrf_export_rtl = NULL;
|
||||
|
||||
/* Encap */
|
||||
tnl_type = BGP_ENCAP_TYPE_VXLAN;
|
||||
memset(&ecom_encap, 0, sizeof(ecom_encap));
|
||||
encode_encap_extcomm(tnl_type, &eval);
|
||||
ecom_encap.size = 1;
|
||||
ecom_encap.val = (u_int8_t *)eval.val;
|
||||
|
||||
/* Add Encap */
|
||||
attr->ecommunity = ecommunity_dup(&ecom_encap);
|
||||
|
||||
/* Add the export RTs for L3VNI/VRF */
|
||||
vrf_export_rtl = bgp_vrf->vrf_export_rtl;
|
||||
if (vrf_export_rtl && !list_isempty(vrf_export_rtl)) {
|
||||
for (ALL_LIST_ELEMENTS(vrf_export_rtl, node, nnode, ecom))
|
||||
attr->ecommunity = ecommunity_merge(attr->ecommunity,
|
||||
ecom);
|
||||
}
|
||||
|
||||
/* add the router mac extended community */
|
||||
if (!is_zero_mac(&attr->rmac)) {
|
||||
memset(&ecom_rmac, 0, sizeof(ecom_rmac));
|
||||
encode_rmac_extcomm(&eval_rmac, &attr->rmac);
|
||||
ecom_rmac.size = 1;
|
||||
ecom_rmac.val = (uint8_t *)eval_rmac.val;
|
||||
attr->ecommunity = ecommunity_merge(attr->ecommunity,
|
||||
&ecom_rmac);
|
||||
}
|
||||
|
||||
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build extended communities for EVPN route. RT and ENCAP are
|
||||
* applicable to all routes.
|
||||
@ -907,6 +953,112 @@ static int evpn_route_is_sticky(struct bgp *bgp, struct bgp_node *rn)
|
||||
return local_ri->attr->sticky;
|
||||
}
|
||||
|
||||
static int update_evpn_type5_route_entry(struct bgp *bgp_def,
|
||||
struct bgp *bgp_vrf, afi_t afi,
|
||||
safi_t safi, struct bgp_node *rn,
|
||||
struct attr *attr)
|
||||
{
|
||||
struct attr *attr_new = NULL;
|
||||
struct bgp_info *ri = NULL;
|
||||
mpls_label_t label = MPLS_INVALID_LABEL;
|
||||
struct bgp_info *local_ri = NULL;
|
||||
struct bgp_info *tmp_ri = NULL;
|
||||
|
||||
|
||||
/* locate the local route entry if any */
|
||||
for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) {
|
||||
if (tmp_ri->peer == bgp_def->peer_self
|
||||
&& tmp_ri->type == ZEBRA_ROUTE_BGP
|
||||
&& tmp_ri->sub_type == BGP_ROUTE_STATIC)
|
||||
local_ri = tmp_ri;
|
||||
}
|
||||
|
||||
/* create a new route entry if one doesnt exist.
|
||||
Otherwise see if route attr has changed */
|
||||
if (!local_ri) {
|
||||
|
||||
/* Add (or update) attribute to hash. */
|
||||
attr_new = bgp_attr_intern(attr);
|
||||
|
||||
/* create the route info from attribute */
|
||||
ri = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0,
|
||||
bgp_def->peer_self, attr_new, rn);
|
||||
SET_FLAG(ri->flags, BGP_INFO_VALID);
|
||||
|
||||
/* L3-VNI goes in the label2 field */
|
||||
bgp_info_extra_get(ri);
|
||||
vni2label(bgp_vrf->l3vni, &label);
|
||||
memcpy(&ri->extra->label2, &label, BGP_LABEL_BYTES);
|
||||
|
||||
/* add the route entry to route node*/
|
||||
bgp_info_add(rn, ri);
|
||||
} else {
|
||||
|
||||
tmp_ri = local_ri;
|
||||
if (!attrhash_cmp(tmp_ri->attr, attr)) {
|
||||
/* The attribute has changed. */
|
||||
/* Add (or update) attribute to hash. */
|
||||
attr_new = bgp_attr_intern(attr);
|
||||
bgp_info_set_flag(rn, tmp_ri, BGP_INFO_ATTR_CHANGED);
|
||||
|
||||
/* Restore route, if needed. */
|
||||
if (CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED))
|
||||
bgp_info_restore(rn, tmp_ri);
|
||||
|
||||
/* Unintern existing, set to new. */
|
||||
bgp_attr_unintern(&tmp_ri->attr);
|
||||
tmp_ri->attr = attr_new;
|
||||
tmp_ri->uptime = bgp_clock();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* update evpn type-5 route entry */
|
||||
static int update_evpn_type5_route(struct bgp *bgp_vrf,
|
||||
struct prefix_evpn *evp)
|
||||
{
|
||||
afi_t afi = AFI_L2VPN;
|
||||
safi_t safi = SAFI_EVPN;
|
||||
struct attr attr;
|
||||
struct bgp_node *rn = NULL;
|
||||
struct bgp *bgp_def = NULL;
|
||||
|
||||
bgp_def = bgp_get_default();
|
||||
if (!bgp_def)
|
||||
return -1;
|
||||
|
||||
/* build path attribute for this route */
|
||||
memset(&attr, 0, sizeof(struct attr));
|
||||
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
|
||||
attr.nexthop = bgp_vrf->originator_ip;
|
||||
attr.mp_nexthop_global_in = bgp_vrf->originator_ip;
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
memcpy(&attr.rmac, &bgp_vrf->rmac, sizeof(struct ethaddr));
|
||||
|
||||
/* Setup RT and encap extended community */
|
||||
build_evpn_type5_route_extcomm(bgp_vrf, &attr);
|
||||
|
||||
/* get the route node in global table */
|
||||
rn = bgp_afi_node_get(bgp_def->rib[afi][safi], afi, safi,
|
||||
(struct prefix *)evp,
|
||||
&bgp_vrf->vrf_prd);
|
||||
assert(rn);
|
||||
|
||||
/* create or update the route entry within the route node */
|
||||
update_evpn_type5_route_entry(bgp_def, bgp_vrf,
|
||||
afi, safi,
|
||||
rn, &attr);
|
||||
|
||||
/* schedule for processing and unlock node */
|
||||
bgp_process(bgp_def, rn, afi, safi);
|
||||
bgp_unlock_node(rn);
|
||||
|
||||
/* uninten temporary */
|
||||
aspath_unintern(&attr.aspath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create or update EVPN route entry. This could be in the VNI route table
|
||||
* or the global route table.
|
||||
@ -1089,6 +1241,58 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Delete EVPN type5 route entry from global table */
|
||||
static void delete_evpn_type5_route_entry(struct bgp *bgp_def,
|
||||
struct bgp *bgp_vrf,
|
||||
afi_t afi, safi_t safi,
|
||||
struct bgp_node *rn,
|
||||
struct bgp_info **ri)
|
||||
{
|
||||
struct bgp_info *tmp_ri = NULL;
|
||||
|
||||
*ri = NULL;
|
||||
|
||||
/* find the matching route entry */
|
||||
for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next)
|
||||
if (tmp_ri->peer == bgp_def->peer_self
|
||||
&& tmp_ri->type == ZEBRA_ROUTE_BGP
|
||||
&& tmp_ri->sub_type == BGP_ROUTE_STATIC)
|
||||
break;
|
||||
|
||||
*ri = tmp_ri;
|
||||
|
||||
/* Mark route for delete. */
|
||||
if (tmp_ri)
|
||||
bgp_info_delete(rn, tmp_ri);
|
||||
}
|
||||
|
||||
/* Delete EVPN type5 route */
|
||||
static int delete_evpn_type5_route(struct bgp *bgp_vrf,
|
||||
struct prefix_evpn *evp)
|
||||
{
|
||||
afi_t afi = AFI_L2VPN;
|
||||
safi_t safi = SAFI_EVPN;
|
||||
struct bgp_node *rn = NULL;
|
||||
struct bgp_info *ri = NULL;
|
||||
struct bgp *bgp_def = NULL; /* default bgp instance */
|
||||
|
||||
bgp_def = bgp_get_default();
|
||||
if (!bgp_def)
|
||||
return -1;
|
||||
|
||||
/* locate the global route entry for this type-5 prefix */
|
||||
rn = bgp_afi_node_lookup(bgp_def->rib[afi][safi], afi, safi,
|
||||
(struct prefix *)evp, &bgp_vrf->vrf_prd);
|
||||
if (!rn)
|
||||
return 0;
|
||||
|
||||
delete_evpn_type5_route_entry(bgp_def, bgp_vrf, afi, safi, rn, &ri);
|
||||
if (ri)
|
||||
bgp_process(bgp_def, rn, afi, safi);
|
||||
bgp_unlock_node(rn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete EVPN route entry. This could be in the VNI route table
|
||||
* or the global route table.
|
||||
@ -2804,6 +3008,58 @@ static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf)
|
||||
* Public functions.
|
||||
*/
|
||||
|
||||
/* withdraw all type-5 routes for an address family */
|
||||
void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf,
|
||||
afi_t afi)
|
||||
{
|
||||
struct bgp_table *table = NULL;
|
||||
struct bgp_node *rn = NULL;
|
||||
|
||||
table = bgp_vrf->rib[afi][SAFI_UNICAST];
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
|
||||
|
||||
int ret = 0;
|
||||
struct prefix_evpn evp;
|
||||
char buf[PREFIX_STRLEN];
|
||||
|
||||
build_type5_prefix_from_ip_prefix(&evp, &rn->p);
|
||||
ret = delete_evpn_type5_route(bgp_vrf, &evp);
|
||||
if (ret) {
|
||||
zlog_err(
|
||||
"%u failed to delete type-5 route for prefix %s in vrf %s",
|
||||
bgp_vrf->vrf_id,
|
||||
prefix2str(&rn->p, buf, sizeof(buf)),
|
||||
vrf_id_to_name(bgp_vrf->vrf_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* advertise all type-5 routes for an address family */
|
||||
void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf,
|
||||
afi_t afi)
|
||||
{
|
||||
struct bgp_table *table = NULL;
|
||||
struct bgp_node *rn = NULL;
|
||||
|
||||
table = bgp_vrf->rib[afi][SAFI_UNICAST];
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
|
||||
|
||||
int ret = 0;
|
||||
struct prefix_evpn evp;
|
||||
char buf[PREFIX_STRLEN];
|
||||
|
||||
build_type5_prefix_from_ip_prefix(&evp, &rn->p);
|
||||
ret = update_evpn_type5_route(bgp_vrf, &evp);
|
||||
if (ret) {
|
||||
zlog_err(
|
||||
"%u failed to create type-5 route for prefix %s in vrf %s",
|
||||
bgp_vrf->vrf_id,
|
||||
prefix2str(&rn->p, buf, sizeof(buf)),
|
||||
vrf_id_to_name(bgp_vrf->vrf_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void evpn_rt_delete_auto(struct bgp *bgp, vni_t vni,
|
||||
struct list *rtl)
|
||||
{
|
||||
@ -3128,6 +3384,13 @@ char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len)
|
||||
inet_ntop(family, &p->prefix.ip.ip.addr, buf2,
|
||||
PREFIX2STR_BUFFER));
|
||||
}
|
||||
} else if (p->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) {
|
||||
snprintf(buf, len, "[%d]:[0]:[%d]:[%s]",
|
||||
p->prefix.route_type,
|
||||
p->prefix.ip_prefix_length,
|
||||
IS_EVPN_PREFIX_IPADDR_V4(p) ?
|
||||
inet_ntoa(p->prefix.ip.ipaddr_v4) :
|
||||
inet6_ntoa(p->prefix.ip.ipaddr_v6));
|
||||
} else {
|
||||
/* For EVPN route types not supported yet. */
|
||||
snprintf(buf, len, "(unsupported route type %d)",
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
|
||||
#define EVPN_ROUTE_STRLEN 200 /* Must be >> MAC + IPv6 strings. */
|
||||
|
||||
extern void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi);
|
||||
extern void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi);
|
||||
extern void bgp_evpn_vrf_delete(struct bgp *);
|
||||
extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw);
|
||||
extern char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len);
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
/* EVPN prefix lengths. */
|
||||
#define EVPN_TYPE_2_ROUTE_PREFIXLEN 224
|
||||
#define EVPN_TYPE_3_ROUTE_PREFIXLEN 224
|
||||
#define EVPN_TYPE_5_ROUTE_PREFIXLEN 168
|
||||
|
||||
/* EVPN route types. */
|
||||
typedef enum {
|
||||
@ -128,11 +129,14 @@ static inline int bgp_evpn_vrf_rd_matches_existing(struct bgp *bgp_vrf,
|
||||
|
||||
static inline int is_evpn_prefix_routes_adv_enabled(struct bgp *bgp_vrf)
|
||||
{
|
||||
if (!bgp_vrf->l3vni ||
|
||||
!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_EVPN_PREFIX_ROUTE))
|
||||
if (!bgp_vrf->l3vni)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
if (CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN) ||
|
||||
CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline vni_t bgpevpn_get_l3vni(struct bgpevpn *vpn)
|
||||
@ -312,6 +316,31 @@ static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
|
||||
memcpy(&p->prefix.ip, ip, sizeof(*ip));
|
||||
}
|
||||
|
||||
static inline void build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp,
|
||||
struct prefix *ip_prefix)
|
||||
{
|
||||
struct ipaddr ip;
|
||||
|
||||
memset(&ip, 0, sizeof(struct ipaddr));
|
||||
if (ip_prefix->family == AF_INET) {
|
||||
ip.ipa_type = IPADDR_V4;
|
||||
memcpy(&ip.ipaddr_v4, &ip_prefix->u.prefix4,
|
||||
sizeof(struct in_addr));
|
||||
} else {
|
||||
ip.ipa_type = IPADDR_V6;
|
||||
memcpy(&ip.ipaddr_v6, &ip_prefix->u.prefix6,
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
memset(evp, 0, sizeof(struct prefix_evpn));
|
||||
evp->family = AF_EVPN;
|
||||
evp->prefixlen = EVPN_TYPE_5_ROUTE_PREFIXLEN;
|
||||
evp->prefix.ip_prefix_length = ip_prefix->prefixlen;
|
||||
evp->prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE;
|
||||
evp->prefix.ip.ipa_type = ip.ipa_type;
|
||||
memcpy(&evp->prefix.ip, &ip, sizeof(struct ipaddr));
|
||||
}
|
||||
|
||||
static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
|
||||
struct in_addr originator_ip)
|
||||
{
|
||||
|
||||
@ -1978,11 +1978,11 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
|
||||
/* RD header and legend - once overall. */
|
||||
if (rd_header && !json) {
|
||||
vty_out(vty,
|
||||
"EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
|
||||
"[MAC]\n");
|
||||
"EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]\n");
|
||||
vty_out(vty,
|
||||
"EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:"
|
||||
"[OrigIP]\n\n");
|
||||
"EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
|
||||
vty_out(vty,
|
||||
"EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
|
||||
rd_header = 0;
|
||||
}
|
||||
|
||||
@ -2440,6 +2440,105 @@ DEFUN (no_bgp_evpn_advertise_all_vni,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (bgp_evpn_advertise_type5,
|
||||
bgp_evpn_advertise_type5_cmd,
|
||||
"advertise <ipv4|ipv6|both>",
|
||||
"Advertise prefix routes\n"
|
||||
"advertise ipv4 prefix only\n"
|
||||
"advertise ipv6 prefix only\n"
|
||||
"advertise both ipv4/ipv6 prefix\n")
|
||||
{
|
||||
struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
|
||||
uint32_t type = 0;
|
||||
|
||||
if (strcmp(argv[1]->text, "ipv4")) {
|
||||
type = BGP_VRF_ADVERTISE_IPV4_IN_EVPN;
|
||||
} else if (strcmp(argv[1]->text, "ipv6")) {
|
||||
type = BGP_VRF_ADVERTISE_IPV4_IN_EVPN;
|
||||
} else if (strcmp(argv[1]->text, "both")) {
|
||||
type = BGP_VRF_ADVERTISE_IPV4_IN_EVPN |
|
||||
BGP_VRF_ADVERTISE_IPV6_IN_EVPN;
|
||||
} else {
|
||||
vty_out(vty, "%%invalid command");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(type, BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
|
||||
|
||||
/* if we are already advertising ipv4 prefix as type-5
|
||||
* nothing to do */
|
||||
if (!CHECK_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
|
||||
SET_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
|
||||
bgp_evpn_advertise_type5_routes(bgp_vrf,
|
||||
AFI_IP);
|
||||
}
|
||||
} else {
|
||||
|
||||
/* if we are already advertising ipv6 prefix as type-5
|
||||
* nothing to do */
|
||||
if (!CHECK_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) {
|
||||
SET_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV6_IN_EVPN);
|
||||
bgp_evpn_advertise_type5_routes(bgp_vrf,
|
||||
AFI_IP6);
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_bgp_evpn_advertise_type5,
|
||||
no_bgp_evpn_advertise_type5_cmd,
|
||||
"no advertise <ipv4|ipv6|both>",
|
||||
NO_STR
|
||||
"Advertise prefix routes\n"
|
||||
"advertise ipv4 prefix only\n"
|
||||
"advertise ipv6 prefix only\n"
|
||||
"advertise both ipv4/ipv6 prefix\n")
|
||||
{
|
||||
struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
|
||||
uint32_t type = 0;
|
||||
|
||||
if (strcmp(argv[1]->text, "ipv4")) {
|
||||
type = BGP_VRF_ADVERTISE_IPV4_IN_EVPN;
|
||||
} else if (strcmp(argv[1]->text, "ipv6")) {
|
||||
type = BGP_VRF_ADVERTISE_IPV4_IN_EVPN;
|
||||
} else if (strcmp(argv[1]->text, "both")) {
|
||||
type = BGP_VRF_ADVERTISE_IPV4_IN_EVPN |
|
||||
BGP_VRF_ADVERTISE_IPV6_IN_EVPN;
|
||||
} else {
|
||||
vty_out(vty, "%%invalid command");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(type, BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
|
||||
|
||||
/* if we are already advertising ipv4 prefix as type-5
|
||||
* nothing to do */
|
||||
if (CHECK_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
|
||||
bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP);
|
||||
UNSET_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
|
||||
}
|
||||
} else {
|
||||
|
||||
/* if we are already advertising ipv6 prefix as type-5
|
||||
* nothing to do */
|
||||
if (CHECK_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) {
|
||||
bgp_evpn_withdraw_type5_routes(bgp_vrf,
|
||||
AFI_IP6);
|
||||
UNSET_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV6_IN_EVPN);
|
||||
}
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display VNI information - for all or a specific VNI
|
||||
*/
|
||||
@ -3955,6 +4054,8 @@ void bgp_ethernetvpn_init(void)
|
||||
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
|
||||
install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
|
||||
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
|
||||
install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
|
||||
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
|
||||
|
||||
/* "show bgp l2vpn evpn" commands. */
|
||||
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
|
||||
|
||||
@ -73,9 +73,12 @@ struct bgp_info_extra {
|
||||
/* Nexthop reachability check. */
|
||||
u_int32_t igpmetric;
|
||||
|
||||
/* MPLS label. */
|
||||
/* MPLS label - L2VNI */
|
||||
mpls_label_t label;
|
||||
|
||||
/* MPLS label - L3-VNI */
|
||||
mpls_label_t label2;
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
union {
|
||||
|
||||
|
||||
@ -424,10 +424,11 @@ struct bgp {
|
||||
/* vrf flags */
|
||||
uint32_t vrf_flags;
|
||||
#define BGP_VRF_AUTO (1 << 0)
|
||||
#define BGP_VRF_ADVERTISE_EVPN_PREFIX_ROUTE (1 << 1)
|
||||
#define BGP_VRF_IMPORT_RT_CFGD (1 << 2)
|
||||
#define BGP_VRF_EXPORT_RT_CFGD (1 << 3)
|
||||
#define BGP_VRF_RD_CFGD (1 << 4)
|
||||
#define BGP_VRF_ADVERTISE_IPV4_IN_EVPN (1 << 1)
|
||||
#define BGP_VRF_ADVERTISE_IPV6_IN_EVPN (1 << 2)
|
||||
#define BGP_VRF_IMPORT_RT_CFGD (1 << 3)
|
||||
#define BGP_VRF_EXPORT_RT_CFGD (1 << 4)
|
||||
#define BGP_VRF_RD_CFGD (1 << 5)
|
||||
|
||||
/* unique ID for auto derivation of RD for this vrf */
|
||||
uint16_t vrf_rd_id;
|
||||
|
||||
@ -1043,10 +1043,11 @@ static const char *prefixevpn2str(const struct prefix *p, char *str, int size)
|
||||
family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)
|
||||
? AF_INET
|
||||
: AF_INET6;
|
||||
snprintf(str, size, "[%d]:[%u][%s]/%d",
|
||||
snprintf(str, size, "[%d]:[%u][%s/%d]/%d",
|
||||
p->u.prefix_evpn.route_type, p->u.prefix_evpn.eth_tag,
|
||||
inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, buf,
|
||||
PREFIX2STR_BUFFER),
|
||||
p->u.prefix_evpn.ip_prefix_length,
|
||||
p->prefixlen);
|
||||
} else {
|
||||
sprintf(str, "Unsupported EVPN route type %d",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user