mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 08:50:16 +00:00
Merge pull request #16128 from LabNConsulting/aceelindem/ospf-ls-retrans-improve
ospfd: Improve OSPF neighbor retransmission list granularity and pacing
This commit is contained in:
commit
87c2f100e1
69
doc/developer/ospf-ls-retrans.rst
Normal file
69
doc/developer/ospf-ls-retrans.rst
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
OSPF Neighor Retransmission List
|
||||||
|
================================
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
OSPF neighbor link-state retransmission lists are implemented using
|
||||||
|
both a sparse Link State Database (LSDB) and a doubly-linked list.
|
||||||
|
Rather than previous per-neighbor periodic timer, a per-neighbor
|
||||||
|
timer is set to the expiration time of the next scheduled LSA
|
||||||
|
retransmission.
|
||||||
|
|
||||||
|
Sparse Link State Database (LSDB)
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
When an explicit or implied acknowledgment is recieved from a
|
||||||
|
neighbor in 2-way state or higher, the acknowledge LSA must be
|
||||||
|
removed from the neighbor's link state retransmission list. In order
|
||||||
|
to do this efficiently, a sparse LSDB is utilized. LSDB entries also
|
||||||
|
include a pointer to the corresponding list entry so that it may be
|
||||||
|
efficiently removed from the doubly-linked list.
|
||||||
|
|
||||||
|
The sparse LSDB is implemented using the OSPF functions is
|
||||||
|
ospf_lsdb.[c,h]. OSPF LSDBs are implemented as an array of route
|
||||||
|
tables (lib/table.[c,h]). What is unique of the LS Retransmission
|
||||||
|
list LSDB is that each entry also has a pointer into the doubly-linked
|
||||||
|
list to facilitate fast deletions.
|
||||||
|
|
||||||
|
Doubly-Linked List
|
||||||
|
------------------
|
||||||
|
|
||||||
|
In addition to the sparse LSDB, LSAs on a neighbor LS retransmission
|
||||||
|
list are also maintained in a linked-list order chronologically
|
||||||
|
with the LSA scheduled for the next retransmission at the head of
|
||||||
|
the list.
|
||||||
|
|
||||||
|
The doubly-link list is implemented using the dlist macros in
|
||||||
|
lib/typesafe.h.
|
||||||
|
|
||||||
|
LSA LS Retransmission List Addition
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
When an LSA is added to a neighbor retransmission list, it is
|
||||||
|
added to both the sparse LSDB and the doubly-linked list with a pointer
|
||||||
|
in the LSDB route-table node to the list entry. The LSA is added to
|
||||||
|
the tail of the list with the expiration time set to the current time
|
||||||
|
with the retransmission interval added. If the neighbor retransmission
|
||||||
|
timer is not set, it is set to expire at the time of the newly added
|
||||||
|
LSA.
|
||||||
|
|
||||||
|
LSA LS Retransmission List Deletion
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
When an LSA is deleted from a neighbor retransmission list, it is
|
||||||
|
deleted from eboth the sparse LSDB and the doubly-linked list with the
|
||||||
|
pointer the LSDB route-table node used to efficiently delete the entry
|
||||||
|
from the list. If the LSA at the head of the list was removed, then
|
||||||
|
the neighbor retransmission timer is reset to the expiration of the
|
||||||
|
LSA at the head of the list or canceled if the list is empty.
|
||||||
|
|
||||||
|
Neighbor LS Retransmission List Expiration
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
When the neighbor retransmission timer expires, the LSA at the top of
|
||||||
|
list and any in a configured window (e.g., 50 milliseconds) are
|
||||||
|
retransmitted. The LSAs that have been retransmitted are removed from
|
||||||
|
the list and readded to the tail of the list with a new expiration time
|
||||||
|
which is retransmit-interval seconds in the future.
|
||||||
|
|
@ -8,6 +8,7 @@ OSPFD
|
|||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
ospf-api
|
ospf-api
|
||||||
|
ospf-ls-retrans
|
||||||
ospf-sr
|
ospf-sr
|
||||||
cspf
|
cspf
|
||||||
|
|
||||||
|
@ -738,7 +738,17 @@ Interfaces
|
|||||||
retransmitting Database Description and Link State Request packets. The
|
retransmitting Database Description and Link State Request packets. The
|
||||||
default value is 5 seconds.
|
default value is 5 seconds.
|
||||||
|
|
||||||
.. clicmd:: ip ospf transmit-delay (1-65535) [A.B.C.D]
|
.. clicmd:: ip ospf retransmit-window (20-1000)
|
||||||
|
|
||||||
|
|
||||||
|
Set number of milliseconds in the window for neighbor LSA retransmission.
|
||||||
|
When a neighbor Link State (LS) retransmission timer expires, LSAs scheduled
|
||||||
|
to be retransmitted within the number of milliseconds configured are
|
||||||
|
retransmitted to the neighbor. Any expiring after the window will be
|
||||||
|
retransmitted the next time the neighbor LS retransmission timer expires.
|
||||||
|
The default is 50 milliseconds.
|
||||||
|
|
||||||
|
.. clicmd:: ip ospf transmit-delay (1-65535) [A.B.C.D]
|
||||||
|
|
||||||
|
|
||||||
Set number of seconds for InfTransDelay value. LSAs' age should be
|
Set number of seconds for InfTransDelay value. LSAs' age should be
|
||||||
|
@ -58,6 +58,7 @@ extern "C" {
|
|||||||
#define OSPF_HELLO_DELAY_DEFAULT 10
|
#define OSPF_HELLO_DELAY_DEFAULT 10
|
||||||
#define OSPF_ROUTER_PRIORITY_DEFAULT 1
|
#define OSPF_ROUTER_PRIORITY_DEFAULT 1
|
||||||
#define OSPF_RETRANSMIT_INTERVAL_DEFAULT 5
|
#define OSPF_RETRANSMIT_INTERVAL_DEFAULT 5
|
||||||
|
#define OSPF_RETRANSMIT_WINDOW_DEFAULT 50 /* milliseconds */
|
||||||
#define OSPF_TRANSMIT_DELAY_DEFAULT 1
|
#define OSPF_TRANSMIT_DELAY_DEFAULT 1
|
||||||
#define OSPF_DEFAULT_BANDWIDTH 10000 /* Mbps */
|
#define OSPF_DEFAULT_BANDWIDTH 10000 /* Mbps */
|
||||||
|
|
||||||
|
@ -1015,7 +1015,7 @@ void ospf_ls_request_delete(struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
|
|||||||
ospf_lsdb_delete(&nbr->ls_req, lsa);
|
ospf_lsdb_delete(&nbr->ls_req, lsa);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove all LSA from neighbor's ls-requenst list. */
|
/* Remove all LSAs from neighbor's ls-request list. */
|
||||||
void ospf_ls_request_delete_all(struct ospf_neighbor *nbr)
|
void ospf_ls_request_delete_all(struct ospf_neighbor *nbr)
|
||||||
{
|
{
|
||||||
ospf_lsa_unlock(&nbr->ls_req_last);
|
ospf_lsa_unlock(&nbr->ls_req_last);
|
||||||
@ -1061,58 +1061,114 @@ int ospf_ls_retransmit_isempty(struct ospf_neighbor *nbr)
|
|||||||
/* Add LSA to be retransmitted to neighbor's ls-retransmit list. */
|
/* Add LSA to be retransmitted to neighbor's ls-retransmit list. */
|
||||||
void ospf_ls_retransmit_add(struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
|
void ospf_ls_retransmit_add(struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
struct ospf_lsa *old;
|
struct ospf_lsdb_linked_node *ls_rxmt_node;
|
||||||
|
struct ospf_lsa_list_entry *ls_rxmt_list_entry;
|
||||||
|
struct ospf_lsa *old = NULL;
|
||||||
|
bool rxmt_head_replaced = false;
|
||||||
|
|
||||||
old = ospf_ls_retransmit_lookup(nbr, lsa);
|
ls_rxmt_node = ospf_lsdb_linked_lookup(&nbr->ls_rxmt, lsa);
|
||||||
|
if (ls_rxmt_node)
|
||||||
|
old = ls_rxmt_node->info;
|
||||||
|
|
||||||
if (ospf_lsa_more_recent(old, lsa) < 0) {
|
if (ospf_lsa_more_recent(old, lsa) < 0) {
|
||||||
if (old) {
|
if (old) {
|
||||||
old->retransmit_counter--;
|
old->retransmit_counter--;
|
||||||
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
|
if (ls_rxmt_node->lsa_list_entry ==
|
||||||
zlog_debug("RXmtL(%lu)--, NBR(%pI4(%s)), LSA[%s]",
|
ospf_lsa_list_first(&nbr->ls_rxmt_list))
|
||||||
ospf_ls_retransmit_count(nbr),
|
rxmt_head_replaced = true;
|
||||||
&nbr->router_id,
|
ospf_lsa_list_del(&nbr->ls_rxmt_list,
|
||||||
ospf_get_name(nbr->oi->ospf),
|
ls_rxmt_node->lsa_list_entry);
|
||||||
dump_lsa_key(old));
|
XFREE(MTYPE_OSPF_LSA_LIST, ls_rxmt_node->lsa_list_entry);
|
||||||
ospf_lsdb_delete(&nbr->ls_rxmt, old);
|
ospf_lsdb_delete(&nbr->ls_rxmt, old);
|
||||||
}
|
|
||||||
lsa->retransmit_counter++;
|
|
||||||
/*
|
|
||||||
* We cannot make use of the newly introduced callback function
|
|
||||||
* "lsdb->new_lsa_hook" to replace debug output below, just
|
|
||||||
* because
|
|
||||||
* it seems no simple and smart way to pass neighbor information
|
|
||||||
* to
|
|
||||||
* the common function "ospf_lsdb_add()" -- endo.
|
|
||||||
*/
|
|
||||||
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
|
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
|
||||||
zlog_debug("RXmtL(%lu)++, NBR(%pI4(%s)), LSA[%s]",
|
zlog_debug("RXmtL(%lu) NBR(%pI4(%s)) Old Delete LSA[%s] on Add",
|
||||||
ospf_ls_retransmit_count(nbr),
|
ospf_ls_retransmit_count(nbr),
|
||||||
&nbr->router_id,
|
&nbr->router_id,
|
||||||
ospf_get_name(nbr->oi->ospf),
|
ospf_get_name(nbr->oi->ospf),
|
||||||
dump_lsa_key(lsa));
|
dump_lsa_key(lsa));
|
||||||
|
ospf_lsa_unlock(&old);
|
||||||
|
}
|
||||||
|
lsa->retransmit_counter++;
|
||||||
|
ls_rxmt_list_entry = XCALLOC(MTYPE_OSPF_LSA_LIST,
|
||||||
|
sizeof(struct ospf_lsa_list_entry));
|
||||||
|
/*
|
||||||
|
* Set the LSA retransmission time for the neighbor;
|
||||||
|
*/
|
||||||
|
monotime(&ls_rxmt_list_entry->list_entry_time);
|
||||||
|
ls_rxmt_list_entry->list_entry_time.tv_sec += nbr->v_ls_rxmt;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the LSA to the neighbor retransmission list.
|
||||||
|
*/
|
||||||
|
ls_rxmt_list_entry->lsa = ospf_lsa_lock(lsa);
|
||||||
|
ospf_lsa_list_add_tail(&nbr->ls_rxmt_list, ls_rxmt_list_entry);
|
||||||
ospf_lsdb_add(&nbr->ls_rxmt, lsa);
|
ospf_lsdb_add(&nbr->ls_rxmt, lsa);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up the newly added node and set the list pointer.
|
||||||
|
*/
|
||||||
|
ls_rxmt_node = ospf_lsdb_linked_lookup(&nbr->ls_rxmt, lsa);
|
||||||
|
ls_rxmt_node->lsa_list_entry = ls_rxmt_list_entry;
|
||||||
|
|
||||||
|
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
|
||||||
|
zlog_debug("RXmtL(%lu) NBR(%pI4(%s)) Add LSA[%s] retrans at (%ld/%ld)",
|
||||||
|
ospf_ls_retransmit_count(nbr),
|
||||||
|
&nbr->router_id, ospf_get_name(nbr->oi->ospf),
|
||||||
|
dump_lsa_key(lsa),
|
||||||
|
(long)ls_rxmt_list_entry->list_entry_time
|
||||||
|
.tv_sec,
|
||||||
|
(long)ls_rxmt_list_entry->list_entry_time
|
||||||
|
.tv_usec);
|
||||||
|
/*
|
||||||
|
* Reset the neighbor LSA retransmission timer if isn't currently
|
||||||
|
* running or the LSA at the head of the list was updated.
|
||||||
|
*/
|
||||||
|
if (!nbr->t_ls_rxmt || rxmt_head_replaced)
|
||||||
|
ospf_ls_retransmit_set_timer(nbr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove LSA from neibghbor's ls-retransmit list. */
|
/* Remove LSA from neibghbor's ls-retransmit list. */
|
||||||
void ospf_ls_retransmit_delete(struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
|
void ospf_ls_retransmit_delete(struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
|
||||||
{
|
{
|
||||||
if (ospf_ls_retransmit_lookup(nbr, lsa)) {
|
struct ospf_lsdb_linked_node *ls_rxmt_node;
|
||||||
|
|
||||||
|
ls_rxmt_node = ospf_lsdb_linked_lookup(&nbr->ls_rxmt, lsa);
|
||||||
|
|
||||||
|
if (ls_rxmt_node) {
|
||||||
|
bool rxmt_timer_reset;
|
||||||
|
|
||||||
|
if (ls_rxmt_node->lsa_list_entry ==
|
||||||
|
ospf_lsa_list_first(&nbr->ls_rxmt_list))
|
||||||
|
rxmt_timer_reset = true;
|
||||||
|
else
|
||||||
|
rxmt_timer_reset = false;
|
||||||
|
|
||||||
lsa->retransmit_counter--;
|
lsa->retransmit_counter--;
|
||||||
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) /* -- endo. */
|
ospf_lsa_list_del(&nbr->ls_rxmt_list,
|
||||||
zlog_debug("RXmtL(%lu)--, NBR(%pI4(%s)), LSA[%s]",
|
ls_rxmt_node->lsa_list_entry);
|
||||||
ospf_ls_retransmit_count(nbr),
|
XFREE(MTYPE_OSPF_LSA_LIST, ls_rxmt_node->lsa_list_entry);
|
||||||
&nbr->router_id,
|
|
||||||
ospf_get_name(nbr->oi->ospf),
|
|
||||||
dump_lsa_key(lsa));
|
|
||||||
ospf_lsdb_delete(&nbr->ls_rxmt, lsa);
|
ospf_lsdb_delete(&nbr->ls_rxmt, lsa);
|
||||||
|
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
|
||||||
|
zlog_debug("RXmtL(%lu) NBR(%pI4(%s)) Delete LSA[%s]",
|
||||||
|
ospf_ls_retransmit_count(nbr),
|
||||||
|
&nbr->router_id, ospf_get_name(nbr->oi->ospf),
|
||||||
|
dump_lsa_key(lsa));
|
||||||
|
ospf_lsa_unlock(&lsa);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the LS retransmission entry at the head of the list was
|
||||||
|
* deleted, reset the timer.
|
||||||
|
*/
|
||||||
|
if (rxmt_timer_reset)
|
||||||
|
ospf_ls_retransmit_set_timer(nbr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear neighbor's ls-retransmit list. */
|
/* Clear neighbor's ls-retransmit list. */
|
||||||
void ospf_ls_retransmit_clear(struct ospf_neighbor *nbr)
|
void ospf_ls_retransmit_clear(struct ospf_neighbor *nbr)
|
||||||
{
|
{
|
||||||
|
struct ospf_lsa_list_entry *ls_rxmt_list_entry;
|
||||||
struct ospf_lsdb *lsdb;
|
struct ospf_lsdb *lsdb;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -1128,10 +1184,54 @@ void ospf_ls_retransmit_clear(struct ospf_neighbor *nbr)
|
|||||||
ospf_ls_retransmit_delete(nbr, lsa);
|
ospf_ls_retransmit_delete(nbr, lsa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frr_each_safe (ospf_lsa_list, &nbr->ls_rxmt_list, ls_rxmt_list_entry) {
|
||||||
|
ospf_lsa_list_del(&nbr->ls_rxmt_list, ls_rxmt_list_entry);
|
||||||
|
ospf_lsa_unlock(&ls_rxmt_list_entry->lsa);
|
||||||
|
XFREE(MTYPE_OSPF_LSA_LIST, ls_rxmt_list_entry);
|
||||||
|
}
|
||||||
|
|
||||||
ospf_lsa_unlock(&nbr->ls_req_last);
|
ospf_lsa_unlock(&nbr->ls_req_last);
|
||||||
nbr->ls_req_last = NULL;
|
nbr->ls_req_last = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the neighbor's ls-retransmit timer based on the next
|
||||||
|
* LSA retransmit time.
|
||||||
|
*/
|
||||||
|
void ospf_ls_retransmit_set_timer(struct ospf_neighbor *nbr)
|
||||||
|
{
|
||||||
|
struct ospf_lsa_list_entry *ls_rxmt_list_entry;
|
||||||
|
|
||||||
|
if (nbr->t_ls_rxmt)
|
||||||
|
EVENT_OFF(nbr->t_ls_rxmt);
|
||||||
|
|
||||||
|
ls_rxmt_list_entry = ospf_lsa_list_first(&nbr->ls_rxmt_list);
|
||||||
|
if (ls_rxmt_list_entry) {
|
||||||
|
struct timeval current_time, delay;
|
||||||
|
unsigned long delay_milliseconds;
|
||||||
|
|
||||||
|
monotime(¤t_time);
|
||||||
|
if (timercmp(¤t_time,
|
||||||
|
&ls_rxmt_list_entry->list_entry_time, >=))
|
||||||
|
delay_milliseconds = 10;
|
||||||
|
else {
|
||||||
|
timersub(&ls_rxmt_list_entry->list_entry_time,
|
||||||
|
¤t_time, &delay);
|
||||||
|
delay_milliseconds = (delay.tv_sec * 1000) +
|
||||||
|
(delay.tv_usec / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_add_timer_msec(master, ospf_ls_rxmt_timer, nbr,
|
||||||
|
delay_milliseconds, &nbr->t_ls_rxmt);
|
||||||
|
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
|
||||||
|
zlog_debug("RXmtL(%lu) NBR(%pI4(%s)) retrans timer set in %ld msecs - Head LSA(%s)",
|
||||||
|
ospf_ls_retransmit_count(nbr),
|
||||||
|
&nbr->router_id, ospf_get_name(nbr->oi->ospf),
|
||||||
|
delay_milliseconds,
|
||||||
|
dump_lsa_key(ls_rxmt_list_entry->lsa));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Lookup LSA from neighbor's ls-retransmit list. */
|
/* Lookup LSA from neighbor's ls-retransmit list. */
|
||||||
struct ospf_lsa *ospf_ls_retransmit_lookup(struct ospf_neighbor *nbr,
|
struct ospf_lsa *ospf_ls_retransmit_lookup(struct ospf_neighbor *nbr,
|
||||||
struct ospf_lsa *lsa)
|
struct ospf_lsa *lsa)
|
||||||
|
@ -7,6 +7,26 @@
|
|||||||
#ifndef _ZEBRA_OSPF_FLOOD_H
|
#ifndef _ZEBRA_OSPF_FLOOD_H
|
||||||
#define _ZEBRA_OSPF_FLOOD_H
|
#define _ZEBRA_OSPF_FLOOD_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OSPF Temporal LSA List
|
||||||
|
*/
|
||||||
|
PREDECL_DLIST(ospf_lsa_list);
|
||||||
|
|
||||||
|
struct ospf_lsa_list_entry {
|
||||||
|
/* Linkage for LSA List */
|
||||||
|
struct ospf_lsa_list_item list_linkage;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Time associated with the list entry. For example, for a neigbhor
|
||||||
|
* link retransmission list, this is the retransmission time.
|
||||||
|
*/
|
||||||
|
struct timeval list_entry_time;
|
||||||
|
|
||||||
|
struct ospf_lsa *lsa;
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_DLIST(ospf_lsa_list, struct ospf_lsa_list_entry, list_linkage);
|
||||||
|
|
||||||
extern int ospf_flood(struct ospf *, struct ospf_neighbor *, struct ospf_lsa *,
|
extern int ospf_flood(struct ospf *, struct ospf_neighbor *, struct ospf_lsa *,
|
||||||
struct ospf_lsa *);
|
struct ospf_lsa *);
|
||||||
extern int ospf_flood_through(struct ospf *, struct ospf_neighbor *,
|
extern int ospf_flood_through(struct ospf *, struct ospf_neighbor *,
|
||||||
@ -36,6 +56,8 @@ extern void ospf_ls_retransmit_add(struct ospf_neighbor *, struct ospf_lsa *);
|
|||||||
extern void ospf_ls_retransmit_delete(struct ospf_neighbor *,
|
extern void ospf_ls_retransmit_delete(struct ospf_neighbor *,
|
||||||
struct ospf_lsa *);
|
struct ospf_lsa *);
|
||||||
extern void ospf_ls_retransmit_clear(struct ospf_neighbor *);
|
extern void ospf_ls_retransmit_clear(struct ospf_neighbor *);
|
||||||
|
extern void ospf_ls_retransmit_set_timer(struct ospf_neighbor *nbr);
|
||||||
|
|
||||||
extern struct ospf_lsa *ospf_ls_retransmit_lookup(struct ospf_neighbor *,
|
extern struct ospf_lsa *ospf_ls_retransmit_lookup(struct ospf_neighbor *,
|
||||||
struct ospf_lsa *);
|
struct ospf_lsa *);
|
||||||
extern void ospf_ls_retransmit_delete_nbr_area(struct ospf_area *,
|
extern void ospf_ls_retransmit_delete_nbr_area(struct ospf_area *,
|
||||||
|
@ -542,6 +542,7 @@ static struct ospf_if_params *ospf_new_if_params(void)
|
|||||||
UNSET_IF_PARAM(oip, output_cost_cmd);
|
UNSET_IF_PARAM(oip, output_cost_cmd);
|
||||||
UNSET_IF_PARAM(oip, transmit_delay);
|
UNSET_IF_PARAM(oip, transmit_delay);
|
||||||
UNSET_IF_PARAM(oip, retransmit_interval);
|
UNSET_IF_PARAM(oip, retransmit_interval);
|
||||||
|
UNSET_IF_PARAM(oip, retransmit_window);
|
||||||
UNSET_IF_PARAM(oip, passive_interface);
|
UNSET_IF_PARAM(oip, passive_interface);
|
||||||
UNSET_IF_PARAM(oip, v_hello);
|
UNSET_IF_PARAM(oip, v_hello);
|
||||||
UNSET_IF_PARAM(oip, fast_hello);
|
UNSET_IF_PARAM(oip, fast_hello);
|
||||||
@ -599,6 +600,7 @@ void ospf_free_if_params(struct interface *ifp, struct in_addr addr)
|
|||||||
if (!OSPF_IF_PARAM_CONFIGURED(oip, output_cost_cmd) &&
|
if (!OSPF_IF_PARAM_CONFIGURED(oip, output_cost_cmd) &&
|
||||||
!OSPF_IF_PARAM_CONFIGURED(oip, transmit_delay) &&
|
!OSPF_IF_PARAM_CONFIGURED(oip, transmit_delay) &&
|
||||||
!OSPF_IF_PARAM_CONFIGURED(oip, retransmit_interval) &&
|
!OSPF_IF_PARAM_CONFIGURED(oip, retransmit_interval) &&
|
||||||
|
!OSPF_IF_PARAM_CONFIGURED(oip, retransmit_window) &&
|
||||||
!OSPF_IF_PARAM_CONFIGURED(oip, passive_interface) &&
|
!OSPF_IF_PARAM_CONFIGURED(oip, passive_interface) &&
|
||||||
!OSPF_IF_PARAM_CONFIGURED(oip, v_hello) &&
|
!OSPF_IF_PARAM_CONFIGURED(oip, v_hello) &&
|
||||||
!OSPF_IF_PARAM_CONFIGURED(oip, fast_hello) &&
|
!OSPF_IF_PARAM_CONFIGURED(oip, fast_hello) &&
|
||||||
@ -695,6 +697,9 @@ int ospf_if_new_hook(struct interface *ifp)
|
|||||||
IF_DEF_PARAMS(ifp)->retransmit_interval =
|
IF_DEF_PARAMS(ifp)->retransmit_interval =
|
||||||
OSPF_RETRANSMIT_INTERVAL_DEFAULT;
|
OSPF_RETRANSMIT_INTERVAL_DEFAULT;
|
||||||
|
|
||||||
|
SET_IF_PARAM(IF_DEF_PARAMS(ifp), retransmit_window);
|
||||||
|
IF_DEF_PARAMS(ifp)->retransmit_window = OSPF_RETRANSMIT_WINDOW_DEFAULT;
|
||||||
|
|
||||||
SET_IF_PARAM(IF_DEF_PARAMS(ifp), priority);
|
SET_IF_PARAM(IF_DEF_PARAMS(ifp), priority);
|
||||||
IF_DEF_PARAMS(ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT;
|
IF_DEF_PARAMS(ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT;
|
||||||
|
|
||||||
|
@ -47,6 +47,8 @@ struct ospf_if_params {
|
|||||||
output_cost_cmd); /* Command Interface Output Cost */
|
output_cost_cmd); /* Command Interface Output Cost */
|
||||||
DECLARE_IF_PARAM(uint32_t,
|
DECLARE_IF_PARAM(uint32_t,
|
||||||
retransmit_interval); /* Retransmission Interval */
|
retransmit_interval); /* Retransmission Interval */
|
||||||
|
DECLARE_IF_PARAM(uint32_t,
|
||||||
|
retransmit_window); /* Retransmission Window */
|
||||||
DECLARE_IF_PARAM(uint8_t, passive_interface); /* OSPF Interface is
|
DECLARE_IF_PARAM(uint8_t, passive_interface); /* OSPF Interface is
|
||||||
passive: no sending or
|
passive: no sending or
|
||||||
receiving (no need to
|
receiving (no need to
|
||||||
@ -296,6 +298,7 @@ struct ospf_interface {
|
|||||||
uint32_t ls_ack_out; /* LS Ack message output count. */
|
uint32_t ls_ack_out; /* LS Ack message output count. */
|
||||||
uint32_t discarded; /* discarded input count by error. */
|
uint32_t discarded; /* discarded input count by error. */
|
||||||
uint32_t state_change; /* Number of status change. */
|
uint32_t state_change; /* Number of status change. */
|
||||||
|
uint32_t ls_rxmt_lsa; /* Number of LSAs retransmitted. */
|
||||||
|
|
||||||
uint32_t full_nbrs;
|
uint32_t full_nbrs;
|
||||||
|
|
||||||
|
@ -34,6 +34,59 @@ void ospf_lsdb_init(struct ospf_lsdb *lsdb)
|
|||||||
lsdb->type[i].db = route_table_init();
|
lsdb->type[i].db = route_table_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct route_node *
|
||||||
|
ospf_lsdb_linked_node_create(route_table_delegate_t *delegate,
|
||||||
|
struct route_table *table)
|
||||||
|
{
|
||||||
|
struct ospf_lsdb_linked_node *node;
|
||||||
|
|
||||||
|
node = XCALLOC(MTYPE_OSPF_LSDB_NODE,
|
||||||
|
sizeof(struct ospf_lsdb_linked_node));
|
||||||
|
|
||||||
|
return (struct route_node *)node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ospf_lsdb_linked_node_destroy(route_table_delegate_t *delegate,
|
||||||
|
struct route_table *table,
|
||||||
|
struct route_node *node)
|
||||||
|
{
|
||||||
|
struct ospf_lsdb_linked_node *lsdb_linked_node =
|
||||||
|
(struct ospf_lsdb_linked_node *)node;
|
||||||
|
|
||||||
|
XFREE(MTYPE_OSPF_LSDB_NODE, lsdb_linked_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static route_table_delegate_t ospf_lsdb_linked_table_delegate = {
|
||||||
|
.create_node = ospf_lsdb_linked_node_create,
|
||||||
|
.destroy_node = ospf_lsdb_linked_node_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
void ospf_lsdb_linked_init(struct ospf_lsdb *lsdb)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
|
||||||
|
lsdb->type[i].db = route_table_init_with_delegate(
|
||||||
|
&ospf_lsdb_linked_table_delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ospf_lsdb_linked_node *ospf_lsdb_linked_lookup(struct ospf_lsdb *lsdb,
|
||||||
|
struct ospf_lsa *lsa)
|
||||||
|
{
|
||||||
|
struct ospf_lsdb_linked_node *lsdb_linked_node;
|
||||||
|
struct route_table *table;
|
||||||
|
struct prefix_ls lp;
|
||||||
|
|
||||||
|
table = lsdb->type[lsa->data->type].db;
|
||||||
|
ls_prefix_set(&lp, lsa);
|
||||||
|
lsdb_linked_node = (struct ospf_lsdb_linked_node *)
|
||||||
|
route_node_lookup(table, (struct prefix *)&lp);
|
||||||
|
if (lsdb_linked_node)
|
||||||
|
route_unlock_node((struct route_node *)lsdb_linked_node);
|
||||||
|
|
||||||
|
return lsdb_linked_node;
|
||||||
|
}
|
||||||
|
|
||||||
void ospf_lsdb_free(struct ospf_lsdb *lsdb)
|
void ospf_lsdb_free(struct ospf_lsdb *lsdb)
|
||||||
{
|
{
|
||||||
ospf_lsdb_cleanup(lsdb);
|
ospf_lsdb_cleanup(lsdb);
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
#ifndef _ZEBRA_OSPF_LSDB_H
|
#ifndef _ZEBRA_OSPF_LSDB_H
|
||||||
#define _ZEBRA_OSPF_LSDB_H
|
#define _ZEBRA_OSPF_LSDB_H
|
||||||
|
|
||||||
|
#include "prefix.h"
|
||||||
|
#include "table.h"
|
||||||
|
|
||||||
/* OSPF LSDB structure. */
|
/* OSPF LSDB structure. */
|
||||||
struct ospf_lsdb {
|
struct ospf_lsdb {
|
||||||
struct {
|
struct {
|
||||||
@ -43,9 +46,29 @@ struct ospf_lsdb {
|
|||||||
#define AREA_LSDB(A,T) ((A)->lsdb->type[(T)].db)
|
#define AREA_LSDB(A,T) ((A)->lsdb->type[(T)].db)
|
||||||
#define AS_LSDB(O,T) ((O)->lsdb->type[(T)].db)
|
#define AS_LSDB(O,T) ((O)->lsdb->type[(T)].db)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Alternate route node structure for LSDB nodes linked to
|
||||||
|
* list elements.
|
||||||
|
*/
|
||||||
|
struct ospf_lsdb_linked_node {
|
||||||
|
/*
|
||||||
|
* Caution these must be the very first fields
|
||||||
|
*/
|
||||||
|
ROUTE_NODE_FIELDS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List entry on an LSA list, e.g., a neighbor
|
||||||
|
* retransmission list.
|
||||||
|
*/
|
||||||
|
struct ospf_lsa_list_entry *lsa_list_entry;
|
||||||
|
};
|
||||||
|
|
||||||
/* OSPF LSDB related functions. */
|
/* OSPF LSDB related functions. */
|
||||||
extern struct ospf_lsdb *ospf_lsdb_new(void);
|
extern struct ospf_lsdb *ospf_lsdb_new(void);
|
||||||
extern void ospf_lsdb_init(struct ospf_lsdb *);
|
extern void ospf_lsdb_init(struct ospf_lsdb *);
|
||||||
|
extern void ospf_lsdb_linked_init(struct ospf_lsdb *lsdb);
|
||||||
|
extern struct ospf_lsdb_linked_node *
|
||||||
|
ospf_lsdb_linked_lookup(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa);
|
||||||
extern void ospf_lsdb_free(struct ospf_lsdb *);
|
extern void ospf_lsdb_free(struct ospf_lsdb *);
|
||||||
extern void ospf_lsdb_cleanup(struct ospf_lsdb *);
|
extern void ospf_lsdb_cleanup(struct ospf_lsdb *);
|
||||||
extern void ls_prefix_set(struct prefix_ls *lp, struct ospf_lsa *lsa);
|
extern void ls_prefix_set(struct prefix_ls *lp, struct ospf_lsa *lsa);
|
||||||
|
@ -45,3 +45,5 @@ DEFINE_MTYPE(OSPFD, OSPF_GR_HELPER, "OSPF Graceful Restart Helper");
|
|||||||
DEFINE_MTYPE(OSPFD, OSPF_EXTERNAL_RT_AGGR, "OSPF External Route Summarisation");
|
DEFINE_MTYPE(OSPFD, OSPF_EXTERNAL_RT_AGGR, "OSPF External Route Summarisation");
|
||||||
DEFINE_MTYPE(OSPFD, OSPF_P_SPACE, "OSPF TI-LFA P-Space");
|
DEFINE_MTYPE(OSPFD, OSPF_P_SPACE, "OSPF TI-LFA P-Space");
|
||||||
DEFINE_MTYPE(OSPFD, OSPF_Q_SPACE, "OSPF TI-LFA Q-Space");
|
DEFINE_MTYPE(OSPFD, OSPF_Q_SPACE, "OSPF TI-LFA Q-Space");
|
||||||
|
DEFINE_MTYPE(OSPFD, OSPF_LSA_LIST, "OSPF LSA List");
|
||||||
|
DEFINE_MTYPE(OSPFD, OSPF_LSDB_NODE, "OSPF LSDB Linked Node");
|
||||||
|
@ -44,5 +44,7 @@ DECLARE_MTYPE(OSPF_GR_HELPER);
|
|||||||
DECLARE_MTYPE(OSPF_EXTERNAL_RT_AGGR);
|
DECLARE_MTYPE(OSPF_EXTERNAL_RT_AGGR);
|
||||||
DECLARE_MTYPE(OSPF_P_SPACE);
|
DECLARE_MTYPE(OSPF_P_SPACE);
|
||||||
DECLARE_MTYPE(OSPF_Q_SPACE);
|
DECLARE_MTYPE(OSPF_Q_SPACE);
|
||||||
|
DECLARE_MTYPE(OSPF_LSA_LIST);
|
||||||
|
DECLARE_MTYPE(OSPF_LSDB_NODE);
|
||||||
|
|
||||||
#endif /* _QUAGGA_OSPF_MEMORY_H */
|
#endif /* _QUAGGA_OSPF_MEMORY_H */
|
||||||
|
@ -68,7 +68,7 @@ struct ospf_neighbor *ospf_nbr_new(struct ospf_interface *oi)
|
|||||||
nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait);
|
nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait);
|
||||||
nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval);
|
nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval);
|
||||||
nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval);
|
nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval);
|
||||||
nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval);
|
nbr->v_ls_rxmt = OSPF_IF_PARAM(oi, retransmit_interval);
|
||||||
nbr->priority = -1;
|
nbr->priority = -1;
|
||||||
|
|
||||||
/* DD flags. */
|
/* DD flags. */
|
||||||
@ -80,8 +80,10 @@ struct ospf_neighbor *ospf_nbr_new(struct ospf_interface *oi)
|
|||||||
nbr->nbr_nbma = NULL;
|
nbr->nbr_nbma = NULL;
|
||||||
|
|
||||||
ospf_lsdb_init(&nbr->db_sum);
|
ospf_lsdb_init(&nbr->db_sum);
|
||||||
ospf_lsdb_init(&nbr->ls_rxmt);
|
|
||||||
|
ospf_lsdb_linked_init(&nbr->ls_rxmt);
|
||||||
ospf_lsdb_init(&nbr->ls_req);
|
ospf_lsdb_init(&nbr->ls_req);
|
||||||
|
ospf_lsa_list_init(&nbr->ls_rxmt_list);
|
||||||
|
|
||||||
nbr->crypt_seqnum = 0;
|
nbr->crypt_seqnum = 0;
|
||||||
|
|
||||||
@ -128,7 +130,7 @@ void ospf_nbr_free(struct ospf_neighbor *nbr)
|
|||||||
EVENT_OFF(nbr->t_inactivity);
|
EVENT_OFF(nbr->t_inactivity);
|
||||||
EVENT_OFF(nbr->t_db_desc);
|
EVENT_OFF(nbr->t_db_desc);
|
||||||
EVENT_OFF(nbr->t_ls_req);
|
EVENT_OFF(nbr->t_ls_req);
|
||||||
EVENT_OFF(nbr->t_ls_upd);
|
EVENT_OFF(nbr->t_ls_rxmt);
|
||||||
|
|
||||||
/* Cancel all events. */ /* Thread lookup cost would be negligible. */
|
/* Cancel all events. */ /* Thread lookup cost would be negligible. */
|
||||||
event_cancel_event(master, nbr);
|
event_cancel_event(master, nbr);
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <ospfd/ospf_gr.h>
|
#include <ospfd/ospf_gr.h>
|
||||||
#include <ospfd/ospf_packet.h>
|
#include <ospfd/ospf_packet.h>
|
||||||
|
#include <ospfd/ospf_flood.h>
|
||||||
|
|
||||||
/* Neighbor Data Structure */
|
/* Neighbor Data Structure */
|
||||||
struct ospf_neighbor {
|
struct ospf_neighbor {
|
||||||
@ -44,6 +45,7 @@ struct ospf_neighbor {
|
|||||||
|
|
||||||
/* LSA data. */
|
/* LSA data. */
|
||||||
struct ospf_lsdb ls_rxmt;
|
struct ospf_lsdb ls_rxmt;
|
||||||
|
struct ospf_lsa_list_head ls_rxmt_list;
|
||||||
struct ospf_lsdb db_sum;
|
struct ospf_lsdb db_sum;
|
||||||
struct ospf_lsdb ls_req;
|
struct ospf_lsdb ls_req;
|
||||||
struct ospf_lsa *ls_req_last;
|
struct ospf_lsa *ls_req_last;
|
||||||
@ -54,13 +56,13 @@ struct ospf_neighbor {
|
|||||||
uint32_t v_inactivity;
|
uint32_t v_inactivity;
|
||||||
uint32_t v_db_desc;
|
uint32_t v_db_desc;
|
||||||
uint32_t v_ls_req;
|
uint32_t v_ls_req;
|
||||||
uint32_t v_ls_upd;
|
uint32_t v_ls_rxmt;
|
||||||
|
|
||||||
/* Threads. */
|
/* Threads. */
|
||||||
struct event *t_inactivity;
|
struct event *t_inactivity;
|
||||||
struct event *t_db_desc;
|
struct event *t_db_desc;
|
||||||
struct event *t_ls_req;
|
struct event *t_ls_req;
|
||||||
struct event *t_ls_upd;
|
struct event *t_ls_rxmt;
|
||||||
struct event *t_hello_reply;
|
struct event *t_hello_reply;
|
||||||
|
|
||||||
/* NBMA configured neighbour */
|
/* NBMA configured neighbour */
|
||||||
@ -71,6 +73,7 @@ struct ospf_neighbor {
|
|||||||
struct timeval ts_last_regress; /* last regressive NSM change */
|
struct timeval ts_last_regress; /* last regressive NSM change */
|
||||||
const char *last_regress_str; /* Event which last regressed NSM */
|
const char *last_regress_str; /* Event which last regressed NSM */
|
||||||
uint32_t state_change; /* NSM state change counter */
|
uint32_t state_change; /* NSM state change counter */
|
||||||
|
uint32_t ls_rxmt_lsa; /* Number of LSAs retransmited. */
|
||||||
|
|
||||||
/* BFD information */
|
/* BFD information */
|
||||||
struct bfd_session_params *bfd_session;
|
struct bfd_session_params *bfd_session;
|
||||||
|
@ -112,18 +112,16 @@ static void nsm_timer_set(struct ospf_neighbor *nbr)
|
|||||||
case NSM_Init:
|
case NSM_Init:
|
||||||
case NSM_TwoWay:
|
case NSM_TwoWay:
|
||||||
EVENT_OFF(nbr->t_db_desc);
|
EVENT_OFF(nbr->t_db_desc);
|
||||||
EVENT_OFF(nbr->t_ls_upd);
|
EVENT_OFF(nbr->t_ls_rxmt);
|
||||||
EVENT_OFF(nbr->t_ls_req);
|
EVENT_OFF(nbr->t_ls_req);
|
||||||
break;
|
break;
|
||||||
case NSM_ExStart:
|
case NSM_ExStart:
|
||||||
OSPF_NSM_TIMER_ON(nbr->t_db_desc, ospf_db_desc_timer,
|
OSPF_NSM_TIMER_ON(nbr->t_db_desc, ospf_db_desc_timer,
|
||||||
nbr->v_db_desc);
|
nbr->v_db_desc);
|
||||||
EVENT_OFF(nbr->t_ls_upd);
|
EVENT_OFF(nbr->t_ls_rxmt);
|
||||||
EVENT_OFF(nbr->t_ls_req);
|
EVENT_OFF(nbr->t_ls_req);
|
||||||
break;
|
break;
|
||||||
case NSM_Exchange:
|
case NSM_Exchange:
|
||||||
OSPF_NSM_TIMER_ON(nbr->t_ls_upd, ospf_ls_upd_timer,
|
|
||||||
nbr->v_ls_upd);
|
|
||||||
if (!IS_SET_DD_MS(nbr->dd_flags))
|
if (!IS_SET_DD_MS(nbr->dd_flags))
|
||||||
EVENT_OFF(nbr->t_db_desc);
|
EVENT_OFF(nbr->t_db_desc);
|
||||||
break;
|
break;
|
||||||
|
@ -292,54 +292,66 @@ void ospf_ls_req_event(struct ospf_neighbor *nbr)
|
|||||||
event_add_event(master, ospf_ls_req_timer, nbr, 0, &nbr->t_ls_req);
|
event_add_event(master, ospf_ls_req_timer, nbr, 0, &nbr->t_ls_req);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cyclic timer function. Fist registered in ospf_nbr_new () in
|
/*
|
||||||
ospf_neighbor.c */
|
* OSPF neighbor link state retransmission timer handler. Unicast
|
||||||
void ospf_ls_upd_timer(struct event *thread)
|
* unacknowledged LSAs to the neigbhors.
|
||||||
|
*/
|
||||||
|
void ospf_ls_rxmt_timer(struct event *thread)
|
||||||
{
|
{
|
||||||
struct ospf_neighbor *nbr;
|
struct ospf_neighbor *nbr;
|
||||||
|
int retransmit_interval, retransmit_window, rxmt_lsa_count = 0;
|
||||||
|
|
||||||
nbr = EVENT_ARG(thread);
|
nbr = EVENT_ARG(thread);
|
||||||
nbr->t_ls_upd = NULL;
|
nbr->t_ls_rxmt = NULL;
|
||||||
|
retransmit_interval = nbr->v_ls_rxmt;
|
||||||
|
retransmit_window = OSPF_IF_PARAM(nbr->oi, retransmit_window);
|
||||||
|
|
||||||
/* Send Link State Update. */
|
/* Send Link State Update. */
|
||||||
if (ospf_ls_retransmit_count(nbr) > 0) {
|
if (ospf_ls_retransmit_count(nbr) > 0) {
|
||||||
|
struct ospf_lsa_list_entry *ls_rxmt_list_entry;
|
||||||
|
struct timeval current_time, latest_rxmt_time, next_rxmt_time;
|
||||||
|
struct timeval rxmt_interval = { retransmit_interval, 0 };
|
||||||
|
struct timeval rxmt_window;
|
||||||
struct list *update;
|
struct list *update;
|
||||||
struct ospf_lsdb *lsdb;
|
|
||||||
int i;
|
|
||||||
int retransmit_interval;
|
|
||||||
|
|
||||||
retransmit_interval =
|
/*
|
||||||
OSPF_IF_PARAM(nbr->oi, retransmit_interval);
|
* Set the retransmission window based on the configured value
|
||||||
|
* in milliseconds.
|
||||||
|
*/
|
||||||
|
rxmt_window.tv_sec = retransmit_window / 1000;
|
||||||
|
rxmt_window.tv_usec = (retransmit_window % 1000) * 1000;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the latest retransmit time for LSAs transmited in
|
||||||
|
* this timer pass by adding the retransmission window to the
|
||||||
|
* current time. Calculate the next retransmission time by adding
|
||||||
|
* the retransmit interval to the current time.
|
||||||
|
*/
|
||||||
|
monotime(¤t_time);
|
||||||
|
timeradd(¤t_time, &rxmt_window, &latest_rxmt_time);
|
||||||
|
timeradd(¤t_time, &rxmt_interval, &next_rxmt_time);
|
||||||
|
|
||||||
lsdb = &nbr->ls_rxmt;
|
|
||||||
update = list_new();
|
update = list_new();
|
||||||
|
while ((ls_rxmt_list_entry =
|
||||||
|
ospf_lsa_list_first(&nbr->ls_rxmt_list))) {
|
||||||
|
if (timercmp(&ls_rxmt_list_entry->list_entry_time,
|
||||||
|
&latest_rxmt_time, >))
|
||||||
|
break;
|
||||||
|
|
||||||
for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) {
|
listnode_add(update, ls_rxmt_list_entry->lsa);
|
||||||
struct route_table *table = lsdb->type[i].db;
|
rxmt_lsa_count++;
|
||||||
struct route_node *rn;
|
|
||||||
|
|
||||||
for (rn = route_top(table); rn; rn = route_next(rn)) {
|
/*
|
||||||
struct ospf_lsa *lsa;
|
* Set the next retransmit time for the LSA and move it
|
||||||
|
* to the end of the neighbor's retransmission list.
|
||||||
if ((lsa = rn->info) != NULL) {
|
*/
|
||||||
/* Don't retransmit an LSA if we
|
ls_rxmt_list_entry->list_entry_time = next_rxmt_time;
|
||||||
received it within
|
ospf_lsa_list_del(&nbr->ls_rxmt_list,
|
||||||
the last RxmtInterval seconds - this
|
ls_rxmt_list_entry);
|
||||||
is to allow the
|
ospf_lsa_list_add_tail(&nbr->ls_rxmt_list,
|
||||||
neighbour a chance to acknowledge the
|
ls_rxmt_list_entry);
|
||||||
LSA as it may
|
nbr->ls_rxmt_lsa++;
|
||||||
have ben just received before the
|
nbr->oi->ls_rxmt_lsa++;
|
||||||
retransmit timer
|
|
||||||
fired. This is a small tweak to what
|
|
||||||
is in the RFC,
|
|
||||||
but it will cut out out a lot of
|
|
||||||
retransmit traffic
|
|
||||||
- MAG */
|
|
||||||
if (monotime_since(&lsa->tv_recv, NULL)
|
|
||||||
>= retransmit_interval * 1000000LL)
|
|
||||||
listnode_add(update, rn->info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listcount(update) > 0)
|
if (listcount(update) > 0)
|
||||||
@ -348,8 +360,13 @@ void ospf_ls_upd_timer(struct event *thread)
|
|||||||
list_delete(&update);
|
list_delete(&update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_DEBUG_OSPF_EVENT)
|
||||||
|
zlog_debug("RXmtL(%lu) NBR(%pI4(%s)) timer event - sent %u LSAs",
|
||||||
|
ospf_ls_retransmit_count(nbr), &nbr->router_id,
|
||||||
|
ospf_get_name(nbr->oi->ospf), rxmt_lsa_count);
|
||||||
|
|
||||||
/* Set LS Update retransmission timer. */
|
/* Set LS Update retransmission timer. */
|
||||||
OSPF_NSM_TIMER_ON(nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
|
ospf_ls_retransmit_set_timer(nbr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ospf_ls_ack_timer(struct event *thread)
|
void ospf_ls_ack_timer(struct event *thread)
|
||||||
|
@ -140,7 +140,7 @@ extern void ospf_ls_ack_send_delayed(struct ospf_interface *);
|
|||||||
extern void ospf_ls_retransmit(struct ospf_interface *, struct ospf_lsa *);
|
extern void ospf_ls_retransmit(struct ospf_interface *, struct ospf_lsa *);
|
||||||
extern void ospf_ls_req_event(struct ospf_neighbor *);
|
extern void ospf_ls_req_event(struct ospf_neighbor *);
|
||||||
|
|
||||||
extern void ospf_ls_upd_timer(struct event *thread);
|
extern void ospf_ls_rxmt_timer(struct event *thread);
|
||||||
extern void ospf_ls_ack_timer(struct event *thread);
|
extern void ospf_ls_ack_timer(struct event *thread);
|
||||||
extern void ospf_poll_timer(struct event *thread);
|
extern void ospf_poll_timer(struct event *thread);
|
||||||
extern void ospf_hello_reply_timer(struct event *thread);
|
extern void ospf_hello_reply_timer(struct event *thread);
|
||||||
|
116
ospfd/ospf_vty.c
116
ospfd/ospf_vty.c
@ -815,6 +815,7 @@ struct ospf_vl_config_data {
|
|||||||
int del_keychain;
|
int del_keychain;
|
||||||
int hello_interval; /* Obvious what these are... */
|
int hello_interval; /* Obvious what these are... */
|
||||||
int retransmit_interval;
|
int retransmit_interval;
|
||||||
|
int retransmit_window;
|
||||||
int transmit_delay;
|
int transmit_delay;
|
||||||
int dead_interval;
|
int dead_interval;
|
||||||
};
|
};
|
||||||
@ -957,6 +958,12 @@ static int ospf_vl_set_timers(struct ospf_vl_data *vl_data,
|
|||||||
vl_config->retransmit_interval;
|
vl_config->retransmit_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vl_config->retransmit_window) {
|
||||||
|
SET_IF_PARAM(IF_DEF_PARAMS(ifp), retransmit_window);
|
||||||
|
IF_DEF_PARAMS(ifp)->retransmit_window =
|
||||||
|
vl_config->retransmit_window;
|
||||||
|
}
|
||||||
|
|
||||||
if (vl_config->transmit_delay) {
|
if (vl_config->transmit_delay) {
|
||||||
SET_IF_PARAM(IF_DEF_PARAMS(ifp), transmit_delay);
|
SET_IF_PARAM(IF_DEF_PARAMS(ifp), transmit_delay);
|
||||||
IF_DEF_PARAMS(ifp)->transmit_delay = vl_config->transmit_delay;
|
IF_DEF_PARAMS(ifp)->transmit_delay = vl_config->transmit_delay;
|
||||||
@ -1017,6 +1024,8 @@ static int ospf_vl_set(struct ospf *ospf, struct ospf_vl_config_data *vl_config)
|
|||||||
"Seconds\n" \
|
"Seconds\n" \
|
||||||
"Time between retransmitting lost link state advertisements\n" \
|
"Time between retransmitting lost link state advertisements\n" \
|
||||||
"Seconds\n" \
|
"Seconds\n" \
|
||||||
|
"Window for LSA retransmit - Retransmit LSAs expiring in this window\n" \
|
||||||
|
"Milliseconds\n" \
|
||||||
"Link state transmit delay\n" \
|
"Link state transmit delay\n" \
|
||||||
"Seconds\n" \
|
"Seconds\n" \
|
||||||
"Interval time after which a neighbor is declared down\n" \
|
"Interval time after which a neighbor is declared down\n" \
|
||||||
@ -1204,7 +1213,7 @@ DEFUN (no_ospf_area_vlink,
|
|||||||
|
|
||||||
DEFUN (ospf_area_vlink_intervals,
|
DEFUN (ospf_area_vlink_intervals,
|
||||||
ospf_area_vlink_intervals_cmd,
|
ospf_area_vlink_intervals_cmd,
|
||||||
"area <A.B.C.D|(0-4294967295)> virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|transmit-delay (1-65535)|dead-interval (1-65535)}",
|
"area <A.B.C.D|(0-4294967295)> virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|retransmit-window (20-10000)|transmit-delay (1-65535)|dead-interval (1-65535)}",
|
||||||
VLINK_HELPSTR_IPADDR
|
VLINK_HELPSTR_IPADDR
|
||||||
VLINK_HELPSTR_TIME_PARAM)
|
VLINK_HELPSTR_TIME_PARAM)
|
||||||
{
|
{
|
||||||
@ -1236,6 +1245,9 @@ DEFUN (ospf_area_vlink_intervals,
|
|||||||
else if (strmatch(argv[idx]->text, "retransmit-interval"))
|
else if (strmatch(argv[idx]->text, "retransmit-interval"))
|
||||||
vl_config.retransmit_interval =
|
vl_config.retransmit_interval =
|
||||||
strtol(argv[++idx]->arg, NULL, 10);
|
strtol(argv[++idx]->arg, NULL, 10);
|
||||||
|
else if (strmatch(argv[idx]->text, "retransmit-window"))
|
||||||
|
vl_config.retransmit_window = strtol(argv[++idx]->arg,
|
||||||
|
NULL, 10);
|
||||||
else if (strmatch(argv[idx]->text, "transmit-delay"))
|
else if (strmatch(argv[idx]->text, "transmit-delay"))
|
||||||
vl_config.transmit_delay =
|
vl_config.transmit_delay =
|
||||||
strtol(argv[++idx]->arg, NULL, 10);
|
strtol(argv[++idx]->arg, NULL, 10);
|
||||||
@ -1250,7 +1262,7 @@ DEFUN (ospf_area_vlink_intervals,
|
|||||||
|
|
||||||
DEFUN (no_ospf_area_vlink_intervals,
|
DEFUN (no_ospf_area_vlink_intervals,
|
||||||
no_ospf_area_vlink_intervals_cmd,
|
no_ospf_area_vlink_intervals_cmd,
|
||||||
"no area <A.B.C.D|(0-4294967295)> virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|transmit-delay (1-65535)|dead-interval (1-65535)}",
|
"no area <A.B.C.D|(0-4294967295)> virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|retransmit-window (20-1000)|transmit-delay (1-65535)|dead-interval (1-65535)}",
|
||||||
NO_STR
|
NO_STR
|
||||||
VLINK_HELPSTR_IPADDR
|
VLINK_HELPSTR_IPADDR
|
||||||
VLINK_HELPSTR_TIME_PARAM)
|
VLINK_HELPSTR_TIME_PARAM)
|
||||||
@ -1282,6 +1294,9 @@ DEFUN (no_ospf_area_vlink_intervals,
|
|||||||
else if (strmatch(argv[idx]->text, "retransmit-interval"))
|
else if (strmatch(argv[idx]->text, "retransmit-interval"))
|
||||||
vl_config.retransmit_interval =
|
vl_config.retransmit_interval =
|
||||||
OSPF_RETRANSMIT_INTERVAL_DEFAULT;
|
OSPF_RETRANSMIT_INTERVAL_DEFAULT;
|
||||||
|
else if (strmatch(argv[idx]->text, "retransmit-window"))
|
||||||
|
vl_config.retransmit_window =
|
||||||
|
OSPF_RETRANSMIT_WINDOW_DEFAULT;
|
||||||
else if (strmatch(argv[idx]->text, "transmit-delay"))
|
else if (strmatch(argv[idx]->text, "transmit-delay"))
|
||||||
vl_config.transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT;
|
vl_config.transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT;
|
||||||
else if (strmatch(argv[idx]->text, "dead-interval"))
|
else if (strmatch(argv[idx]->text, "dead-interval"))
|
||||||
@ -3846,6 +3861,10 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
|
|||||||
json_object_int_add(
|
json_object_int_add(
|
||||||
json_interface_sub, "timerRetransmitSecs",
|
json_interface_sub, "timerRetransmitSecs",
|
||||||
OSPF_IF_PARAM(oi, retransmit_interval));
|
OSPF_IF_PARAM(oi, retransmit_interval));
|
||||||
|
json_object_int_add(json_interface_sub,
|
||||||
|
"timerRetransmitWindowMsecs",
|
||||||
|
OSPF_IF_PARAM(oi,
|
||||||
|
retransmit_window));
|
||||||
} else {
|
} else {
|
||||||
vty_out(vty, " Timer intervals configured,");
|
vty_out(vty, " Timer intervals configured,");
|
||||||
vty_out(vty, " Hello ");
|
vty_out(vty, " Hello ");
|
||||||
@ -3964,6 +3983,16 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
|
|||||||
"nbrFilterPrefixList",
|
"nbrFilterPrefixList",
|
||||||
"N/A");
|
"N/A");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Non-Traffic interface counters
|
||||||
|
*/
|
||||||
|
if (use_json)
|
||||||
|
json_object_int_add(json_interface_sub,
|
||||||
|
"lsaRetransmissions",
|
||||||
|
oi->ls_rxmt_lsa);
|
||||||
|
else
|
||||||
|
vty_out(vty, " LSA retransmissions: %u\n",
|
||||||
|
oi->ls_rxmt_lsa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5177,6 +5206,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
|
|||||||
lookup_msg(ospf_ism_state_msg, ospf_nbr_ism_state(nbr),
|
lookup_msg(ospf_ism_state_msg, ospf_nbr_ism_state(nbr),
|
||||||
NULL));
|
NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show state changes. */
|
/* Show state changes. */
|
||||||
if (use_json)
|
if (use_json)
|
||||||
json_object_int_add(json_neigh, "stateChangeCounter",
|
json_object_int_add(json_neigh, "stateChangeCounter",
|
||||||
@ -5184,6 +5214,13 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
|
|||||||
else
|
else
|
||||||
vty_out(vty, " %d state changes\n", nbr->state_change);
|
vty_out(vty, " %d state changes\n", nbr->state_change);
|
||||||
|
|
||||||
|
/* Show LSA retransmissions. */
|
||||||
|
if (use_json)
|
||||||
|
json_object_int_add(json_neigh, "lsaRetransmissions",
|
||||||
|
nbr->ls_rxmt_lsa);
|
||||||
|
else
|
||||||
|
vty_out(vty, " %u LSA retransmissions\n", nbr->ls_rxmt_lsa);
|
||||||
|
|
||||||
if (nbr->ts_last_progress.tv_sec || nbr->ts_last_progress.tv_usec) {
|
if (nbr->ts_last_progress.tv_sec || nbr->ts_last_progress.tv_usec) {
|
||||||
struct timeval res;
|
struct timeval res;
|
||||||
long time_store;
|
long time_store;
|
||||||
@ -5347,7 +5384,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
|
|||||||
|
|
||||||
/* Show Link State Update Retransmission thread. */
|
/* Show Link State Update Retransmission thread. */
|
||||||
if (use_json) {
|
if (use_json) {
|
||||||
if (nbr->t_ls_upd != NULL)
|
if (nbr->t_ls_rxmt != NULL)
|
||||||
json_object_string_add(
|
json_object_string_add(
|
||||||
json_neigh,
|
json_neigh,
|
||||||
"threadLinkStateUpdateRetransmission",
|
"threadLinkStateUpdateRetransmission",
|
||||||
@ -5355,7 +5392,7 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
|
|||||||
} else
|
} else
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
" Thread Link State Update Retransmission %s\n\n",
|
" Thread Link State Update Retransmission %s\n\n",
|
||||||
nbr->t_ls_upd != NULL ? "on" : "off");
|
nbr->t_ls_rxmt != NULL ? "on" : "off");
|
||||||
|
|
||||||
if (!use_json) {
|
if (!use_json) {
|
||||||
vty_out(vty, " Graceful restart Helper info:\n");
|
vty_out(vty, " Graceful restart Helper info:\n");
|
||||||
@ -7993,7 +8030,7 @@ static void ospf_nbr_timer_update(struct ospf_interface *oi)
|
|||||||
nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait);
|
nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait);
|
||||||
nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval);
|
nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval);
|
||||||
nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval);
|
nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval);
|
||||||
nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval);
|
nbr->v_ls_rxmt = OSPF_IF_PARAM(oi, retransmit_interval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8728,6 +8765,40 @@ DEFUN_HIDDEN (no_ospf_retransmit_interval,
|
|||||||
return no_ip_ospf_retransmit_interval(self, vty, argc, argv);
|
return no_ip_ospf_retransmit_interval(self, vty, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFPY(ip_ospf_retransmit_window, ip_ospf_retransmit_window_addr_cmd,
|
||||||
|
"[no] ip ospf retransmit-window ![(20-1000)]$retransmit-window [A.B.C.D]$ip_addr", NO_STR
|
||||||
|
"IP Information\n"
|
||||||
|
"OSPF interface commands\n"
|
||||||
|
"Window for LSA retransmit - Retransmit LSAs expiring in this window\n"
|
||||||
|
"Milliseconds\n"
|
||||||
|
"Address of interface\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||||
|
struct ospf_if_params *params;
|
||||||
|
|
||||||
|
params = IF_DEF_PARAMS(ifp);
|
||||||
|
|
||||||
|
if (ip_addr.s_addr != INADDR_ANY) {
|
||||||
|
params = ospf_get_if_params(ifp, ip_addr);
|
||||||
|
ospf_if_update_params(ifp, ip_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no) {
|
||||||
|
UNSET_IF_PARAM(params, retransmit_window);
|
||||||
|
params->retransmit_window = OSPF_RETRANSMIT_WINDOW_DEFAULT;
|
||||||
|
} else {
|
||||||
|
SET_IF_PARAM(params, retransmit_window);
|
||||||
|
params->retransmit_window = retransmit_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There is nothing to do when the retransmit-window changes, any
|
||||||
|
* change will take effect the next time the interface LSA retransmision
|
||||||
|
* timer expires.
|
||||||
|
*/
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DEFPY (ip_ospf_gr_hdelay,
|
DEFPY (ip_ospf_gr_hdelay,
|
||||||
ip_ospf_gr_hdelay_cmd,
|
ip_ospf_gr_hdelay_cmd,
|
||||||
"ip ospf graceful-restart hello-delay (1-1800)",
|
"ip ospf graceful-restart hello-delay (1-1800)",
|
||||||
@ -12210,6 +12281,17 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
|
|||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Retransmit Window print. */
|
||||||
|
if (OSPF_IF_PARAM_CONFIGURED(params, retransmit_window) &&
|
||||||
|
params->retransmit_window !=
|
||||||
|
OSPF_RETRANSMIT_WINDOW_DEFAULT) {
|
||||||
|
vty_out(vty, " ip ospf retransmit-window %u",
|
||||||
|
params->retransmit_window);
|
||||||
|
if (params != IF_DEF_PARAMS(ifp) && rn)
|
||||||
|
vty_out(vty, " %pI4", &rn->p.u.prefix4);
|
||||||
|
vty_out(vty, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* Transmit Delay print. */
|
/* Transmit Delay print. */
|
||||||
if (OSPF_IF_PARAM_CONFIGURED(params, transmit_delay)
|
if (OSPF_IF_PARAM_CONFIGURED(params, transmit_delay)
|
||||||
&& params->transmit_delay
|
&& params->transmit_delay
|
||||||
@ -12567,19 +12649,22 @@ static int config_write_virtual_link(struct vty *vty, struct ospf *ospf)
|
|||||||
oi = vl_data->vl_oi;
|
oi = vl_data->vl_oi;
|
||||||
|
|
||||||
/* timers */
|
/* timers */
|
||||||
if (OSPF_IF_PARAM(oi, v_hello)
|
if (OSPF_IF_PARAM(oi, v_hello) !=
|
||||||
!= OSPF_HELLO_INTERVAL_DEFAULT
|
OSPF_HELLO_INTERVAL_DEFAULT ||
|
||||||
|| OSPF_IF_PARAM(oi, v_wait)
|
OSPF_IF_PARAM(oi, v_wait) !=
|
||||||
!= OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
|
OSPF_ROUTER_DEAD_INTERVAL_DEFAULT ||
|
||||||
|| OSPF_IF_PARAM(oi, retransmit_interval)
|
OSPF_IF_PARAM(oi, retransmit_interval) !=
|
||||||
!= OSPF_RETRANSMIT_INTERVAL_DEFAULT
|
OSPF_RETRANSMIT_INTERVAL_DEFAULT ||
|
||||||
|| OSPF_IF_PARAM(oi, transmit_delay)
|
OSPF_IF_PARAM(oi, retransmit_window) !=
|
||||||
!= OSPF_TRANSMIT_DELAY_DEFAULT)
|
OSPF_RETRANSMIT_WINDOW_DEFAULT ||
|
||||||
|
OSPF_IF_PARAM(oi, transmit_delay) !=
|
||||||
|
OSPF_TRANSMIT_DELAY_DEFAULT)
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
" area %s virtual-link %pI4 hello-interval %d retransmit-interval %d transmit-delay %d dead-interval %d\n",
|
" area %s virtual-link %pI4 hello-interval %d retransmit-interval %d retransmit-window %d transmit-delay %d dead-interval %d\n",
|
||||||
buf, &vl_data->vl_peer,
|
buf, &vl_data->vl_peer,
|
||||||
OSPF_IF_PARAM(oi, v_hello),
|
OSPF_IF_PARAM(oi, v_hello),
|
||||||
OSPF_IF_PARAM(oi, retransmit_interval),
|
OSPF_IF_PARAM(oi, retransmit_interval),
|
||||||
|
OSPF_IF_PARAM(oi, retransmit_window),
|
||||||
OSPF_IF_PARAM(oi, transmit_delay),
|
OSPF_IF_PARAM(oi, transmit_delay),
|
||||||
OSPF_IF_PARAM(oi, v_wait));
|
OSPF_IF_PARAM(oi, v_wait));
|
||||||
else
|
else
|
||||||
@ -13112,6 +13197,9 @@ static void ospf_vty_if_init(void)
|
|||||||
install_element(INTERFACE_NODE,
|
install_element(INTERFACE_NODE,
|
||||||
&no_ip_ospf_retransmit_interval_addr_cmd);
|
&no_ip_ospf_retransmit_interval_addr_cmd);
|
||||||
|
|
||||||
|
/* "ip ospf retransmit-window" commands. */
|
||||||
|
install_element(INTERFACE_NODE, &ip_ospf_retransmit_window_addr_cmd);
|
||||||
|
|
||||||
/* "ip ospf transmit-delay" commands. */
|
/* "ip ospf transmit-delay" commands. */
|
||||||
install_element(INTERFACE_NODE, &ip_ospf_transmit_delay_addr_cmd);
|
install_element(INTERFACE_NODE, &ip_ospf_transmit_delay_addr_cmd);
|
||||||
install_element(INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd);
|
install_element(INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd);
|
||||||
|
@ -11,6 +11,7 @@ r1-eth0 is up
|
|||||||
Hello due in XX.XXXs
|
Hello due in XX.XXXs
|
||||||
Neighbor Count is 0, Adjacent neighbor count is 0
|
Neighbor Count is 0, Adjacent neighbor count is 0
|
||||||
Graceful Restart hello delay: 10s
|
Graceful Restart hello delay: 10s
|
||||||
|
LSA retransmissions: 0
|
||||||
r1-eth3 is up
|
r1-eth3 is up
|
||||||
ifindex X, MTU 1500 bytes, BW XX Mbit <UP,LOWER_UP,BROADCAST,RUNNING,MULTICAST>
|
ifindex X, MTU 1500 bytes, BW XX Mbit <UP,LOWER_UP,BROADCAST,RUNNING,MULTICAST>
|
||||||
Internet Address 192.168.3.1/26, Broadcast 192.168.3.63, Area 0.0.0.0
|
Internet Address 192.168.3.1/26, Broadcast 192.168.3.63, Area 0.0.0.0
|
||||||
@ -24,3 +25,4 @@ r1-eth3 is up
|
|||||||
Hello due in XX.XXXs
|
Hello due in XX.XXXs
|
||||||
Neighbor Count is 0, Adjacent neighbor count is 0
|
Neighbor Count is 0, Adjacent neighbor count is 0
|
||||||
Graceful Restart hello delay: 10s
|
Graceful Restart hello delay: 10s
|
||||||
|
LSA retransmissions: 0
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
!
|
!
|
||||||
|
!log file ospfd.log debug
|
||||||
|
! debug ospf event
|
||||||
|
! debug ospf client
|
||||||
|
! debug ospf lsa
|
||||||
|
! debug ospf packet all
|
||||||
|
|
||||||
hostname r1
|
hostname r1
|
||||||
password zebra
|
password zebra
|
||||||
log file /tmp/r1-frr.log
|
log file /tmp/r1-frr.log
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
!
|
!
|
||||||
|
!log file ospfd.log debug
|
||||||
|
! debug ospf event
|
||||||
|
! debug ospf client
|
||||||
|
! debug ospf lsa
|
||||||
|
! debug ospf packet all
|
||||||
|
!
|
||||||
hostname r2
|
hostname r2
|
||||||
password zebra
|
password zebra
|
||||||
log file /tmp/r1-frr.log
|
log file /tmp/r1-frr.log
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
!
|
!
|
||||||
|
!log file ospfd.log debug
|
||||||
|
! debug ospf event
|
||||||
|
! debug ospf client
|
||||||
|
! debug ospf lsa
|
||||||
|
! debug ospf packet all
|
||||||
|
!
|
||||||
hostname r3
|
hostname r3
|
||||||
password zebra
|
password zebra
|
||||||
log file /tmp/r1-frr.log
|
log file /tmp/r1-frr.log
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
!
|
!
|
||||||
|
!log file ospfd.log debug
|
||||||
|
! debug ospf event
|
||||||
|
! debug ospf client
|
||||||
|
! debug ospf lsa
|
||||||
|
! debug ospf packet all
|
||||||
|
!
|
||||||
hostname r4
|
hostname r4
|
||||||
password zebra
|
password zebra
|
||||||
log file /tmp/r1-frr.log
|
log file /tmp/r1-frr.log
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from time import sleep
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -113,7 +114,9 @@ def teardown_module():
|
|||||||
tgen.stop_topology()
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
def verify_p2mp_interface(tgen, router, nbr_cnt, nbr_adj_cnt, nbr_filter):
|
def verify_p2mp_interface(
|
||||||
|
tgen, router, nbr_cnt, nbr_adj_cnt, delay_reflood, nbr_filter
|
||||||
|
):
|
||||||
"Verify the P2MP Configuration and interface settings"
|
"Verify the P2MP Configuration and interface settings"
|
||||||
|
|
||||||
topo_router = tgen.gears[router]
|
topo_router = tgen.gears[router]
|
||||||
@ -147,7 +150,7 @@ def verify_p2mp_interface(tgen, router, nbr_cnt, nbr_adj_cnt, nbr_filter):
|
|||||||
"nbrCount": nbr_cnt,
|
"nbrCount": nbr_cnt,
|
||||||
"nbrAdjacentCount": nbr_adj_cnt,
|
"nbrAdjacentCount": nbr_adj_cnt,
|
||||||
"prefixSuppression": False,
|
"prefixSuppression": False,
|
||||||
"p2mpDelayReflood": False,
|
"p2mpDelayReflood": delay_reflood,
|
||||||
"nbrFilterPrefixList": nbr_filter,
|
"nbrFilterPrefixList": nbr_filter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,7 +283,7 @@ def test_p2mp_broadcast_interface():
|
|||||||
pytest.skip("Skipped because of router(s) failure")
|
pytest.skip("Skipped because of router(s) failure")
|
||||||
|
|
||||||
step("Verify router r1 interface r1-eth0 p2mp configuration")
|
step("Verify router r1 interface r1-eth0 p2mp configuration")
|
||||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
verify_p2mp_interface(tgen, "r1", 3, 3, False, "N/A")
|
||||||
|
|
||||||
step("Verify router r1 p2mp interface r1-eth0 neighbors")
|
step("Verify router r1 p2mp interface r1-eth0 neighbors")
|
||||||
verify_p2mp_neighbor(
|
verify_p2mp_neighbor(
|
||||||
@ -305,7 +308,7 @@ def test_p2mp_broadcast_interface():
|
|||||||
|
|
||||||
step("Verify router r1 interface r1-eth0 p2mp configuration application")
|
step("Verify router r1 interface r1-eth0 p2mp configuration application")
|
||||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf network point-to-multipoint")
|
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf network point-to-multipoint")
|
||||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
verify_p2mp_interface(tgen, "r1", 3, 3, False, "N/A")
|
||||||
|
|
||||||
step("Verify restablishment of r1-eth0 p2mp neighbors")
|
step("Verify restablishment of r1-eth0 p2mp neighbors")
|
||||||
verify_p2mp_neighbor(
|
verify_p2mp_neighbor(
|
||||||
@ -324,14 +327,14 @@ def test_p2mp_broadcast_interface():
|
|||||||
verify_p2mp_route(tgen, "r1", "10.1.4.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_p2mp_broadcast_neighbor_filter():
|
def p2mp_broadcast_neighbor_filter_common(delay_reflood):
|
||||||
tgen = get_topogen()
|
tgen = get_topogen()
|
||||||
|
|
||||||
if tgen.routers_have_failure():
|
if tgen.routers_have_failure():
|
||||||
pytest.skip("Skipped because of router(s) failure")
|
pytest.skip("Skipped because of router(s) failure")
|
||||||
|
|
||||||
step("Verify router r1 interface r1-eth0 p2mp configuration")
|
step("Verify router r1 interface r1-eth0 p2mp configuration")
|
||||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
verify_p2mp_interface(tgen, "r1", 3, 3, delay_reflood, "N/A")
|
||||||
|
|
||||||
step("Verify router r1 p2mp interface r1-eth0 neighbors")
|
step("Verify router r1 p2mp interface r1-eth0 neighbors")
|
||||||
verify_p2mp_neighbor(
|
verify_p2mp_neighbor(
|
||||||
@ -362,7 +365,7 @@ def test_p2mp_broadcast_neighbor_filter():
|
|||||||
assert neighbor_filter_cfg == " ip ospf neighbor-filter nbr-filter", assertmsg
|
assert neighbor_filter_cfg == " ip ospf neighbor-filter nbr-filter", assertmsg
|
||||||
|
|
||||||
step("Verify non-existent neighbor-filter is not applied to r1 interfaces")
|
step("Verify non-existent neighbor-filter is not applied to r1 interfaces")
|
||||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
verify_p2mp_interface(tgen, "r1", 3, 3, delay_reflood, "N/A")
|
||||||
|
|
||||||
step("Add nbr-filter prefix-list configuration to r1")
|
step("Add nbr-filter prefix-list configuration to r1")
|
||||||
r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 200 permit any")
|
r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 200 permit any")
|
||||||
@ -370,7 +373,7 @@ def test_p2mp_broadcast_neighbor_filter():
|
|||||||
step(
|
step(
|
||||||
"Verify neighbor-filter is now applied to r1 interface and neighbors still adjacent"
|
"Verify neighbor-filter is now applied to r1 interface and neighbors still adjacent"
|
||||||
)
|
)
|
||||||
verify_p2mp_interface(tgen, "r1", 3, 3, "nbr-filter")
|
verify_p2mp_interface(tgen, "r1", 3, 3, delay_reflood, "nbr-filter")
|
||||||
|
|
||||||
step("Add nbr-filter prefix-list configuration to block r4")
|
step("Add nbr-filter prefix-list configuration to block r4")
|
||||||
r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 10 deny 10.1.0.4/32")
|
r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 10 deny 10.1.0.4/32")
|
||||||
@ -378,7 +381,7 @@ def test_p2mp_broadcast_neighbor_filter():
|
|||||||
step(
|
step(
|
||||||
"Verify neighbor-filter is now applied to r1 interface and r4 is no longer adjacent"
|
"Verify neighbor-filter is now applied to r1 interface and r4 is no longer adjacent"
|
||||||
)
|
)
|
||||||
verify_p2mp_interface(tgen, "r1", 2, 2, "nbr-filter")
|
verify_p2mp_interface(tgen, "r1", 2, 2, delay_reflood, "nbr-filter")
|
||||||
verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4")
|
verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4")
|
||||||
|
|
||||||
step("Verify route to r4 subnet is now through r2")
|
step("Verify route to r4 subnet is now through r2")
|
||||||
@ -390,7 +393,7 @@ def test_p2mp_broadcast_neighbor_filter():
|
|||||||
step(
|
step(
|
||||||
"Verify neighbor-filter is now applied to r1 interface and r2 is no longer adjacent"
|
"Verify neighbor-filter is now applied to r1 interface and r2 is no longer adjacent"
|
||||||
)
|
)
|
||||||
verify_p2mp_interface(tgen, "r1", 1, 1, "nbr-filter")
|
verify_p2mp_interface(tgen, "r1", 1, 1, delay_reflood, "nbr-filter")
|
||||||
verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2")
|
verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2")
|
||||||
|
|
||||||
step("Verify route to r4 and r2 subnet are now through r3")
|
step("Verify route to r4 and r2 subnet are now through r3")
|
||||||
@ -406,24 +409,105 @@ def test_p2mp_broadcast_neighbor_filter():
|
|||||||
assert rc, assertmsg
|
assert rc, assertmsg
|
||||||
|
|
||||||
step("Verify interface neighbor-filter is removed and neighbors present")
|
step("Verify interface neighbor-filter is removed and neighbors present")
|
||||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
verify_p2mp_interface(tgen, "r1", 3, 3, delay_reflood, "N/A")
|
||||||
|
|
||||||
step("Add neighbor filter configuration and verify neighbors are filtered")
|
step("Add neighbor filter configuration and verify neighbors are filtered")
|
||||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter")
|
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter")
|
||||||
verify_p2mp_interface(tgen, "r1", 1, 1, "nbr-filter")
|
verify_p2mp_interface(tgen, "r1", 1, 1, delay_reflood, "nbr-filter")
|
||||||
verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2")
|
verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2")
|
||||||
verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4")
|
verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4")
|
||||||
|
|
||||||
step("Remove nbr-filter prefix-list configuration to block r2 and verify neighbor")
|
step("Remove nbr-filter prefix-list configuration to block r2 and verify neighbor")
|
||||||
r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter seq 20")
|
r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter seq 20")
|
||||||
verify_p2mp_interface(tgen, "r1", 2, 2, "nbr-filter")
|
verify_p2mp_interface(tgen, "r1", 2, 2, delay_reflood, "nbr-filter")
|
||||||
verify_p2mp_neighbor(
|
verify_p2mp_neighbor(
|
||||||
tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
|
tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
step("Delete nbr-filter prefix-list and verify neighbors are present")
|
step("Delete nbr-filter prefix-list and verify neighbors are present")
|
||||||
r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter")
|
r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter")
|
||||||
verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
|
verify_p2mp_interface(tgen, "r1", 3, 3, delay_reflood, "N/A")
|
||||||
|
|
||||||
|
|
||||||
|
def test_p2mp_broadcast_neighbor_filter():
|
||||||
|
p2mp_broadcast_neighbor_filter_common(False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_p2mp_broadcast_neighbor_filter_delay_reflood():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip("Skipped because of router(s) failure")
|
||||||
|
|
||||||
|
step("Modify router r1 interface r1-eth0 p2mp delay-reflood configuration")
|
||||||
|
r1 = tgen.gears["r1"]
|
||||||
|
r1.vtysh_cmd(
|
||||||
|
"conf t\ninterface r1-eth0\nip ospf network point-to-multipoint delay-reflood"
|
||||||
|
)
|
||||||
|
verify_p2mp_interface(tgen, "r1", 3, 3, True, "N/A")
|
||||||
|
|
||||||
|
step("Modify router r2 interface r2-eth0 p2mp delay-reflood configuration")
|
||||||
|
r2 = tgen.gears["r2"]
|
||||||
|
r2.vtysh_cmd(
|
||||||
|
"conf t\ninterface r2-eth0\nip ospf network point-to-multipoint delay-reflood"
|
||||||
|
)
|
||||||
|
|
||||||
|
step("Modify router r3 interface r3-eth0 p2mp delay-reflood configuration")
|
||||||
|
r3 = tgen.gears["r3"]
|
||||||
|
r3.vtysh_cmd(
|
||||||
|
"conf t\ninterface r3-eth0\nip ospf network point-to-multipoint delay-reflood"
|
||||||
|
)
|
||||||
|
|
||||||
|
step("Modify router r4 interface r4-eth0 p2mp delay-reflood configuration")
|
||||||
|
r4 = tgen.gears["r4"]
|
||||||
|
r4.vtysh_cmd(
|
||||||
|
"conf t\ninterface r4-eth0\nip ospf network point-to-multipoint delay-reflood"
|
||||||
|
)
|
||||||
|
|
||||||
|
p2mp_broadcast_neighbor_filter_common(True)
|
||||||
|
|
||||||
|
step("Recreate a partial P2MP mesh with neighbor filters")
|
||||||
|
step("Add nbr-filter prefix-list configuration to block r4")
|
||||||
|
r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 30 permit any")
|
||||||
|
r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 10 deny 10.1.0.3/32")
|
||||||
|
r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 20 deny 10.1.0.4/32")
|
||||||
|
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter")
|
||||||
|
|
||||||
|
r2.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 30 permit any")
|
||||||
|
r2.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 10 deny 10.1.0.4/32")
|
||||||
|
r2.vtysh_cmd("conf t\ninterface r2-eth0\nip ospf neighbor-filter nbr-filter")
|
||||||
|
|
||||||
|
r3.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 30 permit any")
|
||||||
|
r3.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 10 deny 10.1.0.1/32")
|
||||||
|
r3.vtysh_cmd("conf t\ninterface r3-eth0\nip ospf neighbor-filter nbr-filter")
|
||||||
|
|
||||||
|
r4.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 30 permit any")
|
||||||
|
r4.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 10 deny 10.1.0.1/32")
|
||||||
|
r4.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 20 deny 10.1.0.2/32")
|
||||||
|
r4.vtysh_cmd("conf t\ninterface r4-eth0\nip ospf neighbor-filter nbr-filter")
|
||||||
|
|
||||||
|
step(
|
||||||
|
"Add redistribution and spaced static routes to r1 to test delay flood retransmission"
|
||||||
|
)
|
||||||
|
r1.vtysh_cmd("conf t\nrouter ospf\nredistribute static")
|
||||||
|
r1.vtysh_cmd("conf t\nip route 20.1.1.1/32 null0")
|
||||||
|
sleep(1)
|
||||||
|
r1.vtysh_cmd("conf t\nip route 20.1.1.2/32 null0")
|
||||||
|
sleep(1)
|
||||||
|
r1.vtysh_cmd("conf t\nip route 20.1.1.3/32 null0")
|
||||||
|
sleep(1)
|
||||||
|
r1.vtysh_cmd("conf t\nip route 20.1.1.4/32 null0")
|
||||||
|
sleep(1)
|
||||||
|
r1.vtysh_cmd("conf t\nip route 20.1.1.5/32 null0")
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
step(
|
||||||
|
"Verify the routes are installed on r1 with delay-reflood in P2MP partial mesh"
|
||||||
|
)
|
||||||
|
verify_p2mp_route(tgen, "r4", "20.1.1.1/32", 32, "10.1.0.3", "r4-eth0")
|
||||||
|
verify_p2mp_route(tgen, "r4", "20.1.1.2/32", 32, "10.1.0.3", "r4-eth0")
|
||||||
|
verify_p2mp_route(tgen, "r4", "20.1.1.3/32", 32, "10.1.0.3", "r4-eth0")
|
||||||
|
verify_p2mp_route(tgen, "r4", "20.1.1.4/32", 32, "10.1.0.3", "r4-eth0")
|
||||||
|
|
||||||
|
|
||||||
def test_memory_leak():
|
def test_memory_leak():
|
||||||
|
Loading…
Reference in New Issue
Block a user