From 6452df092bf6b694ea62a0423ac242f10ab997f9 Mon Sep 17 00:00:00 2001 From: hasso Date: Sun, 15 Aug 2004 05:52:07 +0000 Subject: SVN revisions 916-920 from Zebra. ABR support is almost done. --- ospf6d/ChangeLog | 22 ++ ospf6d/ospf6_abr.c | 380 +++++++++++++++----- ospf6d/ospf6_abr.h | 8 +- ospf6d/ospf6_area.c | 186 ++++++++-- ospf6d/ospf6_area.h | 28 +- ospf6d/ospf6_asbr.c | 136 ++------ ospf6d/ospf6_flood.c | 886 +++++++++++++++++++++++++---------------------- ospf6d/ospf6_flood.h | 30 +- ospf6d/ospf6_interface.c | 29 +- ospf6d/ospf6_interface.h | 1 + ospf6d/ospf6_intra.c | 370 ++++++++------------ ospf6d/ospf6_intra.h | 14 +- ospf6d/ospf6_lsa.c | 241 ++++++------- ospf6d/ospf6_lsa.h | 65 ++-- ospf6d/ospf6_lsdb.c | 6 +- ospf6d/ospf6_lsdb.h | 5 +- ospf6d/ospf6_message.c | 164 ++++++--- ospf6d/ospf6_neighbor.c | 34 +- ospf6d/ospf6_proto.c | 7 +- ospf6d/ospf6_route.c | 26 ++ ospf6d/ospf6_route.h | 35 +- ospf6d/ospf6_spf.c | 13 +- ospf6d/ospf6_top.c | 101 +++++- ospf6d/ospf6_top.h | 2 +- ospf6d/ospf6d.c | 131 +++++-- ospf6d/ospf6d.h | 8 +- 26 files changed, 1721 insertions(+), 1207 deletions(-) (limited to 'ospf6d') diff --git a/ospf6d/ChangeLog b/ospf6d/ChangeLog index e9fe1195..52f4cefd 100644 --- a/ospf6d/ChangeLog +++ b/ospf6d/ChangeLog @@ -1,3 +1,25 @@ +2004-08-15 Yasuhiro Ohara + + * *.c: Area support almost done. (almost ! ;p) + * ospf6d.h: version 0.9.7i + +2004-08-15 Yasuhiro Ohara + + * ospf6_message.c: Bug cause BadLSReq is fixed. + * ospf6_abr.c: Border Router check. + * ospf6d.h: version 0.9.7h + +2004-08-14 Yasuhiro Ohara + + * ospf6_area.[ch], ospf6_abr.[ch]: area range, + border-routers, Inter-Area-Router-LSA origination + * ospf6d.h: version 0.9.7g + +2004-08-12 Yasuhiro Ohara + + * *.[c,h]: LSA refreshing is changed and cleaned up. + * ospf6d.h: version 0.9.7f + 2004-08-01 Yasuhiro Ohara * ospf6_abr.[ch]: add files for abr function. diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 04a55c46..397cef76 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -34,18 +34,42 @@ #include "ospf6_lsa.h" #include "ospf6_route.h" #include "ospf6_lsdb.h" +#include "ospf6_message.h" + #include "ospf6_top.h" #include "ospf6_area.h" #include "ospf6_interface.h" +#include "ospf6_neighbor.h" + #include "ospf6_abr.h" +#include "ospf6_flood.h" #include "ospf6d.h" unsigned char conf_debug_ospf6_abr; +int +ospf6_is_router_abr (struct ospf6 *o) +{ + listnode node; + struct ospf6_area *oa; + int area_count = 0; + + for (node = listhead (o->area_list); node; nextnode (node)) + { + oa = OSPF6_AREA (getdata (node)); + if (IS_AREA_ENABLED (oa)) + area_count++; + } + + if (area_count > 1) + return 1; + return 0; +} + /* RFC 2328 12.4.3. Summary-LSAs */ void -ospf6_abr_originate_prefix_to_area (struct ospf6_route *route, - struct ospf6_area *area) +ospf6_abr_originate_summary_to_area (struct ospf6_route *route, + struct ospf6_area *area) { struct ospf6_lsa *lsa, *old = NULL; struct ospf6_interface *oi; @@ -55,26 +79,63 @@ ospf6_abr_originate_prefix_to_area (struct ospf6_route *route, struct ospf6_lsa_header *lsa_header; caddr_t p; struct ospf6_inter_prefix_lsa *prefix_lsa; + struct ospf6_inter_router_lsa *router_lsa; + struct ospf6_route_table *summary_table = NULL; + u_int16_t type; + + if (IS_OSPF6_DEBUG_ABR) + { + char buf[64]; + if (route->type == OSPF6_DEST_TYPE_ROUTER) + { + inet_ntop (AF_INET, + &(ospf6_linkstate_prefix_adv_router (&route->prefix)), + buf, sizeof (buf)); + zlog_info ("Originating summary in area %s for ASBR %s", + area->name, buf); + } + else + { + prefix2str (&route->prefix, buf, sizeof (buf)); + zlog_info ("Originating summary in area %s for %s", + area->name, buf); + } + } - summary = ospf6_route_lookup (&route->prefix, area->summary_table); + if (route->type == OSPF6_DEST_TYPE_ROUTER) + summary_table = area->summary_router; + else + summary_table = area->summary_prefix; + summary = ospf6_route_lookup (&route->prefix, summary_table); if (summary) - old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTER_PREFIX), + old = ospf6_lsdb_lookup (summary->path.origin.type, summary->path.origin.id, area->ospf6->router_id, area->lsdb); /* if this route has just removed, remove corresponding LSA */ if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE)) { + if (IS_OSPF6_DEBUG_ABR) + zlog_info ("The route has just removed, purge previous LSA"); + if (summary) + ospf6_route_remove (summary, summary_table); if (old) - ospf6_lsa_premature_aging (old); + ospf6_lsa_purge (old); return; } - /* Only destination type network and address range are considered */ - if (route->type != OSPF6_DEST_TYPE_NETWORK) + /* Only destination type network, range or ASBR are considered */ + if (route->type != OSPF6_DEST_TYPE_NETWORK && + route->type != OSPF6_DEST_TYPE_RANGE && + (route->type != OSPF6_DEST_TYPE_ROUTER || + ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E))) { + if (IS_OSPF6_DEBUG_ABR) + zlog_info ("Route type is none of network, range nor ASBR, withdraw"); + if (summary) + ospf6_route_remove (summary, summary_table); if (old) - ospf6_lsa_premature_aging (old); + ospf6_lsa_purge (old); return; } @@ -82,95 +143,203 @@ ospf6_abr_originate_prefix_to_area (struct ospf6_route *route, if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 || route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) { + if (IS_OSPF6_DEBUG_ABR) + zlog_info ("Path type is external, withdraw"); + if (summary) + ospf6_route_remove (summary, summary_table); if (old) - ospf6_lsa_premature_aging (old); + ospf6_lsa_purge (old); return; } - /* do not generate if the route cost is greater or equal to LSInfinity */ - if (route->path.cost >= LS_INFINITY) + /* do not generate if the path's area is the same as target area */ + if (route->path.area_id == area->area_id) { + if (IS_OSPF6_DEBUG_ABR) + zlog_info ("The route is in the area itself, ignore"); + if (summary) + ospf6_route_remove (summary, summary_table); if (old) - ospf6_lsa_premature_aging (old); + ospf6_lsa_purge (old); return; } - /* if this is an inter-area route */ - if (route->path.type == OSPF6_PATH_TYPE_INTRA) + /* do not generate if the nexthops belongs to the target area */ + oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex); + if (oi && oi->area && oi->area == area) { - /* search for configured address range for the route's area */ - route_area = ospf6_area_lookup (route->path.area_id, area->ospf6); - assert (route_area); - range = ospf6_route_lookup_bestmatch (&route->prefix, - route_area->summary_table); + if (IS_OSPF6_DEBUG_ABR) + zlog_info ("The route's nexthop is in the same area, ignore"); + if (summary) + ospf6_route_remove (summary, summary_table); + if (old) + ospf6_lsa_purge (old); + return; } - /* ranges are ignored when originate backbone routes to transit area. - Otherwise, if ranges are configured, the route is suppressed. */ - if (range && (route->path.area_id != htonl (0) || ! area->transit_capability)) + /* do not generate if the route cost is greater or equal to LSInfinity */ + if (route->path.cost >= LS_INFINITY) { + if (IS_OSPF6_DEBUG_ABR) + zlog_info ("The cost exceeds LSInfinity, withdraw"); + if (summary) + ospf6_route_remove (summary, summary_table); if (old) - ospf6_lsa_premature_aging (old); - if (range->path.cost < route->path.cost) - range->path.cost = route->path.cost; - SET_FLAG (range->flag, OSPF6_ROUTE_HAVE_LONGER); + ospf6_lsa_purge (old); return; } - /* do not generate if the path's area is the same as target area */ - if (route->path.area_id == area->area_id) + /* if this is a route to ASBR */ + if (route->type == OSPF6_DEST_TYPE_ROUTER) { - if (old) - ospf6_lsa_premature_aging (old); - return; + /* Only the prefered best path is considered */ + if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)) + { + if (IS_OSPF6_DEBUG_ABR) + zlog_info ("This is the secondary path to the ASBR, ignore"); + if (summary) + ospf6_route_remove (summary, summary_table); + if (old) + ospf6_lsa_purge (old); + return; + } + + /* Do not generate if the area is stub */ + /* XXX */ } - /* do not generate if the nexthops belongs to the target area */ - oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex); - if (oi && oi->area && oi->area->area_id == area->area_id) + /* if this is an intra-area route, this may be suppressed by aggregation */ + if (route->type == OSPF6_DEST_TYPE_NETWORK && + route->path.type == OSPF6_PATH_TYPE_INTRA) { - if (old) - ospf6_lsa_premature_aging (old); - return; + /* search for configured address range for the route's area */ + route_area = ospf6_area_lookup (route->path.area_id, area->ospf6); + assert (route_area); + range = ospf6_route_lookup_bestmatch (&route->prefix, + route_area->range_table); + + /* ranges are ignored when originate backbone routes to transit area. + Otherwise, if ranges are configured, the route is suppressed. */ + if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) && + (route->path.area_id != BACKBONE_AREA_ID || + ! IS_AREA_TRANSIT (area))) + { + if (IS_OSPF6_DEBUG_ABR) + { + char buf[64]; + prefix2str (&range->prefix, buf, sizeof (buf)); + zlog_info ("Suppressed by range %s of area %s", + buf, route_area->name); + } + + if (summary) + ospf6_route_remove (summary, summary_table); + if (old) + ospf6_lsa_purge (old); + return; + } + } + + /* If this is a configured address range */ + if (route->type == OSPF6_DEST_TYPE_RANGE) + { + /* If DoNotAdvertise is set */ + if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) + { + if (IS_OSPF6_DEBUG_ABR) + zlog_info ("This is the range with DoNotAdvertise set. ignore"); + if (summary) + ospf6_route_remove (summary, summary_table); + if (old) + ospf6_lsa_purge (old); + return; + } + + /* Whether the route have active longer prefix */ + if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) + { + if (IS_OSPF6_DEBUG_ABR) + zlog_info ("The range is not active. withdraw"); + if (summary) + ospf6_route_remove (summary, summary_table); + if (old) + ospf6_lsa_purge (old); + return; + } } /* the route is going to be originated. store it in area's summary_table */ if (summary == NULL) { summary = ospf6_route_copy (route); - summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX); + if (route->type == OSPF6_DEST_TYPE_NETWORK || + route->type == OSPF6_DEST_TYPE_RANGE) + summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX); + else + summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER); summary->path.origin.adv_router = area->ospf6->router_id; summary->path.origin.id = ospf6_new_ls_id (summary->path.origin.type, summary->path.origin.adv_router, area->lsdb); - ospf6_route_add (summary, area->summary_table); + ospf6_route_add (summary, summary_table); + } + else + { + summary->type = route->type; + gettimeofday (&summary->changed, NULL); } + summary->path.router_bits = route->path.router_bits; + summary->path.options[0] = route->path.options[0]; + summary->path.options[1] = route->path.options[1]; + summary->path.options[2] = route->path.options[2]; + summary->path.prefix_options = route->path.prefix_options; + summary->path.area_id = area->area_id; + summary->path.type = OSPF6_PATH_TYPE_INTER; + summary->path.cost = route->path.cost; + summary->nexthop[0] = route->nexthop[0]; + /* prepare buffer */ memset (buffer, 0, sizeof (buffer)); lsa_header = (struct ospf6_lsa_header *) buffer; - prefix_lsa = (struct ospf6_inter_prefix_lsa *) - ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); - p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa); - /* Fill Inter-Area-Prefix-LSA */ - OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost); - - /* prefixlen */ - prefix_lsa->prefix.prefix_length = route->prefix.prefixlen; - - /* PrefixOptions */ - prefix_lsa->prefix.prefix_options = route->path.prefix_options; - - /* set Prefix */ - memcpy (p, &route->prefix.u.prefix6, - OSPF6_PREFIX_SPACE (route->prefix.prefixlen)); - ospf6_prefix_apply_mask (&prefix_lsa->prefix); - p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen); + if (route->type == OSPF6_DEST_TYPE_ROUTER) + { + router_lsa = (struct ospf6_inter_router_lsa *) + ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); + p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa); + + /* Fill Inter-Area-Router-LSA */ + router_lsa->options[0] = route->path.options[0]; + router_lsa->options[1] = route->path.options[1]; + router_lsa->options[2] = route->path.options[2]; + OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost); + router_lsa->router_id = + ospf6_linkstate_prefix_adv_router (&route->prefix); + type = htons (OSPF6_LSTYPE_INTER_ROUTER); + } + else + { + prefix_lsa = (struct ospf6_inter_prefix_lsa *) + ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); + p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa); + + /* Fill Inter-Area-Prefix-LSA */ + OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost); + prefix_lsa->prefix.prefix_length = route->prefix.prefixlen; + prefix_lsa->prefix.prefix_options = route->path.prefix_options; + + /* set Prefix */ + memcpy (p, &route->prefix.u.prefix6, + OSPF6_PREFIX_SPACE (route->prefix.prefixlen)); + ospf6_prefix_apply_mask (&prefix_lsa->prefix); + p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen); + type = htons (OSPF6_LSTYPE_INTER_PREFIX); + } /* Fill LSA Header */ lsa_header->age = 0; - lsa_header->type = htons (OSPF6_LSTYPE_INTER_PREFIX); + lsa_header->type = type; lsa_header->id = summary->path.origin.id; lsa_header->adv_router = area->ospf6->router_id; lsa_header->seqnum = @@ -183,23 +352,63 @@ ospf6_abr_originate_prefix_to_area (struct ospf6_route *route, /* create LSA */ lsa = ospf6_lsa_create (lsa_header); - lsa->scope = area; - SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); /* XXX */ + + if (IS_OSPF6_DEBUG_ABR) + zlog_info ("Originate as %s", lsa->name); /* Originate */ - ospf6_lsa_originate (lsa); + ospf6_lsa_originate_area (lsa, area); +} + +void +ospf6_abr_range_update (struct ospf6_route *range) +{ + u_int32_t cost = 0; + struct ospf6_route *ro; + + assert (range->type == OSPF6_DEST_TYPE_RANGE); + + /* update range's cost and active flag */ + for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table); + ro; ro = ospf6_route_match_next (&range->prefix, ro)) + { + if (ro->path.area_id == range->path.area_id && + ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE)) + cost = MAX (cost, ro->path.cost); + } + + if (range->path.cost != cost) + { + range->path.cost = cost; + + if (range->path.cost) + SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); + else + UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); + + ospf6_abr_originate_summary (range); + } } void -ospf6_abr_originate_prefix (struct ospf6_route *route, struct ospf6 *o) +ospf6_abr_originate_summary (struct ospf6_route *route) { listnode node; struct ospf6_area *oa; + struct ospf6_route *range = NULL; - for (node = listhead (o->area_list); node; nextnode (node)) + if (route->type == OSPF6_DEST_TYPE_NETWORK) + { + oa = ospf6_area_lookup (route->path.area_id, ospf6); + range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table); + if (range) + ospf6_abr_range_update (range); + } + + for (node = listhead (ospf6->area_list); node; nextnode (node)) { oa = (struct ospf6_area *) getdata (node); - ospf6_abr_originate_prefix_to_area (route, oa); + ospf6_abr_originate_summary_to_area (route, oa); } } @@ -211,7 +420,7 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa) struct ospf6_route_table *table = NULL; struct ospf6_route *range, *route, *old = NULL; struct ospf6_route *abr_entry; - u_char type; + u_char type = 0; char options[3] = {0, 0, 0}; u_int8_t prefix_options = 0; u_int32_t cost = 0; @@ -274,18 +483,22 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa) } /* (3) if the prefix is equal to an active configured address range */ - range = ospf6_route_lookup (&prefix, oa->summary_table); - if (range && CHECK_FLAG (range->flag, OSPF6_ROUTE_HAVE_LONGER)) + if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX)) { - if (old) - ospf6_route_remove (old, oa->ospf6->route_table); - return; + range = ospf6_route_lookup (&prefix, oa->range_table); + if (range) + { + if (old) + ospf6_route_remove (old, oa->ospf6->route_table); + return; + } } /* (4) if the routing table entry for the ABR does not exist */ ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix); abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table); - if (abr_entry == NULL) + if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id || + ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) { if (old) ospf6_route_remove (old, oa->ospf6->route_table); @@ -318,11 +531,6 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa) ospf6_route_add (route, table); } -int -dummy (struct ospf6_lsa *lsa) -{ -} - /* Display functions */ int @@ -412,15 +620,25 @@ install_element_ospf6_debug_abr () install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd); } +struct ospf6_lsa_handler inter_prefix_handler = +{ + OSPF6_LSTYPE_INTER_PREFIX, + "Inter-Prefix", + ospf6_inter_area_prefix_lsa_show +}; + +struct ospf6_lsa_handler inter_router_handler = +{ + OSPF6_LSTYPE_INTER_ROUTER, + "Inter-Router", + ospf6_inter_area_router_lsa_show +}; + void ospf6_abr_init () { - ospf6_lstype[3].name = "Inter-Area-Prefix-LSA"; - ospf6_lstype[3].reoriginate = dummy; - ospf6_lstype[3].show = ospf6_inter_area_prefix_lsa_show; - ospf6_lstype[4].name = "Inter-Area-Router-LSA"; - ospf6_lstype[4].reoriginate = dummy; - ospf6_lstype[4].show = ospf6_inter_area_router_lsa_show; + ospf6_install_lsa_handler (&inter_prefix_handler); + ospf6_install_lsa_handler (&inter_router_handler); } diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h index 1c5c6a3f..a12d985e 100644 --- a/ospf6d/ospf6_abr.h +++ b/ospf6d/ospf6_abr.h @@ -52,9 +52,11 @@ struct ospf6_inter_router_lsa { (E)->metric &= htonl (0x00000000); \ (E)->metric |= htonl (0x00ffffff) & htonl (C); } -void ospf6_abr_originate_prefix_to_area (struct ospf6_route *route, - struct ospf6_area *area); -void ospf6_abr_originate_prefix (struct ospf6_route *route, struct ospf6 *o); +int ospf6_is_router_abr (struct ospf6 *o); + +void ospf6_abr_originate_summary_to_area (struct ospf6_route *route, + struct ospf6_area *area); +void ospf6_abr_originate_summary (struct ospf6_route *route); void ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa); int config_write_ospf6_debug_abr (struct vty *vty); diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 04cbb0a3..fc2103ca 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -48,29 +48,18 @@ ospf6_area_cmp (void *va, void *vb) { struct ospf6_area *oa = (struct ospf6_area *) va; struct ospf6_area *ob = (struct ospf6_area *) vb; - return (ntohl (oa->area_id) - ntohl (ob->area_id)); -} - -int -ospf6_area_is_stub (struct ospf6_area *o6a) -{ - if (OSPF6_OPT_ISSET (o6a->options, OSPF6_OPT_E)) - return 0; - return 1; + return (ntohl (oa->area_id) < ntohl (ob->area_id) ? -1 : 1); } /* schedule routing table recalculation */ void ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa) { - struct ospf6_area *oa; - - oa = (struct ospf6_area *) lsa->scope; switch (ntohs (lsa->header->type)) { case OSPF6_LSTYPE_ROUTER: case OSPF6_LSTYPE_NETWORK: - ospf6_spf_schedule (oa); + ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data)); break; case OSPF6_LSTYPE_INTRA_PREFIX: @@ -83,7 +72,8 @@ ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa) default: if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("Unknown LSA in Area %s's lsdb", oa->name); + zlog_info ("Unknown LSA in Area %s's lsdb", + OSPF6_AREA (lsa->lsdb->data)->name); break; } } @@ -91,14 +81,11 @@ ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa) void ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa) { - struct ospf6_area *oa; - - oa = (struct ospf6_area *) lsa->scope; switch (ntohs (lsa->header->type)) { case OSPF6_LSTYPE_ROUTER: case OSPF6_LSTYPE_NETWORK: - ospf6_spf_schedule (oa); + ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data)); break; case OSPF6_LSTYPE_INTRA_PREFIX: @@ -111,7 +98,8 @@ ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa) default: if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("Unknown LSA in Area %s's lsdb", oa->name); + zlog_info ("Unknown LSA in Area %s's lsdb", + OSPF6_AREA (lsa->lsdb->data)->name); break; } } @@ -146,17 +134,20 @@ ospf6_area_create (u_int32_t area_id, struct ospf6 *o) oa->area_id = area_id; oa->if_list = list_new (); - oa->summary_table = ospf6_route_table_create (); - - oa->lsdb = ospf6_lsdb_create (); + oa->lsdb = ospf6_lsdb_create (oa); oa->lsdb->hook_add = ospf6_area_lsdb_hook_add; oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove; + oa->lsdb_self = ospf6_lsdb_create (oa); oa->spf_table = ospf6_route_table_create (); oa->route_table = ospf6_route_table_create (); oa->route_table->hook_add = ospf6_area_route_hook_add; oa->route_table->hook_remove = ospf6_area_route_hook_remove; + oa->range_table = ospf6_route_table_create (); + oa->summary_prefix = ospf6_route_table_create (); + oa->summary_router = ospf6_route_table_create (); + /* set default options */ OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6); OSPF6_OPT_SET (oa->options, OSPF6_OPT_E); @@ -168,7 +159,7 @@ ospf6_area_create (u_int32_t area_id, struct ospf6 *o) /* import athoer area's routes as inter-area routes */ for (route = ospf6_route_head (o->route_table); route; route = ospf6_route_next (route)) - ospf6_abr_originate_prefix_to_area (route, oa); + ospf6_abr_originate_summary_to_area (route, oa); return oa; } @@ -179,7 +170,9 @@ ospf6_area_delete (struct ospf6_area *oa) listnode n; struct ospf6_interface *oi; - ospf6_route_table_delete (oa->summary_table); + ospf6_route_table_delete (oa->range_table); + ospf6_route_table_delete (oa->summary_prefix); + ospf6_route_table_delete (oa->summary_router); /* ospf6 interface list */ for (n = listhead (oa->if_list); n; nextnode (n)) @@ -190,6 +183,8 @@ ospf6_area_delete (struct ospf6_area *oa) list_delete (oa->if_list); ospf6_lsdb_delete (oa->lsdb); + ospf6_lsdb_delete (oa->lsdb_self); + ospf6_route_table_delete (oa->spf_table); ospf6_route_table_delete (oa->route_table); @@ -224,13 +219,23 @@ ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6) return (struct ospf6_area *) NULL; } +struct ospf6_area * +ospf6_area_get (u_int32_t area_id, struct ospf6 *o) +{ + struct ospf6_area *oa; + oa = ospf6_area_lookup (area_id, o); + if (oa == NULL) + oa = ospf6_area_create (area_id, o); + return oa; +} + void ospf6_area_enable (struct ospf6_area *oa) { listnode i; struct ospf6_interface *oi; - UNSET_FLAG (oa->flag, OSPF6_AREA_DISABLE); + SET_FLAG (oa->flag, OSPF6_AREA_ENABLE); for (i = listhead (oa->if_list); i; nextnode (i)) { @@ -245,7 +250,7 @@ ospf6_area_disable (struct ospf6_area *oa) listnode i; struct ospf6_interface *oi; - SET_FLAG (oa->flag, OSPF6_AREA_DISABLE); + UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE); for (i = listhead (oa->if_list); i; nextnode (i)) { @@ -291,6 +296,130 @@ ospf6_area_show (struct vty *vty, struct ospf6_area *oa) } \ } +#define OSPF6_CMD_AREA_GET(str, oa) \ +{ \ + u_int32_t area_id = 0; \ + if (inet_pton (AF_INET, str, &area_id) != 1) \ + { \ + vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \ + return CMD_SUCCESS; \ + } \ + oa = ospf6_area_get (area_id, ospf6); \ +} + +DEFUN (area_range, + area_range_cmd, + "area A.B.C.D range X:X::X:X/M", + "OSPF area parameters\n" + OSPF6_AREA_ID_STR + "Configured address range\n" + "Specify IPv6 prefix\n" + ) +{ + int ret; + struct ospf6_area *oa; + struct prefix prefix; + struct ospf6_route *range; + + OSPF6_CMD_AREA_GET (argv[0], oa); + argc--; + argv++; + + ret = str2prefix (argv[0], &prefix); + if (ret != 1 || prefix.family != AF_INET6) + { + vty_out (vty, "Malformed argument: %s%s", argv[0], VNL); + return CMD_SUCCESS; + } + argc--; + argv++; + + range = ospf6_route_lookup (&prefix, oa->range_table); + if (range == NULL) + { + range = ospf6_route_create (); + range->type = OSPF6_DEST_TYPE_RANGE; + range->prefix = prefix; + } + + if (argc) + { + if (! strcmp (argv[0], "not-advertise")) + SET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + else if (! strcmp (argv[0], "advertise")) + UNSET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + } + + ospf6_route_add (range, oa->range_table); + return CMD_SUCCESS; +} + +ALIAS (area_range, + area_range_advertise_cmd, + "area A.B.C.D range X:X::X:X/M (advertise|not-advertise)", + "OSPF area parameters\n" + OSPF6_AREA_ID_STR + "Configured address range\n" + "Specify IPv6 prefix\n" + ); + +DEFUN (no_area_range, + no_area_range_cmd, + "no area A.B.C.D range X:X::X:X/M", + "OSPF area parameters\n" + OSPF6_AREA_ID_STR + "Configured address range\n" + "Specify IPv6 prefix\n" + ) +{ + int ret; + struct ospf6_area *oa; + struct prefix prefix; + struct ospf6_route *range; + + OSPF6_CMD_AREA_GET (argv[0], oa); + argc--; + argv++; + + ret = str2prefix (argv[0], &prefix); + if (ret != 1 || prefix.family != AF_INET6) + { + vty_out (vty, "Malformed argument: %s%s", argv[0], VNL); + return CMD_SUCCESS; + } + + range = ospf6_route_lookup (&prefix, oa->range_table); + if (range == NULL) + { + vty_out (vty, "Range %s does not exists.%s", argv[0], VNL); + return CMD_SUCCESS; + } + + ospf6_route_remove (range, oa->range_table); + return CMD_SUCCESS; +} + +void +ospf6_area_config_write (struct vty *vty) +{ + listnode node; + struct ospf6_area *oa; + struct ospf6_route *range; + char buf[128]; + + for (node = listhead (ospf6->area_list); node; nextnode (node)) + { + oa = OSPF6_AREA (getdata (node)); + + for (range = ospf6_route_head (oa->range_table); range; + range = ospf6_route_next (range)) + { + prefix2str (&range->prefix, buf, sizeof (buf)); + vty_out (vty, " area %s range %s%s", oa->name, buf, VNL); + } + } +} + DEFUN (show_ipv6_ospf6_area_route_intra, show_ipv6_ospf6_area_route_intra_cmd, "show ipv6 ospf6 area A.B.C.D route intra-area", @@ -876,5 +1005,10 @@ ospf6_area_init () install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_intra_match_detail_cmd); install_element (ENABLE_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd); + + install_element (OSPF6_NODE, &area_range_cmd); + install_element (OSPF6_NODE, &area_range_advertise_cmd); + install_element (OSPF6_NODE, &no_area_range_cmd); } + diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h index c15960cd..734f030c 100644 --- a/ospf6d/ospf6_area.h +++ b/ospf6d/ospf6_area.h @@ -41,16 +41,17 @@ struct ospf6_area /* OSPF Option */ u_char options[3]; - /* TransitCapability */ - int transit_capability; - /* Summary routes to be originated (includes Configured Address Ranges) */ - struct ospf6_route_table *summary_table; + struct ospf6_route_table *range_table; + struct ospf6_route_table *summary_prefix; + struct ospf6_route_table *summary_router; /* OSPF interface list */ list if_list; - struct ospf6_lsdb *lsdb; + struct ospf6_lsdb *lsdb; + struct ospf6_lsdb *lsdb_self; + struct ospf6_route_table *spf_table; struct ospf6_route_table *route_table; @@ -62,12 +63,21 @@ struct ospf6_area u_int32_t router_lsa_size_limit; }; -#define OSPF6_AREA_DISABLE 0x01 -#define OSPF6_AREA_STUB 0x02 +#define OSPF6_AREA_ENABLE 0x01 +#define OSPF6_AREA_ACTIVE 0x02 +#define OSPF6_AREA_TRANSIT 0x04 /* TransitCapability */ +#define OSPF6_AREA_STUB 0x08 + +#define BACKBONE_AREA_ID (htonl (0)) +#define IS_AREA_BACKBONE(oa) ((oa)->area_id == BACKBONE_AREA_ID) +#define IS_AREA_ENABLED(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_ENABLE)) +#define IS_AREA_ACTIVE(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_ACTIVE)) +#define IS_AREA_TRANSIT(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_TRANSIT)) +#define IS_AREA_STUB(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_STUB)) /* prototypes */ int ospf6_area_cmp (void *va, void *vb); -int ospf6_area_is_stub (struct ospf6_area *o6a); + struct ospf6_area *ospf6_area_create (u_int32_t, struct ospf6 *); void ospf6_area_delete (struct ospf6_area *); struct ospf6_area *ospf6_area_lookup (u_int32_t, struct ospf6 *); @@ -76,6 +86,8 @@ void ospf6_area_enable (struct ospf6_area *); void ospf6_area_disable (struct ospf6_area *); void ospf6_area_show (struct vty *, struct ospf6_area *); + +void ospf6_area_config_write (struct vty *vty); void ospf6_area_init (); #endif /* OSPF_AREA_H */ diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 18f7cc26..a8a1ce11 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -37,10 +37,15 @@ #include "ospf6_lsdb.h" #include "ospf6_route.h" #include "ospf6_zebra.h" +#include "ospf6_message.h" + #include "ospf6_top.h" #include "ospf6_area.h" +#include "ospf6_interface.h" +#include "ospf6_neighbor.h" #include "ospf6_asbr.h" #include "ospf6_intra.h" +#include "ospf6_flood.h" #include "ospf6d.h" unsigned char conf_debug_ospf6_asbr = 0; @@ -61,20 +66,19 @@ char *zroute_abname[] = /* AS External LSA origination */ void -ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force) +ospf6_as_external_lsa_originate (struct ospf6_route *route) { char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa_header *lsa_header; struct ospf6_lsa *old, *lsa; - struct ospf6_external_info *info = route->route_option; struct ospf6_as_external_lsa *as_external_lsa; char buf[64]; caddr_t p; /* find previous LSA */ old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL), - htonl (info->id), ospf6->router_id, + route->path.origin.id, ospf6->router_id, ospf6->lsdb); if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) @@ -99,7 +103,7 @@ ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force) UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E); /* forwarding address */ - if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding)) + if (! IN6_IS_ADDR_UNSPECIFIED (&route->nexthop[0].address)) SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F); else UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F); @@ -128,7 +132,7 @@ ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force) /* Forwarding address */ if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F)) { - memcpy (p, &info->forwarding, sizeof (struct in6_addr)); + memcpy (p, &route->nexthop[0].address, sizeof (struct in6_addr)); p += sizeof (struct in6_addr); } @@ -141,7 +145,7 @@ ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force) /* Fill LSA Header */ lsa_header->age = 0; lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL); - lsa_header->id = htonl (info->id); + lsa_header->id = route->path.origin.id; lsa_header->adv_router = ospf6->router_id; lsa_header->seqnum = ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, @@ -153,37 +157,11 @@ ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force) /* create LSA */ lsa = ospf6_lsa_create (lsa_header); - lsa->scope = ospf6; - if (force) - SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); /* Originate */ - ospf6_lsa_originate (lsa); + ospf6_lsa_originate_process (lsa, ospf6); } -int -ospf6_as_external_lsa_reoriginate (struct ospf6_lsa *lsa) -{ - struct prefix prefix_id; - struct route_node *node; - struct ospf6_route *route; - - /* create/update binding in external_id_table */ - prefix_id.family = AF_INET; - prefix_id.prefixlen = 32; - prefix_id.u.prefix4.s_addr = lsa->header->id; - node = route_node_get (ospf6->external_id_table, &prefix_id); - route = node->info; - - if (route) - ospf6_as_external_lsa_originate_sub (route, 1); - else - ospf6_lsa_premature_aging (lsa); - - return 0; -} - - void ospf6_asbr_lsa_add (struct ospf6_lsa *lsa) @@ -217,7 +195,7 @@ ospf6_asbr_lsa_add (struct ospf6_lsa *lsa) asbr_id.family = AF_INET; asbr_id.prefixlen = 32; asbr_id.u.prefix4.s_addr = lsa->header->adv_router; - asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->asbr_table); + asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table); if (asbr_entry == NULL) { @@ -545,7 +523,7 @@ ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix, zlog_info ("Advertise as AS-External Id:%s", ibuf); } - ospf6_as_external_lsa_originate_sub (match, 0); + ospf6_as_external_lsa_originate (match); return; } @@ -593,7 +571,7 @@ ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix, zlog_info ("Advertise as AS-External Id:%s", ibuf); } - ospf6_as_external_lsa_originate_sub (route, 0); + ospf6_as_external_lsa_originate (route); /* Router-Bit (ASBR Flag) may have to be updated */ for (lnode = listhead (ospf6->area_list); lnode; nextnode (lnode)) @@ -649,7 +627,7 @@ ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix) lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL), htonl (info->id), ospf6->router_id, ospf6->lsdb); if (lsa) - ospf6_lsa_premature_aging (lsa); + ospf6_lsa_purge (lsa); /* remove binding in external_id_table */ prefix_id.family = AF_INET; @@ -1254,95 +1232,23 @@ DEFUN (show_ipv6_ospf6_redistribute, return CMD_SUCCESS; } -DEFUN (show_ipv6_ospf6_asbr, - show_ipv6_ospf6_asbr_cmd, - "show ipv6 ospf6 asbr", - SHOW_STR - IP6_STR - OSPF6_STR - "Show AS Boundary Router table\n" - ) -{ - ospf6_lsentry_table_show (vty, argc, argv, ospf6->asbr_table); - return CMD_SUCCESS; -} - -ALIAS (show_ipv6_ospf6_asbr, - show_ipv6_ospf6_asbr_1_cmd, - "show ipv6 ospf6 asbr (A.B.C.D|A.B.C.D/M|detail)", - SHOW_STR - IP6_STR - OSPF6_STR - "Show AS Boundary Router table\n" - "Specify Router-ID\n" - "Display multiple entry by specifying match-prefix of Router-ID\n" - "Display Detail\n" - ); - -ALIAS (show_ipv6_ospf6_asbr, - show_ipv6_ospf6_asbr_2_cmd, - "show ipv6 ospf6 asbr (A.B.C.D|A.B.C.D/M|*) (A.B.C.D|A.B.C.D/M|detail)", - SHOW_STR - IP6_STR - OSPF6_STR - "Show AS Boundary Router table\n" - "Specify Router-ID\n" - "Display multiple entry by specifying match-prefix of Router-ID\n" - "Wildcard Router-ID\n" - "Specify Link State ID\n" - "Display multiple entry by specifying match-prefix of Link State ID\n" - "Display Detail\n" - ); - -DEFUN (show_ipv6_ospf6_asbr_3, - show_ipv6_ospf6_asbr_3_cmd, - "show ipv6 ospf6 asbr (A.B.C.D|*) A.B.C.D/M detail", - SHOW_STR - IP6_STR - OSPF6_STR - "Show AS Boundary Router table\n" - "Specify Router-ID\n" - "Wildcard Router-ID\n" - "Display multiple entry by specifying match-prefix of Link State ID\n" - "Display Detail\n" - ) +struct ospf6_lsa_handler as_external_handler = { - char *sargv[CMD_ARGC_MAX]; - int i, sargc; - - /* copy argv to sargv and then append "detail" */ - for (i = 0; i < argc; i++) - sargv[i] = argv[i]; - sargc = argc; - sargv[sargc++] = "detail"; - sargv[sargc] = NULL; - - ospf6_lsentry_table_show (vty, sargc, sargv, ospf6->asbr_table); - return CMD_SUCCESS; -} - + OSPF6_LSTYPE_AS_EXTERNAL, + "AS-External", + ospf6_as_external_lsa_show +}; void ospf6_asbr_init () { ospf6_routemap_init (); - ospf6_lstype[5].name = "AS-External"; - ospf6_lstype[5].reoriginate = ospf6_as_external_lsa_reoriginate; - ospf6_lstype[5].show = ospf6_as_external_lsa_show; + ospf6_install_lsa_handler (&as_external_handler); install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd); install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_1_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_2_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_3_cmd); - install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_cmd); - install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_1_cmd); - install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_2_cmd); - install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_3_cmd); - install_element (OSPF6_NODE, &ospf6_redistribute_cmd); install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd); install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd); diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 6e84a034..aeff15bc 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -39,160 +39,169 @@ #include "ospf6_interface.h" #include "ospf6_neighbor.h" +#include "ospf6_flood.h" -void * -ospf6_get_lsa_scope (u_int16_t type, struct ospf6_neighbor *from) +struct ospf6_lsdb * +ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa) { - void *scope = NULL; - - if (from == NULL) - return NULL; - - switch (OSPF6_LSA_SCOPE (type)) - { - case OSPF6_LSA_SCOPE_AS: - scope = (from)->ospf6_if->area->ospf6; - break; - case OSPF6_LSA_SCOPE_AREA: - scope = (from)->ospf6_if->area; - break; - case OSPF6_LSA_SCOPE_LINKLOCAL: - scope = (from)->ospf6_if; - break; - default: - break; + struct ospf6_lsdb *lsdb = NULL; + switch (OSPF6_LSA_SCOPE (lsa->header->type)) + { + case OSPF6_SCOPE_LINKLOCAL: + lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb; + break; + default: + assert (0); + break; } - - return scope; + return lsdb; } struct ospf6_lsdb * -ospf6_get_scoped_lsdb (u_int16_t type, void *scope) +ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa) { - struct ospf6_lsdb *lsdb = NULL; + struct ospf6_lsdb *lsdb_self = NULL; + switch (OSPF6_LSA_SCOPE (lsa->header->type)) + { + case OSPF6_SCOPE_LINKLOCAL: + lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self; + break; + case OSPF6_SCOPE_AREA: + lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self; + break; + case OSPF6_SCOPE_AS: + lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self; + break; + default: + assert (0); + break; + } + return lsdb_self; +} + +void +ospf6_lsa_originate (struct ospf6_lsa *lsa) +{ + struct ospf6_lsa *old; + struct ospf6_lsdb *lsdb_self; - if (scope == NULL) - return NULL; + /* find previous LSA */ + old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsa->lsdb); - switch (OSPF6_LSA_SCOPE (type)) + /* if the new LSA does not differ from previous, + suppress this update of the LSA */ + if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old)) { - case OSPF6_LSA_SCOPE_AS: - lsdb = ((struct ospf6 *)(scope))->lsdb; - break; - case OSPF6_LSA_SCOPE_AREA: - lsdb = ((struct ospf6_area *)(scope))->lsdb; - break; - case OSPF6_LSA_SCOPE_LINKLOCAL: - lsdb = ((struct ospf6_interface *)(scope))->lsdb; - break; - default: - break; + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info ("Suppress updating LSA: %s", lsa->name); + ospf6_lsa_delete (lsa); + return; } - return lsdb; -} + /* store it in the LSDB for self-originated LSAs */ + lsdb_self = ospf6_get_scoped_lsdb_self (lsa); + ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self); -void -ospf6_decrement_onretrans (struct ospf6_lsa *lsa) -{ - struct ospf6_lsdb *lsdb; - struct ospf6_lsa *src; + lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, + LS_REFRESH_TIME); - lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope); - if (lsdb == NULL) + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) { - zlog_warn ("Decrement onretrans: no such scope: %s", lsa->name); - return; + zlog_info ("LSA Originate:"); + ospf6_lsa_header_print (lsa); } - src = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsdb); - if (src && src != lsa) - src->onretrans--; + if (old) + ospf6_flood_clear (old); + ospf6_flood (NULL, lsa); + ospf6_install_lsa (lsa); +} - if (src->onretrans < 0) - zlog_warn ("internal error: onretrans"); +void +ospf6_lsa_originate_process (struct ospf6_lsa *lsa, + struct ospf6 *process) +{ + lsa->lsdb = process->lsdb; + ospf6_lsa_originate (lsa); } void -ospf6_flood_clear (struct ospf6_lsa *lsa) +ospf6_lsa_originate_area (struct ospf6_lsa *lsa, + struct ospf6_area *oa) { - struct ospf6_neighbor *on; - struct ospf6_interface *oi, *ospf6_if = NULL; - struct ospf6_area *oa, *area = NULL; - struct ospf6 *ospf6 = NULL; - u_int16_t scope_type; - list scoped_interfaces; - struct ospf6_lsa *rxmt; - listnode i, j; + lsa->lsdb = oa->lsdb; + ospf6_lsa_originate (lsa); +} + +void +ospf6_lsa_originate_interface (struct ospf6_lsa *lsa, + struct ospf6_interface *oi) +{ + lsa->lsdb = oi->lsdb; + ospf6_lsa_originate (lsa); +} - scoped_interfaces = list_new (); - scope_type = OSPF6_LSA_SCOPE (lsa->header->type); +void +ospf6_lsa_purge (struct ospf6_lsa *lsa) +{ + struct ospf6_lsa *self; + struct ospf6_lsdb *lsdb_self; - if (scope_type == OSPF6_LSA_SCOPE_LINKLOCAL) - { - ospf6_if = (struct ospf6_interface *) lsa->scope; - area = ospf6_if->area; - ospf6 = area->ospf6; - } - else if (scope_type == OSPF6_LSA_SCOPE_AREA) - { - area = (struct ospf6_area *) lsa->scope; - ospf6 = area->ospf6; - } - else if (scope_type == OSPF6_LSA_SCOPE_AS) - { - ospf6 = (struct ospf6 *) lsa->scope; - } - else + /* remove it from the LSDB for self-originated LSAs */ + lsdb_self = ospf6_get_scoped_lsdb_self (lsa); + self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsdb_self); + if (self) { - zlog_warn ("Can't decide LSA scope, quit ospf6_flood_clear ()"); - return; + THREAD_OFF (self->expire); + THREAD_OFF (self->refresh); + ospf6_lsdb_remove (self, lsdb_self); } - /* Collect eligible interfaces */ - for (i = listhead (ospf6->area_list); i; nextnode (i)) - { - oa = (struct ospf6_area *) getdata (i); - if (scope_type != OSPF6_LSA_SCOPE_AS && oa != area) - continue; + ospf6_lsa_premature_aging (lsa); +} - for (j = listhead (oa->if_list); j; nextnode (j)) - { - oi = (struct ospf6_interface *) getdata (j); - if (scope_type != OSPF6_LSA_SCOPE_AS && - scope_type != OSPF6_LSA_SCOPE_AREA && oi != ospf6_if) - continue; - listnode_add (scoped_interfaces, oi); - } - } +void +ospf6_increment_retrans_count (struct ospf6_lsa *lsa) +{ + /* The LSA must be the original one (see the description + in ospf6_decrement_retrans_count () below) */ + lsa->retrans_count++; +} - for (i = listhead (scoped_interfaces); i; nextnode (i)) - { - oi = (struct ospf6_interface *) getdata (i); - for (j = listhead (oi->neighbor_list); j; nextnode (j)) - { - on = (struct ospf6_neighbor *) getdata (j); - rxmt = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, on->retrans_list); - if (rxmt && ! ospf6_lsa_compare (rxmt, lsa)) - { - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info ("Remove %s from retrans_list of %s", - rxmt->name, on->name); - ospf6_decrement_onretrans (rxmt); - ospf6_lsdb_remove (rxmt, on->retrans_list); - } - } - } +void +ospf6_decrement_retrans_count (struct ospf6_lsa *lsa) +{ + struct ospf6_lsdb *lsdb; + struct ospf6_lsa *orig; + + /* The LSA must be on the retrans-list of a neighbor. It means + the "lsa" is a copied one, and we have to decrement the + retransmission count of the original one (instead of "lsa"'s). + In order to find the original LSA, first we have to find + appropriate LSDB that have the original LSA. */ + lsdb = ospf6_get_scoped_lsdb (lsa); + + /* Find the original LSA of which the retrans_count should be decremented */ + orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsdb); + if (orig) + orig->retrans_count--; - list_delete (scoped_interfaces); + assert (orig->retrans_count >= 0); } /* RFC2328 section 13.2 Installing LSAs in the database */ void -ospf6_install_lsa (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) +ospf6_install_lsa (struct ospf6_lsa *lsa) { struct ospf6_lsa *old; @@ -202,185 +211,299 @@ ospf6_install_lsa (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) /* Remove the old instance from all neighbors' Link state retransmission list (RFC2328 13.2 last paragraph) */ old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsdb); + lsa->header->adv_router, lsa->lsdb); if (old) ospf6_flood_clear (old); /* actually install */ gettimeofday (&lsa->installed, (struct timezone *) NULL); - ospf6_lsdb_add (lsa, lsdb); + ospf6_lsdb_add (lsa, lsa->lsdb); return; } +/* RFC2740 section 3.5.2. Sending Link State Update packets */ /* RFC2328 section 13.3 Next step in the flooding procedure */ void -ospf6_flood_lsa (struct ospf6_lsa *lsa, struct ospf6_neighbor *from) +ospf6_flood_interface (struct ospf6_neighbor *from, + struct ospf6_lsa *lsa, struct ospf6_interface *oi) { - struct ospf6 *scope_as = NULL; - struct ospf6_area *oa, *scope_area = NULL; - struct ospf6_interface *oi, *scope_linklocal = NULL; + listnode node; struct ospf6_neighbor *on; - list eligible_interfaces; - listnode i, j; - u_int16_t scope_type; struct ospf6_lsa *req; int retrans_added = 0; - scope_type = OSPF6_LSA_SCOPE (lsa->header->type); - switch (scope_type) - { - case OSPF6_LSA_SCOPE_AS: - scope_as = (struct ospf6 *) lsa->scope; - break; - case OSPF6_LSA_SCOPE_AREA: - scope_as = ((struct ospf6_area *) lsa->scope)->ospf6; - scope_area = (struct ospf6_area *) lsa->scope; - break; - case OSPF6_LSA_SCOPE_LINKLOCAL: - scope_as = ((struct ospf6_interface *) lsa->scope)->area->ospf6; - scope_area = ((struct ospf6_interface *) lsa->scope)->area; - scope_linklocal = (struct ospf6_interface *) lsa->scope; - break; - default: - if (IS_OSPF6_DEBUG_LSA (SEND)) - zlog_info ("Can't decide LSA scope"); - return; - } - if (IS_OSPF6_DEBUG_LSA (SEND)) - zlog_info ("Flood %s", lsa->name); + zlog_info ("Flooding on %s: %s", oi->interface->name, lsa->name); - /* Collect eligible interfaces */ - eligible_interfaces = list_new (); - for (i = listhead (scope_as->area_list); i; nextnode (i)) + /* (1) For each neighbor */ + for (node = listhead (oi->neighbor_list); node; nextnode (node)) { - oa = (struct ospf6_area *) getdata (i); - if (scope_type != OSPF6_LSA_SCOPE_AS && - oa != scope_area) - continue; + on = (struct ospf6_neighbor *) getdata (node); - for (j = listhead (oa->if_list); j; nextnode (j)) - { - oi = (struct ospf6_interface *) getdata (j); - if (scope_type != OSPF6_LSA_SCOPE_AS && - scope_type != OSPF6_LSA_SCOPE_AREA && - oi != scope_linklocal) - continue; + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("To neighbor %s", on->name); - listnode_add (eligible_interfaces, oi); + /* (a) if neighbor state < Exchange, examin next */ + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) + { + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Neighbor state less than ExChange, next neighbor"); + continue; } - } - /* For each eligible interface: */ - for (i = listhead (eligible_interfaces); i; nextnode (i)) - { - oi = (struct ospf6_interface *) getdata (i); - - /* (1) For each neighbor */ - for (j = listhead (oi->neighbor_list); j; nextnode (j)) + /* (b) if neighbor not yet Full, check request-list */ + if (on->state != OSPF6_NEIGHBOR_FULL) { - on = (struct ospf6_neighbor *) getdata (j); + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Neighbor not yet Full"); - /* (a) if neighbor state < Exchange, examin next */ - if (on->state < OSPF6_NEIGHBOR_EXCHANGE) - continue; - - /* (b) if neighbor not yet Full, check request-list */ - if (on->state != OSPF6_NEIGHBOR_FULL) + req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, on->request_list); + if (req == NULL) { - req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, - on->request_list); - if (req) + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Not on request-list for this neighbor"); + /* fall through */ + } + else + { + /* If new LSA less recent, examin next neighbor */ + if (ospf6_lsa_compare (lsa, req) > 0) + { + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Requesting is newer, next neighbor"); + continue; + } + + /* If the same instance, delete from request-list and + examin next neighbor */ + if (ospf6_lsa_compare (lsa, req) == 0) { - /* If new LSA less recent, examin next neighbor */ - if (ospf6_lsa_compare (lsa, req) > 0) - continue; - - /* If the same instance, delete from request-list and - examin next neighbor */ - if (ospf6_lsa_compare (lsa, req) == 0) - { - if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info ("Remove %s from request-list of %s: " - "the same instance", req->name, on->name); - ospf6_lsdb_remove (req, on->request_list); - continue; - } - - /* If the new LSA is more recent, delete from - request-list */ - if (ospf6_lsa_compare (lsa, req) < 0) - { - if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info ("Remove %s from request-list of %s: " - "newer instance", req->name, on->name); - ospf6_lsdb_remove (req, on->request_list); - /* fall through */ - } + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Requesting the same, remove it, next neighbor"); + ospf6_lsdb_remove (req, on->request_list); + continue; + } + + /* If the new LSA is more recent, delete from request-list */ + if (ospf6_lsa_compare (lsa, req) < 0) + { + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Received is newer, remove requesting"); + ospf6_lsdb_remove (req, on->request_list); + /* fall through */ } } + } - /* (c) If the new LSA was received from this neighbor, - examin next neighbor */ - if (from == on) - continue; - - /* (d) add retrans-list, schedule retransmission */ - if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info (" Add copy of %s to retrans-list of %s", - lsa->name, on->name); - lsa->onretrans++; - ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); - if (on->thread_send_lsupdate == NULL) - on->thread_send_lsupdate = - thread_add_event (master, ospf6_lsupdate_send_neighbor, - on, on->ospf6_if->rxmt_interval); - retrans_added++; + /* (c) If the new LSA was received from this neighbor, + examin next neighbor */ + if (from == on) + { + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Received is from the neighbor, next neighbor"); + continue; } - /* (2) examin next interface if not added to retrans-list */ - if (retrans_added == 0) + /* (d) add retrans-list, schedule retransmission */ + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Add retrans-list of this neighbor"); + ospf6_increment_retrans_count (lsa); + ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); + if (on->thread_send_lsupdate == NULL) + on->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_neighbor, + on, on->ospf6_if->rxmt_interval); + retrans_added++; + } + + /* (2) examin next interface if not added to retrans-list */ + if (retrans_added == 0) + { + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("No retransmission scheduled, next interface"); + return; + } + + /* (3) If the new LSA was received on this interface, + and it was from DR or BDR, examin next interface */ + if (from && from->ospf6_if == oi && + (from->router_id == oi->drouter || from->router_id == oi->bdrouter)) + { + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Received is from the I/F's DR or BDR, next interface"); + return; + } + + /* (4) If the new LSA was received on this interface, + and the interface state is BDR, examin next interface */ + if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR) + { + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Received is from the I/F, itself BDR, next interface"); + return; + } + + /* (5) flood the LSA out the interface. */ + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("Schedule flooding for the interface"); + if (if_is_broadcast (oi->interface)) + { + ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list); + if (oi->thread_send_lsupdate == NULL) + oi->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0); + } + else + { + /* reschedule retransmissions to all neighbors */ + for (node = listhead (oi->neighbor_list); node; nextnode (node)) + { + on = (struct ospf6_neighbor *) getdata (node); + THREAD_OFF (on->thread_send_lsupdate); + on->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0); + } + } +} + +void +ospf6_flood_area (struct ospf6_neighbor *from, + struct ospf6_lsa *lsa, struct ospf6_area *oa) +{ + listnode node; + struct ospf6_interface *oi; + + for (node = listhead (oa->if_list); node; nextnode (node)) + { + oi = OSPF6_INTERFACE (getdata (node)); + + if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && + oi != OSPF6_INTERFACE (lsa->lsdb->data)) continue; - /* (3) If the new LSA was received on this interface, - and it was from DR or BDR, examin next interface */ - if (from && from->ospf6_if == oi && - (from->router_id == oi->drouter || from->router_id == oi->bdrouter)) +#if 0 + if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS && + ospf6_is_interface_virtual_link (oi)) continue; +#endif/*0*/ + + ospf6_flood_interface (from, lsa, oi); + } +} + +void +ospf6_flood_process (struct ospf6_neighbor *from, + struct ospf6_lsa *lsa, struct ospf6 *process) +{ + listnode node; + struct ospf6_area *oa; - /* (4) If the new LSA was received on this interface, - and the interface state is BDR, examin next interface */ - if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR) + for (node = listhead (process->area_list); node; nextnode (node)) + { + oa = OSPF6_AREA (getdata (node)); + + if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA && + oa != OSPF6_AREA (lsa->lsdb->data)) + continue; + if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && + oa != OSPF6_INTERFACE (lsa->lsdb->data)->area) continue; - /* (5) flood the LSA out the interface. */ - if (if_is_broadcast (oi->interface)) - { - if (IS_OSPF6_DEBUG_LSA (SEND) || IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info (" Add copy of %s to lsupdate_list of %s", - lsa->name, oi->interface->name); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list); - if (oi->thread_send_lsupdate == NULL) - oi->thread_send_lsupdate = - thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0); - } - else + if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && + IS_AREA_STUB (oa)) + continue; + + ospf6_flood_area (from, lsa, oa); + } +} + +void +ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa) +{ + ospf6_flood_process (from, lsa, ospf6); +} + +void +ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi) +{ + listnode node; + struct ospf6_neighbor *on; + struct ospf6_lsa *rem; + + for (node = listhead (oi->neighbor_list); node; nextnode (node)) + { + on = OSPF6_NEIGHBOR (getdata (node)); + rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, on->retrans_list); + if (rem && ! ospf6_lsa_compare (rem, lsa)) { - for (j = listhead (oi->neighbor_list); j; nextnode (j)) - { - on = (struct ospf6_neighbor *) getdata (j); - THREAD_OFF (on->thread_send_lsupdate); - on->thread_send_lsupdate = - thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0); - } + if (IS_OSPF6_DEBUG_LSA (DATABASE)) + zlog_info ("Remove %s from retrans_list of %s", + rem->name, on->name); + ospf6_decrement_retrans_count (rem); + ospf6_lsdb_remove (rem, on->retrans_list); } } +} + +void +ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa) +{ + listnode node; + struct ospf6_interface *oi; + + for (node = listhead (oa->if_list); node; nextnode (node)) + { + oi = OSPF6_INTERFACE (getdata (node)); - list_delete (eligible_interfaces); + if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && + oi != OSPF6_INTERFACE (lsa->lsdb->data)) + continue; + +#if 0 + if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS && + ospf6_is_interface_virtual_link (oi)) + continue; +#endif/*0*/ + + ospf6_flood_clear_interface (lsa, oi); + } +} + +void +ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process) +{ + listnode node; + struct ospf6_area *oa; + + for (node = listhead (process->area_list); node; nextnode (node)) + { + oa = OSPF6_AREA (getdata (node)); + + if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA && + oa != OSPF6_AREA (lsa->lsdb->data)) + continue; + if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && + oa != OSPF6_INTERFACE (lsa->lsdb->data)->area) + continue; + + if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && + IS_AREA_STUB (oa)) + continue; + + ospf6_flood_clear_area (lsa, oa); + } +} + +void +ospf6_flood_clear (struct ospf6_lsa *lsa) +{ + ospf6_flood_clear_process (lsa, ospf6); } + /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */ static void ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent, @@ -396,7 +519,7 @@ ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent, if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK)) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" BDR, FloodBack, No acknowledgement."); + zlog_info ("No acknowledgement (BDR & FloodBack)"); return; } @@ -406,16 +529,11 @@ ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent, otherwide do nothing. */ if (ismore_recent < 0) { - if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" BDR, Not FloodBack, MoreRecent, "); if (oi->drouter == from->router_id) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" From DR, Delayed acknowledgement."); + zlog_info ("Delayed acknowledgement (BDR & MoreRecent & from DR)"); /* Delayed acknowledgement */ - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info (" Add copy of %s to lsack_list of %s", - lsa->name, oi->interface->name); ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); if (oi->thread_send_lsack == NULL) oi->thread_send_lsack = @@ -424,7 +542,7 @@ ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent, else { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" Not From DR, No acknowledgement."); + zlog_info ("No acknowledgement (BDR & MoreRecent & ! from DR)"); } return; } @@ -435,16 +553,11 @@ ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent, if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) { - if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" BDR, Duplicate, ImpliedAck, "); if (oi->drouter == from->router_id) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" From DR, Delayed acknowledgement."); + zlog_info ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)"); /* Delayed acknowledgement */ - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info (" Add copy of %s to lsack_list of %s", - lsa->name, oi->interface->name); ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); if (oi->thread_send_lsack == NULL) oi->thread_send_lsack = @@ -453,7 +566,7 @@ ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent, else { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" Not From DR, No acknowledgement."); + zlog_info ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)"); } return; } @@ -464,10 +577,7 @@ ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent, ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" BDR, Duplicate, Not ImpliedAck, Direct acknowledgement."); - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info (" Add copy of %s to lsack_list of %s", - lsa->name, from->name); + zlog_info ("Direct acknowledgement (BDR & Duplicate)"); ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); if (from->thread_send_lsack == NULL) from->thread_send_lsack = @@ -496,7 +606,7 @@ ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent, if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK)) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" AllOther, FloodBack, No acknowledgement."); + zlog_info ("No acknowledgement (AllOther & FloodBack)"); return; } @@ -505,11 +615,8 @@ ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent, if (ismore_recent < 0) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" AllOther, Not FloodBack, Delayed acknowledgement."); + zlog_info ("Delayed acknowledgement (AllOther & MoreRecent)"); /* Delayed acknowledgement */ - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info (" Add copy of %s to lsack_list of %s", - lsa->name, oi->interface->name); ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); if (oi->thread_send_lsack == NULL) oi->thread_send_lsack = @@ -523,7 +630,7 @@ ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent, CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" AllOther, Duplicate, ImpliedAck, No acknowledgement."); + zlog_info ("No acknowledgement (AllOther & Duplicate & ImpliedAck)"); return; } @@ -533,10 +640,7 @@ ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent, ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info (" AllOther, Duplicate, Not ImpliedAck, Direct acknowledgement."); - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info (" Add copy of %s to lsack_list of %s", - lsa->name, from->name); + zlog_info ("Direct acknowledgement (AllOther & Duplicate)"); ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); if (from->thread_send_lsack == NULL) from->thread_send_lsack = @@ -571,106 +675,55 @@ ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent, is in states Exchange or Loading returns 1 if match this case, else returns 0 */ static int -ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, - struct ospf6_neighbor *from) +ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from) { - struct ospf6_lsdb *lsdb = NULL; struct ospf6_neighbor *on; - struct ospf6_interface *oi, *ospf6_if = NULL; - struct ospf6_area *oa, *area = NULL; - struct ospf6 *ospf6 = NULL; - u_int16_t scope_type; - list scoped_interfaces; - listnode i, j; + struct ospf6_interface *oi; + struct ospf6_area *oa; + struct ospf6 *process = NULL; + listnode i, j, k; int count = 0; if (! OSPF6_LSA_IS_MAXAGE (lsa)) return 0; - lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope); - if (lsdb == NULL) - { - zlog_info ("Can't decide scoped LSDB"); - return 0; - } - if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsdb)) + lsa->header->adv_router, lsa->lsdb)) return 0; - scoped_interfaces = list_new (); - scope_type = OSPF6_LSA_SCOPE (lsa->header->type); - - if (scope_type == OSPF6_LSA_SCOPE_LINKLOCAL) - { - ospf6_if = (struct ospf6_interface *) lsa->scope; - area = ospf6_if->area; - ospf6 = area->ospf6; - } - else if (scope_type == OSPF6_LSA_SCOPE_AREA) - { - area = (struct ospf6_area *) lsa->scope; - ospf6 = area->ospf6; - } - else if (scope_type == OSPF6_LSA_SCOPE_AS) - { - ospf6 = (struct ospf6 *) lsa->scope; - } - else - { - zlog_info ("Can't decide LSA scope"); - return 0; - } - - /* Collect eligible interfaces */ - for (i = listhead (ospf6->area_list); i; nextnode (i)) + process = from->ospf6_if->area->ospf6; + for (i = listhead (process->area_list); i; nextnode (i)) { - oa = (struct ospf6_area *) getdata (i); - if (scope_type != OSPF6_LSA_SCOPE_AS && oa != area) - continue; - + oa = OSPF6_AREA (getdata (i)); for (j = listhead (oa->if_list); j; nextnode (j)) { - oi = (struct ospf6_interface *) getdata (j); - if (scope_type != OSPF6_LSA_SCOPE_AS && - scope_type != OSPF6_LSA_SCOPE_AREA && oi != ospf6_if) - continue; - - listnode_add (scoped_interfaces, oi); - } - } - - for (i = listhead (scoped_interfaces); i; nextnode (i)) - { - oi = (struct ospf6_interface *) getdata (i); - for (j = listhead (oi->neighbor_list); j; nextnode (j)) - { - on = (struct ospf6_neighbor *) getdata (j); - if (on->state == OSPF6_NEIGHBOR_EXCHANGE || - on->state == OSPF6_NEIGHBOR_LOADING) - count ++; + oi = OSPF6_INTERFACE (getdata (j)); + for (k = listhead (oi->neighbor_list); k; nextnode (k)) + { + on = OSPF6_NEIGHBOR (getdata (k)); + if (on->state == OSPF6_NEIGHBOR_EXCHANGE || + on->state == OSPF6_NEIGHBOR_LOADING) + count++; + } } } - list_delete (scoped_interfaces); - if (count == 0) return 1; - return 0; } /* RFC2328 section 13 The Flooding Procedure */ void -ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header, - struct ospf6_neighbor *from) +ospf6_receive_lsa (struct ospf6_neighbor *from, + struct ospf6_lsa_header *lsa_header) { struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL; int ismore_recent; unsigned short cksum; - struct ospf6_lsdb *lsdb = NULL; ismore_recent = 1; + assert (from); /* make lsa structure for received lsa */ new = ospf6_lsa_create (lsa_header); @@ -681,30 +734,45 @@ ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header, ospf6_lsa_header_print (new); } - new->scope = ospf6_get_lsa_scope (new->header->type, from); - if (new->scope == NULL) + /* (1) LSA Checksum */ + cksum = ntohs (new->header->checksum); + if (ntohs (ospf6_lsa_checksum (new->header)) != cksum) { - zlog_warn ("Can't decide LSA scope, ignore"); + if (IS_OSPF6_DEBUG_LSA (RECV)) + zlog_info ("Wrong LSA Checksum, discard"); ospf6_lsa_delete (new); return; } - /* (1) LSA Checksum */ - cksum = ntohs (new->header->checksum); - if (ntohs (ospf6_lsa_checksum (new->header)) != cksum) + /* (2) Examine the LSA's LS type. + RFC2470 3.5.1. Receiving Link State Update packets */ + if (IS_AREA_STUB (from->ospf6_if->area) && + OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("Wrong LSA Checksum"); + zlog_info ("AS-External-LSA (or AS-scope LSA) in stub area, discard"); ospf6_lsa_delete (new); return; } - /* (3) Ebit Missmatch: AS-External-LSA */ - if (ntohs (new->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && - ospf6_area_is_stub (from->ospf6_if->area)) - { + /* (3) LSA which have reserved scope is discarded + RFC2470 3.5.1. Receiving Link State Update packets */ + /* Flooding scope check. LSAs with unknown scope are discarded here. + Set appropriate LSDB for the LSA */ + switch (OSPF6_LSA_SCOPE (new->header->type)) + { + case OSPF6_SCOPE_LINKLOCAL: + new->lsdb = from->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + new->lsdb = from->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + new->lsdb = from->ospf6_if->area->ospf6->lsdb; + break; + default: if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("AS-External-LSA in stub area"); + zlog_info ("LSA has reserved scope, discard"); ospf6_lsa_delete (new); return; } @@ -715,41 +783,30 @@ ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header, { /* log */ if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("Drop MaxAge LSA with Direct acknowledgement."); + zlog_info ("Drop MaxAge LSA with direct acknowledgement."); /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */ - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info (" Add %s to lsack_list of %s", - new->name, from->name); - ospf6_lsdb_add (new, from->lsack_list); + ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list); if (from->thread_send_lsack == NULL) from->thread_send_lsack = thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); /* b) Discard */ - /* "new" LSA will be discarded just after the LSAck sent */ + ospf6_lsa_delete (new); return; } /* (5) */ /* lookup the same database copy in lsdb */ - lsdb = ospf6_get_scoped_lsdb (new->header->type, new->scope); - if (lsdb == NULL) - { - zlog_warn ("Can't decide scoped LSDB, ignore"); - ospf6_lsa_delete (new); - return; - } - old = ospf6_lsdb_lookup (new->header->type, new->header->id, - new->header->adv_router, lsdb); + new->header->adv_router, new->lsdb); if (old) { ismore_recent = ospf6_lsa_compare (new, old); if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum)) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("Duplicated LSA"); + zlog_info ("Received is duplicated LSA"); SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE); } } @@ -769,35 +826,43 @@ ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header, if (res.tv_sec < MIN_LS_ARRIVAL) { if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (TIMER)) - zlog_info ("LSA can't be updated within MinLSArrival"); + zlog_info ("LSA can't be updated within MinLSArrival, discard"); ospf6_lsa_delete (new); return; /* examin next lsa */ } } + if (IS_OSPF6_DEBUG_LSA (RECV)) + zlog_info ("Flood, Install, Possibly acknowledge the received LSA"); + /* (b) immediately flood and (c) remove from all retrans-list */ - ospf6_flood_lsa (new, from); + ospf6_flood (from, new); + + /* (c) Remove the current database copy from all neighbors' Link + state retransmission lists. */ + /* XXX, flood_clear ? */ /* (d), installing lsdb, which may cause routing table calculation (replacing database copy) */ - ospf6_install_lsa (new, lsdb); + ospf6_install_lsa (new); /* (e) possibly acknowledge */ ospf6_acknowledge_lsa (new, ismore_recent, from); - /* (f) */ - /* Self Originated LSA, section 13.4 */ - if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id - && (! old || ismore_recent < 0)) + /* (f) Self Originated LSA, section 13.4 */ + if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id) { - /* We have to make a new instance of the LSA + /* Self-originated LSA (newer than ours) is received from + another router. We have to make a new instance of the LSA or have to flush this LSA. */ if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("New instance of the self-originated LSA"); - - SET_FLAG (new->flag, OSPF6_LSA_REFRESH); - ospf6_lsa_re_originate (new); + { + zlog_info ("Newer instance of the self-originated LSA"); + zlog_info ("Schedule reorigination"); + } + new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0); } + return; } @@ -809,7 +874,10 @@ ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header, assert (old); if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("LSA is not newer and on request-list of sending neighbor"); + { + zlog_info ("Received is not newer, on the neighbor's request-list"); + zlog_info ("BadLSReq, discard the received LSA"); + } /* BadLSReq */ thread_add_event (master, bad_lsreq, from, 0); @@ -822,7 +890,7 @@ ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header, if (ismore_recent == 0) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("The same instance as database copy"); + zlog_info ("The same instance as database copy (neither recent)"); /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */ rem = ospf6_lsdb_lookup (new->header->type, new->header->id, @@ -830,15 +898,18 @@ ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header, if (rem) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("Treat as an Implied acknowledgement"); + { + zlog_info ("It is on the neighbor's retrans-list."); + zlog_info ("Treat as an Implied acknowledgement"); + } SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK); - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info ("Remove %s from retrans_list of %s", - rem->name, from->name); - ospf6_decrement_onretrans (rem); + ospf6_decrement_retrans_count (rem); ospf6_lsdb_remove (rem, from->retrans_list); } + if (IS_OSPF6_DEBUG_LSA (RECV)) + zlog_info ("Possibly acknowledge and then discard"); + /* (b) possibly acknowledge */ ospf6_acknowledge_lsa (new, ismore_recent, from); @@ -856,7 +927,10 @@ ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header, old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER)) { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("Database copy is in Seqnumber Wrapping"); + { + zlog_info ("The LSA is in Seqnumber Wrapping"); + zlog_info ("MaxAge & MaxSeqNum, discard"); + } ospf6_lsa_delete (new); return; } @@ -864,13 +938,13 @@ ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header, /* Otherwise, Send database copy of this LSA to this neighbor */ { if (IS_OSPF6_DEBUG_LSA (RECV)) - zlog_info ("Database is more recent, send back directly"); + { + zlog_info ("Database copy is more recent."); + zlog_info ("Send back directly and then discard"); + } /* XXX, MinLSArrival check !? RFC 2328 13 (8) */ - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info (" Add copy of %s to lsupdate_list of %s", - old->name, from->name); ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list); if (from->thread_send_lsupdate == NULL) from->thread_send_lsupdate = diff --git a/ospf6d/ospf6_flood.h b/ospf6d/ospf6_flood.h index f639f63d..e894e568 100644 --- a/ospf6d/ospf6_flood.h +++ b/ospf6d/ospf6_flood.h @@ -23,15 +23,31 @@ #define OSPF6_FLOOD_H /* Function Prototypes */ -void *ospf6_get_lsa_scope (u_int16_t type, struct ospf6_neighbor *from); -struct ospf6_lsdb *ospf6_get_scoped_lsdb (u_int16_t type, void *scope); +struct ospf6_lsdb *ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa); +struct ospf6_lsdb *ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa); -void ospf6_decrement_onretrans (struct ospf6_lsa *lsa); +/* origination & purging */ +void ospf6_lsa_originate (struct ospf6_lsa *lsa); +void ospf6_lsa_originate_process (struct ospf6_lsa *lsa, + struct ospf6 *process); +void ospf6_lsa_originate_area (struct ospf6_lsa *lsa, + struct ospf6_area *oa); +void ospf6_lsa_originate_interface (struct ospf6_lsa *lsa, + struct ospf6_interface *oi); +void ospf6_lsa_purge (struct ospf6_lsa *lsa); + +/* access method to retrans_count */ +void ospf6_increment_retrans_count (struct ospf6_lsa *lsa); +void ospf6_decrement_retrans_count (struct ospf6_lsa *lsa); + +/* flooding & clear flooding */ void ospf6_flood_clear (struct ospf6_lsa *lsa); -void ospf6_flood_lsa (struct ospf6_lsa *lsa, struct ospf6_neighbor *from); -void ospf6_install_lsa (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb); -void ospf6_receive_lsa (struct ospf6_lsa_header *header, - struct ospf6_neighbor *from); +void ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa); + +/* receive & install */ +void ospf6_receive_lsa (struct ospf6_neighbor *from, + struct ospf6_lsa_header *header); +void ospf6_install_lsa (struct ospf6_lsa *lsa); #endif /* OSPF6_FLOOD_H */ diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index ccacc237..56ecacc6 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -89,21 +89,18 @@ ospf6_interface_lookup_by_name (char *ifname) void ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa) { - struct ospf6_interface *oi; - - oi = (struct ospf6_interface *) lsa->scope; switch (ntohs (lsa->header->type)) { case OSPF6_LSTYPE_LINK: - if (oi->state == OSPF6_INTERFACE_DR) - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); - ospf6_spf_schedule (oi->area); + if (OSPF6_INTERFACE (lsa->lsdb->data)->state == OSPF6_INTERFACE_DR) + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (OSPF6_INTERFACE (lsa->lsdb->data)); + ospf6_spf_schedule (OSPF6_INTERFACE (lsa->lsdb->data)->area); break; default: if (IS_OSPF6_DEBUG_LSA (RECV)) zlog_info ("Unknown LSA in Interface %s's lsdb", - oi->interface->name); + OSPF6_INTERFACE (lsa->lsdb->data)->interface->name); break; } } @@ -151,11 +148,12 @@ ospf6_interface_create (struct interface *ifp) oi->ifmtu = iobuflen; } - oi->lsupdate_list = ospf6_lsdb_create (); - oi->lsack_list = ospf6_lsdb_create (); - oi->lsdb = ospf6_lsdb_create (); + oi->lsupdate_list = ospf6_lsdb_create (oi); + oi->lsack_list = ospf6_lsdb_create (oi); + oi->lsdb = ospf6_lsdb_create (oi); oi->lsdb->hook_add = ospf6_interface_lsdb_hook; oi->lsdb->hook_remove = ospf6_interface_lsdb_hook; + oi->lsdb_self = ospf6_lsdb_create (oi); oi->route_connected = ospf6_route_table_create (); @@ -188,6 +186,8 @@ ospf6_interface_delete (struct ospf6_interface *oi) ospf6_lsdb_remove_all (oi->lsack_list); ospf6_lsdb_delete (oi->lsdb); + ospf6_lsdb_delete (oi->lsdb_self); + ospf6_lsdb_delete (oi->lsupdate_list); ospf6_lsdb_delete (oi->lsack_list); @@ -428,7 +428,14 @@ ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi) ospf6_join_alldrouters (oi->interface->ifindex); OSPF6_ROUTER_LSA_SCHEDULE (oi->area); - if (prev_state == OSPF6_INTERFACE_DR || next_state == OSPF6_INTERFACE_DR) + if (next_state == OSPF6_INTERFACE_DOWN) + { + OSPF6_NETWORK_LSA_EXECUTE (oi); + OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT (oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); + } + else if (prev_state == OSPF6_INTERFACE_DR || + next_state == OSPF6_INTERFACE_DR) { OSPF6_NETWORK_LSA_SCHEDULE (oi); OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index 48b56fc0..be3007d9 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -84,6 +84,7 @@ struct ospf6_interface /* Linklocal LSA Database: includes Link-LSA */ struct ospf6_lsdb *lsdb; + struct ospf6_lsdb *lsdb_self; struct ospf6_lsdb *lsupdate_list; struct ospf6_lsdb *lsack_list; diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 72e2bde2..74a89642 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -43,6 +43,8 @@ #include "ospf6_neighbor.h" #include "ospf6_intra.h" #include "ospf6_asbr.h" +#include "ospf6_abr.h" +#include "ospf6_flood.h" #include "ospf6d.h" /******************************/ @@ -97,9 +99,11 @@ ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) return 0; } -void -ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force) +int +ospf6_router_lsa_originate (struct thread *thread) { + struct ospf6_area *oa; + char buffer [OSPF6_MAX_LSASIZE]; struct ospf6_lsa_header *lsa_header; struct ospf6_lsa *lsa; @@ -114,6 +118,9 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force) u_int32_t router; int count; + oa = (struct ospf6_area *) THREAD_ARG (thread); + oa->thread_router_lsa = NULL; + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) zlog_info ("Originate Router-LSA for Area %s", oa->name); @@ -129,7 +136,10 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force) OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R); OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC); - UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B); + if (ospf6_is_router_abr (ospf6)) + SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B); + else + UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B); if (ospf6_asbr_is_asbr (ospf6)) SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E); else @@ -171,7 +181,7 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force) { if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) zlog_info ("Size limit setting for Router-LSA too short"); - return; + return 0; } /* Fill LSA Header */ @@ -189,12 +199,9 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force) /* create LSA */ lsa = ospf6_lsa_create (lsa_header); - lsa->scope = oa; - if (force) - SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); /* Originate */ - ospf6_lsa_originate (lsa); + ospf6_lsa_originate_area (lsa, oa); /* Reset setting for consecutive origination */ memset ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa), @@ -277,15 +284,17 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force) /* create LSA */ lsa = ospf6_lsa_create (lsa_header); - lsa->scope = oa; - if (force) - SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); /* Originate */ - ospf6_lsa_originate (lsa); + ospf6_lsa_originate_area (lsa, oa); link_state_id ++; } + else + { + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info ("Nothing to describe in Router-LSA, suppress"); + } /* Do premature-aging of rest, undesired Router-LSAs */ type = ntohs (OSPF6_LSTYPE_ROUTER); @@ -295,36 +304,12 @@ ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force) { if (ntohl (lsa->header->id) < link_state_id) continue; - ospf6_lsa_premature_aging (lsa); + ospf6_lsa_purge (lsa); } -} - -int -ospf6_router_lsa_originate (struct thread *thread) -{ - struct ospf6_area *oa; - int force = 0; - - oa = (struct ospf6_area *) THREAD_ARG (thread); - oa->thread_router_lsa = NULL; - ospf6_router_lsa_originate_sub (oa, force); - - return 0; -} - -int -ospf6_router_lsa_reoriginate (struct ospf6_lsa *lsa) -{ - struct ospf6_area *oa; - int force = 1; - - oa = (struct ospf6_area *) lsa->scope; - ospf6_router_lsa_originate_sub (oa, force); return 0; } - /*******************************/ /* RFC2740 3.4.3.2 Network-LSA */ /*******************************/ @@ -355,9 +340,11 @@ ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) return 0; } -void -ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force) +int +ospf6_network_lsa_originate (struct thread *thread) { + struct ospf6_interface *oi; + char buffer [OSPF6_MAX_LSASIZE]; struct ospf6_lsa_header *lsa_header; @@ -370,15 +357,13 @@ ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force) listnode i; u_int16_t type; - /* If self-originated Network-LSA for currently unenabled I/F - (but was once enabled, so other routers send it to this router), - we can't find oi->area for ospf6_lsdb_lookup (), and so can't - do premature aging of the Network-LSA. Just let the LSA flow - in network (other routers LSDB) for maximum duration of - MaxAge. The contents of this router's Router-LSA will preclude - the stale Network-LSA to be involved in routing calculation. */ - if (oi->area == NULL) - return; + oi = (struct ospf6_interface *) THREAD_ARG (thread); + oi->thread_network_lsa = NULL; + + /* The interface must be enabled until here. A Network-LSA of a + disabled interface (but was once enabled) should be flushed + by ospf6_lsa_refresh (), and does not come here. */ + assert (oi->area); old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK), htonl (oi->interface->ifindex), @@ -388,8 +373,8 @@ ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force) if (oi->state != OSPF6_INTERFACE_DR) { if (old) - ospf6_lsa_premature_aging (old); - return; + ospf6_lsa_purge (old); + return 0; } if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) @@ -408,8 +393,8 @@ ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force) if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) zlog_info ("Interface stub, ignore"); if (old) - ospf6_lsa_premature_aging (old); - return; + ospf6_lsa_purge (old); + return 0; } /* prepare buffer */ @@ -466,35 +451,9 @@ ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force) /* create LSA */ lsa = ospf6_lsa_create (lsa_header); - lsa->scope = oi->area; - if (force) - SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); /* Originate */ - ospf6_lsa_originate (lsa); -} - -int -ospf6_network_lsa_originate (struct thread *thread) -{ - struct ospf6_interface *oi; - int force = 0; - - oi = (struct ospf6_interface *) THREAD_ARG (thread); - oi->thread_network_lsa = NULL; - ospf6_network_lsa_originate_sub (oi, force); - - return 0; -} - -int -ospf6_network_lsa_reoriginate (struct ospf6_lsa *lsa) -{ - struct ospf6_interface *oi; - int force = 1; - - oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id)); - ospf6_network_lsa_originate_sub (oi, force); + ospf6_lsa_originate_area (lsa, oi->area); return 0; } @@ -558,9 +517,11 @@ ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) return 0; } -void -ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force) +int +ospf6_link_lsa_originate (struct thread *thread) { + struct ospf6_interface *oi; + char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa_header *lsa_header; struct ospf6_lsa *old, *lsa; @@ -569,8 +530,10 @@ ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force) struct ospf6_route *route; struct ospf6_prefix *op; - if (oi->area == NULL) - return; + oi = (struct ospf6_interface *) THREAD_ARG (thread); + oi->thread_link_lsa = NULL; + + assert (oi->area); /* find previous LSA */ old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK), @@ -580,8 +543,8 @@ ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force) if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE)) { if (old) - ospf6_lsa_premature_aging (old); - return; + ospf6_lsa_purge (old); + return 0; } if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) @@ -594,8 +557,8 @@ ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force) zlog_info ("No Linklocal address on %s, defer originating", oi->interface->name); if (old) - ospf6_lsa_premature_aging (old); - return; + ospf6_lsa_purge (old); + return 0; } /* prepare buffer */ @@ -641,35 +604,9 @@ ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force) /* create LSA */ lsa = ospf6_lsa_create (lsa_header); - lsa->scope = oi; - if (force) - SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); /* Originate */ - ospf6_lsa_originate (lsa); -} - -int -ospf6_link_lsa_originate (struct thread *thread) -{ - struct ospf6_interface *oi; - int force = 0; - - oi = (struct ospf6_interface *) THREAD_ARG (thread); - oi->thread_link_lsa = NULL; - ospf6_link_lsa_originate_sub (oi, force); - - return 0; -} - -int -ospf6_link_lsa_reoriginate (struct ospf6_lsa *lsa) -{ - struct ospf6_interface *oi; - int force = 1; - - oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id)); - ospf6_link_lsa_originate_sub (oi, force); + ospf6_lsa_originate_interface (lsa, oi); return 0; } @@ -736,10 +673,11 @@ ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) return 0; } -void -ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa, - int force) +int +ospf6_intra_prefix_lsa_originate_stub (struct thread *thread) { + struct ospf6_area *oa; + char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa_header *lsa_header; struct ospf6_lsa *old, *lsa; @@ -755,15 +693,18 @@ ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa, char buf[BUFSIZ]; struct ospf6_route_table *route_advertise; + oa = (struct ospf6_area *) THREAD_ARG (thread); + oa->thread_intra_prefix_lsa = NULL; + /* find previous LSA */ old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX), htonl (0), oa->ospf6->router_id, oa->lsdb); - if (CHECK_FLAG (oa->flag, OSPF6_AREA_DISABLE)) + if (! IS_AREA_ENABLED (oa)) { if (old) - ospf6_lsa_premature_aging (old); - return; + ospf6_lsa_purge (old); + return 0; } if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) @@ -830,9 +771,9 @@ ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa, if (route_advertise->count == 0) { if (old) - ospf6_lsa_premature_aging (old); + ospf6_lsa_purge (old); ospf6_route_table_delete (route_advertise); - return; + return 0; } /* put prefixes to advertise */ @@ -857,7 +798,7 @@ ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa, { if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise"); - return; + return 0; } intra_prefix_lsa->prefix_num = htons (prefix_num); @@ -877,18 +818,19 @@ ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa, /* create LSA */ lsa = ospf6_lsa_create (lsa_header); - lsa->scope = oa; - if (force) - SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); /* Originate */ - ospf6_lsa_originate (lsa); + ospf6_lsa_originate_area (lsa, oa); + + return 0; } -void -ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi, - int force) + +int +ospf6_intra_prefix_lsa_originate_transit (struct thread *thread) { + struct ospf6_interface *oi; + char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa_header *lsa_header; struct ospf6_lsa *old, *lsa; @@ -906,8 +848,10 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi, u_int16_t type; char buf[BUFSIZ]; - if (oi->area == NULL) - return; + oi = (struct ospf6_interface *) THREAD_ARG (thread); + oi->thread_intra_prefix_lsa = NULL; + + assert (oi->area); /* find previous LSA */ old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX), @@ -917,8 +861,8 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi, if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE)) { if (old) - ospf6_lsa_premature_aging (old); - return; + ospf6_lsa_purge (old); + return 0; } if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) @@ -941,8 +885,8 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi, if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) zlog_info (" Interface is not DR"); if (old) - ospf6_lsa_premature_aging (old); - return; + ospf6_lsa_purge (old); + return 0; } full_count = 0; @@ -957,8 +901,8 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi, if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) zlog_info (" Interface is stub"); if (old) - ospf6_lsa_premature_aging (old); - return; + ospf6_lsa_purge (old); + return 0; } /* connected prefix to advertise */ @@ -1053,7 +997,7 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi, { if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise"); - return; + return 0; } intra_prefix_lsa->prefix_num = htons (prefix_num); @@ -1073,69 +1017,9 @@ ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi, /* create LSA */ lsa = ospf6_lsa_create (lsa_header); - lsa->scope = oi->area; - if (force) - SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); /* Originate */ - ospf6_lsa_originate (lsa); -} - -int -ospf6_intra_prefix_lsa_originate_stub (struct thread *thread) -{ - struct ospf6_area *oa; - int force = 0; - - oa = (struct ospf6_area *) THREAD_ARG (thread); - oa->thread_intra_prefix_lsa = NULL; - ospf6_intra_prefix_lsa_originate_stub_sub (oa, force); - - return 0; -} - -int -ospf6_intra_prefix_lsa_originate_transit (struct thread *thread) -{ - struct ospf6_interface *oi; - int force = 0; - - oi = (struct ospf6_interface *) THREAD_ARG (thread); - oi->thread_intra_prefix_lsa = NULL; - ospf6_intra_prefix_lsa_originate_transit_sub (oi, force); - - return 0; -} - -int -ospf6_intra_prefix_lsa_reoriginate (struct ospf6_lsa *lsa) -{ - struct ospf6_intra_prefix_lsa *intra_prefix_lsa; - u_int16_t type; - u_int32_t id; - struct ospf6_area *oa; - struct ospf6_interface *oi; - int force = 1; - - intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) - ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - type = ntohs (intra_prefix_lsa->ref_type); - id = ntohl (intra_prefix_lsa->ref_id); - - if (type == OSPF6_LSTYPE_ROUTER && id == 0) - { - oa = (struct ospf6_area *) lsa->scope; - ospf6_intra_prefix_lsa_originate_stub_sub (oa, force); - } - else if (type == OSPF6_LSTYPE_NETWORK && id != 0) - { - if (intra_prefix_lsa->ref_id != lsa->header->id) - ospf6_lsa_premature_aging (lsa); - oi = ospf6_interface_lookup_by_ifindex (id); - ospf6_intra_prefix_lsa_originate_transit_sub (oi, force); - } - else - ospf6_lsa_premature_aging (lsa); + ospf6_lsa_originate_area (lsa, oi->area); return 0; } @@ -1155,7 +1039,8 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa) if (IS_OSPF6_DEBUG_ROUTE (INTRA)) zlog_info ("%s found", lsa->name); - oa = (struct ospf6_area *) lsa->scope; + oa = OSPF6_AREA (lsa->lsdb->data); + intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) OSPF6_LSA_HEADER_END (lsa->header); if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER)) @@ -1244,7 +1129,8 @@ ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa) if (IS_OSPF6_DEBUG_ROUTE (INTRA)) zlog_info ("%s disappearing", lsa->name); - oa = (struct ospf6_area *) lsa->scope; + oa = OSPF6_AREA (lsa->lsdb->data); + intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) OSPF6_LSA_HEADER_END (lsa->header); @@ -1355,21 +1241,22 @@ ospf6_intra_route_calculation (struct ospf6_area *oa) } void -ospf6_intra_asbr_calculation (struct ospf6_area *oa) +ospf6_intra_brouter_calculation (struct ospf6_area *oa) { struct ospf6_route *lsentry, *copy; void (*hook_add) (struct ospf6_route *) = NULL; void (*hook_remove) (struct ospf6_route *) = NULL; - if (IS_OSPF6_DEBUG_ASBR) - zlog_info ("Intra-area ASBR calculation for area %s", oa->name); + if (IS_OSPF6_DEBUG_ROUTE (INTRA)) + zlog_info ("Border-router calculation for area %s", oa->name); - hook_add = oa->ospf6->asbr_table->hook_add; - hook_remove = oa->ospf6->asbr_table->hook_remove; - oa->ospf6->asbr_table->hook_add = NULL; - oa->ospf6->asbr_table->hook_remove = NULL; + hook_add = oa->ospf6->brouter_table->hook_add; + hook_remove = oa->ospf6->brouter_table->hook_remove; + oa->ospf6->brouter_table->hook_add = NULL; + oa->ospf6->brouter_table->hook_remove = NULL; - for (lsentry = ospf6_route_head (oa->ospf6->asbr_table); lsentry; + /* withdraw the previous router entries for the area */ + for (lsentry = ospf6_route_head (oa->ospf6->brouter_table); lsentry; lsentry = ospf6_route_next (lsentry)) { if (lsentry->path.area_id != oa->area_id) @@ -1384,20 +1271,21 @@ ospf6_intra_asbr_calculation (struct ospf6_area *oa) continue; if (ospf6_linkstate_prefix_id (&lsentry->prefix) != htonl (0)) continue; - if (! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_E)) + if (! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_E) && + ! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_B)) continue; copy = ospf6_route_copy (lsentry); copy->type = OSPF6_DEST_TYPE_ROUTER; copy->prefix.family = AF_INET; copy->prefix.prefixlen = 32; - ospf6_route_add (copy, oa->ospf6->asbr_table); + ospf6_route_add (copy, oa->ospf6->brouter_table); } - oa->ospf6->asbr_table->hook_add = hook_add; - oa->ospf6->asbr_table->hook_remove = hook_remove; + oa->ospf6->brouter_table->hook_add = hook_add; + oa->ospf6->brouter_table->hook_remove = hook_remove; - for (lsentry = ospf6_route_head (oa->ospf6->asbr_table); lsentry; + for (lsentry = ospf6_route_head (oa->ospf6->brouter_table); lsentry; lsentry = ospf6_route_next (lsentry)) { if (lsentry->path.area_id != oa->area_id) @@ -1411,7 +1299,7 @@ ospf6_intra_asbr_calculation (struct ospf6_area *oa) } if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE)) - ospf6_route_remove (lsentry, oa->ospf6->asbr_table); + ospf6_route_remove (lsentry, oa->ospf6->brouter_table); else if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD) || CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_CHANGE)) { @@ -1422,27 +1310,45 @@ ospf6_intra_asbr_calculation (struct ospf6_area *oa) lsentry->flag = 0; } - if (IS_OSPF6_DEBUG_ASBR) - zlog_info ("Intra-area ASBR calculation for area %s: Done", oa->name); + if (IS_OSPF6_DEBUG_ROUTE (INTRA)) + zlog_info ("Border-router calculation for area %s: Done", oa->name); } +struct ospf6_lsa_handler router_handler = +{ + OSPF6_LSTYPE_ROUTER, + "Router", + ospf6_router_lsa_show +}; + +struct ospf6_lsa_handler network_handler = +{ + OSPF6_LSTYPE_NETWORK, + "Network", + ospf6_network_lsa_show +}; + +struct ospf6_lsa_handler link_handler = +{ + OSPF6_LSTYPE_LINK, + "Link", + ospf6_link_lsa_show +}; + +struct ospf6_lsa_handler intra_prefix_handler = +{ + OSPF6_LSTYPE_INTRA_PREFIX, + "Intra-Prefix", + ospf6_intra_prefix_lsa_show +}; + void ospf6_intra_init () { - ospf6_lstype[1].name = "Router"; - ospf6_lstype[2].name = "Network"; - ospf6_lstype[8].name = "Link"; - ospf6_lstype[9].name = "Intra-Prefix"; - - ospf6_lstype[1].reoriginate = ospf6_router_lsa_reoriginate; - ospf6_lstype[2].reoriginate = ospf6_network_lsa_reoriginate; - ospf6_lstype[8].reoriginate = ospf6_link_lsa_reoriginate; - ospf6_lstype[9].reoriginate = ospf6_intra_prefix_lsa_reoriginate; - - ospf6_lstype[1].show = ospf6_router_lsa_show; - ospf6_lstype[2].show = ospf6_network_lsa_show; - ospf6_lstype[8].show = ospf6_link_lsa_show; - ospf6_lstype[9].show = ospf6_intra_prefix_lsa_show; + ospf6_install_lsa_handler (&router_handler); + ospf6_install_lsa_handler (&network_handler); + ospf6_install_lsa_handler (&link_handler); + ospf6_install_lsa_handler (&intra_prefix_handler); } diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h index 28780b4a..db92f7e7 100644 --- a/ospf6d/ospf6_intra.h +++ b/ospf6d/ospf6_intra.h @@ -128,6 +128,18 @@ struct ospf6_intra_prefix_lsa oi, 0); \ } while (0) +#define OSPF6_NETWORK_LSA_EXECUTE(oi) \ + do { \ + THREAD_OFF ((oi)->thread_network_lsa); \ + thread_execute (master, ospf6_network_lsa_originate, oi, 0); \ + } while (0) +#define OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi) \ + do { \ + THREAD_OFF ((oi)->thread_intra_prefix_lsa); \ + thread_execute (master, ospf6_intra_prefix_lsa_originate_transit, oi, 0); \ + } while (0) + + /* Function Prototypes */ char *ospf6_router_lsdesc_lookup (u_char type, u_int32_t interface_id, u_int32_t neighbor_interface_id, @@ -145,7 +157,7 @@ void ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa); void ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa); void ospf6_intra_route_calculation (struct ospf6_area *oa); -void ospf6_intra_asbr_calculation (struct ospf6_area *oa); +void ospf6_intra_brouter_calculation (struct ospf6_area *oa); void ospf6_intra_init (); diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index 56ed318d..c031a2d9 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -43,7 +43,7 @@ unsigned char conf_debug_ospf6_lsa = 0; -struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE]; +struct ospf6_lsa_handler *ospf6_lsa_handler[OSPF6_LSTYPE_SIZE]; char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE] = {"Unknown", "Router", "Network", "Inter-Prefix", "Inter-Router", @@ -53,10 +53,10 @@ char * ospf6_lstype_name (u_int16_t type) { static char buf[8]; - int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK; + int index = OSPF6_LSTYPE_INDEX (type); - if (index < OSPF6_LSTYPE_SIZE && ospf6_lstype_str[index]) - return ospf6_lstype_str[index]; + if (ospf6_lsa_handler[index]) + return ospf6_lsa_handler[index]->name; snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type)); return buf; @@ -125,8 +125,7 @@ ospf6_lsa_age_set (struct ospf6_lsa *lsa) lsa->birth.tv_usec = now.tv_usec; if (ntohs (lsa->header->age) != MAXAGE) lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, - MAXAGE + lsa->birth.tv_sec - - now.tv_sec); + MAXAGE + lsa->birth.tv_sec - now.tv_sec); else lsa->expire = NULL; return; @@ -271,37 +270,6 @@ ospf6_lsa_header_print (struct ospf6_lsa *lsa) ospf6_lsa_header_print_raw (lsa->header); } -void -ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) -{ - char adv_router[64], id[64]; - int index; - - assert (lsa && lsa->header); - - inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); - inet_ntop (AF_INET, &lsa->header->adv_router, - adv_router, sizeof (adv_router)); - - vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa), - OSPF6_LSTYPE_NAME (lsa->header->type), VNL); - vty_out (vty, "Link State ID: %s%s", id, VNL); - vty_out (vty, "Advertising Router: %s%s", adv_router, VNL); - vty_out (vty, "LS Sequence Number: %#010lx%s", - (u_long) ntohl (lsa->header->seqnum), VNL); - vty_out (vty, "CheckSum: %#06hx Length: %hu%s", - ntohs (lsa->header->checksum), - ntohs (lsa->header->length), VNL); - - index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type)); - if (ospf6_lstype[index].show) - (*ospf6_lstype[index].show) (vty, lsa); - else - vty_out (vty, "%sUnknown LSA type ...%s", VNL, VNL); - - vty_out (vty, "%s", VNL); -} - void ospf6_lsa_show_summary_header (struct vty *vty) { @@ -360,6 +328,7 @@ ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa) } vty_out (vty, "%s%s", VNL, VNL); + return; } void @@ -386,10 +355,44 @@ ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa) vty_out (vty, " Prev: %p This: %p Next: %p%s", lsa->prev, lsa, lsa->next, VNL); vty_out (vty, "%s", VNL); + return; } -/* OSPFv3 LSA creation/deletion function */ +void +ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) +{ + char adv_router[64], id[64]; + int index; + + assert (lsa && lsa->header); + + inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); + inet_ntop (AF_INET, &lsa->header->adv_router, + adv_router, sizeof (adv_router)); + + vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa), + OSPF6_LSTYPE_NAME (lsa->header->type), VNL); + vty_out (vty, "Link State ID: %s%s", id, VNL); + vty_out (vty, "Advertising Router: %s%s", adv_router, VNL); + vty_out (vty, "LS Sequence Number: %#010lx%s", + (u_long) ntohl (lsa->header->seqnum), VNL); + vty_out (vty, "CheckSum: %#06hx Length: %hu%s", + ntohs (lsa->header->checksum), + ntohs (lsa->header->length), VNL); + index = OSPF6_LSTYPE_INDEX (lsa->header->type); + if (ospf6_lsa_handler[index]->show) + (*ospf6_lsa_handler[index]->show) (vty, lsa); + else + { + ospf6_lsa_show_dump (vty, lsa); + vty_out (vty, "%sUnknown LSA type ...%s", VNL, VNL); + } + + vty_out (vty, "%s", VNL); +} + +/* OSPFv3 LSA creation/deletion function */ struct ospf6_lsa * ospf6_lsa_create (struct ospf6_lsa_header *header) { @@ -414,7 +417,6 @@ ospf6_lsa_create (struct ospf6_lsa_header *header) memset (lsa, 0, sizeof (struct ospf6_lsa)); lsa->header = (struct ospf6_lsa_header *) new_header; - lsa->headeronly = 0; /* this is not header only */ /* dump string */ ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name)); @@ -449,7 +451,7 @@ ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header) memset (lsa, 0, sizeof (struct ospf6_lsa)); lsa->header = (struct ospf6_lsa_header *) new_header; - lsa->headeronly = 1; /* this is header only */ + SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY); /* dump string */ ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name)); @@ -475,8 +477,8 @@ ospf6_lsa_delete (struct ospf6_lsa *lsa) if (IS_OSPF6_DEBUG_LSA (MEMORY)) zlog_info ("Delete LSA %s Memory: %s (%p/%p)", - (lsa->headeronly ? "(Header-only) " : ""), - lsa->name, lsa, lsa->header); + (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY) ? + "(Header-only) " : ""), lsa->name, lsa, lsa->header); /* do free */ XFREE (MTYPE_OSPF6_LSA, lsa->header); @@ -492,7 +494,7 @@ ospf6_lsa_copy (struct ospf6_lsa *lsa) zlog_info ("Create LSA Copy from %s", lsa->name); ospf6_lsa_age_current (lsa); - if (lsa->headeronly) + if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY)) copy = ospf6_lsa_create_headeronly (lsa->header); else copy = ospf6_lsa_create (lsa->header); @@ -500,7 +502,7 @@ ospf6_lsa_copy (struct ospf6_lsa *lsa) copy->installed = lsa->installed; copy->originated = lsa->originated; - copy->scope = lsa->scope; + copy->lsdb = lsa->lsdb; return copy; } @@ -527,77 +529,12 @@ ospf6_lsa_unlock (struct ospf6_lsa *lsa) ospf6_lsa_delete (lsa); } -void -ospf6_lsa_originate (struct ospf6_lsa *lsa) -{ - struct ospf6_lsa *old; - struct ospf6_lsdb *lsdb = NULL; - - /* find previous LSA */ - lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope); - if (lsdb == NULL) - { - zlog_warn ("Can't decide scoped LSDB"); - ospf6_lsa_delete (lsa); - return; - } - - old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsdb); - if (old) - { - /* If this origination is neither different instance nor refresh, - suppress this origination */ - if (! CHECK_FLAG (old->flag, OSPF6_LSA_REFRESH) && - ! OSPF6_LSA_IS_DIFFER (lsa, old)) - { - if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) - zlog_info ("Suppress updating LSA: %s", lsa->name); - ospf6_lsa_delete (lsa); - return; - } - } - - lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, - LS_REFRESH_TIME); - - if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) - { - zlog_info ("LSA Originate:"); - ospf6_lsa_header_print (lsa); - } - - if (old) - ospf6_flood_clear (old); - ospf6_flood_lsa (lsa, NULL); - ospf6_install_lsa (lsa, lsdb); -} - -void -ospf6_lsa_re_originate (struct ospf6_lsa *lsa) -{ - u_int16_t index; - - if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) - { - zlog_info ("LSA Reoriginate:"); - ospf6_lsa_header_print (lsa); - } - - index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type)); - if (ospf6_lstype[index].reoriginate) - (*ospf6_lstype[index].reoriginate) (lsa); - else - ospf6_lsa_premature_aging (lsa); -} - /* ospf6 lsa expiry */ int ospf6_lsa_expire (struct thread *thread) { struct ospf6_lsa *lsa; - struct ospf6_lsdb *lsdb = NULL; lsa = (struct ospf6_lsa *) THREAD_ARG (thread); @@ -613,22 +550,16 @@ ospf6_lsa_expire (struct thread *thread) ospf6_lsa_header_print (lsa); } - if (lsa->headeronly) + if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY)) return 0; /* dbexchange will do something ... */ /* reflood lsa */ - ospf6_flood_lsa (lsa, NULL); + ospf6_flood (NULL, lsa); /* reinstall lsa */ - lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope); - if (lsdb == NULL) - { - zlog_warn ("Can't decide scoped LSDB: %s", lsa->name); - return 0; - } if (IS_OSPF6_DEBUG_LSA (DATABASE)) zlog_info ("Reinstall MaxAge %s", lsa->name); - ospf6_lsdb_add (lsa, lsdb); + ospf6_lsdb_add (lsa, lsa->lsdb); /* schedule maxage remover */ ospf6_maxage_remove (ospf6); @@ -636,29 +567,52 @@ ospf6_lsa_expire (struct thread *thread) return 0; } -/* Below will become dummy thread. - refresh function must be set individually per each LSAs */ int ospf6_lsa_refresh (struct thread *thread) { - struct ospf6_lsa *lsa; + struct ospf6_lsa *old, *self, *new; + struct ospf6_lsdb *lsdb_self; assert (thread); - lsa = (struct ospf6_lsa *) THREAD_ARG (thread); - assert (lsa && lsa->header); + old = (struct ospf6_lsa *) THREAD_ARG (thread); + assert (old && old->header); - lsa->refresh = (struct thread *) NULL; + old->refresh = (struct thread *) NULL; + + lsdb_self = ospf6_get_scoped_lsdb_self (old); + self = ospf6_lsdb_lookup (old->header->type, old->header->id, + old->header->adv_router, lsdb_self); + if (self == NULL) + { + ospf6_lsa_premature_aging (old); + return 0; + } + + /* Reset age, increment LS sequence number. */ + self->header->age = htons (0); + self->header->seqnum = + ospf6_new_ls_seqnum (self->header->type, self->header->id, + self->header->adv_router, old->lsdb); + ospf6_lsa_checksum (self->header); + + new = ospf6_lsa_create (self->header); + new->lsdb = old->lsdb; + new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new, + LS_REFRESH_TIME); - /* this will be used later to decide really originate or not */ - SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH); + /* store it in the LSDB for self-originated LSAs */ + ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self); if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) { zlog_info ("LSA Refresh:"); - ospf6_lsa_header_print (lsa); + ospf6_lsa_header_print (new); } - ospf6_lsa_re_originate (lsa); + ospf6_flood_clear (old); + ospf6_flood (NULL, new); + ospf6_install_lsa (new); + return 0; } @@ -708,14 +662,7 @@ ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header) } int -ospf6_unknown_reoriginate (struct ospf6_lsa *lsa) -{ - ospf6_lsa_premature_aging (lsa); - return 0; -} - -int -ospf6_unknown_show (struct vty *vty, struct ospf6_lsa *lsa) +ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) { u_char *start, *end, *current; char byte[4]; @@ -740,13 +687,25 @@ ospf6_unknown_show (struct vty *vty, struct ospf6_lsa *lsa) } void -ospf6_lsa_init () +ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler) +{ + /* might need to adjust dynamic array length ... */ + int index = OSPF6_LSTYPE_INDEX (htons (handler->type)); + ospf6_lsa_handler[index] = handler; +} + +struct ospf6_lsa_handler unknown_handler = { - memset (ospf6_lstype, 0, sizeof (ospf6_lstype)); + OSPF6_LSTYPE_UNKNOWN, + "Unknown", + ospf6_unknown_lsa_show +}; - ospf6_lstype[0].name = "Unknown"; - ospf6_lstype[0].reoriginate = ospf6_unknown_reoriginate; - ospf6_lstype[0].show = ospf6_unknown_show; +void +ospf6_lsa_init () +{ + memset (ospf6_lsa_handler, 0, sizeof (ospf6_lsa_handler)); + ospf6_install_lsa_handler (&unknown_handler); } diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index dd750e80..54921e11 100644 --- a/ospf6d/ospf6_lsa.h +++ b/ospf6d/ospf6_lsa.h @@ -62,11 +62,12 @@ extern unsigned char conf_debug_ospf6_lsa; #define OSPF6_LSTYPE_FCODE_MASK 0x1fff /* LSA scope */ -#define OSPF6_LSA_SCOPE_LINKLOCAL 0x0000 -#define OSPF6_LSA_SCOPE_AREA 0x2000 -#define OSPF6_LSA_SCOPE_AS 0x4000 -#define OSPF6_LSA_SCOPE_RESERVED 0x6000 +#define OSPF6_SCOPE_LINKLOCAL 0x0000 +#define OSPF6_SCOPE_AREA 0x2000 +#define OSPF6_SCOPE_AS 0x4000 +#define OSPF6_SCOPE_RESERVED 0x6000 +/* XXX U-bit handling should be treated here */ #define OSPF6_LSA_SCOPE(type) \ (ntohs (type) & OSPF6_LSTYPE_SCOPE_MASK) @@ -103,55 +104,46 @@ struct ospf6_lsa_header struct ospf6_lsa { - char name[64]; /* dump string */ + char name[64]; /* dump string */ - struct ospf6_lsa *prev; - struct ospf6_lsa *next; + struct ospf6_lsa *prev; + struct ospf6_lsa *next; - unsigned char lock; /* reference counter */ - unsigned char flag; /* special meaning (e.g. floodback) */ + unsigned char lock; /* reference counter */ + unsigned char flag; /* special meaning (e.g. floodback) */ - struct timeval birth; /* tv_sec when LS age 0 */ - struct timeval installed; /* used by MinLSArrival check */ - struct timeval originated; /* used by MinLSInterval check */ + struct timeval birth; /* tv_sec when LS age 0 */ + struct timeval installed; /* used by MinLSArrival check */ + struct timeval originated; /* used by MinLSInterval check */ - struct thread *expire; - struct thread *refresh; /* For self-originated LSA */ + struct thread *expire; + struct thread *refresh; /* For self-originated LSA */ - void *scope; /* pointer to scope data structure */ - int headeronly; /* indicate this is LS header only */ - int onretrans; + int retrans_count; + +struct ospf6_lsdb; + struct ospf6_lsdb *lsdb; /* lsa instance */ struct ospf6_lsa_header *header; }; -#define OSPF6_LSA_FLOODBACK 0x01 -#define OSPF6_LSA_DUPLICATE 0x02 -#define OSPF6_LSA_IMPLIEDACK 0x04 -#define OSPF6_LSA_REFRESH 0x08 +#define OSPF6_LSA_HEADERONLY 0x01 +#define OSPF6_LSA_FLOODBACK 0x02 +#define OSPF6_LSA_DUPLICATE 0x04 +#define OSPF6_LSA_IMPLIEDACK 0x08 -struct ospf6_lstype +struct ospf6_lsa_handler { + u_int16_t type; /* network byte order */ char *name; - int (*reoriginate) (struct ospf6_lsa *); int (*show) (struct vty *, struct ospf6_lsa *); }; -extern struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE]; #define OSPF6_LSTYPE_INDEX(type) \ - (((type) & OSPF6_LSTYPE_FCODE_MASK) < OSPF6_LSTYPE_SIZE ? \ - ((type) & OSPF6_LSTYPE_FCODE_MASK) : OSPF6_LSTYPE_UNKNOWN) - -#if 0 -extern char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE]; -#define OSPF6_LSTYPE_NAME(type) \ ((ntohs (type) & OSPF6_LSTYPE_FCODE_MASK) < OSPF6_LSTYPE_SIZE ? \ - ospf6_lstype_str[ntohs (type) & OSPF6_LSTYPE_FCODE_MASK] : \ - ospf6_lstype_str[OSPF6_LSTYPE_UNKNOWN]) -#else /*0*/ + (ntohs (type) & OSPF6_LSTYPE_FCODE_MASK) : OSPF6_LSTYPE_UNKNOWN) #define OSPF6_LSTYPE_NAME(type) (ospf6_lstype_name (type)) -#endif /*0*/ /* Macro for LSA Origination */ /* void (CONTINUE_IF_...) (struct prefix *addr); */ @@ -219,11 +211,11 @@ int ospf6_lsa_compare (struct ospf6_lsa *, struct ospf6_lsa *); char *ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size); void ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header); void ospf6_lsa_header_print (struct ospf6_lsa *lsa); -void ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa); void ospf6_lsa_show_summary_header (struct vty *vty); void ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa); void ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa); void ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa); +void ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa); struct ospf6_lsa *ospf6_lsa_create (struct ospf6_lsa_header *header); struct ospf6_lsa *ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header); @@ -233,8 +225,6 @@ struct ospf6_lsa *ospf6_lsa_copy (struct ospf6_lsa *); void ospf6_lsa_lock (struct ospf6_lsa *); void ospf6_lsa_unlock (struct ospf6_lsa *); -void ospf6_lsa_originate (struct ospf6_lsa *); -void ospf6_lsa_re_originate (struct ospf6_lsa *lsa); int ospf6_lsa_expire (struct thread *); int ospf6_lsa_refresh (struct thread *); @@ -242,6 +232,7 @@ unsigned short ospf6_lsa_checksum (struct ospf6_lsa_header *); int ospf6_lsa_prohibited_duration (u_int16_t type, u_int32_t id, u_int32_t adv_router, void *scope); +void ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler); void ospf6_lsa_init (); int config_write_ospf6_debug_lsa (struct vty *vty); diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c index 5c132caa..9b37406d 100644 --- a/ospf6d/ospf6_lsdb.c +++ b/ospf6d/ospf6_lsdb.c @@ -34,7 +34,7 @@ #include "ospf6d.h" struct ospf6_lsdb * -ospf6_lsdb_create () +ospf6_lsdb_create (void *data) { struct ospf6_lsdb *lsdb; @@ -46,6 +46,7 @@ ospf6_lsdb_create () } memset (lsdb, 0, sizeof (struct ospf6_lsdb)); + lsdb->data = data; lsdb->table = route_table_init (); return lsdb; } @@ -228,6 +229,7 @@ ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) ospf6_lsa_unlock (lsa); route_unlock_node (node); + ospf6_lsdb_count_assert (lsdb); } @@ -475,7 +477,7 @@ ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router, if (ntohl (lsa->header->id) < id) continue; if (ntohl (lsa->header->id) > id) - return ((u_int32_t) htonl (id)); + break; id++; } diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h index 71d996ee..a10f001c 100644 --- a/ospf6d/ospf6_lsdb.h +++ b/ospf6d/ospf6_lsdb.h @@ -27,6 +27,7 @@ struct ospf6_lsdb { + void *data; /* data structure that holds this lsdb */ struct route_table *table; u_int32_t count; void (*hook_add) (struct ospf6_lsa *); @@ -40,7 +41,7 @@ struct ospf6_lsdb { \ if (! OSPF6_LSA_IS_MAXAGE (lsa)) \ continue; \ - if (lsa->onretrans != 0) \ + if (lsa->retrans_count != 0) \ continue; \ if (IS_OSPF6_DEBUG_LSA (TIMER)) \ zlog_info (" remove maxage %s", lsa->name); \ @@ -49,7 +50,7 @@ struct ospf6_lsdb } while (0) /* Function Prototypes */ -struct ospf6_lsdb *ospf6_lsdb_create (); +struct ospf6_lsdb *ospf6_lsdb_create (void *data); void ospf6_lsdb_delete (struct ospf6_lsdb *lsdb); struct ospf6_lsa *ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 91ecdf45..7e022da5 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -245,7 +245,7 @@ ospf6_header_examin (struct in6_addr *src, struct in6_addr *dst, /* Area-ID check */ if (oh->area_id != oi->area->area_id) { - if (oh->area_id == 0) + if (oh->area_id == BACKBONE_AREA_ID) { if (IS_OSPF6_DEBUG_MESSAGE (type, RECV)) zlog_info ("Message may be via Virtual Link: not supported"); @@ -519,21 +519,34 @@ ospf6_dbdesc_recv_master (struct ospf6_header *oh, struct ospf6_lsdb *lsdb = NULL; his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p); - his->scope = ospf6_get_lsa_scope (his->header->type, on); - lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope); - if (lsdb == NULL) + + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("%s", his->name); + + switch (OSPF6_LSA_SCOPE (his->header->type)) { - zlog_warn ("Can't decide scoped LSDB"); + case OSPF6_SCOPE_LINKLOCAL: + lsdb = on->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = on->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = on->ospf6_if->area->ospf6->lsdb; + break; + case OSPF6_SCOPE_RESERVED: + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Ignoring LSA of reserved scope"); ospf6_lsa_delete (his); - thread_add_event (master, seqnumber_mismatch, on, 0); - return; + continue; + break; } if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && - ospf6_area_is_stub (on->ospf6_if->area)) + IS_AREA_STUB (on->ospf6_if->area)) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_info ("E-bit mismatch with LSA Headers"); + zlog_info ("SeqNumMismatch (E-bit mismatch), discard"); ospf6_lsa_delete (his); thread_add_event (master, seqnumber_mismatch, on, 0); return; @@ -541,14 +554,24 @@ ospf6_dbdesc_recv_master (struct ospf6_header *oh, mine = ospf6_lsdb_lookup (his->header->type, his->header->id, his->header->adv_router, lsdb); - if (mine == NULL || ospf6_lsa_compare (his, mine) < 0) + if (mine == NULL) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Add request (No database copy)", his->name); + ospf6_lsdb_add (his, on->request_list); + } + else if (ospf6_lsa_compare (his, mine) < 0) { - if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info ("Add %s's request-list: %s", on->name, his->name); + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Add request (Received MoreRecent)", his->name); ospf6_lsdb_add (his, on->request_list); } else - ospf6_lsa_delete (his); + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Discard (Existing MoreRecent)", his->name); + ospf6_lsa_delete (his); + } } if (p != OSPF6_MESSAGE_END (oh)) @@ -721,18 +744,28 @@ ospf6_dbdesc_recv_slave (struct ospf6_header *oh, struct ospf6_lsdb *lsdb = NULL; his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p); - his->scope = ospf6_get_lsa_scope (his->header->type, on); - lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope); - if (lsdb == NULL) + + switch (OSPF6_LSA_SCOPE (his->header->type)) { - zlog_warn ("Can't decide scoped LSDB"); + case OSPF6_SCOPE_LINKLOCAL: + lsdb = on->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = on->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = on->ospf6_if->area->ospf6->lsdb; + break; + case OSPF6_SCOPE_RESERVED: + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Ignoring LSA of reserved scope"); ospf6_lsa_delete (his); - thread_add_event (master, seqnumber_mismatch, on, 0); - return; + continue; + break; } - if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && - ospf6_area_is_stub (on->ospf6_if->area)) + if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS && + IS_AREA_STUB (on->ospf6_if->area)) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_info ("E-bit mismatch with LSA Headers"); @@ -745,8 +778,8 @@ ospf6_dbdesc_recv_slave (struct ospf6_header *oh, his->header->adv_router, lsdb); if (mine == NULL || ospf6_lsa_compare (his, mine) < 0) { - if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info ("Add %s to request-list of %s", his->name, on->name); + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Add request-list: %s", his->name); ospf6_lsdb_add (his, on->request_list); } else @@ -838,7 +871,6 @@ ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst, struct ospf6_neighbor *on; char *p; struct ospf6_lsreq_entry *e; - void *scope = NULL; struct ospf6_lsdb *lsdb = NULL; struct ospf6_lsa *lsa; @@ -875,8 +907,24 @@ ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst, p += sizeof (struct ospf6_lsreq_entry)) { e = (struct ospf6_lsreq_entry *) p; - scope = ospf6_get_lsa_scope (e->type, on); - lsdb = ospf6_get_scoped_lsdb (e->type, scope); + + switch (OSPF6_LSA_SCOPE (e->type)) + { + case OSPF6_SCOPE_LINKLOCAL: + lsdb = on->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = on->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = on->ospf6_if->area->ospf6->lsdb; + break; + default: + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Ignoring LSA of reserved scope"); + continue; + break; + } /* Find database copy */ lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb); @@ -895,9 +943,6 @@ ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst, return; } - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info ("Add copy of %s to lsupdate_list of %s", - lsa->name, on->name); ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list); } @@ -969,7 +1014,7 @@ ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst, break; } - ospf6_receive_lsa ((struct ospf6_lsa_header *) p, on); + ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p); num--; } @@ -1041,11 +1086,27 @@ ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst, p += sizeof (struct ospf6_lsa_header)) { his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p); - his->scope = ospf6_get_lsa_scope (his->header->type, on); - lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope); - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) || - IS_OSPF6_DEBUG_LSA (SEND)) + switch (OSPF6_LSA_SCOPE (his->header->type)) + { + case OSPF6_SCOPE_LINKLOCAL: + lsdb = on->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = on->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = on->ospf6_if->area->ospf6->lsdb; + break; + case OSPF6_SCOPE_RESERVED: + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Ignoring LSA of reserved scope"); + ospf6_lsa_delete (his); + continue; + break; + } + + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_info ("%s acknowledged by %s", his->name, on->name); /* Find database copy */ @@ -1080,18 +1141,14 @@ ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst, continue; } - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) || - IS_OSPF6_DEBUG_LSA (SEND)) + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_info ("Acknowledged, remove from %s's retrans-list", on->name); if (OSPF6_LSA_IS_MAXAGE (mine)) ospf6_maxage_remove (on->ospf6_if->area->ospf6); - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info ("remove %s from retrans_list of %s", - mine->name, on->name); - ospf6_decrement_onretrans (mine); + ospf6_decrement_retrans_count (mine); ospf6_lsdb_remove (mine, on->retrans_list); ospf6_lsa_delete (his); } @@ -1473,8 +1530,6 @@ ospf6_dbdesc_send_newone (struct thread *thread) unsigned int size = 0; on = (struct ospf6_neighbor *) THREAD_ARG (thread); - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info ("Remove entire dbdesc_list of %s: sending newone", on->name); ospf6_lsdb_remove_all (on->dbdesc_list); /* move LSAs from summary_list to dbdesc_list (within neighbor structure) @@ -1489,9 +1544,6 @@ ospf6_dbdesc_send_newone (struct thread *thread) break; } - if (IS_OSPF6_DEBUG_LSA (DATABASE)) - zlog_info ("Move %s from summary_list to dbdesc_list of %s", - lsa->name, on->name); ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list); ospf6_lsdb_remove (lsa, on->summary_list); size += sizeof (struct ospf6_lsa_header); @@ -1587,21 +1639,25 @@ ospf6_lsupdate_send_neighbor (struct thread *thread) on = (struct ospf6_neighbor *) THREAD_ARG (thread); on->thread_send_lsupdate = (struct thread *) NULL; + if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + zlog_info ("LSUpdate to neighbor %s", on->name); + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) { if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) - zlog_info ("Quit to send LSUpdate to neighbor %s state %s", - on->name, ospf6_neighbor_state_str[on->state]); + zlog_info ("Quit to send (neighbor state %s)", + ospf6_neighbor_state_str[on->state]); return 0; } /* if we have nothing to send, return */ if (on->lsupdate_list->count == 0 && on->retrans_list->count == 0) - return 0; - - if (IS_OSPF6_DEBUG_LSA (SEND)) - zlog_info ("LSA Send to %s", on->name); + { + if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + zlog_info ("Quit to send (nothing to send)"); + return 0; + } memset (sendbuf, 0, iobuflen); oh = (struct ospf6_header *) sendbuf; @@ -1623,9 +1679,6 @@ ospf6_lsupdate_send_neighbor (struct thread *thread) break; } - if (IS_OSPF6_DEBUG_LSA (SEND)) - ospf6_lsa_header_print (lsa); - ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); p += OSPF6_LSA_SIZE (lsa->header); @@ -1645,9 +1698,6 @@ ospf6_lsupdate_send_neighbor (struct thread *thread) break; } - if (IS_OSPF6_DEBUG_LSA (SEND)) - ospf6_lsa_header_print (lsa); - ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); p += OSPF6_LSA_SIZE (lsa->header); diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index a4823d28..e7818abb 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -51,7 +51,7 @@ ospf6_neighbor_cmp (void *va, void *vb) { struct ospf6_neighbor *ona = (struct ospf6_neighbor *) va; struct ospf6_neighbor *onb = (struct ospf6_neighbor *) vb; - return (ntohl (ona->router_id) - ntohl (onb->router_id)); + return (ntohl (ona->router_id) < ntohl (onb->router_id) ? -1 : 1); } struct ospf6_neighbor * @@ -94,14 +94,14 @@ ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *oi) gettimeofday (&on->last_changed, (struct timezone *) NULL); on->router_id = router_id; - on->summary_list = ospf6_lsdb_create (); - on->request_list = ospf6_lsdb_create (); - on->retrans_list = ospf6_lsdb_create (); + on->summary_list = ospf6_lsdb_create (on); + on->request_list = ospf6_lsdb_create (on); + on->retrans_list = ospf6_lsdb_create (on); - on->dbdesc_list = ospf6_lsdb_create (); - on->lsreq_list = ospf6_lsdb_create (); - on->lsupdate_list = ospf6_lsdb_create (); - on->lsack_list = ospf6_lsdb_create (); + on->dbdesc_list = ospf6_lsdb_create (on); + on->lsreq_list = ospf6_lsdb_create (on); + on->lsupdate_list = ospf6_lsdb_create (on); + on->lsack_list = ospf6_lsdb_create (on); listnode_add_sort (oi->neighbor_list, on); return on; @@ -117,7 +117,7 @@ ospf6_neighbor_delete (struct ospf6_neighbor *on) for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { - ospf6_decrement_onretrans (lsa); + ospf6_decrement_retrans_count (lsa); ospf6_lsdb_remove (lsa, on->retrans_list); } @@ -286,7 +286,7 @@ negotiation_done (struct thread *thread) for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { - ospf6_decrement_onretrans (lsa); + ospf6_decrement_retrans_count (lsa); ospf6_lsdb_remove (lsa, on->retrans_list); } @@ -300,7 +300,7 @@ negotiation_done (struct thread *thread) "summary_list"), on->name); if (OSPF6_LSA_IS_MAXAGE (lsa)) { - lsa->onretrans++; + ospf6_increment_retrans_count (lsa); ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); } else @@ -317,7 +317,7 @@ negotiation_done (struct thread *thread) "summary_list"), on->name); if (OSPF6_LSA_IS_MAXAGE (lsa)) { - lsa->onretrans++; + ospf6_increment_retrans_count (lsa); ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); } else @@ -334,7 +334,7 @@ negotiation_done (struct thread *thread) "summary_list"), on->name); if (OSPF6_LSA_IS_MAXAGE (lsa)) { - lsa->onretrans++; + ospf6_increment_retrans_count (lsa); ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); } else @@ -431,7 +431,7 @@ adj_ok (struct thread *thread) for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { - ospf6_decrement_onretrans (lsa); + ospf6_decrement_retrans_count (lsa); ospf6_lsdb_remove (lsa, on->retrans_list); } } @@ -464,7 +464,7 @@ seqnumber_mismatch (struct thread *thread) for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { - ospf6_decrement_onretrans (lsa); + ospf6_decrement_retrans_count (lsa); ospf6_lsdb_remove (lsa, on->retrans_list); } @@ -500,7 +500,7 @@ bad_lsreq (struct thread *thread) for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { - ospf6_decrement_onretrans (lsa); + ospf6_decrement_retrans_count (lsa); ospf6_lsdb_remove (lsa, on->retrans_list); } @@ -534,7 +534,7 @@ oneway_received (struct thread *thread) for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { - ospf6_decrement_onretrans (lsa); + ospf6_decrement_retrans_count (lsa); ospf6_lsdb_remove (lsa, on->retrans_list); } diff --git a/ospf6d/ospf6_proto.c b/ospf6d/ospf6_proto.c index 7ee7e0a7..5b47cf80 100644 --- a/ospf6d/ospf6_proto.c +++ b/ospf6d/ospf6_proto.c @@ -36,12 +36,15 @@ ospf6_prefix_apply_mask (struct ospf6_prefix *op) offset = op->prefix_length % 8; mask = 0xff << (8 - offset); - if (index >= 16) + if (index > 16) { - zlog_warn ("Apply mask to ospf6_prefix failed"); + zlog_warn ("Prefix length too long: %d", op->prefix_length); return; } + if (index == 16) + return; + pnt[index] &= mask; index ++; diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 9e64ea01..1202a3ae 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -1069,6 +1069,32 @@ ospf6_lsentry_table_show (struct vty *vty, int argc, char **argv, return CMD_SUCCESS; } +void +ospf6_brouter_show_header (struct vty *vty) +{ + vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s", + "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); +} + +void +ospf6_brouter_show (struct vty *vty, struct ospf6_route *route) +{ + u_int32_t adv_router; + char adv[16], rbits[16], options[16], area[16]; + + adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix); + inet_ntop (AF_INET, &adv_router, adv, sizeof (adv)); + ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits)); + ospf6_options_printbuf (route->path.options, options, sizeof (options)); + inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area)); + + /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s", + "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */ + vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s", + adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type), + area, VNL); +} + DEFUN (debug_ospf6_route, debug_ospf6_route_cmd, "debug ospf6 route (table|intra-area|inter-area)", diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index f58a8017..333b2cec 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -90,6 +90,7 @@ struct ospf6_path /* Path-type */ u_char type; + u_char subtype; /* only used for redistribute i.e ZEBRA_ROUTE_XXX */ /* Cost */ u_int8_t metric_type; @@ -97,12 +98,13 @@ struct ospf6_path u_int32_t cost_e2; }; -#define OSPF6_PATH_TYPE_NONE 0 -#define OSPF6_PATH_TYPE_INTRA 1 -#define OSPF6_PATH_TYPE_INTER 2 -#define OSPF6_PATH_TYPE_EXTERNAL1 3 -#define OSPF6_PATH_TYPE_EXTERNAL2 4 -#define OSPF6_PATH_TYPE_MAX 5 +#define OSPF6_PATH_TYPE_NONE 0 +#define OSPF6_PATH_TYPE_INTRA 1 +#define OSPF6_PATH_TYPE_INTER 2 +#define OSPF6_PATH_TYPE_EXTERNAL1 3 +#define OSPF6_PATH_TYPE_EXTERNAL2 4 +#define OSPF6_PATH_TYPE_REDISTRIBUTE 5 +#define OSPF6_PATH_TYPE_MAX 6 #include "prefix.h" #include "table.h" @@ -147,13 +149,15 @@ struct ospf6_route #define OSPF6_DEST_TYPE_NETWORK 2 #define OSPF6_DEST_TYPE_DISCARD 3 #define OSPF6_DEST_TYPE_LINKSTATE 4 -#define OSPF6_DEST_TYPE_MAX 5 +#define OSPF6_DEST_TYPE_RANGE 5 +#define OSPF6_DEST_TYPE_MAX 6 -#define OSPF6_ROUTE_CHANGE 0x01 -#define OSPF6_ROUTE_ADD 0x02 -#define OSPF6_ROUTE_REMOVE 0x04 -#define OSPF6_ROUTE_BEST 0x08 -#define OSPF6_ROUTE_HAVE_LONGER 0x10 +#define OSPF6_ROUTE_CHANGE 0x01 +#define OSPF6_ROUTE_ADD 0x02 +#define OSPF6_ROUTE_REMOVE 0x04 +#define OSPF6_ROUTE_BEST 0x08 +#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x08 +#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x10 struct ospf6_route_table { @@ -252,11 +256,18 @@ struct ospf6_route_table *ospf6_route_table_create (); void ospf6_route_table_delete (struct ospf6_route_table *); void ospf6_route_dump (struct ospf6_route_table *table); + +void ospf6_route_show (struct vty *vty, struct ospf6_route *route); +void ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route); + int ospf6_route_table_show (struct vty *, int, char **, struct ospf6_route_table *); int ospf6_lsentry_table_show (struct vty *, int, char **, struct ospf6_route_table *); +void ospf6_brouter_show_header (struct vty *vty); +void ospf6_brouter_show (struct vty *vty, struct ospf6_route *route); + int config_write_ospf6_debug_route (struct vty *vty); void install_element_ospf6_debug_route (); void ospf6_route_init (); diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index 285d4bbb..d3c0f816 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -342,8 +342,11 @@ ospf6_spf_install (struct ospf6_vertex *v, /* There should be no case where candidate being installed (variable "v") is closer than the one in the SPF tree (variable "route"). - In the case something's gone wrong with the behavior of + In the case something has gone wrong with the behavior of Priority-Queue. */ + + /* the case where the route exists already is handled and returned + up to here. */ assert (route == NULL); route = ospf6_route_create (); @@ -387,6 +390,8 @@ ospf6_spf_table_finish (struct ospf6_route_table *result_table) } } +/* RFC2328 16.1. Calculating the shortest-path tree for an area */ +/* RFC2740 3.8.1. Calculating the shortest path tree for an area */ void ospf6_spf_calculation (u_int32_t router_id, struct ospf6_route_table *result_table, @@ -415,7 +420,7 @@ ospf6_spf_calculation (u_int32_t router_id, root->area = oa; root->cost = 0; root->hops = 0; - root->nexthop[0].ifindex = 0; /* should have been loopbak I/F ... */ + root->nexthop[0].ifindex = 0; /* loopbak I/F is better ... */ inet_pton (AF_INET6, "::1", &root->nexthop[0].address); /* Actually insert root to the candidate-list as the only candidate */ @@ -427,7 +432,7 @@ ospf6_spf_calculation (u_int32_t router_id, /* get closest candidate from priority queue */ v = pqueue_dequeue (candidate_list); - /* install may result in merging and rejecting of the vertex */ + /* installing may result in merging or rejecting of the vertex */ if (ospf6_spf_install (v, result_table) < 0) continue; @@ -507,7 +512,7 @@ ospf6_spf_calculation_thread (struct thread *t) } ospf6_intra_route_calculation (oa); - ospf6_intra_asbr_calculation (oa); + ospf6_intra_brouter_calculation (oa); return 0; } diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 4a33d476..865a1167 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -42,8 +42,10 @@ #include "ospf6_interface.h" #include "ospf6_neighbor.h" +#include "ospf6_flood.h" #include "ospf6_asbr.h" #include "ospf6_abr.h" +#include "ospf6_intra.h" #include "ospf6d.h" /* global ospf6d variable */ @@ -84,17 +86,31 @@ ospf6_top_lsdb_hook_remove (struct ospf6_lsa *lsa) void ospf6_top_route_hook_add (struct ospf6_route *route) { - ospf6_abr_originate_prefix (route, ospf6); + ospf6_abr_originate_summary (route); ospf6_zebra_route_update_add (route); } void ospf6_top_route_hook_remove (struct ospf6_route *route) { - ospf6_abr_originate_prefix (route, ospf6); + ospf6_abr_originate_summary (route); ospf6_zebra_route_update_remove (route); } +void +ospf6_top_brouter_hook_add (struct ospf6_route *route) +{ + ospf6_abr_originate_summary (route); + ospf6_asbr_lsentry_add (route); +} + +void +ospf6_top_brouter_hook_remove (struct ospf6_route *route) +{ + ospf6_abr_originate_summary (route); + ospf6_asbr_lsentry_remove (route); +} + struct ospf6 * ospf6_create () { @@ -107,7 +123,8 @@ ospf6_create () gettimeofday (&o->starttime, (struct timezone *) NULL); o->area_list = list_new (); o->area_list->cmp = ospf6_area_cmp; - o->lsdb = ospf6_lsdb_create (); + o->lsdb = ospf6_lsdb_create (o); + o->lsdb_self = ospf6_lsdb_create (o); o->lsdb->hook_add = ospf6_top_lsdb_hook_add; o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove; @@ -115,11 +132,9 @@ ospf6_create () o->route_table->hook_add = ospf6_top_route_hook_add; o->route_table->hook_remove = ospf6_top_route_hook_remove; - o->asbr_table = ospf6_route_table_create (); - o->asbr_table->hook_add = ospf6_asbr_lsentry_add; - o->asbr_table->hook_remove = ospf6_asbr_lsentry_remove; - o->brouter_table = ospf6_route_table_create (); + o->brouter_table->hook_add = ospf6_top_brouter_hook_add; + o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove; o->external_table = ospf6_route_table_create (); o->external_id_table = route_table_init (); @@ -140,9 +155,9 @@ ospf6_delete (struct ospf6 *o) } ospf6_lsdb_delete (o->lsdb); + ospf6_lsdb_delete (o->lsdb_self); ospf6_route_table_delete (o->route_table); - ospf6_route_table_delete (o->asbr_table); ospf6_route_table_delete (o->brouter_table); ospf6_route_table_delete (o->external_table); @@ -185,7 +200,7 @@ ospf6_disable (struct ospf6 *o) ospf6_lsdb_remove_all (o->lsdb); ospf6_route_remove_all (o->route_table); - ospf6_route_remove_all (o->asbr_table); + ospf6_route_remove_all (o->brouter_table); } } @@ -320,10 +335,12 @@ DEFUN (ospf6_interface_area, ) { struct ospf6 *o; - struct ospf6_area *oa; + struct ospf6_area *oa, *area; struct ospf6_interface *oi; struct interface *ifp; u_int32_t area_id; + listnode node; + struct ospf6_route *ro; o = (struct ospf6 *) vty->index; @@ -355,8 +372,31 @@ DEFUN (ospf6_interface_area, listnode_add (oa->if_list, oi); /* sort ?? */ oi->area = oa; + SET_FLAG (oa->flag, OSPF6_AREA_ENABLE); + /* start up */ thread_add_event (master, interface_up, oi, 0); + + /* ABR stuff, redistribute inter-area LSAs and + re-originate Router-LSA (B-bit may have been changed) */ + for (node = listhead (o->area_list); node; nextnode (node)) + { + area = OSPF6_AREA (getdata (node)); + OSPF6_ROUTER_LSA_SCHEDULE (area); + + for (ro = ospf6_route_head (area->range_table); ro; + ro = ospf6_route_next (ro)) + ospf6_abr_originate_summary_to_area (ro, oa); + } + + for (ro = ospf6_route_head (o->brouter_table); ro; + ro = ospf6_route_next (ro)) + ospf6_abr_originate_summary_to_area (ro, oa); + + for (ro = ospf6_route_head (o->route_table); ro; + ro = ospf6_route_next (ro)) + ospf6_abr_originate_summary_to_area (ro, oa); + return CMD_SUCCESS; } @@ -372,8 +412,12 @@ DEFUN (no_ospf6_interface_area, { struct ospf6 *o; struct ospf6_interface *oi; + struct ospf6_area *oa, *area; struct interface *ifp; u_int32_t area_id; + listnode node; + struct ospf6_route *ro; + struct ospf6_lsa *old; o = (struct ospf6 *) vty->index; @@ -407,9 +451,45 @@ DEFUN (no_ospf6_interface_area, thread_execute (master, interface_down, oi, 0); + oa = oi->area; listnode_delete (oi->area->if_list, oi); oi->area = (struct ospf6_area *) NULL; + /* Withdraw inter-area routes from this area, if necessary */ + if (oa->if_list->count == 0) + { + UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE); + + for (ro = ospf6_route_head (oa->summary_prefix); ro; + ro = ospf6_route_next (ro)) + { + old = ospf6_lsdb_lookup (ro->path.origin.type, + ro->path.origin.id, + oa->ospf6->router_id, oa->lsdb); + if (old) + ospf6_lsa_purge (old); + ospf6_route_remove (ro, oa->summary_prefix); + } + for (ro = ospf6_route_head (oa->summary_router); ro; + ro = ospf6_route_next (ro)) + { + old = ospf6_lsdb_lookup (ro->path.origin.type, + ro->path.origin.id, + oa->ospf6->router_id, oa->lsdb); + if (old) + ospf6_lsa_purge (old); + ospf6_route_remove (ro, oa->summary_router); + } + } + + /* Schedule Refreshment of Router-LSA for each area + (ABR status may change) */ + for (node = listhead (o->area_list); node; nextnode (node)) + { + area = OSPF6_AREA (getdata (node)); + OSPF6_ROUTER_LSA_SCHEDULE (area); + } + return CMD_SUCCESS; } @@ -562,6 +642,7 @@ config_write_ospf6 (struct vty *vty) vty_out (vty, " router-id %s%s", router_id, VNL); ospf6_redistribute_config_write (vty); + ospf6_area_config_write (vty); for (j = listhead (ospf6->area_list); j; nextnode (j)) { diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index f48b7f60..d831d94f 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -38,9 +38,9 @@ struct ospf6 /* AS scope link state database */ struct ospf6_lsdb *lsdb; + struct ospf6_lsdb *lsdb_self; struct ospf6_route_table *route_table; - struct ospf6_route_table *asbr_table; struct ospf6_route_table *brouter_table; struct ospf6_route_table *external_table; diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 4eba8a42..6cc0764a 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -140,7 +140,8 @@ route_prev (struct route_node *node) return prev; } - + +/* show database functions */ DEFUN (show_version_ospf6, show_version_ospf6_cmd, "show version ospf6", @@ -186,7 +187,7 @@ config_write_ospf6_debug (struct vty *vty) static int parse_show_level (int argc, char **argv) { - int level; + int level = 0; if (argc) { if (! strncmp (argv[0], "de", 2)) @@ -204,7 +205,7 @@ parse_show_level (int argc, char **argv) static u_int16_t parse_type_spec (int argc, char **argv) { - u_int16_t type; + u_int16_t type = 0; assert (argc); if (! strcmp (argv[0], "router")) type = htons (OSPF6_LSTYPE_ROUTER); @@ -316,7 +317,7 @@ DEFUN (show_ipv6_ospf6_database_type, switch (OSPF6_LSA_SCOPE (type)) { - case OSPF6_LSA_SCOPE_AREA: + case OSPF6_SCOPE_AREA: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -325,7 +326,7 @@ DEFUN (show_ipv6_ospf6_database_type, } break; - case OSPF6_LSA_SCOPE_LINKLOCAL: + case OSPF6_SCOPE_LINKLOCAL: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -339,7 +340,7 @@ DEFUN (show_ipv6_ospf6_database_type, } break; - case OSPF6_LSA_SCOPE_AS: + case OSPF6_SCOPE_AS: vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL); ospf6_lsdb_show (vty, level, &type, NULL, NULL, o->lsdb); break; @@ -623,7 +624,7 @@ DEFUN (show_ipv6_ospf6_database_type_id, switch (OSPF6_LSA_SCOPE (type)) { - case OSPF6_LSA_SCOPE_AREA: + case OSPF6_SCOPE_AREA: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -632,7 +633,7 @@ DEFUN (show_ipv6_ospf6_database_type_id, } break; - case OSPF6_LSA_SCOPE_LINKLOCAL: + case OSPF6_SCOPE_LINKLOCAL: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -646,7 +647,7 @@ DEFUN (show_ipv6_ospf6_database_type_id, } break; - case OSPF6_LSA_SCOPE_AS: + case OSPF6_SCOPE_AS: vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL); ospf6_lsdb_show (vty, level, &type, &id, NULL, o->lsdb); break; @@ -782,7 +783,7 @@ DEFUN (show_ipv6_ospf6_database_type_router, switch (OSPF6_LSA_SCOPE (type)) { - case OSPF6_LSA_SCOPE_AREA: + case OSPF6_SCOPE_AREA: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -791,7 +792,7 @@ DEFUN (show_ipv6_ospf6_database_type_router, } break; - case OSPF6_LSA_SCOPE_LINKLOCAL: + case OSPF6_SCOPE_LINKLOCAL: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -805,7 +806,7 @@ DEFUN (show_ipv6_ospf6_database_type_router, } break; - case OSPF6_LSA_SCOPE_AS: + case OSPF6_SCOPE_AS: vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL); ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, o->lsdb); break; @@ -918,7 +919,7 @@ DEFUN (show_ipv6_ospf6_database_id_router, if ((inet_pton (AF_INET, argv[0], &id)) != 1) { vty_out (vty, "Link state ID is not parsable: %s%s", - argv[1], VNL); + argv[0], VNL); return CMD_SUCCESS; } @@ -1014,7 +1015,7 @@ DEFUN (show_ipv6_ospf6_database_adv_router_linkstate_id, if ((inet_pton (AF_INET, argv[0], &id)) != 1) { vty_out (vty, "Link state ID is not parsable: %s%s", - argv[1], VNL); + argv[0], VNL); return CMD_SUCCESS; } @@ -1125,7 +1126,7 @@ DEFUN (show_ipv6_ospf6_database_type_id_router, switch (OSPF6_LSA_SCOPE (type)) { - case OSPF6_LSA_SCOPE_AREA: + case OSPF6_SCOPE_AREA: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -1134,7 +1135,7 @@ DEFUN (show_ipv6_ospf6_database_type_id_router, } break; - case OSPF6_LSA_SCOPE_LINKLOCAL: + case OSPF6_SCOPE_LINKLOCAL: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -1148,7 +1149,7 @@ DEFUN (show_ipv6_ospf6_database_type_id_router, } break; - case OSPF6_LSA_SCOPE_AS: + case OSPF6_SCOPE_AS: vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL); ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb); break; @@ -1250,7 +1251,7 @@ DEFUN (show_ipv6_ospf6_database_type_adv_router_linkstate_id, switch (OSPF6_LSA_SCOPE (type)) { - case OSPF6_LSA_SCOPE_AREA: + case OSPF6_SCOPE_AREA: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -1259,7 +1260,7 @@ DEFUN (show_ipv6_ospf6_database_type_adv_router_linkstate_id, } break; - case OSPF6_LSA_SCOPE_LINKLOCAL: + case OSPF6_SCOPE_LINKLOCAL: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -1273,7 +1274,7 @@ DEFUN (show_ipv6_ospf6_database_type_adv_router_linkstate_id, } break; - case OSPF6_LSA_SCOPE_AS: + case OSPF6_SCOPE_AS: vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL); ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb); break; @@ -1416,7 +1417,7 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated, switch (OSPF6_LSA_SCOPE (type)) { - case OSPF6_LSA_SCOPE_AREA: + case OSPF6_SCOPE_AREA: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -1425,7 +1426,7 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated, } break; - case OSPF6_LSA_SCOPE_LINKLOCAL: + case OSPF6_SCOPE_LINKLOCAL: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -1439,7 +1440,7 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated, } break; - case OSPF6_LSA_SCOPE_AS: + case OSPF6_SCOPE_AS: vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL); ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, o->lsdb); break; @@ -1517,7 +1518,7 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated_linkstate_id, argc--; argv++; - if ((inet_pton (AF_INET, argv[1], &id)) != 1) + if ((inet_pton (AF_INET, argv[0], &id)) != 1) { vty_out (vty, "Link State ID is not parsable: %s%s", argv[0], VNL); @@ -1532,7 +1533,7 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated_linkstate_id, switch (OSPF6_LSA_SCOPE (type)) { - case OSPF6_LSA_SCOPE_AREA: + case OSPF6_SCOPE_AREA: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -1541,7 +1542,7 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated_linkstate_id, } break; - case OSPF6_LSA_SCOPE_LINKLOCAL: + case OSPF6_SCOPE_LINKLOCAL: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -1555,7 +1556,7 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated_linkstate_id, } break; - case OSPF6_LSA_SCOPE_AS: + case OSPF6_SCOPE_AS: vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL); ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb); break; @@ -1633,7 +1634,7 @@ DEFUN (show_ipv6_ospf6_database_type_id_self_originated, argc--; argv++; - if ((inet_pton (AF_INET, argv[1], &id)) != 1) + if ((inet_pton (AF_INET, argv[0], &id)) != 1) { vty_out (vty, "Link State ID is not parsable: %s%s", argv[0], VNL); @@ -1648,7 +1649,7 @@ DEFUN (show_ipv6_ospf6_database_type_id_self_originated, switch (OSPF6_LSA_SCOPE (type)) { - case OSPF6_LSA_SCOPE_AREA: + case OSPF6_SCOPE_AREA: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -1657,7 +1658,7 @@ DEFUN (show_ipv6_ospf6_database_type_id_self_originated, } break; - case OSPF6_LSA_SCOPE_LINKLOCAL: + case OSPF6_SCOPE_LINKLOCAL: for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); @@ -1671,7 +1672,7 @@ DEFUN (show_ipv6_ospf6_database_type_id_self_originated, } break; - case OSPF6_LSA_SCOPE_AS: + case OSPF6_SCOPE_AS: vty_out (vty, AS_LSDB_TITLE_FORMAT, VNL, VNL, VNL); ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb); break; @@ -1712,6 +1713,68 @@ ALIAS (show_ipv6_ospf6_database_type_id_self_originated, "Display LSA's internal information\n" ); + +DEFUN (show_ipv6_ospf6_border_routers, + show_ipv6_ospf6_border_routers_cmd, + "show ipv6 ospf6 border-routers", + SHOW_STR + IP6_STR + OSPF6_STR + "Display routing table for ABR and ASBR\n" + ) +{ + u_int32_t adv_router; + void (*showfunc) (struct vty *, struct ospf6_route *); + struct ospf6_route *ro; + struct prefix prefix; + + OSPF6_CMD_CHECK_RUNNING (); + + if (argc && ! strcmp ("detail", argv[0])) + { + showfunc = ospf6_route_show_detail; + argc--; + argv++; + } + else + showfunc = ospf6_brouter_show; + + if (argc) + { + if ((inet_pton (AF_INET, argv[0], &adv_router)) != 1) + { + vty_out (vty, "Router ID is not parsable: %s%s", argv[0], VNL); + return CMD_SUCCESS; + } + + ospf6_linkstate_prefix (adv_router, 0, &prefix); + ro = ospf6_route_lookup (&prefix, ospf6->brouter_table); + ospf6_route_show_detail (vty, ro); + return CMD_SUCCESS; + } + + if (showfunc == ospf6_brouter_show) + ospf6_brouter_show_header (vty); + + for (ro = ospf6_route_head (ospf6->brouter_table); ro; + ro = ospf6_route_next (ro)) + (*showfunc) (vty, ro); + + return CMD_SUCCESS; +} + +ALIAS (show_ipv6_ospf6_border_routers, + show_ipv6_ospf6_border_routers_detail_cmd, + "show ipv6 ospf6 border-routers (A.B.C.D|detail)", + SHOW_STR + IP6_STR + OSPF6_STR + "Display routing table for ABR and ASBR\n" + "Specify Router-ID\n" + "Display Detail\n" + ); + + /* Install ospf related commands. */ void ospf6_init () @@ -1726,10 +1789,16 @@ ospf6_init () install_element_ospf6_debug_spf (); install_element_ospf6_debug_route (); install_element_ospf6_debug_asbr (); + install_element_ospf6_debug_abr (); install_element (VIEW_NODE, &show_version_ospf6_cmd); install_element (ENABLE_NODE, &show_version_ospf6_cmd); + install_element (VIEW_NODE, &show_ipv6_ospf6_border_routers_cmd); + install_element (VIEW_NODE, &show_ipv6_ospf6_border_routers_detail_cmd); + install_element (ENABLE_NODE, &show_ipv6_ospf6_border_routers_cmd); + install_element (ENABLE_NODE, &show_ipv6_ospf6_border_routers_detail_cmd); + #define INSTALL(n,c) \ install_element (n ## _NODE, &show_ipv6_ospf6_ ## c); diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h index c738df65..3274242d 100644 --- a/ospf6d/ospf6d.h +++ b/ospf6d/ospf6d.h @@ -22,7 +22,7 @@ #ifndef OSPF6D_H #define OSPF6D_H -#define OSPF6_DAEMON_VERSION "0.9.7e" +#define OSPF6_DAEMON_VERSION "0.9.7i" /* global variables */ extern int errno; @@ -50,6 +50,12 @@ extern struct thread_master *master; #endif /* IPV6_DROP_MEMBERSHIP */ #endif /* ! IPV6_LEAVE_GROUP */ +/* cast macro */ +#define OSPF6_PROCESS(x) ((struct ospf6 *) (x)) +#define OSPF6_AREA(x) ((struct ospf6_area *) (x)) +#define OSPF6_INTERFACE(x) ((struct ospf6_interface *) (x)) +#define OSPF6_NEIGHBOR(x) ((struct ospf6_neighbor *) (x)) + /* operation on timeval structure */ #ifndef timerclear #define timerclear(a) (a)->tv_sec = (tvp)->tv_usec = 0 -- cgit v1.2.1