mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-10-31 10:31:50 +00:00 
			
		
		
		
	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); | ||||
| @ -579,7 +610,8 @@ void ospf_free_if_params(struct interface *ifp, struct in_addr addr) | ||||
| 	    !OSPF_IF_PARAM_CONFIGURED(oip, if_area) && | ||||
| 	    !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, 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 New Issue
	
	Block a user
	 Acee Lindem
						Acee Lindem