mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
Merge pull request #14034 from LabNConsulting/aceelindem/ospf_prefix_suppression
ospfd: Implement OSPF prefix-suppression as specified in RFC 6860
This commit is contained in:
commit
3a58764e3a
|
@ -699,6 +699,15 @@ Interfaces
|
|||
OSPF (:ref:`redistribute-routes-to-ospf`). This is the only way to
|
||||
advertise non-OSPF links into stub areas.
|
||||
|
||||
.. clicmd:: ip ospf prefix-suppression [A.B.C.D]
|
||||
|
||||
Configure OSPF to not advertise the IPv4 prefix associated with the
|
||||
OSPF interface. The associated IPv4 prefix will be omitted from an OSPF
|
||||
router-LSA or advertised with a host mask in an OSPF network-LSA as
|
||||
specified in RFC 6860, "Hiding Transit-Only Networks in OSPF". If an
|
||||
optional IPv4 address is specified, the prefix suppression will apply
|
||||
to the OSPF interface associated with the specified interface address.
|
||||
|
||||
.. clicmd:: ip ospf area (A.B.C.D|(0-4294967295))
|
||||
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ extern "C" {
|
|||
#define OSPF_FAST_HELLO_DEFAULT 0
|
||||
#define OSPF_P2MP_DELAY_REFLOOD_DEFAULT false
|
||||
#define OSPF_OPAQUE_CAPABLE_DEFAULT true
|
||||
|
||||
#define OSPF_PREFIX_SUPPRESSION_DEFAULT false
|
||||
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
|
||||
#define OSPF_AREA_RANGE_COST_UNSPEC -1U
|
||||
|
||||
|
|
|
@ -600,6 +600,7 @@ void ospf_free_if_params(struct interface *ifp, struct in_addr addr)
|
|||
!OSPF_IF_PARAM_CONFIGURED(oip, auth_type) &&
|
||||
!OSPF_IF_PARAM_CONFIGURED(oip, if_area) &&
|
||||
!OSPF_IF_PARAM_CONFIGURED(oip, opaque_capable) &&
|
||||
!OSPF_IF_PARAM_CONFIGURED(oip, prefix_suppression) &&
|
||||
listcount(oip->auth_crypt) == 0) {
|
||||
ospf_del_if_params(ifp, oip);
|
||||
rn->info = NULL;
|
||||
|
@ -709,6 +710,8 @@ int ospf_if_new_hook(struct interface *ifp)
|
|||
SET_IF_PARAM(IF_DEF_PARAMS(ifp), opaque_capable);
|
||||
IF_DEF_PARAMS(ifp)->opaque_capable = OSPF_OPAQUE_CAPABLE_DEFAULT;
|
||||
|
||||
IF_DEF_PARAMS(ifp)->prefix_suppression = OSPF_PREFIX_SUPPRESSION_DEFAULT;
|
||||
|
||||
rc = ospf_opaque_new_if(ifp);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -81,6 +81,9 @@ struct ospf_if_params {
|
|||
/* Fast-Hellos */
|
||||
DECLARE_IF_PARAM(uint8_t, fast_hello);
|
||||
|
||||
/* Prefix-Suppression */
|
||||
DECLARE_IF_PARAM(bool, prefix_suppression);
|
||||
|
||||
/* Authentication data. */
|
||||
uint8_t auth_simple[OSPF_AUTH_SIMPLE_SIZE + 1]; /* Simple password. */
|
||||
uint8_t auth_simple__config : 1;
|
||||
|
|
|
@ -539,16 +539,23 @@ static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
|
|||
}
|
||||
|
||||
/* no need for a stub link for unnumbered interfaces */
|
||||
if (oi->ptp_dmvpn
|
||||
|| !CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) {
|
||||
/* Regardless of the state of the neighboring router, we must
|
||||
add a Type 3 link (stub network).
|
||||
N.B. Options 1 & 2 share basically the same logic. */
|
||||
masklen2ip(oi->address->prefixlen, &mask);
|
||||
id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr
|
||||
& mask.s_addr;
|
||||
links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0,
|
||||
oi->output_cost);
|
||||
if (OSPF_IF_PARAM(oi, prefix_suppression)) {
|
||||
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
|
||||
zlog_debug("LSA[Type1]: Interface %s stub link omitted due prefix-suppression",
|
||||
oi->ifp->name);
|
||||
} else {
|
||||
if (oi->ptp_dmvpn ||
|
||||
!CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) {
|
||||
/* Regardless of the state of the neighboring router, we must
|
||||
add a Type 3 link (stub network).
|
||||
N.B. Options 1 & 2 share basically the same logic. */
|
||||
masklen2ip(oi->address->prefixlen, &mask);
|
||||
id.s_addr =
|
||||
CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr &
|
||||
mask.s_addr;
|
||||
links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB,
|
||||
0, oi->output_cost);
|
||||
}
|
||||
}
|
||||
|
||||
return links;
|
||||
|
@ -563,10 +570,15 @@ static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi)
|
|||
|
||||
/* Describe Type 3 Link. */
|
||||
if (oi->state == ISM_Waiting) {
|
||||
if (OSPF_IF_PARAM(oi, prefix_suppression)) {
|
||||
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
|
||||
zlog_debug("LSA[Type1]: Interface %s stub link omitted due prefix-suppression",
|
||||
oi->ifp->name);
|
||||
return 0;
|
||||
}
|
||||
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
|
||||
zlog_debug(
|
||||
"LSA[Type1]: Interface %s is in state Waiting. Adding stub interface",
|
||||
oi->ifp->name);
|
||||
zlog_debug("LSA[Type1]: Interface %s is in state Waiting. Adding stub interface",
|
||||
oi->ifp->name);
|
||||
masklen2ip(oi->address->prefixlen, &mask);
|
||||
id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
|
||||
return link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0,
|
||||
|
@ -587,10 +599,15 @@ static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi)
|
|||
}
|
||||
/* Describe type 3 link. */
|
||||
else {
|
||||
if (OSPF_IF_PARAM(oi, prefix_suppression)) {
|
||||
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
|
||||
zlog_debug("LSA[Type1]: Interface %s stub link omitted due prefix-suppression",
|
||||
oi->ifp->name);
|
||||
return 0;
|
||||
}
|
||||
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
|
||||
zlog_debug(
|
||||
"LSA[Type1]: Interface %s has no DR. Adding stub interface",
|
||||
oi->ifp->name);
|
||||
zlog_debug("LSA[Type1]: Interface %s has no DR. Adding stub interface",
|
||||
oi->ifp->name);
|
||||
masklen2ip(oi->address->prefixlen, &mask);
|
||||
id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
|
||||
return link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0,
|
||||
|
@ -603,7 +620,7 @@ static int lsa_link_loopback_set(struct stream **s, struct ospf_interface *oi)
|
|||
struct in_addr id, mask;
|
||||
|
||||
/* Describe Type 3 Link. */
|
||||
if (oi->state != ISM_Loopback)
|
||||
if ((oi->state != ISM_Loopback) || OSPF_IF_PARAM(oi, prefix_suppression))
|
||||
return 0;
|
||||
|
||||
mask.s_addr = 0xffffffff;
|
||||
|
@ -645,9 +662,15 @@ static int lsa_link_ptomp_set(struct stream **s, struct ospf_interface *oi)
|
|||
struct in_addr id, mask;
|
||||
uint16_t cost = ospf_link_cost(oi);
|
||||
|
||||
mask.s_addr = 0xffffffff;
|
||||
id.s_addr = oi->address->u.prefix4.s_addr;
|
||||
links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);
|
||||
if (OSPF_IF_PARAM(oi, prefix_suppression)) {
|
||||
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
|
||||
zlog_debug("LSA[Type1]: Interface %s stub link omitted due prefix-suppression",
|
||||
oi->ifp->name);
|
||||
} else {
|
||||
mask.s_addr = 0xffffffff;
|
||||
id.s_addr = oi->address->u.prefix4.s_addr;
|
||||
links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);
|
||||
}
|
||||
|
||||
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
|
||||
zlog_debug("PointToMultipoint: running ptomultip_set");
|
||||
|
@ -1006,7 +1029,14 @@ static void ospf_network_lsa_body_set(struct stream *s,
|
|||
struct route_node *rn;
|
||||
struct ospf_neighbor *nbr;
|
||||
|
||||
masklen2ip(oi->address->prefixlen, &mask);
|
||||
if (OSPF_IF_PARAM(oi, prefix_suppression)) {
|
||||
mask.s_addr = 0xffffffff;
|
||||
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
|
||||
zlog_debug("LSA[Type2]: Interface %s network mask set to host mask due prefix-suppression",
|
||||
oi->ifp->name);
|
||||
} else {
|
||||
masklen2ip(oi->address->prefixlen, &mask);
|
||||
}
|
||||
stream_put_ipv4(s, mask.s_addr);
|
||||
|
||||
/* The network-LSA lists those routers that are fully adjacent to
|
||||
|
|
|
@ -463,6 +463,12 @@ void ospf_intra_add_transit(struct route_table *rt, struct vertex *v,
|
|||
the IP network number, which can be obtained by masking the
|
||||
Vertex ID (Link State ID) with its associated subnet mask (found
|
||||
in the body of the associated network-LSA). */
|
||||
if (lsa->mask.s_addr == 0xffffffff) {
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_debug("Suppress installing LSA[Type2,%pI4] route due to host mask",
|
||||
&(lsa->header.id));
|
||||
return;
|
||||
}
|
||||
p.family = AF_INET;
|
||||
p.prefix = v->id;
|
||||
p.prefixlen = ip_masklen(lsa->mask);
|
||||
|
|
|
@ -4076,6 +4076,20 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
|
|||
|
||||
ospf_interface_bfd_show(vty, ifp, json_interface_sub);
|
||||
|
||||
if (use_json) {
|
||||
json_object_boolean_add(json_interface_sub,
|
||||
"prefixSuppression",
|
||||
OSPF_IF_PARAM(oi,
|
||||
prefix_suppression));
|
||||
json_object_boolean_add(json_oi, "prefixSuppression",
|
||||
OSPF_IF_PARAM(oi,
|
||||
prefix_suppression));
|
||||
} else {
|
||||
if (OSPF_IF_PARAM(oi, prefix_suppression))
|
||||
vty_out(vty,
|
||||
" Suppress advertisement of interface IP prefix\n");
|
||||
}
|
||||
|
||||
/* OSPF Authentication information */
|
||||
ospf_interface_auth_show(vty, oi, json_interface_sub, use_json);
|
||||
|
||||
|
@ -9865,6 +9879,56 @@ DEFPY(ip_ospf_capability_opaque, ip_ospf_capability_opaque_addr_cmd,
|
|||
}
|
||||
|
||||
|
||||
DEFPY(ip_ospf_prefix_suppression, ip_ospf_prefix_suppression_addr_cmd,
|
||||
"[no] ip ospf prefix-suppression [A.B.C.D]$ip_addr", NO_STR
|
||||
"IP Information\n"
|
||||
"OSPF interface commands\n"
|
||||
"Supress OSPF prefix advertisement on this interface\n"
|
||||
"Address of interface\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct route_node *rn;
|
||||
bool prefix_suppression_change;
|
||||
struct ospf_if_params *params;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
prefix_suppression_change = (params->prefix_suppression == (bool)no);
|
||||
params->prefix_suppression = (no) ? false : true;
|
||||
if (params->prefix_suppression != OSPF_PREFIX_SUPPRESSION_DEFAULT)
|
||||
SET_IF_PARAM(params, prefix_suppression);
|
||||
else {
|
||||
UNSET_IF_PARAM(params, prefix_suppression);
|
||||
if (params != IF_DEF_PARAMS(ifp)) {
|
||||
ospf_free_if_params(ifp, ip_addr);
|
||||
ospf_if_update_params(ifp, ip_addr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a change to the prefix suppression, update the Router-LSA.
|
||||
*/
|
||||
if (prefix_suppression_change) {
|
||||
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
|
||||
struct ospf_interface *oi = rn->info;
|
||||
|
||||
if (oi && (oi->state > ISM_Down) &&
|
||||
(ip_addr.s_addr == INADDR_ANY ||
|
||||
IPV4_ADDR_SAME(&oi->address->u.prefix4, &ip_addr))) {
|
||||
(void)ospf_router_lsa_update_area(oi->area);
|
||||
if (oi->state == ISM_DR)
|
||||
ospf_network_lsa_update(oi);
|
||||
}
|
||||
}
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf_max_metric_router_lsa_admin,
|
||||
ospf_max_metric_router_lsa_admin_cmd,
|
||||
"max-metric router-lsa administrative",
|
||||
|
@ -12285,6 +12349,22 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
|
|||
vty_out(vty, "\n");
|
||||
}
|
||||
|
||||
/* prefix-suppression print. */
|
||||
if (OSPF_IF_PARAM_CONFIGURED(params,
|
||||
prefix_suppression) &&
|
||||
params->prefix_suppression !=
|
||||
OSPF_PREFIX_SUPPRESSION_DEFAULT) {
|
||||
if (params->prefix_suppression == false)
|
||||
vty_out(vty,
|
||||
" no ip ospf prefix-suppression");
|
||||
else
|
||||
vty_out(vty,
|
||||
" ip ospf prefix-suppression");
|
||||
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));
|
||||
|
@ -13097,6 +13177,9 @@ static void ospf_vty_if_init(void)
|
|||
/* "ip ospf capability opaque" commands. */
|
||||
install_element(INTERFACE_NODE, &ip_ospf_capability_opaque_addr_cmd);
|
||||
|
||||
/* "ip ospf prefix-suppression" commands. */
|
||||
install_element(INTERFACE_NODE, &ip_ospf_prefix_suppression_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);
|
||||
|
|
47
tests/topotests/ospf_prefix_suppression/r1/frr.conf
Normal file
47
tests/topotests/ospf_prefix_suppression/r1/frr.conf
Normal file
|
@ -0,0 +1,47 @@
|
|||
!
|
||||
hostname r1
|
||||
password zebra
|
||||
log file /tmp/r1-frr.log
|
||||
ip forwarding
|
||||
!
|
||||
interface r1-eth0
|
||||
ip address 10.1.1.1/24
|
||||
ip ospf network broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
interface r1-eth1
|
||||
ip address 10.1.2.1/24
|
||||
ip ospf network non-broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
interface r1-eth2
|
||||
ip address 10.1.3.1/24
|
||||
ip ospf network point-to-point
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
interface r1-eth3
|
||||
ip address 10.1.4.1/24
|
||||
ip ospf network point-to-multipoint
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
interface r1-eth4
|
||||
ip address 10.1.7.1/24
|
||||
ip ospf network broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
router ospf
|
||||
ospf router-id 1.1.1.1
|
||||
distance 20
|
||||
network 10.1.1.0/24 area 0
|
||||
network 10.1.2.0/24 area 0
|
||||
network 10.1.3.0/24 area 0
|
||||
network 10.1.4.0/24 area 0
|
||||
network 10.1.7.0/24 area 0
|
||||
!
|
57
tests/topotests/ospf_prefix_suppression/r2/frr.conf
Normal file
57
tests/topotests/ospf_prefix_suppression/r2/frr.conf
Normal file
|
@ -0,0 +1,57 @@
|
|||
!
|
||||
hostname r2
|
||||
password zebra
|
||||
log file /tmp/r1-frr.log
|
||||
ip forwarding
|
||||
!
|
||||
interface r2-eth0
|
||||
ip address 10.1.1.2/24
|
||||
ip ospf network broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
interface r2-eth1
|
||||
ip address 10.1.2.2/24
|
||||
ip ospf network non-broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
interface r2-eth2
|
||||
ip address 10.1.3.2/24
|
||||
ip ospf network point-to-point
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
interface r2-eth3
|
||||
ip address 10.1.4.2/24
|
||||
ip ospf network point-to-multipoint
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
interface r2-eth4
|
||||
ip address 10.1.5.2/24
|
||||
ip ospf network broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
interface r2-eth5
|
||||
ip address 10.1.6.2/24
|
||||
ip ospf network broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
router ospf
|
||||
ospf router-id 2.2.2.2
|
||||
distance 20
|
||||
network 10.1.1.0/24 area 0
|
||||
network 10.1.2.0/24 area 0
|
||||
network 10.1.3.0/24 area 0
|
||||
network 10.1.4.0/24 area 0
|
||||
network 10.1.5.0/24 area 0
|
||||
network 10.1.6.0/24 area 1
|
||||
!
|
25
tests/topotests/ospf_prefix_suppression/r3/frr.conf
Normal file
25
tests/topotests/ospf_prefix_suppression/r3/frr.conf
Normal file
|
@ -0,0 +1,25 @@
|
|||
!
|
||||
hostname r3
|
||||
password zebra
|
||||
log file /tmp/r1-frr.log
|
||||
ip forwarding
|
||||
!
|
||||
interface r3-eth0
|
||||
ip address 10.1.5.3/24
|
||||
ip ospf network broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
interface r3-eth1
|
||||
ip address 10.1.6.3/24
|
||||
ip ospf network broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
router ospf
|
||||
ospf router-id 3.3.3.3
|
||||
distance 20
|
||||
network 10.1.5.0/24 area 0
|
||||
network 10.1.6.0/24 area 1
|
|
@ -0,0 +1,951 @@
|
|||
#!/usr/bin/env python
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
#
|
||||
# test_ospf_prefix_suppression.py
|
||||
#
|
||||
# Copyright (c) 2023 LabN Consulting
|
||||
# Acee Lindem
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
from time import sleep
|
||||
from functools import partial
|
||||
import pytest
|
||||
|
||||
# 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
|
||||
|
||||
from lib.common_config import (
|
||||
run_frr_cmd,
|
||||
shutdown_bringup_interface,
|
||||
start_router_daemons,
|
||||
step,
|
||||
)
|
||||
|
||||
|
||||
"""
|
||||
test_ospf_metric_propagation.py: Test OSPF/BGP metric propagation
|
||||
"""
|
||||
|
||||
TOPOLOGY = """
|
||||
|
||||
|
||||
+-----+ +-----+ +-----+
|
||||
eth4 | | eth0 | | eth4 eth0 | |
|
||||
------+ +-------------+ +--------------+ |
|
||||
10.1.7.0/24 | | 10.1.1.0/24 | | 10.1.5.0/24 | |
|
||||
| | | |.2 .3| |
|
||||
| | eth1 | | | |
|
||||
| +-------------+ | | |
|
||||
| R1 | 10.1.2.0/24 | R2 | | R3 |
|
||||
| | | | | |
|
||||
| | eth2 | | | |
|
||||
| +-------------+ | | |
|
||||
| | 10.1.3.0/24 | | | |
|
||||
| | | | | |
|
||||
| | eth3 | | eth5 eth1 | |
|
||||
| +-------------+ +--------------+ |
|
||||
| | 10.1.4.0/24 | | 10.1.6.0/24 | |
|
||||
.1 +-----+.1 .2+-----+.2 .3+-----+
|
||||
|
||||
"""
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
|
||||
# Required to instantiate the topology builder class.
|
||||
|
||||
pytestmark = [pytest.mark.ospfd, pytest.mark.bgpd]
|
||||
|
||||
|
||||
def build_topo(tgen):
|
||||
"Build function"
|
||||
|
||||
# Create 3 routers
|
||||
tgen.add_router("r1")
|
||||
tgen.add_router("r2")
|
||||
tgen.add_router("r3")
|
||||
|
||||
# Interconect router 1, 2 (0)
|
||||
switch = tgen.add_switch("s1-1-2")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
|
||||
# Interconect router 1, 2 (1)
|
||||
switch = tgen.add_switch("s2-1-2")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
|
||||
# Interconect router 1, 2 (2)
|
||||
switch = tgen.add_switch("s3-1-2")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
|
||||
# Interconect router 1, 2 (3)
|
||||
switch = tgen.add_switch("s4-1-2")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
|
||||
# Interconect router 2, 3 (0)
|
||||
switch = tgen.add_switch("s5-2-3")
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
switch.add_link(tgen.gears["r3"])
|
||||
|
||||
# Interconect router 2, 3 (1)
|
||||
switch = tgen.add_switch("s6-2-3")
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
switch.add_link(tgen.gears["r3"])
|
||||
|
||||
# Add standalone network to router 1
|
||||
switch = tgen.add_switch("s7-1")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
logger.info("OSPF Prefix Suppression:\n {}".format(TOPOLOGY))
|
||||
|
||||
tgen = Topogen(build_topo, mod.__name__)
|
||||
tgen.start_topology()
|
||||
|
||||
# Starting Routers
|
||||
router_list = tgen.routers()
|
||||
|
||||
for rname, router in router_list.items():
|
||||
logger.info("Loading router %s" % rname)
|
||||
router.load_frr_config(os.path.join(CWD, "{}/frr.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_all_routes_advertised():
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip("Skipped because of router(s) failure")
|
||||
|
||||
# Verify OSPF routes are installed
|
||||
r3 = tgen.gears["r3"]
|
||||
input_dict = {
|
||||
"10.1.1.0/24": [
|
||||
{
|
||||
"prefix": "10.1.1.0/24",
|
||||
"prefixLen": 24,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.1.0/24 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.1.0/24 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
input_dict = {
|
||||
"10.1.2.0/24": [
|
||||
{
|
||||
"prefix": "10.1.2.0/24",
|
||||
"prefixLen": 24,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.2.0/24 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.2.0/24 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
input_dict = {
|
||||
"10.1.3.0/24": [
|
||||
{
|
||||
"prefix": "10.1.3.0/24",
|
||||
"prefixLen": 24,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.3.0/24 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.3.0/24 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
input_dict = {
|
||||
"10.1.4.1/32": [
|
||||
{
|
||||
"prefix": "10.1.4.1/32",
|
||||
"prefixLen": 32,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.4.1/32 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.4.1/32 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
input_dict = {
|
||||
"10.1.4.2/32": [
|
||||
{
|
||||
"prefix": "10.1.4.2/32",
|
||||
"prefixLen": 32,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.4.2/32 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.4.2/32 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
input_dict = {
|
||||
"10.1.7.0/24": [
|
||||
{
|
||||
"prefix": "10.1.7.0/24",
|
||||
"prefixLen": 24,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.7.0/24 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.7.0/24 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
input_dict = {}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.8.0/24 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.8.0/24 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def test_broadcast_stub_suppression():
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip("Skipped because of router(s) failure")
|
||||
|
||||
step("Configure R1 interface r1-eth4 with prefix suppression")
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth4\nip ospf prefix-suppression")
|
||||
|
||||
step("Verify the R1 configuration of 'ip ospf prefix-suppression'")
|
||||
prefix_suppression_cfg = (
|
||||
tgen.net["r1"]
|
||||
.cmd('vtysh -c "show running ospfd" | grep "^ ip ospf prefix-suppression"')
|
||||
.rstrip()
|
||||
)
|
||||
assertmsg = "'ip ospf prefix-suppression' applied, but not present in configuration"
|
||||
assert prefix_suppression_cfg == " ip ospf prefix-suppression", assertmsg
|
||||
|
||||
step("Verify that ospf-prefix suppression is applied to the R1 interface")
|
||||
r1_eth4_with_prefix_suppression = {
|
||||
"interfaces": {
|
||||
"r1-eth4": {
|
||||
"ifUp": True,
|
||||
"ospfEnabled": True,
|
||||
"ipAddress": "10.1.7.1",
|
||||
"ospfIfType": "Broadcast",
|
||||
"prefixSuppression": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
r1,
|
||||
"show ip ospf interface r1-eth4 json",
|
||||
r1_eth4_with_prefix_suppression,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "R1 OSPF interface r1-eth4 doesn't have prefix-suppression enabled"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step(
|
||||
"Verify that ospf-prefix suppression is applied to the R1 interface (non-JSON)"
|
||||
)
|
||||
prefix_suppression_show = (
|
||||
tgen.net["r1"]
|
||||
.cmd(
|
||||
'vtysh -c "show ip ospf interface r1-eth4" | grep "^ Suppress advertisement of interface IP prefix"'
|
||||
)
|
||||
.rstrip()
|
||||
)
|
||||
assertmsg = (
|
||||
"'ip ospf prefix-suppression' applied, but not present in interface show"
|
||||
)
|
||||
assert (
|
||||
prefix_suppression_show == " Suppress advertisement of interface IP prefix"
|
||||
), assertmsg
|
||||
|
||||
step("Verify the ospf prefix is not advertised and not present on r3")
|
||||
r3 = tgen.gears["r3"]
|
||||
input_dict = {}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.7.0/24 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.7.0/24 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Remove R1 interface r1-eth4 prefix-suppression configuration")
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth4\nno ip ospf prefix-suppression")
|
||||
|
||||
step("Verify no R1 configuration of 'ip ospf prefix-suppression")
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
"show running ospfd | grep -q 'ip ospf prefix-suppression'", warn=False
|
||||
)
|
||||
assertmsg = (
|
||||
"'ip ospf prefix-suppression' not applied, but present in R1 configuration"
|
||||
)
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Verify that ospf-prefix suppression is not applied to the R1 interface")
|
||||
r1_eth4_without_prefix_suppression = {
|
||||
"interfaces": {
|
||||
"r1-eth4": {
|
||||
"ifUp": True,
|
||||
"ospfEnabled": True,
|
||||
"ipAddress": "10.1.7.1",
|
||||
"ospfIfType": "Broadcast",
|
||||
"prefixSuppression": False,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
r1,
|
||||
"show ip ospf interface r1-eth4 json",
|
||||
r1_eth4_without_prefix_suppression,
|
||||
)
|
||||
|
||||
step("Verify that 10.1.7.0/24 route is now installed on R3")
|
||||
input_dict = {
|
||||
"10.1.7.0/24": [
|
||||
{
|
||||
"prefix": "10.1.7.0/24",
|
||||
"prefixLen": 24,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.7.0/24 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.7.0/24 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def test_broadcast_transit_suppression():
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip("Skipped because of router(s) failure")
|
||||
|
||||
step(
|
||||
"Configure R1 interface r1-eth0 with prefix suppression using interface address"
|
||||
)
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf prefix-suppression 10.1.1.1")
|
||||
|
||||
step("Verify the R1 configuration of 'ip ospf prefix-suppression 10.1.1.1'")
|
||||
prefix_suppression_cfg = (
|
||||
tgen.net["r1"]
|
||||
.cmd(
|
||||
'vtysh -c "show running ospfd" | grep "^ ip ospf prefix-suppression 10.1.1.1"'
|
||||
)
|
||||
.rstrip()
|
||||
)
|
||||
assertmsg = "'ip ospf prefix-suppression 10.1.1.1' applied, but not present in configuration"
|
||||
assert prefix_suppression_cfg == " ip ospf prefix-suppression 10.1.1.1", assertmsg
|
||||
|
||||
step(
|
||||
"Configure R2 interface r2-eth0 with prefix suppression using interface address"
|
||||
)
|
||||
r2 = tgen.gears["r2"]
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth0\nip ospf prefix-suppression 10.1.1.2")
|
||||
|
||||
step("Verify that ospf-prefix suppression is applied to the R1 interface")
|
||||
r1_eth0_with_prefix_suppression = {
|
||||
"interfaces": {
|
||||
"r1-eth0": {
|
||||
"ifUp": True,
|
||||
"ospfEnabled": True,
|
||||
"ipAddress": "10.1.1.1",
|
||||
"ospfIfType": "Broadcast",
|
||||
"networkType": "BROADCAST",
|
||||
"prefixSuppression": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
r1,
|
||||
"show ip ospf interface r1-eth0 json",
|
||||
r1_eth0_with_prefix_suppression,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "R1 OSPF interface r1-eth0 doesn't have prefix-suppression enabled"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify the OSPF prefix is not advertised and not present on r3")
|
||||
r3 = tgen.gears["r3"]
|
||||
input_dict = {}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.1.0/24 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.1.0/24 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify the OSPF Network-LSA prefixes are also not present on R3 ")
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.1.1/24 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.1.1/24 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.1.2/24 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.1.2/24 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step(
|
||||
"Remove R1 interface r1-eth0 prefix-suppression configuration using interface address"
|
||||
)
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip ospf prefix-suppression 10.1.1.1")
|
||||
|
||||
step(
|
||||
"Remove R2 interface r2-eth0 prefix-suppression configuration using interface address"
|
||||
)
|
||||
r2 = tgen.gears["r2"]
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth0\nno ip ospf prefix-suppression 10.1.1.2")
|
||||
|
||||
step("Verify no R1 configuration of 'ip ospf prefix-suppression")
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
"show running ospfd | grep -q 'ip ospf prefix-suppression 10.1.1.1'", warn=False
|
||||
)
|
||||
assertmsg = "'ip ospf prefix-suppression 10.1.1.1' not applied, but present in R1 configuration"
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Verify that ospf-prefix suppression is not applied to the R1 interface")
|
||||
r1_eth0_without_prefix_suppression = {
|
||||
"interfaces": {
|
||||
"r1-eth0": {
|
||||
"ifUp": True,
|
||||
"ospfEnabled": True,
|
||||
"ipAddress": "10.1.1.1",
|
||||
"ospfIfType": "Broadcast",
|
||||
"networkType": "BROADCAST",
|
||||
"prefixSuppression": False,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
r1,
|
||||
"show ip ospf interface r1-eth0 json",
|
||||
r1_eth0_without_prefix_suppression,
|
||||
)
|
||||
|
||||
step("Verify that 10.1.1.0/24 route is now installed on R3")
|
||||
input_dict = {
|
||||
"10.1.1.0/24": [
|
||||
{
|
||||
"prefix": "10.1.1.0/24",
|
||||
"prefixLen": 24,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.1.0/24 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.1.0/24 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def test_nbma_transit_suppression():
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip("Skipped because of router(s) failure")
|
||||
|
||||
step("Configure R1 interface r1-eth1 with prefix suppression")
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth1\nip ospf prefix-suppression")
|
||||
|
||||
step("Configure R2 interface r2-eth1 with prefix suppression")
|
||||
r2 = tgen.gears["r2"]
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth1\nip ospf prefix-suppression")
|
||||
|
||||
step("Verify that ospf-prefix suppression is applied to the R1 interface")
|
||||
r1_eth1_with_prefix_suppression = {
|
||||
"interfaces": {
|
||||
"r1-eth1": {
|
||||
"ifUp": True,
|
||||
"ospfEnabled": True,
|
||||
"ipAddress": "10.1.2.1",
|
||||
"ospfIfType": "Broadcast",
|
||||
"networkType": "NBMA",
|
||||
"prefixSuppression": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
r1,
|
||||
"show ip ospf interface r1-eth1 json",
|
||||
r1_eth1_with_prefix_suppression,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "R1 OSPF interface r1-eth1 doesn't have prefix-suppression enabled"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify the OSPF prefix is not advertised and not present on r3")
|
||||
r3 = tgen.gears["r3"]
|
||||
input_dict = {}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.2.0/24 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.2.0/24 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify the OSPF Network-LSA prefixes are also not present on R3 ")
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.2.1/24 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.2.1/24 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.2.2/24 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.2.2/24 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Remove R1 interface r1-eth1 prefix-suppression configuration")
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth1\nno ip ospf prefix-suppression")
|
||||
|
||||
step("Remove R2 interface eth1 prefix-suppression configuration")
|
||||
r2 = tgen.gears["r2"]
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth1\nno ip ospf prefix-suppression")
|
||||
|
||||
step("Verify no R1 configuration of 'ip ospf prefix-suppression")
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
"show running ospfd | grep -q 'ip ospf prefix-suppression'", warn=False
|
||||
)
|
||||
assertmsg = (
|
||||
"'ip ospf prefix-suppression' not applied, but present in R1 configuration"
|
||||
)
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Verify that ospf-prefix suppression is not applied to the R1 interface")
|
||||
r1_eth1_without_prefix_suppression = {
|
||||
"interfaces": {
|
||||
"r1-eth1": {
|
||||
"ifUp": True,
|
||||
"ospfEnabled": True,
|
||||
"ipAddress": "10.1.2.1",
|
||||
"ospfIfType": "Broadcast",
|
||||
"networkType": "NBMA",
|
||||
"prefixSuppression": False,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
r1,
|
||||
"show ip ospf interface r1-eth1 json",
|
||||
r1_eth1_without_prefix_suppression,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "Prefix suppression on interface r1-eth1"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify that 10.1.2.0/24 route is now installed on R3")
|
||||
input_dict = {
|
||||
"10.1.2.0/24": [
|
||||
{
|
||||
"prefix": "10.1.2.0/24",
|
||||
"prefixLen": 24,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.2.0/24 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.2.0/24 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def test_p2p_suppression():
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip("Skipped because of router(s) failure")
|
||||
|
||||
step(
|
||||
"Configure R1 interface r1-eth2 with prefix suppression with interface address"
|
||||
)
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth2\nip ospf prefix-suppression 10.1.3.1")
|
||||
|
||||
step(
|
||||
"Configure R2 interface r2-eth1 with prefix suppression with interface address"
|
||||
)
|
||||
r2 = tgen.gears["r2"]
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth2\nip ospf prefix-suppression 10.1.3.2")
|
||||
|
||||
step("Verify the R1 configuration of 'ip ospf prefix-suppression 10.1.3.1'")
|
||||
prefix_suppression_cfg = (
|
||||
tgen.net["r1"]
|
||||
.cmd(
|
||||
'vtysh -c "show running ospfd" | grep "^ ip ospf prefix-suppression 10.1.3.1"'
|
||||
)
|
||||
.rstrip()
|
||||
)
|
||||
assertmsg = "'ip ospf prefix-suppression 10.1.3.1' applied, but not present in configuration"
|
||||
assert prefix_suppression_cfg == " ip ospf prefix-suppression 10.1.3.1", assertmsg
|
||||
|
||||
step("Verify that ospf-prefix suppression is applied to the R1 interface")
|
||||
r1_eth2_with_prefix_suppression = {
|
||||
"interfaces": {
|
||||
"r1-eth2": {
|
||||
"ifUp": True,
|
||||
"ospfEnabled": True,
|
||||
"ipAddress": "10.1.3.1",
|
||||
"ospfIfType": "Broadcast",
|
||||
"networkType": "POINTOPOINT",
|
||||
"prefixSuppression": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
r1,
|
||||
"show ip ospf interface r1-eth2 json",
|
||||
r1_eth2_with_prefix_suppression,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "R1 OSPF interface r1-eth2 doesn't have prefix-suppression enabled"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify the OSPF prefix is not advertised and not present on r3")
|
||||
r3 = tgen.gears["r3"]
|
||||
input_dict = {}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.3.0/24 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.3.0/24 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step(
|
||||
"Remove R1 interface r1-eth2 prefix-suppression configuration using interface address"
|
||||
)
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth2\nno ip ospf prefix-suppression 10.1.3.1")
|
||||
|
||||
step(
|
||||
"Remove R2 interface r2-eth2 prefix-suppression configuration using interface address"
|
||||
)
|
||||
r2 = tgen.gears["r2"]
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth2\nno ip ospf prefix-suppression 10.1.3.2")
|
||||
|
||||
step("Verify no R1 configuration of 'ip ospf prefix-suppression")
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
"show running ospfd | grep -q 'ip ospf prefix-suppression 10.1.3.1'", warn=False
|
||||
)
|
||||
assertmsg = "'ip ospf prefix-suppressio 10.1.3.1' not applied, but present in R1 configuration"
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Verify that ospf-prefix suppression is not applied to the R1 interface")
|
||||
r1_eth2_without_prefix_suppression = {
|
||||
"interfaces": {
|
||||
"r1-eth2": {
|
||||
"ifUp": True,
|
||||
"ospfEnabled": True,
|
||||
"ipAddress": "10.1.3.1",
|
||||
"ospfIfType": "Broadcast",
|
||||
"networkType": "POINTOPOINT",
|
||||
"prefixSuppression": False,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
r1,
|
||||
"show ip ospf interface r1-eth2 json",
|
||||
r1_eth2_without_prefix_suppression,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "Prefix suppression on interface r1-eth2"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify that 10.1.3.0/24 route is now installed on R3")
|
||||
input_dict = {
|
||||
"10.1.3.0/24": [
|
||||
{
|
||||
"prefix": "10.1.3.0/24",
|
||||
"prefixLen": 24,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.3.0/24 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.3.0/24 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def test_p2mp_suppression():
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip("Skipped because of router(s) failure")
|
||||
|
||||
step("Configure R1 interface r1-eth3 with prefix suppression")
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth3\nip ospf prefix-suppression")
|
||||
|
||||
step("Configure R2 interface r2-eth3 with prefix suppression")
|
||||
r2 = tgen.gears["r2"]
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth3\nip ospf prefix-suppression")
|
||||
|
||||
step("Verify that ospf-prefix suppression is applied to the R1 interface")
|
||||
r1_eth3_with_prefix_suppression = {
|
||||
"interfaces": {
|
||||
"r1-eth3": {
|
||||
"ifUp": True,
|
||||
"ospfEnabled": True,
|
||||
"ipAddress": "10.1.4.1",
|
||||
"ospfIfType": "Broadcast",
|
||||
"networkType": "POINTOMULTIPOINT",
|
||||
"prefixSuppression": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
r1,
|
||||
"show ip ospf interface r1-eth3 json",
|
||||
r1_eth3_with_prefix_suppression,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "R1 OSPF interface r1-eth3 doesn't have prefix-suppression enabled"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify the OSPF P2MP prefixes are not advertised and not present on r3")
|
||||
r3 = tgen.gears["r3"]
|
||||
input_dict = {}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.4.1/32 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.4.1/32 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.4.2/32 json", input_dict, True
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.4.2/32 installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Remove R1 interface r1-eth3 prefix-suppression configuration")
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth3\nno ip ospf prefix-suppression")
|
||||
|
||||
step("Remove R2 interface r2-eth3 prefix-suppression configuration")
|
||||
r2 = tgen.gears["r2"]
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth3\nno ip ospf prefix-suppression")
|
||||
|
||||
step("Verify no R1 configuration of 'ip ospf prefix-suppression")
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
"show running ospfd | grep -q 'ip ospf prefix-suppression'", warn=False
|
||||
)
|
||||
assertmsg = (
|
||||
"'ip ospf prefix-suppression' not applied, but present in R1 configuration"
|
||||
)
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Verify that ospf-prefix suppression is not applied to the R1 interface")
|
||||
r1_eth3_without_prefix_suppression = {
|
||||
"interfaces": {
|
||||
"r1-eth3": {
|
||||
"ifUp": True,
|
||||
"ospfEnabled": True,
|
||||
"ipAddress": "10.1.4.1",
|
||||
"ospfIfType": "Broadcast",
|
||||
"networkType": "POINTOMULTIPOINT",
|
||||
"prefixSuppression": False,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
r1,
|
||||
"show ip ospf interface r1-eth3 json",
|
||||
r1_eth3_without_prefix_suppression,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "Prefix suppression on interface r1-eth3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify that 10.1.4.1/32 route is now installed on R3")
|
||||
input_dict = {
|
||||
"10.1.4.1/32": [
|
||||
{
|
||||
"prefix": "10.1.4.1/32",
|
||||
"prefixLen": 32,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.4.1/32 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.4.1/32 not installed on router r3"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify that 10.1.4.2/32 route is now installed on R3")
|
||||
input_dict = {
|
||||
"10.1.4.2/32": [
|
||||
{
|
||||
"prefix": "10.1.4.2/32",
|
||||
"prefixLen": 32,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "10.1.5.2",
|
||||
"interfaceName": "r3-eth0",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r3, "show ip route 10.1.4.2/32 json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "10.1.4.2/32 not installed on router r3"
|
||||
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))
|
Loading…
Reference in a new issue