]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: add an API to get incoming VRF from a RT
authorPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 23 Jan 2018 17:09:12 +0000 (18:09 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 27 Mar 2018 13:21:51 +0000 (15:21 +0200)
This commit is relying on bgp vpn-policy. It is needed to configure
several bgp vrf instances, and in each of the bgp instance, configure
the following command under address-family ipv4 unicast node:
[no] rt redirect import RTLIST

Then, a function is provided, that will parse the BGP instances.
The incoming ecommunity will be compared with the configured rt redirect
import ecommunity list, and return the VRF first instance of the matching
route target.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/bgp_mplsvpn.c
bgpd/bgp_mplsvpn.h
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index 9f740db325c3b2e0753d1ae40089e90b711e11bd..68eb35776ee45658e4e47f5fd7c4bd762982ca36 100644 (file)
@@ -1774,3 +1774,22 @@ void bgp_mplsvpn_init(void)
                        &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd);
 #endif /* KEEP_OLD_VPN_COMMANDS */
 }
+
+vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey)
+{
+       struct listnode *mnode, *mnnode;
+       struct bgp *bgp;
+
+       for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
+               struct ecommunity *ec;
+
+               if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+                       continue;
+
+               ec = bgp->vpn_policy[AFI_IP].import_redirect_rtlist;
+
+               if (ecom_intersect(ec, eckey))
+                       return bgp->vrf_id;
+       }
+       return VRF_UNKNOWN;
+}
index d35568b8385729179bc79c179ada30deea2d4935..fa3ddbac73f29a5f1a942a4cb3afd972226b5eab 100644 (file)
@@ -176,4 +176,6 @@ static inline void vpn_leak_postchange(vpn_policy_direction_t direction,
 
 extern void vpn_policy_routemap_event(const char *rmap_name);
 
+extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey);
+
 #endif /* _QUAGGA_BGP_MPLSVPN_H */
index ad6f1a558873f4d02f03409715261915a4a04608..3f51c1509c605ea427384bd25e0557d0730bb5d8 100644 (file)
@@ -6588,6 +6588,63 @@ DEFPY (bgp_imexport_vpn,
        return CMD_SUCCESS;
 }
 
+DEFPY (af_routetarget_import,
+       af_routetarget_import_cmd,
+       "[no] <rt|route-target> redirect import RTLIST...",
+       NO_STR
+       "Specify route target list\n"
+       "Specify route target list\n"
+       "Flow-spec redirect type route target\n"
+       "Import routes to this address-family\n"
+       "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
+{
+       VTY_DECLVAR_CONTEXT(bgp, bgp);
+       int ret;
+       struct ecommunity *ecom = NULL;
+       int doafi[AFI_MAX] = {0};
+       afi_t afi;
+       int idx = 0;
+       int yes = 1;
+
+       if (argv_find(argv, argc, "no", &idx))
+               yes = 0;
+
+       ret = vpn_policy_getafi(vty, doafi);
+       if (ret != CMD_SUCCESS)
+               return ret;
+       if (yes) {
+               if (!argv_find(argv, argc, "RTLIST", &idx)) {
+                       vty_out(vty, "%% Missing RTLIST\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+               ret = set_ecom_list(vty, argc - idx, argv + idx, &ecom);
+               if (ret != CMD_SUCCESS)
+                       return ret;
+       }
+       for (afi = 0; afi < AFI_MAX; ++afi) {
+               if (!doafi[afi])
+                       continue;
+               if (yes) {
+                       if (bgp->vpn_policy[afi].import_redirect_rtlist)
+                               ecommunity_free(
+                                       &bgp->vpn_policy[afi]
+                                       .import_redirect_rtlist);
+                       bgp->vpn_policy[afi].import_redirect_rtlist =
+                               ecommunity_dup(ecom);
+               } else {
+                       if (bgp->vpn_policy[afi].import_redirect_rtlist)
+                               ecommunity_free(
+                                       &bgp->vpn_policy[afi]
+                                       .import_redirect_rtlist);
+                       bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
+               }
+       }
+       if (ecom)
+               ecommunity_free(&ecom);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN_NOSH (address_family_ipv4_safi,
        address_family_ipv4_safi_cmd,
        "address-family ipv4 [<unicast|multicast|vpn|labeled-unicast>]",
@@ -11685,7 +11742,16 @@ void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
                        bgp->vpn_policy[afi]
                                .rmap_name[BGP_VPN_POLICY_DIR_TOVPN]);
        }
+       if (bgp->vpn_policy[afi].import_redirect_rtlist) {
+               char *b = ecommunity_ecom2str(
+                                       bgp->vpn_policy[afi]
+                                       .import_redirect_rtlist,
+                                       ECOMMUNITY_FORMAT_ROUTE_MAP,
+                                       ECOMMUNITY_ROUTE_TARGET);
 
+               vty_out(vty, "%*srt redirect import %s\n", indent, "", b);
+               XFREE(MTYPE_ECOMMUNITY_STR, b);
+       }
 }
 
 
@@ -12897,6 +12963,9 @@ void bgp_vty_init(void)
        install_element(BGP_IPV4_NODE, &af_route_map_vpn_imexport_cmd);
        install_element(BGP_IPV6_NODE, &af_route_map_vpn_imexport_cmd);
 
+       install_element(BGP_IPV4_NODE, &af_routetarget_import_cmd);
+       install_element(BGP_IPV6_NODE, &af_routetarget_import_cmd);
+
        install_element(BGP_IPV4_NODE, &af_no_rd_vpn_export_cmd);
        install_element(BGP_IPV6_NODE, &af_no_rd_vpn_export_cmd);
        install_element(BGP_IPV4_NODE, &af_no_label_vpn_export_cmd);
index d103584594182e71c9a259314f366341a5c2c797..c1c1ee07df6724d9887079afc015a33b917c7598 100644 (file)
@@ -3272,6 +3272,14 @@ int bgp_delete(struct bgp *bgp)
 #endif
        bgp_cleanup_routes(bgp);
 
+       for (afi = 0; afi < AFI_MAX; ++afi) {
+               if (!bgp->vpn_policy[afi].import_redirect_rtlist)
+                       continue;
+               ecommunity_free(
+                               &bgp->vpn_policy[afi]
+                               .import_redirect_rtlist);
+               bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
+       }
        /* Remove visibility via the master list - there may however still be
         * routes to be processed still referencing the struct bgp.
         */
index 79fe8c8c3bab69da98f9f17d43917a4f0ab1af98..d4c2a1aba98204075bc1da70761130fc92559514 100644 (file)
@@ -465,6 +465,7 @@ struct bgp {
        /* vpn-policy */
        struct {
                struct ecommunity *rtlist[BGP_VPN_POLICY_DIR_MAX];
+               struct ecommunity *import_redirect_rtlist;
                char *rmap_name[BGP_VPN_POLICY_DIR_MAX];
                struct route_map *rmap[BGP_VPN_POLICY_DIR_MAX];