diff options
Diffstat (limited to 'bgpd')
-rw-r--r-- | bgpd/bgp_mplsvpn.c | 63 | ||||
-rw-r--r-- | bgpd/bgp_mplsvpn.h | 42 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 730 | ||||
-rw-r--r-- | bgpd/bgp_vty.h | 3 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 29 | ||||
-rw-r--r-- | bgpd/bgpd.c | 16 | ||||
-rw-r--r-- | bgpd/bgpd.h | 3 |
7 files changed, 348 insertions, 538 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 56676e62c..5ed43e4bd 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -28,8 +28,8 @@ #include "queue.h" #include "filter.h" #include "mpls.h" -#include "lib/json.h" -#include "lib/zclient.h" +#include "json.h" +#include "zclient.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_debug.h" @@ -732,7 +732,6 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */ safi_t safi = SAFI_MPLS_VPN; /* - * Walk vpn table, delete bi with parent == bgp_vrf * Walk vpn table, delete bi with bgp_orig == bgp_vrf */ for (prn = bgp_table_top(bgp_vpn->rib[afi][safi]); prn; @@ -818,7 +817,6 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ struct prefix *p = &info_vpn->net->p; afi_t afi = family2afi(p->family); - struct bgp_redist *red; struct attr static_attr = {0}; struct attr *new_attr = NULL; struct bgp_node *bn; @@ -830,7 +828,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF); - if (!vpn_leak_from_vpn_active(bgp_vrf, afi, &debugmsg, &red)) { + if (!vpn_leak_from_vpn_active(bgp_vrf, afi, &debugmsg)) { if (debug) zlog_debug("%s: skipping: %s", __func__, debugmsg); return; @@ -887,28 +885,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ /* * route map handling - * For now, we apply two route maps: the "redist" route map and the - * vpn-policy route map. Once we finalize CLI syntax, one of these - * route maps will probably go away. */ - if (red->rmap.map) { - struct bgp_info info; - route_map_result_t ret; - - memset(&info, 0, sizeof(info)); - info.peer = bgp_vrf->peer_self; - info.attr = &static_attr; - ret = route_map_apply(red->rmap.map, p, RMAP_BGP, &info); - if (RMAP_DENYMATCH == ret) { - bgp_attr_flush(&static_attr); /* free any added parts */ - if (debug) - zlog_debug( - "%s: vrf %s redist route map \"%s\" says DENY, skipping", - __func__, bgp_vrf->name, - red->rmap.name); - return; - } - } if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) { struct bgp_info info; route_map_result_t ret; @@ -988,7 +965,6 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */ safi_t safi = SAFI_UNICAST; struct bgp *bgp; struct listnode *mnode, *mnnode; - struct bgp_redist *red; struct bgp_node *bn; struct bgp_info *bi; const char *debugmsg; @@ -1001,7 +977,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */ /* Loop over VRFs */ for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { - if (!vpn_leak_from_vpn_active(bgp, afi, &debugmsg, &red)) { + if (!vpn_leak_from_vpn_active(bgp, afi, &debugmsg)) { if (debug) zlog_debug("%s: skipping: %s", __func__, debugmsg); @@ -1158,36 +1134,27 @@ static void vpn_policy_routemap_update(struct bgp *bgp, const char *rmap_name) __func__); } - /* - * vpn -> vrf leaking currently can have two route-maps: - * 1. the vpn-policy tovpn route-map - * 2. the (per-afi) redistribute vpn route-map - */ - char *mapname_vpn_policy = - bgp->vpn_policy[afi] - .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]; - struct bgp_redist *red = NULL; - - if (vpn_leak_from_vpn_active(bgp, afi, NULL, &red) - && ((mapname_vpn_policy - && !strcmp(rmap_name, mapname_vpn_policy)) - || (red && red->rmap.name - && !strcmp(red->rmap.name, rmap_name)))) { + char *mapname = bgp->vpn_policy[afi] + .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]; - if (debug) - zlog_debug( - "%s: rmap \"%s\" matches vrf-policy fromvpn" - " for as %d afi %s", + if (vpn_leak_from_vpn_active(bgp, afi, NULL) && + mapname && + !strcmp(rmap_name, mapname)) { + + if (debug) { + zlog_debug("%s: rmap \"%s\" matches vrf-policy fromvpn for as %d afi %s", __func__, rmap_name, bgp->as, afi2str(afi)); + } vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi, bgp_get_default(), bgp); - if (!rmap) + if (!rmap) { bgp->vpn_policy[afi] .rmap[BGP_VPN_POLICY_DIR_FROMVPN] = NULL; + } vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi, bgp_get_default(), bgp); diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index d0ad8ac84..d35568b83 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -81,6 +81,14 @@ extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi); static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi, const char **pmsg) { + if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF + && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) { + + if (pmsg) + *pmsg = "source bgp instance neither vrf nor default"; + return 0; + } + /* Is vrf configured to export to vpn? */ if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST], BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) { @@ -107,27 +115,21 @@ static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi, } static inline int vpn_leak_from_vpn_active(struct bgp *bgp_vrf, afi_t afi, - const char **pmsg, - struct bgp_redist **pred) + const char **pmsg) { - struct bgp_redist *red; - if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF - && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) { + && bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) { if (pmsg) *pmsg = "destination bgp instance neither vrf nor default"; return 0; } - /* Hijack zebra redist bits for this route type */ - red = bgp_redist_lookup(bgp_vrf, afi, ZEBRA_ROUTE_BGP_VPN, 0); - if (red) { - if (pred) - *pred = red; - } else { + /* Is vrf configured to import from vpn? */ + if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST], + BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) { if (pmsg) - *pmsg = "redist not set"; + *pmsg = "import not set"; return 0; } if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) { @@ -142,10 +144,16 @@ static inline void vpn_leak_prechange(vpn_policy_direction_t direction, afi_t afi, struct bgp *bgp_vpn, struct bgp *bgp_vrf) { - if (direction == BGP_VPN_POLICY_DIR_FROMVPN) + if ((direction == BGP_VPN_POLICY_DIR_FROMVPN) && + vpn_leak_from_vpn_active(bgp_vrf, afi, NULL)) { + vpn_leak_to_vrf_withdraw_all(bgp_vrf, afi); - if (direction == BGP_VPN_POLICY_DIR_TOVPN) + } + if ((direction == BGP_VPN_POLICY_DIR_TOVPN) && + vpn_leak_to_vpn_active(bgp_vrf, afi, NULL)) { + vpn_leak_from_vrf_withdraw_all(bgp_vpn, bgp_vrf, afi); + } } static inline void vpn_leak_postchange(vpn_policy_direction_t direction, @@ -156,16 +164,14 @@ static inline void vpn_leak_postchange(vpn_policy_direction_t direction, vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi); if (direction == BGP_VPN_POLICY_DIR_TOVPN) { - if (bgp_vrf->vpn_policy[afi].tovpn_label - != bgp_vrf->vpn_policy[afi] + if (bgp_vrf->vpn_policy[afi].tovpn_label != + bgp_vrf->vpn_policy[afi] .tovpn_zebra_vrf_label_last_sent) { vpn_leak_zebra_vrf_label_update(bgp_vrf, afi); } vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi); } - if (direction == BGP_VPN_POLICY_DIR_TOVPN) - vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi); } extern void vpn_policy_routemap_event(const char *rmap_name); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 4a5633c94..ad6f1a558 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -6112,74 +6112,63 @@ ALIAS_HIDDEN(no_neighbor_addpath_tx_bestpath_per_as, NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Use addpath to advertise the bestpath per each neighboring AS\n") - -DEFUN_NOSH (vpn_policy_afi, - vpn_policy_afi_cmd, - "vpn-policy <ipv4|ipv6>", - "Enter vpn-policy command mode\n" - BGP_AFI_HELP_STR) +static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv, + struct ecommunity **list) { - VTY_DECLVAR_CONTEXT(bgp, bgp); - if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF - && bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT) { + struct ecommunity *ecom = NULL; + struct ecommunity *ecomadd; - vty_out(vty, - "vpn-policy supported only in core or vrf instances.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + for (; argc; --argc, ++argv) { - afi_t afi; - int idx = 0; + ecomadd = ecommunity_str2com(argv[0]->arg, + ECOMMUNITY_ROUTE_TARGET, 0); + if (!ecomadd) { + vty_out(vty, "Malformed community-list value\n"); + if (ecom) + ecommunity_free(&ecom); + return CMD_WARNING_CONFIG_FAILED; + } - if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { - if (afi == AFI_IP) - vty->node = BGP_VPNPOLICY_IPV4_NODE; - else - vty->node = BGP_VPNPOLICY_IPV6_NODE; - return CMD_SUCCESS; + if (ecom) { + ecommunity_merge(ecom, ecomadd); + ecommunity_free(&ecomadd); + } else { + ecom = ecomadd; + } + } + + if (*list) { + ecommunity_free(&*list); } - return CMD_WARNING_CONFIG_FAILED; + *list = ecom; + + return CMD_SUCCESS; } -static int vpn_policy_afis(struct vty *vty, int *doafi) +static int vpn_policy_getafi(struct vty *vty, int *doafi) { switch (vty->node) { - case BGP_VPNPOLICY_IPV4_NODE: + case BGP_IPV4_NODE: doafi[AFI_IP] = 1; break; - case BGP_VPNPOLICY_IPV6_NODE: + case BGP_IPV6_NODE: doafi[AFI_IP6] = 1; break; default: vty_out(vty, - "%% context error: valid only in vpn-policy block\n"); + "%% context error: valid only in address-family <ipv4|ipv6> unicast block\n"); return CMD_WARNING_CONFIG_FAILED; } return CMD_SUCCESS; } -static int argv_find_and_parse_vpn_policy_dirs(struct vty *vty, - struct cmd_token **argv, - int argc, int *idx, int *dodir) -{ - if (argv_find(argv, argc, "fromvpn", idx)) { - dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1; - } else if (argv_find(argv, argc, "tovpn", idx)) { - dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1; - } else if (argv_find(argv, argc, "both", idx)) { - dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1; - dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1; - } else { - vty_out(vty, "%% direction parse error\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; -} - -DEFUN (vpn_policy_rd, - vpn_policy_rd_cmd, - "rd ASN:NN_OR_IP-ADDRESS:NN", +DEFPY (af_rd_vpn_export, + af_rd_vpn_export_cmd, + "[no] rd vpn export ASN:NN_OR_IP-ADDRESS:NN$rd_str", + NO_STR "Specify route distinguisher\n" + "Between current address-family and vpn\n" + "For routes leaked from current address-family to vpn\n" "Route Distinguisher (<as-number>:<number> | <ip-address>:<number>)\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); @@ -6187,14 +6176,21 @@ DEFUN (vpn_policy_rd, int ret; int doafi[AFI_MAX] = {0}; afi_t afi; + int idx = 0; + int yes = 1; - ret = str2prefix_rd(argv[1]->arg, &prd); - if (!ret) { - vty_out(vty, "%% Malformed rd\n"); - return CMD_WARNING_CONFIG_FAILED; + if (argv_find(argv, argc, "no", &idx)) + yes = 0; + + if (yes) { + ret = str2prefix_rd(rd_str, &prd); + if (!ret) { + vty_out(vty, "%% Malformed rd\n"); + return CMD_WARNING_CONFIG_FAILED; + } } - ret = vpn_policy_afis(vty, doafi); + ret = vpn_policy_getafi(vty, doafi); if (ret != CMD_SUCCESS) return ret; @@ -6208,9 +6204,14 @@ DEFUN (vpn_policy_rd, vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi, bgp_get_default(), bgp); - bgp->vpn_policy[afi].tovpn_rd = prd; - SET_FLAG(bgp->vpn_policy[afi].flags, - BGP_VPN_POLICY_TOVPN_RD_SET); + if (yes) { + bgp->vpn_policy[afi].tovpn_rd = prd; + SET_FLAG(bgp->vpn_policy[afi].flags, + BGP_VPN_POLICY_TOVPN_RD_SET); + } else { + UNSET_FLAG(bgp->vpn_policy[afi].flags, + BGP_VPN_POLICY_TOVPN_RD_SET); + } /* post-change: re-export vpn routes */ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, @@ -6220,57 +6221,38 @@ DEFUN (vpn_policy_rd, return CMD_SUCCESS; } -DEFUN (vpn_policy_no_rd, - vpn_policy_no_rd_cmd, - "no rd", +ALIAS (af_rd_vpn_export, + af_no_rd_vpn_export_cmd, + "no rd vpn export", NO_STR - "Specify route distinguisher\n") -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - int doafi[AFI_MAX] = {0}; - afi_t afi; - - ret = vpn_policy_afis(vty, doafi); - if (ret != CMD_SUCCESS) - return ret; - - - for (afi = 0; afi < AFI_MAX; ++afi) { - if (!doafi[afi]) - continue; - - /* pre-change: un-export vpn routes (vpn->vrf routes unaffected) - */ - vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi, - bgp_get_default(), bgp); - - UNSET_FLAG(bgp->vpn_policy[afi].flags, - BGP_VPN_POLICY_TOVPN_RD_SET); - - /* post-change: re-export vpn routes */ - vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, - bgp_get_default(), bgp); - } - - return CMD_SUCCESS; -} + "Specify route distinguisher\n" + "Between current address-family and vpn\n" + "For routes leaked from current address-family to vpn\n") -DEFUN (vpn_policy_label, - vpn_policy_label_cmd, - "label (0-1048575)", +DEFPY (af_label_vpn_export, + af_label_vpn_export_cmd, + "[no] label vpn export (0-1048575)$label_val", + NO_STR "label value for VRF\n" + "Between current address-family and vpn\n" + "For routes leaked from current address-family to vpn\n" "Label Value <0-1048575>\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); - mpls_label_t label; + mpls_label_t label = MPLS_LABEL_NONE; int doafi[AFI_MAX] = {0}; afi_t afi; int ret; + int idx = 0; + int yes = 1; - label = strtoul(argv[1]->arg, NULL, 10); + if (argv_find(argv, argc, "no", &idx)) + yes = 0; - ret = vpn_policy_afis(vty, doafi); + if (yes) + label = label_val; /* rely on parser to force unsigned */ + + ret = vpn_policy_getafi(vty, doafi); if (ret != CMD_SUCCESS) return ret; @@ -6278,7 +6260,8 @@ DEFUN (vpn_policy_label, if (!doafi[afi]) continue; - /* pre-change: un-export vpn routes (vpn->vrf routes unaffected) + /* + * pre-change: un-export vpn routes (vpn->vrf routes unaffected) */ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi, bgp_get_default(), bgp); @@ -6293,44 +6276,21 @@ DEFUN (vpn_policy_label, return CMD_SUCCESS; } -DEFUN (vpn_policy_no_label, - vpn_policy_no_label_cmd, - "no label", - "Negate a command or set its defaults\n" - "label value for VRF\n") -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int doafi[AFI_MAX] = {0}; - afi_t afi; - int ret; - - ret = vpn_policy_afis(vty, doafi); - if (ret != CMD_SUCCESS) - return ret; - - for (afi = 0; afi < AFI_MAX; ++afi) { - if (!doafi[afi]) - continue; - - /* pre-change: un-export vpn routes (vpn->vrf routes unaffected) - */ - vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi, - bgp_get_default(), bgp); - - bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE; - - /* post-change: re-export vpn routes */ - vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, - bgp_get_default(), bgp); - } - - return CMD_SUCCESS; -} +ALIAS (af_label_vpn_export, + af_no_label_vpn_export_cmd, + "no label vpn export", + NO_STR + "label value for VRF\n" + "Between current address-family and vpn\n" + "For routes leaked from current address-family to vpn\n") -DEFPY (vpn_policy_nexthop, - vpn_policy_nexthop_cmd, - "nexthop <A.B.C.D|X:X::X:X>$nexthop", +DEFPY (af_nexthop_vpn_export, + af_nexthop_vpn_export_cmd, + "[no] nexthop vpn export <A.B.C.D|X:X::X:X>$nexthop_str", + NO_STR "Specify next hop to use for VRF advertised prefixes\n" + "Between current address-family and vpn\n" + "For routes leaked from current address-family to vpn\n" "IPv4 prefix\n" "IPv6 prefix\n") { @@ -6339,11 +6299,18 @@ DEFPY (vpn_policy_nexthop, afi_t afi; int ret; struct prefix p; + int idx = 0; + int yes = 1; - if (!sockunion2hostprefix(nexthop, &p)) - return CMD_WARNING_CONFIG_FAILED; + if (argv_find(argv, argc, "no", &idx)) + yes = 0; + + if (yes) { + if (!sockunion2hostprefix(nexthop_str, &p)) + return CMD_WARNING_CONFIG_FAILED; + } - ret = vpn_policy_afis(vty, doafi); + ret = vpn_policy_getafi(vty, doafi); if (ret != CMD_SUCCESS) return ret; @@ -6357,9 +6324,14 @@ DEFPY (vpn_policy_nexthop, vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi, bgp_get_default(), bgp); - bgp->vpn_policy[afi].tovpn_nexthop = p; - SET_FLAG(bgp->vpn_policy[afi].flags, - BGP_VPN_POLICY_TOVPN_NEXTHOP_SET); + if (yes) { + bgp->vpn_policy[afi].tovpn_nexthop = p; + SET_FLAG(bgp->vpn_policy[afi].flags, + BGP_VPN_POLICY_TOVPN_NEXTHOP_SET); + } else { + UNSET_FLAG(bgp->vpn_policy[afi].flags, + BGP_VPN_POLICY_TOVPN_NEXTHOP_SET); + } /* post-change: re-export vpn routes */ vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, @@ -6369,81 +6341,40 @@ DEFPY (vpn_policy_nexthop, return CMD_SUCCESS; } -DEFUN (vpn_policy_no_nexthop, - vpn_policy_no_nexthop_cmd, - "no nexthop", +ALIAS (af_nexthop_vpn_export, + af_no_nexthop_vpn_export_cmd, + "no nexthop vpn export", NO_STR - "Specify next hop to use for VRF advertised prefixes\n") -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int doafi[AFI_MAX] = {0}; - afi_t afi; - int ret; - - ret = vpn_policy_afis(vty, doafi); - if (ret != CMD_SUCCESS) - return ret; - - for (afi = 0; afi < AFI_MAX; ++afi) { - if (!doafi[afi]) - continue; - - /* pre-change: un-export vpn routes (vpn->vrf routes unaffected) - */ - vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi, - bgp_get_default(), bgp); - - UNSET_FLAG(bgp->vpn_policy[afi].flags, - BGP_VPN_POLICY_TOVPN_NEXTHOP_SET); - - /* post-change: re-export vpn routes */ - vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, - bgp_get_default(), bgp); - } - - return CMD_SUCCESS; -} + "Specify next hop to use for VRF advertised prefixes\n" + "Between current address-family and vpn\n" + "For routes leaked from current address-family to vpn\n") -static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv, - struct ecommunity **list) +static int vpn_policy_getdirs(struct vty *vty, const char *dstr, int *dodir) { - struct ecommunity *ecom = NULL; - struct ecommunity *ecomadd; - - for (; argc; --argc, ++argv) { - - ecomadd = ecommunity_str2com(argv[0]->arg, - ECOMMUNITY_ROUTE_TARGET, 0); - if (!ecomadd) { - vty_out(vty, "Malformed community-list value\n"); - if (ecom) - ecommunity_free(&ecom); - return CMD_WARNING_CONFIG_FAILED; - } - - if (ecom) { - ecommunity_merge(ecom, ecomadd); - ecommunity_free(&ecomadd); - } else { - ecom = ecomadd; - } - } - - if (*list) { - ecommunity_free(&*list); + if (!strcmp(dstr, "import")) { + dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1; + } else if (!strcmp(dstr, "export")) { + dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1; + } else if (!strcmp(dstr, "both")) { + dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1; + dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1; + } else { + vty_out(vty, "%% direction parse error\n"); + return CMD_WARNING_CONFIG_FAILED; } - *list = ecom; - return CMD_SUCCESS; } -DEFUN (vpn_policy_rt, - vpn_policy_rt_cmd, - "rt <fromvpn|tovpn|both> RTLIST...", +DEFPY (af_rt_vpn_imexport, + af_rt_vpn_imexport_cmd, + "[no] <rt|route-target> vpn <import|export|both>$direction_str RTLIST...", + NO_STR "Specify route target list\n" - "fromvpn: match any\n" - "tovpn: set\n" - "both fromvpn: match any and tovpn: set\n" + "Specify route target list\n" + "Between current address-family and vpn\n" + "For routes leaked from vpn to current address-family: match any\n" + "For routes leaked from current address-family to vpn: set\n" + "both import: match any and export: set\n" "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); @@ -6454,18 +6385,28 @@ DEFUN (vpn_policy_rt, vpn_policy_direction_t dir; afi_t afi; int idx = 0; + int yes = 1; + + if (argv_find(argv, argc, "no", &idx)) + yes = 0; - ret = vpn_policy_afis(vty, doafi); + ret = vpn_policy_getafi(vty, doafi); if (ret != CMD_SUCCESS) return ret; - ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir); + ret = vpn_policy_getdirs(vty, direction_str, dodir); if (ret != CMD_SUCCESS) return ret; - ret = set_ecom_list(vty, argc - 2, argv + 2, &ecom); - 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) { @@ -6477,71 +6418,48 @@ DEFUN (vpn_policy_rt, vpn_leak_prechange(dir, afi, bgp_get_default(), bgp); - if (bgp->vpn_policy[afi].rtlist[dir]) - ecommunity_free( - &bgp->vpn_policy[afi].rtlist[dir]); - bgp->vpn_policy[afi].rtlist[dir] = ecommunity_dup(ecom); + if (yes) { + if (bgp->vpn_policy[afi].rtlist[dir]) + ecommunity_free( + &bgp->vpn_policy[afi].rtlist[dir]); + bgp->vpn_policy[afi].rtlist[dir] = + ecommunity_dup(ecom); + } else { + if (bgp->vpn_policy[afi].rtlist[dir]) + ecommunity_free( + &bgp->vpn_policy[afi].rtlist[dir]); + bgp->vpn_policy[afi].rtlist[dir] = NULL; + } vpn_leak_postchange(dir, afi, bgp_get_default(), bgp); } } - ecommunity_free(&ecom); + if (ecom) + ecommunity_free(&ecom); return CMD_SUCCESS; } -DEFUN (vpn_policy_no_rt, - vpn_policy_no_rt_cmd, - "no rt <fromvpn|tovpn|both>", +ALIAS (af_rt_vpn_imexport, + af_no_rt_vpn_imexport_cmd, + "no <rt|route-target> vpn <import|export|both>$direction_str", NO_STR "Specify route target list\n" - "fromvpn: match any\n" - "tovpn: set\n" - "both fromvpn: match any and tovpn: set\n") -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - int dodir[BGP_VPN_POLICY_DIR_MAX] = {0}; - int doafi[AFI_MAX] = {0}; - vpn_policy_direction_t dir; - afi_t afi; - int idx = 0; - - ret = vpn_policy_afis(vty, doafi); - if (ret != CMD_SUCCESS) - return ret; - - ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir); - if (ret != CMD_SUCCESS) - return ret; - - for (afi = 0; afi < AFI_MAX; ++afi) { - if (!doafi[afi]) - continue; - for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) { - if (!dodir[dir]) - continue; - - vpn_leak_prechange(dir, afi, bgp_get_default(), bgp); - - if (bgp->vpn_policy[afi].rtlist[dir]) - ecommunity_free( - &bgp->vpn_policy[afi].rtlist[dir]); - bgp->vpn_policy[afi].rtlist[dir] = NULL; - - vpn_leak_postchange(dir, afi, bgp_get_default(), bgp); - } - } - - return CMD_SUCCESS; -} - -DEFUN (vpn_policy_route_map, - vpn_policy_route_map_cmd, - "route-map <fromvpn|tovpn> WORD", + "Specify route target list\n" + "Between current address-family and vpn\n" + "For routes leaked from vpn to current address-family\n" + "For routes leaked from current address-family to vpn\n" + "both import and export\n") + +DEFPY (af_route_map_vpn_imexport, + af_route_map_vpn_imexport_cmd, +/* future: "route-map <vpn|evpn|vrf NAME> <import|export> RMAP" */ + "[no] route-map vpn <import|export>$direction_str RMAP$rmap_str", + NO_STR "Specify route map\n" - "fromvpn: core vpn -> this vrf\n" - "tovpn: this vrf -> core vpn\n" + "Between current address-family and vpn\n" + "For routes leaked from vpn to current address-family\n" + "For routes leaked from current address-family to vpn\n" "name of route-map\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); @@ -6550,14 +6468,17 @@ DEFUN (vpn_policy_route_map, int doafi[AFI_MAX] = {0}; vpn_policy_direction_t dir; afi_t afi; - int map_name_arg = 2; int idx = 0; + int yes = 1; + + if (argv_find(argv, argc, "no", &idx)) + yes = 0; - ret = vpn_policy_afis(vty, doafi); + ret = vpn_policy_getafi(vty, doafi); if (ret != CMD_SUCCESS) return ret; - ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir); + ret = vpn_policy_getdirs(vty, direction_str, dodir); if (ret != CMD_SUCCESS) return ret; @@ -6570,14 +6491,21 @@ DEFUN (vpn_policy_route_map, vpn_leak_prechange(dir, afi, bgp_get_default(), bgp); - if (bgp->vpn_policy[afi].rmap_name[dir]) - XFREE(MTYPE_ROUTE_MAP_NAME, - bgp->vpn_policy[afi].rmap_name[dir]); - bgp->vpn_policy[afi].rmap_name[dir] = XSTRDUP( - MTYPE_ROUTE_MAP_NAME, argv[map_name_arg]->arg); - bgp->vpn_policy[afi].rmap[dir] = - route_map_lookup_by_name( - argv[map_name_arg]->arg); + if (yes) { + if (bgp->vpn_policy[afi].rmap_name[dir]) + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp->vpn_policy[afi].rmap_name[dir]); + bgp->vpn_policy[afi].rmap_name[dir] = XSTRDUP( + MTYPE_ROUTE_MAP_NAME, rmap_str); + bgp->vpn_policy[afi].rmap[dir] = + route_map_lookup_by_name(rmap_str); + } else { + if (bgp->vpn_policy[afi].rmap_name[dir]) + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp->vpn_policy[afi].rmap_name[dir]); + bgp->vpn_policy[afi].rmap_name[dir] = NULL; + bgp->vpn_policy[afi].rmap[dir] = NULL; + } vpn_leak_postchange(dir, afi, bgp_get_default(), bgp); } @@ -6586,47 +6514,75 @@ DEFUN (vpn_policy_route_map, return CMD_SUCCESS; } -DEFUN (vpn_policy_no_route_map, - vpn_policy_no_route_map_cmd, - "no route-map <fromvpn|tovpn>", +ALIAS (af_route_map_vpn_imexport, + af_no_route_map_vpn_imexport_cmd, + "no route-map vpn <import|export>$direction_str", NO_STR "Specify route map\n" - "fromvpn: core vpn -> this vrf\n" - "tovpn: this vrf -> core vpn\n") + "Between current address-family and vpn\n" + "For routes leaked from vpn to current address-family\n" + "For routes leaked from current address-family to vpn\n") + +/* This command is valid only in a bgp vrf instance or the default instance */ +DEFPY (bgp_imexport_vpn, + bgp_imexport_vpn_cmd, + "[no] <import|export>$direction_str vpn", + NO_STR + "Import routes to this address-family\n" + "Export routes from this address-family\n" + "to/from default instance VPN RIB\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - int dodir[BGP_VPN_POLICY_DIR_MAX] = {0}; - int doafi[AFI_MAX] = {0}; - vpn_policy_direction_t dir; + int previous_state; afi_t afi; + safi_t safi; int idx = 0; + int yes = 1; + int flag; + vpn_policy_direction_t dir; - ret = vpn_policy_afis(vty, doafi); - if (ret != CMD_SUCCESS) - return ret; + if (argv_find(argv, argc, "no", &idx)) + yes = 0; - ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir); - if (ret != CMD_SUCCESS) - return ret; + if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type && + BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) { - for (afi = 0; afi < AFI_MAX; ++afi) { - if (!doafi[afi]) - continue; - for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) { - if (!dodir[dir]) - continue; + vty_out(vty, "%% import|export vpn valid only for bgp vrf or default instance\n"); + return CMD_WARNING_CONFIG_FAILED; + } - vpn_leak_prechange(dir, afi, bgp_get_default(), bgp); + afi = bgp_node_afi(vty); + safi = bgp_node_safi(vty); + if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) { + vty_out(vty, "%% import|export vpn valid only for unicast ipv4|ipv6\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (!strcmp(direction_str, "import")) { + flag = BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT; + dir = BGP_VPN_POLICY_DIR_FROMVPN; + } else if (!strcmp(direction_str, "export")) { + flag = BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT; + dir = BGP_VPN_POLICY_DIR_TOVPN; + } else { + vty_out(vty, "%% unknown direction %s\n", direction_str); + return CMD_WARNING_CONFIG_FAILED; + } - if (bgp->vpn_policy[afi].rmap_name[dir]) - XFREE(MTYPE_ROUTE_MAP_NAME, - bgp->vpn_policy[afi].rmap_name[dir]); - bgp->vpn_policy[afi].rmap_name[dir] = NULL; - bgp->vpn_policy[afi].rmap[dir] = NULL; + previous_state = CHECK_FLAG(bgp->af_flags[afi][safi], flag); + if (yes) { + SET_FLAG(bgp->af_flags[afi][safi], flag); + if (!previous_state) { + /* trigger export current vrf */ vpn_leak_postchange(dir, afi, bgp_get_default(), bgp); } + } else { + if (previous_state) { + /* trigger un-export current vrf */ + vpn_leak_prechange(dir, afi, bgp_get_default(), bgp); + } + UNSET_FLAG(bgp->af_flags[afi][safi], flag); } return CMD_SUCCESS; @@ -11659,99 +11615,20 @@ void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi, } } -/* This command is valid only in a bgp vrf instance or the default instance */ -DEFUN (bgp_export_vpn, - bgp_export_vpn_cmd, - "export vpn", - "Export routes to another routing protocol\n" - "to VPN RIB per vpn-policy") -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int was_off = 0; - afi_t afi; - safi_t safi; - - if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type - && BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) { - vty_out(vty, - "%% export vpn valid only for bgp vrf or default instance\n"); - return CMD_WARNING_CONFIG_FAILED; - } - afi = bgp_node_afi(vty); - safi = bgp_node_safi(vty); - if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) { - vty_out(vty, - "%% export vpn valid only for unicast ipv4|ipv6\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!CHECK_FLAG(bgp->af_flags[afi][safi], - BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) { - was_off = 1; - } - SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT); - if (was_off) { - /* trigger export current vrf */ - zlog_debug("%s: calling postchange", __func__); - vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, - bgp_get_default(), bgp); - } - return CMD_SUCCESS; -} - -DEFUN (bgp_no_export_vpn, - bgp_no_export_vpn_cmd, - "no export vpn", - NO_STR - "Export routes to another routing protocol\n" - "to VPN RIB per vpn-policy") -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int was_on = 0; - afi_t afi; - safi_t safi; - - if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type - && BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) { - vty_out(vty, - "%% export vpn valid only for bgp vrf or default instance\n"); - return CMD_WARNING_CONFIG_FAILED; - } - afi = bgp_node_afi(vty); - safi = bgp_node_safi(vty); - if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) { - vty_out(vty, - "%% export vpn valid only for unicast ipv4|ipv6\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (CHECK_FLAG(bgp->af_flags[afi][safi], - BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) { - was_on = 1; - } - if (was_on) { - /* trigger un-export current vrf */ - zlog_debug("%s: calling postchange", __func__); - vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi, - bgp_get_default(), bgp); - } - UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT); - return CMD_SUCCESS; -} - -static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp, +/* This is part of the address-family block (unicast only) */ +void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp, afi_t afi) { - vty_frame(vty, " vpn-policy ipv%d\n", ((afi == AFI_IP) ? 4 : 6)); + int indent = 2; if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) { - vty_out(vty, " label %u\n", + vty_out(vty, "%*slabel vpn export %u\n", indent, "", bgp->vpn_policy[afi].tovpn_label); } if (CHECK_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET)) { char buf[RD_ADDRSTRLEN]; - vty_out(vty, " rd %s\n", + vty_out(vty, "%*srd vpn export %s\n", indent, "", prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf, sizeof(buf))); } @@ -11763,7 +11640,8 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp, &bgp->vpn_policy[afi].tovpn_nexthop.u.prefix, buf, sizeof(buf))) { - vty_out(vty, " nexthop %s\n", buf); + vty_out(vty, "%*snexthop vpn export %s\n", + indent, "", buf); } } if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN] @@ -11775,7 +11653,7 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp, char *b = ecommunity_ecom2str( bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN], ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out(vty, " rt both %s\n", b); + vty_out(vty, "%*srt vpn both %s\n", indent, "", b); XFREE(MTYPE_ECOMMUNITY_STR, b); } else { if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) { @@ -11784,7 +11662,7 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp, .rtlist[BGP_VPN_POLICY_DIR_FROMVPN], ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out(vty, " rt fromvpn %s\n", b); + vty_out(vty, "%*srt vpn import %s\n", indent, "", b); XFREE(MTYPE_ECOMMUNITY_STR, b); } if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]) { @@ -11793,28 +11671,21 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp, .rtlist[BGP_VPN_POLICY_DIR_TOVPN], ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out(vty, " rt tovpn %s\n", b); + vty_out(vty, "%*srt vpn export %s\n", indent, "", b); XFREE(MTYPE_ECOMMUNITY_STR, b); } } if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]) { - vty_out(vty, " route-map fromvpn %s\n", + vty_out(vty, "%*sroute-map vpn import %s\n", indent, "", bgp->vpn_policy[afi] .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]); } if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN]) { - vty_out(vty, " route-map tovpn %s\n", + vty_out(vty, "%*sroute-map vpn export %s\n", indent, "", bgp->vpn_policy[afi] .rmap_name[BGP_VPN_POLICY_DIR_TOVPN]); } - vty_endframe(vty, " exit\n"); -} - -void bgp_vpn_policy_config_write(struct vty *vty, struct bgp *bgp) -{ - bgp_vpn_policy_config_write_afi(vty, bgp, AFI_IP); - bgp_vpn_policy_config_write_afi(vty, bgp, AFI_IP6); } @@ -11859,12 +11730,6 @@ static struct cmd_node bgp_evpn_node = {BGP_EVPN_NODE, static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE, "%s(config-router-af-vni)# ", 1}; -static struct cmd_node bgp_vpn_policy_ipv4_node = { - BGP_VPNPOLICY_IPV4_NODE, "%s(config-router-vpn-policy-ipv4)# ", 1}; - -static struct cmd_node bgp_vpn_policy_ipv6_node = { - BGP_VPNPOLICY_IPV6_NODE, "%s(config-router-vpn-policy-ipv6)# ", 1}; - static void community_list_vty(void); static void bgp_ac_neighbor(vector comps, struct cmd_token *token) @@ -11925,8 +11790,6 @@ void bgp_vty_init(void) install_node(&bgp_vpnv6_node, NULL); install_node(&bgp_evpn_node, NULL); install_node(&bgp_evpn_vni_node, NULL); - install_node(&bgp_vpn_policy_ipv4_node, NULL); - install_node(&bgp_vpn_policy_ipv6_node, NULL); /* Install default VTY commands to new nodes. */ install_default(BGP_NODE); @@ -11940,8 +11803,6 @@ void bgp_vty_init(void) install_default(BGP_VPNV6_NODE); install_default(BGP_EVPN_NODE); install_default(BGP_EVPN_VNI_NODE); - install_default(BGP_VPNPOLICY_IPV4_NODE); - install_default(BGP_VPNPOLICY_IPV6_NODE); /* "bgp multiple-instance" commands. */ install_element(CONFIG_NODE, &bgp_multiple_instance_cmd); @@ -13001,11 +12862,9 @@ void bgp_vty_init(void) install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd); install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd); - /* export vpn [route-map WORD] */ - install_element(BGP_IPV4_NODE, &bgp_export_vpn_cmd); - install_element(BGP_IPV6_NODE, &bgp_export_vpn_cmd); - install_element(BGP_IPV4_NODE, &bgp_no_export_vpn_cmd); - install_element(BGP_IPV6_NODE, &bgp_no_export_vpn_cmd); + /* import|export vpn [route-map WORD] */ + install_element(BGP_IPV4_NODE, &bgp_imexport_vpn_cmd); + install_element(BGP_IPV6_NODE, &bgp_imexport_vpn_cmd); /* ttl_security commands */ install_element(BGP_NODE, &neighbor_ttl_security_cmd); @@ -13027,28 +12886,27 @@ void bgp_vty_init(void) community_list_vty(); /* vpn-policy commands */ - install_element(BGP_NODE, &vpn_policy_afi_cmd); - install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_rd_cmd); - install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_rd_cmd); - install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_label_cmd); - install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_label_cmd); - install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_nexthop_cmd); - install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_nexthop_cmd); - install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_rt_cmd); - install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_rt_cmd); - install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_route_map_cmd); - install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_route_map_cmd); - - install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_rd_cmd); - install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_rd_cmd); - install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_label_cmd); - install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_label_cmd); - install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_nexthop_cmd); - install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_nexthop_cmd); - install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_rt_cmd); - install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_rt_cmd); - install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_route_map_cmd); - install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_route_map_cmd); + install_element(BGP_IPV4_NODE, &af_rd_vpn_export_cmd); + install_element(BGP_IPV6_NODE, &af_rd_vpn_export_cmd); + install_element(BGP_IPV4_NODE, &af_label_vpn_export_cmd); + install_element(BGP_IPV6_NODE, &af_label_vpn_export_cmd); + install_element(BGP_IPV4_NODE, &af_nexthop_vpn_export_cmd); + install_element(BGP_IPV6_NODE, &af_nexthop_vpn_export_cmd); + install_element(BGP_IPV4_NODE, &af_rt_vpn_imexport_cmd); + install_element(BGP_IPV6_NODE, &af_rt_vpn_imexport_cmd); + 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_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); + install_element(BGP_IPV6_NODE, &af_no_label_vpn_export_cmd); + install_element(BGP_IPV4_NODE, &af_no_nexthop_vpn_export_cmd); + install_element(BGP_IPV6_NODE, &af_no_nexthop_vpn_export_cmd); + install_element(BGP_IPV4_NODE, &af_no_rt_vpn_imexport_cmd); + install_element(BGP_IPV6_NODE, &af_no_rt_vpn_imexport_cmd); + install_element(BGP_IPV4_NODE, &af_no_route_map_vpn_imexport_cmd); + install_element(BGP_IPV6_NODE, &af_no_route_map_vpn_imexport_cmd); } #include "memory.h" diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 459c4ffcc..f77ebb610 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -71,5 +71,6 @@ extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, safi_t *safi, struct bgp **bgp); extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, safi_t safi, u_char use_json); -extern void bgp_vpn_policy_config_write(struct vty *vty, struct bgp *bgp); +extern void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp, + afi_t afi); #endif /* _QUAGGA_BGP_VTY_H */ diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index cba3811e1..486ea3937 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1445,27 +1445,7 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, u_short instance) } #endif - /* vpn -> vrf (happens within bgp but we hijack redist bits */ - if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT - || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - && type == ZEBRA_ROUTE_BGP_VPN) { - - /* leak update all */ - vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi, - bgp_get_default(), bgp); - } - vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id); - - /* vpn -> vrf (happens within bgp but we hijack redist bits */ - if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT - || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - && type == ZEBRA_ROUTE_BGP_VPN) { - - /* leak update all */ - vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi, - bgp_get_default(), bgp); - } } /* @@ -1619,15 +1599,6 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type, vnc_export_bgp_disable(bgp, afi); } #endif - /* vpn -> vrf (happend within bgp but we hijack redist bits */ - if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT - || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - && type == ZEBRA_ROUTE_BGP_VPN) { - - /* leak withdraw all */ - vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi, - bgp_get_default(), bgp); - } red = bgp_redist_lookup(bgp, afi, type, instance); if (!red) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 2eae2e5e9..c178727b5 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7132,10 +7132,18 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, if (safi == SAFI_EVPN) bgp_config_write_evpn_info(vty, bgp, afi, safi); - if (CHECK_FLAG(bgp->af_flags[afi][safi], - BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) { + if (safi == SAFI_UNICAST) { + bgp_vpn_policy_config_write_afi(vty, bgp, afi); + if (CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) { - vty_out(vty, " export vpn\n"); + vty_out(vty, " export vpn\n"); + } + if (CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) { + + vty_out(vty, " import vpn\n"); + } } vty_endframe(vty, " exit-address-family\n"); @@ -7404,8 +7412,6 @@ int bgp_config_write(struct vty *vty) if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) vty_out(vty, " no auto-summary\n"); - bgp_vpn_policy_config_write(vty, bgp); - /* IPv4 unicast configuration. */ bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 664f8c9da..79fe8c8c3 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -318,6 +318,7 @@ struct bgp { u_int16_t af_flags[AFI_MAX][SAFI_MAX]; #define BGP_CONFIG_DAMPENING (1 << 0) #define BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT (1 << 1) +#define BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT (1 << 2) /* l2vpn evpn flags - 1 << 0 is used for DAMPENNG */ #define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 1) @@ -471,7 +472,7 @@ struct bgp { uint32_t tovpn_label; /* may be MPLS_LABEL_NONE */ uint32_t tovpn_zebra_vrf_label_last_sent; struct prefix_rd tovpn_rd; - struct prefix tovpn_nexthop; /* unset => set to router id */ + struct prefix tovpn_nexthop; /* unset => set to 0 */ uint32_t flags; #define BGP_VPN_POLICY_TOVPN_RD_SET 0x00000004 #define BGP_VPN_POLICY_TOVPN_NEXTHOP_SET 0x00000008 |