mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 20:34:33 +00:00
Merge pull request #11823 from pguibert6WIND/bgp_vpnv4_gre_ebgp
Bgp vpnv4 convey without transport label
This commit is contained in:
commit
340ed5f9e2
@ -348,6 +348,7 @@ struct attr {
|
|||||||
#define BATTR_RMAP_IPV6_LL_NHOP_CHANGED (1 << 5)
|
#define BATTR_RMAP_IPV6_LL_NHOP_CHANGED (1 << 5)
|
||||||
#define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6)
|
#define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6)
|
||||||
#define BATTR_RMAP_LINK_BW_SET (1 << 7)
|
#define BATTR_RMAP_LINK_BW_SET (1 << 7)
|
||||||
|
#define BATTR_RMAP_L3VPN_ACCEPT_GRE (1 << 8)
|
||||||
|
|
||||||
/* Router Reflector related structure. */
|
/* Router Reflector related structure. */
|
||||||
struct cluster_list {
|
struct cluster_list {
|
||||||
|
@ -511,6 +511,8 @@ int main(int argc, char **argv)
|
|||||||
", bgp@%s:%d", address, bm->port);
|
", bgp@%s:%d", address, bm->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bgp_if_init();
|
||||||
|
|
||||||
frr_config_fork();
|
frr_config_fork();
|
||||||
/* must be called after fork() */
|
/* must be called after fork() */
|
||||||
bgp_gr_apply_running_config();
|
bgp_gr_apply_running_config();
|
||||||
|
@ -978,6 +978,11 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
|
|||||||
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
|
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
|
||||||
to_bgp->peer_self, new_attr, bn);
|
to_bgp->peer_self, new_attr, bn);
|
||||||
|
|
||||||
|
if (source_bpi->peer) {
|
||||||
|
extra = bgp_path_info_extra_get(new);
|
||||||
|
extra->peer_orig = peer_lock(source_bpi->peer);
|
||||||
|
}
|
||||||
|
|
||||||
if (nexthop_self_flag)
|
if (nexthop_self_flag)
|
||||||
bgp_path_info_set_flag(bn, new, BGP_PATH_ANNC_NH_SELF);
|
bgp_path_info_set_flag(bn, new, BGP_PATH_ANNC_NH_SELF);
|
||||||
|
|
||||||
|
@ -61,22 +61,88 @@ static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
|
|||||||
&& bnc->nexthop_num > 0));
|
&& bnc->nexthop_num > 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bgp_isvalid_labeled_nexthop(struct bgp_nexthop_cache *bnc)
|
static int bgp_isvalid_nexthop_for_ebgp(struct bgp_nexthop_cache *bnc,
|
||||||
|
struct bgp_path_info *path)
|
||||||
|
{
|
||||||
|
struct interface *ifp = NULL;
|
||||||
|
struct nexthop *nexthop;
|
||||||
|
struct bgp_interface *iifp;
|
||||||
|
struct peer *peer;
|
||||||
|
|
||||||
|
if (!path->extra || !path->extra->peer_orig)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
peer = path->extra->peer_orig;
|
||||||
|
|
||||||
|
/* only connected ebgp peers are valid */
|
||||||
|
if (peer->sort != BGP_PEER_EBGP || peer->ttl != BGP_DEFAULT_TTL ||
|
||||||
|
CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) ||
|
||||||
|
CHECK_FLAG(peer->bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) {
|
||||||
|
if (nexthop->type == NEXTHOP_TYPE_IFINDEX ||
|
||||||
|
nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX ||
|
||||||
|
nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
|
||||||
|
ifp = if_lookup_by_index(
|
||||||
|
bnc->ifindex ? bnc->ifindex : nexthop->ifindex,
|
||||||
|
bnc->bgp->vrf_id);
|
||||||
|
}
|
||||||
|
if (!ifp)
|
||||||
|
continue;
|
||||||
|
iifp = ifp->info;
|
||||||
|
if (CHECK_FLAG(iifp->flags, BGP_INTERFACE_MPLS_BGP_FORWARDING))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bgp_isvalid_nexthop_for_mplsovergre(struct bgp_nexthop_cache *bnc,
|
||||||
|
struct bgp_path_info *path)
|
||||||
|
{
|
||||||
|
struct interface *ifp = NULL;
|
||||||
|
struct nexthop *nexthop;
|
||||||
|
|
||||||
|
for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) {
|
||||||
|
if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE) {
|
||||||
|
ifp = if_lookup_by_index(
|
||||||
|
bnc->ifindex ? bnc->ifindex : nexthop->ifindex,
|
||||||
|
bnc->bgp->vrf_id);
|
||||||
|
if (ifp && (ifp->ll_type == ZEBRA_LLT_IPGRE ||
|
||||||
|
ifp->ll_type == ZEBRA_LLT_IP6GRE))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ifp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (CHECK_FLAG(path->attr->rmap_change_flags,
|
||||||
|
BATTR_RMAP_L3VPN_ACCEPT_GRE))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bgp_isvalid_nexthop_for_mpls(struct bgp_nexthop_cache *bnc,
|
||||||
|
struct bgp_path_info *path)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* In the case of MPLS-VPN, the label is learned from LDP or other
|
* - In the case of MPLS-VPN, the label is learned from LDP or other
|
||||||
* protocols, and nexthop tracking is enabled for the label.
|
* protocols, and nexthop tracking is enabled for the label.
|
||||||
* The value is recorded as BGP_NEXTHOP_LABELED_VALID.
|
* The value is recorded as BGP_NEXTHOP_LABELED_VALID.
|
||||||
* In the case of SRv6-VPN, we need to track the reachability to the
|
* - In the case of SRv6-VPN, we need to track the reachability to the
|
||||||
* SID (in other words, IPv6 address). As in MPLS, we need to record
|
* SID (in other words, IPv6 address). As in MPLS, we need to record
|
||||||
* the value as BGP_NEXTHOP_SID_VALID. However, this function is
|
* the value as BGP_NEXTHOP_SID_VALID. However, this function is
|
||||||
* currently not implemented, and this function assumes that all
|
* currently not implemented, and this function assumes that all
|
||||||
* Transit routes for SRv6-VPN are valid.
|
* Transit routes for SRv6-VPN are valid.
|
||||||
|
* - Otherwise check for mpls-gre acceptance
|
||||||
*/
|
*/
|
||||||
return (bgp_zebra_num_connects() == 0
|
return (bgp_zebra_num_connects() == 0 ||
|
||||||
|| (bnc && bnc->nexthop_num > 0
|
(bnc && (bnc->nexthop_num > 0 &&
|
||||||
&& (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)
|
(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) ||
|
||||||
|| bnc->bgp->srv6_enabled)));
|
bnc->bgp->srv6_enabled ||
|
||||||
|
bgp_isvalid_nexthop_for_ebgp(bnc, path) ||
|
||||||
|
bgp_isvalid_nexthop_for_mplsovergre(bnc, path)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
|
static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
|
||||||
@ -359,11 +425,11 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
|
|||||||
*/
|
*/
|
||||||
if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW)
|
if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW)
|
||||||
return 1;
|
return 1;
|
||||||
else if (safi == SAFI_UNICAST && pi
|
else if (safi == SAFI_UNICAST && pi &&
|
||||||
&& pi->sub_type == BGP_ROUTE_IMPORTED && pi->extra
|
pi->sub_type == BGP_ROUTE_IMPORTED && pi->extra &&
|
||||||
&& pi->extra->num_labels && !bnc->is_evpn_gwip_nexthop) {
|
pi->extra->num_labels && !bnc->is_evpn_gwip_nexthop)
|
||||||
return bgp_isvalid_labeled_nexthop(bnc);
|
return bgp_isvalid_nexthop_for_mpls(bnc, pi);
|
||||||
} else
|
else
|
||||||
return (bgp_isvalid_nexthop(bnc));
|
return (bgp_isvalid_nexthop(bnc));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1063,7 +1129,8 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
|
|||||||
&& (path->attr->evpn_overlay.type
|
&& (path->attr->evpn_overlay.type
|
||||||
!= OVERLAY_INDEX_GATEWAY_IP)) {
|
!= OVERLAY_INDEX_GATEWAY_IP)) {
|
||||||
bnc_is_valid_nexthop =
|
bnc_is_valid_nexthop =
|
||||||
bgp_isvalid_labeled_nexthop(bnc) ? true : false;
|
bgp_isvalid_nexthop_for_mpls(bnc, path) ? true
|
||||||
|
: false;
|
||||||
} else {
|
} else {
|
||||||
if (bgp_update_martian_nexthop(
|
if (bgp_update_martian_nexthop(
|
||||||
bnc->bgp, afi, safi, path->type,
|
bnc->bgp, afi, safi, path->type,
|
||||||
|
@ -255,6 +255,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
|
|||||||
if (e->bgp_orig)
|
if (e->bgp_orig)
|
||||||
bgp_unlock(e->bgp_orig);
|
bgp_unlock(e->bgp_orig);
|
||||||
|
|
||||||
|
if (e->peer_orig)
|
||||||
|
peer_unlock(e->peer_orig);
|
||||||
|
|
||||||
if (e->aggr_suppressors)
|
if (e->aggr_suppressors)
|
||||||
list_delete(&e->aggr_suppressors);
|
list_delete(&e->aggr_suppressors);
|
||||||
|
|
||||||
@ -8462,6 +8465,17 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
|
|||||||
|
|
||||||
switch (nhtype) {
|
switch (nhtype) {
|
||||||
case NEXTHOP_TYPE_IFINDEX:
|
case NEXTHOP_TYPE_IFINDEX:
|
||||||
|
switch (p->family) {
|
||||||
|
case AF_INET:
|
||||||
|
attr.nexthop.s_addr = INADDR_ANY;
|
||||||
|
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
memset(&attr.mp_nexthop_global, 0,
|
||||||
|
sizeof(attr.mp_nexthop_global));
|
||||||
|
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_IPV4:
|
case NEXTHOP_TYPE_IPV4:
|
||||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||||
|
@ -235,6 +235,12 @@ struct bgp_path_info_extra {
|
|||||||
*/
|
*/
|
||||||
struct bgp *bgp_orig;
|
struct bgp *bgp_orig;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Original bgp session to know if the session is a
|
||||||
|
* connected EBGP session or not
|
||||||
|
*/
|
||||||
|
struct peer *peer_orig;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Nexthop in context of original bgp instance. Needed
|
* Nexthop in context of original bgp instance. Needed
|
||||||
* for label resolution of core mpls routes exported to a vrf.
|
* for label resolution of core mpls routes exported to a vrf.
|
||||||
|
@ -1953,6 +1953,57 @@ static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
|
|||||||
route_set_ip_nexthop_free
|
route_set_ip_nexthop_free
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* `set l3vpn next-hop encapsulation l3vpn gre' */
|
||||||
|
|
||||||
|
/* Set nexthop to object */
|
||||||
|
struct rmap_l3vpn_nexthop_encapsulation_set {
|
||||||
|
uint8_t protocol;
|
||||||
|
};
|
||||||
|
|
||||||
|
static enum route_map_cmd_result_t
|
||||||
|
route_set_l3vpn_nexthop_encapsulation(void *rule, const struct prefix *prefix,
|
||||||
|
void *object)
|
||||||
|
{
|
||||||
|
struct rmap_l3vpn_nexthop_encapsulation_set *rins = rule;
|
||||||
|
struct bgp_path_info *path;
|
||||||
|
|
||||||
|
path = object;
|
||||||
|
|
||||||
|
if (rins->protocol != IPPROTO_GRE)
|
||||||
|
return RMAP_OKAY;
|
||||||
|
|
||||||
|
SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_L3VPN_ACCEPT_GRE);
|
||||||
|
return RMAP_OKAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Route map `l3vpn nexthop encapsulation' compile function. */
|
||||||
|
static void *route_set_l3vpn_nexthop_encapsulation_compile(const char *arg)
|
||||||
|
{
|
||||||
|
struct rmap_l3vpn_nexthop_encapsulation_set *rins;
|
||||||
|
|
||||||
|
rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
|
||||||
|
sizeof(struct rmap_l3vpn_nexthop_encapsulation_set));
|
||||||
|
|
||||||
|
/* XXX ALL GRE modes are accepted for now: gre or ip6gre */
|
||||||
|
rins->protocol = IPPROTO_GRE;
|
||||||
|
|
||||||
|
return rins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free route map's compiled `ip nexthop' value. */
|
||||||
|
static void route_set_l3vpn_nexthop_encapsulation_free(void *rule)
|
||||||
|
{
|
||||||
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Route map commands for l3vpn next-hop encapsulation set. */
|
||||||
|
static const struct route_map_rule_cmd
|
||||||
|
route_set_l3vpn_nexthop_encapsulation_cmd = {
|
||||||
|
"l3vpn next-hop encapsulation",
|
||||||
|
route_set_l3vpn_nexthop_encapsulation,
|
||||||
|
route_set_l3vpn_nexthop_encapsulation_compile,
|
||||||
|
route_set_l3vpn_nexthop_encapsulation_free};
|
||||||
|
|
||||||
/* `set local-preference LOCAL_PREF' */
|
/* `set local-preference LOCAL_PREF' */
|
||||||
|
|
||||||
/* Set local preference. */
|
/* Set local preference. */
|
||||||
@ -5290,6 +5341,34 @@ DEFUN_YANG (no_set_distance,
|
|||||||
return nb_cli_apply_changes(vty, NULL);
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFPY_YANG(set_l3vpn_nexthop_encapsulation, set_l3vpn_nexthop_encapsulation_cmd,
|
||||||
|
"[no] set l3vpn next-hop encapsulation gre",
|
||||||
|
NO_STR SET_STR
|
||||||
|
"L3VPN operations\n"
|
||||||
|
"Next hop Information\n"
|
||||||
|
"Encapsulation options (for BGP only)\n"
|
||||||
|
"Accept L3VPN traffic over GRE encapsulation\n")
|
||||||
|
{
|
||||||
|
const char *xpath =
|
||||||
|
"./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']";
|
||||||
|
const char *xpath_value =
|
||||||
|
"./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']/rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation";
|
||||||
|
enum nb_operation operation;
|
||||||
|
|
||||||
|
if (no)
|
||||||
|
operation = NB_OP_DESTROY;
|
||||||
|
else
|
||||||
|
operation = NB_OP_CREATE;
|
||||||
|
|
||||||
|
nb_cli_enqueue_change(vty, xpath, operation, NULL);
|
||||||
|
if (operation == NB_OP_DESTROY)
|
||||||
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
|
|
||||||
|
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "gre");
|
||||||
|
|
||||||
|
return nb_cli_apply_changes(vty, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN_YANG (set_local_pref,
|
DEFUN_YANG (set_local_pref,
|
||||||
set_local_pref_cmd,
|
set_local_pref_cmd,
|
||||||
"set local-preference WORD",
|
"set local-preference WORD",
|
||||||
@ -6835,6 +6914,7 @@ void bgp_route_map_init(void)
|
|||||||
route_map_install_set(&route_set_ecommunity_none_cmd);
|
route_map_install_set(&route_set_ecommunity_none_cmd);
|
||||||
route_map_install_set(&route_set_tag_cmd);
|
route_map_install_set(&route_set_tag_cmd);
|
||||||
route_map_install_set(&route_set_label_index_cmd);
|
route_map_install_set(&route_set_label_index_cmd);
|
||||||
|
route_map_install_set(&route_set_l3vpn_nexthop_encapsulation_cmd);
|
||||||
|
|
||||||
install_element(RMAP_NODE, &match_peer_cmd);
|
install_element(RMAP_NODE, &match_peer_cmd);
|
||||||
install_element(RMAP_NODE, &match_peer_local_cmd);
|
install_element(RMAP_NODE, &match_peer_local_cmd);
|
||||||
@ -6937,6 +7017,7 @@ void bgp_route_map_init(void)
|
|||||||
install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
|
install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
|
||||||
install_element(RMAP_NODE, &set_originator_id_cmd);
|
install_element(RMAP_NODE, &set_originator_id_cmd);
|
||||||
install_element(RMAP_NODE, &no_set_originator_id_cmd);
|
install_element(RMAP_NODE, &no_set_originator_id_cmd);
|
||||||
|
install_element(RMAP_NODE, &set_l3vpn_nexthop_encapsulation_cmd);
|
||||||
|
|
||||||
route_map_install_match(&route_match_ipv6_address_cmd);
|
route_map_install_match(&route_match_ipv6_address_cmd);
|
||||||
route_map_install_match(&route_match_ipv6_next_hop_cmd);
|
route_map_install_match(&route_match_ipv6_next_hop_cmd);
|
||||||
|
@ -406,6 +406,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
|
|||||||
.destroy = lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_destroy,
|
.destroy = lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_destroy,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation",
|
||||||
|
.cbs = {
|
||||||
|
.modify = lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_modify,
|
||||||
|
.destroy = lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_destroy,
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.xpath = NULL,
|
.xpath = NULL,
|
||||||
},
|
},
|
||||||
|
@ -150,6 +150,10 @@ int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_modify(
|
|||||||
struct nb_cb_modify_args *args);
|
struct nb_cb_modify_args *args);
|
||||||
int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_destroy(
|
int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_destroy(
|
||||||
struct nb_cb_destroy_args *args);
|
struct nb_cb_destroy_args *args);
|
||||||
|
int lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_modify(
|
||||||
|
struct nb_cb_modify_args *args);
|
||||||
|
int lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_destroy(
|
||||||
|
struct nb_cb_destroy_args *args);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -2922,3 +2922,56 @@ int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_destroy(
|
|||||||
|
|
||||||
return NB_OK;
|
return NB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath:
|
||||||
|
* /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/l3vpn-nexthop-encapsulation
|
||||||
|
*/
|
||||||
|
int lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_modify(
|
||||||
|
struct nb_cb_modify_args *args)
|
||||||
|
{
|
||||||
|
struct routemap_hook_context *rhc;
|
||||||
|
const char *type;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
/* Add configuration. */
|
||||||
|
rhc = nb_running_get_entry(args->dnode, NULL, true);
|
||||||
|
type = yang_dnode_get_string(args->dnode, NULL);
|
||||||
|
|
||||||
|
/* Set destroy information. */
|
||||||
|
rhc->rhc_shook = generic_set_delete;
|
||||||
|
rhc->rhc_rule = "l3vpn next-hop encapsulation";
|
||||||
|
rhc->rhc_event = RMAP_EVENT_SET_DELETED;
|
||||||
|
|
||||||
|
rv = generic_set_add(rhc->rhc_rmi,
|
||||||
|
"l3vpn next-hop encapsulation", type,
|
||||||
|
args->errmsg, args->errmsg_len);
|
||||||
|
if (rv != CMD_SUCCESS) {
|
||||||
|
rhc->rhc_shook = NULL;
|
||||||
|
return NB_ERR_INCONSISTENCY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_destroy(
|
||||||
|
struct nb_cb_destroy_args *args)
|
||||||
|
{
|
||||||
|
switch (args->event) {
|
||||||
|
case NB_EV_VALIDATE:
|
||||||
|
case NB_EV_PREPARE:
|
||||||
|
case NB_EV_ABORT:
|
||||||
|
break;
|
||||||
|
case NB_EV_APPLY:
|
||||||
|
return lib_route_map_entry_set_destroy(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NB_OK;
|
||||||
|
}
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#include "bgpd/bgp_debug.h"
|
#include "bgpd/bgp_debug.h"
|
||||||
#include "bgpd/bgp_errors.h"
|
#include "bgpd/bgp_errors.h"
|
||||||
#include "bgpd/bgp_fsm.h"
|
#include "bgpd/bgp_fsm.h"
|
||||||
|
#include "bgpd/bgp_nht.h"
|
||||||
#include "bgpd/bgp_nexthop.h"
|
#include "bgpd/bgp_nexthop.h"
|
||||||
#include "bgpd/bgp_network.h"
|
#include "bgpd/bgp_network.h"
|
||||||
#include "bgpd/bgp_open.h"
|
#include "bgpd/bgp_open.h"
|
||||||
@ -18124,6 +18125,84 @@ static void bgp_config_end(void)
|
|||||||
bgp_post_config_delay, &t_bgp_cfg);
|
bgp_post_config_delay, &t_bgp_cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
|
||||||
|
{
|
||||||
|
int write = 0;
|
||||||
|
struct interface *ifp;
|
||||||
|
struct bgp_interface *iifp;
|
||||||
|
|
||||||
|
FOR_ALL_INTERFACES (vrf, ifp) {
|
||||||
|
iifp = ifp->info;
|
||||||
|
if (!iifp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if_vty_config_start(vty, ifp);
|
||||||
|
|
||||||
|
if (CHECK_FLAG(iifp->flags,
|
||||||
|
BGP_INTERFACE_MPLS_BGP_FORWARDING)) {
|
||||||
|
vty_out(vty, " mpls bgp forwarding\n");
|
||||||
|
write++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if_vty_config_end(vty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return write;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configuration write function for bgpd. */
|
||||||
|
static int config_write_interface(struct vty *vty)
|
||||||
|
{
|
||||||
|
int write = 0;
|
||||||
|
struct vrf *vrf = NULL;
|
||||||
|
|
||||||
|
/* Display all VRF aware OSPF interface configuration */
|
||||||
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||||
|
write += config_write_interface_one(vty, vrf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return write;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFPY(mpls_bgp_forwarding, mpls_bgp_forwarding_cmd,
|
||||||
|
"[no$no] mpls bgp forwarding",
|
||||||
|
NO_STR MPLS_STR BGP_STR
|
||||||
|
"Enable MPLS forwarding for eBGP directly connected peers\n")
|
||||||
|
{
|
||||||
|
bool check;
|
||||||
|
struct bgp_interface *iifp;
|
||||||
|
|
||||||
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||||
|
iifp = ifp->info;
|
||||||
|
if (!iifp) {
|
||||||
|
vty_out(vty, "Interface %s not available\n", ifp->name);
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
check = CHECK_FLAG(iifp->flags, BGP_INTERFACE_MPLS_BGP_FORWARDING);
|
||||||
|
if (check != !no) {
|
||||||
|
if (no)
|
||||||
|
UNSET_FLAG(iifp->flags,
|
||||||
|
BGP_INTERFACE_MPLS_BGP_FORWARDING);
|
||||||
|
else
|
||||||
|
SET_FLAG(iifp->flags,
|
||||||
|
BGP_INTERFACE_MPLS_BGP_FORWARDING);
|
||||||
|
/* trigger a nht update on eBGP sessions */
|
||||||
|
if (if_is_operative(ifp))
|
||||||
|
bgp_nht_ifp_up(ifp);
|
||||||
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialization of BGP interface. */
|
||||||
|
static void bgp_vty_if_init(void)
|
||||||
|
{
|
||||||
|
/* Install interface node. */
|
||||||
|
if_cmd_init(config_write_interface);
|
||||||
|
|
||||||
|
/* "mpls bgp forwarding" commands. */
|
||||||
|
install_element(INTERFACE_NODE, &mpls_bgp_forwarding_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
void bgp_vty_init(void)
|
void bgp_vty_init(void)
|
||||||
{
|
{
|
||||||
cmd_variable_handler_register(bgp_var_neighbor);
|
cmd_variable_handler_register(bgp_var_neighbor);
|
||||||
@ -19581,6 +19660,8 @@ void bgp_vty_init(void)
|
|||||||
install_element(BGP_SRV6_NODE, &no_bgp_srv6_locator_cmd);
|
install_element(BGP_SRV6_NODE, &no_bgp_srv6_locator_cmd);
|
||||||
install_element(BGP_IPV4_NODE, &af_sid_vpn_export_cmd);
|
install_element(BGP_IPV4_NODE, &af_sid_vpn_export_cmd);
|
||||||
install_element(BGP_IPV6_NODE, &af_sid_vpn_export_cmd);
|
install_element(BGP_IPV6_NODE, &af_sid_vpn_export_cmd);
|
||||||
|
|
||||||
|
bgp_vty_if_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
@ -75,6 +75,8 @@ struct zclient *zclient = NULL;
|
|||||||
DEFINE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp),
|
DEFINE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp),
|
||||||
(bgp, ifp));
|
(bgp, ifp));
|
||||||
|
|
||||||
|
DEFINE_MTYPE_STATIC(BGPD, BGP_IF_INFO, "BGP interface context");
|
||||||
|
|
||||||
/* Can we install into zebra? */
|
/* Can we install into zebra? */
|
||||||
static inline bool bgp_install_info_to_zebra(struct bgp *bgp)
|
static inline bool bgp_install_info_to_zebra(struct bgp *bgp)
|
||||||
{
|
{
|
||||||
@ -3335,6 +3337,31 @@ static zclient_handler *const bgp_handlers[] = {
|
|||||||
bgp_zebra_process_srv6_locator_chunk,
|
bgp_zebra_process_srv6_locator_chunk,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int bgp_if_new_hook(struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct bgp_interface *iifp;
|
||||||
|
|
||||||
|
if (ifp->info)
|
||||||
|
return 0;
|
||||||
|
iifp = XCALLOC(MTYPE_BGP_IF_INFO, sizeof(struct bgp_interface));
|
||||||
|
ifp->info = iifp;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bgp_if_delete_hook(struct interface *ifp)
|
||||||
|
{
|
||||||
|
XFREE(MTYPE_BGP_IF_INFO, ifp->info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bgp_if_init(void)
|
||||||
|
{
|
||||||
|
/* Initialize Zebra interface data structure. */
|
||||||
|
hook_register_prio(if_add, 0, bgp_if_new_hook);
|
||||||
|
hook_register_prio(if_del, 0, bgp_if_delete_hook);
|
||||||
|
}
|
||||||
|
|
||||||
void bgp_zebra_init(struct thread_master *master, unsigned short instance)
|
void bgp_zebra_init(struct thread_master *master, unsigned short instance)
|
||||||
{
|
{
|
||||||
zclient_num_connects = 0;
|
zclient_num_connects = 0;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
extern void bgp_zebra_init(struct thread_master *master,
|
extern void bgp_zebra_init(struct thread_master *master,
|
||||||
unsigned short instance);
|
unsigned short instance);
|
||||||
|
extern void bgp_if_init(void);
|
||||||
extern void bgp_zebra_init_tm_connect(struct bgp *bgp);
|
extern void bgp_zebra_init_tm_connect(struct bgp *bgp);
|
||||||
extern uint32_t bgp_zebra_tm_get_id(void);
|
extern uint32_t bgp_zebra_tm_get_id(void);
|
||||||
extern bool bgp_zebra_tm_chunk_obtained(void);
|
extern bool bgp_zebra_tm_chunk_obtained(void);
|
||||||
|
@ -778,6 +778,11 @@ struct bgp {
|
|||||||
};
|
};
|
||||||
DECLARE_QOBJ_TYPE(bgp);
|
DECLARE_QOBJ_TYPE(bgp);
|
||||||
|
|
||||||
|
struct bgp_interface {
|
||||||
|
#define BGP_INTERFACE_MPLS_BGP_FORWARDING (1 << 0)
|
||||||
|
uint32_t flags;
|
||||||
|
};
|
||||||
|
|
||||||
DECLARE_HOOK(bgp_inst_delete, (struct bgp *bgp), (bgp));
|
DECLARE_HOOK(bgp_inst_delete, (struct bgp *bgp), (bgp));
|
||||||
DECLARE_HOOK(bgp_inst_config_write,
|
DECLARE_HOOK(bgp_inst_config_write,
|
||||||
(struct bgp *bgp, struct vty *vty),
|
(struct bgp *bgp, struct vty *vty),
|
||||||
|
@ -2720,6 +2720,25 @@ are reached using *core* MPLS labels which are distributed using LDP or BGP
|
|||||||
labeled unicast. *bgpd* also supports inter-VRF route leaking.
|
labeled unicast. *bgpd* also supports inter-VRF route leaking.
|
||||||
|
|
||||||
|
|
||||||
|
L3VPN over GRE interfaces
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
In MPLS-VPN or SRv6-VPN, an L3VPN next-hop entry requires that the path
|
||||||
|
chosen respectively contains a labelled path or a valid SID IPv6 address.
|
||||||
|
Otherwise the L3VPN entry will not be installed. It is possible to ignore
|
||||||
|
that check when the path chosen by the next-hop uses a GRE interface, and
|
||||||
|
there is a route-map configured at inbound side of ipv4-vpn or ipv6-vpn
|
||||||
|
address family with following syntax:
|
||||||
|
|
||||||
|
.. clicmd:: set l3vpn next-hop encapsulation gre
|
||||||
|
|
||||||
|
The incoming BGP L3VPN entry is accepted, provided that the next hop of the
|
||||||
|
L3VPN entry uses a path that takes the GRE tunnel as outgoing interface. The
|
||||||
|
remote endpoint should be configured just behind the GRE tunnel; remote
|
||||||
|
device configuration may vary depending whether it acts at edge endpoint or
|
||||||
|
not: in any case, the expectation is that incoming MPLS traffic received at
|
||||||
|
this endpoint should be considered as a valid path for L3VPN.
|
||||||
|
|
||||||
.. _bgp-vrf-route-leaking:
|
.. _bgp-vrf-route-leaking:
|
||||||
|
|
||||||
VRF Route Leaking
|
VRF Route Leaking
|
||||||
@ -2848,6 +2867,13 @@ added for all routes from the CPEs. Routes are validated and prevented from
|
|||||||
being sent back to the same CPE (e.g.: multi-site). This is especially needed
|
being sent back to the same CPE (e.g.: multi-site). This is especially needed
|
||||||
when using ``as-override`` or ``allowas-in`` to prevent routing loops.
|
when using ``as-override`` or ``allowas-in`` to prevent routing loops.
|
||||||
|
|
||||||
|
.. clicmd:: mpls bgp forwarding
|
||||||
|
|
||||||
|
It is possible to permit BGP install VPN prefixes without transport labels,
|
||||||
|
by issuing the following command under the interface configuration context.
|
||||||
|
This configuration will install VPN prefixes originated from an e-bgp session,
|
||||||
|
and with the next-hop directly connected.
|
||||||
|
|
||||||
.. _bgp-l3vpn-srv6:
|
.. _bgp-l3vpn-srv6:
|
||||||
|
|
||||||
L3VPN SRv6
|
L3VPN SRv6
|
||||||
|
@ -339,6 +339,9 @@ Route Map Set Command
|
|||||||
Set the color of a SR-TE Policy to be applied to a learned route. The SR-TE
|
Set the color of a SR-TE Policy to be applied to a learned route. The SR-TE
|
||||||
Policy is uniquely determined by the color and the BGP nexthop.
|
Policy is uniquely determined by the color and the BGP nexthop.
|
||||||
|
|
||||||
|
.. clicmd:: set l3vpn next-hop encapsulation gre
|
||||||
|
|
||||||
|
Accept L3VPN traffic over GRE encapsulation.
|
||||||
|
|
||||||
.. _route-map-call-command:
|
.. _route-map-call-command:
|
||||||
|
|
||||||
|
@ -387,6 +387,8 @@ DECLARE_QOBJ_TYPE(route_map);
|
|||||||
(strmatch(A, "frr-bgp-route-map:set-evpn-gateway-ip-ipv4"))
|
(strmatch(A, "frr-bgp-route-map:set-evpn-gateway-ip-ipv4"))
|
||||||
#define IS_SET_BGP_EVPN_GATEWAY_IP_IPV6(A) \
|
#define IS_SET_BGP_EVPN_GATEWAY_IP_IPV6(A) \
|
||||||
(strmatch(A, "frr-bgp-route-map:set-evpn-gateway-ip-ipv6"))
|
(strmatch(A, "frr-bgp-route-map:set-evpn-gateway-ip-ipv6"))
|
||||||
|
#define IS_SET_BGP_L3VPN_NEXTHOP_ENCAPSULATION(A) \
|
||||||
|
(strmatch(A, "frr-bgp-route-map:set-l3vpn-nexthop-encapsulation"))
|
||||||
|
|
||||||
enum ecommunity_lb_type {
|
enum ecommunity_lb_type {
|
||||||
EXPLICIT_BANDWIDTH,
|
EXPLICIT_BANDWIDTH,
|
||||||
|
@ -1258,6 +1258,11 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
|
|||||||
yang_dnode_get_string(
|
yang_dnode_get_string(
|
||||||
dnode,
|
dnode,
|
||||||
"./rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6"));
|
"./rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6"));
|
||||||
|
} else if (IS_SET_BGP_L3VPN_NEXTHOP_ENCAPSULATION(action)) {
|
||||||
|
vty_out(vty, " set l3vpn next-hop encapsulation %s\n",
|
||||||
|
yang_dnode_get_string(
|
||||||
|
dnode,
|
||||||
|
"./rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
tests/topotests/bgp_vpnv4_ebgp/__init__.py
Normal file
0
tests/topotests/bgp_vpnv4_ebgp/__init__.py
Normal file
25
tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf
Normal file
25
tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
router bgp 65500
|
||||||
|
bgp router-id 1.1.1.1
|
||||||
|
no bgp ebgp-requires-policy
|
||||||
|
neighbor 10.125.0.2 remote-as 65501
|
||||||
|
address-family ipv4 unicast
|
||||||
|
no neighbor 10.125.0.2 activate
|
||||||
|
exit-address-family
|
||||||
|
address-family ipv4 vpn
|
||||||
|
neighbor 10.125.0.2 activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
router bgp 65500 vrf vrf1
|
||||||
|
bgp router-id 1.1.1.1
|
||||||
|
address-family ipv4 unicast
|
||||||
|
redistribute connected
|
||||||
|
label vpn export 101
|
||||||
|
rd vpn export 444:1
|
||||||
|
rt vpn both 52:100
|
||||||
|
export vpn
|
||||||
|
import vpn
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
interface r1-eth0
|
||||||
|
mpls bgp forwarding
|
||||||
|
!
|
50
tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json
Normal file
50
tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"10.200.0.0/24": [
|
||||||
|
{
|
||||||
|
"prefix": "10.200.0.0/24",
|
||||||
|
"prefixLen": 24,
|
||||||
|
"protocol": "bgp",
|
||||||
|
"vrfName": "vrf1",
|
||||||
|
"selected": true,
|
||||||
|
"destSelected": true,
|
||||||
|
"distance": 20,
|
||||||
|
"metric": 0,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"flags": 3,
|
||||||
|
"fib": true,
|
||||||
|
"ip": "10.125.0.2",
|
||||||
|
"afi": "ipv4",
|
||||||
|
"interfaceName": "r1-eth0",
|
||||||
|
"vrf": "default",
|
||||||
|
"active": true,
|
||||||
|
"labels":[
|
||||||
|
102
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.201.0.0/24": [
|
||||||
|
{
|
||||||
|
"prefix": "10.201.0.0/24",
|
||||||
|
"prefixLen": 24,
|
||||||
|
"protocol": "connected",
|
||||||
|
"vrfName": "vrf1",
|
||||||
|
"selected": true,
|
||||||
|
"destSelected": true,
|
||||||
|
"distance": 0,
|
||||||
|
"metric": 0,
|
||||||
|
"installed": true,
|
||||||
|
"nexthops":[
|
||||||
|
{
|
||||||
|
"flags": 3,
|
||||||
|
"fib": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"interfaceName": "r1-eth1",
|
||||||
|
"active": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
7
tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf
Normal file
7
tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
log stdout
|
||||||
|
interface r1-eth1 vrf vrf1
|
||||||
|
ip address 10.201.0.1/24
|
||||||
|
!
|
||||||
|
interface r1-eth0
|
||||||
|
ip address 10.125.0.1/24
|
||||||
|
!
|
38
tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json
Normal file
38
tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"vrfName": "vrf1",
|
||||||
|
"localAS": 65501,
|
||||||
|
"routes":
|
||||||
|
{
|
||||||
|
"10.201.0.0/24": [
|
||||||
|
{
|
||||||
|
"prefix": "10.201.0.0",
|
||||||
|
"prefixLen": 24,
|
||||||
|
"network": "10.201.0.0\/24",
|
||||||
|
"nhVrfName": "default",
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"ip": "10.125.0.1",
|
||||||
|
"afi": "ipv4",
|
||||||
|
"used": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.200.0.0/24": [
|
||||||
|
{
|
||||||
|
"valid": true,
|
||||||
|
"bestpath": true,
|
||||||
|
"prefix": "10.200.0.0",
|
||||||
|
"prefixLen": 24,
|
||||||
|
"network": "10.200.0.0\/24",
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"ip": "0.0.0.0",
|
||||||
|
"afi": "ipv4",
|
||||||
|
"used": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
25
tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf
Normal file
25
tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
router bgp 65501
|
||||||
|
bgp router-id 2.2.2.2
|
||||||
|
no bgp ebgp-requires-policy
|
||||||
|
neighbor 10.125.0.1 remote-as 65500
|
||||||
|
address-family ipv4 unicast
|
||||||
|
no neighbor 10.125.0.1 activate
|
||||||
|
exit-address-family
|
||||||
|
address-family ipv4 vpn
|
||||||
|
neighbor 10.125.0.1 activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
router bgp 65501 vrf vrf1
|
||||||
|
bgp router-id 2.2.2.2
|
||||||
|
address-family ipv4 unicast
|
||||||
|
redistribute connected
|
||||||
|
label vpn export 102
|
||||||
|
rd vpn export 444:2
|
||||||
|
rt vpn both 52:100
|
||||||
|
export vpn
|
||||||
|
import vpn
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
interface r2-eth0
|
||||||
|
mpls bgp forwarding
|
||||||
|
!
|
7
tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf
Normal file
7
tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
log stdout
|
||||||
|
interface r2-eth1 vrf vrf1
|
||||||
|
ip address 10.200.0.2/24
|
||||||
|
!
|
||||||
|
interface r2-eth0
|
||||||
|
ip address 10.125.0.2/24
|
||||||
|
!
|
187
tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
Normal file
187
tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# test_bgp_vpnv4_ebgp.py
|
||||||
|
# Part of NetDEF Topology Tests
|
||||||
|
#
|
||||||
|
# Copyright (c) 2022 by 6WIND
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software
|
||||||
|
# for any purpose with or without fee is hereby granted, provided
|
||||||
|
# that the above copyright notice and this permission notice appear
|
||||||
|
# in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
|
||||||
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
|
||||||
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||||
|
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||||
|
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
# OF THIS SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
test_bgp_vpnv4_ebgp.py: Test the FRR BGP daemon with EBGP direct connection
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
from functools import partial
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
# Save the Current Working Directory to find configuration files.
|
||||||
|
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.join(CWD, "../"))
|
||||||
|
|
||||||
|
# pylint: disable=C0413
|
||||||
|
# Import topogen and topotest helpers
|
||||||
|
from lib import topotest
|
||||||
|
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||||
|
from lib.topolog import logger
|
||||||
|
|
||||||
|
# Required to instantiate the topology builder class.
|
||||||
|
|
||||||
|
|
||||||
|
pytestmark = [pytest.mark.bgpd]
|
||||||
|
|
||||||
|
|
||||||
|
def build_topo(tgen):
|
||||||
|
"Build function"
|
||||||
|
|
||||||
|
# Create 2 routers.
|
||||||
|
tgen.add_router("r1")
|
||||||
|
tgen.add_router("r2")
|
||||||
|
|
||||||
|
switch = tgen.add_switch("s1")
|
||||||
|
switch.add_link(tgen.gears["r1"])
|
||||||
|
switch.add_link(tgen.gears["r2"])
|
||||||
|
|
||||||
|
switch = tgen.add_switch("s2")
|
||||||
|
switch.add_link(tgen.gears["r1"])
|
||||||
|
|
||||||
|
switch = tgen.add_switch("s3")
|
||||||
|
switch.add_link(tgen.gears["r2"])
|
||||||
|
|
||||||
|
def _populate_iface():
|
||||||
|
tgen = get_topogen()
|
||||||
|
cmds_list = [
|
||||||
|
'ip link add vrf1 type vrf table 10',
|
||||||
|
'echo 100000 > /proc/sys/net/mpls/platform_labels',
|
||||||
|
'ip link set dev vrf1 up',
|
||||||
|
'ip link set dev {0}-eth1 master vrf1',
|
||||||
|
'echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input',
|
||||||
|
]
|
||||||
|
|
||||||
|
for cmd in cmds_list:
|
||||||
|
input = cmd.format('r1', '1', '2')
|
||||||
|
logger.info('input: ' + cmd)
|
||||||
|
output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2'))
|
||||||
|
logger.info('output: ' + output)
|
||||||
|
|
||||||
|
for cmd in cmds_list:
|
||||||
|
input = cmd.format('r2', '2', '1')
|
||||||
|
logger.info('input: ' + cmd)
|
||||||
|
output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1'))
|
||||||
|
logger.info('output: ' + output)
|
||||||
|
|
||||||
|
def setup_module(mod):
|
||||||
|
"Sets up the pytest environment"
|
||||||
|
tgen = Topogen(build_topo, mod.__name__)
|
||||||
|
tgen.start_topology()
|
||||||
|
|
||||||
|
router_list = tgen.routers()
|
||||||
|
_populate_iface()
|
||||||
|
|
||||||
|
for rname, router in router_list.items():
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||||
|
)
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize all routers.
|
||||||
|
tgen.start_router()
|
||||||
|
|
||||||
|
|
||||||
|
def teardown_module(_mod):
|
||||||
|
"Teardown the pytest environment"
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
|
def test_protocols_convergence():
|
||||||
|
"""
|
||||||
|
Assert that all protocols have converged
|
||||||
|
statuses as they depend on it.
|
||||||
|
"""
|
||||||
|
tgen = get_topogen()
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
router = tgen.gears['r1']
|
||||||
|
logger.info("Dump some context for r1")
|
||||||
|
router.vtysh_cmd("show bgp ipv4 vpn")
|
||||||
|
router.vtysh_cmd("show bgp summary")
|
||||||
|
router.vtysh_cmd("show bgp vrf vrf1 ipv4")
|
||||||
|
router.vtysh_cmd("show running-config")
|
||||||
|
router = tgen.gears['r2']
|
||||||
|
logger.info("Dump some context for r2")
|
||||||
|
router.vtysh_cmd("show bgp ipv4 vpn")
|
||||||
|
router.vtysh_cmd("show bgp summary")
|
||||||
|
router.vtysh_cmd("show bgp vrf vrf1 ipv4")
|
||||||
|
router.vtysh_cmd("show running-config")
|
||||||
|
|
||||||
|
# Check IPv4 routing tables on r1
|
||||||
|
logger.info("Checking IPv4 routes for convergence on r1")
|
||||||
|
router = tgen.gears['r1']
|
||||||
|
json_file = "{}/{}/ipv4_routes.json".format(CWD, router.name)
|
||||||
|
if not os.path.isfile(json_file):
|
||||||
|
logger.info("skipping file {}".format(json_file))
|
||||||
|
assert 0, 'ipv4_routes.json file not found'
|
||||||
|
return
|
||||||
|
|
||||||
|
expected = json.loads(open(json_file).read())
|
||||||
|
test_func = partial(
|
||||||
|
topotest.router_json_cmp,
|
||||||
|
router,
|
||||||
|
"show ip route vrf vrf1 json",
|
||||||
|
expected,
|
||||||
|
)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
|
||||||
|
assertmsg = '"{}" JSON output mismatches'.format(router.name)
|
||||||
|
assert result is None, assertmsg
|
||||||
|
|
||||||
|
# Check BGP IPv4 routing tables on r2 not installed
|
||||||
|
logger.info("Checking BGP IPv4 routes for convergence on r2")
|
||||||
|
router = tgen.gears['r2']
|
||||||
|
json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name)
|
||||||
|
if not os.path.isfile(json_file):
|
||||||
|
assert 0, 'bgp_ipv4_routes.json file not found'
|
||||||
|
|
||||||
|
expected = json.loads(open(json_file).read())
|
||||||
|
test_func = partial(
|
||||||
|
topotest.router_json_cmp,
|
||||||
|
router,
|
||||||
|
"show bgp vrf vrf1 ipv4 json",
|
||||||
|
expected,
|
||||||
|
)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
|
||||||
|
assertmsg = '"{}" JSON output mismatches'.format(router.name)
|
||||||
|
assert result is None, assertmsg
|
||||||
|
|
||||||
|
def test_memory_leak():
|
||||||
|
"Run the memory leak test and report results."
|
||||||
|
tgen = get_topogen()
|
||||||
|
if not tgen.is_memleak_enabled():
|
||||||
|
pytest.skip("Memory leak test/report is disabled")
|
||||||
|
|
||||||
|
tgen.report_memory_leaks()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = ["-s"] + sys.argv[1:]
|
||||||
|
sys.exit(pytest.main(args))
|
0
tests/topotests/bgp_vpnv4_gre/__init__.py
Normal file
0
tests/topotests/bgp_vpnv4_gre/__init__.py
Normal file
26
tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf
Normal file
26
tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
router bgp 65500
|
||||||
|
bgp router-id 192.0.2.1
|
||||||
|
neighbor 192.0.2.2 remote-as 65500
|
||||||
|
neighbor 192.0.2.2 update-source 192.0.2.1
|
||||||
|
address-family ipv4 unicast
|
||||||
|
no neighbor 192.0.2.2 activate
|
||||||
|
exit-address-family
|
||||||
|
address-family ipv4 vpn
|
||||||
|
neighbor 192.0.2.2 activate
|
||||||
|
neighbor 192.0.2.2 route-map rmap in
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
router bgp 65500 vrf vrf1
|
||||||
|
bgp router-id 192.0.2.1
|
||||||
|
address-family ipv4 unicast
|
||||||
|
redistribute connected
|
||||||
|
label vpn export 101
|
||||||
|
rd vpn export 444:1
|
||||||
|
rt vpn both 52:100
|
||||||
|
export vpn
|
||||||
|
import vpn
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
route-map rmap permit 1
|
||||||
|
set l3vpn next-hop encapsulation gre
|
||||||
|
!
|
50
tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json
Normal file
50
tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"10.200.0.0/24": [
|
||||||
|
{
|
||||||
|
"prefix": "10.200.0.0/24",
|
||||||
|
"prefixLen": 24,
|
||||||
|
"protocol": "bgp",
|
||||||
|
"vrfName": "vrf1",
|
||||||
|
"selected": true,
|
||||||
|
"destSelected": true,
|
||||||
|
"distance": 20,
|
||||||
|
"metric": 0,
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"flags": 3,
|
||||||
|
"fib": true,
|
||||||
|
"ip": "192.168.0.2",
|
||||||
|
"afi": "ipv4",
|
||||||
|
"interfaceName": "r1-gre0",
|
||||||
|
"vrf": "default",
|
||||||
|
"active": true,
|
||||||
|
"labels":[
|
||||||
|
102
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.201.0.0/24": [
|
||||||
|
{
|
||||||
|
"prefix": "10.201.0.0/24",
|
||||||
|
"prefixLen": 24,
|
||||||
|
"protocol": "connected",
|
||||||
|
"vrfName": "vrf1",
|
||||||
|
"selected": true,
|
||||||
|
"destSelected": true,
|
||||||
|
"distance": 0,
|
||||||
|
"metric": 0,
|
||||||
|
"installed": true,
|
||||||
|
"nexthops":[
|
||||||
|
{
|
||||||
|
"flags": 3,
|
||||||
|
"fib": true,
|
||||||
|
"directlyConnected": true,
|
||||||
|
"interfaceName": "r1-eth1",
|
||||||
|
"active": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
14
tests/topotests/bgp_vpnv4_gre/r1/zebra.conf
Normal file
14
tests/topotests/bgp_vpnv4_gre/r1/zebra.conf
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
log stdout
|
||||||
|
ip route 192.0.2.2/32 192.168.0.2
|
||||||
|
interface lo
|
||||||
|
ip address 192.0.2.1/32
|
||||||
|
!
|
||||||
|
interface r1-gre0
|
||||||
|
ip address 192.168.0.1/24
|
||||||
|
!
|
||||||
|
interface r1-eth1 vrf vrf1
|
||||||
|
ip address 10.201.0.1/24
|
||||||
|
!
|
||||||
|
interface r1-eth0
|
||||||
|
ip address 10.125.0.1/24
|
||||||
|
!
|
38
tests/topotests/bgp_vpnv4_gre/r2/bgp_ipv4_routes.json
Normal file
38
tests/topotests/bgp_vpnv4_gre/r2/bgp_ipv4_routes.json
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"vrfName": "vrf1",
|
||||||
|
"localAS": 65500,
|
||||||
|
"routes":
|
||||||
|
{
|
||||||
|
"10.201.0.0/24": [
|
||||||
|
{
|
||||||
|
"prefix": "10.201.0.0",
|
||||||
|
"prefixLen": 24,
|
||||||
|
"network": "10.201.0.0\/24",
|
||||||
|
"nhVrfName": "default",
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"ip": "192.0.2.1",
|
||||||
|
"afi": "ipv4",
|
||||||
|
"used": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"10.200.0.0/24": [
|
||||||
|
{
|
||||||
|
"valid": true,
|
||||||
|
"bestpath": true,
|
||||||
|
"prefix": "10.200.0.0",
|
||||||
|
"prefixLen": 24,
|
||||||
|
"network": "10.200.0.0\/24",
|
||||||
|
"nexthops": [
|
||||||
|
{
|
||||||
|
"ip": "0.0.0.0",
|
||||||
|
"afi": "ipv4",
|
||||||
|
"used": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
22
tests/topotests/bgp_vpnv4_gre/r2/bgpd.conf
Normal file
22
tests/topotests/bgp_vpnv4_gre/r2/bgpd.conf
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
router bgp 65500
|
||||||
|
bgp router-id 192.0.2.2
|
||||||
|
neighbor 192.0.2.1 remote-as 65500
|
||||||
|
neighbor 192.0.2.1 update-source 192.0.2.2
|
||||||
|
address-family ipv4 unicast
|
||||||
|
no neighbor 192.0.2.1 activate
|
||||||
|
exit-address-family
|
||||||
|
address-family ipv4 vpn
|
||||||
|
neighbor 192.0.2.1 activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
router bgp 65500 vrf vrf1
|
||||||
|
bgp router-id 192.0.2.2
|
||||||
|
address-family ipv4 unicast
|
||||||
|
redistribute connected
|
||||||
|
label vpn export 102
|
||||||
|
rd vpn export 444:2
|
||||||
|
rt vpn both 52:100
|
||||||
|
export vpn
|
||||||
|
import vpn
|
||||||
|
exit-address-family
|
||||||
|
!
|
14
tests/topotests/bgp_vpnv4_gre/r2/zebra.conf
Normal file
14
tests/topotests/bgp_vpnv4_gre/r2/zebra.conf
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
log stdout
|
||||||
|
ip route 192.0.2.1/32 192.168.0.1
|
||||||
|
interface lo
|
||||||
|
ip address 192.0.2.2/32
|
||||||
|
!
|
||||||
|
interface r2-gre0
|
||||||
|
ip address 192.168.0.2/24
|
||||||
|
!
|
||||||
|
interface r2-eth1 vrf vrf1
|
||||||
|
ip address 10.200.0.2/24
|
||||||
|
!
|
||||||
|
interface r2-eth0
|
||||||
|
ip address 10.125.0.2/24
|
||||||
|
!
|
191
tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
Normal file
191
tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# test_bgp_vpnv4_gre.py
|
||||||
|
# Part of NetDEF Topology Tests
|
||||||
|
#
|
||||||
|
# Copyright (c) 2021 by 6WIND
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software
|
||||||
|
# for any purpose with or without fee is hereby granted, provided
|
||||||
|
# that the above copyright notice and this permission notice appear
|
||||||
|
# in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
|
||||||
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
|
||||||
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||||
|
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||||
|
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
# OF THIS SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
test_bgp_vpnv4_gre.py: Test the FRR BGP daemon with BGP IPv6 interface
|
||||||
|
with route advertisements on a separate netns.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
from functools import partial
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
# Save the Current Working Directory to find configuration files.
|
||||||
|
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.join(CWD, "../"))
|
||||||
|
|
||||||
|
# pylint: disable=C0413
|
||||||
|
# Import topogen and topotest helpers
|
||||||
|
from lib import topotest
|
||||||
|
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||||
|
from lib.topolog import logger
|
||||||
|
|
||||||
|
# Required to instantiate the topology builder class.
|
||||||
|
|
||||||
|
|
||||||
|
pytestmark = [pytest.mark.bgpd]
|
||||||
|
|
||||||
|
|
||||||
|
def build_topo(tgen):
|
||||||
|
"Build function"
|
||||||
|
|
||||||
|
# Create 2 routers.
|
||||||
|
tgen.add_router("r1")
|
||||||
|
tgen.add_router("r2")
|
||||||
|
|
||||||
|
switch = tgen.add_switch("s1")
|
||||||
|
switch.add_link(tgen.gears["r1"])
|
||||||
|
switch.add_link(tgen.gears["r2"])
|
||||||
|
|
||||||
|
switch = tgen.add_switch("s2")
|
||||||
|
switch.add_link(tgen.gears["r1"])
|
||||||
|
|
||||||
|
switch = tgen.add_switch("s3")
|
||||||
|
switch.add_link(tgen.gears["r2"])
|
||||||
|
|
||||||
|
def _populate_iface():
|
||||||
|
tgen = get_topogen()
|
||||||
|
cmds_list = [
|
||||||
|
'ip link add vrf1 type vrf table 10',
|
||||||
|
'echo 10 > /proc/sys/net/mpls/platform_labels',
|
||||||
|
'ip link set dev vrf1 up',
|
||||||
|
'ip link set dev {0}-eth1 master vrf1',
|
||||||
|
'echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input',
|
||||||
|
'ip tunnel add {0}-gre0 mode gre ttl 64 dev {0}-eth0 local 10.125.0.{1} remote 10.125.0.{2}',
|
||||||
|
'ip link set dev {0}-gre0 up',
|
||||||
|
'echo 1 > /proc/sys/net/mpls/conf/{0}-gre0/input',
|
||||||
|
]
|
||||||
|
|
||||||
|
for cmd in cmds_list:
|
||||||
|
input = cmd.format('r1', '1', '2')
|
||||||
|
logger.info('input: ' + cmd)
|
||||||
|
output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2'))
|
||||||
|
logger.info('output: ' + output)
|
||||||
|
|
||||||
|
for cmd in cmds_list:
|
||||||
|
input = cmd.format('r2', '2', '1')
|
||||||
|
logger.info('input: ' + cmd)
|
||||||
|
output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1'))
|
||||||
|
logger.info('output: ' + output)
|
||||||
|
|
||||||
|
def setup_module(mod):
|
||||||
|
"Sets up the pytest environment"
|
||||||
|
tgen = Topogen(build_topo, mod.__name__)
|
||||||
|
tgen.start_topology()
|
||||||
|
|
||||||
|
router_list = tgen.routers()
|
||||||
|
_populate_iface()
|
||||||
|
|
||||||
|
for rname, router in router_list.items():
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||||
|
)
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize all routers.
|
||||||
|
tgen.start_router()
|
||||||
|
|
||||||
|
|
||||||
|
def teardown_module(_mod):
|
||||||
|
"Teardown the pytest environment"
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
|
def test_protocols_convergence():
|
||||||
|
"""
|
||||||
|
Assert that all protocols have converged
|
||||||
|
statuses as they depend on it.
|
||||||
|
"""
|
||||||
|
tgen = get_topogen()
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
router = tgen.gears['r1']
|
||||||
|
logger.info("Dump some context for r1")
|
||||||
|
router.vtysh_cmd("show bgp ipv4 vpn")
|
||||||
|
router.vtysh_cmd("show bgp summary")
|
||||||
|
router.vtysh_cmd("show bgp vrf vrf1 ipv4")
|
||||||
|
router.vtysh_cmd("show running-config")
|
||||||
|
router = tgen.gears['r2']
|
||||||
|
logger.info("Dump some context for r2")
|
||||||
|
router.vtysh_cmd("show bgp ipv4 vpn")
|
||||||
|
router.vtysh_cmd("show bgp summary")
|
||||||
|
router.vtysh_cmd("show bgp vrf vrf1 ipv4")
|
||||||
|
router.vtysh_cmd("show running-config")
|
||||||
|
|
||||||
|
# Check IPv4 routing tables on r1
|
||||||
|
logger.info("Checking IPv4 routes for convergence on r1")
|
||||||
|
router = tgen.gears['r1']
|
||||||
|
json_file = "{}/{}/ipv4_routes.json".format(CWD, router.name)
|
||||||
|
if not os.path.isfile(json_file):
|
||||||
|
logger.info("skipping file {}".format(json_file))
|
||||||
|
assert 0, 'ipv4_routes.json file not found'
|
||||||
|
return
|
||||||
|
|
||||||
|
expected = json.loads(open(json_file).read())
|
||||||
|
test_func = partial(
|
||||||
|
topotest.router_json_cmp,
|
||||||
|
router,
|
||||||
|
"show ip route vrf vrf1 json",
|
||||||
|
expected,
|
||||||
|
)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
|
||||||
|
assertmsg = '"{}" JSON output mismatches'.format(router.name)
|
||||||
|
assert result is None, assertmsg
|
||||||
|
|
||||||
|
# Check BGP IPv4 routing tables on r2 not installed
|
||||||
|
logger.info("Checking BGP IPv4 routes for convergence on r2")
|
||||||
|
router = tgen.gears['r2']
|
||||||
|
json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name)
|
||||||
|
if not os.path.isfile(json_file):
|
||||||
|
assert 0, 'bgp_ipv4_routes.json file not found'
|
||||||
|
|
||||||
|
expected = json.loads(open(json_file).read())
|
||||||
|
test_func = partial(
|
||||||
|
topotest.router_json_cmp,
|
||||||
|
router,
|
||||||
|
"show bgp vrf vrf1 ipv4 json",
|
||||||
|
expected,
|
||||||
|
)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
|
||||||
|
assertmsg = '"{}" JSON output mismatches'.format(router.name)
|
||||||
|
assert result is None, assertmsg
|
||||||
|
|
||||||
|
def test_memory_leak():
|
||||||
|
"Run the memory leak test and report results."
|
||||||
|
tgen = get_topogen()
|
||||||
|
if not tgen.is_memleak_enabled():
|
||||||
|
pytest.skip("Memory leak test/report is disabled")
|
||||||
|
|
||||||
|
tgen.report_memory_leaks()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = ["-s"] + sys.argv[1:]
|
||||||
|
sys.exit(pytest.main(args))
|
@ -60,8 +60,13 @@ extern struct thread_master *master;
|
|||||||
#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_SHARPD|VTYSH_PBRD|VTYSH_STATICD|VTYSH_BFDD|VTYSH_FABRICD|VTYSH_VRRPD|VTYSH_PATHD
|
#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_SHARPD|VTYSH_PBRD|VTYSH_STATICD|VTYSH_BFDD|VTYSH_FABRICD|VTYSH_VRRPD|VTYSH_PATHD
|
||||||
#define VTYSH_ACL VTYSH_BFDD|VTYSH_BABELD|VTYSH_BGPD|VTYSH_EIGRPD|VTYSH_ISISD|VTYSH_FABRICD|VTYSH_LDPD|VTYSH_NHRPD|VTYSH_OSPF6D|VTYSH_OSPFD|VTYSH_PBRD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_VRRPD|VTYSH_ZEBRA
|
#define VTYSH_ACL VTYSH_BFDD|VTYSH_BABELD|VTYSH_BGPD|VTYSH_EIGRPD|VTYSH_ISISD|VTYSH_FABRICD|VTYSH_LDPD|VTYSH_NHRPD|VTYSH_OSPF6D|VTYSH_OSPFD|VTYSH_PBRD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_VRRPD|VTYSH_ZEBRA
|
||||||
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_EIGRPD|VTYSH_FABRICD
|
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_EIGRPD|VTYSH_FABRICD
|
||||||
#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_PBRD|VTYSH_FABRICD|VTYSH_VRRPD
|
#define VTYSH_INTERFACE_SUBSET \
|
||||||
#define VTYSH_VRF VTYSH_INTERFACE|VTYSH_STATICD
|
VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D | \
|
||||||
|
VTYSH_ISISD | VTYSH_PIMD | VTYSH_PIM6D | VTYSH_NHRPD | \
|
||||||
|
VTYSH_EIGRPD | VTYSH_BABELD | VTYSH_PBRD | VTYSH_FABRICD | \
|
||||||
|
VTYSH_VRRPD
|
||||||
|
#define VTYSH_INTERFACE VTYSH_INTERFACE_SUBSET | VTYSH_BGPD
|
||||||
|
#define VTYSH_VRF VTYSH_INTERFACE_SUBSET | VTYSH_STATICD
|
||||||
#define VTYSH_KEYS VTYSH_RIPD | VTYSH_EIGRPD | VTYSH_OSPF6D
|
#define VTYSH_KEYS VTYSH_RIPD | VTYSH_EIGRPD | VTYSH_OSPF6D
|
||||||
/* Daemons who can process nexthop-group configs */
|
/* Daemons who can process nexthop-group configs */
|
||||||
#define VTYSH_NH_GROUP VTYSH_PBRD|VTYSH_SHARPD
|
#define VTYSH_NH_GROUP VTYSH_PBRD|VTYSH_SHARPD
|
||||||
|
@ -330,6 +330,12 @@ module frr-bgp-route-map {
|
|||||||
"Set EVPN gateway IP overlay index IPv6";
|
"Set EVPN gateway IP overlay index IPv6";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
identity set-l3vpn-nexthop-encapsulation {
|
||||||
|
base frr-route-map:rmap-set-type;
|
||||||
|
description
|
||||||
|
"Accept L3VPN traffic over other than LSP encapsulation";
|
||||||
|
}
|
||||||
|
|
||||||
grouping extcommunity-non-transitive-types {
|
grouping extcommunity-non-transitive-types {
|
||||||
leaf two-octet-as-specific {
|
leaf two-octet-as-specific {
|
||||||
type boolean;
|
type boolean;
|
||||||
@ -902,5 +908,21 @@ module frr-bgp-route-map {
|
|||||||
type inet:ipv6-address;
|
type inet:ipv6-address;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case l3vpn-nexthop-encapsulation {
|
||||||
|
when
|
||||||
|
"derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action,
|
||||||
|
'frr-bgp-route-map:set-l3vpn-nexthop-encapsulation')";
|
||||||
|
description
|
||||||
|
"Accept L3VPN traffic over other than LSP encapsulation";
|
||||||
|
leaf l3vpn-nexthop-encapsulation {
|
||||||
|
type enumeration {
|
||||||
|
enum "gre" {
|
||||||
|
value 0;
|
||||||
|
description
|
||||||
|
"GRE protocol";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user