mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 12:15:33 +00:00
commit
f894c3b2ea
@ -1283,8 +1283,14 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
|
||||
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
attr.sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY) ? 1 : 0;
|
||||
attr.default_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW) ? 1 : 0;
|
||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
|
||||
bgpevpn_get_rmac(vpn, &attr.rmac);
|
||||
|
||||
/* PMSI is only needed for type-3 routes */
|
||||
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE)
|
||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
|
||||
|
||||
/* router mac is only needed for type-2 and type-5 routes */
|
||||
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
|
||||
bgpevpn_get_rmac(vpn, &attr.rmac);
|
||||
vni2label(vpn->vni, &(attr.label));
|
||||
|
||||
/* Set up RT and ENCAP extended community. */
|
||||
|
@ -64,6 +64,8 @@ struct bgpevpn {
|
||||
#define VNI_FLAG_USE_TWO_LABELS 0x20 /* Attach both L2-VNI and L3-VNI if
|
||||
needed for this VPN */
|
||||
|
||||
struct bgp *bgp_vrf; /* back pointer to the vrf instance */
|
||||
|
||||
/* Flag to indicate if we are advertising the g/w mac ip for this VNI*/
|
||||
u_int8_t advertise_gw_macip;
|
||||
|
||||
@ -134,77 +136,66 @@ static inline int bgp_evpn_vrf_rd_matches_existing(struct bgp *bgp_vrf,
|
||||
|
||||
static inline vni_t bgpevpn_get_l3vni(struct bgpevpn *vpn)
|
||||
{
|
||||
struct bgp *bgp_vrf = NULL;
|
||||
|
||||
bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
|
||||
if (!bgp_vrf)
|
||||
return 0;
|
||||
|
||||
return bgp_vrf->l3vni;
|
||||
return vpn->bgp_vrf ? vpn->bgp_vrf->l3vni : 0;
|
||||
}
|
||||
|
||||
static inline void bgpevpn_get_rmac(struct bgpevpn *vpn, struct ethaddr *rmac)
|
||||
{
|
||||
struct bgp *bgp_vrf = NULL;
|
||||
|
||||
memset(rmac, 0, sizeof(struct ethaddr));
|
||||
bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
|
||||
if (!bgp_vrf)
|
||||
if (!vpn->bgp_vrf)
|
||||
return;
|
||||
memcpy(rmac, &bgp_vrf->rmac, sizeof(struct ethaddr));
|
||||
memcpy(rmac, &vpn->bgp_vrf->rmac, sizeof(struct ethaddr));
|
||||
}
|
||||
|
||||
static inline struct list *bgpevpn_get_vrf_export_rtl(struct bgpevpn *vpn)
|
||||
{
|
||||
struct bgp *bgp_vrf = NULL;
|
||||
|
||||
bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
|
||||
if (!bgp_vrf)
|
||||
if (!vpn->bgp_vrf)
|
||||
return NULL;
|
||||
|
||||
return bgp_vrf->vrf_export_rtl;
|
||||
return vpn->bgp_vrf->vrf_export_rtl;
|
||||
}
|
||||
|
||||
static inline struct list *bgpevpn_get_vrf_import_rtl(struct bgpevpn *vpn)
|
||||
{
|
||||
struct bgp *bgp_vrf = NULL;
|
||||
|
||||
bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
|
||||
if (!bgp_vrf)
|
||||
if (!vpn->bgp_vrf)
|
||||
return NULL;
|
||||
|
||||
return bgp_vrf->vrf_import_rtl;
|
||||
return vpn->bgp_vrf->vrf_import_rtl;
|
||||
}
|
||||
|
||||
static inline void bgpevpn_unlink_from_l3vni(struct bgpevpn *vpn)
|
||||
{
|
||||
struct bgp *bgp_vrf = NULL;
|
||||
|
||||
bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
|
||||
if (!bgp_vrf)
|
||||
/* bail if vpn is not associated to bgp_vrf */
|
||||
if (!vpn->bgp_vrf)
|
||||
return;
|
||||
|
||||
|
||||
UNSET_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS);
|
||||
|
||||
if (bgp_vrf->l2vnis)
|
||||
listnode_delete(bgp_vrf->l2vnis, vpn);
|
||||
listnode_delete(vpn->bgp_vrf->l2vnis, vpn);
|
||||
|
||||
/* remove the backpointer to the vrf instance */
|
||||
vpn->bgp_vrf = NULL;
|
||||
}
|
||||
|
||||
static inline void bgpevpn_link_to_l3vni(struct bgpevpn *vpn)
|
||||
{
|
||||
struct bgp *bgp_vrf = NULL;
|
||||
|
||||
/* bail if vpn is already associated to vrf */
|
||||
if (vpn->bgp_vrf)
|
||||
return;
|
||||
|
||||
bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
|
||||
if (!bgp_vrf)
|
||||
return;
|
||||
|
||||
/* associate the vpn to the bgp_vrf instance */
|
||||
vpn->bgp_vrf = bgp_vrf;
|
||||
listnode_add_sort(bgp_vrf->l2vnis, vpn);
|
||||
|
||||
/* check if we are advertising two labels for this vpn */
|
||||
if (!CHECK_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY))
|
||||
SET_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS);
|
||||
|
||||
if (bgp_vrf->l2vnis)
|
||||
listnode_add_sort(bgp_vrf->l2vnis, vpn);
|
||||
}
|
||||
|
||||
static inline int is_vni_configured(struct bgpevpn *vpn)
|
||||
|
@ -491,53 +491,6 @@ 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;
|
||||
struct bgp_table *table;
|
||||
|
||||
prefix_cnt = path_cnt = 0;
|
||||
bgp_def = bgp_get_default();
|
||||
if (!bgp_def)
|
||||
return;
|
||||
|
||||
table = (struct bgp_table *)bgp_vrf->rib[AFI_L2VPN][SAFI_EVPN];
|
||||
for (rn = bgp_table_top(table); 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)
|
||||
@ -2967,16 +2920,23 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
|
||||
*/
|
||||
DEFUN(show_bgp_l2vpn_evpn_summary,
|
||||
show_bgp_l2vpn_evpn_summary_cmd,
|
||||
"show bgp l2vpn evpn summary [json]",
|
||||
"show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
|
||||
SHOW_STR
|
||||
BGP_STR
|
||||
"bgp vrf\n"
|
||||
"vrf name\n"
|
||||
L2VPN_HELP_STR
|
||||
EVPN_HELP_STR
|
||||
"Summary of BGP neighbor status\n"
|
||||
JSON_STR)
|
||||
{
|
||||
int idx_vrf = 0;
|
||||
u_char uj = use_json(argc, argv);
|
||||
return bgp_show_summary_vty(vty, NULL, AFI_L2VPN, SAFI_EVPN, uj);
|
||||
char *vrf = NULL;
|
||||
|
||||
if (argv_find(argv, argc, "vrf", &idx_vrf))
|
||||
vrf = argv[++idx_vrf]->arg;
|
||||
return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, uj);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3183,33 +3143,6 @@ 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.
|
||||
*/
|
||||
@ -4377,6 +4310,8 @@ DEFUN (no_bgp_evpn_vni_rt_without_val,
|
||||
void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
char buf1[RD_ADDRSTRLEN];
|
||||
|
||||
if (bgp->vnihash)
|
||||
hash_iterate(bgp->vnihash,
|
||||
(void (*)(struct hash_backet *,
|
||||
@ -4394,6 +4329,42 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
|
||||
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
|
||||
vty_out(vty, " advertise ipv6 unicast\n");
|
||||
|
||||
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
|
||||
vty_out(vty, " rd %s\n",
|
||||
prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
|
||||
|
||||
/* import route-target */
|
||||
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
|
||||
char *ecom_str;
|
||||
struct listnode *node, *nnode;
|
||||
struct ecommunity *ecom;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
|
||||
ecom)) {
|
||||
ecom_str = ecommunity_ecom2str(
|
||||
ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
vty_out(vty, " route-target import %s\n",
|
||||
ecom_str);
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
}
|
||||
|
||||
/* export route-target */
|
||||
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
|
||||
char *ecom_str;
|
||||
struct listnode *node, *nnode;
|
||||
struct ecommunity *ecom;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
|
||||
ecom)) {
|
||||
ecom_str = ecommunity_ecom2str(
|
||||
ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
vty_out(vty, " route-target export %s\n",
|
||||
ecom_str);
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bgp_ethernetvpn_init(void)
|
||||
@ -4431,7 +4402,6 @@ 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);
|
||||
|
@ -7278,8 +7278,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
|
||||
safi = SAFI_MAX;
|
||||
}
|
||||
afi++;
|
||||
if (!afi_wildcard
|
||||
|| afi == AFI_L2VPN) /* special case, not handled yet */
|
||||
if (!afi_wildcard)
|
||||
afi = AFI_MAX;
|
||||
}
|
||||
|
||||
|
32
bgpd/bgpd.c
32
bgpd/bgpd.c
@ -7400,38 +7400,6 @@ int bgp_config_write(struct vty *vty)
|
||||
if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
|
||||
vty_out(vty, " no auto-summary\n");
|
||||
|
||||
/* import route-target */
|
||||
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
|
||||
char *ecom_str;
|
||||
struct listnode *node, *nnode;
|
||||
struct ecommunity *ecom;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
|
||||
ecom)) {
|
||||
ecom_str = ecommunity_ecom2str(
|
||||
ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
vty_out(vty, " route-target import %s\n",
|
||||
ecom_str);
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
}
|
||||
|
||||
/* export route-target */
|
||||
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
|
||||
char *ecom_str;
|
||||
struct listnode *node, *nnode;
|
||||
struct ecommunity *ecom;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
|
||||
ecom)) {
|
||||
ecom_str = ecommunity_ecom2str(
|
||||
ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
|
||||
vty_out(vty, " route-target export %s\n",
|
||||
ecom_str);
|
||||
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
|
||||
}
|
||||
}
|
||||
|
||||
/* IPv4 unicast configuration. */
|
||||
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user