summaryrefslogtreecommitdiff
path: root/bgpd
diff options
context:
space:
mode:
authorDonatas Abraitis <donatas@opensourcerouting.org>2022-09-18 22:18:13 +0300
committerDonatas Abraitis <donatas@opensourcerouting.org>2022-10-12 17:48:43 +0300
commit46dbf9d0c0b99f60767793ef3b688f95175edc6e (patch)
treecaa2b86397dc6c9dec7969e9ea3a91119e211293 /bgpd
parent984eb32b588186ac946733c5c3fe8032bae28ebc (diff)
bgpd: Implement ACCEPT_OWN extended community
TL;DR: rfc7611. Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_community.h27
-rw-r--r--bgpd/bgp_mplsvpn.c84
-rw-r--r--bgpd/bgp_mplsvpn.h3
-rw-r--r--bgpd/bgp_nht.c3
-rw-r--r--bgpd/bgp_route.c147
-rw-r--r--bgpd/bgp_route.h5
-rw-r--r--bgpd/bgp_table.h1
-rw-r--r--bgpd/bgp_vty.c34
-rw-r--r--bgpd/bgpd.c1
-rw-r--r--bgpd/bgpd.h1
10 files changed, 274 insertions, 32 deletions
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h
index 616ddb4405..05a5d4486a 100644
--- a/bgpd/bgp_community.h
+++ b/bgpd/bgp_community.h
@@ -23,6 +23,7 @@
#include "lib/json.h"
#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
/* Communities attribute. */
struct community {
@@ -109,4 +110,30 @@ extern void bgp_remove_comm_from_aggregate_hash(struct bgp_aggregate *aggregate,
struct community *community);
extern void bgp_aggr_community_remove(void *arg);
+/* This implies that when propagating routes into a VRF, the ACCEPT_OWN
+ * community SHOULD NOT be propagated.
+ */
+static inline void community_strip_accept_own(struct attr *attr)
+{
+ struct community *old_com = bgp_attr_get_community(attr);
+ struct community *new_com = NULL;
+ uint32_t val = COMMUNITY_ACCEPT_OWN;
+
+ if (old_com && community_include(old_com, val)) {
+ new_com = community_dup(old_com);
+ val = htonl(val);
+ community_del_val(new_com, &val);
+
+ if (!old_com->refcnt)
+ community_free(&old_com);
+
+ if (!new_com->size) {
+ community_free(&new_com);
+ bgp_attr_set_community(attr, NULL);
+ } else {
+ bgp_attr_set_community(attr, new_com);
+ }
+ }
+}
+
#endif /* _QUAGGA_BGP_COMMUNITY_H */
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 08748d2eba..66eef1aa52 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -42,6 +42,7 @@
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_vpn.h"
+#include "bgpd/bgp_community.h"
#include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_nexthop.h"
@@ -996,6 +997,9 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
if (nexthop_self_flag)
bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF);
+ if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN))
+ bgp_path_info_set_flag(bn, bpi, BGP_PATH_ACCEPT_OWN);
+
if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi,
source_bpi, bpi, bgp_orig, p,
debug))
@@ -1036,6 +1040,9 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
if (nexthop_self_flag)
bgp_path_info_set_flag(bn, new, BGP_PATH_ANNC_NH_SELF);
+ if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN))
+ bgp_path_info_set_flag(bn, new, BGP_PATH_ACCEPT_OWN);
+
bgp_path_info_extra_get(new);
/*
@@ -1217,6 +1224,8 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
XFREE(MTYPE_ECOMMUNITY_STR, s);
}
+ community_strip_accept_own(&static_attr);
+
/* Nexthop */
/* if policy nexthop not set, use 0 */
if (CHECK_FLAG(from_bgp->vpn_policy[afi].flags,
@@ -1362,7 +1371,7 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
* because of loop checking.
*/
if (new_info)
- vpn_leak_to_vrf_update(from_bgp, new_info);
+ vpn_leak_to_vrf_update(from_bgp, new_info, NULL);
}
void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, /* to */
@@ -1518,10 +1527,40 @@ void vpn_leak_from_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,
}
}
-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 */
+static struct bgp *bgp_lookup_by_rd(struct bgp_path_info *bpi,
+ struct prefix_rd *rd, afi_t afi)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+
+ if (!rd)
+ return NULL;
+
+ /* If ACCEPT_OWN is not enabled for this path - return. */
+ if (!CHECK_FLAG(bpi->flags, BGP_PATH_ACCEPT_OWN))
+ return NULL;
+
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+
+ if (!CHECK_FLAG(bgp->vpn_policy[afi].flags,
+ BGP_VPN_POLICY_TOVPN_RD_SET))
+ continue;
+
+ /* Check if we have source VRF by RD value */
+ if (memcmp(&bgp->vpn_policy[afi].tovpn_rd.val, rd->val,
+ ECOMMUNITY_SIZE) == 0)
+ return bgp;
+ }
+
+ return NULL;
+}
+
+static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
+ struct bgp *from_bgp, /* from */
+ struct bgp_path_info *path_vpn,
+ struct prefix_rd *prd)
{
const struct prefix *p = bgp_dest_get_prefix(path_vpn->net);
afi_t afi = family2afi(p->family);
@@ -1558,9 +1597,22 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
return false;
}
+ /* A route MUST NOT ever be accepted back into its source VRF, even if
+ * it carries one or more RTs that match that VRF.
+ */
+ if (prd && memcmp(&prd->val, &to_bgp->vpn_policy[afi].tovpn_rd.val,
+ ECOMMUNITY_SIZE) == 0) {
+ if (debug)
+ zlog_debug(
+ "%s: skipping import, match RD (%pRD) of src VRF (%s) and the prefix (%pFX)",
+ __func__, prd, to_bgp->name_pretty, p);
+
+ return false;
+ }
+
if (debug)
- zlog_debug("%s: updating %pFX to vrf %s", __func__, p,
- to_bgp->name_pretty);
+ zlog_debug("%s: updating RD %pRD, %pFX to vrf %s", __func__,
+ prd, p, to_bgp->name_pretty);
/* shallow copy */
static_attr = *path_vpn->attr;
@@ -1585,6 +1637,8 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
ecommunity_free(&old_ecom);
}
+ community_strip_accept_own(&static_attr);
+
/*
* Nexthop: stash and clear
*
@@ -1711,9 +1765,16 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
/*
* For VRF-2-VRF route-leaking,
* the source will be the originating VRF.
+ *
+ * If ACCEPT_OWN mechanism is enabled, then we SHOULD(?)
+ * get the source VRF (BGP) by looking at the RD.
*/
+ struct bgp *src_bgp = bgp_lookup_by_rd(path_vpn, prd, afi);
+
if (path_vpn->extra && path_vpn->extra->bgp_orig)
src_vrf = path_vpn->extra->bgp_orig;
+ else if (src_bgp)
+ src_vrf = src_bgp;
else
src_vrf = from_bgp;
@@ -1723,8 +1784,9 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
return true;
}
-bool vpn_leak_to_vrf_update(struct bgp *from_bgp, /* from */
- struct bgp_path_info *path_vpn) /* route */
+bool vpn_leak_to_vrf_update(struct bgp *from_bgp,
+ struct bgp_path_info *path_vpn,
+ struct prefix_rd *prd)
{
struct listnode *mnode, *mnnode;
struct bgp *bgp;
@@ -1741,7 +1803,7 @@ bool vpn_leak_to_vrf_update(struct bgp *from_bgp, /* from */
if (!path_vpn->extra
|| path_vpn->extra->bgp_orig != bgp) { /* no loop */
leak_success |= vpn_leak_to_vrf_update_onevrf(
- bgp, from_bgp, path_vpn);
+ bgp, from_bgp, path_vpn, prd);
}
}
return leak_success;
@@ -1897,7 +1959,7 @@ void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *vpn_from,
continue;
vpn_leak_to_vrf_update_onevrf(to_bgp, vpn_from,
- bpi);
+ bpi, NULL);
}
}
}
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index 46607a38c4..9af4cdf3a2 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -72,7 +72,8 @@ extern void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,
afi_t afi);
extern bool vpn_leak_to_vrf_update(struct bgp *from_bgp,
- struct bgp_path_info *path_vpn);
+ struct bgp_path_info *path_vpn,
+ struct prefix_rd *prd);
extern void vpn_leak_to_vrf_withdraw(struct bgp *from_bgp,
struct bgp_path_info *path_vpn);
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 7274bcdb21..7eeab373a0 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -139,7 +139,8 @@ static int bgp_isvalid_nexthop_for_mpls(struct bgp_nexthop_cache *bnc,
*/
return (bgp_zebra_num_connects() == 0 ||
(bnc && (bnc->nexthop_num > 0 &&
- (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) ||
+ (CHECK_FLAG(path->flags, BGP_PATH_ACCEPT_OWN) ||
+ CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) ||
bnc->bgp->srv6_enabled ||
bgp_isvalid_nexthop_for_ebgp(bnc, path) ||
bgp_isvalid_nexthop_for_mplsovergre(bnc, path)))));
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 0b411d0ec1..f6b6cb93db 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -103,10 +103,6 @@ DEFINE_HOOK(bgp_rpki_prefix_status,
const struct prefix *prefix),
(peer, attr, prefix));
-/* Render dest to prefix_rd based on safi */
-static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
- safi_t safi);
-
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
@@ -881,6 +877,49 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
return 0;
}
+ /* If a BGP speaker supports ACCEPT_OWN and is configured for the
+ * extensions defined in this document, the following step is inserted
+ * after the LOCAL_PREF comparison step in the BGP decision process:
+ * When comparing a pair of routes for a BGP destination, the
+ * route with the ACCEPT_OWN community attached is preferred over
+ * the route that does not have the community.
+ * This extra step MUST only be invoked during the best path selection
+ * process of VPN-IP routes.
+ */
+ if (safi == SAFI_MPLS_VPN &&
+ (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) ||
+ CHECK_FLAG(exist->peer->af_flags[afi][safi],
+ PEER_FLAG_ACCEPT_OWN))) {
+ bool new_accept_own = false;
+ bool exist_accept_own = false;
+ uint32_t accept_own = COMMUNITY_ACCEPT_OWN;
+
+ if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
+ new_accept_own = community_include(
+ bgp_attr_get_community(newattr), accept_own);
+ if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))
+ exist_accept_own = community_include(
+ bgp_attr_get_community(existattr), accept_own);
+
+ if (new_accept_own && !exist_accept_own) {
+ *reason = bgp_path_selection_accept_own;
+ if (debug)
+ zlog_debug(
+ "%s: %s wins over %s due to accept-own",
+ pfx_buf, new_buf, exist_buf);
+ return 1;
+ }
+
+ if (!new_accept_own && exist_accept_own) {
+ *reason = bgp_path_selection_accept_own;
+ if (debug)
+ zlog_debug(
+ "%s: %s loses to %s due to accept-own",
+ pfx_buf, new_buf, exist_buf);
+ return 0;
+ }
+ }
+
/* 3. Local route check. We prefer:
* - BGP_ROUTE_STATIC
* - BGP_ROUTE_AGGREGATE
@@ -3883,6 +3922,60 @@ static void bgp_attr_add_no_export_community(struct attr *attr)
bgp_attr_set_community(attr, new);
}
+static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
+ struct attr *attr, const struct prefix *prefix,
+ int *sub_type)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+ bool accept_own_found = false;
+
+ if (safi != SAFI_MPLS_VPN)
+ return false;
+
+ /* Processing of the ACCEPT_OWN community is enabled by configuration */
+ if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN))
+ return false;
+
+ /* The route in question carries the ACCEPT_OWN community */
+ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
+ struct community *comm = bgp_attr_get_community(attr);
+
+ if (community_include(comm, COMMUNITY_ACCEPT_OWN))
+ accept_own_found = true;
+ }
+
+ /* The route in question is targeted to one or more destination VRFs
+ * on the router (as determined by inspecting the Route Target(s)).
+ */
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+
+ if (accept_own_found &&
+ ecommunity_include(
+ bgp->vpn_policy[afi]
+ .rtlist[BGP_VPN_POLICY_DIR_TOVPN],
+ bgp_attr_get_ecommunity(attr))) {
+ if (bgp_debug_update(peer, prefix, NULL, 1))
+ zlog_debug(
+ "%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN",
+ peer, prefix);
+
+ /* Treat this route as imported, because it's leaked
+ * already from another VRF, and we got an updated
+ * version from route-reflector with ACCEPT_OWN
+ * community.
+ */
+ *sub_type = BGP_ROUTE_IMPORTED;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
struct attr *attr, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd, mpls_label_t *label,
@@ -3996,12 +4089,20 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
}
}
- /* Route reflector originator ID check. */
+ /* Route reflector originator ID check. If ACCEPT_OWN mechanism is
+ * enabled, then take care of that too.
+ */
+ bool accept_own = false;
+
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
&& IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
- peer->stat_pfx_originator_loop++;
- reason = "originator is us;";
- goto filtered;
+ accept_own =
+ bgp_accept_own(peer, afi, safi, attr, p, &sub_type);
+ if (!accept_own) {
+ peer->stat_pfx_originator_loop++;
+ reason = "originator is us;";
+ goto filtered;
+ }
}
/* Route reflector cluster ID check. */
@@ -4499,8 +4600,13 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_path_info_unset_flag(dest, pi,
BGP_PATH_VALID);
}
- } else
+ } else {
+ if (accept_own)
+ bgp_path_info_set_flag(dest, pi,
+ BGP_PATH_ACCEPT_OWN);
+
bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
+ }
#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN) {
@@ -4550,8 +4656,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)) {
-
- leak_success = vpn_leak_to_vrf_update(bgp, pi);
+ leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);
}
#ifdef ENABLE_BGP_VNC
@@ -4659,8 +4764,12 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
}
bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
}
- } else
+ } else {
+ if (accept_own)
+ bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN);
+
bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
+ }
/* Addpath ID */
new->addpath_rx_id = addpath_id;
@@ -4706,7 +4815,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)) {
- leak_success = vpn_leak_to_vrf_update(bgp, new);
+ leak_success = vpn_leak_to_vrf_update(bgp, new, prd);
}
#ifdef ENABLE_BGP_VNC
if (SAFI_MPLS_VPN == safi) {
@@ -6427,7 +6536,8 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
if (SAFI_MPLS_VPN == safi
&& bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
- vpn_leak_to_vrf_update(bgp, pi);
+ vpn_leak_to_vrf_update(bgp, pi,
+ &bgp_static->prd);
}
#ifdef ENABLE_BGP_VNC
rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
@@ -6467,7 +6577,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
if (SAFI_MPLS_VPN == safi
&& bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
- vpn_leak_to_vrf_update(bgp, new);
+ vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
}
#ifdef ENABLE_BGP_VNC
rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
@@ -8826,6 +8936,8 @@ const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
return "Weight";
case bgp_path_selection_local_pref:
return "Local Pref";
+ case bgp_path_selection_accept_own:
+ return "Accept Own";
case bgp_path_selection_local_route:
return "Local Route";
case bgp_path_selection_confed_as_path:
@@ -11902,8 +12014,8 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
/*
* Return rd based on safi
*/
-static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
- safi_t safi)
+const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
+ safi_t safi)
{
switch (safi) {
case SAFI_MPLS_VPN:
@@ -11912,7 +12024,6 @@ static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
default:
return NULL;
-
}
}
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index ddef4ca1bb..22d28ecd00 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -289,7 +289,7 @@ struct bgp_path_info {
int lock;
/* BGP information status. */
- uint16_t flags;
+ uint32_t flags;
#define BGP_PATH_IGP_CHANGED (1 << 0)
#define BGP_PATH_DAMPED (1 << 1)
#define BGP_PATH_HISTORY (1 << 2)
@@ -306,6 +306,7 @@ struct bgp_path_info {
#define BGP_PATH_RIB_ATTR_CHG (1 << 13)
#define BGP_PATH_ANNC_NH_SELF (1 << 14)
#define BGP_PATH_LINK_BW_CHG (1 << 15)
+#define BGP_PATH_ACCEPT_OWN (1 << 16)
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
uint8_t type;
@@ -852,4 +853,6 @@ extern void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr);
const char *
bgp_path_selection_reason2str(enum bgp_path_selection_reason reason);
extern bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi);
+extern const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
+ safi_t safi);
#endif /* _QUAGGA_BGP_ROUTE_H */
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index 86cd4f3da1..91d92ebd6d 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -63,6 +63,7 @@ enum bgp_path_selection_reason {
bgp_path_selection_evpn_lower_ip,
bgp_path_selection_weight,
bgp_path_selection_local_pref,
+ bgp_path_selection_accept_own,
bgp_path_selection_local_route,
bgp_path_selection_confed_as_path,
bgp_path_selection_as_path,
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 10396b8b4f..b85f3707b6 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -8327,6 +8327,32 @@ ALIAS_HIDDEN(
"Only give warning message when limit is exceeded\n"
"Force checking all received routes not only accepted\n")
+/* "neighbor accept-own" */
+DEFPY (neighbor_accept_own,
+ neighbor_accept_own_cmd,
+ "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor accept-own",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Enable handling of self-originated VPN routes containing ACCEPT_OWN community\n")
+{
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (no)
+ ret = peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ACCEPT_OWN);
+ else
+ ret = peer_af_flag_set(peer, afi, safi, PEER_FLAG_ACCEPT_OWN);
+
+ return bgp_vty_return(vty, ret);
+}
+
/* "neighbor soo" */
DEFPY (neighbor_soo,
neighbor_soo_cmd,
@@ -17362,6 +17388,10 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
}
}
+ /* accept-own */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ACCEPT_OWN))
+ vty_out(vty, " neighbor %s accept-own\n", addr);
+
/* soo */
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOO)) {
char *soo_str = ecommunity_ecom2str(
@@ -19571,6 +19601,10 @@ void bgp_vty_init(void)
install_element(BGP_EVPN_NODE, &neighbor_allowas_in_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_allowas_in_cmd);
+ /* neighbor accept-own */
+ install_element(BGP_VPNV4_NODE, &neighbor_accept_own_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_accept_own_cmd);
+
/* "neighbor soo" */
install_element(BGP_IPV4_NODE, &neighbor_soo_cmd);
install_element(BGP_IPV4_NODE, &no_neighbor_soo_cmd);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 188402d0b4..40e6c90dfc 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -4313,6 +4313,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] = {
{PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
{PEER_FLAG_DISABLE_ADDPATH_RX, 0, peer_change_reset},
{PEER_FLAG_SOO, 0, peer_change_reset},
+ {PEER_FLAG_ACCEPT_OWN, 0, peer_change_reset},
{0, 0, 0}};
/* Proper action set. */
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index b9d24969e3..44e225b043 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1462,6 +1462,7 @@ struct peer {
#define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 29)
#define PEER_FLAG_SOO (1ULL << 30)
#define PEER_FLAG_ORR_GROUP (1ULL << 31) /* Optimal-Route-Reflection */
+#define PEER_FLAG_ACCEPT_OWN (1ULL << 32)
/* BGP Optimal Route Reflection Group name */
char *orr_group_name[AFI_MAX][SAFI_MAX];