]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: add an option for RT auto-derivation to use RFC 8635.
authorVincent Bernat <vincent@bernat.im>
Wed, 12 Apr 2017 09:24:07 +0000 (11:24 +0200)
committerVincent Bernat <vincent@bernat.im>
Mon, 23 Apr 2018 15:05:23 +0000 (17:05 +0200)
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 <vincent@bernat.im>
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_evpn_private.h
bgpd/bgp_evpn_vty.c
bgpd/bgpd.h

index e5e5f72699f40d71b21ba343f3f5e1f2554ea0fd..f940c0f570824883175d6e7552de4bf33fcbb064 100644 (file)
@@ -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.
  */
index dd8d6e2e8e903cced9e3ecceb9c6464fc451af2a..8e954159c04f20d20a6965dd8fb600e2ae241445 100644 (file)
@@ -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)
 {
index 1eecb9ecf7e47372bc1f7efca12f5ebc24dd4a02..5a3d9e0939cc6ce3f07b83e9db0a2ba00b8337ca 100644 (file)
@@ -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);
index 8fd7cb5d14c1b25dc29b38f75d18579e08058b2d..439bea5bd11e44dc695094d8f775a64245fe1b85 100644 (file)
@@ -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 <ipv4 | ipv6>",
@@ -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);
index 0c5f72662cf4ce7307df94781ceeccb17d547611..7d5222120efd125c9c959947a8881a4d5182dfe1 100644 (file)
@@ -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;