From: Vincent Bernat Date: Wed, 12 Apr 2017 09:24:07 +0000 (+0200) Subject: bgpd: add an option for RT auto-derivation to use RFC 8635. X-Git-Tag: frr-6.1-dev~433^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=bf1061d876951adf778c5d4da907cb6bd914cba4;p=matthieu%2Ffrr.git bgpd: add an option for RT auto-derivation to use RFC 8635. RFC 8635 explains how RT auto-derivation should be done in section 5.1.2.1 [1]. In addition to encoding the VNI in the lowest bytes, a 3-bit field is used to encode a namespace. For VXLAN, we have to put 1 in this field. This is needed for proper interoperability with RT auto-derivation in JunOS. Since this would break existing setup, an additional option, "autort rfc8365-compatible" is used. [1]: https://tools.ietf.org/html/rfc8365#section-5.1.2.1 Signed-off-by: Vincent Bernat --- diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index e5e5f72699..f940c0f570 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -453,6 +453,8 @@ static void form_auto_rt(struct bgp *bgp, vni_t vni, struct list *rtl) struct ecommunity_val eval; struct ecommunity *ecomadd; + if (bgp->advertise_autort_rfc8365) + vni |= EVPN_AUTORT_VXLAN; encode_route_target_as((bgp->as & 0xFFFF), vni, &eval); ecomadd = ecommunity_new(); @@ -3224,6 +3226,41 @@ static void bgp_evpn_handle_export_rt_change_for_vrf(struct bgp *bgp_vrf) update_routes_for_vni(bgp_def, vpn); } +/* + * Handle autort change for a given VNI. + */ +static void update_autort_vni(struct hash_backet *backet, struct bgp *bgp) +{ + struct bgpevpn *vpn = backet->data; + struct listnode *node, *nnode; + struct ecommunity *ecom; + + if (!vpn) { + zlog_warn("%s: VNI hash entry for VNI not found", __PRETTY_FUNCTION__); + return; + } + + if (!is_import_rt_configured(vpn)) { + if (is_vni_live(vpn)) + bgp_evpn_uninstall_routes(bgp, vpn); + bgp_evpn_unmap_vni_from_its_rts(bgp, vpn); + for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) + ecommunity_free(&ecom); + list_delete_all_node(vpn->import_rtl); + bgp_evpn_derive_auto_rt_import(bgp, vpn); + if (is_vni_live(vpn)) + bgp_evpn_install_routes(bgp, vpn); + } + if (!is_export_rt_configured(vpn)) { + for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) + ecommunity_free(&ecom); + list_delete_all_node(vpn->export_rtl); + bgp_evpn_derive_auto_rt_export(bgp, vpn); + if (is_vni_live(vpn)) + bgp_evpn_handle_export_rt_change(bgp, vpn); + } +} + /* * Public functions. */ @@ -3335,6 +3372,8 @@ void evpn_rt_delete_auto(struct bgp *bgp, vni_t vni, struct list *rtl) struct ecommunity *ecom, *ecom_auto; struct ecommunity_val eval; + if (bgp->advertise_autort_rfc8365) + vni |= EVPN_AUTORT_VXLAN; encode_route_target_as((bgp->as & 0xFFFF), vni, &eval); ecom_auto = ecommunity_new(); @@ -3494,6 +3533,17 @@ void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw) } } +/* + * Handle change to auto-RT algorithm - update and advertise local routes. + */ +void bgp_evpn_handle_autort_change(struct bgp *bgp) +{ + hash_iterate(bgp->vnihash, + (void (*)(struct hash_backet *, + void*))update_autort_vni, + bgp); +} + /* * Handle change to export RT - update and advertise local routes. */ diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index dd8d6e2e8e..8e954159c0 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -25,6 +25,7 @@ #include "bgpd.h" #define EVPN_ROUTE_STRLEN 200 /* Must be >> MAC + IPv6 strings. */ +#define EVPN_AUTORT_VXLAN 0x10000000 static inline int is_evpn_enabled(void) { diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index 1eecb9ecf7..5a3d9e0939 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -385,6 +385,7 @@ extern void bgp_evpn_unconfigure_import_rt_for_vrf(struct bgp *bgp_vrf, struct ecommunity *ecomdel); extern int bgp_evpn_handle_export_rt_change(struct bgp *bgp, struct bgpevpn *vpn); +extern void bgp_evpn_handle_autort_change(struct bgp *bgp); extern void bgp_evpn_handle_vrf_rd_change(struct bgp *bgp_vrf, int withdraw); extern void bgp_evpn_handle_rd_change(struct bgp *bgp, struct bgpevpn *vpn, int withdraw); diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 8fd7cb5d14..439bea5bd1 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -2502,6 +2502,24 @@ static void evpn_unset_advertise_all_vni(struct bgp *bgp) bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni); bgp_evpn_cleanup_on_disable(bgp); } + +/* + * EVPN - use RFC8365 to auto-derive RT + */ +static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp) +{ + bgp->advertise_autort_rfc8365 = 1; + bgp_evpn_handle_autort_change(bgp); +} + +/* + * EVPN - don't use RFC8365 to auto-derive RT + */ +static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp) +{ + bgp->advertise_autort_rfc8365 = 0; + bgp_evpn_handle_autort_change(bgp); +} #endif /* HAVE_CUMULUS */ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn) @@ -2655,6 +2673,35 @@ DEFUN (no_bgp_evpn_advertise_all_vni, return CMD_SUCCESS; } +DEFUN (bgp_evpn_advertise_autort_rfc8365, + bgp_evpn_advertise_autort_rfc8365_cmd, + "autort rfc8365-compatible", + "Auto-derivation of RT\n" + "Auto-derivation of RT using RFC8365\n") +{ + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + + if (!bgp) + return CMD_WARNING; + evpn_set_advertise_autort_rfc8365(bgp); + return CMD_SUCCESS; +} + +DEFUN (no_bgp_evpn_advertise_autort_rfc8365, + no_bgp_evpn_advertise_autort_rfc8365_cmd, + "no autort rfc8365-compatible", + NO_STR + "Auto-derivation of RT\n" + "Auto-derivation of RT using RFC8365\n") +{ + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + + if (!bgp) + return CMD_WARNING; + evpn_unset_advertise_autort_rfc8365(bgp); + return CMD_SUCCESS; +} + DEFUN (bgp_evpn_default_originate, bgp_evpn_default_originate_cmd, "default-originate ", @@ -4378,6 +4425,9 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, if (bgp->advertise_all_vni) vty_out(vty, " advertise-all-vni\n"); + if (bgp->advertise_autort_rfc8365) + vty_out(vty, " autort rfc8365-compatible\n"); + if (bgp->advertise_gw_macip) vty_out(vty, " advertise-default-gw\n"); @@ -4455,6 +4505,8 @@ void bgp_ethernetvpn_init(void) #if defined(HAVE_CUMULUS) install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd); install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd); + install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd); + install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_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); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 0c5f72662c..7d5222120e 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -423,6 +423,9 @@ struct bgp { /* EVPN enable - advertise local VNIs and their MACs etc. */ int advertise_all_vni; + /* EVPN - use RFC 8365 to auto-derive RT */ + int advertise_autort_rfc8365; + /* Hash table of Import RTs to EVIs */ struct hash *import_rt_hash;