diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog index 4749618..b3d4857 100644 --- a/ospfd/ChangeLog +++ b/ospfd/ChangeLog @@ -1,3 +1,95 @@ +2006-06-02 Paul Jakma + + * (general) Audit and rationalise LSA refcounts ('lock') a bit. + - don't /create/ LSAs with refcnt set to 1, should be 0. + - Hence get rid of ospf_lsa.c's implicit refcount and the need + for the silly 'OSPF_LSA_DISCARD' flag. + - Installation of LSAs to respective LSDBs become the primary + LSA references (generally via ospf_lsa_install). + * ospf_lsa.c: (ospf_lsa_unlock) Make ospf_lsa_unlock take a + double pointer, so it can NULL out the caller's pointer to + the LSA if it is freed, and hence hopefully allow refcounting + errors to be caught *much* earlier (rather than turning into + weird memory corruption bugs) - and update all its callers to + suit. + (ospf_lsa_{new,lock,unlock}) Some extra debug. + (ospf_lsa_{dup,new}) Dont create LSAs with refcount + implicitely set to 1. + (ospf_lsa_discard) Deleted, along with the horrid implicit refcount + rubbish. + (ospf_*_lsa_{originate,new}) replace ospf_lsa_discard with + ospf_lsa_free where appropriate. Remove any weird implicit + refcounting for mere LSA construction. + (ospf_discard_from_db) Remove ospf_lsa_discard, let LSDB removal + unlock and hence reap LSAs when required. + * ospf_lsdb.c: (ospf_lsdb_delete_entry) new function, consolidate + lsa LSDB removal which was duplicated in the _add, _delete and + _delete_all LSDB functions. + * ospf_dump.{c,h}: Add 'debug ospf lsa lock'. + * ospf_opaque.c: (ospf_opaque_self_originated_lsa_received) With + the removal of ospf_lsa_discard, the goto stuff can be removed + too. + * ospf_packet.c: (ospf_ls_upd_list_lsa) Always lock the newly + created LSA as it's added to the temporary list used to + hand back LSAs to caller. + (ospf_ls_upd) Reform, in light of ospf_lsa_discard being removed. + DISCARD_LSA becomes LSA_DONE, which generally is how *every* + loop iteration should end, which unlocks the LSA, and provides + some debug functionality. + (ospf_make_ls_ack) Address the XXX, easy to do with the + ALL_LIST_ELEMENTS macro. + (ospf_make_db_desc) run function through indent, to fix + inconsistent formatting - the only /functional/ change is + that the conditional on OSPF_LSA_DISCARD changes to + IS_LSA_MAXAGE. + * ospf_flood.c: (ospf_lsa_flush) Fix mistake in previous commit, + args to ospf_lsa_flush_area were wrong way around. + +2006-05-31 Paul Jakma + + * ospf_lsdb.c: (ospf_lsdb_delete) robustify against NULL arguments, + print warning. + * ospf_lsa.c: (ospf_discard_from_db) ditto. + (ospf_maxage_lsa_remover) Check lsa->lsdb for validity, possible + mitigation (but not solution) for bug #269. + +2006-05-30 Paul Jakma + + * ospf_packet.c: (ospf_read) Debug message about packets + received on unenabled interfaces should be conditional on + debug being set. + +2006-05-30 Paul Jakma + + * (general) Fix confusion around MaxAge-ing and problem with + high-latency networks. Analysis and suggested fixes by + Phillip Spagnolo, in [quagga-dev 4132], on which this commit + expands slightly. + * ospf_flood.{c,h}: (ospf_lsa_flush) new function. + Scope-general form of existing flush functions, essentially + the dormant ospf_maxage_flood() but without the ambiguity of + whether it is responsible for flooding. + * ospf_lsa.c: (ospf_lsa_maxage) Role minimised to simply setup + LSA on the Maxage list and schedule removal - no more. + ospf_lsa_flush* being the primary way to kick-off flushes + of LSAs. + Don't hardcode the remover-timer value, which was too + short for very high-latency networks. + (ospf_maxage_lsa_remover) Just do what needs to be done to + remove maxage LSAs from the maxage list, remove the call + to ospf_flood_through(). + Don't hardcode remove-timer value. + (ospf_lsa_{install,flush_schedule}) ospf_lsa_flush is the correct + (lsa_header_set) Use a define for the initial age, useful for + testing. + entrypoint to flushing maxaged LSAs. + * ospf_opaque.c: (ospf_opaque_lsa_refresh) ditto. + (ospf_opaque_lsa_flush_schedule) ditto. + * ospfd.h: ({struct ospf,ospf_new}) Add maxage_delay parameter, + interval to wait before running the maxage_remover. Supply a + suitable default. + Add a define for OSPF_LSA_INITIAL_AGE, see lsa_header_set(). + 2006-05-13 Paul Jakma * ospf_lsa.c: (ospf_translated_nssa_refresh) fix the sanity diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index 2ee4d3e..8302b3b 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -1520,7 +1520,7 @@ ospf_apiserver_opaque_lsa_new (struct os if ((new->data = ospf_lsa_data_new (length)) == NULL) { zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?"); - ospf_lsa_unlock (new); + ospf_lsa_free (new); stream_free (s); return NULL; } @@ -1885,7 +1885,7 @@ ospf_apiserver_lsa_refresher (struct osp if (ospf_lsa_install (ospf, new->oi, new) == NULL) { zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed"); - ospf_lsa_unlock (new); + ospf_lsa_unlock (&new); goto out; } diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index f4b285b..c3733cb 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -711,7 +711,7 @@ ospf_ase_register_external_lsa (struct o /* We assume that if LSA is deleted from DB is is also deleted from this RT */ - listnode_add (lst, ospf_lsa_lock (lsa)); + listnode_add (lst, ospf_lsa_lock (lsa)); /* external_lsas lst */ } void @@ -730,18 +730,11 @@ ospf_ase_unregister_external_lsa (struct rn = route_node_get (top->external_lsas, (struct prefix *) &p); lst = rn->info; -#ifdef ORIGINAL_CODING - assert (lst); - listnode_delete (lst, lsa); - ospf_lsa_unlock (lsa); -#else /* ORIGINAL_CODING */ - /* XXX lst can be NULL */ if (lst) { listnode_delete (lst, lsa); - ospf_lsa_unlock (lsa); + ospf_lsa_unlock (&lsa); /* external_lsas list */ } -#endif /* ORIGINAL_CODING */ } void @@ -756,7 +749,7 @@ ospf_ase_external_lsas_finish (struct ro if ((lst = rn->info) != NULL) { for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa)) - ospf_lsa_unlock (lsa); + ospf_lsa_unlock (&lsa); /* external_lsas lst */ list_delete (lst); } diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 95d24b1..a67cb22 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -1171,6 +1171,8 @@ DEFUN (debug_ospf_lsa, DEBUG_ON (lsa, LSA_INSTALL); else if (strncmp (argv[0], "r", 1) == 0) DEBUG_ON (lsa, LSA_REFRESH); + else if (strncmp (argv[0], "l", 1) == 0) + DEBUG_ON (lsa, LSA_LOCK); } return CMD_SUCCESS; @@ -1189,6 +1191,8 @@ DEFUN (debug_ospf_lsa, TERM_DEBUG_ON (lsa, LSA_INSTALL); else if (strncmp (argv[0], "r", 1) == 0) TERM_DEBUG_ON (lsa, LSA_REFRESH); + else if (strncmp (argv[0], "l", 1) == 0) + TERM_DEBUG_ON (lsa, LSA_LOCK); } return CMD_SUCCESS; @@ -1196,14 +1200,15 @@ DEFUN (debug_ospf_lsa, ALIAS (debug_ospf_lsa, debug_ospf_lsa_sub_cmd, - "debug ospf lsa (generate|flooding|install|refresh)", + "debug ospf lsa (generate|flooding|install|refresh|locks)", DEBUG_STR OSPF_STR "OSPF Link State Advertisement\n" "LSA Generation\n" "LSA Flooding\n" "LSA Install/Delete\n" - "LSA Refresh\n") + "LSA Refresh\n" + "LSA 'Locking' (ie reference counting)\n") DEFUN (no_debug_ospf_lsa, no_debug_ospf_lsa_cmd, @@ -1227,6 +1232,8 @@ DEFUN (no_debug_ospf_lsa, DEBUG_OFF (lsa, LSA_INSTALL); else if (strncmp (argv[0], "r", 1) == 0) DEBUG_OFF (lsa, LSA_REFRESH); + else if (strncmp (argv[0], "l", 1) == 0) + DEBUG_OFF (lsa, LSA_LOCK); } return CMD_SUCCESS; @@ -1245,6 +1252,8 @@ DEFUN (no_debug_ospf_lsa, TERM_DEBUG_OFF (lsa, LSA_INSTALL); else if (strncmp (argv[0], "r", 1) == 0) TERM_DEBUG_OFF (lsa, LSA_REFRESH); + else if (strncmp (argv[0], "l", 1) == 0) + TERM_DEBUG_OFF (lsa, LSA_LOCK); } return CMD_SUCCESS; @@ -1252,7 +1261,7 @@ DEFUN (no_debug_ospf_lsa, ALIAS (no_debug_ospf_lsa, no_debug_ospf_lsa_sub_cmd, - "no debug ospf lsa (generate|flooding|install|refresh)", + "no debug ospf lsa (generate|flooding|install|refresh|locks)", NO_STR DEBUG_STR OSPF_STR @@ -1260,7 +1269,8 @@ ALIAS (no_debug_ospf_lsa, "LSA Generation\n" "LSA Flooding\n" "LSA Install/Delete\n" - "LSA Refres\n") + "LSA Refresh\n" + "LSA 'Locking' (ie reference counting)\n") DEFUN (debug_ospf_zebra, @@ -1564,6 +1574,8 @@ config_write_debug (struct vty *vty) vty_out (vty, "debug ospf lsa install%s", VTY_NEWLINE); if (IS_CONF_DEBUG_OSPF (lsa, LSA_REFRESH)) vty_out (vty, "debug ospf lsa refresh%s", VTY_NEWLINE); + if (IS_CONF_DEBUG_OSPF (lsa, LSA_LOCK)) + vty_out (vty, "debug ospf lsa lock%s", VTY_NEWLINE); write = 1; } diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h index fb81371..8d81ff1 100644 --- a/ospfd/ospf_dump.h +++ b/ospfd/ospf_dump.h @@ -49,7 +49,8 @@ #define OSPF_DEBUG_LSA_GENERATE 0x01 #define OSPF_DEBUG_LSA_FLOODING 0x02 #define OSPF_DEBUG_LSA_INSTALL 0x04 #define OSPF_DEBUG_LSA_REFRESH 0x08 -#define OSPF_DEBUG_LSA 0x0F +#define OSPF_DEBUG_LSA_LOCK 0x10 +#define OSPF_DEBUG_LSA 0xFF #define OSPF_DEBUG_ZEBRA_INTERFACE 0x01 #define OSPF_DEBUG_ZEBRA_REDISTRIBUTE 0x02 diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index d7ab859..39dcd67 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -72,7 +72,7 @@ ospf_flood_delayed_lsa_ack (struct ospf_ return; /* Schedule a delayed LSA Ack to be sent */ - listnode_add (inbr->oi->ls_ack, ospf_lsa_lock (lsa)); + listnode_add (inbr->oi->ls_ack, ospf_lsa_lock (lsa)); /* delayed LSA Ack */ } /* Check LSA is related to external info. */ @@ -134,7 +134,7 @@ ospf_process_self_originated_lsa (struct case OSPF_ROUTER_LSA: /* Originate a new instance and schedule flooding */ /* It shouldn't be necessary, but anyway */ - ospf_lsa_unlock (area->router_lsa_self); + ospf_lsa_unlock (&area->router_lsa_self); area->router_lsa_self = ospf_lsa_lock (new); ospf_router_lsa_timer_add (area); @@ -170,7 +170,7 @@ #ifdef HAVE_OPAQUE_LSA } #endif /* HAVE_OPAQUE_LSA */ - ospf_lsa_unlock (oi->network_lsa_self); + ospf_lsa_unlock (&oi->network_lsa_self); oi->network_lsa_self = ospf_lsa_lock (new); /* Schedule network-LSA origination. */ @@ -797,7 +797,7 @@ ospf_ls_request_delete (struct ospf_neig { if (nbr->ls_req_last == lsa) { - ospf_lsa_unlock (nbr->ls_req_last); + ospf_lsa_unlock (&nbr->ls_req_last); nbr->ls_req_last = NULL; } @@ -813,7 +813,7 @@ ospf_ls_request_delete (struct ospf_neig void ospf_ls_request_delete_all (struct ospf_neighbor *nbr) { - ospf_lsa_unlock (nbr->ls_req_last); + ospf_lsa_unlock (&nbr->ls_req_last); nbr->ls_req_last = NULL; ospf_lsdb_delete_all (&nbr->ls_req); } @@ -922,7 +922,7 @@ ospf_ls_retransmit_clear (struct ospf_ne ospf_ls_retransmit_delete (nbr, lsa); } - ospf_lsa_unlock (nbr->ls_req_last); + ospf_lsa_unlock (&nbr->ls_req_last); nbr->ls_req_last = NULL; } @@ -994,3 +994,33 @@ ospf_lsa_flush_as (struct ospf *ospf, st ospf_flood_through_as (ospf, NULL, lsa); ospf_lsa_maxage (ospf, lsa); } + +void +ospf_lsa_flush (struct ospf *ospf, struct ospf_lsa *lsa) +{ + lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); + + switch (lsa->data->type) + { + case OSPF_ROUTER_LSA: + case OSPF_NETWORK_LSA: + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + case OSPF_AS_NSSA_LSA: +#ifdef HAVE_OPAQUE_LSA + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: +#endif /* HAVE_OPAQUE_LSA */ + ospf_lsa_flush_area (lsa, lsa->area); + break; + case OSPF_AS_EXTERNAL_LSA: +#ifdef HAVE_OPAQUE_LSA + case OSPF_OPAQUE_AS_LSA: +#endif /* HAVE_OPAQUE_LSA */ + ospf_lsa_flush_as (ospf, lsa); + break; + default: + zlog_info ("%s: Unknown LSA type %u", __func__, lsa->data->type); + break; + } +} diff --git a/ospfd/ospf_flood.h b/ospfd/ospf_flood.h index 5382e8f..1ab11b8 100644 --- a/ospfd/ospf_flood.h +++ b/ospfd/ospf_flood.h @@ -66,6 +66,7 @@ extern void ospf_flood_lsa_area (struct extern void ospf_flood_lsa_as (struct ospf_lsa *); extern void ospf_lsa_flush_area (struct ospf_lsa *, struct ospf_area *); extern void ospf_lsa_flush_as (struct ospf *, struct ospf_lsa *); +extern void ospf_lsa_flush (struct ospf *, struct ospf_lsa *); extern struct external_info *ospf_external_info_check (struct ospf_lsa *); extern void ospf_lsdb_init (struct ospf_lsdb *); diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index b94cfa3..1a67e6f 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -289,7 +289,7 @@ ospf_if_cleanup (struct ospf_interface * /* Cleanup Link State Acknowlegdment list. */ for (ALL_LIST_ELEMENTS (oi->ls_ack, node, nnode, lsa)) - ospf_lsa_unlock (lsa); + ospf_lsa_unlock (&lsa); /* oi->ls_ack */ list_delete_all_node (oi->ls_ack); oi->crypt_seqnum = 0; @@ -302,7 +302,7 @@ ospf_if_cleanup (struct ospf_interface * oi->nbr_self = ospf_nbr_new (oi); ospf_nbr_add_self (oi); - ospf_lsa_unlock (oi->network_lsa_self); + ospf_lsa_unlock (&oi->network_lsa_self); oi->network_lsa_self = NULL; OSPF_TIMER_OFF (oi->t_network_lsa_self); } diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c index 0875e92..829ea00 100644 --- a/ospfd/ospf_ism.c +++ b/ospfd/ospf_ism.c @@ -593,7 +593,7 @@ #endif OSPF_TIMER_OFF (oi->t_network_lsa_self); } - ospf_lsa_unlock (oi->network_lsa_self); + ospf_lsa_unlock (&oi->network_lsa_self); oi->network_lsa_self = NULL; } diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 7c3be3d..6913014 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -226,8 +226,10 @@ ospf_lsa_new () new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa)); memset (new, 0, sizeof (struct ospf_lsa)); + if (IS_DEBUG_OSPF (lsa, LSA)) + zlog_debug ("LSA: created %p", new); + new->flags = 0; - new->lock = 1; new->retransmit_counter = 0; gettimeofday (&new->tv_recv, NULL); new->tv_orig = new->tv_recv; @@ -248,8 +250,7 @@ ospf_lsa_dup (struct ospf_lsa *lsa) new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa)); memcpy (new, lsa, sizeof (struct ospf_lsa)); - UNSET_FLAG (new->flags, OSPF_LSA_DISCARD); - new->lock = 1; + new->lock = 0; new->retransmit_counter = 0; new->data = ospf_lsa_data_dup (lsa->data); @@ -289,36 +290,32 @@ struct ospf_lsa * ospf_lsa_lock (struct ospf_lsa *lsa) { lsa->lock++; + + if (IS_DEBUG_OSPF(lsa, LSA_LOCK)) + zlog_debug ("%15s: lsa: %18p cnt: %u", __func__, lsa, lsa->lock); + return lsa; } /* Unlock LSA. */ void -ospf_lsa_unlock (struct ospf_lsa *lsa) +ospf_lsa_unlock (struct ospf_lsa **lsa) { /* This is sanity check. */ - if (!lsa) + if (!lsa || !*lsa) return; - lsa->lock--; + (*lsa)->lock--; - assert (lsa->lock >= 0); + if (IS_DEBUG_OSPF(lsa, LSA_LOCK)) + zlog_debug ("%15s: lsa: %18p cnt: %u", __func__, *lsa, (*lsa)->lock); - if (lsa->lock == 0) - { - assert (CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD)); - ospf_lsa_free (lsa); - } -} + assert ((*lsa)->lock >= 0); -/* Check discard flag. */ -void -ospf_lsa_discard (struct ospf_lsa *lsa) -{ - if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD)) + if ((*lsa)->lock == 0) { - SET_FLAG (lsa->flags, OSPF_LSA_DISCARD); - ospf_lsa_unlock (lsa); + ospf_lsa_free (*lsa); + *lsa = NULL; } } @@ -400,7 +397,7 @@ lsa_header_set (struct stream *s, u_char lsah = (struct lsa_header *) STREAM_DATA (s); - lsah->ls_age = htons (0); + lsah->ls_age = htons (OSPF_LSA_INITIAL_AGE); lsah->options = options; lsah->type = type; lsah->id = id; @@ -892,7 +889,7 @@ ospf_router_lsa_originate (struct ospf_a { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("LSA[Type1]: AdvRouter is 0, discard"); - ospf_lsa_discard (new); + ospf_lsa_free (new); return NULL; } @@ -1043,7 +1040,7 @@ ospf_router_lsa_update_timer (struct thr zlog_debug("LSA[Type%d:%s]: Refresh router-LSA for Area %s", lsa->data->type, inet_ntoa (lsa->data->id), area_str); ospf_lsa_flush_area (lsa, area); - ospf_lsa_unlock (area->router_lsa_self); + ospf_lsa_unlock (&area->router_lsa_self); area->router_lsa_self = NULL; /* Refresh router-LSA, (not install) and flood through area. */ @@ -1849,7 +1846,7 @@ ospf_install_flood_nssa (struct ospf *os { if (IS_DEBUG_OSPF_NSSA) zlog_debug ("LSA[Type-7]: Could not build FWD-ADDR"); - ospf_lsa_discard(new); + ospf_lsa_free (new); return; } } @@ -1905,7 +1902,6 @@ ospf_lsa_translated_nssa_new (struct osp /* add translated flag, checksum and lock new lsa */ SET_FLAG (new->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7 */ ospf_lsa_checksum (new->data); - new = ospf_lsa_lock (new); return new; } @@ -2517,7 +2513,7 @@ ospf_router_lsa_install (struct ospf *os ospf_router_lsa_timer, OSPF_LS_REFRESH_TIME); /* Set self-originated router-LSA. */ - ospf_lsa_unlock (area->router_lsa_self); + ospf_lsa_unlock (&area->router_lsa_self); area->router_lsa_self = ospf_lsa_lock (new); if (IS_DEBUG_OSPF (lsa, LSA_INSTALL)) @@ -2561,7 +2557,7 @@ ospf_network_lsa_install (struct ospf *o ospf_network_lsa_refresh_timer, OSPF_LS_REFRESH_TIME); - ospf_lsa_unlock (oi->network_lsa_self); + ospf_lsa_unlock (&oi->network_lsa_self); oi->network_lsa_self = ospf_lsa_lock (new); } @@ -2679,6 +2675,17 @@ ospf_discard_from_db (struct ospf *ospf, { struct ospf_lsa *old; + if (!lsdb) + { + zlog_warn ("%s: Called with NULL lsdb!", __func__); + if (!lsa) + zlog_warn ("%s: and NULL LSA!", __func__); + else + zlog_warn ("LSA[Type%d:%s]: not associated with LSDB!", + lsa->data->type, inet_ntoa (lsa->data->id)); + return; + } + old = ospf_lsdb_lookup (lsdb, lsa); if (!old) @@ -2708,7 +2715,6 @@ #endif /* HAVE_OPAQUE_LSA */ } ospf_lsa_maxage_delete (ospf, old); - ospf_lsa_discard (old); } struct ospf_lsa * @@ -2902,7 +2908,7 @@ #endif /* HAVE_OPAQUE_LSA */ new->data->type, inet_ntoa (new->data->id), lsa); - ospf_lsa_maxage (ospf, lsa); + ospf_lsa_flush (ospf, lsa); } return new; @@ -2934,35 +2940,6 @@ ospf_check_nbr_status (struct ospf *ospf } -#ifdef ORIGINAL_CODING -/* This function flood the maxaged LSA to DR. */ -void -ospf_maxage_flood (struct ospf_lsa *lsa) -{ - switch (lsa->data->type) - { - case OSPF_ROUTER_LSA: - case OSPF_NETWORK_LSA: - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - case OSPF_AS_NSSA_LSA: -#ifdef HAVE_OPAQUE_LSA - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: -#endif /* HAVE_OPAQUE_LSA */ - ospf_flood_through_area (lsa->area, NULL, lsa); - break; - case OSPF_AS_EXTERNAL_LSA: -#ifdef HAVE_OPAQUE_LSA - case OSPF_OPAQUE_AS_LSA: -#endif /* HAVE_OPAQUE_LSA */ - ospf_flood_through_as (NULL, lsa); - break; - default: - break; - } -} -#endif /* ORIGINAL_CODING */ static int ospf_maxage_lsa_remover (struct thread *thread) @@ -2998,13 +2975,6 @@ ospf_maxage_lsa_remover (struct thread * zlog_debug ("LSA[Type%d:%s]: MaxAge LSA removed from list", lsa->data->type, inet_ntoa (lsa->data->id)); - /* Flood max age LSA. */ -#ifdef ORIGINAL_CODING - ospf_maxage_flood (lsa); -#else /* ORIGINAL_CODING */ - ospf_flood_through (ospf, NULL, lsa); -#endif /* ORIGINAL_CODING */ - if (lsa->flags & OSPF_LSA_PREMATURE_AGE) { if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) @@ -3014,8 +2984,14 @@ #endif /* ORIGINAL_CODING */ } /* Remove from lsdb. */ - ospf_discard_from_db (ospf, lsa->lsdb, lsa); - ospf_lsdb_delete (lsa->lsdb, lsa); + if (lsa->lsdb) + { + ospf_discard_from_db (ospf, lsa->lsdb, lsa); + ospf_lsdb_delete (lsa->lsdb, lsa); + } + else + zlog_warn ("%s: LSA[Type%d:%s]: No associated LSDB!", __func__, + lsa->data->type, inet_ntoa (lsa->data->id)); } /* A MaxAge LSA must be removed immediately from the router's link @@ -3023,7 +2999,8 @@ #endif /* ORIGINAL_CODING */ neighbor Link state retransmission lists and b) none of the router's neighbors are in states Exchange or Loading. */ if (reschedule) - OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 2); + OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, + ospf->maxage_delay); return 0; } @@ -3049,10 +3026,15 @@ ospf_lsa_maxage_delete (struct ospf *osp if ((n = listnode_lookup (ospf->maxage_lsa, lsa))) { list_delete_node (ospf->maxage_lsa, n); - ospf_lsa_unlock (lsa); + ospf_lsa_unlock (&lsa); /* maxage_lsa */ } } +/* Add LSA onto the MaxAge list, and schedule for removal. + * This does *not* lead to the LSA being flooded, that must be taken + * care of elsewhere, see, e.g., ospf_lsa_flush* (which are callers of this + * function). + */ void ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa) { @@ -3071,7 +3053,8 @@ ospf_lsa_maxage (struct ospf *ospf, stru if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) zlog_debug ("LSA[%s]: MaxAge LSA remover scheduled.", dump_lsa_key (lsa)); - OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 2); + OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, + ospf->maxage_delay); } static int @@ -3431,6 +3414,7 @@ ospf_lsa_flush_schedule (struct ospf *os switch (lsa->data->type) { #ifdef HAVE_OPAQUE_LSA + /* Opaque wants to be notified of flushes */ case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: @@ -3438,7 +3422,7 @@ #ifdef HAVE_OPAQUE_LSA break; #endif /* HAVE_OPAQUE_LSA */ default: - ospf_lsa_maxage (ospf, lsa); + ospf_lsa_flush (ospf, lsa); break; } @@ -3464,7 +3448,7 @@ ospf_flush_self_originated_lsas_now (str zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id)); ospf_lsa_flush_area (lsa, area); - ospf_lsa_unlock (area->router_lsa_self); + ospf_lsa_unlock (&area->router_lsa_self); area->router_lsa_self = NULL; OSPF_TIMER_OFF (area->t_router_lsa_self); } @@ -3479,7 +3463,7 @@ ospf_flush_self_originated_lsas_now (str zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id)); ospf_lsa_flush_area (oi->network_lsa_self, area); - ospf_lsa_unlock (oi->network_lsa_self); + ospf_lsa_unlock (&oi->network_lsa_self); oi->network_lsa_self = NULL; OSPF_TIMER_OFF (oi->t_network_lsa_self); } @@ -3648,7 +3632,7 @@ ospf_lsa_action (struct thread *t) break; } - ospf_lsa_unlock (data->lsa); + ospf_lsa_unlock (&data->lsa); /* Message */ XFREE (MTYPE_OSPF_MESSAGE, data); return 0; } @@ -3663,7 +3647,7 @@ ospf_schedule_lsa_flood_area (struct osp data->action = LSA_ACTION_FLOOD_AREA; data->area = area; - data->lsa = ospf_lsa_lock (lsa); + data->lsa = ospf_lsa_lock (lsa); /* Message / Flood area */ thread_add_event (master, ospf_lsa_action, data, 0); } @@ -3678,7 +3662,7 @@ ospf_schedule_lsa_flush_area (struct osp data->action = LSA_ACTION_FLUSH_AREA; data->area = area; - data->lsa = ospf_lsa_lock (lsa); + data->lsa = ospf_lsa_lock (lsa); /* Message / Flush area */ thread_add_event (master, ospf_lsa_action, data, 0); } @@ -3761,7 +3745,8 @@ ospf_refresher_register_lsa (struct ospf inet_ntoa (lsa->data->id), LS_AGE (lsa), index); if (!ospf->lsa_refresh_queue.qs[index]) ospf->lsa_refresh_queue.qs[index] = list_new (); - listnode_add (ospf->lsa_refresh_queue.qs[index], ospf_lsa_lock (lsa)); + listnode_add (ospf->lsa_refresh_queue.qs[index], + ospf_lsa_lock (lsa)); /* lsa_refresh_queue */ lsa->refresh_list = index; if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) zlog_debug ("LSA[Refresh:%s]: ospf_refresher_register_lsa(): " @@ -3783,7 +3768,7 @@ ospf_refresher_unregister_lsa (struct os list_free (refresh_list); ospf->lsa_refresh_queue.qs[lsa->refresh_list] = NULL; } - ospf_lsa_unlock (lsa); + ospf_lsa_unlock (&lsa); /* Refresh list */ lsa->refresh_list = -1; } } @@ -3837,7 +3822,7 @@ ospf_lsa_refresh_walker (struct thread * inet_ntoa (lsa->data->id), lsa, i); list_delete_node (refresh_list, node); - ospf_lsa_unlock (lsa); + ospf_lsa_unlock (&lsa); /* refresh list */ lsa->refresh_list = -1; listnode_add (lsa_to_refresh, lsa); } diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index 9e480de..10816a2 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -77,7 +77,6 @@ #define OSPF_LSA_SELF 0x01 #define OSPF_LSA_SELF_CHECKED 0x02 #define OSPF_LSA_RECEIVED 0x04 #define OSPF_LSA_APPROVED 0x08 -#define OSPF_LSA_DISCARD 0x10 #define OSPF_LSA_LOCAL_XLT 0x20 #define OSPF_LSA_PREMATURE_AGE 0x40 @@ -245,8 +244,7 @@ extern struct ospf_lsa *ospf_lsa_new (vo extern struct ospf_lsa *ospf_lsa_dup (struct ospf_lsa *); extern void ospf_lsa_free (struct ospf_lsa *); extern struct ospf_lsa *ospf_lsa_lock (struct ospf_lsa *); -extern void ospf_lsa_unlock (struct ospf_lsa *); -extern void ospf_lsa_discard (struct ospf_lsa *); +extern void ospf_lsa_unlock (struct ospf_lsa **); extern struct lsa_header *ospf_lsa_data_new (size_t); extern struct lsa_header *ospf_lsa_data_dup (struct lsa_header *); diff --git a/ospfd/ospf_lsdb.c b/ospfd/ospf_lsdb.c index c0ec4b3..a992cf4 100644 --- a/ospfd/ospf_lsdb.c +++ b/ospfd/ospf_lsdb.c @@ -81,6 +81,31 @@ lsdb_prefix_set (struct prefix_ls *lp, s lp->adv_router = lsa->data->adv_router; } +static void +ospf_lsdb_delete_entry (struct ospf_lsdb *lsdb, struct route_node *rn) +{ + struct ospf_lsa *lsa = rn->info; + + if (!lsa) + return; + + assert (rn->table == lsdb->type[lsa->data->type].db); + + if (IS_LSA_SELF (lsa)) + lsdb->type[lsa->data->type].count_self--; + lsdb->type[lsa->data->type].count--; + lsdb->type[lsa->data->type].checksum -= ntohs(lsa->data->checksum); + lsdb->total--; + rn->info = NULL; + route_unlock_node (rn); +#ifdef MONITOR_LSDB_CHANGE + if (lsdb->del_lsa_hook != NULL) + (* lsdb->del_lsa_hook)(lsa); +#endif /* MONITOR_LSDB_CHANGE */ + ospf_lsa_unlock (&lsa); /* lsdb */ + return; +} + /* Add new LSA to lsdb. */ void ospf_lsdb_add (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) @@ -88,36 +113,30 @@ ospf_lsdb_add (struct ospf_lsdb *lsdb, s struct route_table *table; struct prefix_ls lp; struct route_node *rn; - struct ospf_lsa *old; table = lsdb->type[lsa->data->type].db; lsdb_prefix_set (&lp, lsa); rn = route_node_get (table, (struct prefix *)&lp); - if (!rn->info) - { - if (IS_LSA_SELF (lsa)) - lsdb->type[lsa->data->type].count_self++; - lsdb->type[lsa->data->type].count++; - lsdb->total++; - } - else - { - if (rn->info == lsa) - return; - - old = rn->info; - lsdb->type[old->data->type].checksum -= ntohs(old->data->checksum); + + /* nothing to do? */ + if (rn->info && rn->info == lsa) + return; + + /* purge old entry? */ + if (rn->info) + ospf_lsdb_delete_entry (lsdb, rn); - ospf_lsa_unlock (rn->info); - route_unlock_node (rn); - } + if (IS_LSA_SELF (lsa)) + lsdb->type[lsa->data->type].count_self++; + lsdb->type[lsa->data->type].count++; + lsdb->total++; #ifdef MONITOR_LSDB_CHANGE if (lsdb->new_lsa_hook != NULL) (* lsdb->new_lsa_hook)(lsa); #endif /* MONITOR_LSDB_CHANGE */ lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum); - rn->info = ospf_lsa_lock (lsa); + rn->info = ospf_lsa_lock (lsa); /* lsdb */ } void @@ -127,27 +146,30 @@ ospf_lsdb_delete (struct ospf_lsdb *lsdb struct prefix_ls lp; struct route_node *rn; + if (!lsdb) + { + zlog_warn ("%s: Called with NULL LSDB", __func__); + if (lsa) + zlog_warn ("LSA[Type%d:%s]: LSA %p, lsa->lsdb %p", + lsa->data->type, inet_ntoa (lsa->data->id), + lsa, lsa->lsdb); + return; + } + + if (!lsa) + { + zlog_warn ("%s: Called with NULL LSA", __func__); + return; + } + table = lsdb->type[lsa->data->type].db; lsdb_prefix_set (&lp, lsa); rn = route_node_lookup (table, (struct prefix *) &lp); - if (rn) - if (rn->info == lsa) - { - if (IS_LSA_SELF (lsa)) - lsdb->type[lsa->data->type].count_self--; - lsdb->type[lsa->data->type].count--; - lsdb->type[lsa->data->type].checksum -= ntohs(lsa->data->checksum); - lsdb->total--; - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); -#ifdef MONITOR_LSDB_CHANGE - if (lsdb->del_lsa_hook != NULL) - (* lsdb->del_lsa_hook)(lsa); -#endif /* MONITOR_LSDB_CHANGE */ - ospf_lsa_unlock (lsa); - return; - } + if (rn && (rn->info == lsa)) + { + ospf_lsdb_delete_entry (lsdb, rn); + route_unlock_node (rn); /* route_node_lookup */ + } } void @@ -155,28 +177,14 @@ ospf_lsdb_delete_all (struct ospf_lsdb * { struct route_table *table; struct route_node *rn; - struct ospf_lsa *lsa; int i; for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { table = lsdb->type[i].db; for (rn = route_top (table); rn; rn = route_next (rn)) - if ((lsa = (rn->info)) != NULL) - { - if (IS_LSA_SELF (lsa)) - lsdb->type[i].count_self--; - lsdb->type[i].count--; - lsdb->type[i].checksum -= ntohs(lsa->data->checksum); - lsdb->total--; - rn->info = NULL; - route_unlock_node (rn); -#ifdef MONITOR_LSDB_CHANGE - if (lsdb->del_lsa_hook != NULL) - (* lsdb->del_lsa_hook)(lsa); -#endif /* MONITOR_LSDB_CHANGE */ - ospf_lsa_unlock (lsa); - } + if (rn->info != NULL) + ospf_lsdb_delete_entry (lsdb, rn); } } diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 8a93f0e..bd2af54 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -777,7 +777,7 @@ #endif if (oi->network_lsa_self && oi->full_nbrs == 0) { ospf_lsa_flush_area (oi->network_lsa_self, oi->area); - ospf_lsa_unlock (oi->network_lsa_self); + ospf_lsa_unlock (&oi->network_lsa_self); oi->network_lsa_self = NULL; OSPF_TIMER_OFF (oi->t_network_lsa_self); } diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index f2496cf..df0962f 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -708,7 +708,7 @@ free_opaque_info_per_id (void *val) OSPF_TIMER_OFF (oipi->t_opaque_lsa_self); if (oipi->lsa != NULL) - ospf_lsa_unlock (oipi->lsa); + ospf_lsa_unlock (&oipi->lsa); XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi); return; } @@ -1554,7 +1554,7 @@ ospf_opaque_lsa_install (struct ospf_lsa if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL) { - ospf_lsa_unlock (oipi->lsa); + ospf_lsa_unlock (&oipi->lsa); oipi->lsa = ospf_lsa_lock (lsa); } /* Register the new lsa entry and get its control info. */ @@ -1630,7 +1630,7 @@ ospf_opaque_lsa_refresh (struct ospf_lsa zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id)); lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - ospf_lsa_maxage (ospf, lsa); + ospf_lsa_flush (ospf, lsa); } else (* functab->lsa_refresher)(lsa); @@ -2108,7 +2108,7 @@ ospf_opaque_lsa_flush_schedule (struct o zlog_debug ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr))); /* This lsa will be flushed and removed eventually. */ - ospf_lsa_maxage (lsa0->area->ospf, lsa); + ospf_lsa_flush (lsa0->area->ospf, lsa); out: return; @@ -2234,7 +2234,7 @@ ospf_opaque_self_originated_lsa_received u_char before; if ((top = oi_to_top (nbr->oi)) == NULL) - goto out; + return; before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque); @@ -2259,19 +2259,14 @@ ospf_opaque_self_originated_lsa_received break; default: zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type); - goto out; + return; } - ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */ - if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque)) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("Block Opaque-LSA origination: OFF -> ON"); } - -out: - return; } void diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index d6aca71..d63bd24 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1035,17 +1035,14 @@ #endif /* HAVE_OPAQUE_LSA */ /* Lookup received LSA, then add LS request list. */ find = ospf_lsa_lookup_by_header (oi->area, lsah); if (!find || ospf_lsa_more_recent (find, new) < 0) - { - ospf_ls_request_add (nbr, new); - ospf_lsa_discard (new); - } + ospf_ls_request_add (nbr, new); /* *Always* adds LSA to LSDB */ else { /* Received LSA is not recent. */ if (IS_DEBUG_OSPF_EVENT) zlog_debug ("Packet [DD:RECV]: LSA received Type %d, " "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id)); - ospf_lsa_discard (new); + ospf_lsa_free (new); continue; } } @@ -1577,7 +1574,7 @@ #endif /* HAVE_OPAQUE_LSA */ if (IS_DEBUG_OSPF_EVENT) zlog_debug("LSA[Type%d:%s]: %p new LSA created with Link State Update", lsa->data->type, inet_ntoa (lsa->data->id), lsa); - listnode_add (lsas, lsa); + listnode_add (lsas, ospf_lsa_lock (lsa)); /* ospf_ls_upd_list_lsa tmp list */ } return lsas; @@ -1591,7 +1588,7 @@ ospf_upd_list_clean (struct list *lsas) struct ospf_lsa *lsa; for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa)) - ospf_lsa_discard (lsa); + ospf_lsa_unlock (&lsa); /* ospf_ls_upd_list_lsa tmp list */ list_delete (lsas); } @@ -1652,19 +1649,30 @@ #ifdef HAVE_OPAQUE_LSA ospf_opaque_adjust_lsreq (nbr, lsas); #endif /* HAVE_OPAQUE_LSA */ -#define DISCARD_LSA(L,N) {\ +#define LSA_DONE(L,R) {\ if (IS_DEBUG_OSPF_EVENT) \ - zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \ - ospf_lsa_discard (L); \ - continue; } + zlog_debug ("%s: lsa %p, result: %s", __func__, (L), (R)); \ + list_delete_node (lsas, node); \ + ospf_lsa_unlock (&(L)); /* ospf_ls_upd_list_lsa tmp list */ \ + continue;\ + } - /* Process each LSA received in the one packet. */ + /* Process each LSA received in the one packet. + * + * Each LSA is new, but locked once by ospf_ls_upd_list_lsa. + * Each loop iteration *must* end by unlocking the LSA, preferably + * by using LSA_DONE (which also provides some useful debug output). + * + * If any called functions store a reference to the LSA being + * considered, obviously it is that functions responsibility to + * increment the refcount. (ie 'lock'). + */ for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa)) { struct ospf_lsa *ls_ret, *current; int ret = 1; - if (IS_DEBUG_OSPF_NSSA) + if (IS_DEBUG_OSPF_EVENT) { char buf1[INET_ADDRSTRLEN]; char buf2[INET_ADDRSTRLEN]; @@ -1680,7 +1688,6 @@ #define DISCARD_LSA(L,N) {\ buf3, INET_ADDRSTRLEN)); } - listnode_delete (lsas, lsa); /* We don't need it in list anymore */ /* Validate Checksum - Done above by ospf_ls_upd_list_lsa() */ @@ -1701,17 +1708,17 @@ #define DISCARD_LSA(L,N) {\ /* Reject from STUB or NSSA */ if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT) { - DISCARD_LSA (lsa, 1); if (IS_DEBUG_OSPF_NSSA) zlog_debug("Incoming External LSA Discarded: We are NSSA/STUB Area"); + LSA_DONE (lsa, "Discarded, area not external capable"); } if (lsa->data->type == OSPF_AS_NSSA_LSA) if (nbr->oi->area->external_routing != OSPF_AREA_NSSA) { - DISCARD_LSA (lsa,2); if (IS_DEBUG_OSPF_NSSA) zlog_debug("Incoming NSSA LSA Discarded: Not NSSA Area"); + LSA_DONE (lsa,"Discarded, not NSSA area"); } /* Find the LSA in the current database. */ @@ -1733,7 +1740,7 @@ #define DISCARD_LSA(L,N) {\ /* Discard LSA. */ zlog_info ("Link State Update[%s]: LS age is equal to MaxAge.", dump_lsa_key(lsa)); - DISCARD_LSA (lsa, 3); + LSA_DONE (lsa, "Discarded, Maxage LSA, but no current copy"); } #ifdef HAVE_OPAQUE_LSA @@ -1745,16 +1752,19 @@ #ifdef HAVE_OPAQUE_LSA * be a case that self-originated LSA with MaxAge still remain * in the routing domain. * Just send an LSAck message to cease retransmission. + * + * XXX: If this is a genuine problem, it's surely not specific + * to Opaque LSA.. */ if (IS_LSA_MAXAGE (lsa)) { zlog_warn ("LSA[%s]: Boomerang effect?", dump_lsa_key (lsa)); ospf_ls_ack_send (nbr, lsa); - ospf_lsa_discard (lsa); if (current != NULL && ! IS_LSA_MAXAGE (current)) ospf_opaque_lsa_refresh_schedule (current); - continue; + + LSA_DONE (lsa, "Got back own LSA with MaxAge"); } /* @@ -1780,17 +1790,17 @@ #ifdef HAVE_OPAQUE_LSA ospf_opaque_self_originated_lsa_received (nbr, lsa); ospf_ls_ack_send (nbr, lsa); - - continue; + LSA_DONE (lsa, "Acked"); } } #endif /* HAVE_OPAQUE_LSA */ - /* It might be happen that received LSA is self-originated network LSA, but - * router ID is cahnged. So, we should check if LSA is a network-LSA whose - * Link State ID is one of the router's own IP interface addresses but whose - * Advertising Router is not equal to the router's own Router ID - * According to RFC 2328 12.4.2 and 13.4 this LSA should be flushed. + /* It might be happen that received LSA is self-originated + * network LSA, but router ID is cahnged. So, we should check if + * LSA is a network-LSA whose Link State ID is one of the + * router's own IP interface addresses but whose Advertising + * Router is not equal to the router's own Router ID According to + * RFC 2328 12.4.2 and 13.4 this LSA should be flushed. */ if(lsa->data->type == OSPF_NETWORK_LSA) @@ -1807,15 +1817,12 @@ #endif /* HAVE_OPAQUE_LSA */ if((IPV4_ADDR_SAME(&out_if->address->u.prefix4, &lsa->data->id)) && (!(IPV4_ADDR_SAME(&oi->ospf->router_id, &lsa->data->adv_router)))) { - if(out_if->network_lsa_self) - { - ospf_lsa_flush_area(lsa,out_if->area); - if(IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d", - lsa, (int) lsa->data->type); - ospf_lsa_discard (lsa); - Flag = 1; - } + if (out_if->network_lsa_self) + { + ospf_lsa_flush_area(lsa,out_if->area); + Flag = 1; + LSA_DONE (lsa, "Flushed, our Net LSA with different RID"); + } break; } } @@ -1833,8 +1840,8 @@ #endif /* HAVE_OPAQUE_LSA */ { /* Actual flooding procedure. */ if (ospf_flood (oi->ospf, nbr, current, lsa) < 0) /* Trap NSSA later. */ - DISCARD_LSA (lsa, 4); - continue; + LSA_DONE (lsa, "Discarded, valid LSA but not flooded"); + LSA_DONE (lsa, "Flooded"); } /* (6) Else, If there is an instance of the LSA on the sending @@ -1851,9 +1858,7 @@ #endif /* HAVE_OPAQUE_LSA */ dump_lsa_key(lsa)); /* Clean list of LSAs. */ - ospf_upd_list_clean (lsas); - /* this lsa is not on lsas list already. */ - ospf_lsa_discard (lsa); + ospf_upd_list_clean (lsas); return; } @@ -1882,7 +1887,7 @@ #endif /* HAVE_OPAQUE_LSA */ if (NBR_IS_DR (nbr)) listnode_add (oi->ls_ack, ospf_lsa_lock (lsa)); - DISCARD_LSA (lsa, 5); + LSA_DONE (lsa, "Delayed ACK, Implied acknowledgement"); } else /* Acknowledge the receipt of the LSA by sending a @@ -1890,7 +1895,7 @@ #endif /* HAVE_OPAQUE_LSA */ interface. */ { ospf_ls_ack_send (nbr, lsa); - DISCARD_LSA (lsa, 6); + LSA_DONE (lsa, "ACKed"); } } @@ -1905,9 +1910,9 @@ #endif /* HAVE_OPAQUE_LSA */ { if (IS_LSA_MAXAGE (current) && current->data->ls_seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER)) - { - DISCARD_LSA (lsa, 7); - } + { + LSA_DONE (lsa, "Discarded, current max-seq LSA still present"); + } /* Otherwise, as long as the database copy has not been sent in a Link State Update within the last MinLSArrival seconds, send the database copy back to the sending neighbor, encapsulated within @@ -1926,10 +1931,12 @@ #endif /* HAVE_OPAQUE_LSA */ int2tv (OSPF_MIN_LS_ARRIVAL)) > 0) /* Trap NSSA type later.*/ ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT); - DISCARD_LSA (lsa, 8); + LSA_DONE (lsa, "Discarded, Current is more recent than received"); } } + LSA_DONE (lsa, "Discarded, not handled / no action"); } +#undef LSA_DONE assert (listcount (lsas) == 0); list_delete (lsas); @@ -1976,7 +1983,7 @@ ospf_ls_ack (struct ip *iph, struct ospf if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA) { lsa->data = NULL; - ospf_lsa_discard (lsa); + ospf_lsa_free (lsa); continue; } @@ -1993,7 +2000,7 @@ #endif /* HAVE_OPAQUE_LSA */ } lsa->data = NULL; - ospf_lsa_discard (lsa); + ospf_lsa_free (lsa); } return; @@ -2363,9 +2370,10 @@ ospf_read (struct thread *thread) { if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL) { - zlog_debug ("Packet from [%s] received on link %s" - " but no ospf_interface", - inet_ntoa (iph->ip_src), ifp->name); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug ("Packet from [%s] received on link %s" + " but no ospf_interface", + inet_ntoa (iph->ip_src), ifp->name); return 0; } } @@ -2644,7 +2652,7 @@ ospf_make_db_desc (struct ospf_interface unsigned long pp; int i; struct ospf_lsdb *lsdb; - + /* Set Interface MTU. */ if (oi->type == OSPF_IFTYPE_VIRTUALLINK) stream_putw (s, 0); @@ -2657,19 +2665,19 @@ #ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { if (IS_SET_DD_I (nbr->dd_flags) - || CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - /* - * Set O-bit in the outgoing DD packet for capablity negotiation, - * if one of following case is applicable. - * - * 1) WaitTimer expiration event triggered the neighbor state to - * change to Exstart, but no (valid) DD packet has received - * from the neighbor yet. - * - * 2) At least one DD packet with O-bit on has received from the - * neighbor. - */ - SET_FLAG (options, OSPF_OPTION_O); + || CHECK_FLAG (nbr->options, OSPF_OPTION_O)) + /* + * Set O-bit in the outgoing DD packet for capablity negotiation, + * if one of following case is applicable. + * + * 1) WaitTimer expiration event triggered the neighbor state to + * change to Exstart, but no (valid) DD packet has received + * from the neighbor yet. + * + * 2) At least one DD packet with O-bit on has received from the + * neighbor. + */ + SET_FLAG (options, OSPF_OPTION_O); } #endif /* HAVE_OPAQUE_LSA */ stream_putc (s, options); @@ -2704,39 +2712,38 @@ #endif /* HAVE_OPAQUE_LSA */ if ((lsa = rn->info) != NULL) { #ifdef HAVE_OPAQUE_LSA - if (IS_OPAQUE_LSA (lsa->data->type) - && (! CHECK_FLAG (options, OSPF_OPTION_O))) - { - /* Suppress advertising opaque-informations. */ - /* Remove LSA from DB summary list. */ - ospf_lsdb_delete (lsdb, lsa); - continue; - } + if (IS_OPAQUE_LSA (lsa->data->type) + && (!CHECK_FLAG (options, OSPF_OPTION_O))) + { + /* Suppress advertising opaque-informations. */ + /* Remove LSA from DB summary list. */ + ospf_lsdb_delete (lsdb, lsa); + continue; + } #endif /* HAVE_OPAQUE_LSA */ - if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD)) + if (!IS_LSA_MAXAGE (lsa)) { struct lsa_header *lsah; u_int16_t ls_age; - + /* DD packet overflows interface MTU. */ if (length + OSPF_LSA_HEADER_SIZE > ospf_packet_max (oi)) break; - + /* Keep pointer to LS age. */ lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_endp (s)); - + /* Proceed stream pointer. */ stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE); length += OSPF_LSA_HEADER_SIZE; - + /* Set LS age. */ ls_age = LS_AGE (lsa); lsah->ls_age = htons (ls_age); - } - + /* Remove LSA from DB summary list. */ ospf_lsdb_delete (lsdb, lsa); } @@ -2762,7 +2769,7 @@ ospf_make_ls_req_func (struct stream *s, stream_put_ipv4 (s, lsa->data->id.s_addr); stream_put_ipv4 (s, lsa->data->adv_router.s_addr); - ospf_lsa_unlock (nbr->ls_req_last); + ospf_lsa_unlock (&nbr->ls_req_last); nbr->ls_req_last = ospf_lsa_lock (lsa); *length += 12; @@ -2858,7 +2865,7 @@ ospf_make_ls_upd (struct ospf_interface count++; list_delete_node (update, node); - ospf_lsa_unlock (lsa); + ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */ } /* Now set #LSAs. */ @@ -2872,17 +2879,13 @@ ospf_make_ls_upd (struct ospf_interface static int ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s) { - struct list *rm_list; - struct listnode *node; + struct listnode *node, *nnode; u_int16_t length = OSPF_LS_ACK_MIN_SIZE; unsigned long delta = stream_get_endp(s) + 24; struct ospf_lsa *lsa; - rm_list = list_new (); - - for (ALL_LIST_ELEMENTS_RO (ack, node, lsa)) + for (ALL_LIST_ELEMENTS (ack, node, nnode, lsa)) { - lsa = listgetdata (node); assert (lsa); if (length + delta > ospf_packet_max (oi)) @@ -2891,21 +2894,10 @@ ospf_make_ls_ack (struct ospf_interface stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE); length += OSPF_LSA_HEADER_SIZE; - listnode_add (rm_list, lsa); + list_delete_node (ack, node); + ospf_lsa_unlock (&lsa); /* oi->ls_ack_direct.ls_ack */ } - /* Remove LSA from LS-Ack list. */ - /* XXX: this loop should be removed and the list move done in previous - * loop - */ - for (ALL_LIST_ELEMENTS_RO (rm_list, node, lsa)) - { - listnode_delete (ack, lsa); - ospf_lsa_unlock (lsa); - } - - list_delete (rm_list); - return length; } @@ -3394,10 +3386,7 @@ ospf_ls_upd_send (struct ospf_neighbor * rn->info = list_new (); for (ALL_LIST_ELEMENTS_RO (update, node, lsa)) - { - ospf_lsa_lock (lsa); - listnode_add (rn->info, lsa); - } + listnode_add (rn->info, ospf_lsa_lock (lsa)); /* oi->ls_upd_queue */ if (oi->t_ls_upd_event == NULL) oi->t_ls_upd_event = diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 10a94b8..6d531e0 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -904,7 +904,6 @@ ospf_mpls_te_lsa_new (struct ospf_area * if ((new->data = ospf_lsa_data_new (length)) == NULL) { zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?"); - ospf_lsa_unlock (new); new = NULL; stream_free (s); goto out; @@ -936,7 +935,6 @@ ospf_mpls_te_lsa_originate1 (struct ospf if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL) { zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?"); - ospf_lsa_unlock (new); goto out; } @@ -1054,7 +1052,6 @@ ospf_mpls_te_lsa_refresh (struct ospf_ls if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL) { zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?"); - ospf_lsa_unlock (new); goto out; } diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 79c4543..3bbe516 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -181,6 +181,7 @@ ospf_new (void) new->spf_hold_multiplier = 1; /* MaxAge init. */ + new->maxage_delay = OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT; new->maxage_lsa = list_new (); new->t_maxage_walker = thread_add_timer (master, ospf_lsa_maxage_walker, @@ -475,7 +476,7 @@ #endif /* HAVE_OPAQUE_LSA */ ospf_lsdb_free (ospf->lsdb); for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa)) - ospf_lsa_unlock (lsa); + ospf_lsa_unlock (&lsa); /* maxage_lsa */ list_delete (ospf->maxage_lsa); @@ -592,7 +593,7 @@ #endif /* HAVE_OPAQUE_LSA */ ospf_lsdb_delete_all (area->lsdb); ospf_lsdb_free (area->lsdb); - ospf_lsa_unlock (area->router_lsa_self); + ospf_lsa_unlock (&area->router_lsa_self); route_table_finish (area->ranges); list_delete (area->oiflist); @@ -905,7 +906,7 @@ ospf_ls_upd_queue_empty (struct ospf_int if ((lst = (struct list *) rn->info)) { for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa)) - ospf_lsa_unlock (lsa); + ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */ list_free (lst); rn->info = NULL; } diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index f2a6109..fdb3af1 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -56,6 +56,7 @@ #define OSPF_LS_REFRESH_TIME #endif #define OSPF_MIN_LS_INTERVAL 5 #define OSPF_MIN_LS_ARRIVAL 1 +#define OSPF_LSA_INITIAL_AGE 0 /* useful for debug */ #define OSPF_LSA_MAXAGE 3600 #define OSPF_CHECK_AGE 300 #define OSPF_LSA_MAXAGE_DIFF 900 @@ -64,7 +65,6 @@ #define OSPF_DEFAULT_DESTINATION #define OSPF_INITIAL_SEQUENCE_NUMBER 0x80000001 #define OSPF_MAX_SEQUENCE_NUMBER 0x7fffffff -#define OSPF_LSA_MAXAGE_CHECK_INTERVAL 30 #define OSPF_NSSA_TRANS_STABLE_DEFAULT 40 #define OSPF_ALLSPFROUTERS 0xe0000005 /* 224.0.0.5 */ @@ -256,8 +256,13 @@ #endif /* HAVE_OPAQUE_LSA */ #ifdef HAVE_OPAQUE_LSA struct thread *t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */ #endif /* HAVE_OPAQUE_LSA */ + +#define OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT 60 + unsigned int maxage_delay; /* Delay on Maxage remover timer, sec */ struct thread *t_maxage; /* MaxAge LSA remover timer. */ +#define OSPF_LSA_MAXAGE_CHECK_INTERVAL 30 struct thread *t_maxage_walker; /* MaxAge LSA checking timer. */ + struct thread *t_deferred_shutdown; /* deferred/stub-router shutdown timer*/ struct thread *t_write;