From ee851c8c771c475706b4b4980cad314c40291581 Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Mon, 19 Feb 2018 00:57:54 -0800 Subject: [PATCH 1/6] bgpd: add show bgp vrf all l2vpn evpn summary as an option Ticket: CM-19738 Review: CCR-7194 Testing: Manual Signed-off-by: Mitesh Kanjariya --- bgpd/bgp_evpn_vty.c | 11 +++++++++-- bgpd/bgp_vty.c | 3 +-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 1373afec4e..131bb82276 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -2967,16 +2967,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); } /* diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index c7140b2f1f..15cc5673ac 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -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; } From db29a4a8bc91c0a7bcea8c411b7c9d41b2ba44d2 Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Mon, 19 Feb 2018 01:39:48 -0800 Subject: [PATCH 2/6] bgpd: move route-target for a vrf under address-family evpn command Signed-off-by: Mitesh Kanjariya --- bgpd/bgp_evpn_vty.c | 32 ++++++++++++++++++++++++++++++++ bgpd/bgpd.c | 32 -------------------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 131bb82276..db865adf11 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -4393,6 +4393,38 @@ 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"); + + /* 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) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 78e748fb6c..de2b913056 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7315,38 +7315,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); From a75c25534a30b47b39f80b0fb8d66fd67f4836e0 Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Mon, 19 Feb 2018 02:04:27 -0800 Subject: [PATCH 3/6] bgpd: write vrf rd to config When a non-default vrf rd is configured under l2vpn evpn in a vrf, we need to update the config file. Signed-off-by: Mitesh Kanjariya --- bgpd/bgp_evpn_vty.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index db865adf11..f65ea5a698 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -4376,6 +4376,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 +4396,10 @@ 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; From bc4606bd1ac5c34dc1f735898e0ad37a862e2892 Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Fri, 23 Feb 2018 01:16:32 -0800 Subject: [PATCH 4/6] bgpd: keep a backpointer to vrf instance in struct bgpevpn We will keep a backpointer to bgp vrf instance in bgpevpn. struct bgpevpn denotes a l2vni and bgp_vrf corresponds to l3vni. A back pointer to the vrf will provide efficient access to vrf when needed. Signed-off-by: Mitesh Kanjariya --- bgpd/bgp_evpn_private.h | 50 +++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index cc0ec82344..54e9b014cf 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -62,6 +62,8 @@ struct bgpevpn { #define VNI_FLAG_IMPRT_CFGD 0x8 /* Import RT is user configured */ #define VNI_FLAG_EXPRT_CFGD 0x10 /* Export RT is user configured */ + 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; @@ -132,65 +134,59 @@ 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 || !bgp_vrf->l2vnis) + /* bail if vpn is not associated to bgp_vrf */ + if (!vpn->bgp_vrf) return; - 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 || !bgp_vrf->l2vnis) return; + + /* associate the vpn to the bgp_vrf instance */ + vpn->bgp_vrf = bgp_vrf; listnode_add_sort(bgp_vrf->l2vnis, vpn); } From be41eb6823defd48d7e84c63fffb3e618b67ab36 Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Fri, 23 Feb 2018 02:16:47 -0800 Subject: [PATCH 5/6] bgpd: Attach PMSI to only type-3 routes and rmac to only type-2 routes The PMSI attribute is only applicable to EVPN type-3 route. Rmac is applicable to type-2 and type-5 routes. We should attach these attributes appropiately based on route-type. Signed-off-by: Mitesh Kanjariya --- bgpd/bgp_evpn.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index ec8e2907a6..9d32e0c375 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1254,8 +1254,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. */ From 3f230b347b6485962620c379b918910d33639838 Mon Sep 17 00:00:00 2001 From: mitesh Date: Sun, 25 Feb 2018 02:15:50 -0800 Subject: [PATCH 6/6] bgpd: remove show bgp l2vpn evpn route vrf cmd This command doesnt make sense as EVPN routes are only present in global table. Signed-off-by: Mitesh Kanjariya --- bgpd/bgp_evpn_vty.c | 75 --------------------------------------------- 1 file changed, 75 deletions(-) diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index f65ea5a698..8001e5bd91 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -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) @@ -3190,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. */ @@ -4468,7 +4394,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);