forked from Mirror/frr
bgpd: implement retain route-target all behaviour
A new command is available under SAFI_MPLS_VPN: With this command, the BGP vpnvx prefixes received are not kept, if there are no VRF interested in importing those vpn entries. A soft refresh is performed if there is a change of configuration: retain cmd, vrf import settings, or route-map change. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
1004137bf3
commit
a486300b26
|
@ -1472,7 +1472,7 @@ void vpn_leak_from_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static bool
|
||||
vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
|
||||
struct bgp *from_bgp, /* from */
|
||||
struct bgp_path_info *path_vpn) /* route */
|
||||
|
@ -1498,7 +1498,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
|
|||
if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) {
|
||||
if (debug)
|
||||
zlog_debug("%s: skipping: %s", __func__, debugmsg);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check for intersection of route targets */
|
||||
|
@ -1509,7 +1509,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
|
|||
zlog_debug(
|
||||
"from vpn (%s) to vrf (%s), skipping after no intersection of route targets",
|
||||
from_bgp->name_pretty, to_bgp->name_pretty);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
|
@ -1604,7 +1604,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
|
|||
to_bgp->vpn_policy[afi]
|
||||
.rmap[BGP_VPN_POLICY_DIR_FROMVPN]
|
||||
->name);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* if route-map changed nexthop, don't nexthop-self on output
|
||||
|
@ -1674,13 +1674,15 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
|
|||
leak_update(to_bgp, bn, new_attr, afi, safi, path_vpn, pLabels,
|
||||
num_labels, src_vrf, &nexthop_orig, nexthop_self_flag,
|
||||
debug);
|
||||
return true;
|
||||
}
|
||||
|
||||
void vpn_leak_to_vrf_update(struct bgp *from_bgp, /* from */
|
||||
bool vpn_leak_to_vrf_update(struct bgp *from_bgp, /* from */
|
||||
struct bgp_path_info *path_vpn) /* route */
|
||||
{
|
||||
struct listnode *mnode, *mnnode;
|
||||
struct bgp *bgp;
|
||||
bool leak_success = false;
|
||||
|
||||
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
|
||||
|
||||
|
@ -1692,9 +1694,11 @@ void vpn_leak_to_vrf_update(struct bgp *from_bgp, /* from */
|
|||
|
||||
if (!path_vpn->extra
|
||||
|| path_vpn->extra->bgp_orig != bgp) { /* no loop */
|
||||
vpn_leak_to_vrf_update_onevrf(bgp, from_bgp, path_vpn);
|
||||
leak_success |= vpn_leak_to_vrf_update_onevrf(
|
||||
bgp, from_bgp, path_vpn);
|
||||
}
|
||||
}
|
||||
return leak_success;
|
||||
}
|
||||
|
||||
void vpn_leak_to_vrf_withdraw(struct bgp *from_bgp, /* from */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "bgpd/bgp_route.h"
|
||||
#include "bgpd/bgp_rd.h"
|
||||
#include "bgpd/bgp_zebra.h"
|
||||
#include "bgpd/bgp_vty.h"
|
||||
|
||||
#define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
|
||||
#define MPLS_LABEL_IS_NULL(label) \
|
||||
|
@ -70,7 +71,7 @@ extern void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi);
|
|||
extern void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,
|
||||
afi_t afi);
|
||||
|
||||
extern void vpn_leak_to_vrf_update(struct bgp *from_bgp,
|
||||
extern bool vpn_leak_to_vrf_update(struct bgp *from_bgp,
|
||||
struct bgp_path_info *path_vpn);
|
||||
|
||||
extern void vpn_leak_to_vrf_withdraw(struct bgp *from_bgp,
|
||||
|
@ -233,8 +234,14 @@ static inline void vpn_leak_postchange(enum vpn_policy_direction direction,
|
|||
if (!bgp_vpn)
|
||||
return;
|
||||
|
||||
if (direction == BGP_VPN_POLICY_DIR_FROMVPN)
|
||||
vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi);
|
||||
if (direction == BGP_VPN_POLICY_DIR_FROMVPN) {
|
||||
/* trigger a flush to re-sync with ADJ-RIB-in */
|
||||
if (!CHECK_FLAG(bgp_vpn->af_flags[afi][SAFI_MPLS_VPN],
|
||||
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL))
|
||||
bgp_clear_soft_in(bgp_vpn, afi, SAFI_MPLS_VPN);
|
||||
else
|
||||
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 !=
|
||||
|
|
|
@ -3785,6 +3785,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
|
|||
uint8_t pi_sub_type = 0;
|
||||
bool force_evpn_import = false;
|
||||
safi_t orig_safi = safi;
|
||||
bool leak_success = true;
|
||||
|
||||
if (frrtrace_enabled(frr_bgp, process_update)) {
|
||||
char pfxprint[PREFIX2STR_BUFFER];
|
||||
|
@ -4410,7 +4411,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
|
|||
if ((SAFI_MPLS_VPN == safi)
|
||||
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||
|
||||
vpn_leak_to_vrf_update(bgp, pi);
|
||||
leak_success = vpn_leak_to_vrf_update(bgp, pi);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BGP_VNC
|
||||
|
@ -4425,7 +4426,13 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
|
|||
type, sub_type, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((safi == SAFI_MPLS_VPN) &&
|
||||
!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
|
||||
!leak_success) {
|
||||
bgp_unlink_nexthop(pi);
|
||||
bgp_path_info_delete(dest, pi);
|
||||
}
|
||||
return 0;
|
||||
} // End of implicit withdraw
|
||||
|
||||
|
@ -4559,8 +4566,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
|
|||
}
|
||||
if ((SAFI_MPLS_VPN == safi)
|
||||
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||
|
||||
vpn_leak_to_vrf_update(bgp, new);
|
||||
leak_success = vpn_leak_to_vrf_update(bgp, new);
|
||||
}
|
||||
#ifdef ENABLE_BGP_VNC
|
||||
if (SAFI_MPLS_VPN == safi) {
|
||||
|
@ -4574,6 +4580,13 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
|
|||
sub_type, NULL);
|
||||
}
|
||||
#endif
|
||||
if ((safi == SAFI_MPLS_VPN) &&
|
||||
!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
|
||||
!leak_success) {
|
||||
bgp_unlink_nexthop(new);
|
||||
bgp_path_info_delete(dest, new);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -951,14 +951,24 @@ static void bgp_clear_vty_error(struct vty *vty, struct peer *peer, afi_t afi,
|
|||
{
|
||||
switch (error) {
|
||||
case BGP_ERR_AF_UNCONFIGURED:
|
||||
vty_out(vty,
|
||||
"%% BGP: Enable %s address family for the neighbor %s\n",
|
||||
get_afi_safi_str(afi, safi, false), peer->host);
|
||||
if (vty)
|
||||
vty_out(vty,
|
||||
"%% BGP: Enable %s address family for the neighbor %s\n",
|
||||
get_afi_safi_str(afi, safi, false), peer->host);
|
||||
else
|
||||
zlog_warn(
|
||||
"%% BGP: Enable %s address family for the neighbor %s\n",
|
||||
get_afi_safi_str(afi, safi, false), peer->host);
|
||||
break;
|
||||
case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED:
|
||||
vty_out(vty,
|
||||
"%% BGP: Inbound soft reconfig for %s not possible as it\n has neither refresh capability, nor inbound soft reconfig\n",
|
||||
peer->host);
|
||||
if (vty)
|
||||
vty_out(vty,
|
||||
"%% BGP: Inbound soft reconfig for %s not possible as it\n has neither refresh capability, nor inbound soft reconfig\n",
|
||||
peer->host);
|
||||
else
|
||||
zlog_warn(
|
||||
"%% BGP: Inbound soft reconfig for %s not possible as it\n has neither refresh capability, nor inbound soft reconfig\n",
|
||||
peer->host);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1274,6 +1284,11 @@ static void bgp_clear_star_soft_out(struct vty *vty, const char *name)
|
|||
}
|
||||
|
||||
|
||||
void bgp_clear_soft_in(struct bgp *bgp, afi_t afi, safi_t safi)
|
||||
{
|
||||
bgp_clear(NULL, bgp, afi, safi, clear_all, BGP_CLEAR_SOFT_IN, NULL);
|
||||
}
|
||||
|
||||
#ifndef VTYSH_EXTRACT_PL
|
||||
#include "bgpd/bgp_vty_clippy.c"
|
||||
#endif
|
||||
|
@ -16315,6 +16330,34 @@ DEFUN(no_neighbor_tcp_mss, no_neighbor_tcp_mss_cmd,
|
|||
return peer_tcp_mss_vty(vty, argv[peer_index]->arg, NULL);
|
||||
}
|
||||
|
||||
DEFPY(bgp_retain_route_target, bgp_retain_route_target_cmd,
|
||||
"[no$no] bgp retain route-target all",
|
||||
NO_STR BGP_STR
|
||||
"Retain BGP updates\n"
|
||||
"Retain BGP updates based on route-target values\n"
|
||||
"Retain all BGP updates\n")
|
||||
{
|
||||
bool check;
|
||||
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
|
||||
|
||||
check = CHECK_FLAG(bgp->af_flags[bgp_node_afi(vty)][bgp_node_safi(vty)],
|
||||
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
|
||||
if (check != !no) {
|
||||
if (!no)
|
||||
SET_FLAG(bgp->af_flags[bgp_node_afi(vty)]
|
||||
[bgp_node_safi(vty)],
|
||||
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
|
||||
else
|
||||
UNSET_FLAG(bgp->af_flags[bgp_node_afi(vty)]
|
||||
[bgp_node_safi(vty)],
|
||||
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
|
||||
/* trigger a flush to re-sync with ADJ-RIB-in */
|
||||
bgp_clear(vty, bgp, bgp_node_afi(vty), bgp_node_safi(vty),
|
||||
clear_all, BGP_CLEAR_SOFT_IN, NULL);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp,
|
||||
afi_t afi, safi_t safi)
|
||||
{
|
||||
|
@ -17197,6 +17240,14 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
|||
}
|
||||
}
|
||||
|
||||
static void bgp_vpn_config_write(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi)
|
||||
{
|
||||
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL))
|
||||
vty_out(vty, " no bgp retain route-target all\n");
|
||||
}
|
||||
|
||||
/* Address family based peer configuration display. */
|
||||
static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||
safi_t safi)
|
||||
|
@ -17267,6 +17318,9 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
|
|||
if (safi == SAFI_FLOWSPEC)
|
||||
bgp_fs_config_write_pbr(vty, bgp, afi, safi);
|
||||
|
||||
if (safi == SAFI_MPLS_VPN)
|
||||
bgp_vpn_config_write(vty, bgp, afi, safi);
|
||||
|
||||
if (safi == SAFI_UNICAST) {
|
||||
bgp_vpn_policy_config_write_afi(vty, bgp, afi);
|
||||
if (CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||
|
@ -19251,6 +19305,10 @@ void bgp_vty_init(void)
|
|||
install_element(BGP_FLOWSPECV6_NODE, &exit_address_family_cmd);
|
||||
install_element(BGP_EVPN_NODE, &exit_address_family_cmd);
|
||||
|
||||
/* BGP retain all route-target */
|
||||
install_element(BGP_VPNV4_NODE, &bgp_retain_route_target_cmd);
|
||||
install_element(BGP_VPNV6_NODE, &bgp_retain_route_target_cmd);
|
||||
|
||||
/* "clear ip bgp commands" */
|
||||
install_element(ENABLE_NODE, &clear_ip_bgp_all_cmd);
|
||||
|
||||
|
|
|
@ -152,6 +152,7 @@ struct bgp;
|
|||
"endOfRibSentAfterUpdate"); \
|
||||
} while (0)
|
||||
|
||||
extern void bgp_clear_soft_in(struct bgp *bgp, afi_t afi, safi_t safi);
|
||||
extern void bgp_vty_init(void);
|
||||
extern void community_alias_vty(void);
|
||||
extern const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
|
||||
|
|
|
@ -3240,6 +3240,8 @@ static struct bgp *bgp_create(as_t *as, const char *name,
|
|||
bgp->vpn_policy[afi].export_vrf = list_new();
|
||||
bgp->vpn_policy[afi].export_vrf->del =
|
||||
bgp_vrf_string_name_delete;
|
||||
SET_FLAG(bgp->af_flags[afi][SAFI_MPLS_VPN],
|
||||
BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
|
||||
}
|
||||
if (name)
|
||||
bgp->name = XSTRDUP(MTYPE_BGP, name);
|
||||
|
|
|
@ -527,6 +527,8 @@ struct bgp {
|
|||
/* vrf-route leaking flags */
|
||||
#define BGP_CONFIG_VRF_TO_VRF_IMPORT (1 << 9)
|
||||
#define BGP_CONFIG_VRF_TO_VRF_EXPORT (1 << 10)
|
||||
/* vpnvx retain flag */
|
||||
#define BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL (1 << 11)
|
||||
|
||||
/* BGP per AF peer count */
|
||||
uint32_t af_peer_count[AFI_MAX][SAFI_MAX];
|
||||
|
|
|
@ -2827,6 +2827,14 @@ address-family:
|
|||
The CLI will disallow attempts to configure incompatible leaking
|
||||
modes.
|
||||
|
||||
.. clicmd:: bgp retain route-target all
|
||||
|
||||
It is possible to retain or not VPN prefixes that are not imported by local
|
||||
VRF configuration. This can be done via the following command in the context
|
||||
of the global VPNv4/VPNv6 family. This command defaults to on and is not
|
||||
displayed.
|
||||
The `no bgp retain route-target all` form of the command is displayed.
|
||||
|
||||
.. _bgp-l3vpn-srv6:
|
||||
|
||||
L3VPN SRv6
|
||||
|
|
Loading…
Reference in a new issue