mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-01 19:51:11 +00:00
[ospfd] Restructure opsf_if_update() and ospf_network_run()
Add an struct interface paramenter and adjust the affected code accordingly. The old code was a mess looping over all interfaces several times when one interface was added/changed. * ospfd/ospfd.h: Add struct interface parameter to ospf_if_update() * ospfd/ospf_zebra.c: Add ifp arg to ospf_if_update() calls. (ospf_interface_address_delete) delete ospf_if_update() call, redundant as function calls ospf_if_free() itself. * ospfd/ospfd.c: (ospf_network_unset) handle deconfiguration here, rather than ospf_if_update. (ospf_network_run_interface) ospf_network_run, for any given interface. (ospf_network_run) move guts to previous, and use it. (ospf_if_update) Adjust to take struct interface as argument, as all callers have a specific ifp in mind. Iterate over ifp's connected list and call ospf_network_run_interface instead of ospf_network_run, turning this path into O(nm) rather than O(n^2). Adjust all code dealing with opsf_if_update and ospf_network_run to pass the new struct interface * arg. (some minor modifications and bug-additions by Paul Jakma). Signed-off-by: Paul Jakma <paul@quagga.net>
This commit is contained in:
parent
5d7bdd0ed9
commit
a49eb30a17
@ -87,7 +87,6 @@ static int
|
|||||||
ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length)
|
ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length)
|
||||||
{
|
{
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct ospf *ospf;
|
|
||||||
|
|
||||||
ifp = zebra_interface_add_read (zclient->ibuf);
|
ifp = zebra_interface_add_read (zclient->ibuf);
|
||||||
|
|
||||||
@ -103,9 +102,7 @@ ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length)
|
|||||||
IF_DEF_PARAMS (ifp)->type = ospf_default_iftype(ifp);
|
IF_DEF_PARAMS (ifp)->type = ospf_default_iftype(ifp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ospf = ospf_lookup ();
|
ospf_if_update (NULL, ifp);
|
||||||
if (ospf != NULL)
|
|
||||||
ospf_if_update (ospf);
|
|
||||||
|
|
||||||
#ifdef HAVE_SNMP
|
#ifdef HAVE_SNMP
|
||||||
ospf_snmp_if_update (ifp);
|
ospf_snmp_if_update (ifp);
|
||||||
@ -255,7 +252,6 @@ static int
|
|||||||
ospf_interface_address_add (int command, struct zclient *zclient,
|
ospf_interface_address_add (int command, struct zclient *zclient,
|
||||||
zebra_size_t length)
|
zebra_size_t length)
|
||||||
{
|
{
|
||||||
struct ospf *ospf;
|
|
||||||
struct connected *c;
|
struct connected *c;
|
||||||
|
|
||||||
c = zebra_interface_address_read (command, zclient->ibuf);
|
c = zebra_interface_address_read (command, zclient->ibuf);
|
||||||
@ -270,9 +266,7 @@ ospf_interface_address_add (int command, struct zclient *zclient,
|
|||||||
zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf);
|
zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
ospf = ospf_lookup ();
|
ospf_if_update (NULL, c->ifp);
|
||||||
if (ospf != NULL)
|
|
||||||
ospf_if_update (ospf);
|
|
||||||
|
|
||||||
#ifdef HAVE_SNMP
|
#ifdef HAVE_SNMP
|
||||||
ospf_snmp_if_update (c->ifp);
|
ospf_snmp_if_update (c->ifp);
|
||||||
@ -285,7 +279,6 @@ static int
|
|||||||
ospf_interface_address_delete (int command, struct zclient *zclient,
|
ospf_interface_address_delete (int command, struct zclient *zclient,
|
||||||
zebra_size_t length)
|
zebra_size_t length)
|
||||||
{
|
{
|
||||||
struct ospf *ospf;
|
|
||||||
struct connected *c;
|
struct connected *c;
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct ospf_interface *oi;
|
struct ospf_interface *oi;
|
||||||
@ -327,10 +320,6 @@ ospf_interface_address_delete (int command, struct zclient *zclient,
|
|||||||
|
|
||||||
connected_free (c);
|
connected_free (c);
|
||||||
|
|
||||||
ospf = ospf_lookup ();
|
|
||||||
if (ospf != NULL)
|
|
||||||
ospf_if_update (ospf);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
217
ospfd/ospfd.c
217
ospfd/ospfd.c
@ -68,7 +68,9 @@ extern struct in_addr router_id_zebra;
|
|||||||
static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
|
static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *);
|
||||||
static void ospf_network_free (struct ospf *, struct ospf_network *);
|
static void ospf_network_free (struct ospf *, struct ospf_network *);
|
||||||
static void ospf_area_free (struct ospf_area *);
|
static void ospf_area_free (struct ospf_area *);
|
||||||
static void ospf_network_run (struct ospf *, struct prefix *, struct ospf_area *);
|
static void ospf_network_run (struct prefix *, struct ospf_area *);
|
||||||
|
static void ospf_network_run_interface (struct prefix *, struct ospf_area *,
|
||||||
|
struct interface *);
|
||||||
static void ospf_finish_final (struct ospf *);
|
static void ospf_finish_final (struct ospf *);
|
||||||
|
|
||||||
#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
|
#define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
|
||||||
@ -78,6 +80,7 @@ ospf_router_id_update (struct ospf *ospf)
|
|||||||
{
|
{
|
||||||
struct in_addr router_id, router_id_old;
|
struct in_addr router_id, router_id_old;
|
||||||
struct ospf_interface *oi;
|
struct ospf_interface *oi;
|
||||||
|
struct interface *ifp;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
|
|
||||||
if (IS_DEBUG_OSPF_EVENT)
|
if (IS_DEBUG_OSPF_EVENT)
|
||||||
@ -130,7 +133,8 @@ ospf_router_id_update (struct ospf *ospf)
|
|||||||
ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
|
ospf_router_lsa_update_timer, OSPF_LSA_UPDATE_DELAY);
|
||||||
|
|
||||||
/* update ospf_interface's */
|
/* update ospf_interface's */
|
||||||
ospf_if_update (ospf);
|
for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
|
||||||
|
ospf_if_update (ospf, ifp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,7 +749,7 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p,
|
|||||||
area = ospf_area_get (ospf, area_id, ret);
|
area = ospf_area_get (ospf, area_id, ret);
|
||||||
|
|
||||||
/* Run network config now. */
|
/* Run network config now. */
|
||||||
ospf_network_run (ospf, (struct prefix *)p, area);
|
ospf_network_run ((struct prefix *)p, area);
|
||||||
|
|
||||||
/* Update connected redistribute. */
|
/* Update connected redistribute. */
|
||||||
if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
|
if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
|
||||||
@ -770,6 +774,8 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
|
|||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
struct ospf_network *network;
|
struct ospf_network *network;
|
||||||
struct external_info *ei;
|
struct external_info *ei;
|
||||||
|
struct listnode *node, *nnode;
|
||||||
|
struct ospf_interface *oi;
|
||||||
|
|
||||||
rn = route_node_lookup (ospf->networks, (struct prefix *)p);
|
rn = route_node_lookup (ospf->networks, (struct prefix *)p);
|
||||||
if (rn == NULL)
|
if (rn == NULL)
|
||||||
@ -783,7 +789,31 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
|
|||||||
rn->info = NULL;
|
rn->info = NULL;
|
||||||
route_unlock_node (rn);
|
route_unlock_node (rn);
|
||||||
|
|
||||||
ospf_if_update (ospf);
|
/* Find interfaces that not configured already. */
|
||||||
|
for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
|
||||||
|
{
|
||||||
|
int found = 0;
|
||||||
|
struct connected *co = oi->connected;
|
||||||
|
|
||||||
|
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
|
||||||
|
{
|
||||||
|
if (rn->info == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ospf_network_match_iface(co,&rn->p))
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
route_unlock_node (rn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found == 0)
|
||||||
|
ospf_if_free (oi);
|
||||||
|
}
|
||||||
|
|
||||||
/* Update connected redistribute. */
|
/* Update connected redistribute. */
|
||||||
if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
|
if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT))
|
||||||
@ -857,73 +887,78 @@ ospf_network_match_iface(struct connected *co, struct prefix *net)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
|
ospf_network_run_interface (struct prefix *p, struct ospf_area *area,
|
||||||
|
struct interface *ifp)
|
||||||
|
{
|
||||||
|
struct listnode *cnode;
|
||||||
|
struct connected *co;
|
||||||
|
|
||||||
|
if (memcmp (ifp->name, "VLINK", 5) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* if interface prefix is match specified prefix,
|
||||||
|
then create socket and join multicast group. */
|
||||||
|
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
|
||||||
|
{
|
||||||
|
struct prefix *addr;
|
||||||
|
|
||||||
|
if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
addr = CONNECTED_ID(co);
|
||||||
|
|
||||||
|
if (p->family == co->address->family
|
||||||
|
&& ! ospf_if_is_configured (area->ospf, &(addr->u.prefix4))
|
||||||
|
&& ospf_network_match_iface(co,p))
|
||||||
|
{
|
||||||
|
struct ospf_interface *oi;
|
||||||
|
|
||||||
|
oi = ospf_if_new (area->ospf, ifp, co->address);
|
||||||
|
oi->connected = co;
|
||||||
|
|
||||||
|
oi->area = area;
|
||||||
|
|
||||||
|
oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
|
||||||
|
oi->output_cost = ospf_if_get_output_cost (oi);
|
||||||
|
|
||||||
|
/* Add pseudo neighbor. */
|
||||||
|
ospf_nbr_add_self (oi);
|
||||||
|
|
||||||
|
/* Relate ospf interface to ospf instance. */
|
||||||
|
oi->ospf = area->ospf;
|
||||||
|
|
||||||
|
/* update network type as interface flag */
|
||||||
|
/* If network type is specified previously,
|
||||||
|
skip network type setting. */
|
||||||
|
oi->type = IF_DEF_PARAMS (ifp)->type;
|
||||||
|
|
||||||
|
ospf_area_add_if (oi->area, oi);
|
||||||
|
|
||||||
|
/* if router_id is not configured, dont bring up
|
||||||
|
* interfaces.
|
||||||
|
* ospf_router_id_update() will call ospf_if_update
|
||||||
|
* whenever r-id is configured instead.
|
||||||
|
*/
|
||||||
|
if ((area->ospf->router_id.s_addr != 0)
|
||||||
|
&& if_is_operative (ifp))
|
||||||
|
ospf_if_up (oi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ospf_network_run (struct prefix *p, struct ospf_area *area)
|
||||||
{
|
{
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct connected *co;
|
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
|
|
||||||
/* Schedule Router ID Update. */
|
/* Schedule Router ID Update. */
|
||||||
if (ospf->router_id.s_addr == 0)
|
if (area->ospf->router_id.s_addr == 0)
|
||||||
ospf_router_id_update (ospf);
|
ospf_router_id_update (area->ospf);
|
||||||
|
|
||||||
/* Get target interface. */
|
/* Get target interface. */
|
||||||
for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
|
for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
|
||||||
{
|
ospf_network_run_interface (p, area, ifp);
|
||||||
struct listnode *cnode;
|
|
||||||
|
|
||||||
if (memcmp (ifp->name, "VLINK", 5) == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* if interface prefix is match specified prefix,
|
|
||||||
then create socket and join multicast group. */
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co))
|
|
||||||
{
|
|
||||||
struct prefix *addr;
|
|
||||||
|
|
||||||
if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
addr = CONNECTED_ID(co);
|
|
||||||
|
|
||||||
if (p->family == co->address->family
|
|
||||||
&& ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
|
|
||||||
&& ospf_network_match_iface(co,p))
|
|
||||||
{
|
|
||||||
struct ospf_interface *oi;
|
|
||||||
|
|
||||||
oi = ospf_if_new (ospf, ifp, co->address);
|
|
||||||
oi->connected = co;
|
|
||||||
|
|
||||||
oi->area = area;
|
|
||||||
|
|
||||||
oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
|
|
||||||
oi->output_cost = ospf_if_get_output_cost (oi);
|
|
||||||
|
|
||||||
/* Add pseudo neighbor. */
|
|
||||||
ospf_nbr_add_self (oi);
|
|
||||||
|
|
||||||
/* Relate ospf interface to ospf instance. */
|
|
||||||
oi->ospf = ospf;
|
|
||||||
|
|
||||||
/* update network type as interface flag */
|
|
||||||
/* If network type is specified previously,
|
|
||||||
skip network type setting. */
|
|
||||||
oi->type = IF_DEF_PARAMS (ifp)->type;
|
|
||||||
|
|
||||||
ospf_area_add_if (oi->area, oi);
|
|
||||||
|
|
||||||
/* if router_id is not configured, dont bring up
|
|
||||||
* interfaces.
|
|
||||||
* ospf_router_id_update() will call ospf_if_update
|
|
||||||
* whenever r-id is configured instead.
|
|
||||||
*/
|
|
||||||
if ((ospf->router_id.s_addr != 0)
|
|
||||||
&& if_is_operative (ifp))
|
|
||||||
ospf_if_up (oi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -954,55 +989,27 @@ ospf_ls_upd_queue_empty (struct ospf_interface *oi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_if_update (struct ospf *ospf)
|
ospf_if_update (struct ospf *ospf, struct interface *ifp)
|
||||||
{
|
{
|
||||||
struct route_node *rn;
|
struct route_node *rn;
|
||||||
struct listnode *node, *nnode;
|
|
||||||
struct ospf_network *network;
|
struct ospf_network *network;
|
||||||
struct ospf_area *area;
|
struct ospf_area *area;
|
||||||
struct ospf_interface *oi;
|
|
||||||
|
|
||||||
if (ospf != NULL)
|
if (!ospf)
|
||||||
{
|
ospf = ospf_lookup ();
|
||||||
/* Router-ID must be configured. */
|
|
||||||
if (ospf->router_id.s_addr == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Find interfaces that not configured already. */
|
/* Router-ID must be configured. */
|
||||||
for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
|
if (ospf->router_id.s_addr == 0)
|
||||||
{
|
return;
|
||||||
int found = 0;
|
|
||||||
struct connected *co = oi->connected;
|
|
||||||
|
|
||||||
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
/* Run each netowrk for this interface. */
|
||||||
continue;
|
for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
|
||||||
|
if (rn->info != NULL)
|
||||||
for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
|
{
|
||||||
{
|
network = (struct ospf_network *) rn->info;
|
||||||
if (rn->info == NULL)
|
area = ospf_area_get (ospf, network->area_id, network->format);
|
||||||
continue;
|
ospf_network_run_interface (&rn->p, area, ifp);
|
||||||
|
}
|
||||||
if (ospf_network_match_iface(co,&rn->p))
|
|
||||||
{
|
|
||||||
found = 1;
|
|
||||||
route_unlock_node (rn);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found == 0)
|
|
||||||
ospf_if_free (oi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Run each interface. */
|
|
||||||
for (rn = route_top (ospf->networks); rn; rn = route_next (rn))
|
|
||||||
if (rn->info != NULL)
|
|
||||||
{
|
|
||||||
network = (struct ospf_network *) rn->info;
|
|
||||||
area = ospf_area_get (ospf, network->area_id, network->format);
|
|
||||||
ospf_network_run (ospf, &rn->p, area);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -588,7 +588,7 @@ extern int ospf_nbr_nbma_poll_interval_set (struct ospf *, struct in_addr,
|
|||||||
extern int ospf_nbr_nbma_poll_interval_unset (struct ospf *, struct in_addr);
|
extern int ospf_nbr_nbma_poll_interval_unset (struct ospf *, struct in_addr);
|
||||||
extern void ospf_prefix_list_update (struct prefix_list *);
|
extern void ospf_prefix_list_update (struct prefix_list *);
|
||||||
extern void ospf_init (void);
|
extern void ospf_init (void);
|
||||||
extern void ospf_if_update (struct ospf *);
|
extern void ospf_if_update (struct ospf *, struct interface *);
|
||||||
extern void ospf_ls_upd_queue_empty (struct ospf_interface *);
|
extern void ospf_ls_upd_queue_empty (struct ospf_interface *);
|
||||||
extern void ospf_terminate (void);
|
extern void ospf_terminate (void);
|
||||||
extern void ospf_nbr_nbma_if_update (struct ospf *, struct ospf_interface *);
|
extern void ospf_nbr_nbma_if_update (struct ospf *, struct ospf_interface *);
|
||||||
|
Loading…
Reference in New Issue
Block a user