diff options
author | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2009-08-07 10:48:15 +0000 |
---|---|---|
committer | David Lamparter <equinox@diac24.net> | 2010-02-04 01:55:32 +0100 |
commit | 4f559f6cd3a0377391a32a307729479e7081cb16 (patch) | |
tree | 21c61571293004c87570f593aeaa9e64af6d57c6 /ospfd/ospfd.c | |
parent | 90fa62d5fd1055bde66bd3a0b049fa13e2f54649 (diff) | |
download | quagga-4f559f6cd3a0377391a32a307729479e7081cb16.tar.bz2 quagga-4f559f6cd3a0377391a32a307729479e7081cb16.tar.xz |
ospfd: Impl. command ip ospf area
Use with interface command:
interface ppp0
ip ospf area 0.0.0.0
This will enable OSPF on ppp0 with area 0.0.0.0
Remove with "no ip ospf area"
Diffstat (limited to 'ospfd/ospfd.c')
-rw-r--r-- | ospfd/ospfd.c | 243 |
1 files changed, 181 insertions, 62 deletions
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index a7553e73..f2c2c26c 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -701,6 +701,67 @@ ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi) listnode_add (area->oiflist, oi); } +void add_ospf_interface(struct interface *ifp, struct ospf_area *area, + struct connected *co) +{ + 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 update_redistributed(struct ospf *ospf, int add_to_ospf) +{ + struct route_node *rn; + struct external_info *ei; + + if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) + if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) + for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); + rn; rn = route_next (rn)) + if ((ei = rn->info) != NULL) + if (add_to_ospf) + { + if (ospf_external_info_find_lsa (ospf, &ei->p)) + if (!ospf_distribute_check_connected (ospf, ei)) + ospf_external_lsa_flush (ospf, ei->type, &ei->p, + ei->ifindex /*, ei->nexthop */); + } + else + { + if (!ospf_external_info_find_lsa (ospf, &ei->p)) + if (ospf_distribute_check_connected (ospf, ei)) + ospf_external_lsa_originate (ospf, ei); + } +} + void ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi) { @@ -754,16 +815,7 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p, ospf_network_run ((struct prefix *)p, area); /* Update connected redistribute. */ - if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) - if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) - for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); - rn; rn = route_next (rn)) - if ((ei = rn->info) != NULL) - if (ospf_external_info_find_lsa (ospf, &ei->p)) - if (!ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_flush (ospf, ei->type, &ei->p, - ei->ifindex /*, ei->nexthop */); - + update_redistributed(ospf, 1); /* interfaces possibly added */ ospf_area_check_free (ospf, area_id); return 1; @@ -795,12 +847,17 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, /* Find interfaces that not configured already. */ for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) { + struct ospf_if_params *params; int found = 0; struct connected *co = oi->connected; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - continue; - + continue; + + params = IF_DEF_PARAMS (oi->ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) + continue; + for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) { if (rn->info == NULL) @@ -819,18 +876,103 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, } /* Update connected redistribute. */ - if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) - if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) - for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); - rn; rn = route_next (rn)) - if ((ei = rn->info) != NULL) - if (!ospf_external_info_find_lsa (ospf, &ei->p)) - if (ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_originate (ospf, ei); + update_redistributed(ospf, 0); /* interfaces possibly removed */ + return 1; +} + +int +ospf_interface_set (struct interface *ifp) +{ + struct ospf_area *area; + struct route_node *rn; + struct external_info *ei; + struct listnode *cnode; + struct connected *co; + struct ospf *ospf; + struct ospf_if_params *params; + struct in_addr area_id; + int ret = OSPF_AREA_ID_FORMAT_ADDRESS; + + if ((ospf = ospf_lookup ()) == NULL) + return 1; /* Ospf not ready yet */ + + params = IF_DEF_PARAMS (ifp); + area_id = params->if_area; + + area = ospf_area_get (ospf, area_id, ret); + for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co)) + { + struct ospf_interface *oi; + + if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY)) + continue; + + oi = ospf_if_table_lookup(ifp, co->address); + if (oi) + { /* Just adjust area for existing interface */ + ospf_area_del_if (oi->area, oi); + oi->area = area; + ospf_area_add_if (oi->area, oi); + } + else + { + add_ospf_interface(ifp, area, co); + } + } + + /* Update connected redistribute. */ + update_redistributed(ospf, 1); /* interface possibly added */ + ospf_area_check_free (ospf, area_id); + + return 1; +} + +int +ospf_interface_unset (struct interface *ifp) +{ + struct route_node *rn_oi, *rn; + struct ospf *ospf; + + if ((ospf = ospf_lookup ()) == NULL) + return 1; /* Ospf not ready yet */ + + /* Find interfaces that may need to be removed. */ + for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next (rn_oi)) + { + struct ospf_interface *oi; + struct connected *co; + int found = 0; + + if ( (oi = rn_oi->info) == NULL) + continue; + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + continue; + co = oi->connected; + + 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_redistributed(ospf, 0); /* interfaces possibly removed */ return 1; } + /* Check whether interface matches given network * returns: 1, true. 0, false */ @@ -862,39 +1004,9 @@ ospf_network_run_interface (struct prefix *p, struct ospf_area *area, if (p->family == co->address->family && ! ospf_if_table_lookup(ifp, co->address) && 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); - } + { + add_ospf_interface(ifp, area, co); + } } } @@ -953,15 +1065,22 @@ ospf_if_update (struct ospf *ospf, struct interface *ifp) /* OSPF must be on and Router-ID must be configured. */ if (!ospf || 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); - } + + if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS (ifp), if_area)) + { + ospf_interface_set (ifp); + } + else + { + /* 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 |