mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 14:34:22 +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.
|
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
|
This config enables/disables helper support on this router
|
||||||
for all neighbours.
|
for all neighbors.
|
||||||
To enable/disable helper support for a specific
|
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
|
.. 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
|
:term:`distance-vector` protocols, such as :abbr:`RIP` or :abbr:`BGP`, where
|
||||||
routers describe available `paths` (i.e. routes) to each other, in
|
routers describe available `paths` (i.e. routes) to each other, in
|
||||||
:term:`link-state` protocols routers instead describe the state of their links
|
:term:`link-state` protocols routers instead describe the state of their links
|
||||||
to their immediate neighbouring routers.
|
to their immediate neighboring routers.
|
||||||
|
|
||||||
.. index::
|
.. index::
|
||||||
single: Link State Announcement
|
single: Link State Announcement
|
||||||
@ -127,7 +127,7 @@ LSA Flooding
|
|||||||
""""""""""""
|
""""""""""""
|
||||||
|
|
||||||
OSPF defines several related mechanisms, used to manage synchronisation of
|
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.
|
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.
|
LSA is originated for such a link.
|
||||||
|
|
||||||
Stub
|
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
|
- 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.
|
of different LSA types.
|
||||||
|
|
||||||
The first LSA being the router LSA describing 192.168.0.49's links: 2 links
|
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
|
to multi-access networks with fully-adjacent neighbors (i.e. Transit
|
||||||
links) and 1 being a Stub link (no adjacent neighbours).
|
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
|
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
|
: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
|
This configuration setting MUST be consistent across all routers within the
|
||||||
OSPF domain.
|
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 A.B.C.D
|
||||||
|
|
||||||
.. clicmd:: network A.B.C.D/M area (0-4294967295)
|
.. 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
|
Note that OSPF MD5 authentication requires that time never go backwards
|
||||||
(correct time is NOT important, only that it never goes backwards), even
|
(correct time is NOT important, only that it never goes backwards), even
|
||||||
across resets, if ospfd is to be able to promptly reestablish adjacencies
|
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
|
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
|
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
|
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
|
Note that OSPF HMAC cryptographic authentication requires that time never go backwards
|
||||||
(correct time is NOT important, only that it never goes backwards), even
|
(correct time is NOT important, only that it never goes backwards), even
|
||||||
across resets, if ospfd is to be able to promptly reestablish adjacencies
|
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
|
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
|
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
|
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.
|
it's recommended to set the hello delay and hello interval with the same values.
|
||||||
The default value is 10 seconds.
|
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
|
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
|
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
|
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.
|
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`
|
When the network is configured as point-to-multipoint and `delay-reflood`
|
||||||
is specified, LSAs received on the interface from neighbors on the
|
is specified, LSAs received on the interface from neighbors on the
|
||||||
interface will not be flooded back out on the interface immediately.
|
interface will not be flooded back out on the interface immediately.
|
||||||
@ -838,11 +856,11 @@ Graceful Restart
|
|||||||
|
|
||||||
|
|
||||||
Configure Graceful Restart (RFC 3623) helper support.
|
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
|
This config enables/disables helper support on this router
|
||||||
for all neighbours.
|
for all neighbors.
|
||||||
To enable/disable helper support for a specific
|
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
|
.. clicmd:: graceful-restart helper strict-lsa-checking
|
||||||
|
|
||||||
@ -1082,7 +1100,7 @@ Router Information
|
|||||||
respectively the PCE IP address, Autonomous System (AS) numbers of
|
respectively the PCE IP address, Autonomous System (AS) numbers of
|
||||||
controlled domains, neighbor ASs, flag and scope. For flag and scope, please
|
controlled domains, neighbor ASs, flag and scope. For flag and scope, please
|
||||||
refer to :rfc`5088` for the BITPATTERN recognition. Multiple 'pce neighbor'
|
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
|
.. clicmd:: show ip ospf router-info
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ extern "C" {
|
|||||||
#define OSPF_MTU_IGNORE_DEFAULT 0
|
#define OSPF_MTU_IGNORE_DEFAULT 0
|
||||||
#define OSPF_FAST_HELLO_DEFAULT 0
|
#define OSPF_FAST_HELLO_DEFAULT 0
|
||||||
#define OSPF_P2MP_DELAY_REFLOOD_DEFAULT false
|
#define OSPF_P2MP_DELAY_REFLOOD_DEFAULT false
|
||||||
|
#define OSPF_P2MP_NON_BROADCAST_DEFAULT false
|
||||||
#define OSPF_OPAQUE_CAPABLE_DEFAULT true
|
#define OSPF_OPAQUE_CAPABLE_DEFAULT true
|
||||||
#define OSPF_PREFIX_SUPPRESSION_DEFAULT false
|
#define OSPF_PREFIX_SUPPRESSION_DEFAULT false
|
||||||
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
|
#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
|
packets must be sent, as unicasts, to each adjacent neighbor
|
||||||
(i.e., those in state Exchange or greater). The destination
|
(i.e., those in state Exchange or greater). The destination
|
||||||
IP addresses for these packets are the neighbors' IP
|
IP addresses for these packets are the neighbors' IP
|
||||||
addresses. */
|
addresses. This behavior is extended to P2MP networks which
|
||||||
if (oi->type == OSPF_IFTYPE_NBMA) {
|
don't support broadcast. */
|
||||||
|
if (OSPF_IF_NON_BROADCAST(oi)) {
|
||||||
struct ospf_neighbor *nbr;
|
struct ospf_neighbor *nbr;
|
||||||
|
|
||||||
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
|
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. */
|
/* Set default values. */
|
||||||
/* don't clear this flag. oi->flag = OSPF_IF_DISABLE; */
|
|
||||||
|
|
||||||
if (oi->vl_data)
|
oi->type = OSPF_IFTYPE_BROADCAST;
|
||||||
oi->type = OSPF_IFTYPE_VIRTUALLINK;
|
|
||||||
else
|
|
||||||
/* preserve network-type */
|
|
||||||
if (oi->type != OSPF_IFTYPE_NBMA)
|
|
||||||
oi->type = OSPF_IFTYPE_BROADCAST;
|
|
||||||
|
|
||||||
oi->state = ISM_Down;
|
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();
|
oi->ls_ack_direct.ls_ack = list_new();
|
||||||
|
|
||||||
/* Set default values. */
|
/* Set default values. */
|
||||||
ospf_if_reset_variables(oi);
|
ospf_if_default_variables(oi);
|
||||||
|
|
||||||
/* Set pseudo neighbor to Null */
|
/* Set pseudo neighbor to Null */
|
||||||
oi->nbr_self = NULL;
|
oi->nbr_self = NULL;
|
||||||
|
@ -119,6 +119,9 @@ struct ospf_if_params {
|
|||||||
/* point-to-multipoint delayed reflooding configuration */
|
/* point-to-multipoint delayed reflooding configuration */
|
||||||
bool p2mp_delay_reflood;
|
bool p2mp_delay_reflood;
|
||||||
|
|
||||||
|
/* point-to-multipoint doesn't support broadcast */
|
||||||
|
bool p2mp_non_broadcast;
|
||||||
|
|
||||||
/* Opaque LSA capability at interface level (see RFC5250) */
|
/* Opaque LSA capability at interface level (see RFC5250) */
|
||||||
DECLARE_IF_PARAM(bool, opaque_capable);
|
DECLARE_IF_PARAM(bool, opaque_capable);
|
||||||
};
|
};
|
||||||
@ -185,6 +188,10 @@ struct ospf_interface {
|
|||||||
|
|
||||||
/* OSPF Network Type. */
|
/* OSPF Network Type. */
|
||||||
uint8_t 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 */
|
/* point-to-point DMVPN configuration */
|
||||||
uint8_t ptp_dmvpn;
|
uint8_t ptp_dmvpn;
|
||||||
@ -192,6 +199,9 @@ struct ospf_interface {
|
|||||||
/* point-to-multipoint delayed reflooding */
|
/* point-to-multipoint delayed reflooding */
|
||||||
bool p2mp_delay_reflood;
|
bool p2mp_delay_reflood;
|
||||||
|
|
||||||
|
/* point-to-multipoint doesn't support broadcast */
|
||||||
|
bool p2mp_non_broadcast;
|
||||||
|
|
||||||
/* State of Interface State Machine. */
|
/* State of Interface State Machine. */
|
||||||
uint8_t state;
|
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 int ospf_if_new_hook(struct interface *ifp);
|
||||||
extern void ospf_if_init(void);
|
extern void ospf_if_init(void);
|
||||||
extern void ospf_if_stream_unset(struct ospf_interface *oi);
|
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_is_enable(struct ospf_interface *oi);
|
||||||
extern int ospf_if_get_output_cost(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);
|
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. */
|
/* Otherwise, the state transitions to Waiting. */
|
||||||
next_state = ISM_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_nbr_nbma_if_update(oi->ospf, oi);
|
||||||
|
|
||||||
/* ospf_ism_event (t); */
|
/* 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));
|
memcpy(&nbr->address, p, sizeof(struct prefix));
|
||||||
|
|
||||||
nbr->nbr_nbma = NULL;
|
nbr->nbr_nbma = NULL;
|
||||||
if (oi->type == OSPF_IFTYPE_NBMA) {
|
if (OSPF_IF_NON_BROADCAST(oi)) {
|
||||||
struct ospf_nbr_nbma *nbr_nbma;
|
struct ospf_nbr_nbma *nbr_nbma;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
|
|
||||||
@ -485,7 +485,7 @@ struct ospf_neighbor *ospf_nbr_get(struct ospf_interface *oi,
|
|||||||
route_unlock_node(rn);
|
route_unlock_node(rn);
|
||||||
nbr = rn->info;
|
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;
|
nbr->src = iph->ip_src;
|
||||||
memcpy(&nbr->address, p, sizeof(struct prefix));
|
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,
|
OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer,
|
||||||
nbr->v_inactivity);
|
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);
|
EVENT_OFF(nbr->nbr_nbma->t_poll);
|
||||||
|
|
||||||
/* Send proactive ARP requests */
|
/* Send proactive ARP requests */
|
||||||
@ -377,7 +377,7 @@ static int nsm_kill_nbr(struct ospf_neighbor *nbr)
|
|||||||
return 0;
|
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;
|
struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma;
|
||||||
|
|
||||||
nbr_nbma->nbr = NULL;
|
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)
|
if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (oi->type != OSPF_IFTYPE_NBMA)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
|
if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PRIORITY(oi) == 0)
|
if (oi->type == OSPF_IFTYPE_NBMA) {
|
||||||
return;
|
if (PRIORITY(oi) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (nbr_nbma->priority == 0 && oi->state != ISM_DR
|
if (nbr_nbma->priority == 0 && oi->state != ISM_DR &&
|
||||||
&& oi->state != ISM_Backup)
|
oi->state != ISM_Backup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else if (oi->type != OSPF_IFTYPE_POINTOMULTIPOINT ||
|
||||||
|
!oi->p2mp_non_broadcast)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ospf_hello_send_sub(oi, nbr_nbma->addr.s_addr);
|
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)
|
if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (oi->type == OSPF_IFTYPE_NBMA) {
|
if (OSPF_IF_NON_BROADCAST(oi)) {
|
||||||
struct ospf_neighbor *nbr;
|
struct ospf_neighbor *nbr;
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
|
|
||||||
@ -3467,31 +3469,44 @@ void ospf_hello_send(struct ospf_interface *oi)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RFC 2328 Section 9.5.1
|
* Always send to all neighbors on Point-to-Multipoint
|
||||||
* If the router is not eligible to become Designated
|
* non-braodcast networks.
|
||||||
* Router, it must periodically send Hello Packets to
|
|
||||||
* both the Designated Router and the Backup
|
|
||||||
* Designated Router (if they exist).
|
|
||||||
*/
|
*/
|
||||||
if (PRIORITY(oi) == 0 &&
|
if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
|
||||||
IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
|
ospf_hello_send_sub(oi, nbr->address.u.prefix4
|
||||||
IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
|
.s_addr);
|
||||||
continue;
|
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
|
* If the router is eligible to become Designated
|
||||||
* Router, it must periodically send Hello Packets to
|
* Router, it must periodically send Hello Packets to
|
||||||
* all neighbors that are also eligible. In addition,
|
* all neighbors that are also eligible. In addition,
|
||||||
* if the router is itself the Designated Router or
|
* if the router is itself the Designated Router or
|
||||||
* Backup Designated Router, it must also send periodic
|
* Backup Designated Router, it must also send periodic
|
||||||
* Hello Packets to all other neighbors.
|
* Hello Packets to all other neighbors.
|
||||||
*/
|
*/
|
||||||
if (nbr->priority == 0 && oi->state == ISM_DROther)
|
if (nbr->priority == 0 &&
|
||||||
continue;
|
oi->state == ISM_DROther)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* if oi->state == Waiting, send
|
/* if oi->state == Waiting, send
|
||||||
* hello to all neighbors */
|
* hello to all neighbors */
|
||||||
ospf_hello_send_sub(oi, nbr->address.u.prefix4.s_addr);
|
ospf_hello_send_sub(oi, nbr->address.u.prefix4
|
||||||
|
.s_addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Decide destination address. */
|
/* Decide destination address. */
|
||||||
@ -3848,11 +3863,10 @@ void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag,
|
|||||||
else
|
else
|
||||||
p.prefix.s_addr = htonl(OSPF_ALLDROUTERS);
|
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)
|
if (flag == OSPF_SEND_PACKET_INDIRECT)
|
||||||
flog_warn(
|
flog_warn(EC_OSPF_PACKET,
|
||||||
EC_OSPF_PACKET,
|
"* LS-Update is directly sent on non-broadcast network.");
|
||||||
"* LS-Update is directly sent on NBMA network.");
|
|
||||||
if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix))
|
if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix))
|
||||||
flog_warn(EC_OSPF_PACKET,
|
flog_warn(EC_OSPF_PACKET,
|
||||||
"* LS-Update is sent to myself.");
|
"* 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. */
|
/* Decide destination address. */
|
||||||
if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
|
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);
|
op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS);
|
||||||
else
|
else
|
||||||
op->dst.s_addr = dst.s_addr;
|
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
|
networks, delayed Link State Acknowledgment packets must be
|
||||||
unicast separately over each adjacency (i.e., neighbor whose
|
unicast separately over each adjacency (i.e., neighbor whose
|
||||||
state is >= Exchange). */
|
state is >= Exchange). */
|
||||||
if (oi->type == OSPF_IFTYPE_NBMA) {
|
if (OSPF_IF_NON_BROADCAST(oi)) {
|
||||||
struct ospf_neighbor *nbr;
|
struct ospf_neighbor *nbr;
|
||||||
struct route_node *rn;
|
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;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (ospf_neighbor,
|
DEFPY(ospf_neighbor, ospf_neighbor_cmd,
|
||||||
ospf_neighbor_cmd,
|
"[no] neighbor A.B.C.D$nbr_address [{priority (0-255)$priority | poll-interval (1-65535)$interval}]",
|
||||||
"neighbor A.B.C.D [priority (0-255) [poll-interval (1-65535)]]",
|
NO_STR
|
||||||
NEIGHBOR_STR
|
NEIGHBOR_STR
|
||||||
"Neighbor IP address\n"
|
"Neighbor IP address\n"
|
||||||
"Neighbor Priority\n"
|
"Neighbor Priority\n"
|
||||||
"Priority\n"
|
"Priority\n"
|
||||||
"Dead Neighbor Polling interval\n"
|
"Dead Neighbor Polling interval\n"
|
||||||
"Seconds\n")
|
"Seconds\n")
|
||||||
{
|
{
|
||||||
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
|
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)) {
|
if (no)
|
||||||
vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
|
ospf_nbr_nbma_unset(ospf, nbr_address);
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
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;
|
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_interface_sub, use_json);
|
||||||
|
|
||||||
ospf_interface_auth_show(vty, oi, json_oi, use_json);
|
ospf_interface_auth_show(vty, oi, json_oi, use_json);
|
||||||
|
|
||||||
|
/* Point-to-Multipoint Interface options. */
|
||||||
if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
|
if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
|
||||||
if (use_json) {
|
if (use_json) {
|
||||||
json_object_boolean_add(json_interface_sub,
|
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",
|
" %sDelay reflooding LSAs received on P2MP interface\n",
|
||||||
oi->p2mp_delay_reflood ? "" : "Don't ");
|
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
|
/* 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;
|
prev_nbr = nbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oi->type != OSPF_IFTYPE_NBMA)
|
if (!OSPF_IF_NON_BROADCAST(oi))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
struct listnode *nd;
|
struct listnode *nd;
|
||||||
@ -8548,7 +8463,7 @@ DEFUN_HIDDEN (no_ospf_hello_interval,
|
|||||||
DEFUN(ip_ospf_network, ip_ospf_network_cmd,
|
DEFUN(ip_ospf_network, ip_ospf_network_cmd,
|
||||||
"ip ospf network <broadcast|"
|
"ip ospf network <broadcast|"
|
||||||
"non-broadcast|"
|
"non-broadcast|"
|
||||||
"point-to-multipoint [delay-reflood]|"
|
"point-to-multipoint [delay-reflood|non-broadcast]|"
|
||||||
"point-to-point [dmvpn]>",
|
"point-to-point [dmvpn]>",
|
||||||
"IP Information\n"
|
"IP Information\n"
|
||||||
"OSPF interface commands\n"
|
"OSPF interface commands\n"
|
||||||
@ -8557,6 +8472,7 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
|
|||||||
"Specify OSPF NBMA network\n"
|
"Specify OSPF NBMA network\n"
|
||||||
"Specify OSPF point-to-multipoint network\n"
|
"Specify OSPF point-to-multipoint network\n"
|
||||||
"Specify OSPF delayed reflooding of LSAs received on P2MP interface\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 network\n"
|
||||||
"Specify OSPF point-to-point DMVPN 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;
|
int old_type = IF_DEF_PARAMS(ifp)->type;
|
||||||
uint8_t old_ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
|
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_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;
|
struct route_node *rn;
|
||||||
|
|
||||||
if (old_type == OSPF_IFTYPE_LOOPBACK) {
|
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)->ptp_dmvpn = 0;
|
||||||
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
|
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
|
||||||
OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
|
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 (argv_find(argv, argc, "broadcast", &idx))
|
||||||
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_BROADCAST;
|
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)) {
|
else if (argv_find(argv, argc, "point-to-multipoint", &idx)) {
|
||||||
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT;
|
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT;
|
||||||
if (argv_find(argv, argc, "delay-reflood", &idx))
|
if (argv_find(argv, argc, "delay-reflood", &idx))
|
||||||
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood = true;
|
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_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOPOINT;
|
||||||
if (argv_find(argv, argc, "dmvpn", &idx))
|
if (argv_find(argv, argc, "dmvpn", &idx))
|
||||||
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1;
|
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 (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_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;
|
return CMD_SUCCESS;
|
||||||
|
|
||||||
SET_IF_PARAM(IF_DEF_PARAMS(ifp), type);
|
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->type = IF_DEF_PARAMS(ifp)->type;
|
||||||
oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
|
oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
|
||||||
oi->p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood;
|
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
|
* The OSPF interface only needs to be flapped if the network
|
||||||
* type or DMVPN parameter changes.
|
* type or DMVPN parameter changes.
|
||||||
*/
|
*/
|
||||||
if (IF_DEF_PARAMS(ifp)->type != old_type ||
|
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) {
|
if (oi->state > ISM_Down) {
|
||||||
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
|
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
|
||||||
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp);
|
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)->ptp_dmvpn = 0;
|
||||||
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
|
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
|
||||||
OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
|
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)
|
if (IF_DEF_PARAMS(ifp)->type == old_type)
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
@ -12225,6 +12150,10 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
|
|||||||
OSPF_IFTYPE_POINTOMULTIPOINT &&
|
OSPF_IFTYPE_POINTOMULTIPOINT &&
|
||||||
params->p2mp_delay_reflood)
|
params->p2mp_delay_reflood)
|
||||||
vty_out(vty, " 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)
|
if (params != IF_DEF_PARAMS(ifp) && rn)
|
||||||
vty_out(vty, " %pI4",
|
vty_out(vty, " %pI4",
|
||||||
&rn->p.u.prefix4);
|
&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, &ospf_auto_cost_reference_bandwidth_cmd);
|
||||||
install_element(OSPF_NODE, &no_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_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 */
|
/* write multiplier commands */
|
||||||
install_element(OSPF_NODE, &ospf_write_multiplier_cmd);
|
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->type = IF_DEF_PARAMS(co->ifp)->type;
|
||||||
oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
|
oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
|
||||||
oi->p2mp_delay_reflood = IF_DEF_PARAMS(co->ifp)->p2mp_delay_reflood;
|
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. */
|
/* Add pseudo neighbor. */
|
||||||
ospf_nbr_self_reset(oi, oi->ospf->router_id);
|
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 route_node *rn;
|
||||||
struct prefix p;
|
struct prefix p;
|
||||||
|
|
||||||
if (oi->type != OSPF_IFTYPE_NBMA)
|
if (!OSPF_IF_NON_BROADCAST(oi))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (nbr_nbma->nbr != NULL)
|
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 route_node *rn;
|
||||||
struct prefix_ipv4 p;
|
struct prefix_ipv4 p;
|
||||||
|
|
||||||
if (oi->type != OSPF_IFTYPE_NBMA)
|
if (!OSPF_IF_NON_BROADCAST(oi))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn))
|
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;
|
rn->info = nbr_nbma;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
|
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)) {
|
if (prefix_match(oi->address, (struct prefix *)&p)) {
|
||||||
ospf_nbr_nbma_add(nbr_nbma, oi);
|
ospf_nbr_nbma_add(nbr_nbma, oi);
|
||||||
break;
|
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