mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 18:42:23 +00:00
Merge pull request #15660 from LabNConsulting/acee/ospf-p2mp-non-broadcast
ospfd: Implement non-broadcast support for point-to-multipoint networks
This commit is contained in:
commit
7f6cda36b1
@ -494,11 +494,11 @@ Graceful Restart
|
||||
|
||||
|
||||
Configure Graceful Restart (RFC 5187) helper support.
|
||||
By default, helper support is disabled for all neighbours.
|
||||
By default, helper support is disabled for all neighbors.
|
||||
This config enables/disables helper support on this router
|
||||
for all neighbours.
|
||||
for all neighbors.
|
||||
To enable/disable helper support for a specific
|
||||
neighbour, the router-id (A.B.C.D) has to be specified.
|
||||
neighbor, the router-id (A.B.C.D) has to be specified.
|
||||
|
||||
.. clicmd:: graceful-restart helper strict-lsa-checking
|
||||
|
||||
|
@ -12,7 +12,7 @@ OSPF Fundamentals
|
||||
:term:`distance-vector` protocols, such as :abbr:`RIP` or :abbr:`BGP`, where
|
||||
routers describe available `paths` (i.e. routes) to each other, in
|
||||
:term:`link-state` protocols routers instead describe the state of their links
|
||||
to their immediate neighbouring routers.
|
||||
to their immediate neighboring routers.
|
||||
|
||||
.. index::
|
||||
single: Link State Announcement
|
||||
@ -127,7 +127,7 @@ LSA Flooding
|
||||
""""""""""""
|
||||
|
||||
OSPF defines several related mechanisms, used to manage synchronisation of
|
||||
:abbr:`LSDB` s between neighbours as neighbours form adjacencies and the
|
||||
:abbr:`LSDB` s between neighbors as neighbors form adjacencies and the
|
||||
propagation, or `flooding` of new or updated :abbr:`LSA` s.
|
||||
|
||||
|
||||
@ -259,7 +259,7 @@ called `intra-area routes`.
|
||||
LSA is originated for such a link.
|
||||
|
||||
Stub
|
||||
A link with no adjacent neighbours, or a host route.
|
||||
A link with no adjacent neighbors, or a host route.
|
||||
|
||||
- Link ID and Data
|
||||
|
||||
@ -339,8 +339,8 @@ The example below shows two :abbr:`LSA` s, both originated by the same router
|
||||
of different LSA types.
|
||||
|
||||
The first LSA being the router LSA describing 192.168.0.49's links: 2 links
|
||||
to multi-access networks with fully-adjacent neighbours (i.e. Transit
|
||||
links) and 1 being a Stub link (no adjacent neighbours).
|
||||
to multi-access networks with fully-adjacent neighbors (i.e. Transit
|
||||
links) and 1 being a Stub link (no adjacent neighbors).
|
||||
|
||||
The second LSA being a Network LSA, for which 192.168.0.49 is the
|
||||
:abbr:`DR`, listing the Router IDs of 4 routers on that network which
|
||||
|
@ -239,6 +239,17 @@ To start OSPF process you have to specify the OSPF router.
|
||||
This configuration setting MUST be consistent across all routers within the
|
||||
OSPF domain.
|
||||
|
||||
.. clicmd:: neighbor A.B.C.D [poll-interval (1-65535)] [priority (0-255)]
|
||||
|
||||
|
||||
Configures OSPF neighbors for non-broadcast multi-access (NBMA) networks
|
||||
and point-to-multipoint non-broadcast networks. The `poll-interval`
|
||||
specifies the rate for sending hello packets to neighbors that are not
|
||||
active. When the configured neighbor is discovered, hello packets will be
|
||||
sent at the rate of the hello-interval. The default `poll-interval` is 60
|
||||
seconds. The `priority` is used to for the Designated Router (DR) election
|
||||
on non-broadcast multi-access networks.
|
||||
|
||||
.. clicmd:: network A.B.C.D/M area A.B.C.D
|
||||
|
||||
.. clicmd:: network A.B.C.D/M area (0-4294967295)
|
||||
@ -580,7 +591,7 @@ Interfaces
|
||||
Note that OSPF MD5 authentication requires that time never go backwards
|
||||
(correct time is NOT important, only that it never goes backwards), even
|
||||
across resets, if ospfd is to be able to promptly reestablish adjacencies
|
||||
with its neighbours after restarts/reboots. The host should have system time
|
||||
with its neighbors after restarts/reboots. The host should have system time
|
||||
be set at boot from an external or non-volatile source (e.g. battery backed
|
||||
clock, NTP, etc.) or else the system clock should be periodically saved to
|
||||
non-volatile storage and restored at boot if MD5 authentication is to be
|
||||
@ -612,7 +623,7 @@ Interfaces
|
||||
Note that OSPF HMAC cryptographic authentication requires that time never go backwards
|
||||
(correct time is NOT important, only that it never goes backwards), even
|
||||
across resets, if ospfd is to be able to promptly reestablish adjacencies
|
||||
with its neighbours after restarts/reboots. The host should have system time
|
||||
with its neighbors after restarts/reboots. The host should have system time
|
||||
be set at boot from an external or non-volatile source (e.g. battery backed
|
||||
clock, NTP, etc.) or else the system clock should be periodically saved to
|
||||
non-volatile storage and restored at boot if HMAC cryptographic authentication is to be
|
||||
@ -679,7 +690,7 @@ Interfaces
|
||||
it's recommended to set the hello delay and hello interval with the same values.
|
||||
The default value is 10 seconds.
|
||||
|
||||
.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint [delay-reflood]|point-to-point [dmvpn])
|
||||
.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint [delay-reflood|non-broadcast]|point-to-point [dmvpn])
|
||||
|
||||
When configuring a point-to-point network on an interface and the interface
|
||||
has a /32 address associated with then OSPF will treat the interface
|
||||
@ -691,6 +702,13 @@ Interfaces
|
||||
point-to-point, but the HUB will be a point-to-multipoint. To make this
|
||||
topology work, specify the optional 'dmvpn' parameter at the spoke.
|
||||
|
||||
When the network is configured as point-to-multipoint and `non-broadcast`
|
||||
is specified, the network doesn't support broadcast or multicast delivery
|
||||
and neighbors cannot be discovered from OSPF hello received from the
|
||||
OSPFAllRouters (224.0.0.5). Rather, they must be explicitly configured
|
||||
using the :clicmd:`neighbor A.B.C.D` configuration command as they are
|
||||
on non-broadcast networks.
|
||||
|
||||
When the network is configured as point-to-multipoint and `delay-reflood`
|
||||
is specified, LSAs received on the interface from neighbors on the
|
||||
interface will not be flooded back out on the interface immediately.
|
||||
@ -838,11 +856,11 @@ Graceful Restart
|
||||
|
||||
|
||||
Configure Graceful Restart (RFC 3623) helper support.
|
||||
By default, helper support is disabled for all neighbours.
|
||||
By default, helper support is disabled for all neighbors.
|
||||
This config enables/disables helper support on this router
|
||||
for all neighbours.
|
||||
for all neighbors.
|
||||
To enable/disable helper support for a specific
|
||||
neighbour, the router-id (A.B.C.D) has to be specified.
|
||||
neighbor, the router-id (A.B.C.D) has to be specified.
|
||||
|
||||
.. clicmd:: graceful-restart helper strict-lsa-checking
|
||||
|
||||
@ -1082,7 +1100,7 @@ Router Information
|
||||
respectively the PCE IP address, Autonomous System (AS) numbers of
|
||||
controlled domains, neighbor ASs, flag and scope. For flag and scope, please
|
||||
refer to :rfc`5088` for the BITPATTERN recognition. Multiple 'pce neighbor'
|
||||
command could be specified in order to specify all PCE neighbours.
|
||||
command could be specified in order to specify all PCE neighbors.
|
||||
|
||||
.. clicmd:: show ip ospf router-info
|
||||
|
||||
|
@ -69,6 +69,7 @@ extern "C" {
|
||||
#define OSPF_MTU_IGNORE_DEFAULT 0
|
||||
#define OSPF_FAST_HELLO_DEFAULT 0
|
||||
#define OSPF_P2MP_DELAY_REFLOOD_DEFAULT false
|
||||
#define OSPF_P2MP_NON_BROADCAST_DEFAULT false
|
||||
#define OSPF_OPAQUE_CAPABLE_DEFAULT true
|
||||
#define OSPF_PREFIX_SUPPRESSION_DEFAULT false
|
||||
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
|
||||
|
@ -765,8 +765,9 @@ int ospf_flood_through_interface(struct ospf_interface *oi,
|
||||
packets must be sent, as unicasts, to each adjacent neighbor
|
||||
(i.e., those in state Exchange or greater). The destination
|
||||
IP addresses for these packets are the neighbors' IP
|
||||
addresses. */
|
||||
if (oi->type == OSPF_IFTYPE_NBMA) {
|
||||
addresses. This behavior is extended to P2MP networks which
|
||||
don't support broadcast. */
|
||||
if (OSPF_IF_NON_BROADCAST(oi)) {
|
||||
struct ospf_neighbor *nbr;
|
||||
|
||||
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
|
||||
|
@ -147,17 +147,11 @@ void ospf_if_reset(struct interface *ifp)
|
||||
}
|
||||
}
|
||||
|
||||
void ospf_if_reset_variables(struct ospf_interface *oi)
|
||||
static void ospf_if_default_variables(struct ospf_interface *oi)
|
||||
{
|
||||
/* Set default values. */
|
||||
/* don't clear this flag. oi->flag = OSPF_IF_DISABLE; */
|
||||
|
||||
if (oi->vl_data)
|
||||
oi->type = OSPF_IFTYPE_VIRTUALLINK;
|
||||
else
|
||||
/* preserve network-type */
|
||||
if (oi->type != OSPF_IFTYPE_NBMA)
|
||||
oi->type = OSPF_IFTYPE_BROADCAST;
|
||||
oi->type = OSPF_IFTYPE_BROADCAST;
|
||||
|
||||
oi->state = ISM_Down;
|
||||
|
||||
@ -254,7 +248,7 @@ struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp,
|
||||
oi->ls_ack_direct.ls_ack = list_new();
|
||||
|
||||
/* Set default values. */
|
||||
ospf_if_reset_variables(oi);
|
||||
ospf_if_default_variables(oi);
|
||||
|
||||
/* Set pseudo neighbor to Null */
|
||||
oi->nbr_self = NULL;
|
||||
|
@ -119,6 +119,9 @@ struct ospf_if_params {
|
||||
/* point-to-multipoint delayed reflooding configuration */
|
||||
bool p2mp_delay_reflood;
|
||||
|
||||
/* point-to-multipoint doesn't support broadcast */
|
||||
bool p2mp_non_broadcast;
|
||||
|
||||
/* Opaque LSA capability at interface level (see RFC5250) */
|
||||
DECLARE_IF_PARAM(bool, opaque_capable);
|
||||
};
|
||||
@ -185,6 +188,10 @@ struct ospf_interface {
|
||||
|
||||
/* OSPF Network Type. */
|
||||
uint8_t type;
|
||||
#define OSPF_IF_NON_BROADCAST(O) \
|
||||
(((O)->type == OSPF_IFTYPE_NBMA) || \
|
||||
((((O)->type == OSPF_IFTYPE_POINTOMULTIPOINT) && \
|
||||
(O)->p2mp_non_broadcast)))
|
||||
|
||||
/* point-to-point DMVPN configuration */
|
||||
uint8_t ptp_dmvpn;
|
||||
@ -192,6 +199,9 @@ struct ospf_interface {
|
||||
/* point-to-multipoint delayed reflooding */
|
||||
bool p2mp_delay_reflood;
|
||||
|
||||
/* point-to-multipoint doesn't support broadcast */
|
||||
bool p2mp_non_broadcast;
|
||||
|
||||
/* State of Interface State Machine. */
|
||||
uint8_t state;
|
||||
|
||||
@ -326,7 +336,6 @@ extern void ospf_if_update_params(struct interface *ifp, struct in_addr addr);
|
||||
extern int ospf_if_new_hook(struct interface *ifp);
|
||||
extern void ospf_if_init(void);
|
||||
extern void ospf_if_stream_unset(struct ospf_interface *oi);
|
||||
extern void ospf_if_reset_variables(struct ospf_interface *oi);
|
||||
extern int ospf_if_is_enable(struct ospf_interface *oi);
|
||||
extern int ospf_if_get_output_cost(struct ospf_interface *oi);
|
||||
extern void ospf_if_recalculate_output_cost(struct interface *ifp);
|
||||
|
@ -367,7 +367,7 @@ static int ism_interface_up(struct ospf_interface *oi)
|
||||
/* Otherwise, the state transitions to Waiting. */
|
||||
next_state = ISM_Waiting;
|
||||
|
||||
if (oi->type == OSPF_IFTYPE_NBMA)
|
||||
if (OSPF_IF_NON_BROADCAST(oi))
|
||||
ospf_nbr_nbma_if_update(oi->ospf, oi);
|
||||
|
||||
/* ospf_ism_event (t); */
|
||||
|
@ -431,7 +431,7 @@ static struct ospf_neighbor *ospf_nbr_add(struct ospf_interface *oi,
|
||||
memcpy(&nbr->address, p, sizeof(struct prefix));
|
||||
|
||||
nbr->nbr_nbma = NULL;
|
||||
if (oi->type == OSPF_IFTYPE_NBMA) {
|
||||
if (OSPF_IF_NON_BROADCAST(oi)) {
|
||||
struct ospf_nbr_nbma *nbr_nbma;
|
||||
struct listnode *node;
|
||||
|
||||
@ -485,7 +485,7 @@ struct ospf_neighbor *ospf_nbr_get(struct ospf_interface *oi,
|
||||
route_unlock_node(rn);
|
||||
nbr = rn->info;
|
||||
|
||||
if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) {
|
||||
if (OSPF_IF_NON_BROADCAST(nbr->oi) && nbr->state == NSM_Attempt) {
|
||||
nbr->src = iph->ip_src;
|
||||
memcpy(&nbr->address, p, sizeof(struct prefix));
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ static int nsm_hello_received(struct ospf_neighbor *nbr)
|
||||
OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer,
|
||||
nbr->v_inactivity);
|
||||
|
||||
if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma)
|
||||
if (OSPF_IF_NON_BROADCAST(nbr->oi) && nbr->nbr_nbma != NULL)
|
||||
EVENT_OFF(nbr->nbr_nbma->t_poll);
|
||||
|
||||
/* Send proactive ARP requests */
|
||||
@ -377,7 +377,7 @@ static int nsm_kill_nbr(struct ospf_neighbor *nbr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL) {
|
||||
if (OSPF_IF_NON_BROADCAST(nbr->oi) && nbr->nbr_nbma != NULL) {
|
||||
struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma;
|
||||
|
||||
nbr_nbma->nbr = NULL;
|
||||
|
@ -3395,17 +3395,19 @@ static void ospf_poll_send(struct ospf_nbr_nbma *nbr_nbma)
|
||||
if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE)
|
||||
return;
|
||||
|
||||
if (oi->type != OSPF_IFTYPE_NBMA)
|
||||
return;
|
||||
|
||||
if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
|
||||
return;
|
||||
|
||||
if (PRIORITY(oi) == 0)
|
||||
return;
|
||||
if (oi->type == OSPF_IFTYPE_NBMA) {
|
||||
if (PRIORITY(oi) == 0)
|
||||
return;
|
||||
|
||||
if (nbr_nbma->priority == 0 && oi->state != ISM_DR
|
||||
&& oi->state != ISM_Backup)
|
||||
if (nbr_nbma->priority == 0 && oi->state != ISM_DR &&
|
||||
oi->state != ISM_Backup)
|
||||
return;
|
||||
|
||||
} else if (oi->type != OSPF_IFTYPE_POINTOMULTIPOINT ||
|
||||
!oi->p2mp_non_broadcast)
|
||||
return;
|
||||
|
||||
ospf_hello_send_sub(oi, nbr_nbma->addr.s_addr);
|
||||
@ -3451,7 +3453,7 @@ void ospf_hello_send(struct ospf_interface *oi)
|
||||
if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE)
|
||||
return;
|
||||
|
||||
if (oi->type == OSPF_IFTYPE_NBMA) {
|
||||
if (OSPF_IF_NON_BROADCAST(oi)) {
|
||||
struct ospf_neighbor *nbr;
|
||||
struct route_node *rn;
|
||||
|
||||
@ -3467,31 +3469,44 @@ void ospf_hello_send(struct ospf_interface *oi)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* RFC 2328 Section 9.5.1
|
||||
* If the router is not eligible to become Designated
|
||||
* Router, it must periodically send Hello Packets to
|
||||
* both the Designated Router and the Backup
|
||||
* Designated Router (if they exist).
|
||||
* Always send to all neighbors on Point-to-Multipoint
|
||||
* non-braodcast networks.
|
||||
*/
|
||||
if (PRIORITY(oi) == 0 &&
|
||||
IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
|
||||
IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
|
||||
continue;
|
||||
if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
|
||||
ospf_hello_send_sub(oi, nbr->address.u.prefix4
|
||||
.s_addr);
|
||||
else {
|
||||
/*
|
||||
* RFC 2328 Section 9.5.1
|
||||
* If the router is not eligible to become Designated
|
||||
* Router, it must periodically send Hello Packets to
|
||||
* both the Designated Router and the Backup
|
||||
* Designated Router (if they exist).
|
||||
*/
|
||||
if (PRIORITY(oi) == 0 &&
|
||||
IPV4_ADDR_CMP(&DR(oi),
|
||||
&nbr->address.u.prefix4) &&
|
||||
IPV4_ADDR_CMP(&BDR(oi),
|
||||
&nbr->address.u.prefix4))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the router is eligible to become Designated
|
||||
* Router, it must periodically send Hello Packets to
|
||||
* all neighbors that are also eligible. In addition,
|
||||
* if the router is itself the Designated Router or
|
||||
* Backup Designated Router, it must also send periodic
|
||||
* Hello Packets to all other neighbors.
|
||||
*/
|
||||
if (nbr->priority == 0 && oi->state == ISM_DROther)
|
||||
continue;
|
||||
/*
|
||||
* If the router is eligible to become Designated
|
||||
* Router, it must periodically send Hello Packets to
|
||||
* all neighbors that are also eligible. In addition,
|
||||
* if the router is itself the Designated Router or
|
||||
* Backup Designated Router, it must also send periodic
|
||||
* Hello Packets to all other neighbors.
|
||||
*/
|
||||
if (nbr->priority == 0 &&
|
||||
oi->state == ISM_DROther)
|
||||
continue;
|
||||
|
||||
/* if oi->state == Waiting, send
|
||||
* hello to all neighbors */
|
||||
ospf_hello_send_sub(oi, nbr->address.u.prefix4.s_addr);
|
||||
/* if oi->state == Waiting, send
|
||||
* hello to all neighbors */
|
||||
ospf_hello_send_sub(oi, nbr->address.u.prefix4
|
||||
.s_addr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Decide destination address. */
|
||||
@ -3848,11 +3863,10 @@ void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag,
|
||||
else
|
||||
p.prefix.s_addr = htonl(OSPF_ALLDROUTERS);
|
||||
|
||||
if (oi->type == OSPF_IFTYPE_NBMA) {
|
||||
if (OSPF_IF_NON_BROADCAST(oi)) {
|
||||
if (flag == OSPF_SEND_PACKET_INDIRECT)
|
||||
flog_warn(
|
||||
EC_OSPF_PACKET,
|
||||
"* LS-Update is directly sent on NBMA network.");
|
||||
flog_warn(EC_OSPF_PACKET,
|
||||
"* LS-Update is directly sent on non-broadcast network.");
|
||||
if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix))
|
||||
flog_warn(EC_OSPF_PACKET,
|
||||
"* LS-Update is sent to myself.");
|
||||
@ -3910,7 +3924,8 @@ static void ospf_ls_ack_send_list(struct ospf_interface *oi, struct list *ack,
|
||||
|
||||
/* Decide destination address. */
|
||||
if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
|
||||
oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
|
||||
(oi->type == OSPF_IFTYPE_POINTOMULTIPOINT &&
|
||||
!oi->p2mp_non_broadcast))
|
||||
op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS);
|
||||
else
|
||||
op->dst.s_addr = dst.s_addr;
|
||||
@ -3962,7 +3977,7 @@ void ospf_ls_ack_send_delayed(struct ospf_interface *oi)
|
||||
networks, delayed Link State Acknowledgment packets must be
|
||||
unicast separately over each adjacency (i.e., neighbor whose
|
||||
state is >= Exchange). */
|
||||
if (oi->type == OSPF_IFTYPE_NBMA) {
|
||||
if (OSPF_IF_NON_BROADCAST(oi)) {
|
||||
struct ospf_neighbor *nbr;
|
||||
struct route_node *rn;
|
||||
|
||||
|
186
ospfd/ospf_vty.c
186
ospfd/ospf_vty.c
@ -2406,130 +2406,30 @@ DEFUN (no_ospf_timers_lsa_min_arrival,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf_neighbor,
|
||||
ospf_neighbor_cmd,
|
||||
"neighbor A.B.C.D [priority (0-255) [poll-interval (1-65535)]]",
|
||||
NEIGHBOR_STR
|
||||
"Neighbor IP address\n"
|
||||
"Neighbor Priority\n"
|
||||
"Priority\n"
|
||||
"Dead Neighbor Polling interval\n"
|
||||
"Seconds\n")
|
||||
DEFPY(ospf_neighbor, ospf_neighbor_cmd,
|
||||
"[no] neighbor A.B.C.D$nbr_address [{priority (0-255)$priority | poll-interval (1-65535)$interval}]",
|
||||
NO_STR
|
||||
NEIGHBOR_STR
|
||||
"Neighbor IP address\n"
|
||||
"Neighbor Priority\n"
|
||||
"Priority\n"
|
||||
"Dead Neighbor Polling interval\n"
|
||||
"Seconds\n")
|
||||
{
|
||||
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
|
||||
int idx_ipv4 = 1;
|
||||
int idx_pri = 3;
|
||||
int idx_poll = 5;
|
||||
struct in_addr nbr_addr;
|
||||
unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
|
||||
unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT;
|
||||
|
||||
if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
|
||||
vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
if (no)
|
||||
ospf_nbr_nbma_unset(ospf, nbr_address);
|
||||
else {
|
||||
ospf_nbr_nbma_set(ospf, nbr_address);
|
||||
if (priority_str)
|
||||
ospf_nbr_nbma_priority_set(ospf, nbr_address, priority);
|
||||
|
||||
if (interval_str)
|
||||
ospf_nbr_nbma_poll_interval_set(ospf, nbr_address,
|
||||
interval);
|
||||
}
|
||||
|
||||
if (argc > 2)
|
||||
priority = strtoul(argv[idx_pri]->arg, NULL, 10);
|
||||
|
||||
if (argc > 4)
|
||||
interval = strtoul(argv[idx_poll]->arg, NULL, 10);
|
||||
|
||||
ospf_nbr_nbma_set(ospf, nbr_addr);
|
||||
|
||||
if (argc > 2)
|
||||
ospf_nbr_nbma_priority_set(ospf, nbr_addr, priority);
|
||||
|
||||
if (argc > 4)
|
||||
ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf_neighbor_poll_interval,
|
||||
ospf_neighbor_poll_interval_cmd,
|
||||
"neighbor A.B.C.D poll-interval (1-65535) [priority (0-255)]",
|
||||
NEIGHBOR_STR
|
||||
"Neighbor IP address\n"
|
||||
"Dead Neighbor Polling interval\n"
|
||||
"Seconds\n"
|
||||
"OSPF priority of non-broadcast neighbor\n"
|
||||
"Priority\n")
|
||||
{
|
||||
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
|
||||
int idx_ipv4 = 1;
|
||||
int idx_poll = 3;
|
||||
int idx_pri = 5;
|
||||
struct in_addr nbr_addr;
|
||||
unsigned int priority;
|
||||
unsigned int interval;
|
||||
|
||||
if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
|
||||
vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
interval = strtoul(argv[idx_poll]->arg, NULL, 10);
|
||||
|
||||
priority = argc > 4 ? strtoul(argv[idx_pri]->arg, NULL, 10)
|
||||
: OSPF_NEIGHBOR_PRIORITY_DEFAULT;
|
||||
|
||||
ospf_nbr_nbma_set(ospf, nbr_addr);
|
||||
ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval);
|
||||
|
||||
if (argc > 4)
|
||||
ospf_nbr_nbma_priority_set(ospf, nbr_addr, priority);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_ospf_neighbor,
|
||||
no_ospf_neighbor_cmd,
|
||||
"no neighbor A.B.C.D [priority (0-255) [poll-interval (1-65525)]]",
|
||||
NO_STR
|
||||
NEIGHBOR_STR
|
||||
"Neighbor IP address\n"
|
||||
"Neighbor Priority\n"
|
||||
"Priority\n"
|
||||
"Dead Neighbor Polling interval\n"
|
||||
"Seconds\n")
|
||||
{
|
||||
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
|
||||
int idx_ipv4 = 2;
|
||||
struct in_addr nbr_addr;
|
||||
|
||||
if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
|
||||
vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
(void)ospf_nbr_nbma_unset(ospf, nbr_addr);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_ospf_neighbor_poll,
|
||||
no_ospf_neighbor_poll_cmd,
|
||||
"no neighbor A.B.C.D poll-interval (1-65535) [priority (0-255)]",
|
||||
NO_STR
|
||||
NEIGHBOR_STR
|
||||
"Neighbor IP address\n"
|
||||
"Dead Neighbor Polling interval\n"
|
||||
"Seconds\n"
|
||||
"Neighbor Priority\n"
|
||||
"Priority\n")
|
||||
{
|
||||
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
|
||||
int idx_ipv4 = 2;
|
||||
struct in_addr nbr_addr;
|
||||
|
||||
if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
|
||||
vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
(void)ospf_nbr_nbma_unset(ospf, nbr_addr);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -4148,6 +4048,8 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
|
||||
ospf_interface_auth_show(vty, oi, json_interface_sub, use_json);
|
||||
|
||||
ospf_interface_auth_show(vty, oi, json_oi, use_json);
|
||||
|
||||
/* Point-to-Multipoint Interface options. */
|
||||
if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
|
||||
if (use_json) {
|
||||
json_object_boolean_add(json_interface_sub,
|
||||
@ -4162,6 +4064,19 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
|
||||
" %sDelay reflooding LSAs received on P2MP interface\n",
|
||||
oi->p2mp_delay_reflood ? "" : "Don't ");
|
||||
}
|
||||
if (use_json) {
|
||||
json_object_boolean_add(json_interface_sub,
|
||||
"p2mpNonBroadcast",
|
||||
oi->p2mp_non_broadcast);
|
||||
|
||||
json_object_boolean_add(json_oi,
|
||||
"p2mpNonBroadcast",
|
||||
oi->p2mp_non_broadcast);
|
||||
} else {
|
||||
vty_out(vty,
|
||||
" P2MP interface does %ssupport broadcast\n",
|
||||
oi->p2mp_non_broadcast ? "not " : "");
|
||||
}
|
||||
}
|
||||
|
||||
/* Add ospf_interface object to main json blob using SIP as key
|
||||
@ -5970,7 +5885,7 @@ static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty,
|
||||
prev_nbr = nbr;
|
||||
}
|
||||
|
||||
if (oi->type != OSPF_IFTYPE_NBMA)
|
||||
if (!OSPF_IF_NON_BROADCAST(oi))
|
||||
continue;
|
||||
|
||||
struct listnode *nd;
|
||||
@ -8548,7 +8463,7 @@ DEFUN_HIDDEN (no_ospf_hello_interval,
|
||||
DEFUN(ip_ospf_network, ip_ospf_network_cmd,
|
||||
"ip ospf network <broadcast|"
|
||||
"non-broadcast|"
|
||||
"point-to-multipoint [delay-reflood]|"
|
||||
"point-to-multipoint [delay-reflood|non-broadcast]|"
|
||||
"point-to-point [dmvpn]>",
|
||||
"IP Information\n"
|
||||
"OSPF interface commands\n"
|
||||
@ -8557,6 +8472,7 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
|
||||
"Specify OSPF NBMA network\n"
|
||||
"Specify OSPF point-to-multipoint network\n"
|
||||
"Specify OSPF delayed reflooding of LSAs received on P2MP interface\n"
|
||||
"Specify OSPF point-to-multipoint network doesn't support broadcast\n"
|
||||
"Specify OSPF point-to-point network\n"
|
||||
"Specify OSPF point-to-point DMVPN network\n")
|
||||
{
|
||||
@ -8565,6 +8481,7 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
|
||||
int old_type = IF_DEF_PARAMS(ifp)->type;
|
||||
uint8_t old_ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
|
||||
uint8_t old_p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood;
|
||||
uint8_t old_p2mp_non_broadcast = IF_DEF_PARAMS(ifp)->p2mp_non_broadcast;
|
||||
struct route_node *rn;
|
||||
|
||||
if (old_type == OSPF_IFTYPE_LOOPBACK) {
|
||||
@ -8576,16 +8493,19 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
|
||||
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
|
||||
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
|
||||
OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
|
||||
IF_DEF_PARAMS(ifp)->p2mp_non_broadcast = OSPF_P2MP_NON_BROADCAST_DEFAULT;
|
||||
|
||||
if (argv_find(argv, argc, "broadcast", &idx))
|
||||
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_BROADCAST;
|
||||
else if (argv_find(argv, argc, "non-broadcast", &idx))
|
||||
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA;
|
||||
else if (argv_find(argv, argc, "point-to-multipoint", &idx)) {
|
||||
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT;
|
||||
if (argv_find(argv, argc, "delay-reflood", &idx))
|
||||
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood = true;
|
||||
} else if (argv_find(argv, argc, "point-to-point", &idx)) {
|
||||
if (argv_find(argv, argc, "non-broadcast", &idx))
|
||||
IF_DEF_PARAMS(ifp)->p2mp_non_broadcast = true;
|
||||
} else if (argv_find(argv, argc, "non-broadcast", &idx))
|
||||
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA;
|
||||
else if (argv_find(argv, argc, "point-to-point", &idx)) {
|
||||
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOPOINT;
|
||||
if (argv_find(argv, argc, "dmvpn", &idx))
|
||||
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1;
|
||||
@ -8593,7 +8513,8 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
|
||||
|
||||
if (IF_DEF_PARAMS(ifp)->type == old_type &&
|
||||
IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn &&
|
||||
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood == old_p2mp_delay_reflood)
|
||||
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood == old_p2mp_delay_reflood &&
|
||||
IF_DEF_PARAMS(ifp)->p2mp_non_broadcast == old_p2mp_non_broadcast)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
SET_IF_PARAM(IF_DEF_PARAMS(ifp), type);
|
||||
@ -8607,13 +8528,16 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
|
||||
oi->type = IF_DEF_PARAMS(ifp)->type;
|
||||
oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
|
||||
oi->p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood;
|
||||
oi->p2mp_non_broadcast = IF_DEF_PARAMS(ifp)->p2mp_non_broadcast;
|
||||
|
||||
/*
|
||||
* The OSPF interface only needs to be flapped if the network
|
||||
* type or DMVPN parameter changes.
|
||||
*/
|
||||
if (IF_DEF_PARAMS(ifp)->type != old_type ||
|
||||
IF_DEF_PARAMS(ifp)->ptp_dmvpn != old_ptp_dmvpn) {
|
||||
IF_DEF_PARAMS(ifp)->ptp_dmvpn != old_ptp_dmvpn ||
|
||||
IF_DEF_PARAMS(ifp)->p2mp_non_broadcast !=
|
||||
old_p2mp_non_broadcast) {
|
||||
if (oi->state > ISM_Down) {
|
||||
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
|
||||
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp);
|
||||
@ -8657,6 +8581,7 @@ DEFUN (no_ip_ospf_network,
|
||||
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
|
||||
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
|
||||
OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
|
||||
IF_DEF_PARAMS(ifp)->p2mp_non_broadcast = OSPF_P2MP_NON_BROADCAST_DEFAULT;
|
||||
|
||||
if (IF_DEF_PARAMS(ifp)->type == old_type)
|
||||
return CMD_SUCCESS;
|
||||
@ -12225,6 +12150,10 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
|
||||
OSPF_IFTYPE_POINTOMULTIPOINT &&
|
||||
params->p2mp_delay_reflood)
|
||||
vty_out(vty, " delay-reflood");
|
||||
if (params->type ==
|
||||
OSPF_IFTYPE_POINTOMULTIPOINT &&
|
||||
params->p2mp_non_broadcast)
|
||||
vty_out(vty, " non-broadcast");
|
||||
if (params != IF_DEF_PARAMS(ifp) && rn)
|
||||
vty_out(vty, " %pI4",
|
||||
&rn->p.u.prefix4);
|
||||
@ -13753,11 +13682,8 @@ void ospf_vty_init(void)
|
||||
install_element(OSPF_NODE, &ospf_auto_cost_reference_bandwidth_cmd);
|
||||
install_element(OSPF_NODE, &no_ospf_auto_cost_reference_bandwidth_cmd);
|
||||
|
||||
/* "neighbor" commands. */
|
||||
/* "neighbor" command. */
|
||||
install_element(OSPF_NODE, &ospf_neighbor_cmd);
|
||||
install_element(OSPF_NODE, &ospf_neighbor_poll_interval_cmd);
|
||||
install_element(OSPF_NODE, &no_ospf_neighbor_cmd);
|
||||
install_element(OSPF_NODE, &no_ospf_neighbor_poll_cmd);
|
||||
|
||||
/* write multiplier commands */
|
||||
install_element(OSPF_NODE, &ospf_write_multiplier_cmd);
|
||||
|
@ -1096,6 +1096,7 @@ struct ospf_interface *add_ospf_interface(struct connected *co,
|
||||
oi->type = IF_DEF_PARAMS(co->ifp)->type;
|
||||
oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
|
||||
oi->p2mp_delay_reflood = IF_DEF_PARAMS(co->ifp)->p2mp_delay_reflood;
|
||||
oi->p2mp_non_broadcast = IF_DEF_PARAMS(co->ifp)->p2mp_non_broadcast;
|
||||
|
||||
/* Add pseudo neighbor. */
|
||||
ospf_nbr_self_reset(oi, oi->ospf->router_id);
|
||||
@ -1989,7 +1990,7 @@ static void ospf_nbr_nbma_add(struct ospf_nbr_nbma *nbr_nbma,
|
||||
struct route_node *rn;
|
||||
struct prefix p;
|
||||
|
||||
if (oi->type != OSPF_IFTYPE_NBMA)
|
||||
if (!OSPF_IF_NON_BROADCAST(oi))
|
||||
return;
|
||||
|
||||
if (nbr_nbma->nbr != NULL)
|
||||
@ -2036,7 +2037,7 @@ void ospf_nbr_nbma_if_update(struct ospf *ospf, struct ospf_interface *oi)
|
||||
struct route_node *rn;
|
||||
struct prefix_ipv4 p;
|
||||
|
||||
if (oi->type != OSPF_IFTYPE_NBMA)
|
||||
if (!OSPF_IF_NON_BROADCAST(oi))
|
||||
return;
|
||||
|
||||
for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn))
|
||||
@ -2095,7 +2096,7 @@ int ospf_nbr_nbma_set(struct ospf *ospf, struct in_addr nbr_addr)
|
||||
rn->info = nbr_nbma;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
|
||||
if (oi->type == OSPF_IFTYPE_NBMA)
|
||||
if (OSPF_IF_NON_BROADCAST(oi))
|
||||
if (prefix_match(oi->address, (struct prefix *)&p)) {
|
||||
ospf_nbr_nbma_add(nbr_nbma, oi);
|
||||
break;
|
||||
|
26
tests/topotests/ospf_p2mp/r1/frr-p2mp-non-broadcast.conf
Normal file
26
tests/topotests/ospf_p2mp/r1/frr-p2mp-non-broadcast.conf
Normal file
@ -0,0 +1,26 @@
|
||||
!
|
||||
hostname r1
|
||||
password zebra
|
||||
log file /tmp/r1-frr.log
|
||||
ip forwarding
|
||||
!
|
||||
interface r1-eth0
|
||||
ip address 10.1.0.1/24
|
||||
ip ospf network point-to-multipoint non-broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
interface r1-eth1
|
||||
ip address 10.1.1.1/24
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
router ospf
|
||||
ospf router-id 1.1.1.1
|
||||
distance 20
|
||||
network 10.1.0.0/24 area 0
|
||||
network 10.1.1.0/24 area 0
|
||||
neighbor 10.1.0.2 poll-interval 5
|
||||
neighbor 10.1.0.3 poll-interval 5
|
||||
neighbor 10.1.0.4 poll-interval 5
|
||||
!
|
23
tests/topotests/ospf_p2mp/r1/frr-p2mp.conf
Normal file
23
tests/topotests/ospf_p2mp/r1/frr-p2mp.conf
Normal file
@ -0,0 +1,23 @@
|
||||
!
|
||||
hostname r1
|
||||
password zebra
|
||||
log file /tmp/r1-frr.log
|
||||
ip forwarding
|
||||
!
|
||||
interface r1-eth0
|
||||
ip address 10.1.0.1/24
|
||||
ip ospf network point-to-multipoint
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
interface r1-eth1
|
||||
ip address 10.1.1.1/24
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
router ospf
|
||||
ospf router-id 1.1.1.1
|
||||
distance 20
|
||||
network 10.1.0.0/24 area 0
|
||||
network 10.1.1.0/24 area 0
|
||||
!
|
29
tests/topotests/ospf_p2mp/r2/frr-p2mp-non-broadcast.conf
Normal file
29
tests/topotests/ospf_p2mp/r2/frr-p2mp-non-broadcast.conf
Normal file
@ -0,0 +1,29 @@
|
||||
!
|
||||
hostname r2
|
||||
password zebra
|
||||
log file /tmp/r1-frr.log
|
||||
ip forwarding
|
||||
!
|
||||
interface r2-eth0
|
||||
ip address 10.1.0.2/24
|
||||
ip ospf network point-to-multipoint non-broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
interface r2-eth1
|
||||
ip address 10.1.2.2/24
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
!
|
||||
!
|
||||
router ospf
|
||||
ospf router-id 2.2.2.2
|
||||
distance 20
|
||||
network 10.1.0.0/24 area 0
|
||||
network 10.1.2.0/24 area 0
|
||||
neighbor 10.1.0.1 poll-interval 5
|
||||
neighbor 10.1.0.3 poll-interval 5
|
||||
neighbor 10.1.0.4 poll-interval 5
|
||||
!
|
26
tests/topotests/ospf_p2mp/r2/frr-p2mp.conf
Normal file
26
tests/topotests/ospf_p2mp/r2/frr-p2mp.conf
Normal file
@ -0,0 +1,26 @@
|
||||
!
|
||||
hostname r2
|
||||
password zebra
|
||||
log file /tmp/r1-frr.log
|
||||
ip forwarding
|
||||
!
|
||||
interface r2-eth0
|
||||
ip address 10.1.0.2/24
|
||||
ip ospf network point-to-multipoint
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
interface r2-eth1
|
||||
ip address 10.1.2.2/24
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
!
|
||||
!
|
||||
router ospf
|
||||
ospf router-id 2.2.2.2
|
||||
distance 20
|
||||
network 10.1.0.0/24 area 0
|
||||
network 10.1.2.0/24 area 0
|
||||
!
|
28
tests/topotests/ospf_p2mp/r3/frr-p2mp-non-broadcast.conf
Normal file
28
tests/topotests/ospf_p2mp/r3/frr-p2mp-non-broadcast.conf
Normal file
@ -0,0 +1,28 @@
|
||||
!
|
||||
hostname r3
|
||||
password zebra
|
||||
log file /tmp/r1-frr.log
|
||||
ip forwarding
|
||||
!
|
||||
interface r3-eth0
|
||||
ip address 10.1.0.3/24
|
||||
ip ospf network point-to-multipoint non-broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
interface r3-eth1
|
||||
ip address 10.1.3.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.0.0/24 area 0
|
||||
network 10.1.3.0/24 area 0
|
||||
neighbor 10.1.0.1 poll-interval 5
|
||||
neighbor 10.1.0.2 poll-interval 5
|
||||
neighbor 10.1.0.4 poll-interval 5
|
25
tests/topotests/ospf_p2mp/r3/frr-p2mp.conf
Normal file
25
tests/topotests/ospf_p2mp/r3/frr-p2mp.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.0.3/24
|
||||
ip ospf network point-to-multipoint
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
interface r3-eth1
|
||||
ip address 10.1.3.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.0.0/24 area 0
|
||||
network 10.1.3.0/24 area 0
|
28
tests/topotests/ospf_p2mp/r4/frr-p2mp-non-broadcast.conf
Normal file
28
tests/topotests/ospf_p2mp/r4/frr-p2mp-non-broadcast.conf
Normal file
@ -0,0 +1,28 @@
|
||||
!
|
||||
hostname r4
|
||||
password zebra
|
||||
log file /tmp/r1-frr.log
|
||||
ip forwarding
|
||||
!
|
||||
interface r4-eth0
|
||||
ip address 10.1.0.4/24
|
||||
ip ospf network point-to-multipoint non-broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
interface r4-eth1
|
||||
ip address 10.1.4.4/24
|
||||
ip ospf network broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
router ospf
|
||||
ospf router-id 4.4.4.4
|
||||
distance 20
|
||||
network 10.1.0.0/24 area 0
|
||||
network 10.1.4.0/24 area 0
|
||||
neighbor 10.1.0.1 poll-interval 5
|
||||
neighbor 10.1.0.2 poll-interval 5
|
||||
neighbor 10.1.0.3 poll-interval 5
|
25
tests/topotests/ospf_p2mp/r4/frr-p2mp.conf
Normal file
25
tests/topotests/ospf_p2mp/r4/frr-p2mp.conf
Normal file
@ -0,0 +1,25 @@
|
||||
!
|
||||
hostname r4
|
||||
password zebra
|
||||
log file /tmp/r1-frr.log
|
||||
ip forwarding
|
||||
!
|
||||
interface r4-eth0
|
||||
ip address 10.1.0.4/24
|
||||
ip ospf network point-to-multipoint
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
interface r4-eth1
|
||||
ip address 10.1.4.4/24
|
||||
ip ospf network broadcast
|
||||
ip ospf hello-interval 1
|
||||
ip ospf dead-interval 30
|
||||
!
|
||||
!
|
||||
router ospf
|
||||
ospf router-id 4.4.4.4
|
||||
distance 20
|
||||
network 10.1.0.0/24 area 0
|
||||
network 10.1.4.0/24 area 0
|
346
tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py
Normal file
346
tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py
Normal file
@ -0,0 +1,346 @@
|
||||
#!/usr/bin/env python
|
||||
# SPDX-License-Identifier: ISC
|
||||
#
|
||||
# test_ospf_prefix_p2mp_broadcast.py
|
||||
#
|
||||
# Copyright (c) 2024 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_p2mp_broadcast.py: Test OSPF Point-to-multipoint
|
||||
"""
|
||||
|
||||
TOPOLOGY = """
|
||||
+-----+ +-----+
|
||||
10.1.1.0/24 | r1 | | r2 | 10.1.2.0/24
|
||||
-----------+ | | +----------
|
||||
+--+--+ +--+--+
|
||||
| 10.1.0.0/24 |
|
||||
| +-------+ |
|
||||
+---- | |-----+
|
||||
| P2MP |
|
||||
+---- | |-----+
|
||||
| +-------+ |
|
||||
| |
|
||||
| |
|
||||
+--+--+ +-+---+
|
||||
10.1.3.0/24 | r3 | | r4 | 10.1.4.0/24
|
||||
-----------+ | | +----------
|
||||
+-----+ +-----+
|
||||
|
||||
|
||||
"""
|
||||
|
||||
# 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 4 routers
|
||||
tgen.add_router("r1")
|
||||
tgen.add_router("r2")
|
||||
tgen.add_router("r3")
|
||||
tgen.add_router("r4")
|
||||
|
||||
# Interconect them all to the P2MP network
|
||||
switch = tgen.add_switch("s0-p2mp")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
switch.add_link(tgen.gears["r3"])
|
||||
switch.add_link(tgen.gears["r4"])
|
||||
|
||||
# Add standalone network to router 1
|
||||
switch = tgen.add_switch("s-r1-1")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
|
||||
# Add standalone network to router 2
|
||||
switch = tgen.add_switch("s-r2-1")
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
|
||||
# Add standalone network to router 3
|
||||
switch = tgen.add_switch("s-r3-1")
|
||||
switch.add_link(tgen.gears["r3"])
|
||||
|
||||
# Add standalone network to router 4
|
||||
switch = tgen.add_switch("s-r4-1")
|
||||
switch.add_link(tgen.gears["r4"])
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
logger.info("OSPF Point-to-MultiPoint:\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-p2mp.conf".format(rname)))
|
||||
|
||||
# Initialize all routers.
|
||||
tgen.start_router()
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
"Teardown the pytest environment"
|
||||
tgen = get_topogen()
|
||||
tgen.stop_topology()
|
||||
|
||||
|
||||
def verify_p2mp_interface(tgen):
|
||||
"Verify the P2MP Configuration and interface settings"
|
||||
|
||||
r1 = tgen.gears["r1"]
|
||||
|
||||
step("Test running configuration for P2MP configuration")
|
||||
rc = 0
|
||||
rc, _, _ = tgen.net["r1"].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"
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Test OSPF interface for P2MP settings")
|
||||
input_dict = {
|
||||
"interfaces": {
|
||||
"r1-eth0": {
|
||||
"ospfEnabled": True,
|
||||
"interfaceIp": {
|
||||
"10.1.0.1": {
|
||||
"ipAddress": "10.1.0.1",
|
||||
"ipAddressPrefixlen": 24,
|
||||
"ospfIfType": "Broadcast",
|
||||
"routerId": "1.1.1.1",
|
||||
"networkType": "POINTOMULTIPOINT",
|
||||
"cost": 10,
|
||||
"state": "Point-To-Point",
|
||||
"nbrCount": 3,
|
||||
"nbrAdjacentCount": 3,
|
||||
"prefixSuppression": False,
|
||||
"p2mpDelayReflood": False,
|
||||
"p2mpNonBroadcast": False,
|
||||
}
|
||||
},
|
||||
"ipAddress": "10.1.0.1",
|
||||
"ipAddressPrefixlen": 24,
|
||||
"ospfIfType": "Broadcast",
|
||||
"area": "0.0.0.0",
|
||||
"routerId": "1.1.1.1",
|
||||
"networkType": "POINTOMULTIPOINT",
|
||||
"cost": 10,
|
||||
"state": "Point-To-Point",
|
||||
"opaqueCapable": True,
|
||||
"nbrCount": 3,
|
||||
"nbrAdjacentCount": 3,
|
||||
"prefixSuppression": False,
|
||||
"p2mpDelayReflood": False,
|
||||
"p2mpNonBroadcast": False,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r1, "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"
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def verify_non_p2mp_interface(tgen):
|
||||
"Verify the removal of P2MP Configuration and interface settings"
|
||||
r1 = tgen.gears["r1"]
|
||||
|
||||
step("Test running configuration for removal of P2MP configuration")
|
||||
rc = 0
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
"show running ospfd | grep -q 'ip ospf network point-to-multipoint'", warn=False
|
||||
)
|
||||
assertmsg = "'ip ospf network point-to-multipoint' not applied, but present in r1 configuration"
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Test OSPF interface for default settings")
|
||||
input_dict = {
|
||||
"interfaces": {
|
||||
"r1-eth0": {
|
||||
"ospfEnabled": True,
|
||||
"interfaceIp": {
|
||||
"10.1.0.1": {
|
||||
"ipAddress": "10.1.0.1",
|
||||
"ipAddressPrefixlen": 24,
|
||||
"ospfIfType": "Broadcast",
|
||||
"routerId": "1.1.1.1",
|
||||
"networkType": "BROADCAST",
|
||||
"cost": 10,
|
||||
"prefixSuppression": False,
|
||||
}
|
||||
},
|
||||
"ipAddress": "10.1.0.1",
|
||||
"ipAddressPrefixlen": 24,
|
||||
"ospfIfType": "Broadcast",
|
||||
"area": "0.0.0.0",
|
||||
"routerId": "1.1.1.1",
|
||||
"networkType": "BROADCAST",
|
||||
"cost": 10,
|
||||
"opaqueCapable": True,
|
||||
"prefixSuppression": False,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r1, "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"
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def verify_p2mp_neighbor(tgen, router, neighbor, state, intf_addr, interface):
|
||||
topo_router = tgen.gears[router]
|
||||
|
||||
step("Verify neighbor " + neighbor + " in " + state + " state")
|
||||
input_dict = {
|
||||
"default": {
|
||||
neighbor: [
|
||||
{
|
||||
"nbrState": state,
|
||||
"ifaceAddress": intf_addr,
|
||||
"ifaceName": interface,
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
topo_router,
|
||||
"show ip ospf neighbor " + neighbor + " json",
|
||||
input_dict,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "P2MP Neighbor " + neighbor + " not in " + state
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def verify_p2mp_route(tgen, router, prefix, prefix_len, nexthop, interface):
|
||||
topo_router = tgen.gears[router]
|
||||
|
||||
step("Verify router " + router + " p2mp route " + prefix + " installed")
|
||||
input_dict = {
|
||||
prefix: [
|
||||
{
|
||||
"prefix": prefix,
|
||||
"prefixLen": prefix_len,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": nexthop,
|
||||
"interfaceName": interface,
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
topo_router,
|
||||
"show ip route " + prefix + " json",
|
||||
input_dict,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = prefix + " not installed on router " + router
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def test_p2mp_broadcast_interface():
|
||||
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)
|
||||
|
||||
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("Verify router r1 p2mp routes installed")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.3", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
|
||||
|
||||
step("Verify router r1 interface r1-eth0 p2mp configuration removal")
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip ospf network point-to-multipoint")
|
||||
verify_non_p2mp_interface(tgen)
|
||||
|
||||
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)
|
||||
|
||||
step("Verify restablishment of r1-eth0 p2mp 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("Verify router r1 p2mp routes reinstalled")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.3", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
|
||||
|
||||
|
||||
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))
|
467
tests/topotests/ospf_p2mp/test_ospf_p2mp_non_broadcast.py
Normal file
467
tests/topotests/ospf_p2mp/test_ospf_p2mp_non_broadcast.py
Normal file
@ -0,0 +1,467 @@
|
||||
#!/usr/bin/env python
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
#
|
||||
# test_ospf_prefix_p2mp_non_broadcast.py
|
||||
#
|
||||
# Copyright (c) 2024 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_p2mp_non_broadcast.py: Test OSPF Point-to-multipoint Non-Broadcast
|
||||
Full Mesh
|
||||
"""
|
||||
|
||||
TOPOLOGY = """
|
||||
+-----+ +-----+
|
||||
10.1.1.0/24 | r1 | | r2 | 10.1.2.0/24
|
||||
-----------+ | | +----------
|
||||
+--+--+ +--+--+
|
||||
| 10.1.0.0/24 |
|
||||
| +-------+ |
|
||||
+---- | |-----+
|
||||
| P2MP |
|
||||
+---- | |-----+
|
||||
| +-------+ |
|
||||
| |
|
||||
| |
|
||||
+--+--+ +-+---+
|
||||
10.1.3.0/24 | r3 | | r4 | 10.1.4.0/24
|
||||
-----------+ | | +----------
|
||||
+-----+ +-----+
|
||||
|
||||
|
||||
"""
|
||||
|
||||
# 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 4 routers
|
||||
tgen.add_router("r1")
|
||||
tgen.add_router("r2")
|
||||
tgen.add_router("r3")
|
||||
tgen.add_router("r4")
|
||||
|
||||
# Interconect them all to the P2MP network
|
||||
switch = tgen.add_switch("s0-p2mp")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
switch.add_link(tgen.gears["r3"])
|
||||
switch.add_link(tgen.gears["r4"])
|
||||
|
||||
# Add standalone network to router 1
|
||||
switch = tgen.add_switch("s-r1-1")
|
||||
switch.add_link(tgen.gears["r1"])
|
||||
|
||||
# Add standalone network to router 2
|
||||
switch = tgen.add_switch("s-r2-1")
|
||||
switch.add_link(tgen.gears["r2"])
|
||||
|
||||
# Add standalone network to router 3
|
||||
switch = tgen.add_switch("s-r3-1")
|
||||
switch.add_link(tgen.gears["r3"])
|
||||
|
||||
# Add standalone network to router 4
|
||||
switch = tgen.add_switch("s-r4-1")
|
||||
switch.add_link(tgen.gears["r4"])
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
logger.info("OSPF Point-to-MultiPoint Non-Broadcast:\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-p2mp-non-broadcast.conf".format(rname))
|
||||
)
|
||||
|
||||
# Initialize all routers.
|
||||
tgen.start_router()
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
"Teardown the pytest environment"
|
||||
tgen = get_topogen()
|
||||
tgen.stop_topology()
|
||||
|
||||
|
||||
def verify_p2mp_interface(tgen, router, nbr_cnt, nbr_adj_cnt, non_broadcast):
|
||||
"Verify the P2MP Configuration and interface settings"
|
||||
|
||||
topo_router = tgen.gears[router]
|
||||
|
||||
step("Test running configuration for P2MP configuration")
|
||||
rc = 0
|
||||
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 "
|
||||
+ router
|
||||
+ "configuration"
|
||||
)
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Test OSPF interface for P2MP settings")
|
||||
input_dict = {
|
||||
"interfaces": {
|
||||
"r1-eth0": {
|
||||
"ospfEnabled": True,
|
||||
"interfaceIp": {
|
||||
"10.1.0.1": {
|
||||
"ipAddress": "10.1.0.1",
|
||||
"ipAddressPrefixlen": 24,
|
||||
"ospfIfType": "Broadcast",
|
||||
"routerId": "1.1.1.1",
|
||||
"networkType": "POINTOMULTIPOINT",
|
||||
"cost": 10,
|
||||
"state": "Point-To-Point",
|
||||
"nbrCount": nbr_cnt,
|
||||
"nbrAdjacentCount": nbr_adj_cnt,
|
||||
"prefixSuppression": False,
|
||||
"p2mpDelayReflood": False,
|
||||
"p2mpNonBroadcast": non_broadcast,
|
||||
}
|
||||
},
|
||||
"ipAddress": "10.1.0.1",
|
||||
"ipAddressPrefixlen": 24,
|
||||
"ospfIfType": "Broadcast",
|
||||
"area": "0.0.0.0",
|
||||
"routerId": "1.1.1.1",
|
||||
"networkType": "POINTOMULTIPOINT",
|
||||
"cost": 10,
|
||||
"state": "Point-To-Point",
|
||||
"opaqueCapable": True,
|
||||
"nbrCount": nbr_cnt,
|
||||
"nbrAdjacentCount": nbr_adj_cnt,
|
||||
"prefixSuppression": False,
|
||||
"p2mpDelayReflood": False,
|
||||
"p2mpNonBroadcast": non_broadcast,
|
||||
}
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
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"
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def verify_p2mp_neighbor(tgen, router, neighbor, state, intf_addr, interface):
|
||||
topo_router = tgen.gears[router]
|
||||
|
||||
step("Verify neighbor " + neighbor + " in " + state + " state")
|
||||
input_dict = {
|
||||
"default": {
|
||||
neighbor: [
|
||||
{
|
||||
"nbrState": state,
|
||||
"ifaceAddress": intf_addr,
|
||||
"ifaceName": interface,
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
topo_router,
|
||||
"show ip ospf neighbor " + neighbor + " json",
|
||||
input_dict,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "P2MP Neighbor " + neighbor + " not in " + state
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def verify_p2mp_route(tgen, router, prefix, prefix_len, nexthop, interface):
|
||||
topo_router = tgen.gears[router]
|
||||
|
||||
step("Verify router " + router + " p2mp route " + prefix + " installed")
|
||||
input_dict = {
|
||||
prefix: [
|
||||
{
|
||||
"prefix": prefix,
|
||||
"prefixLen": prefix_len,
|
||||
"protocol": "ospf",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": nexthop,
|
||||
"interfaceName": interface,
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
topo_router,
|
||||
"show ip route " + prefix + " json",
|
||||
input_dict,
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = prefix + " not installed on router " + router
|
||||
assert result is None, assertmsg
|
||||
|
||||
|
||||
def test_p2mp_non_broadcast_connectivity():
|
||||
tgen = get_topogen()
|
||||
r1 = tgen.gears["r1"]
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip("Skipped because of router(s) failure")
|
||||
|
||||
step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
|
||||
verify_p2mp_interface(tgen, "r1", 3, 3, True)
|
||||
|
||||
step("Verify router r1 interface r1-eth0 p2mp non-broadcast configuration")
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
"show running ospfd | grep -q 'ip ospf network point-to-multipoint non-broadcast'",
|
||||
warn=False,
|
||||
)
|
||||
assertmsg = "'ip ospf network point-to-multipoint non-broadcast' applied, but not present in R1 configuration"
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Verify router r1 OSPF point-to-multipoint 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("Verify router r1 OSPF point-to-multipoint routes are installed")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.3", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
|
||||
|
||||
step("Remove r1 interface r1-eth0 p2mp non-broadcast configuration")
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf network point-to-multipoint")
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
"show running ospfd | grep -q 'ip ospf network point-to-multipoint non-broadcast'",
|
||||
warn=False,
|
||||
)
|
||||
assertmsg = "'ip ospf network point-to-multipoint non-broadcast' not applied, but present in r1 configuration"
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Verify router r1 interface OSPF point-to-multipoint broadcast interface")
|
||||
verify_p2mp_interface(tgen, "r1", 3, 3, False)
|
||||
|
||||
step("Add r1 interface r1-eth0 p2mp non-broadcast configuration back")
|
||||
r1.vtysh_cmd(
|
||||
"conf t\ninterface r1-eth0\nip ospf network point-to-multipoint non-broadcast"
|
||||
)
|
||||
rc, _, _ = tgen.net["r1"].cmd_status(
|
||||
"show running ospfd | grep 'ip ospf network point-to-multipoint non-broadcast'",
|
||||
warn=False,
|
||||
)
|
||||
assertmsg = "'ip ospf netrwork point-to-multipoint non-broadcast' applied, but not present in R1 configuration"
|
||||
assert rc, assertmsg
|
||||
|
||||
step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
|
||||
verify_p2mp_interface(tgen, "r1", 3, 3, True)
|
||||
|
||||
step(
|
||||
"Verify router r1 OSPF point-to-multipoint neighbors adjacencies restablished."
|
||||
)
|
||||
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"
|
||||
)
|
||||
|
||||
|
||||
def test_p2mp_non_broadcast_partial_mesh_connectivity():
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip("Skipped because of router(s) failure")
|
||||
|
||||
"""
|
||||
test_ospf_p2mp_non_broadcast.py: Test OSPF Point-to-multipoint Non-Broadcast
|
||||
Partial Mesh
|
||||
"""
|
||||
|
||||
TOPOLOGY = """
|
||||
+-----+ +------+
|
||||
10.1.1.0/24 | r1 | | r4 | 10.1.4.0/24
|
||||
-----------+ | | +----------
|
||||
+-+---+ +--+-+-+
|
||||
| P2MP |
|
||||
| Non-Broadcast |
|
||||
| 10.1.0.0/24 |
|
||||
+-+---+ +-+---+
|
||||
10.1.2.0/24 | r2 | | r3 | 10.1.3.0/24
|
||||
-----------+ +--------------+ +----------
|
||||
+-----+ +-----+
|
||||
|
||||
|
||||
"""
|
||||
logger.info("OSPF Point-to-MultiPoint Non-Broadcast:\n {}".format(TOPOLOGY))
|
||||
|
||||
step("Change configuration to a partial mesh")
|
||||
step("Delete neighbors in full mesh")
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.3")
|
||||
r1.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.4")
|
||||
r2 = tgen.gears["r2"]
|
||||
r2.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.4")
|
||||
r3 = tgen.gears["r3"]
|
||||
r3.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.1")
|
||||
r4 = tgen.gears["r4"]
|
||||
r4.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.1")
|
||||
r4.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.2")
|
||||
|
||||
step("Flap interfaces on P2MP network to avoid transients")
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nshut")
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth0\nshut")
|
||||
r3.vtysh_cmd("conf t\ninterface r3-eth0\nshut")
|
||||
r4.vtysh_cmd("conf t\ninterface r4-eth0\nshut")
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nno shut")
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth0\nno shut")
|
||||
r3.vtysh_cmd("conf t\ninterface r3-eth0\nno shut")
|
||||
r4.vtysh_cmd("conf t\ninterface r4-eth0\nno shut")
|
||||
|
||||
step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
|
||||
verify_p2mp_interface(tgen, "r1", 1, 1, True)
|
||||
|
||||
step("Verify router r1 interface r1-eth0 p2mp neighbor")
|
||||
verify_p2mp_neighbor(
|
||||
tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
|
||||
)
|
||||
|
||||
step("Verify router r1 p2mp routes are installed")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.2", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.2", "r1-eth0")
|
||||
|
||||
"""
|
||||
test_ospf_p2mp_non_broadcast.py: Test OSPF Point-to-multipoint Non-Broadcast
|
||||
Modified Partial Mesh
|
||||
"""
|
||||
|
||||
TOPOLOGY = """
|
||||
+-----+ +------+
|
||||
10.1.1.0/24 | r1 | | r4 | 10.1.4.0/24
|
||||
-----------+ +-------------+ +----------
|
||||
+-----+ +--+-+-+
|
||||
P2MP |
|
||||
Non-Broadcast |
|
||||
10.1.0.0/24 |
|
||||
+-+---+ +-+---+
|
||||
10.1.2.0/24 | r2 | | r3 | 10.1.3.0/24
|
||||
-----------+ +--------------+ +----------
|
||||
+-----+ +-----+
|
||||
|
||||
|
||||
"""
|
||||
logger.info("OSPF Point-to-MultiPoint Non-Broadcast:\n {}".format(TOPOLOGY))
|
||||
|
||||
step("Change configuration to a partial mesh")
|
||||
step("Modify neighbors in partial mesh")
|
||||
r1 = tgen.gears["r1"]
|
||||
r1.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.2")
|
||||
r1.vtysh_cmd("conf t\nrouter ospf\nneighbor 10.1.0.4 poll-interval 5")
|
||||
r2 = tgen.gears["r2"]
|
||||
r2.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.1")
|
||||
r4 = tgen.gears["r4"]
|
||||
r4.vtysh_cmd("conf t\nrouter ospf\nneighbor 10.1.0.1")
|
||||
|
||||
step("Flap interfaces on P2MP network to avoid transients")
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nshut")
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth0\nshut")
|
||||
r3.vtysh_cmd("conf t\ninterface r3-eth0\nshut")
|
||||
r4.vtysh_cmd("conf t\ninterface r4-eth0\nshut")
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nno shut")
|
||||
r2.vtysh_cmd("conf t\ninterface r2-eth0\nno shut")
|
||||
r3.vtysh_cmd("conf t\ninterface r3-eth0\nno shut")
|
||||
r4.vtysh_cmd("conf t\ninterface r4-eth0\nno shut")
|
||||
|
||||
step("Verify router r1 interface r1-eth0")
|
||||
step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
|
||||
verify_p2mp_interface(tgen, "r1", 1, 1, True)
|
||||
|
||||
step("Verify router r1 interface r1-eth0 p2mp neighbor")
|
||||
input_dict = {
|
||||
"neighbors": {
|
||||
"4.4.4.4": [
|
||||
{
|
||||
"nbrState": "Full/DROther",
|
||||
"ifaceAddress": "10.1.0.4",
|
||||
"ifaceName": "r1-eth0:10.1.0.1",
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp, r1, "show ip ospf neighbor json", input_dict
|
||||
)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
|
||||
assertmsg = "P2MP Non-Broadcast Neighbors not adjacent on router r1"
|
||||
assert result is None, assertmsg
|
||||
|
||||
step("Verify router r1 interface r1-eth0 p2mp routes are installed")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.4", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.4", "r1-eth0")
|
||||
verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
|
||||
|
||||
|
||||
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 New Issue
Block a user