diff options
Diffstat (limited to 'ospfd')
-rw-r--r-- | ospfd/Makefile.am | 2 | ||||
-rw-r--r-- | ospfd/ospf_abr.c | 45 | ||||
-rw-r--r-- | ospfd/ospf_apiserver.c | 2 | ||||
-rw-r--r-- | ospfd/ospf_ase.c | 104 | ||||
-rw-r--r-- | ospfd/ospf_ase.h | 2 | ||||
-rw-r--r-- | ospfd/ospf_dump.c | 4 | ||||
-rw-r--r-- | ospfd/ospf_flood.c | 36 | ||||
-rw-r--r-- | ospfd/ospf_interface.c | 54 | ||||
-rw-r--r-- | ospfd/ospf_interface.h | 13 | ||||
-rw-r--r-- | ospfd/ospf_ism.c | 48 | ||||
-rw-r--r-- | ospfd/ospf_lsa.c | 86 | ||||
-rw-r--r-- | ospfd/ospf_main.c | 20 | ||||
-rw-r--r-- | ospfd/ospf_neighbor.c | 245 | ||||
-rw-r--r-- | ospfd/ospf_neighbor.h | 13 | ||||
-rw-r--r-- | ospfd/ospf_nsm.c | 30 | ||||
-rw-r--r-- | ospfd/ospf_nsm.h | 2 | ||||
-rw-r--r-- | ospfd/ospf_opaque.c | 21 | ||||
-rw-r--r-- | ospfd/ospf_packet.c | 272 | ||||
-rw-r--r-- | ospfd/ospf_packet.h | 1 | ||||
-rw-r--r-- | ospfd/ospf_route.c | 67 | ||||
-rw-r--r-- | ospfd/ospf_route.h | 6 | ||||
-rw-r--r-- | ospfd/ospf_snmp.c | 21 | ||||
-rw-r--r-- | ospfd/ospf_spf.c | 163 | ||||
-rw-r--r-- | ospfd/ospf_vty.c | 376 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 26 | ||||
-rw-r--r-- | ospfd/ospf_zebra.h | 2 | ||||
-rw-r--r-- | ospfd/ospfd.c | 301 | ||||
-rw-r--r-- | ospfd/ospfd.h | 13 |
28 files changed, 1108 insertions, 867 deletions
diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 2e4d5c8e..bed90d7b 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in. INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib @SNMP_INCLUDES@ -DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\" +DEFS = @DEFS@ $(LOCAL_OPTS) INSTALL_SDATA=@INSTALL@ -m 600 lib_LTLIBRARIES = libospf.la diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c index 7e32195b..def55f10 100644 --- a/ospfd/ospf_abr.c +++ b/ospfd/ospf_abr.c @@ -614,15 +614,6 @@ set_metric (struct ospf_lsa *lsa, u_int32_t metric) memcpy(header->metric, mp, 3); } -static int -ospf_abr_check_nssa_range (struct prefix_ipv4 *p, u_int32_t cost, - struct ospf_area *area) -{ - /* The Type-7 is tested against the aggregated prefix and forwarded - for lsa installation and flooding */ - return 0; -} - /* ospf_abr_translate_nssa */ static int ospf_abr_translate_nssa (struct ospf_area *area, struct ospf_lsa *lsa) @@ -1578,42 +1569,6 @@ ospf_abr_send_nssa_aggregates (struct ospf *ospf) /* temporarily turned off */ } static void -ospf_abr_announce_nssa_defaults (struct ospf *ospf) /* By ABR-Translator */ -{ - struct listnode *node; - struct ospf_area *area; - - if (! IS_OSPF_ABR (ospf)) - return; - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_announce_stub_defaults(): Start"); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_announce_nssa_defaults(): looking at area %s", - inet_ntoa (area->area_id)); - - if (area->external_routing != OSPF_AREA_NSSA) - continue; - - if (OSPF_IS_AREA_BACKBONE (area)) - continue; /* Sanity Check */ - - /* if (!TranslatorRole continue V 1.0 look for "always" conf */ - if (area->NSSATranslatorState) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_announce_nssa_defaults(): " - "announcing 0.0.0.0/0 to this nssa"); - /* ospf_abr_announce_nssa_asbr_to_as (&p, area->default_cost, area); */ - /*ospf_abr_announce_network_to_area (&p, area->default_cost, area);*/ - } - } -} - -static void ospf_abr_announce_stub_defaults (struct ospf *ospf) { struct listnode *node; diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index 15fd2e5f..bd5c026c 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -2470,7 +2470,7 @@ ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr) ifaddr = nbr->oi->address->u.prefix4; } - nbraddr = nbr->address.u.prefix4; + nbraddr = nbr->src; msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state); if (!msg) diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index 5d0cae42..c06f0178 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -31,6 +31,7 @@ #include "table.h" #include "vty.h" #include "log.h" +#include "workqueue.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -130,18 +131,6 @@ ospf_find_asbr_route_through_area (struct route_table *rtrs, return NULL; } -static void -ospf_ase_complete_direct_routes (struct ospf_route *ro, struct in_addr nexthop) -{ - struct listnode *node; - struct ospf_path *op; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (ro->paths, node, op)) - if (op->nexthop.s_addr == 0) - op->nexthop.s_addr = nexthop.s_addr; -} - static int ospf_ase_forward_address_check (struct ospf *ospf, struct in_addr fwd_addr) { @@ -284,8 +273,8 @@ ospf_ase_calculate_new_route (struct ospf_lsa *lsa, #define OSPF_ASE_CALC_INTERVAL 1 -int -ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) +static int +ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa *lsa) { u_int32_t metric; struct as_external_lsa *al; @@ -451,8 +440,8 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) /* if there is a Intra/Inter area route to the N do not install external route */ - if (rn = route_node_lookup (ospf->new_table, - (struct prefix *) &p)) + if ((rn = route_node_lookup (ospf->new_table, + (struct prefix *) &p))) { route_unlock_node(rn); if (rn->info == NULL) @@ -463,8 +452,8 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) } /* Find a route to the same dest */ /* If there is no route, create new one. */ - if (rn = route_node_lookup (ospf->new_external_route, - (struct prefix *) &p)) + if ((rn = route_node_lookup (ospf->new_external_route, + (struct prefix *) &p))) route_unlock_node(rn); if (!rn || (or = rn->info) == NULL) @@ -475,8 +464,6 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) ospf_route_add (ospf->new_external_route, &p, new, asbr_route); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr); return 0; } else @@ -513,8 +500,7 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) if (IS_DEBUG_OSPF (lsa, LSA)) zlog_debug ("Route[External]: New route is better"); ospf_route_subst (rn, new, asbr_route); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr); + or = new; new = NULL; } @@ -531,8 +517,6 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) if (IS_DEBUG_OSPF (lsa, LSA)) zlog_debug ("Route[External]: Routes are equal"); ospf_route_copy_nexthops (or, asbr_route->paths); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (or, al->e[0].fwd_addr); } } /* Make sure setting newly calculated ASBR route.*/ @@ -629,6 +613,50 @@ ospf_ase_compare_tables (struct route_table *new_external_route, return 0; } +static int ospf_ase_calculate_timer (struct thread *); + +static void ospf_ase_calc_completion (struct work_queue *wq) +{ + struct ospf *ospf = wq->spec.data; + + /* Compare old and new external routing table and install the + difference info zebra/kernel */ + ospf_ase_compare_tables (ospf->new_external_route, + ospf->old_external_route); + + /* Delete old external routing table */ + ospf_route_table_free (ospf->old_external_route); + ospf->old_external_route = ospf->new_external_route; + ospf->new_external_route = route_table_init (); + + /* another timer fired since, so another run might be needed */ + if (ospf->ase_calc && !ospf->t_ase_calc) + ospf->t_ase_calc = thread_add_timer (master, ospf_ase_calculate_timer, + ospf, 0); +} + +static wq_item_status +ospf_ase_calc_process (struct work_queue *wq, void *data) +{ + struct ospf_lsa *lsa = data; + ospf_ase_calculate_route (wq->spec.data, lsa); + ospf_lsa_unlock (&lsa); + return WQ_SUCCESS; +} + +static void +ospf_ase_calc_queue_init (struct ospf *ospf) +{ + ospf->ase_calc_queue = work_queue_new (master, "ase_calc_queue"); + + ospf->ase_calc_queue->spec.workfunc = &ospf_ase_calc_process; + ospf->ase_calc_queue->spec.completion_func = &ospf_ase_calc_completion; + + ospf->ase_calc_queue->spec.data = ospf; + ospf->ase_calc_queue->spec.max_retries = 0; + ospf->ase_calc_queue->spec.hold = 0; +} + static int ospf_ase_calculate_timer (struct thread *t) { @@ -645,9 +673,12 @@ ospf_ase_calculate_timer (struct thread *t) { ospf->ase_calc = 0; + if (!ospf->ase_calc_queue) + ospf_ase_calc_queue_init (ospf); + /* Calculate external route for each AS-external-LSA */ LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - ospf_ase_calculate_route (ospf, lsa); + work_queue_add (ospf->ase_calc_queue, ospf_lsa_lock (lsa)); /* This version simple adds to the table all NSSA areas */ if (ospf->anyNSSA) @@ -659,39 +690,22 @@ ospf_ase_calculate_timer (struct thread *t) if (area->external_routing == OSPF_AREA_NSSA) LSDB_LOOP (NSSA_LSDB (area), rn, lsa) - ospf_ase_calculate_route (ospf, lsa); + work_queue_add (ospf->ase_calc_queue, ospf_lsa_lock (lsa)); } /* kevinm: And add the NSSA routes in ospf_top */ LSDB_LOOP (NSSA_LSDB (ospf),rn,lsa) - ospf_ase_calculate_route(ospf,lsa); - - /* Compare old and new external routing table and install the - difference info zebra/kernel */ - ospf_ase_compare_tables (ospf->new_external_route, - ospf->old_external_route); - - /* Delete old external routing table */ - ospf_route_table_free (ospf->old_external_route); - ospf->old_external_route = ospf->new_external_route; - ospf->new_external_route = route_table_init (); + work_queue_add (ospf->ase_calc_queue, ospf_lsa_lock (lsa)); } return 0; } void -ospf_ase_calculate_schedule (struct ospf *ospf) +ospf_ase_calculate_timer_add (struct ospf *ospf) { if (ospf == NULL) return; ospf->ase_calc = 1; -} - -void -ospf_ase_calculate_timer_add (struct ospf *ospf) -{ - if (ospf == NULL) - return; if (! ospf->t_ase_calc) ospf->t_ase_calc = thread_add_timer (master, ospf_ase_calculate_timer, diff --git a/ospfd/ospf_ase.h b/ospfd/ospf_ase.h index e6a1b2fb..646a38c0 100644 --- a/ospfd/ospf_ase.h +++ b/ospfd/ospf_ase.h @@ -34,8 +34,6 @@ extern struct ospf_route *ospf_find_asbr_route_through_area (struct struct ospf_area *); -extern int ospf_ase_calculate_route (struct ospf *, struct ospf_lsa *); -extern void ospf_ase_calculate_schedule (struct ospf *); extern void ospf_ase_calculate_timer_add (struct ospf *); extern void ospf_ase_external_lsas_finish (struct route_table *); diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index e65b2e33..4786a87c 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -215,9 +215,9 @@ ospf_nbr_state_message (struct ospf_neighbor *nbr, char *buf, size_t size) int state; struct ospf_interface *oi = nbr->oi; - if (IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4)) + if (IPV4_ADDR_SAME (&DR (oi), &nbr->src)) state = ISM_DR; - else if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4)) + else if (IPV4_ADDR_SAME (&BDR (oi), &nbr->src)) state = ISM_Backup; else state = ISM_DROther; diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 41661da2..5ebf4f2f 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -346,7 +346,7 @@ ospf_flood_through_interface (struct ospf_interface *oi, struct ospf_lsa *lsa) { struct ospf_neighbor *onbr; - struct route_node *rn; + struct listnode *node; int retx_flag; if (IS_DEBUG_OSPF_EVENT) @@ -364,14 +364,10 @@ ospf_flood_through_interface (struct ospf_interface *oi, /* Each of the neighbors attached to this interface are examined, to determine whether they must receive the new LSA. The following steps are executed for each neighbor: */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, onbr)) { struct ospf_lsa *ls_req; - - if (rn->info == NULL) - continue; - onbr = rn->info; if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_flood_through_interface(): considering nbr %s (%s)", inet_ntoa (onbr->router_id), @@ -543,13 +539,12 @@ ospf_flood_through_interface (struct ospf_interface *oi, addresses. */ if (oi->type == OSPF_IFTYPE_NBMA) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange) - ospf_ls_upd_send_lsa (nbr, lsa, OSPF_SEND_PACKET_DIRECT); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange) + ospf_ls_upd_send_lsa (nbr, lsa, OSPF_SEND_PACKET_DIRECT); } else ospf_ls_upd_send_lsa (oi->nbr_self, lsa, OSPF_SEND_PACKET_INDIRECT); @@ -934,21 +929,20 @@ static void ospf_ls_retransmit_delete_nbr_if (struct ospf_interface *oi, struct ospf_lsa *lsa) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; struct ospf_lsa *lsr; if (ospf_if_is_enable (oi)) - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) /* If LSA find in LS-retransmit list, then remove it. */ - if ((nbr = rn->info) != NULL) - { - lsr = ospf_ls_retransmit_lookup (nbr, lsa); - - /* If LSA find in ls-retransmit list, remove it. */ - if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum) - ospf_ls_retransmit_delete (nbr, lsr); - } + { + lsr = ospf_ls_retransmit_lookup (nbr, lsa); + + /* If LSA find in ls-retransmit list, remove it. */ + if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum) + ospf_ls_retransmit_delete (nbr, lsr); + } } void diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index afe3acf1..33a83b4d 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -211,7 +211,9 @@ ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p) } else return oi; - + + ospf_lsa_pos_set(-1,-1, oi); /* delete position in router LSA */ + /* Set zebra interface pointer. */ oi->ifp = ifp; oi->address = p; @@ -223,7 +225,7 @@ ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p) oi->network_lsa_self = NULL; /* Initialize neighbor list. */ - oi->nbrs = route_table_init (); + oi->nbrs = list_new (); /* Initialize static neighbor list. */ oi->nbr_nbma = list_new (); @@ -258,7 +260,6 @@ ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p) void ospf_if_cleanup (struct ospf_interface *oi) { - struct route_node *rn; struct listnode *node, *nnode; struct ospf_neighbor *nbr; struct ospf_nbr_nbma *nbr_nbma; @@ -282,10 +283,9 @@ ospf_if_cleanup (struct ospf_interface *oi) } /* send Neighbor event KillNbr to all associated neighbors. */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr != oi->nbr_self) - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr); + for (ALL_LIST_ELEMENTS (oi->nbrs, node, nnode, nbr)) + if (nbr != oi->nbr_self) + OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr); /* Cleanup Link State Acknowlegdment list. */ for (ALL_LIST_ELEMENTS (oi->ls_ack, node, nnode, lsa)) @@ -321,7 +321,7 @@ ospf_if_free (struct ospf_interface *oi) /* Free Pseudo Neighbour */ ospf_nbr_delete (oi->nbr_self); - route_table_finish (oi->nbrs); + list_free (oi->nbrs); route_table_finish (oi->ls_upd_queue); /* Free any lists that should be freed */ @@ -397,6 +397,29 @@ ospf_if_exists (struct ospf_interface *oic) return NULL; } +/* Lookup OSPF interface by router LSA posistion */ +struct ospf_interface * +ospf_if_lookup_by_lsa_pos (struct ospf_area *area, int lsa_pos) +{ + struct listnode *node; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) + { + if (lsa_pos >= oi->lsa_pos_beg && lsa_pos < oi->lsa_pos_end) + return oi; + } + return NULL; +} + +/* Set OSPF interface position in router LSA */ +void +ospf_lsa_pos_set(int pos_beg, int pos_end, struct ospf_interface *oi) +{ + oi->lsa_pos_beg = pos_beg; + oi->lsa_pos_end = pos_end; +} + struct ospf_interface * ospf_if_lookup_by_local_addr (struct ospf *ospf, struct interface *ifp, struct in_addr address) @@ -479,6 +502,20 @@ ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src, return match; } + +struct ospf_interface * +ospf_if_lookup_by_ifindex(struct ospf_area *area, unsigned int ifindex) +{ + struct listnode *node; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) + { + if (oi->ifp->ifindex == ifindex) + return oi; + } + return NULL; +} void ospf_if_stream_set (struct ospf_interface *oi) @@ -803,6 +840,7 @@ ospf_if_down (struct ospf_interface *oi) return 0; OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown); + ospf_lsa_pos_set(-1, -1, oi); /* delete position in router LSA */ /* Shutdown packet reception and sending */ ospf_if_stream_unset (oi); diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index ab0b7580..82bf31a5 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -47,6 +47,7 @@ struct ospf_if_params DECLARE_IF_PARAM (u_int32_t, retransmit_interval); /* Retransmission Interval */ DECLARE_IF_PARAM (u_char, passive_interface); /* OSPF Interface is passive: no sending or receiving (no need to join multicast groups) */ DECLARE_IF_PARAM (u_char, priority); /* OSPF Interface priority */ + DECLARE_IF_PARAM (struct in_addr, if_area); /* Enable OSPF on this interface with area if_area */ DECLARE_IF_PARAM (u_char, type); /* type of interface */ #define OSPF_IF_ACTIVE 0 #define OSPF_IF_PASSIVE 1 @@ -124,6 +125,10 @@ struct ospf_interface /* OSPF Area. */ struct ospf_area *area; +/* Position range in Router LSA */ + int lsa_pos_beg; /* inclusive, >= */ + int lsa_pos_end; /* exclusive, < */ + /* Interface data from zebra. */ struct interface *ifp; struct ospf_vl_data *vl_data; /* Data for Virtual Link */ @@ -171,7 +176,7 @@ struct ospf_interface u_int32_t output_cost; /* Acutual Interface Output Cost */ /* Neighbor information. */ - struct route_table *nbrs; /* OSPF Neighbor List */ + struct list *nbrs; /* OSPF Neighbor List */ struct ospf_neighbor *nbr_self; /* Neighbor Self */ #define DR(I) ((I)->nbr_self->d_router) #define BDR(I) ((I)->nbr_self->bd_router) @@ -242,6 +247,9 @@ extern int ospf_if_down (struct ospf_interface *); extern int ospf_if_is_up (struct ospf_interface *); extern struct ospf_interface *ospf_if_exists (struct ospf_interface *); +extern struct ospf_interface *ospf_if_lookup_by_lsa_pos (struct ospf_area *, + int); +extern void ospf_lsa_pos_set(int, int, struct ospf_interface *); extern struct ospf_interface *ospf_if_lookup_by_local_addr (struct ospf *, struct interface *, @@ -256,7 +264,8 @@ extern struct ospf_interface *ospf_if_lookup_recv_if (struct ospf *, struct interface *); extern struct ospf_interface *ospf_if_is_configured (struct ospf *, struct in_addr *); - +extern struct ospf_interface *ospf_if_lookup_by_ifindex(struct ospf_area *, + unsigned int); extern struct ospf_if_params *ospf_lookup_if_params (struct interface *, struct in_addr); extern struct ospf_if_params *ospf_get_if_params (struct interface *, diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c index 18402836..2186e894 100644 --- a/ospfd/ospf_ism.c +++ b/ospfd/ospf_ism.c @@ -88,7 +88,7 @@ ospf_elect_dr (struct ospf_interface *oi, struct list *el_list) listnode_add (dr_list, nbr); /* Preserve neighbor BDR. */ - if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4)) + if (IPV4_ADDR_SAME (&BDR (oi), &nbr->src)) bdr = nbr; } @@ -100,7 +100,7 @@ ospf_elect_dr (struct ospf_interface *oi, struct list *el_list) /* Set DR to interface. */ if (dr) - DR (oi) = dr->address.u.prefix4; + DR (oi) = dr->src; else DR (oi).s_addr = 0; @@ -141,7 +141,7 @@ ospf_elect_bdr (struct ospf_interface *oi, struct list *el_list) /* Set BDR to interface. */ if (bdr) - BDR (oi) = bdr->address.u.prefix4; + BDR (oi) = bdr->src; else BDR (oi).s_addr = 0; @@ -163,38 +163,36 @@ ospf_ism_state (struct ospf_interface *oi) } static void -ospf_dr_eligible_routers (struct route_table *nbrs, struct list *el_list) +ospf_dr_eligible_routers (struct list *nbrs, struct list *el_list) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore 0.0.0.0 node*/ - if (nbr->router_id.s_addr != 0) - /* Is neighbor eligible? */ - if (nbr->priority > 0) - /* Is neighbor upper 2-Way? */ - if (nbr->state >= NSM_TwoWay) - listnode_add (el_list, nbr); + for (ALL_LIST_ELEMENTS_RO (nbrs, node, nbr)) + /* Ignore 0.0.0.0 node*/ + if (nbr->router_id.s_addr != 0) + /* Is neighbor eligible? */ + if (nbr->priority > 0) + /* Is neighbor upper 2-Way? */ + if (nbr->state >= NSM_TwoWay) + listnode_add (el_list, nbr); } /* Generate AdjOK? NSM event. */ static void -ospf_dr_change (struct ospf *ospf, struct route_table *nbrs) +ospf_dr_change (struct ospf *ospf, struct list *nbrs) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore 0.0.0.0 node*/ - if (nbr->router_id.s_addr != 0) - /* Is neighbor upper 2-Way? */ - if (nbr->state >= NSM_TwoWay) - /* Ignore myself. */ - if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf->router_id)) - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_AdjOK); + for (ALL_LIST_ELEMENTS_RO (nbrs, node, nbr)) + /* Ignore 0.0.0.0 node*/ + if (nbr->router_id.s_addr != 0) + /* Is neighbor upper 2-Way? */ + if (nbr->state >= NSM_TwoWay) + /* Ignore myself. */ + if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf->router_id)) + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_AdjOK); } static int diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index e708d5e2..25bd754d 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -436,17 +436,13 @@ struct ospf_neighbor * ospf_nbr_lookup_ptop (struct ospf_interface *oi) { struct ospf_neighbor *nbr = NULL; - struct route_node *rn; + struct listnode *node; /* Search neighbor, there must be one of two nbrs. */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (nbr->state == NSM_Full) - { - route_unlock_node (rn); - break; - } + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) + if (nbr->state == NSM_Full) + break; /* PtoP link must have only 1 neighbor. */ if (ospf_nbr_count (oi, 0) > 1) @@ -531,9 +527,16 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi) { /* For unnumbered point-to-point networks, the Link Data field should specify the interface's MIB-II ifIndex value. */ - links += link_info_set (s, nbr->router_id, oi->address->u.prefix4, + if (CHECK_FLAG(oi->ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + id.s_addr = htonl(oi->ifp->ifindex); + else + id = oi->address->u.prefix4; + + links += link_info_set (s, nbr->router_id, id, LSA_LINK_TYPE_POINTOPOINT, 0, cost); } + if (CHECK_FLAG(oi->ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + return links; /* Regardless of the state of the neighboring router, we must add a Type 3 link (stub network). @@ -623,7 +626,7 @@ static int lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) { int links = 0; - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr = NULL; struct in_addr id, mask; u_int16_t cost = ospf_link_cost (oi); @@ -636,20 +639,18 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) zlog_debug ("PointToMultipoint: running ptomultip_set"); /* Search neighbor, */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore myself. */ - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (nbr->state == NSM_Full) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + /* Ignore myself. */ + if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) + if (nbr->state == NSM_Full) + { + links += link_info_set (s, nbr->router_id, oi->address->u.prefix4, + LSA_LINK_TYPE_POINTOPOINT, 0, cost); + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + zlog_debug ("PointToMultipoint: set link to %s", + inet_ntoa(oi->address->u.prefix4)); + } - { - links += link_info_set (s, nbr->router_id, oi->address->u.prefix4, - LSA_LINK_TYPE_POINTOPOINT, 0, cost); - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("PointToMultipoint: set link to %s", - inet_ntoa(oi->address->u.prefix4)); - } - return links; } @@ -657,9 +658,11 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) static int router_lsa_link_set (struct stream *s, struct ospf_area *area) { + struct ospf_host_route *host; + struct in_addr host_mask = {~0}; /* All ones */ struct listnode *node; struct ospf_interface *oi; - int links = 0; + int links = 0, old_links; for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) { @@ -670,6 +673,7 @@ router_lsa_link_set (struct stream *s, struct ospf_area *area) { if (oi->state != ISM_Down) { + old_links = links; /* Describe each link. */ switch (oi->type) { @@ -691,10 +695,14 @@ router_lsa_link_set (struct stream *s, struct ospf_area *area) case OSPF_IFTYPE_LOOPBACK: links += lsa_link_loopback_set (s, oi); } + ospf_lsa_pos_set(old_links, links, oi); } } } - + for (ALL_LIST_ELEMENTS_RO (area->ospf->hostlist, node, host)) + if (host->area == NULL || host->area == area) + links += link_info_set (s, host->host_addr, host_mask, + LSA_LINK_TYPE_STUB, 0, host->cost); return links; } @@ -1025,7 +1033,7 @@ static void ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi) { struct in_addr mask; - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; masklen2ip (oi->address->prefixlen, &mask); @@ -1036,10 +1044,9 @@ ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi) its OSPF Router ID. The Designated Router includes itself in this list. RFC2328, Section 12.4.2 */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr->state == NSM_Full || nbr == oi->nbr_self) - stream_put_ipv4 (s, nbr->router_id.s_addr); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (nbr->state == NSM_Full || nbr == oi->nbr_self) + stream_put_ipv4 (s, nbr->router_id.s_addr); } static struct ospf_lsa * @@ -2839,19 +2846,14 @@ ospf_check_nbr_status (struct ospf *ospf) struct listnode *node, *nnode; struct ospf_interface *oi; - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) + for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) { - struct route_node *rn; struct ospf_neighbor *nbr; if (ospf_if_is_enable (oi)) - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading) - { - route_unlock_node (rn); - return 0; - } + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nnode, nbr)) + if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading) + return 0; } return 1; @@ -2912,6 +2914,10 @@ ospf_maxage_lsa_remover (struct thread *thread) continue; } + /* TODO: maybe convert this function to a work-queue */ + if (thread_should_yield (thread)) + OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 0); + /* Remove LSA from the LSDB */ if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF)) if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 8b9a3458..0e9e182a 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -38,6 +38,7 @@ #include "memory.h" #include "privs.h" #include "sigevent.h" +#include "paths.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -72,12 +73,13 @@ struct zebra_privs_t ospfd_privs = }; /* Configuration filename and directory. */ -char config_default[] = SYSCONFDIR OSPF_DEFAULT_CONFIG; +char config_default[MAXPATHLEN]; /* OSPFd options. */ struct option longopts[] = { { "daemon", no_argument, NULL, 'd'}, + { "namespace", required_argument, NULL, 'N'}, { "config_file", required_argument, NULL, 'f'}, { "pid_file", required_argument, NULL, 'i'}, { "dryrun", no_argument, NULL, 'C'}, @@ -96,8 +98,11 @@ struct option longopts[] = /* Master of threads. */ struct thread_master *master; +/* pid_file default value */ +static char pid_file_default[MAXPATHLEN]; + /* Process ID saved for use by init system */ -const char *pid_file = PATH_OSPFD_PID; +const char *pid_file = pid_file_default; #ifdef SUPPORT_OSPF_API extern int ospf_apiserver_enable; @@ -114,6 +119,7 @@ usage (char *progname, int status) printf ("Usage : %s [OPTION...]\n\ Daemon which manages OSPF.\n\n\ -d, --daemon Runs in daemon mode\n\ +-N, --namespace Insert argument into all paths\n\ -f, --config_file Set configuration file name\n\ -i, --pid_file Set process identifier file name\n\ -A, --vty_addr Set vty's bind address\n\ @@ -214,7 +220,7 @@ main (int argc, char **argv) { int opt; - opt = getopt_long (argc, argv, "df:i:hA:P:u:g:avC", longopts, 0); + opt = getopt_long (argc, argv, "dN:f:i:hA:P:u:g:avC", longopts, 0); if (opt == EOF) break; @@ -226,6 +232,9 @@ main (int argc, char **argv) case 'd': daemon_mode = 1; break; + case 'N': + path_set_namespace (optarg); + break; case 'f': config_file = optarg; break; @@ -274,6 +283,9 @@ main (int argc, char **argv) } } + strcpy (config_default, path_config (OSPF_CONFIG_NAME)); + strcpy (pid_file_default, path_state (OSPF_PID_NAME)); + /* Initializations. */ master = om->master; @@ -324,7 +336,7 @@ main (int argc, char **argv) pid_output (pid_file); /* Create VTY socket */ - vty_serv_sock (vty_addr, vty_port, OSPF_VTYSH_PATH); + vty_serv_sock (vty_addr, vty_port, path_state (OSPF_VTY_NAME)); /* Print banner. */ zlog_notice ("OSPFd %s starting: vty@%d", QUAGGA_VERSION, vty_port); diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c index 967ca15d..e55a1903 100644 --- a/ospfd/ospf_neighbor.c +++ b/ospfd/ospf_neighbor.c @@ -43,26 +43,6 @@ #include "ospfd/ospf_flood.h" #include "ospfd/ospf_dump.h" -/* Fill in the the 'key' as appropriate to retrieve the entry for nbr - * from the ospf_interface's nbrs table. Indexed by interface address - * for all cases except Virtual-link interfaces, where neighbours are - * indexed by router-ID instead. - */ -static void -ospf_nbr_key (struct ospf_interface *oi, struct ospf_neighbor *nbr, - struct prefix *key) -{ - key->family = AF_INET; - key->prefixlen = IPV4_MAX_BITLEN; - - /* vlinks are indexed by router-id */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - key->u.prefix4 = nbr->router_id; - else - key->u.prefix4 = nbr->src; - return; -} - struct ospf_neighbor * ospf_nbr_new (struct ospf_interface *oi) { @@ -143,44 +123,43 @@ ospf_nbr_free (struct ospf_neighbor *nbr) XFREE (MTYPE_OSPF_NEIGHBOR, nbr); } +/* lookup nbr by address - use this only if you know you must + * otherwise use the ospf_nbr_lookup() wrapper, which deals + * with virtual link and PointToPoint neighbours + */ +struct ospf_neighbor * +ospf_nbr_lookup_by_addr (struct list *nbrs, + struct in_addr *addr) +{ + struct listnode *node; + struct ospf_neighbor *nbr; -/* Delete specified OSPF neighbor from interface. */ -void -ospf_nbr_delete (struct ospf_neighbor *nbr) + for (ALL_LIST_ELEMENTS_RO (nbrs, node, nbr)) + if (IPV4_ADDR_SAME (&nbr->src, addr)) + return nbr; + + return NULL; +} + +struct ospf_neighbor * +ospf_nbr_lookup_by_routerid (struct list *nbrs, + struct in_addr *id) { - struct ospf_interface *oi; - struct route_node *rn; - struct prefix p; + struct listnode *node; + struct ospf_neighbor *nbr; - oi = nbr->oi; - - /* get appropriate prefix 'key' */ - ospf_nbr_key (oi, nbr, &p); + for (ALL_LIST_ELEMENTS_RO (nbrs, node, nbr)) + if (IPV4_ADDR_SAME (&nbr->router_id, id)) + return nbr; - rn = route_node_lookup (oi->nbrs, &p); - if (rn) - { - /* If lookup for a NBR succeeds, the leaf route_node could - * only exist because there is (or was) a nbr there. - * If the nbr was deleted, the leaf route_node should have - * lost its last refcount too, and be deleted. - * Therefore a looked-up leaf route_node in nbrs table - * should never have NULL info. - */ - assert (rn->info); - - if (rn->info) - { - rn->info = NULL; - route_unlock_node (rn); - } - else - zlog_info ("Can't find neighbor %s in the interface %s", - inet_ntoa (nbr->src), IF_NAME (oi)); - - route_unlock_node (rn); - } + return NULL; +} +/* Delete specified OSPF neighbor from interface. */ +void +ospf_nbr_delete (struct ospf_neighbor *nbr) +{ + listnode_delete(nbr->oi->nbrs, nbr); /* Free ospf_neighbor structure. */ ospf_nbr_free (nbr); } @@ -206,11 +185,9 @@ ospf_nbr_bidirectional (struct in_addr *router_id, void ospf_nbr_add_self (struct ospf_interface *oi) { - struct prefix p; - struct route_node *rn; + struct ospf_neighbor *nbr; /* Initial state */ - oi->nbr_self->address = *oi->address; oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority); oi->nbr_self->router_id = oi->ospf->router_id; oi->nbr_self->src = oi->address->u.prefix4; @@ -229,19 +206,23 @@ ospf_nbr_add_self (struct ospf_interface *oi) SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); break; } - - /* Add nbr_self to nbrs table */ - ospf_nbr_key (oi, oi->nbr_self, &p); - - rn = route_node_get (oi->nbrs, &p); - if (rn->info) + + /* Sanity check, should not be needed */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK || + oi->type == OSPF_IFTYPE_POINTOPOINT) + nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &oi->nbr_self->router_id); + else + nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &oi->nbr_self->src); + if (nbr) { - /* There is already pseudo neighbor. */ - assert (oi->nbr_self == rn->info); - route_unlock_node (rn); + assert (oi->nbr_self == nbr); + zlog_info("Self neighbor already added for ospf I/F:%s", + oi->ifp->name); + return; } - else - rn->info = oi->nbr_self; + + /* Add nbr_self to nbrs table */ + listnode_add(oi->nbrs, oi->nbr_self); } /* Get neighbor count by status. @@ -250,14 +231,13 @@ int ospf_nbr_count (struct ospf_interface *oi, int state) { struct ospf_neighbor *nbr; - struct route_node *rn; + struct listnode *node; int count = 0; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (state == 0 || nbr->state == state) - count++; + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) + if (state == 0 || nbr->state == state) + count++; return count; } @@ -267,80 +247,24 @@ int ospf_nbr_count_opaque_capable (struct ospf_interface *oi) { struct ospf_neighbor *nbr; - struct route_node *rn; + struct listnode *node; int count = 0; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (nbr->state == NSM_Full) - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - count++; + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) + if (nbr->state == NSM_Full) + if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) + count++; return count; } #endif /* HAVE_OPAQUE_LSA */ -/* lookup nbr by address - use this only if you know you must - * otherwise use the ospf_nbr_lookup() wrapper, which deals - * with virtual link neighbours - */ -struct ospf_neighbor * -ospf_nbr_lookup_by_addr (struct route_table *nbrs, - struct in_addr *addr) -{ - struct prefix p; - struct route_node *rn; - struct ospf_neighbor *nbr; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = *addr; - - rn = route_node_lookup (nbrs, &p); - if (! rn) - return NULL; - - /* See comment in ospf_nbr_delete */ - assert (rn->info); - - if (rn->info == NULL) - { - route_unlock_node (rn); - return NULL; - } - - nbr = (struct ospf_neighbor *) rn->info; - route_unlock_node (rn); - - return nbr; -} - -struct ospf_neighbor * -ospf_nbr_lookup_by_routerid (struct route_table *nbrs, - struct in_addr *id) -{ - struct route_node *rn; - struct ospf_neighbor *nbr; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (IPV4_ADDR_SAME (&nbr->router_id, id)) - { - route_unlock_node(rn); - return nbr; - } - - return NULL; -} - void ospf_renegotiate_optional_capabilities (struct ospf *top) { - struct listnode *node; + struct listnode *node, *nnode; struct ospf_interface *oi; - struct route_table *nbrs; - struct route_node *rn; struct ospf_neighbor *nbr; /* At first, flush self-originated LSAs from routing domain. */ @@ -349,12 +273,9 @@ ospf_renegotiate_optional_capabilities (struct ospf *top) /* Revert all neighbor status to ExStart. */ for (ALL_LIST_ELEMENTS_RO (top->oiflist, node, oi)) { - if ((nbrs = oi->nbrs) == NULL) - continue; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - { - if ((nbr = rn->info) == NULL || nbr == oi->nbr_self) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nnode, nbr)) + { + if (nbr == oi->nbr_self) continue; if (nbr->state < NSM_ExStart) @@ -375,22 +296,22 @@ struct ospf_neighbor * ospf_nbr_lookup (struct ospf_interface *oi, struct ip *iph, struct ospf_header *ospfh) { - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - return (ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id)); + if (oi->type == OSPF_IFTYPE_VIRTUALLINK || + oi->type == OSPF_IFTYPE_POINTOPOINT) + return ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id); else - return (ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src)); + return ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src); } static struct ospf_neighbor * ospf_nbr_add (struct ospf_interface *oi, struct ospf_header *ospfh, - struct prefix *p) + struct ip *iph) { struct ospf_neighbor *nbr; nbr = ospf_nbr_new (oi); nbr->state = NSM_Down; - nbr->src = p->u.prefix4; - memcpy (&nbr->address, p, sizeof (struct prefix)); + nbr->src = iph->ip_src; nbr->nbr_nbma = NULL; if (oi->type == OSPF_IFTYPE_NBMA) @@ -420,43 +341,31 @@ ospf_nbr_add (struct ospf_interface *oi, struct ospf_header *ospfh, if (IS_DEBUG_OSPF_EVENT) zlog_debug ("NSM[%s:%s]: start", IF_NAME (nbr->oi), inet_ntoa (nbr->router_id)); - + + listnode_add(oi->nbrs, nbr); return nbr; } struct ospf_neighbor * ospf_nbr_get (struct ospf_interface *oi, struct ospf_header *ospfh, - struct ip *iph, struct prefix *p) + struct ip *iph) { - struct route_node *rn; - struct prefix key; struct ospf_neighbor *nbr; - - key.family = AF_INET; - key.prefixlen = IPV4_MAX_BITLEN; - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - key.u.prefix4 = ospfh->router_id; /* index vlink nbrs by router-id */ - else - key.u.prefix4 = iph->ip_src; - - rn = route_node_get (oi->nbrs, &key); - if (rn->info) + nbr = ospf_nbr_lookup (oi, iph, ospfh); + if (nbr) { - route_unlock_node (rn); - nbr = rn->info; - if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) { nbr->src = iph->ip_src; - memcpy (&nbr->address, p, sizeof (struct prefix)); } } else { - rn->info = nbr = ospf_nbr_add (oi, ospfh, p); + nbr = ospf_nbr_add (oi, ospfh, iph); + listnode_add (oi->nbrs, nbr); } - + nbr->router_id = ospfh->router_id; return nbr; diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h index 25f13524..70cc7855 100644 --- a/ospfd/ospf_neighbor.h +++ b/ospfd/ospf_neighbor.h @@ -37,8 +37,6 @@ struct ospf_neighbor u_int32_t dd_seqnum; /* DD Sequence Number. */ /* Neighbor Information from Hello. */ - struct prefix address; /* Neighbor Interface Address. */ - struct in_addr src; /* Src address. */ struct in_addr router_id; /* Router ID. */ u_char options; /* Options. */ @@ -91,8 +89,8 @@ struct ospf_neighbor }; /* Macros. */ -#define NBR_IS_DR(n) IPV4_ADDR_SAME (&n->address.u.prefix4, &n->d_router) -#define NBR_IS_BDR(n) IPV4_ADDR_SAME (&n->address.u.prefix4, &n->bd_router) +#define NBR_IS_DR(n) IPV4_ADDR_SAME (&n->src, &n->d_router) +#define NBR_IS_BDR(n) IPV4_ADDR_SAME (&n->src, &n->bd_router) /* Prototypes. */ extern struct ospf_neighbor *ospf_nbr_new (struct ospf_interface *); @@ -106,14 +104,13 @@ extern int ospf_nbr_count_opaque_capable (struct ospf_interface *); #endif /* HAVE_OPAQUE_LSA */ extern struct ospf_neighbor *ospf_nbr_get (struct ospf_interface *, struct ospf_header *, - struct ip *, struct prefix *); + struct ip *); extern struct ospf_neighbor *ospf_nbr_lookup (struct ospf_interface *, struct ip *, struct ospf_header *); -extern struct ospf_neighbor *ospf_nbr_lookup_by_addr (struct route_table *, +extern struct ospf_neighbor *ospf_nbr_lookup_by_addr (struct list *, struct in_addr *); -extern struct ospf_neighbor *ospf_nbr_lookup_by_routerid (struct route_table - *, +extern struct ospf_neighbor *ospf_nbr_lookup_by_routerid (struct list *, struct in_addr *); extern void ospf_renegotiate_optional_capabilities (struct ospf *top); diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 15fff349..26e32d9b 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -153,8 +153,8 @@ nsm_should_adj (struct ospf_neighbor *nbr) || IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) || IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi)) /* Neighboring Router is the DRouter or the BDRouter. */ - || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &DR (oi)) - || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &BDR (oi))) + || IPV4_ADDR_SAME (&nbr->src, &DR (oi)) + || IPV4_ADDR_SAME (&nbr->src, &BDR (oi))) return 1; return 0; @@ -162,7 +162,7 @@ nsm_should_adj (struct ospf_neighbor *nbr) /* OSPF NSM functions. */ static int -nsm_hello_received (struct ospf_neighbor *nbr) +nsm_packet_received (struct ospf_neighbor *nbr) { /* Start or Restart Inactivity Timer. */ OSPF_NSM_TIMER_OFF (nbr->t_inactivity); @@ -393,7 +393,7 @@ nsm_kill_nbr (struct ospf_neighbor *nbr) if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) zlog_debug ("NSM[%s:%s]: Down (PollIntervalTimer scheduled)", - IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4)); + IF_NAME (nbr->oi), inet_ntoa (nbr->src)); } return 0; @@ -408,7 +408,7 @@ struct { { /* DependUpon: dummy state. */ { NULL, NSM_DependUpon }, /* NoEvent */ - { NULL, NSM_DependUpon }, /* HelloReceived */ + { NULL, NSM_DependUpon }, /* PacketReceived */ { NULL, NSM_DependUpon }, /* Start */ { NULL, NSM_DependUpon }, /* 2-WayReceived */ { NULL, NSM_DependUpon }, /* NegotiationDone */ @@ -425,7 +425,7 @@ struct { { /* Deleted: dummy state. */ { NULL, NSM_Deleted }, /* NoEvent */ - { NULL, NSM_Deleted }, /* HelloReceived */ + { NULL, NSM_Deleted }, /* PacketReceived */ { NULL, NSM_Deleted }, /* Start */ { NULL, NSM_Deleted }, /* 2-WayReceived */ { NULL, NSM_Deleted }, /* NegotiationDone */ @@ -442,7 +442,7 @@ struct { { /* Down: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Init }, /* HelloReceived */ + { nsm_packet_received, NSM_Init }, /* PacketReceived */ { nsm_start, NSM_Attempt }, /* Start */ { NULL, NSM_Down }, /* 2-WayReceived */ { NULL, NSM_Down }, /* NegotiationDone */ @@ -459,7 +459,7 @@ struct { { /* Attempt: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Init }, /* HelloReceived */ + { nsm_packet_received, NSM_Init }, /* PacketReceived */ { NULL, NSM_Attempt }, /* Start */ { NULL, NSM_Attempt }, /* 2-WayReceived */ { NULL, NSM_Attempt }, /* NegotiationDone */ @@ -476,7 +476,7 @@ struct { { /* Init: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Init }, /* HelloReceived */ + { nsm_packet_received, NSM_Init }, /* PacketReceived */ { NULL, NSM_Init }, /* Start */ { nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */ { NULL, NSM_Init }, /* NegotiationDone */ @@ -493,7 +493,7 @@ struct { { /* 2-Way: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_TwoWay }, /* HelloReceived */ + { nsm_packet_received, NSM_TwoWay }, /* HelloReceived */ { NULL, NSM_TwoWay }, /* Start */ { NULL, NSM_TwoWay }, /* 2-WayReceived */ { NULL, NSM_TwoWay }, /* NegotiationDone */ @@ -510,7 +510,7 @@ struct { { /* ExStart: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_ExStart }, /* HelloReceived */ + { nsm_packet_received, NSM_ExStart }, /* PacaketReceived */ { NULL, NSM_ExStart }, /* Start */ { NULL, NSM_ExStart }, /* 2-WayReceived */ { nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */ @@ -527,7 +527,7 @@ struct { { /* Exchange: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Exchange }, /* HelloReceived */ + { nsm_packet_received, NSM_Exchange }, /* PacketReceived */ { NULL, NSM_Exchange }, /* Start */ { NULL, NSM_Exchange }, /* 2-WayReceived */ { NULL, NSM_Exchange }, /* NegotiationDone */ @@ -544,7 +544,7 @@ struct { { /* Loading: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Loading }, /* HelloReceived */ + { nsm_packet_received, NSM_Loading }, /* PacketReceived */ { NULL, NSM_Loading }, /* Start */ { NULL, NSM_Loading }, /* 2-WayReceived */ { NULL, NSM_Loading }, /* NegotiationDone */ @@ -560,7 +560,7 @@ struct { }, { /* Full: */ { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_hello_received, NSM_Full }, /* HelloReceived */ + { nsm_packet_received, NSM_Full }, /* PacketReceived */ { NULL, NSM_Full }, /* Start */ { NULL, NSM_Full }, /* 2-WayReceived */ { NULL, NSM_Full }, /* NegotiationDone */ @@ -579,7 +579,7 @@ struct { static const char *ospf_nsm_event_str[] = { "NoEvent", - "HelloReceived", + "PacketReceived", "Start", "2-WayReceived", "NegotiationDone", diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h index 1121dae6..4f2ae808 100644 --- a/ospfd/ospf_nsm.h +++ b/ospfd/ospf_nsm.h @@ -39,7 +39,7 @@ /* OSPF Neighbor State Machine Event. */ #define NSM_NoEvent 0 -#define NSM_HelloReceived 1 +#define NSM_PacketReceived 1 /* HelloReceived in the protocol */ #define NSM_Start 2 #define NSM_TwoWayReceived 3 #define NSM_NegotiationDone 4 diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 0b6ac4cb..826d149f 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -2118,11 +2118,12 @@ out: * Followings are control functions to block origination after restart. *------------------------------------------------------------------------*/ -static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa); +static void ospf_opaque_exclude_lsa_from_lsreq (struct list *nbrs, + struct ospf_neighbor *inbr, struct ospf_lsa *lsa); static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi); static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area); static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top); -static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type); +static unsigned long ospf_opaque_nrxmt_self (struct list *nbrs, int lsa_type); void ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, struct list *lsas) @@ -2199,18 +2200,16 @@ out: } static void -ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, +ospf_opaque_exclude_lsa_from_lsreq (struct list *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *onbr; struct ospf_lsa *ls_req; - for (rn = route_top (nbrs); rn; rn = route_next (rn)) + for (ALL_LIST_ELEMENTS_RO (nbrs, node, onbr)) { - if ((onbr = rn->info) == NULL) - continue; if (onbr == inbr) continue; if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL) @@ -2412,17 +2411,15 @@ out: } static unsigned long -ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type) +ospf_opaque_nrxmt_self (struct list *nbrs, int lsa_type) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; struct ospf *top; unsigned long n = 0; - for (rn = route_top (nbrs); rn; rn = route_next (rn)) + for (ALL_LIST_ELEMENTS_RO (nbrs, node, nbr)) { - if ((nbr = rn->info) == NULL) - continue; if ((top = oi_to_top (nbr->oi)) == NULL) continue; if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id)) diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 1066e64f..c4a6bf92 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -125,6 +125,20 @@ ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op) fifo->count++; } +/* Add new packet to head of fifo. */ +static void +ospf_fifo_push_head (struct ospf_fifo *fifo, struct ospf_packet *op) +{ + op->next = fifo->head; + + if (fifo->tail == NULL) + fifo->tail = op; + + fifo->head = op; + + fifo->count++; +} + /* Delete first packet from fifo. */ struct ospf_packet * ospf_fifo_pop (struct ospf_fifo *fifo) @@ -199,6 +213,27 @@ ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op) /* ospf_fifo_debug (oi->obuf); */ } +static void +ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op) +{ + if (!oi->obuf) + { + zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, " + "destination %s) called with NULL obuf, ignoring " + "(please report this bug)!\n", + IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state), + ospf_packet_type_str[stream_getc_from(op->s, 1)], + inet_ntoa (op->dst)); + return; + } + + /* Add packet to head of queue. */ + ospf_fifo_push_head (oi->obuf, op); + + /* Debug of packet fifo*/ + /* ospf_fifo_debug (oi->obuf); */ +} + void ospf_packet_delete (struct ospf_interface *oi) { @@ -324,7 +359,7 @@ static int ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op) { struct ospf_header *ospfh; - unsigned char digest[OSPF_AUTH_MD5_SIZE]; + unsigned char digest[OSPF_AUTH_MD5_SIZE] = {0}; MD5_CTX ctx; void *ibuf; u_int32_t t; @@ -351,7 +386,7 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op) /* Get MD5 Authentication key from auth_key list. */ if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt))) - auth_key = (const u_int8_t *) ""; + auth_key = (const u_int8_t *) digest; else { ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt))); @@ -745,7 +780,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, struct ospf_hello *hello; struct ospf_neighbor *nbr; int old_state; - struct prefix p; /* increment statistics. */ oi->hello_in++; @@ -765,20 +799,15 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, return; } - /* get neighbor prefix. */ - p.family = AF_INET; - p.prefixlen = ip_masklen (hello->network_mask); - p.u.prefix4 = iph->ip_src; - /* Compare network mask. */ /* Checking is ignored for Point-to-Point and Virtual link. */ if (oi->type != OSPF_IFTYPE_POINTOPOINT && oi->type != OSPF_IFTYPE_VIRTUALLINK) - if (oi->address->prefixlen != p.prefixlen) + if (oi->address->prefixlen != ip_masklen (hello->network_mask)) { zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch on %s (configured prefix length is %d, but hello packet indicates %d).", inet_ntoa(ospfh->router_id), IF_NAME(oi), - (int)oi->address->prefixlen, (int)p.prefixlen); + (int)oi->address->prefixlen, (int)ip_masklen (hello->network_mask)); return; } @@ -873,7 +902,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, } /* get neighbour struct */ - nbr = ospf_nbr_get (oi, ospfh, iph, &p); + nbr = ospf_nbr_get (oi, ospfh, iph); /* neighbour must be valid, ospf_nbr_get creates if none existed */ assert (nbr); @@ -881,7 +910,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, old_state = nbr->state; /* Add event to thread. */ - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived); + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); /* RFC2328 Section 9.5.1 If the router is not eligible to become Designated Router, @@ -901,58 +930,63 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, if (oi->type == OSPF_IFTYPE_NBMA && (old_state == NSM_Down || old_state == NSM_Attempt)) { - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived); - nbr->priority = hello->priority; - nbr->d_router = hello->d_router; - nbr->bd_router = hello->bd_router; - return; + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived); + goto done; } if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors, size - OSPF_HELLO_MIN_SIZE)) { - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived); + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_TwoWayReceived); nbr->options |= hello->options; } else { - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived); - /* Set neighbor information. */ - nbr->priority = hello->priority; - nbr->d_router = hello->d_router; - nbr->bd_router = hello->bd_router; - return; + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived); + goto done; } + /* Neighbor priority check. */ + if (nbr->priority >= 0 && nbr->priority != hello->priority) + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); + /* If neighbor itself declares DR and no BDR exists, cause event BackupSeen */ - if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router)) - if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting) + if (oi->state == ISM_Waiting && + IPV4_ADDR_SAME (&nbr->src, &hello->d_router) && + hello->bd_router.s_addr == 0) + { OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen); + goto done; + } + /* had not previously. */ + if ((IPV4_ADDR_SAME (&nbr->src, &hello->d_router) && + IPV4_ADDR_CMP (&nbr->src, &nbr->d_router)) || + (IPV4_ADDR_CMP (&nbr->src, &hello->d_router) && + IPV4_ADDR_SAME (&nbr->src, &nbr->d_router))) + { + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); + goto done; + } /* neighbor itself declares BDR. */ if (oi->state == ISM_Waiting && - IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router)) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen); - - /* had not previously. */ - if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) && - IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) || - (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) && - IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router))) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); - + IPV4_ADDR_SAME (&nbr->src, &hello->bd_router)) + { + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen); + goto done; + } /* had not previously. */ - if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) && - IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) || - (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) && - IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router))) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); - - /* Neighbor priority check. */ - if (nbr->priority >= 0 && nbr->priority != hello->priority) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); + if ((IPV4_ADDR_SAME (&nbr->src, &hello->bd_router) && + IPV4_ADDR_CMP (&nbr->src, &nbr->bd_router)) || + (IPV4_ADDR_CMP (&nbr->src, &hello->bd_router) && + IPV4_ADDR_SAME (&nbr->src, &nbr->bd_router))) + { + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); + goto done; + } + done: /* Set neighbor information. */ nbr->priority = hello->priority; nbr->d_router = hello->d_router; @@ -1191,6 +1225,9 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, } #endif /* HAVE_OPAQUE_LSA */ + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); + /* Process DD packet by neighbor status. */ switch (nbr->state) { @@ -1260,7 +1297,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT "); if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O) - && IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4)) + && IPV4_ADDR_SAME (&DR (oi), &nbr->src)) { zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; " "Opaque-LSAs cannot be reliably advertised " @@ -1412,6 +1449,9 @@ ospf_ls_req (struct ip *iph, struct ospf_header *ospfh, return; } + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); + /* Neighbor State should be Exchange or later. */ if (nbr->state != NSM_Exchange && nbr->state != NSM_Loading && @@ -1644,6 +1684,9 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, return; } + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); + /* Check neighbor state. */ if (nbr->state < NSM_Exchange) { @@ -1977,6 +2020,9 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh, return; } + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); + if (nbr->state < NSM_Exchange) { zlog_warn ("Link State Acknowledgment: " @@ -2620,7 +2666,7 @@ static int ospf_make_hello (struct ospf_interface *oi, struct stream *s) { struct ospf_neighbor *nbr; - struct route_node *rn; + struct listnode *node; u_int16_t length = OSPF_HELLO_MIN_SIZE; struct in_addr mask; unsigned long p; @@ -2662,10 +2708,9 @@ ospf_make_hello (struct ospf_interface *oi, struct stream *s) stream_put_ipv4 (s, BDR (oi).s_addr); /* Add neighbor seen. */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */ - if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */ + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */ + if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */ if (nbr->state != NSM_Down) /* This is myself for DR election. */ if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) { @@ -2955,8 +3000,8 @@ ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s) return length; } -void -ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr) +static void +ospf_hello_send_sub (struct ospf_interface *oi, in_addr_t addr) { struct ospf_packet *op; u_int16_t length = OSPF_HEADER_SIZE; @@ -2975,10 +3020,12 @@ ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr) /* Set packet length. */ op->length = length; - op->dst.s_addr = addr->s_addr; + op->dst.s_addr = addr; - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op); + /* Add packet to the top of the interface output queue, so that they + * can't get delayed by things like long queues of LS Update packets + */ + ospf_packet_add_top (oi, op); /* Hook thread to write packet. */ OSPF_ISM_WRITE_ON (oi->ospf); @@ -3009,7 +3056,7 @@ ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma) && oi->state != ISM_DR && oi->state != ISM_Backup) return; - ospf_hello_send_sub (oi, &nbr_nbma->addr); + ospf_hello_send_sub (oi, nbr_nbma->addr.s_addr); } int @@ -3048,7 +3095,7 @@ ospf_hello_reply_timer (struct thread *thread) zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)", IF_NAME (nbr->oi), inet_ntoa (nbr->router_id)); - ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4); + ospf_hello_send_sub (nbr->oi, nbr->src.s_addr); return 0; } @@ -3057,84 +3104,48 @@ ospf_hello_reply_timer (struct thread *thread) void ospf_hello_send (struct ospf_interface *oi) { - struct ospf_packet *op; - u_int16_t length = OSPF_HEADER_SIZE; - /* If this is passive interface, do not send OSPF Hello. */ if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE) return; - op = ospf_packet_new (oi->ifp->mtu); - - /* Prepare OSPF common header. */ - ospf_make_header (OSPF_MSG_HELLO, oi, op->s); - - /* Prepare OSPF Hello body. */ - length += ospf_make_hello (oi, op->s); - - /* Fill OSPF header. */ - ospf_fill_header (oi, op->s, length); - - /* Set packet length. */ - op->length = length; - if (oi->type == OSPF_IFTYPE_NBMA) { struct ospf_neighbor *nbr; - struct route_node *rn; - - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr != oi->nbr_self) - if (nbr->state != NSM_Down) - { - /* RFC 2328 Section 9.5.1 - If the router is not eligible to become Designated Router, - it must periodically send Hello Packets to both the - Designated Router and the Backup Designated Router (if they - exist). */ - if (PRIORITY(oi) == 0 && - IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) && - IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4)) - continue; - - /* If the router is eligible to become Designated Router, it - must periodically send Hello Packets to all neighbors that - are also eligible. In addition, if the router is itself the - Designated Router or Backup Designated Router, it must also - send periodic Hello Packets to all other neighbors. */ - - if (nbr->priority == 0 && oi->state == ISM_DROther) - continue; - /* if oi->state == Waiting, send hello to all neighbors */ - { - struct ospf_packet *op_dup; - - op_dup = ospf_packet_dup(op); - op_dup->dst = nbr->address.u.prefix4; + struct listnode *node; - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op_dup); - - OSPF_ISM_WRITE_ON (oi->ospf); - } - - } - ospf_packet_free (op); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (nbr != oi->nbr_self) + if (nbr->state != NSM_Down) + { + /* RFC 2328 Section 9.5.1 + If the router is not eligible to become Designated Router, + it must periodically send Hello Packets to both the + Designated Router and the Backup Designated Router (if they + exist). */ + if (PRIORITY(oi) == 0 && + IPV4_ADDR_CMP(&DR(oi), &nbr->src) && + IPV4_ADDR_CMP(&BDR(oi), &nbr->src)) + continue; + + /* If the router is eligible to become Designated Router, it + must periodically send Hello Packets to all neighbors that + are also eligible. In addition, if the router is itself the + Designated Router or Backup Designated Router, it must also + send periodic Hello Packets to all other neighbors. */ + + if (nbr->priority == 0 && oi->state == ISM_DROther) + continue; + /* if oi->state == Waiting, send hello to all neighbors */ + ospf_hello_send_sub (oi, nbr->src.s_addr); + } } else { /* Decide destination address. */ if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - op->dst.s_addr = oi->vl_data->peer_addr.s_addr; - else - op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); - - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op); - - /* Hook thread to write packet. */ - OSPF_ISM_WRITE_ON (oi->ospf); + ospf_hello_send_sub (oi, oi->vl_data->peer_addr.s_addr); + else + ospf_hello_send_sub (oi, htonl (OSPF_ALLSPFROUTERS)); } } @@ -3165,7 +3176,7 @@ ospf_db_desc_send (struct ospf_neighbor *nbr) if (oi->type == OSPF_IFTYPE_POINTOPOINT) op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); else - op->dst = nbr->address.u.prefix4; + op->dst = nbr->src; /* Add packet to the interface output queue. */ ospf_packet_add (oi, op); @@ -3227,7 +3238,7 @@ ospf_ls_req_send (struct ospf_neighbor *nbr) if (oi->type == OSPF_IFTYPE_POINTOPOINT) op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); else - op->dst = nbr->address.u.prefix4; + op->dst = nbr->src; /* Add packet to the interface output queue. */ ospf_packet_add (oi, op); @@ -3434,7 +3445,7 @@ ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag) else if (oi->type == OSPF_IFTYPE_POINTOPOINT) p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS); else if (flag == OSPF_SEND_PACKET_DIRECT) - p.prefix = nbr->address.u.prefix4; + p.prefix = nbr->src; else if (oi->state == ISM_DR || oi->state == ISM_Backup) p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS); else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) @@ -3514,7 +3525,7 @@ ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) struct ospf_interface *oi = nbr->oi; if (listcount (oi->ls_ack_direct.ls_ack) == 0) - oi->ls_ack_direct.dst = nbr->address.u.prefix4; + oi->ls_ack_direct.dst = nbr->src; listnode_add (oi->ls_ack_direct.ls_ack, ospf_lsa_lock (lsa)); @@ -3537,13 +3548,12 @@ ospf_ls_ack_send_delayed (struct ospf_interface *oi) if (oi->type == OSPF_IFTYPE_NBMA) { struct ospf_neighbor *nbr; - struct route_node *rn; + struct listnode *node; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange) while (listcount (oi->ls_ack)) - ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->address.u.prefix4); + ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->src); return; } if (oi->type == OSPF_IFTYPE_VIRTUALLINK) diff --git a/ospfd/ospf_packet.h b/ospfd/ospf_packet.h index 7b3d6866..9a472081 100644 --- a/ospfd/ospf_packet.h +++ b/ospfd/ospf_packet.h @@ -162,6 +162,5 @@ extern int ospf_ls_upd_timer (struct thread *); extern int ospf_ls_ack_timer (struct thread *); extern int ospf_poll_timer (struct thread *); extern int ospf_hello_reply_timer (struct thread *); -extern void ospf_hello_send_sub (struct ospf_interface *, struct in_addr *); #endif /* _ZEBRA_OSPF_PACKET_H */ diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 267237b8..10608f50 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -272,61 +272,6 @@ ospf_route_install (struct ospf *ospf, struct route_table *rt) } } -static void -ospf_intra_route_add (struct route_table *rt, struct vertex *v, - struct ospf_area *area) -{ - struct route_node *rn; - struct ospf_route *or; - struct prefix_ipv4 p; - struct ospf_path *path; - struct vertex_parent *parent; - struct listnode *node, *nnode; - - p.family = AF_INET; - p.prefix = v->id; - if (v->type == OSPF_VERTEX_ROUTER) - p.prefixlen = IPV4_MAX_BITLEN; - else - { - struct network_lsa *lsa = (struct network_lsa *) v->lsa; - p.prefixlen = ip_masklen (lsa->mask); - } - apply_mask_ipv4 (&p); - - rn = route_node_get (rt, (struct prefix *) &p); - if (rn->info) - { - zlog_warn ("Same routing information exists for %s", inet_ntoa (v->id)); - route_unlock_node (rn); - return; - } - - or = ospf_route_new (); - - if (v->type == OSPF_VERTEX_NETWORK) - { - or->type = OSPF_DESTINATION_NETWORK; - - for (ALL_LIST_ELEMENTS (v->parents, node, nnode, parent)) - { - path = ospf_path_new (); - path->nexthop = parent->nexthop->router; - listnode_add (or->paths, path); - } - } - else - or->type = OSPF_DESTINATION_ROUTER; - - or->id = v->id; - or->u.std.area_id = area->area_id; - or->u.std.external_routing= area->external_routing; - or->path_type = OSPF_PATH_INTRA_AREA; - or->cost = v->distance; - - rn->info = or; -} - /* RFC2328 16.1. (4). For "router". */ void ospf_intra_add_router (struct route_table *rt, struct vertex *v, @@ -810,12 +755,18 @@ ospf_route_copy_nexthops_from_vertex (struct ospf_route *to, { nexthop = vp->nexthop; - if (nexthop->oi != NULL) + if (nexthop->oi != NULL) { - if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi)) + if (!ospf_path_exist (to->paths, nexthop->router, nexthop->oi)) { path = ospf_path_new (); - path->nexthop = nexthop->router; + + /* PtoP I/F's are always directly connected */ + if (if_is_pointopoint (nexthop->oi->ifp)) + path->nexthop.s_addr = INADDR_ANY; + else + path->nexthop = nexthop->router; + path->ifindex = nexthop->oi->ifp->ifindex; listnode_add (to->paths, path); } diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index 17ab68e5..5483aaf5 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -121,6 +121,12 @@ struct ospf_route } u; }; +struct ospf_host_route { + struct in_addr host_addr; + u_int32_t cost; /* i.e. metric. */ + struct ospf_area *area; /* NULL == all areas */ +}; + extern struct ospf_path *ospf_path_new (void); extern void ospf_path_free (struct ospf_path *); extern struct ospf_path *ospf_path_lookup (struct list *, struct ospf_path *); diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index cc4974ce..84b169f4 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -2105,16 +2105,15 @@ static struct ospf_neighbor * ospf_snmp_nbr_lookup (struct ospf *ospf, struct in_addr *nbr_addr, unsigned int *ifindex) { - struct listnode *node, *nnode; + struct listnode *node, *nnode, *nbrnode; struct ospf_interface *oi; struct ospf_neighbor *nbr; struct route_node *rn; for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) { - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL - && nbr != oi->nbr_self + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nbrnode, nbr)) + if (nbr != oi->nbr_self /* If EXACT match is needed, provide ALL entry found && nbr->state != NSM_Down */ @@ -2134,10 +2133,9 @@ static struct ospf_neighbor * ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex, int first) { - struct listnode *nn; + struct listnode *nn, *nbrnode; struct ospf_interface *oi; struct ospf_neighbor *nbr; - struct route_node *rn; struct ospf_neighbor *min = NULL; struct ospf *ospf = ospf; @@ -2145,9 +2143,8 @@ ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex, for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, nn, oi)) { - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL - && nbr != oi->nbr_self + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nbrnode, nbr)) + if (nbr != oi->nbr_self && nbr->state != NSM_Down && nbr->src.s_addr != 0) { @@ -2613,9 +2610,9 @@ ospfTrapNbrStateChange (struct ospf_neighbor *on) ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf)); zlog (NULL, LOG_INFO, "ospfTrapNbrStateChange trap sent: %s now %s", - inet_ntoa(on->address.u.prefix4), msgbuf); + inet_ntoa(on->router_id), msgbuf); - oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE); + oid_copy_addr (index, &(on->router_id), IN_ADDR_SIZE); index[IN_ADDR_SIZE] = 0; smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid), @@ -2632,7 +2629,7 @@ ospfTrapVirtNbrStateChange (struct ospf_neighbor *on) zlog (NULL, LOG_INFO, "ospfTrapVirtNbrStateChange trap sent"); - oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE); + oid_copy_addr (index, &(on->router_id), IN_ADDR_SIZE); index[IN_ADDR_SIZE] = 0; smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid), diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index ca200222..b06c7b9e 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -480,13 +480,15 @@ ospf_spf_add_parent (struct vertex *v, struct vertex *w, static unsigned int ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, struct vertex *w, struct router_lsa_link *l, - unsigned int distance) + unsigned int distance, int lsa_pos) { struct listnode *node, *nnode; struct vertex_nexthop *nh; struct vertex_parent *vp; struct ospf_interface *oi = NULL; unsigned int added = 0; + char buf1[BUFSIZ]; + char buf2[BUFSIZ]; if (IS_DEBUG_OSPF_EVENT) { @@ -505,30 +507,38 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, the OSPF interface connecting to the destination network/router. */ + /* we *must* be supplied with the link data */ + assert (l != NULL); + oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos); + if (!oi) + { + zlog_debug("%s: OI not found in LSA: lsa_pos:%d link_id:%s link_data:%s", + __func__, lsa_pos, + inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), + inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); + return 0; + } + + if (IS_DEBUG_OSPF_EVENT) + { + zlog_debug("%s: considering link:%s " + "type:%d link_id:%s link_data:%s", + __func__, oi->ifp->name, l->m[0].type, + inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), + inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); + } + if (w->type == OSPF_VERTEX_ROUTER) { /* l is a link from v to w * l2 will be link from w to v */ struct router_lsa_link *l2 = NULL; - - /* we *must* be supplied with the link data */ - assert (l != NULL); - - if (IS_DEBUG_OSPF_EVENT) - { - char buf1[BUFSIZ]; - char buf2[BUFSIZ]; - - zlog_debug("ospf_nexthop_calculation(): considering link " - "type %d link_id %s link_data %s", - l->m[0].type, - inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), - inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); - } if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT) { + struct in_addr nexthop; + /* If the destination is a router which connects to the calculating router via a Point-to-MultiPoint network, the destination's next hop IP address(es) @@ -539,68 +549,53 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, provides an IP address of the next hop router. At this point l is a link from V to W, and V is the - root ("us"). Find the local interface associated - with l (its address is in l->link_data). If it - is a point-to-multipoint interface, then look through - the links in the opposite direction (W to V). If - any of them have an address that lands within the + root ("us"). If it is a point-to-multipoint interface, + then look through the links in the opposite direction (W to V). + If any of them have an address that lands within the subnet declared by the PtMP link, then that link - is a constituent of the PtMP link, and its address is + is a constituent of the PtMP link, and its address is a nexthop address for V. */ - oi = ospf_if_is_configured (area->ospf, &l->link_data); - if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) - { - struct prefix_ipv4 la; - - la.family = AF_INET; - la.prefixlen = oi->address->prefixlen; - - /* V links to W on PtMP interface - - find the interface address on W */ - while ((l2 = ospf_get_next_link (w, v, l2))) - { - la.prefix = l2->link_data; - - if (prefix_cmp ((struct prefix *) &la, - oi->address) == 0) - /* link_data is on our PtMP network */ - break; - } - } /* end l is on point-to-multipoint link */ - else - { - /* l is a regular point-to-point link. - Look for a link from W to V. - */ - while ((l2 = ospf_get_next_link (w, v, l2))) - { - oi = ospf_if_is_configured (area->ospf, - &(l2->link_data)); - - if (oi == NULL) - continue; - - if (!IPV4_ADDR_SAME (&oi->address->u.prefix4, - &l->link_data)) - continue; - - break; - } - } - - if (oi && l2) + if (oi->type == OSPF_IFTYPE_POINTOPOINT) + { + added = 1; + nexthop.s_addr = 0; /* Nexthop not required */ + } + else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) + { + struct prefix_ipv4 la; + + la.family = AF_INET; + la.prefixlen = oi->address->prefixlen; + + /* V links to W on PtMP interface + - find the interface address on W */ + while ((l2 = ospf_get_next_link (w, v, l2))) + { + la.prefix = l2->link_data; + + if (prefix_cmp ((struct prefix *) &la, + oi->address) != 0) + continue; + /* link_data is on our PtMP network */ + added = 1; + nexthop = l2->link_data; + break; + } + } + + if (added) { /* found all necessary info to build nexthop */ nh = vertex_nexthop_new (); nh->oi = oi; - nh->router = l2->link_data; + nh->router = nexthop; ospf_spf_add_parent (v, w, nh, distance); return 1; } else - zlog_info("ospf_nexthop_calculation(): " - "could not determine nexthop for link"); + zlog_info("%s: could not determine nexthop for link %s", + __func__, oi->ifp->name); } /* end point-to-point link from V to W */ else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK) { @@ -633,19 +628,13 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, else { assert(w->type == OSPF_VERTEX_NETWORK); - oi = ospf_if_is_configured (area->ospf, &(l->link_data)); - if (oi) - { - nh = vertex_nexthop_new (); - nh->oi = oi; - nh->router.s_addr = 0; - ospf_spf_add_parent (v, w, nh, distance); - return 1; - } + + nh = vertex_nexthop_new (); + nh->oi = oi; + nh->router.s_addr = 0; /* Nexthop not required */ + ospf_spf_add_parent (v, w, nh, distance); + return 1; } - zlog_info("ospf_nexthop_calculation(): " - "Unknown attached link"); - return 0; } /* end V is the root */ /* Check if W's parent is a network connected to root. */ else if (v->type == OSPF_VERTEX_NETWORK) @@ -726,7 +715,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, u_char *lim; struct router_lsa_link *l = NULL; struct in_addr *r; - int type = 0; + int type = 0, lsa_pos=-1, lsa_pos_next=0; /* If this is a router-LSA, and bit V of the router-LSA (see Section A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */ @@ -754,7 +743,8 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, if (v->lsa->type == OSPF_ROUTER_LSA) { l = (struct router_lsa_link *) p; - + lsa_pos = lsa_pos_next; /* LSA link position */ + lsa_pos_next++; p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE)); @@ -876,7 +866,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, w = ospf_vertex_new (w_lsa); /* Calculate nexthop to W. */ - if (ospf_nexthop_calculation (area, v, w, l, distance)) + if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos)) pqueue_enqueue (w, candidate); else if (IS_DEBUG_OSPF_EVENT) zlog_debug ("Nexthop Calc failed"); @@ -896,7 +886,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, { /* Found an equal-cost path to W. * Calculate nexthop of to W from V. */ - ospf_nexthop_calculation (area, v, w, l, distance); + ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos); } /* less than. */ else @@ -906,7 +896,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, * valid nexthop it will call spf_add_parents, which * will flush the old parents */ - if (ospf_nexthop_calculation (area, v, w, l, distance)) + if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos)) /* Decrease the key of the node in the heap. * trickle-sort it up towards root, just in case this * node should now be the new root due the cost change. @@ -1045,6 +1035,7 @@ ospf_rtrs_free (struct route_table *rtrs) route_table_finish (rtrs); } +#if 0 static void ospf_rtrs_print (struct route_table *rtrs) { @@ -1104,6 +1095,7 @@ ospf_rtrs_print (struct route_table *rtrs) zlog_debug ("ospf_rtrs_print() end"); } +#endif /* Calculating the shortest-path tree for an area. */ static void @@ -1269,9 +1261,6 @@ ospf_spf_calculate_timer (struct thread *thread) /* If new Router Route is installed, then schedule re-calculate External routes. */ - if (1) - ospf_ase_calculate_schedule (ospf); - ospf_ase_calculate_timer_add (ospf); /* Update routing table. */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index adc822a7..01e85c71 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -93,29 +93,6 @@ ospf_str2area_id (const char *str, struct in_addr *area_id, int *format) static int -str2distribute_source (const char *str, int *source) -{ - /* Sanity check. */ - if (str == NULL) - return 0; - - if (strncmp (str, "k", 1) == 0) - *source = ZEBRA_ROUTE_KERNEL; - else if (strncmp (str, "c", 1) == 0) - *source = ZEBRA_ROUTE_CONNECT; - else if (strncmp (str, "s", 1) == 0) - *source = ZEBRA_ROUTE_STATIC; - else if (strncmp (str, "r", 1) == 0) - *source = ZEBRA_ROUTE_RIP; - else if (strncmp (str, "b", 1) == 0) - *source = ZEBRA_ROUTE_BGP; - else - return 0; - - return 1; -} - -static int str2metric (const char *str, int *metric) { /* Sanity check. */ @@ -2862,6 +2839,9 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, vty_out (vty, " Internet Address %s/%d,", inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen); + vty_out(vty, " Unnumbered: %s,", + CHECK_FLAG(oi->ifp->status, ZEBRA_INTERFACE_UNNUMBERED) ? "YES" : "NO"); + if (oi->connected->destination || oi->type == OSPF_IFTYPE_VIRTUALLINK) { struct in_addr *dest; @@ -2911,7 +2891,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, vty_out (vty, " Designated Router (ID) %s,", inet_ntoa (nbr->router_id)); vty_out (vty, " Interface Address %s%s", - inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE); + inet_ntoa (nbr->src), VTY_NEWLINE); } } @@ -2930,7 +2910,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, vty_out (vty, " Backup Designated Router (ID) %s,", inet_ntoa (nbr->router_id)); vty_out (vty, " Interface Address %s%s", - inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE); + inet_ntoa (nbr->src), VTY_NEWLINE); } } @@ -3024,39 +3004,37 @@ show_ip_ospf_neighbour_header (struct vty *vty) static void show_ip_ospf_neighbor_sub (struct vty *vty, struct ospf_interface *oi) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; char msgbuf[16]; char timebuf[OSPF_TIME_DUMP_SIZE]; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - /* Do not show myself. */ - if (nbr != oi->nbr_self) - /* Down state is not shown. */ - if (nbr->state != NSM_Down) - { - ospf_nbr_state_message (nbr, msgbuf, 16); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + /* Do not show myself. */ + if (nbr != oi->nbr_self) + /* Down state is not shown. */ + if (nbr->state != NSM_Down) + { + ospf_nbr_state_message (nbr, msgbuf, 16); + if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0) + vty_out (vty, "%-15s %3d %-15s ", + "-", nbr->priority, + msgbuf); + else + vty_out (vty, "%-15s %3d %-15s ", + inet_ntoa (nbr->router_id), nbr->priority, + msgbuf); - if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0) - vty_out (vty, "%-15s %3d %-15s ", - "-", nbr->priority, - msgbuf); - else - vty_out (vty, "%-15s %3d %-15s ", - inet_ntoa (nbr->router_id), nbr->priority, - msgbuf); - - vty_out (vty, "%9s ", - ospf_timer_dump (nbr->t_inactivity, timebuf, + vty_out (vty, "%9s ", + ospf_timer_dump (nbr->t_inactivity, timebuf, sizeof(timebuf))); - - vty_out (vty, "%-15s ", inet_ntoa (nbr->src)); - vty_out (vty, "%-20s %5ld %5ld %5d%s", - IF_NAME (oi), ospf_ls_retransmit_count (nbr), - ospf_ls_request_count (nbr), ospf_db_summary_count (nbr), - VTY_NEWLINE); - } + + vty_out (vty, "%-15s ", inet_ntoa (nbr->src)); + vty_out (vty, "%-20s %5ld %5ld %5d%s", + IF_NAME (oi), ospf_ls_retransmit_count (nbr), + ospf_ls_request_count (nbr), ospf_db_summary_count (nbr), + VTY_NEWLINE); + } } DEFUN (show_ip_ospf_neighbor, @@ -3222,7 +3200,7 @@ show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi, /* Show interface address. */ vty_out (vty, " interface address %s%s", - inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE); + inet_ntoa (nbr->src), VTY_NEWLINE); /* Show Area ID. */ vty_out (vty, " In the area %s via interface %s%s", ospf_area_desc_string (oi->area), oi->ifp->name, VTY_NEWLINE); @@ -3343,14 +3321,13 @@ DEFUN (show_ip_ospf_neighbor_detail, for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) { - struct route_node *rn; + struct listnode *nnode; struct ospf_neighbor *nbr; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr != oi->nbr_self) - if (nbr->state != NSM_Down) - show_ip_ospf_neighbor_detail_sub (vty, oi, nbr); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nnode, nbr)) + if (nbr != oi->nbr_self) + if (nbr->state != NSM_Down) + show_ip_ospf_neighbor_detail_sub (vty, oi, nbr); } return CMD_SUCCESS; @@ -3379,15 +3356,14 @@ DEFUN (show_ip_ospf_neighbor_detail_all, for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) { - struct route_node *rn; + struct listnode *nnode; struct ospf_neighbor *nbr; struct ospf_nbr_nbma *nbr_nbma; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr != oi->nbr_self) - if (oi->type == OSPF_IFTYPE_NBMA && nbr->state != NSM_Down) - show_ip_ospf_neighbor_detail_sub (vty, oi, rn->info); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nnode, nbr)) + if (nbr != oi->nbr_self) + if (oi->type == OSPF_IFTYPE_NBMA && nbr->state != NSM_Down) + show_ip_ospf_neighbor_detail_sub (vty, oi, nbr); if (oi->type == OSPF_IFTYPE_NBMA) { @@ -3416,8 +3392,9 @@ DEFUN (show_ip_ospf_neighbor_int_detail, struct ospf *ospf; struct ospf_interface *oi; struct interface *ifp; - struct route_node *rn, *nrn; + struct route_node *rn; struct ospf_neighbor *nbr; + struct listnode *node; ifp = if_lookup_by_name (argv[0]); if (!ifp) @@ -3436,11 +3413,10 @@ DEFUN (show_ip_ospf_neighbor_int_detail, for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) if ((oi = rn->info)) - for (nrn = route_top (oi->nbrs); nrn; nrn = route_next (nrn)) - if ((nbr = nrn->info)) - if (nbr != oi->nbr_self) - if (nbr->state != NSM_Down) - show_ip_ospf_neighbor_detail_sub (vty, oi, nbr); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (nbr != oi->nbr_self) + if (nbr->state != NSM_Down) + show_ip_ospf_neighbor_detail_sub (vty, oi, nbr); return CMD_SUCCESS; } @@ -3755,7 +3731,7 @@ show_as_external_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) return 0; } -/* N.B. This function currently seems to be unused. */ +#if 0 static int show_as_external_lsa_stdvty (struct ospf_lsa *lsa) { @@ -3779,6 +3755,7 @@ show_as_external_lsa_stdvty (struct ospf_lsa *lsa) return 0; } +#endif /* Show AS-NSSA-LSA detail information. */ static int @@ -4952,17 +4929,16 @@ ALIAS (no_ip_ospf_cost2, static void ospf_nbr_timer_update (struct ospf_interface *oi) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - { - nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait); - nbr->v_db_desc = 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); - } + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + { + nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait); + nbr->v_db_desc = 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); + } } static int @@ -5797,6 +5773,71 @@ ALIAS (no_ip_ospf_transmit_delay, "OSPF interface commands\n" "Link state transmit delay\n") +DEFUN (ip_ospf_area, + ip_ospf_area_cmd, + "ip ospf area (A.B.C.D|<0-4294967295>)", + "IP Information\n" + "OSPF interface commands\n" + "Enable OSPF on this interface\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n") +{ + struct interface *ifp = vty->index; + int format, ret; + struct in_addr area_id; + struct ospf *ospf; + struct ospf_if_params *params; + + ret = ospf_str2area_id (argv[0], &area_id, &format); + + if (ret < 0) + { + vty_out (vty, "Please specify area by A.B.C.D|<0-4294967295>%s", + VTY_NEWLINE); + return CMD_WARNING; + } + params = IF_DEF_PARAMS (ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) + { + vty_out (vty, "There is already a interface statement.%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (memcmp (ifp->name, "VLINK", 5) == 0) + { + vty_out (vty, "Cannot enable OSPF on a virtual link.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + SET_IF_PARAM (params, if_area); + params->if_area = area_id; + ospf_interface_set (ifp); + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_area, + no_ip_ospf_area_cmd, + "no ip ospf area", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Disable OSPF on this interface\n") +{ + struct interface *ifp = vty->index; + struct ospf *ospf; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS (ifp); + if (!OSPF_IF_PARAM_CONFIGURED(params, if_area)) + return CMD_SUCCESS; + + UNSET_IF_PARAM (params, if_area); + + ospf_interface_unset (ifp); + return CMD_SUCCESS; +} + + DEFUN (ospf_redistribute_source_metric_type, ospf_redistribute_source_metric_type_routemap_cmd, @@ -5818,7 +5859,8 @@ DEFUN (ospf_redistribute_source_metric_type, int metric = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -5879,7 +5921,8 @@ DEFUN (ospf_redistribute_source_type_metric, int metric = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -5943,7 +5986,8 @@ DEFUN (ospf_redistribute_source_metric_routemap, int metric = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -5976,7 +6020,8 @@ DEFUN (ospf_redistribute_source_type_routemap, int type = -1; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; /* Get metric value. */ @@ -6004,7 +6049,8 @@ DEFUN (ospf_redistribute_source_routemap, int source; /* Get distribute source. */ - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; if (argc == 2) @@ -6025,7 +6071,8 @@ DEFUN (no_ospf_redistribute_source, struct ospf *ospf = vty->index; int source; - if (!str2distribute_source (argv[0], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; ospf_routemap_unset (ospf, source); @@ -6044,7 +6091,8 @@ DEFUN (ospf_distribute_list_out, int source; /* Get distribute source. */ - if (!str2distribute_source (argv[1], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; return ospf_distribute_list_out_set (ospf, source, argv[0]); @@ -6062,7 +6110,8 @@ DEFUN (no_ospf_distribute_list_out, struct ospf *ospf = vty->index; int source; - if (!str2distribute_source (argv[1], &source)) + source = proto_redistnum(AFI_IP, argv[0]); + if (source < 0 || source == ZEBRA_ROUTE_OSPF) return CMD_WARNING; return ospf_distribute_list_out_unset (ospf, source, argv[0]); @@ -7389,6 +7438,123 @@ DEFUN (show_ip_ospf_route, return CMD_SUCCESS; } +DEFUN (ip_ospf_host, + ip_ospf_host_cmd, + "ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all) cost <0-65535>", + "OSPF specific commands\n" + "Add a host route to OPSF\n" + "Host route in IP address format\n") +{ + struct ospf *ospf; + u_int32_t cost; + struct ospf_area *area = NULL; + struct in_addr host_addr, area_id; + struct ospf_host_route *host = NULL; + struct listnode *node; + int ret, format; + + ospf = ospf_lookup (); + if (ospf == NULL) + { + vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + ret = inet_aton (argv[0], &host_addr); + if (!ret) + { + vty_out (vty, "Please specify host route by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + cost = strtol (argv[2], NULL, 10); + /* cost range is <0-65535>. */ + if (cost < 0 || cost > 65535) + { + vty_out (vty, "cost is invalid%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (strcmp(argv[1], "all") != 0) + { + VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); /* returns if error */ + area = ospf_area_get (ospf, area_id, format); + } + + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + if (IPV4_ADDR_SAME (&host_addr, &host->host_addr) && + area == host->area) + break; + + if (!node) + { + host = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf_host_route)); + listnode_add (ospf->hostlist, host); + } + host->host_addr = host_addr; + host->cost = cost; + host->area = area; + + if (!area) + for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) + ospf_router_lsa_timer_add(area); + else + ospf_router_lsa_timer_add(area); + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_host, + no_ip_ospf_host_cmd, + "no ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all)", + NO_STR + "OSPF specific commands\n" + "Host route in IP address format\n") +{ + struct ospf *ospf; + struct ospf_area *area = NULL; + struct in_addr host_addr, area_id; + struct ospf_host_route *host = NULL; + struct listnode *node; + int ret, format; + + ospf = ospf_lookup (); + if (ospf == NULL) + { + vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + ret = inet_aton (argv[0], &host_addr); + if (!ret) + { + vty_out (vty, "Please specify host route by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (strcmp(argv[1], "all") != 0) + { + VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); + area = ospf_area_get (ospf, area_id, format); + } + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + if (IPV4_ADDR_SAME (&host_addr, &host->host_addr) && + area == host->area) + break; + + if (node) + { + listnode_delete (ospf->hostlist, host); + XFREE (MTYPE_OSPF_TOP, host); + if (!area) + for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) + ospf_router_lsa_timer_add(area); + else + ospf_router_lsa_timer_add(area); + } + return CMD_SUCCESS; +} + const char *ospf_abr_type_str[] = { @@ -7596,6 +7762,14 @@ config_write_interface (struct vty *vty) vty_out (vty, "%s", VTY_NEWLINE); } + /* Area print. */ + if (OSPF_IF_PARAM_CONFIGURED (params, if_area)) + { + vty_out (vty, " ip ospf area %s%s", + inet_ntoa (params->if_area), + VTY_NEWLINE); + } + /* MTU ignore print. */ if (OSPF_IF_PARAM_CONFIGURED (params, mtu_ignore) && params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) @@ -7970,6 +8144,7 @@ ospf_config_write (struct vty *vty) struct interface *ifp; struct ospf_interface *oi; struct listnode *node; + struct ospf_host_route *host; int write = 0; ospf = ospf_lookup (); @@ -8037,7 +8212,20 @@ ospf_config_write (struct vty *vty) /* passive-interface print. */ if (ospf->passive_interface_default == OSPF_IF_PASSIVE) vty_out (vty, " passive-interface default%s", VTY_NEWLINE); - + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + { + char buf[28]; + + if (host->area) + area_id2str(buf, sizeof(buf), host->area); + else + strcpy(buf, "all"); + vty_out (vty, " ip ospf host %s area %s cost %d%s", + inet_ntoa (host->host_addr), + buf, host->cost, VTY_NEWLINE); + } + for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface) && IF_DEF_PARAMS (ifp)->passive_interface != @@ -8237,6 +8425,10 @@ ospf_vty_if_init (void) install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_cmd); + /* "ip ospf area" commands. */ + install_element (INTERFACE_NODE, &ip_ospf_area_cmd); + install_element (INTERFACE_NODE, &no_ip_ospf_area_cmd); + /* These commands are compatibitliy for previous version. */ install_element (INTERFACE_NODE, &ospf_authentication_key_cmd); install_element (INTERFACE_NODE, &no_ospf_authentication_key_cmd); @@ -8523,6 +8715,10 @@ ospf_vty_init (void) install_element (OSPF_NODE, &no_ospf_neighbor_priority_cmd); install_element (OSPF_NODE, &no_ospf_neighbor_poll_interval_cmd); + /* "ip ospf host" commands. */ + install_element (OSPF_NODE, &ip_ospf_host_cmd); + install_element (OSPF_NODE, &no_ip_ospf_host_cmd); + /* Init interface related vty commands. */ ospf_vty_if_init (); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 6f0a71ff..484aba98 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -133,8 +133,9 @@ ospf_interface_delete (int command, struct zclient *zclient, if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) zlog_debug - ("Zebra: interface delete %s index %d flags %lld metric %d mtu %d", - ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu); + ("Zebra: interface delete %s index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long) ifp->flags, + ifp->metric, ifp->mtu); #ifdef HAVE_SNMP ospf_snmp_if_delete (ifp); @@ -195,6 +196,17 @@ ospf_interface_state_up (int command, struct zclient *zclient, ospf_if_recalculate_output_cost (ifp); } + if (CHECK_FLAG(if_tmp.status ^ ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + { + if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) + zlog_debug ("Zebra: Interface[%s] Unnumbered state change %d -> %d.", + ifp->name, + if_tmp.status & ZEBRA_INTERFACE_UNNUMBERED, + ifp->status & ZEBRA_INTERFACE_UNNUMBERED); + + ospf_if_reset (ifp); + } + if (if_tmp.mtu != ifp->mtu) { if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) @@ -481,9 +493,9 @@ ospf_zebra_add_discard (struct prefix_ipv4 *p) if (zclient->redist[ZEBRA_ROUTE_OSPF]) { api.type = ZEBRA_ROUTE_OSPF; - api.flags = ZEBRA_FLAG_BLACKHOLE; + api.flags = 0; api.message = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG (api.message, ZAPI_MESSAGE_BLACKHOLE); api.nexthop_num = 0; api.ifindex_num = 0; @@ -503,9 +515,9 @@ ospf_zebra_delete_discard (struct prefix_ipv4 *p) if (zclient->redist[ZEBRA_ROUTE_OSPF]) { api.type = ZEBRA_ROUTE_OSPF; - api.flags = ZEBRA_FLAG_BLACKHOLE; + api.flags = 0; api.message = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG (api.message, ZAPI_MESSAGE_BLACKHOLE); api.nexthop_num = 0; api.ifindex_num = 0; @@ -964,7 +976,7 @@ ospf_distribute_list_update_timer (struct thread *thread) /* Update distribute-list and set timer to apply access-list. */ void -ospf_distribute_list_update (struct ospf *ospf, int type) +ospf_distribute_list_update (struct ospf *ospf, unsigned long type) { struct route_table *rt; diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 3efd8958..b6419c8b 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -56,7 +56,7 @@ extern int ospf_redistribute_check (struct ospf *, struct external_info *, int *); extern int ospf_distribute_check_connected (struct ospf *, struct external_info *); -extern void ospf_distribute_list_update (struct ospf *, int); +extern void ospf_distribute_list_update (struct ospf *, unsigned long); extern int ospf_is_type_redistributed (int); extern void ospf_distance_reset (struct ospf *); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index a7553e73..35c6b02b 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -231,7 +231,7 @@ ospf_new (void) } new->t_read = thread_add_read (master, ospf_read, new, new->fd); new->oi_write_q = list_new (); - + new->hostlist = list_new(); /* host route list */ return new; } @@ -401,6 +401,7 @@ ospf_finish_final (struct ospf *ospf) struct ospf_lsa *lsa; struct ospf_interface *oi; struct ospf_area *area; + struct ospf_host_route *host; struct ospf_vl_data *vl_data; struct listnode *node, *nnode; int i; @@ -471,6 +472,12 @@ ospf_finish_final (struct ospf *ospf) ospf_area_free (area); } + for (ALL_LIST_ELEMENTS (ospf->hostlist, node, nnode, host)) + { + listnode_delete (ospf->hostlist, host); + XFREE (MTYPE_OSPF_TOP, host); + } + /* Cancel all timers. */ OSPF_TIMER_OFF (ospf->t_external_lsa); OSPF_TIMER_OFF (ospf->t_router_lsa_update); @@ -646,8 +653,32 @@ ospf_area_free (struct ospf_area *area) void ospf_area_check_free (struct ospf *ospf, struct in_addr area_id) { + struct interface *ifp; + struct listnode *node; + struct ospf_if_params *params; + struct route_node *rn; + struct ospf_network *network; + struct ospf_host_route *host; struct ospf_area *area; + /* Check if any interface is a member of this area */ + for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) + { + params = IF_DEF_PARAMS (ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area) + && IPV4_ADDR_SAME (&area_id, ¶ms->if_area)) + return; + } + /* Check if any network is a member of this area */ + for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) + { + network = rn->info; + if (network && IPV4_ADDR_SAME (&area_id, &network->area_id)) + { + route_unlock_node (rn); + return; + } + } area = ospf_area_lookup_by_area_id (ospf, area_id); if (area && listcount (area->oiflist) == 0 && @@ -660,6 +691,9 @@ ospf_area_check_free (struct ospf *ospf, struct in_addr area_id) IMPORT_NAME (area) == NULL && area->auth_type == OSPF_AUTH_NULL) { + for (ALL_LIST_ELEMENTS_RO (area->ospf->hostlist, node, host)) + if (!host->area || host->area == area) + return; listnode_delete (ospf->areas, area); ospf_area_free (area); } @@ -701,6 +735,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 +849,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 +881,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 +910,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 +1038,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 +1099,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 @@ -1205,6 +1358,7 @@ ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id, return 1; } +#if 0 /* XXX: unused? Leave for symmetry? */ static int ospf_area_nssa_translator_role_unset (struct ospf *ospf, @@ -1222,6 +1376,7 @@ ospf_area_nssa_translator_role_unset (struct ospf *ospf, return 1; } +#endif int ospf_area_export_list_set (struct ospf *ospf, @@ -1397,8 +1552,6 @@ ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma, struct ospf_interface *oi) { struct ospf_neighbor *nbr; - struct route_node *rn; - struct prefix p; if (oi->type != OSPF_IFTYPE_NBMA) return; @@ -1406,37 +1559,27 @@ ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma, if (nbr_nbma->nbr != NULL) return; - if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr)) + if (IPV4_ADDR_SAME (&oi->nbr_self->src, &nbr_nbma->addr)) return; nbr_nbma->oi = oi; listnode_add (oi->nbr_nbma, nbr_nbma); /* Get neighbor information from table. */ - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = nbr_nbma->addr; - - rn = route_node_get (oi->nbrs, (struct prefix *)&p); - if (rn->info) + nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &nbr_nbma->addr); + if (nbr) { - nbr = rn->info; nbr->nbr_nbma = nbr_nbma; nbr_nbma->nbr = nbr; - - route_unlock_node (rn); } else { - nbr = rn->info = ospf_nbr_new (oi); + nbr = ospf_nbr_new (oi); nbr->state = NSM_Down; nbr->src = nbr_nbma->addr; nbr->nbr_nbma = nbr_nbma; nbr->priority = nbr_nbma->priority; - nbr->address = p; - nbr_nbma->nbr = nbr; - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start); } } diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index b24b3ced..6cde1099 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -48,7 +48,9 @@ #define OSPF_VL_IP_TTL 100 /* Default configuration file name for ospfd. */ -#define OSPF_DEFAULT_CONFIG "ospfd.conf" +#define OSPF_CONFIG_NAME "ospfd.conf" +#define OSPF_PID_NAME "ospfd.pid" +#define OSPF_VTY_NAME "ospfd.vty" /* Architectual Constants */ #ifdef DEBUG @@ -272,6 +274,9 @@ struct ospf struct stream *ibuf; struct list *oi_write_q; + /* queue for AS-External route calculation */ + struct work_queue *ase_calc_queue; + /* Distribute lists out of other route sources. */ struct { @@ -327,6 +332,9 @@ struct ospf u_int32_t rx_lsa_count; struct route_table *distance_table; + + /* Host route list */ + struct list *hostlist; }; /* OSPF area structure. */ @@ -607,6 +615,9 @@ extern struct ospf_area *ospf_area_lookup_by_area_id (struct ospf *, extern void ospf_area_add_if (struct ospf_area *, struct ospf_interface *); extern void ospf_area_del_if (struct ospf_area *, struct ospf_interface *); +extern int ospf_interface_set (struct interface *ifp); +extern int ospf_interface_unset (struct interface *ifp); + extern void ospf_route_map_init (void); extern void ospf_snmp_init (void); |