forked from Mirror/frr
ospfd: Add prefix-list filtering of OSPF neighbors on OSPF interface
This commit adds the capabiity to filter OSPF neighbors using a prefix-list with rules matching the neighbor's IP source address. Configuration, filtering, immediate neighbor pruning, topo-tests, and documentation are included. The command is: ip ospf neighbor-filter <prefix-list> [A.B.C.D] Signed-off-by: Acee Lindem <acee@lindem.com>
This commit is contained in:
parent
84d1fb19e2
commit
0ccad8a2b0
|
@ -757,6 +757,32 @@ Interfaces
|
|||
optional IPv4 address is specified, the prefix suppression will apply
|
||||
to the OSPF interface associated with the specified interface address.
|
||||
|
||||
.. clicmd:: ip ospf neighbor-filter NAME [A.B.C.D]
|
||||
|
||||
Configure an IP prefix-list to use to filter packets received from
|
||||
OSPF neighbors on the OSPF interface. The prefix-list should include rules
|
||||
to permit or deny OSPF neighbors by IP source address. This is useful for
|
||||
multi-access interfaces where adjacencies with only a subset of the
|
||||
reachable neighbors are desired. Applications include testing partially
|
||||
meshed topologies, OSPF Denial of Sevice (DoS) mitigation, and avoidance
|
||||
of adjacencies with OSPF neighbors not meeting traffic engineering criteria.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: frr
|
||||
|
||||
!
|
||||
! Prefix-list to block neighbor with source address 10.1.0.2
|
||||
!
|
||||
ip prefix-list nbr-filter seq 10 deny 10.1.0.2/32
|
||||
ip prefix-list nbr-filter seq 200 permit any
|
||||
!
|
||||
! Configure the neighbor filter prefix-list on interface eth0
|
||||
!
|
||||
interface eth0
|
||||
ip ospf neighbor-filter nbr-filter
|
||||
!
|
||||
|
||||
.. clicmd:: ip ospf area (A.B.C.D|(0-4294967295))
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "zclient.h"
|
||||
#include "bfd.h"
|
||||
#include "ldp_sync.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "ospfd/ospfd.h"
|
||||
#include "ospfd/ospf_bfd.h"
|
||||
|
@ -67,6 +68,34 @@ int ospf_interface_neighbor_count(struct ospf_interface *oi)
|
|||
return count;
|
||||
}
|
||||
|
||||
|
||||
void ospf_intf_neighbor_filter_apply(struct ospf_interface *oi)
|
||||
{
|
||||
struct route_node *rn;
|
||||
struct ospf_neighbor *nbr = NULL;
|
||||
struct prefix nbr_src_prefix = { AF_INET, IPV4_MAX_BITLEN, { 0 } };
|
||||
|
||||
if (!oi->nbr_filter)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Kill neighbors that don't match the neighbor filter prefix-list
|
||||
* excluding the neighbor for the router itself and any neighbors
|
||||
* that are already down.
|
||||
*/
|
||||
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
|
||||
nbr = rn->info;
|
||||
if (nbr && nbr != oi->nbr_self && nbr->state != NSM_Down) {
|
||||
nbr_src_prefix.u.prefix4 = nbr->src;
|
||||
if (prefix_list_apply(oi->nbr_filter,
|
||||
(struct prefix *)&(
|
||||
nbr_src_prefix)) !=
|
||||
PREFIX_PERMIT)
|
||||
OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ospf_if_get_output_cost(struct ospf_interface *oi)
|
||||
{
|
||||
/* If all else fails, use default OSPF cost */
|
||||
|
@ -526,6 +555,7 @@ static struct ospf_if_params *ospf_new_if_params(void)
|
|||
UNSET_IF_PARAM(oip, if_area);
|
||||
UNSET_IF_PARAM(oip, opaque_capable);
|
||||
UNSET_IF_PARAM(oip, keychain_name);
|
||||
UNSET_IF_PARAM(oip, nbr_filter_name);
|
||||
|
||||
oip->auth_crypt = list_new();
|
||||
|
||||
|
@ -544,6 +574,7 @@ static void ospf_del_if_params(struct interface *ifp,
|
|||
{
|
||||
list_delete(&oip->auth_crypt);
|
||||
XFREE(MTYPE_OSPF_IF_PARAMS, oip->keychain_name);
|
||||
XFREE(MTYPE_OSPF_IF_PARAMS, oip->nbr_filter_name);
|
||||
ospf_interface_disable_bfd(ifp, oip);
|
||||
ldp_sync_info_free(&(oip->ldp_sync_info));
|
||||
XFREE(MTYPE_OSPF_IF_PARAMS, oip);
|
||||
|
@ -580,6 +611,7 @@ void ospf_free_if_params(struct interface *ifp, struct in_addr addr)
|
|||
!OSPF_IF_PARAM_CONFIGURED(oip, opaque_capable) &&
|
||||
!OSPF_IF_PARAM_CONFIGURED(oip, prefix_suppression) &&
|
||||
!OSPF_IF_PARAM_CONFIGURED(oip, keychain_name) &&
|
||||
!OSPF_IF_PARAM_CONFIGURED(oip, nbr_filter_name) &&
|
||||
listcount(oip->auth_crypt) == 0) {
|
||||
ospf_del_if_params(ifp, oip);
|
||||
rn->info = NULL;
|
||||
|
|
|
@ -124,6 +124,9 @@ struct ospf_if_params {
|
|||
|
||||
/* Opaque LSA capability at interface level (see RFC5250) */
|
||||
DECLARE_IF_PARAM(bool, opaque_capable);
|
||||
|
||||
/* Name of prefix-list name for packet source address filtering. */
|
||||
DECLARE_IF_PARAM(char *, nbr_filter_name);
|
||||
};
|
||||
|
||||
enum { MEMBER_ALLROUTERS = 0,
|
||||
|
@ -242,6 +245,9 @@ struct ospf_interface {
|
|||
/* List of configured NBMA neighbor. */
|
||||
struct list *nbr_nbma;
|
||||
|
||||
/* Configured prefix-list for filtering neighbors. */
|
||||
struct prefix_list *nbr_filter;
|
||||
|
||||
/* Graceful-Restart data. */
|
||||
struct {
|
||||
struct {
|
||||
|
@ -367,6 +373,7 @@ extern void ospf_crypt_key_add(struct list *list, struct crypt_key *key);
|
|||
extern int ospf_crypt_key_delete(struct list *list, uint8_t key_id);
|
||||
extern uint8_t ospf_default_iftype(struct interface *ifp);
|
||||
extern int ospf_interface_neighbor_count(struct ospf_interface *oi);
|
||||
extern void ospf_intf_neighbor_filter_apply(struct ospf_interface *oi);
|
||||
|
||||
/* Set all multicast memberships appropriately based on the type and
|
||||
state of the interface. */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#endif
|
||||
#include "vrf.h"
|
||||
#include "lib_errors.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "ospfd/ospfd.h"
|
||||
#include "ospfd/ospf_network.h"
|
||||
|
@ -2746,6 +2747,20 @@ static enum ospf_read_return_enum ospf_read_helper(struct ospf *ospf)
|
|||
/* associate packet with ospf interface */
|
||||
oi = ospf_if_lookup_recv_if(ospf, iph->ip_src, ifp);
|
||||
|
||||
/*
|
||||
* If a neighbor filter prefix-list is configured, apply it to the IP
|
||||
* source address and ignore the packet if it doesn't match.
|
||||
*/
|
||||
if (oi && oi->nbr_filter) {
|
||||
struct prefix ip_src_prefix = { AF_INET, IPV4_MAX_BITLEN, { 0 } };
|
||||
|
||||
ip_src_prefix.u.prefix4 = iph->ip_src;
|
||||
if (prefix_list_apply(oi->nbr_filter,
|
||||
(struct prefix *)&(ip_src_prefix)) !=
|
||||
PREFIX_PERMIT)
|
||||
return OSPF_READ_CONTINUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ospf_verify_header() relies on a valid "oi" and thus can be called
|
||||
* only after the passive/backbone/other checks below are passed.
|
||||
|
|
|
@ -4084,6 +4084,31 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
|
|||
if (use_json)
|
||||
json_object_object_addf(json_ois, json_oi, "%pI4",
|
||||
&oi->address->u.prefix4);
|
||||
|
||||
if (oi->nbr_filter) {
|
||||
if (use_json) {
|
||||
json_object_string_add(json_interface_sub,
|
||||
"nbrFilterPrefixList",
|
||||
prefix_list_name(
|
||||
oi->nbr_filter));
|
||||
json_object_string_add(json_oi,
|
||||
"nbrFilterPrefixList",
|
||||
prefix_list_name(
|
||||
oi->nbr_filter));
|
||||
} else
|
||||
vty_out(vty,
|
||||
" Neighbor filter prefix-list: %s\n",
|
||||
prefix_list_name(oi->nbr_filter));
|
||||
} else {
|
||||
if (use_json) {
|
||||
json_object_string_add(json_interface_sub,
|
||||
"nbrFilterPrefixList",
|
||||
"N/A");
|
||||
json_object_string_add(json_oi,
|
||||
"nbrFilterPrefixList",
|
||||
"N/A");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9936,6 +9961,58 @@ DEFPY(ip_ospf_prefix_suppression, ip_ospf_prefix_suppression_addr_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY(ip_ospf_neighbor_filter, ip_ospf_neighbor_filter_addr_cmd,
|
||||
"[no] ip ospf neighbor-filter ![PREFIXLIST4_NAME]$prefix_list [A.B.C.D]$ip_addr", NO_STR
|
||||
"IP Information\n"
|
||||
"OSPF interface commands\n"
|
||||
"Filter OSPF neighbor packets\n"
|
||||
"Prefix-List used for filtering\n"
|
||||
"Address of interface\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct ospf_if_params *params;
|
||||
struct prefix_list *nbr_filter = NULL;
|
||||
struct route_node *rn;
|
||||
|
||||
params = IF_DEF_PARAMS(ifp);
|
||||
|
||||
if (ip_addr.s_addr != INADDR_ANY) {
|
||||
params = ospf_get_if_params(ifp, ip_addr);
|
||||
ospf_if_update_params(ifp, ip_addr);
|
||||
}
|
||||
|
||||
if (params->nbr_filter_name)
|
||||
XFREE(MTYPE_OSPF_IF_PARAMS, params->nbr_filter_name);
|
||||
|
||||
if (no) {
|
||||
UNSET_IF_PARAM(params, nbr_filter_name);
|
||||
params->nbr_filter_name = NULL;
|
||||
} else {
|
||||
SET_IF_PARAM(params, nbr_filter_name);
|
||||
params->nbr_filter_name = XSTRDUP(MTYPE_OSPF_IF_PARAMS,
|
||||
prefix_list);
|
||||
nbr_filter = prefix_list_lookup(AFI_IP, params->nbr_filter_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if there is a change in neighbor filter prefix-list for the
|
||||
* interface.
|
||||
*/
|
||||
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
|
||||
struct ospf_interface *oi = rn->info;
|
||||
|
||||
if (oi &&
|
||||
(ip_addr.s_addr == INADDR_ANY ||
|
||||
IPV4_ADDR_SAME(&oi->address->u.prefix4, &ip_addr)) &&
|
||||
oi->nbr_filter != nbr_filter) {
|
||||
oi->nbr_filter = nbr_filter;
|
||||
if (oi->nbr_filter)
|
||||
ospf_intf_neighbor_filter_apply(oi);
|
||||
}
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf_max_metric_router_lsa_admin,
|
||||
ospf_max_metric_router_lsa_admin_cmd,
|
||||
"max-metric router-lsa administrative",
|
||||
|
@ -12359,6 +12436,15 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
|
|||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
/* neighbor-filter print. */
|
||||
if (OSPF_IF_PARAM_CONFIGURED(params, nbr_filter_name)) {
|
||||
vty_out(vty, " ip ospf neighbor-filter %s",
|
||||
params->nbr_filter_name);
|
||||
if (params != IF_DEF_PARAMS(ifp) && rn)
|
||||
vty_out(vty, " %pI4", &rn->p.u.prefix4);
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (rn == NULL)
|
||||
rn = route_top(IF_OIFS_PARAMS(ifp));
|
||||
|
@ -13175,6 +13261,9 @@ static void ospf_vty_if_init(void)
|
|||
/* "ip ospf prefix-suppression" commands. */
|
||||
install_element(INTERFACE_NODE, &ip_ospf_prefix_suppression_addr_cmd);
|
||||
|
||||
/* "ip ospf neighbor-filter" commands. */
|
||||
install_element(INTERFACE_NODE, &ip_ospf_neighbor_filter_addr_cmd);
|
||||
|
||||
/* These commands are compatibitliy for previous version. */
|
||||
install_element(INTERFACE_NODE, &ospf_authentication_key_cmd);
|
||||
install_element(INTERFACE_NODE, &ospf_message_digest_key_cmd);
|
||||
|
|
|
@ -1769,6 +1769,7 @@ static void ospf_prefix_list_update(struct prefix_list *plist)
|
|||
int type;
|
||||
int abr_inv = 0;
|
||||
struct ospf_area *area;
|
||||
struct ospf_interface *oi;
|
||||
struct listnode *node, *n1;
|
||||
|
||||
/* If OSPF instatnce does not exist, return right now. */
|
||||
|
@ -1824,6 +1825,19 @@ static void ospf_prefix_list_update(struct prefix_list *plist)
|
|||
}
|
||||
}
|
||||
|
||||
/* Update interface neighbor-filter lists. */
|
||||
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
|
||||
if (OSPF_IF_PARAM(oi, nbr_filter_name) &&
|
||||
strcmp(OSPF_IF_PARAM(oi, nbr_filter_name),
|
||||
prefix_list_name(plist)) == 0) {
|
||||
oi->nbr_filter = prefix_list_lookup(
|
||||
AFI_IP,
|
||||
OSPF_IF_PARAM(oi, nbr_filter_name));
|
||||
if (oi->nbr_filter)
|
||||
ospf_intf_neighbor_filter_apply(oi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Schedule ABR task. */
|
||||
if (IS_OSPF_ABR(ospf) && abr_inv)
|
||||
ospf_schedule_abr_task(ospf);
|
||||
|
|
|
@ -118,17 +118,21 @@ def teardown_module(mod):
|
|||
tgen.stop_topology()
|
||||
|
||||
|
||||
def verify_p2mp_interface(tgen):
|
||||
def verify_p2mp_interface(tgen, router, nbr_cnt, nbr_adj_cnt, nbr_filter):
|
||||
"Verify the P2MP Configuration and interface settings"
|
||||
|
||||
r1 = tgen.gears["r1"]
|
||||
topo_router = tgen.gears[router]
|
||||
|
||||
step("Test running configuration for P2MP configuration")
|
||||
rc = 0
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
rc, _, _ = tgen.net[router].cmd_status(
|
||||
"show running ospfd | grep 'ip ospf network point-to-multipoint'", warn=False
|
||||
)
|
||||
assertmsg = "'ip ospf network point-to-multipoint' applied, but not present in r1 configuration"
|
||||
assertmsg = (
|
||||
"'ip ospf network point-to-multipoint' applied, but not present in "
|
||||
+ router
|
||||
+ "configuration"
|
||||
)
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Test OSPF interface for P2MP settings")
|
||||
|
@ -145,11 +149,11 @@ def verify_p2mp_interface(tgen):
|
|||
"networkType": "POINTOMULTIPOINT",
|
||||
"cost": 10,
|
||||
"state": "Point-To-Point",
|
||||
"nbrCount": 3,
|
||||
"nbrAdjacentCount": 3,
|
||||
"nbrCount": nbr_cnt,
|
||||
"nbrAdjacentCount": nbr_adj_cnt,
|
||||
"prefixSuppression": False,
|
||||
"p2mpDelayReflood": False,
|
||||
"p2mpNonBroadcast": False,
|
||||
"nbrFilterPrefixList": nbr_filter,
|
||||
}
|
||||
},
|
||||
"ipAddress": "10.1.0.1",
|
||||
|
@ -161,16 +165,19 @@ def verify_p2mp_interface(tgen):
|
|||
"cost": 10,
|
||||
"state": "Point-To-Point",
|
||||
"opaqueCapable": True,
|
||||
"nbrCount": 3,
|
||||
"nbrAdjacentCount": 3,
|
||||
"nbrCount": nbr_cnt,
|
||||
"nbrAdjacentCount": nbr_adj_cnt,
|
||||
"prefixSuppression": False,
|
||||
"p2mpDelayReflood": False,
|
||||
"p2mpNonBroadcast": False,
|
||||
"nbrFilterPrefixList": nbr_filter,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r1, "show ip ospf interface r1-eth0 json", input_dict
|
||||
topotest.router_json_cmp,
|
||||
topo_router,
|
||||
"show ip ospf interface r1-eth0 json",
|
||||
input_dict,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "P2MP Interface Mismatch on router r1"
|
||||
|
@ -251,6 +258,23 @@ def verify_p2mp_neighbor(tgen, router, neighbor, state, intf_addr, interface):
|
|||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def verify_p2mp_neighbor_missing(tgen, router, neighbor):
|
||||
topo_router = tgen.gears[router]
|
||||
|
||||
step("Verify neighbor " + neighbor + " missing")
|
||||
input_dict = {"default": {}}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
topo_router,
|
||||
"show ip ospf neighbor " + neighbor + " json",
|
||||
input_dict,
|
||||
True, # Require exact match for missing neighbor
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "P2MP Neighbor " + neighbor + " not missing"
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def verify_p2mp_route(tgen, router, prefix, prefix_len, nexthop, interface):
|
||||
topo_router = tgen.gears[router]
|
||||
|
||||
|
@ -288,7 +312,7 @@ def test_p2mp_broadcast_interface():
|
|||
pytest.skip("Skipped because of router(s) failure")
|
||||
|
||||
step("Verify router r1 interface r1-eth0 p2mp configuration")
|
||||
verify_p2mp_interface(tgen)
|
||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
||||
|
||||
step("Verify router r1 p2mp interface r1-eth0 neighbors")
|
||||
verify_p2mp_neighbor(
|
||||
|
@ -313,7 +337,7 @@ def test_p2mp_broadcast_interface():
|
|||
|
||||
step("Verify router r1 interface r1-eth0 p2mp configuration application")
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf network point-to-multipoint")
|
||||
verify_p2mp_interface(tgen)
|
||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
||||
|
||||
step("Verify restablishment of r1-eth0 p2mp neighbors")
|
||||
verify_p2mp_neighbor(
|
||||
|
@ -332,6 +356,108 @@ def test_p2mp_broadcast_interface():
|
|||
verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
|
||||
|
||||
|
||||
def test_p2mp_broadcast_neighbor_filter():
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip("Skipped because of router(s) failure")
|
||||
|
||||
step("Verify router r1 interface r1-eth0 p2mp configuration")
|
||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
||||
|
||||
step("Verify router r1 p2mp interface r1-eth0 neighbors")
|
||||
verify_p2mp_neighbor(
|
||||
tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
|
||||
)
|
||||
verify_p2mp_neighbor(
|
||||
tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
|
||||
)
|
||||
verify_p2mp_neighbor(
|
||||
tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
|
||||
)
|
||||
|
||||
step("Add OSPF interface neighbor-filter to r1")
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter")
|
||||
|
||||
step("Verify the R1 configuration of 'ip ospf neighbor-filter nbr-filter'")
|
||||
neighbor_filter_cfg = (
|
||||
tgen.net["r1"]
|
||||
.cmd(
|
||||
'vtysh -c "show running ospfd" | grep "^ ip ospf neighbor-filter nbr-filter"'
|
||||
)
|
||||
.rstrip()
|
||||
)
|
||||
assertmsg = (
|
||||
"'ip ospf neighbor-filter nbr-filter' applied, but not present in configuration"
|
||||
)
|
||||
assert neighbor_filter_cfg == " ip ospf neighbor-filter nbr-filter", assertmsg
|
||||
|
||||
step("Verify non-existent neighbor-filter is not applied to r1 interfaces")
|
||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
||||
|
||||
step("Add nbr-filter prefix-list configuration to r1")
|
||||
r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 200 permit any")
|
||||
|
||||
step(
|
||||
"Verify neighbor-filter is now applied to r1 interface and neighbors still adjacent"
|
||||
)
|
||||
verify_p2mp_interface(tgen, "r1", 3, 3, "nbr-filter")
|
||||
|
||||
step("Add nbr-filter prefix-list configuration to block r4")
|
||||
r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 10 deny 10.1.0.4/32")
|
||||
|
||||
step(
|
||||
"Verify neighbor-filter is now applied to r1 interface and r4 is no longer adjacent"
|
||||
)
|
||||
verify_p2mp_interface(tgen, "r1", 2, 2, "nbr-filter")
|
||||
verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4")
|
||||
|
||||
step("Verify route to r4 subnet is now through r2")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.2", "r1-eth0")
|
||||
|
||||
step("Add nbr-filter prefix-list configuration to block r2")
|
||||
r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 20 deny 10.1.0.2/32")
|
||||
|
||||
step(
|
||||
"Verify neighbor-filter is now applied to r1 interface and r2 is no longer adjacent"
|
||||
)
|
||||
verify_p2mp_interface(tgen, "r1", 1, 1, "nbr-filter")
|
||||
verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2")
|
||||
|
||||
step("Verify route to r4 and r2 subnet are now through r3")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.3", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.3", "r1-eth0")
|
||||
|
||||
step("Remove neighbor filter configuration and verify")
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip ospf neighbor-filter")
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
"show running ospfd | grep -q 'ip ospf neighbor-filter'", warn=False
|
||||
)
|
||||
assertmsg = "'ip ospf neighbor' not applied, but present in R1 configuration"
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Verify interface neighbor-filter is removed and neighbors present")
|
||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
||||
|
||||
step("Add neighbor filter configuration and verify neighbors are filtered")
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter")
|
||||
verify_p2mp_interface(tgen, "r1", 1, 1, "nbr-filter")
|
||||
verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2")
|
||||
verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4")
|
||||
|
||||
step("Remove nbr-filter prefix-list configuration to block r2 and verify neighbor")
|
||||
r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter seq 20")
|
||||
verify_p2mp_interface(tgen, "r1", 2, 2, "nbr-filter")
|
||||
verify_p2mp_neighbor(
|
||||
tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
|
||||
)
|
||||
|
||||
step("Delete nbr-filter prefix-list and verify neighbors are present")
|
||||
r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter")
|
||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
||||
|
||||
|
||||
def test_memory_leak():
|
||||
"Run the memory leak test and report results."
|
||||
tgen = get_topogen()
|
||||
|
|
Loading…
Reference in a new issue