From a49eb30a178547189147c8a35bf9e35f429abb66 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Tue, 2 Sep 2008 19:06:31 +0100 Subject: [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 --- ospfd/ospfd.c | 221 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 114 insertions(+), 107 deletions(-) (limited to 'ospfd/ospfd.c') diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index a4c4fac3..32580ccf 100644 --- a/ospfd/ospfd.c +++ b/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_network_free (struct ospf *, struct ospf_network *); 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 *); #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 ospf_interface *oi; + struct interface *ifp; struct listnode *node; 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); /* 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); /* Run network config now. */ - ospf_network_run (ospf, (struct prefix *)p, area); + ospf_network_run ((struct prefix *)p, area); /* Update connected redistribute. */ 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 ospf_network *network; struct external_info *ei; + struct listnode *node, *nnode; + struct ospf_interface *oi; rn = route_node_lookup (ospf->networks, (struct prefix *)p); if (rn == NULL) @@ -783,7 +789,31 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, rn->info = NULL; 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. */ if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) @@ -857,73 +887,78 @@ ospf_network_match_iface(struct connected *co, struct prefix *net) } 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 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 listnode *node; /* Schedule Router ID Update. */ - if (ospf->router_id.s_addr == 0) - ospf_router_id_update (ospf); + if (area->ospf->router_id.s_addr == 0) + ospf_router_id_update (area->ospf); /* Get target interface. */ for (ALL_LIST_ELEMENTS_RO (om->iflist, node, 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); - } - } - } + ospf_network_run_interface (p, area, ifp); } void @@ -954,55 +989,27 @@ ospf_ls_upd_queue_empty (struct ospf_interface *oi) } void -ospf_if_update (struct ospf *ospf) +ospf_if_update (struct ospf *ospf, struct interface *ifp) { struct route_node *rn; - struct listnode *node, *nnode; struct ospf_network *network; struct ospf_area *area; - struct ospf_interface *oi; + + if (!ospf) + ospf = ospf_lookup (); - if (ospf != NULL) - { - /* Router-ID must be configured. */ - if (ospf->router_id.s_addr == 0) - return; - - /* 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); - } - - /* 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); - } - } + /* Router-ID must be configured. */ + if (ospf->router_id.s_addr == 0) + return; + + /* Run each netowrk for this 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_interface (&rn->p, area, ifp); + } } void -- cgit v1.2.1