[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:
Joakim Tjernlund 2008-09-02 19:06:31 +01:00 committed by Paul Jakma
parent 5d7bdd0ed9
commit a49eb30a17
3 changed files with 117 additions and 121 deletions

View File

@ -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;
} }

View File

@ -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

View File

@ -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 *);