diff options
Diffstat (limited to 'ospfd/ospf_route.c')
| -rw-r--r-- | ospfd/ospf_route.c | 1631 | 
1 files changed, 799 insertions, 832 deletions
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index fcd5f18a7f..9c4dca2e2f 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -39,1012 +39,979 @@  #include "ospfd/ospf_zebra.h"  #include "ospfd/ospf_dump.h" -struct ospf_route * -ospf_route_new () +struct ospf_route *ospf_route_new()  { -  struct ospf_route *new; +	struct ospf_route *new; -  new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route)); +	new = XCALLOC(MTYPE_OSPF_ROUTE, sizeof(struct ospf_route)); -  new->paths = list_new (); -  new->paths->del = (void (*) (void *))ospf_path_free; +	new->paths = list_new(); +	new->paths->del = (void (*)(void *))ospf_path_free; -  return new; +	return new;  } -void -ospf_route_free (struct ospf_route *or) +void ospf_route_free(struct ospf_route * or)  { -  if (or->paths) -      list_delete (or->paths); +	if (or->paths) +		list_delete(or->paths); -  XFREE (MTYPE_OSPF_ROUTE, or); +	XFREE(MTYPE_OSPF_ROUTE, or);  } -struct ospf_path * -ospf_path_new () +struct ospf_path *ospf_path_new()  { -  struct ospf_path *new; +	struct ospf_path *new; -  new = XCALLOC (MTYPE_OSPF_PATH, sizeof (struct ospf_path)); +	new = XCALLOC(MTYPE_OSPF_PATH, sizeof(struct ospf_path)); -  return new; +	return new;  } -static struct ospf_path * -ospf_path_dup (struct ospf_path *path) +static struct ospf_path *ospf_path_dup(struct ospf_path *path)  { -  struct ospf_path *new; +	struct ospf_path *new; -  new = ospf_path_new (); -  memcpy (new, path, sizeof (struct ospf_path)); +	new = ospf_path_new(); +	memcpy(new, path, sizeof(struct ospf_path)); -  return new; +	return new;  } -void -ospf_path_free (struct ospf_path *op) +void ospf_path_free(struct ospf_path *op)  { -  XFREE (MTYPE_OSPF_PATH, op); +	XFREE(MTYPE_OSPF_PATH, op);  } -void -ospf_route_delete (struct route_table *rt) +void ospf_route_delete(struct route_table *rt)  { -  struct route_node *rn; -  struct ospf_route *or; - -  for (rn = route_top (rt); rn; rn = route_next (rn)) -    if ((or = rn->info) != NULL) -      { -	if (or->type == OSPF_DESTINATION_NETWORK) -	  ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, -				       or); -	else if (or->type == OSPF_DESTINATION_DISCARD) -	  ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p); -      } +	struct route_node *rn; +	struct ospf_route * or ; + +	for (rn = route_top(rt); rn; rn = route_next(rn)) +		if ((or = rn->info) != NULL) { +			if (or->type == OSPF_DESTINATION_NETWORK) +				ospf_zebra_delete((struct prefix_ipv4 *)&rn->p, +						  or); +			else if (or->type == OSPF_DESTINATION_DISCARD) +				ospf_zebra_delete_discard( +					(struct prefix_ipv4 *)&rn->p); +		}  } -void -ospf_route_table_free (struct route_table *rt) +void ospf_route_table_free(struct route_table *rt)  { -  struct route_node *rn; -  struct ospf_route *or; +	struct route_node *rn; +	struct ospf_route * or ; -  for (rn = route_top (rt); rn; rn = route_next (rn)) -    if ((or = rn->info) != NULL) -      { -	ospf_route_free (or); +	for (rn = route_top(rt); rn; rn = route_next(rn)) +		if ((or = rn->info) != NULL) { +			ospf_route_free(or); -	rn->info = NULL; -	route_unlock_node (rn); -      } +			rn->info = NULL; +			route_unlock_node(rn); +		} -   route_table_finish (rt); +	route_table_finish(rt);  }  /* If a prefix exists in the new routing table, then return 1,     otherwise return 0. Since the ZEBRA-RIB does an implicit     withdraw, it is not necessary to send a delete, an add later     will act like an implicit delete. */ -static int -ospf_route_exist_new_table (struct route_table *rt, struct prefix_ipv4 *prefix) +static int ospf_route_exist_new_table(struct route_table *rt, +				      struct prefix_ipv4 *prefix)  { -  struct route_node *rn; +	struct route_node *rn; -  assert (rt); -  assert (prefix); +	assert(rt); +	assert(prefix); -  rn = route_node_lookup (rt, (struct prefix *) prefix); -  if (!rn) { -    return 0; -  } -  route_unlock_node (rn); +	rn = route_node_lookup(rt, (struct prefix *)prefix); +	if (!rn) { +		return 0; +	} +	route_unlock_node(rn); -  if (!rn->info) { -    return 0; -  } +	if (!rn->info) { +		return 0; +	} -  return 1; +	return 1;  }  /* If a prefix and a nexthop match any route in the routing table,     then return 1, otherwise return 0. */ -int -ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix, -		       struct ospf_route *newor) +int ospf_route_match_same(struct route_table *rt, struct prefix_ipv4 *prefix, +			  struct ospf_route *newor)  { -  struct route_node *rn; -  struct ospf_route *or; -  struct ospf_path *op; -  struct ospf_path *newop; -  struct listnode *n1; -  struct listnode *n2; - -  if (! rt || ! prefix) -    return 0; - -   rn = route_node_lookup (rt, (struct prefix *) prefix); -   if (! rn || ! rn->info) -     return 0; -  -   route_unlock_node (rn); - -   or = rn->info; -   if (or->type == newor->type && or->cost == newor->cost) -     { -       if (or->type == OSPF_DESTINATION_NETWORK) -	 { -	   if (or->paths->count != newor->paths->count) -	     return 0; - -	   /* Check each path. */ -	   for (n1 = listhead (or->paths), n2 = listhead (newor->paths); -		n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2)) -	     {  -	       op = listgetdata (n1); -	       newop = listgetdata (n2); - -	       if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop)) -		 return 0; -	       if (op->ifindex != newop->ifindex) -		 return 0; -	     } -	   return 1; -	 } -       else if (prefix_same (&rn->p, (struct prefix *) prefix)) -	 return 1; -     } -  return 0; +	struct route_node *rn; +	struct ospf_route * or ; +	struct ospf_path *op; +	struct ospf_path *newop; +	struct listnode *n1; +	struct listnode *n2; + +	if (!rt || !prefix) +		return 0; + +	rn = route_node_lookup(rt, (struct prefix *)prefix); +	if (!rn || !rn->info) +		return 0; + +	route_unlock_node(rn); + +	or = rn->info; +	if (or->type == newor->type && or->cost == newor->cost) { +		if (or->type == OSPF_DESTINATION_NETWORK) { +			if (or->paths->count != newor->paths->count) +				return 0; + +			/* Check each path. */ +			for (n1 = listhead(or->paths), +			    n2 = listhead(newor->paths); +			     n1 && n2; +			     n1 = listnextnode(n1), n2 = listnextnode(n2)) { +				op = listgetdata(n1); +				newop = listgetdata(n2); + +				if (!IPV4_ADDR_SAME(&op->nexthop, +						    &newop->nexthop)) +					return 0; +				if (op->ifindex != newop->ifindex) +					return 0; +			} +			return 1; +		} else if (prefix_same(&rn->p, (struct prefix *)prefix)) +			return 1; +	} +	return 0;  }  /* delete routes generated from AS-External routes if there is a inter/intra   * area route   */ -static void  -ospf_route_delete_same_ext(struct route_table *external_routes, -                     struct route_table *routes) +static void ospf_route_delete_same_ext(struct route_table *external_routes, +				       struct route_table *routes)  { -  struct route_node *rn, -                    *ext_rn; -   -  if ( (external_routes == NULL) || (routes == NULL) ) -    return; -   -  /* Remove deleted routes */ -  for ( rn = route_top (routes); rn; rn = route_next (rn) ) -    { -      if (rn && rn->info) -        { -          struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p); -          if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) ) -            { -              if (ext_rn->info) -                { -                  ospf_zebra_delete (p, ext_rn->info); -                  ospf_route_free( ext_rn->info); -                  ext_rn->info = NULL; -                } -              route_unlock_node (ext_rn); -            } -        } -    } +	struct route_node *rn, *ext_rn; + +	if ((external_routes == NULL) || (routes == NULL)) +		return; + +	/* Remove deleted routes */ +	for (rn = route_top(routes); rn; rn = route_next(rn)) { +		if (rn && rn->info) { +			struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p); +			if ((ext_rn = route_node_lookup(external_routes, +							(struct prefix *)p))) { +				if (ext_rn->info) { +					ospf_zebra_delete(p, ext_rn->info); +					ospf_route_free(ext_rn->info); +					ext_rn->info = NULL; +				} +				route_unlock_node(ext_rn); +			} +		} +	}  }  /* rt: Old, cmprt: New */ -static void -ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt) +static void ospf_route_delete_uniq(struct route_table *rt, +				   struct route_table *cmprt)  { -  struct route_node *rn; -  struct ospf_route *or; - -  for (rn = route_top (rt); rn; rn = route_next (rn)) -    if ((or = rn->info) != NULL)  -      if (or->path_type == OSPF_PATH_INTRA_AREA || -	  or->path_type == OSPF_PATH_INTER_AREA) -	{ -	  if (or->type == OSPF_DESTINATION_NETWORK) -	    { -	      if (! ospf_route_exist_new_table (cmprt, -					   (struct prefix_ipv4 *) &rn->p)) -		ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or); -	    } -	  else if (or->type == OSPF_DESTINATION_DISCARD) -	    if (! ospf_route_exist_new_table (cmprt, -					 (struct prefix_ipv4 *) &rn->p)) -	      ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p); -	} +	struct route_node *rn; +	struct ospf_route * or ; + +	for (rn = route_top(rt); rn; rn = route_next(rn)) +		if ((or = rn->info) != NULL) +			if (or->path_type == OSPF_PATH_INTRA_AREA || +			    or->path_type == OSPF_PATH_INTER_AREA) { +				if (or->type == OSPF_DESTINATION_NETWORK) { +					if (!ospf_route_exist_new_table( +						    cmprt, +						    (struct prefix_ipv4 *)&rn +							    ->p)) +						ospf_zebra_delete( +							(struct prefix_ipv4 +								 *)&rn->p, +							or); +				} else if (or->type == OSPF_DESTINATION_DISCARD) +					if (!ospf_route_exist_new_table( +						    cmprt, +						    (struct prefix_ipv4 *)&rn +							    ->p)) +						ospf_zebra_delete_discard( +							(struct prefix_ipv4 +								 *)&rn->p); +			}  }  /* Install routes to table. */ -void -ospf_route_install (struct ospf *ospf, struct route_table *rt) +void ospf_route_install(struct ospf *ospf, struct route_table *rt)  { -  struct route_node *rn; -  struct ospf_route *or; - -  /* rt contains new routing table, new_table contains an old one. -     updating pointers */ -  if (ospf->old_table) -    ospf_route_table_free (ospf->old_table); - -  ospf->old_table = ospf->new_table; -  ospf->new_table = rt; - -  /* Delete old routes. */ -  if (ospf->old_table) -    ospf_route_delete_uniq (ospf->old_table, rt); -  if (ospf->old_external_route) -    ospf_route_delete_same_ext (ospf->old_external_route, rt); - -  /* Install new routes. */ -  for (rn = route_top (rt); rn; rn = route_next (rn)) -    if ((or = rn->info) != NULL) -      { -	if (or->type == OSPF_DESTINATION_NETWORK) -	  { -	    if (! ospf_route_match_same (ospf->old_table, -					 (struct prefix_ipv4 *)&rn->p, or)) -	      ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or); -	  } -	else if (or->type == OSPF_DESTINATION_DISCARD) -	  if (! ospf_route_match_same (ospf->old_table, -				       (struct prefix_ipv4 *) &rn->p, or)) -	    ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p); -      } +	struct route_node *rn; +	struct ospf_route * or ; + +	/* rt contains new routing table, new_table contains an old one. +	   updating pointers */ +	if (ospf->old_table) +		ospf_route_table_free(ospf->old_table); + +	ospf->old_table = ospf->new_table; +	ospf->new_table = rt; + +	/* Delete old routes. */ +	if (ospf->old_table) +		ospf_route_delete_uniq(ospf->old_table, rt); +	if (ospf->old_external_route) +		ospf_route_delete_same_ext(ospf->old_external_route, rt); + +	/* Install new routes. */ +	for (rn = route_top(rt); rn; rn = route_next(rn)) +		if ((or = rn->info) != NULL) { +			if (or->type == OSPF_DESTINATION_NETWORK) { +				if (!ospf_route_match_same( +					    ospf->old_table, +					    (struct prefix_ipv4 *)&rn->p, or)) +					ospf_zebra_add( +						(struct prefix_ipv4 *)&rn->p, +						or); +			} else if (or->type == OSPF_DESTINATION_DISCARD) +				if (!ospf_route_match_same( +					    ospf->old_table, +					    (struct prefix_ipv4 *)&rn->p, or)) +					ospf_zebra_add_discard( +						(struct prefix_ipv4 *)&rn->p); +		}  }  /* RFC2328 16.1. (4). For "router". */ -void -ospf_intra_add_router (struct route_table *rt, struct vertex *v, -		       struct ospf_area *area) +void ospf_intra_add_router(struct route_table *rt, struct vertex *v, +			   struct ospf_area *area)  { -  struct route_node *rn; -  struct ospf_route *or; -  struct prefix_ipv4 p; -  struct router_lsa *lsa; - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("ospf_intra_add_router: Start"); - -  lsa = (struct router_lsa *) v->lsa; - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("ospf_intra_add_router: LS ID: %s", -	       inet_ntoa (lsa->header.id)); -   -  if (!OSPF_IS_AREA_BACKBONE(area)) -    ospf_vl_up_check (area, lsa->header.id, v); - -  if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT)) -    area->shortcut_capability = 0; - -  /* If the newly added vertex is an area border router or AS boundary -     router, a routing table entry is added whose destination type is -     "router". */ -  if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa)) -    { -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug ("ospf_intra_add_router: " -		   "this router is neither ASBR nor ABR, skipping it"); -      return; -    } - -  /* Update ABR and ASBR count in this area. */ -  if (IS_ROUTER_LSA_BORDER (lsa)) -    area->abr_count++; -  if (IS_ROUTER_LSA_EXTERNAL (lsa)) -    area->asbr_count++; - -  /* The Options field found in the associated router-LSA is copied -     into the routing table entry's Optional capabilities field. Call -     the newly added vertex Router X. */ -  or = ospf_route_new (); - -  or->id = v->id; -  or->u.std.area_id = area->area_id; -  or->u.std.external_routing = area->external_routing; -  or->path_type = OSPF_PATH_INTRA_AREA; -  or->cost = v->distance; -  or->type = OSPF_DESTINATION_ROUTER; -  or->u.std.origin = (struct lsa_header *) lsa; -  or->u.std.options = lsa->header.options; -  or->u.std.flags = lsa->flags; - -  /* If Router X is the endpoint of one of the calculating router's -     virtual links, and the virtual link uses Area A as Transit area: -     the virtual link is declared up, the IP address of the virtual -     interface is set to the IP address of the outgoing interface -     calculated above for Router X, and the virtual neighbor's IP -     address is set to Router X's interface address (contained in -     Router X's router-LSA) that points back to the root of the -     shortest- path tree; equivalently, this is the interface that -     points back to Router X's parent vertex on the shortest-path tree -     (similar to the calculation in Section 16.1.1). */ - -  p.family = AF_INET; -  p.prefix = v->id; -  p.prefixlen = IPV4_MAX_BITLEN; - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("ospf_intra_add_router: talking about %s/%d", -	       inet_ntoa (p.prefix), p.prefixlen); - -  rn = route_node_get (rt, (struct prefix *) &p); - -  /* Note that we keep all routes to ABRs and ASBRs, not only the best */ -  if (rn->info == NULL) -    rn->info = list_new (); -  else -    route_unlock_node (rn); - -  ospf_route_copy_nexthops_from_vertex (or, v); - -  listnode_add (rn->info, or); - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("ospf_intra_add_router: Stop"); +	struct route_node *rn; +	struct ospf_route * or ; +	struct prefix_ipv4 p; +	struct router_lsa *lsa; + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("ospf_intra_add_router: Start"); + +	lsa = (struct router_lsa *)v->lsa; + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("ospf_intra_add_router: LS ID: %s", +			   inet_ntoa(lsa->header.id)); + +	if (!OSPF_IS_AREA_BACKBONE(area)) +		ospf_vl_up_check(area, lsa->header.id, v); + +	if (!CHECK_FLAG(lsa->flags, ROUTER_LSA_SHORTCUT)) +		area->shortcut_capability = 0; + +	/* If the newly added vertex is an area border router or AS boundary +	   router, a routing table entry is added whose destination type is +	   "router". */ +	if (!IS_ROUTER_LSA_BORDER(lsa) && !IS_ROUTER_LSA_EXTERNAL(lsa)) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug( +				"ospf_intra_add_router: " +				"this router is neither ASBR nor ABR, skipping it"); +		return; +	} + +	/* Update ABR and ASBR count in this area. */ +	if (IS_ROUTER_LSA_BORDER(lsa)) +		area->abr_count++; +	if (IS_ROUTER_LSA_EXTERNAL(lsa)) +		area->asbr_count++; + +	/* The Options field found in the associated router-LSA is copied +	   into the routing table entry's Optional capabilities field. Call +	   the newly added vertex Router X. */ +	or = ospf_route_new(); + +	or->id = v->id; +	or->u.std.area_id = area->area_id; +	or->u.std.external_routing = area->external_routing; +	or->path_type = OSPF_PATH_INTRA_AREA; +	or->cost = v->distance; +	or->type = OSPF_DESTINATION_ROUTER; +	or->u.std.origin = (struct lsa_header *)lsa; +	or->u.std.options = lsa->header.options; +	or->u.std.flags = lsa->flags; + +	/* If Router X is the endpoint of one of the calculating router's +	   virtual links, and the virtual link uses Area A as Transit area: +	   the virtual link is declared up, the IP address of the virtual +	   interface is set to the IP address of the outgoing interface +	   calculated above for Router X, and the virtual neighbor's IP +	   address is set to Router X's interface address (contained in +	   Router X's router-LSA) that points back to the root of the +	   shortest- path tree; equivalently, this is the interface that +	   points back to Router X's parent vertex on the shortest-path tree +	   (similar to the calculation in Section 16.1.1). */ + +	p.family = AF_INET; +	p.prefix = v->id; +	p.prefixlen = IPV4_MAX_BITLEN; + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("ospf_intra_add_router: talking about %s/%d", +			   inet_ntoa(p.prefix), p.prefixlen); + +	rn = route_node_get(rt, (struct prefix *)&p); + +	/* Note that we keep all routes to ABRs and ASBRs, not only the best */ +	if (rn->info == NULL) +		rn->info = list_new(); +	else +		route_unlock_node(rn); + +	ospf_route_copy_nexthops_from_vertex(or, v); + +	listnode_add(rn->info, or); + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("ospf_intra_add_router: Stop");  }  /* RFC2328 16.1. (4).  For transit network. */ -void -ospf_intra_add_transit (struct route_table *rt, struct vertex *v, -			struct ospf_area *area) +void ospf_intra_add_transit(struct route_table *rt, struct vertex *v, +			    struct ospf_area *area)  { -  struct route_node *rn; -  struct ospf_route *or; -  struct prefix_ipv4 p; -  struct network_lsa *lsa; - -  lsa = (struct network_lsa*) v->lsa; - -  /* If the newly added vertex is a transit network, the routing table -     entry for the network is located.  The entry's Destination ID is -     the IP network number, which can be obtained by masking the -     Vertex ID (Link State ID) with its associated subnet mask (found -     in the body of the associated network-LSA). */ -  p.family = AF_INET; -  p.prefix = v->id; -  p.prefixlen = ip_masklen (lsa->mask); -  apply_mask_ipv4 (&p); - -  rn = route_node_get (rt, (struct prefix *) &p); - -  /* If the routing table entry already exists (i.e., there is already -     an intra-area route to the destination installed in the routing -     table), multiple vertices have mapped to the same IP network. -     For example, this can occur when a new Designated Router is being -     established.  In this case, the current routing table entry -     should be overwritten if and only if the newly found path is just -     as short and the current routing table entry's Link State Origin -     has a smaller Link State ID than the newly added vertex' LSA. */ -  if (rn->info) -    { -      struct ospf_route *cur_or; - -      route_unlock_node (rn); -      cur_or = rn->info; - -      if (v->distance > cur_or->cost || -          IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0) -	return; -       -      ospf_route_free (rn->info); -    } - -  or = ospf_route_new (); - -  or->id = v->id; -  or->u.std.area_id = area->area_id; -  or->u.std.external_routing = area->external_routing; -  or->path_type = OSPF_PATH_INTRA_AREA; -  or->cost = v->distance; -  or->type = OSPF_DESTINATION_NETWORK; -  or->u.std.origin = (struct lsa_header *) lsa; - -  ospf_route_copy_nexthops_from_vertex (or, v); -   -  rn->info = or; +	struct route_node *rn; +	struct ospf_route * or ; +	struct prefix_ipv4 p; +	struct network_lsa *lsa; + +	lsa = (struct network_lsa *)v->lsa; + +	/* If the newly added vertex is a transit network, the routing table +	   entry for the network is located.  The entry's Destination ID is +	   the IP network number, which can be obtained by masking the +	   Vertex ID (Link State ID) with its associated subnet mask (found +	   in the body of the associated network-LSA). */ +	p.family = AF_INET; +	p.prefix = v->id; +	p.prefixlen = ip_masklen(lsa->mask); +	apply_mask_ipv4(&p); + +	rn = route_node_get(rt, (struct prefix *)&p); + +	/* If the routing table entry already exists (i.e., there is already +	   an intra-area route to the destination installed in the routing +	   table), multiple vertices have mapped to the same IP network. +	   For example, this can occur when a new Designated Router is being +	   established.  In this case, the current routing table entry +	   should be overwritten if and only if the newly found path is just +	   as short and the current routing table entry's Link State Origin +	   has a smaller Link State ID than the newly added vertex' LSA. */ +	if (rn->info) { +		struct ospf_route *cur_or; + +		route_unlock_node(rn); +		cur_or = rn->info; + +		if (v->distance > cur_or->cost +		    || IPV4_ADDR_CMP(&cur_or->u.std.origin->id, &lsa->header.id) +			       > 0) +			return; + +		ospf_route_free(rn->info); +	} + +	or = ospf_route_new(); + +	or->id = v->id; +	or->u.std.area_id = area->area_id; +	or->u.std.external_routing = area->external_routing; +	or->path_type = OSPF_PATH_INTRA_AREA; +	or->cost = v->distance; +	or->type = OSPF_DESTINATION_NETWORK; +	or->u.std.origin = (struct lsa_header *)lsa; + +	ospf_route_copy_nexthops_from_vertex(or, v); + +	rn->info = or ;  }  /* RFC2328 16.1. second stage. */ -void -ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link, -		     struct vertex *v, struct ospf_area *area, -		     int parent_is_root, int lsa_pos) +void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link, +			 struct vertex *v, struct ospf_area *area, +			 int parent_is_root, int lsa_pos)  { -  u_int32_t cost; -  struct route_node *rn; -  struct ospf_route *or; -  struct prefix_ipv4 p; -  struct router_lsa *lsa; -  struct ospf_interface *oi; -  struct ospf_path *path; - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("ospf_intra_add_stub(): Start"); - -  lsa = (struct router_lsa *) v->lsa; - -  p.family = AF_INET; -  p.prefix = link->link_id; -  p.prefixlen = ip_masklen (link->link_data); -  apply_mask_ipv4 (&p); - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d",   -	       inet_ntoa (p.prefix), p.prefixlen); - -  /* (1) Calculate the distance D of stub network from the root.  D is -     equal to the distance from the root to the router vertex -     (calculated in stage 1), plus the stub network link's advertised -     cost. */ -  cost = v->distance + ntohs (link->m[0].metric); - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d",  -	       v->distance, ntohs(link->m[0].metric), cost); -   -  /* PtP links with /32 masks adds host routes to remote, directly -   * connected hosts, see RFC 2328, 12.4.1.1, Option 1. -   * Such routes can just be ignored for the sake of tidyness. -   */ -  if (parent_is_root && link->link_data.s_addr == 0xffffffff && -      ospf_if_lookup_by_local_addr (area->ospf, NULL, link->link_id)) -    { -      if (IS_DEBUG_OSPF_EVENT) -        zlog_debug ("%s: ignoring host route %s/32 to self.", -                    __func__, inet_ntoa (link->link_id)); -      return; -    } -   -  rn = route_node_get (rt, (struct prefix *) &p); - -  /* Lookup current routing table. */ -  if (rn->info) -    { -      struct ospf_route *cur_or; - -      route_unlock_node (rn); - -      cur_or = rn->info; - -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug ("ospf_intra_add_stub(): " -		   "another route to the same prefix found with cost %u", -		   cur_or->cost); - -      /* Compare this distance to the current best cost to the stub -	 network.  This is done by looking up the stub network's -	 current routing table entry.  If the calculated distance D is -	 larger, go on to examine the next stub network link in the -	 LSA. */ -      if (cost > cur_or->cost) -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("ospf_intra_add_stub(): old route is better, exit"); -	  return; +	u_int32_t cost; +	struct route_node *rn; +	struct ospf_route * or ; +	struct prefix_ipv4 p; +	struct router_lsa *lsa; +	struct ospf_interface *oi; +	struct ospf_path *path; + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("ospf_intra_add_stub(): Start"); + +	lsa = (struct router_lsa *)v->lsa; + +	p.family = AF_INET; +	p.prefix = link->link_id; +	p.prefixlen = ip_masklen(link->link_data); +	apply_mask_ipv4(&p); + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("ospf_intra_add_stub(): processing route to %s/%d", +			   inet_ntoa(p.prefix), p.prefixlen); + +	/* (1) Calculate the distance D of stub network from the root.  D is +	   equal to the distance from the root to the router vertex +	   (calculated in stage 1), plus the stub network link's advertised +	   cost. */ +	cost = v->distance + ntohs(link->m[0].metric); + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug( +			"ospf_intra_add_stub(): calculated cost is %d + %d = %d", +			v->distance, ntohs(link->m[0].metric), cost); + +	/* PtP links with /32 masks adds host routes to remote, directly +	 * connected hosts, see RFC 2328, 12.4.1.1, Option 1. +	 * Such routes can just be ignored for the sake of tidyness. +	 */ +	if (parent_is_root && link->link_data.s_addr == 0xffffffff +	    && ospf_if_lookup_by_local_addr(area->ospf, NULL, link->link_id)) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug("%s: ignoring host route %s/32 to self.", +				   __func__, inet_ntoa(link->link_id)); +		return;  	} -      /* (2) If this step is reached, the stub network's routing table -	 entry must be updated.  Calculate the set of next hops that -	 would result from using the stub network link.  This -	 calculation is shown in Section 16.1.1; input to this -	 calculation is the destination (the stub network) and the -	 parent vertex (the router vertex). If the distance D is the -	 same as the current routing table cost, simply add this set -	 of next hops to the routing table entry's list of next hops. -	 In this case, the routing table already has a Link State -	 Origin.  If this Link State Origin is a router-LSA whose Link -	 State ID is smaller than V's Router ID, reset the Link State -	 Origin to V's router-LSA. */ - -      if (cost == cur_or->cost) -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("ospf_intra_add_stub(): routes are equal, merge"); +	rn = route_node_get(rt, (struct prefix *)&p); -	  ospf_route_copy_nexthops_from_vertex (cur_or, v); +	/* Lookup current routing table. */ +	if (rn->info) { +		struct ospf_route *cur_or; -	  if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0) -	    cur_or->u.std.origin = (struct lsa_header *) lsa; -	  return; -	} +		route_unlock_node(rn); -      /* Otherwise D is smaller than the routing table cost. -	 Overwrite the current routing table entry by setting the -	 routing table entry's cost to D, and by setting the entry's -	 list of next hops to the newly calculated set.  Set the -	 routing table entry's Link State Origin to V's router-LSA. -	 Then go on to examine the next stub network link. */ +		cur_or = rn->info; -      if (cost < cur_or->cost) -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("ospf_intra_add_stub(): new route is better, set it"); +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug( +				"ospf_intra_add_stub(): " +				"another route to the same prefix found with cost %u", +				cur_or->cost); + +		/* Compare this distance to the current best cost to the stub +		   network.  This is done by looking up the stub network's +		   current routing table entry.  If the calculated distance D is +		   larger, go on to examine the next stub network link in the +		   LSA. */ +		if (cost > cur_or->cost) { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"ospf_intra_add_stub(): old route is better, exit"); +			return; +		} -	  cur_or->cost = cost; +		/* (2) If this step is reached, the stub network's routing table +		   entry must be updated.  Calculate the set of next hops that +		   would result from using the stub network link.  This +		   calculation is shown in Section 16.1.1; input to this +		   calculation is the destination (the stub network) and the +		   parent vertex (the router vertex). If the distance D is the +		   same as the current routing table cost, simply add this set +		   of next hops to the routing table entry's list of next hops. +		   In this case, the routing table already has a Link State +		   Origin.  If this Link State Origin is a router-LSA whose Link +		   State ID is smaller than V's Router ID, reset the Link State +		   Origin to V's router-LSA. */ + +		if (cost == cur_or->cost) { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"ospf_intra_add_stub(): routes are equal, merge"); + +			ospf_route_copy_nexthops_from_vertex(cur_or, v); + +			if (IPV4_ADDR_CMP(&cur_or->u.std.origin->id, +					  &lsa->header.id) +			    < 0) +				cur_or->u.std.origin = (struct lsa_header *)lsa; +			return; +		} -	  list_delete_all_node (cur_or->paths); +		/* Otherwise D is smaller than the routing table cost. +		   Overwrite the current routing table entry by setting the +		   routing table entry's cost to D, and by setting the entry's +		   list of next hops to the newly calculated set.  Set the +		   routing table entry's Link State Origin to V's router-LSA. +		   Then go on to examine the next stub network link. */ -	  ospf_route_copy_nexthops_from_vertex (cur_or, v); +		if (cost < cur_or->cost) { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"ospf_intra_add_stub(): new route is better, set it"); -	  cur_or->u.std.origin = (struct lsa_header *) lsa; -	  return; -	} -    } - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("ospf_intra_add_stub(): installing new route"); - -  or = ospf_route_new (); - -  or->id = v->id; -  or->u.std.area_id = area->area_id; -  or->u.std.external_routing = area->external_routing; -  or->path_type = OSPF_PATH_INTRA_AREA; -  or->cost = cost; -  or->type = OSPF_DESTINATION_NETWORK; -  or->u.std.origin = (struct lsa_header *) lsa; - -  /* Nexthop is depend on connection type. */ -  if (v != area->spf) -    { -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug ("ospf_intra_add_stub(): this network is on remote router"); -      ospf_route_copy_nexthops_from_vertex (or, v); -    } -  else -    { -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug ("ospf_intra_add_stub(): this network is on this router"); - -      if ((oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos))) -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("ospf_intra_add_stub(): the interface is %s", -		       IF_NAME (oi)); - -	  path = ospf_path_new (); -	  path->nexthop.s_addr = 0; -	  path->ifindex = oi->ifp->ifindex; -          if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) -            path->unnumbered = 1; -	  listnode_add (or->paths, path); +			cur_or->cost = cost; + +			list_delete_all_node(cur_or->paths); + +			ospf_route_copy_nexthops_from_vertex(cur_or, v); + +			cur_or->u.std.origin = (struct lsa_header *)lsa; +			return; +		}  	} -      else -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("ospf_intra_add_stub(): where's the interface ?"); + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("ospf_intra_add_stub(): installing new route"); + +	or = ospf_route_new(); + +	or->id = v->id; +	or->u.std.area_id = area->area_id; +	or->u.std.external_routing = area->external_routing; +	or->path_type = OSPF_PATH_INTRA_AREA; +	or->cost = cost; +	or->type = OSPF_DESTINATION_NETWORK; +	or->u.std.origin = (struct lsa_header *)lsa; + +	/* Nexthop is depend on connection type. */ +	if (v != area->spf) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug( +				"ospf_intra_add_stub(): this network is on remote router"); +		ospf_route_copy_nexthops_from_vertex(or, v); +	} else { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug( +				"ospf_intra_add_stub(): this network is on this router"); + +		if ((oi = ospf_if_lookup_by_lsa_pos(area, lsa_pos))) { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"ospf_intra_add_stub(): the interface is %s", +					IF_NAME(oi)); + +			path = ospf_path_new(); +			path->nexthop.s_addr = 0; +			path->ifindex = oi->ifp->ifindex; +			if (CHECK_FLAG(oi->connected->flags, +				       ZEBRA_IFA_UNNUMBERED)) +				path->unnumbered = 1; +			listnode_add(or->paths, path); +		} else { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"ospf_intra_add_stub(): where's the interface ?"); +		}  	} -    } -  rn->info = or; +	rn->info = or ; -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug("ospf_intra_add_stub(): Stop"); +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("ospf_intra_add_stub(): Stop");  } -const char *ospf_path_type_str[] = -{ -  "unknown-type", -  "intra-area", -  "inter-area", -  "type1-external", -  "type2-external" -}; - -void -ospf_route_table_dump (struct route_table *rt) +const char *ospf_path_type_str[] = {"unknown-type", "intra-area", "inter-area", +				    "type1-external", "type2-external"}; + +void ospf_route_table_dump(struct route_table *rt)  { -  struct route_node *rn; -  struct ospf_route *or; -  char buf1[BUFSIZ]; -  char buf2[BUFSIZ]; -  struct listnode *pnode; -  struct ospf_path *path; +	struct route_node *rn; +	struct ospf_route * or ; +	char buf1[BUFSIZ]; +	char buf2[BUFSIZ]; +	struct listnode *pnode; +	struct ospf_path *path;  #if 0    zlog_debug ("Type   Dest   Area   Path	 Type	 Cost	Next	 Adv.");    zlog_debug ("					Hop(s)	 Router(s)");  #endif /* 0 */ -  zlog_debug ("========== OSPF routing table =========="); -  for (rn = route_top (rt); rn; rn = route_next (rn)) -    if ((or = rn->info) != NULL) -      { -        if (or->type == OSPF_DESTINATION_NETWORK) -	  { -	    zlog_debug ("N %s/%d\t%s\t%s\t%d",  -		       inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ), -		       rn->p.prefixlen, -		       inet_ntop (AF_INET, &or->u.std.area_id, buf2, -				  BUFSIZ), -		       ospf_path_type_str[or->path_type], -		       or->cost); -	    for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path)) -              zlog_debug ("  -> %s", inet_ntoa (path->nexthop)); -	  } -        else -	  zlog_debug ("R %s\t%s\t%s\t%d",  -		     inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ), -		     inet_ntop (AF_INET, &or->u.std.area_id, buf2, -				BUFSIZ), -		     ospf_path_type_str[or->path_type], -		     or->cost); -      } -  zlog_debug ("========================================"); +	zlog_debug("========== OSPF routing table =========="); +	for (rn = route_top(rt); rn; rn = route_next(rn)) +		if ((or = rn->info) != NULL) { +			if (or->type == OSPF_DESTINATION_NETWORK) { +				zlog_debug("N %s/%d\t%s\t%s\t%d", +					   inet_ntop(AF_INET, &rn->p.u.prefix4, +						     buf1, BUFSIZ), +					   rn->p.prefixlen, +					   inet_ntop(AF_INET, +						     & or->u.std.area_id, buf2, +						     BUFSIZ), +					   ospf_path_type_str[or->path_type], +					   or->cost); +				for (ALL_LIST_ELEMENTS_RO(or->paths, pnode, +							  path)) +					zlog_debug("  -> %s", +						   inet_ntoa(path->nexthop)); +			} else +				zlog_debug("R %s\t%s\t%s\t%d", +					   inet_ntop(AF_INET, &rn->p.u.prefix4, +						     buf1, BUFSIZ), +					   inet_ntop(AF_INET, +						     & or->u.std.area_id, buf2, +						     BUFSIZ), +					   ospf_path_type_str[or->path_type], +					   or->cost); +		} +	zlog_debug("========================================");  }  /* This is 16.4.1 implementation.     o Intra-area paths using non-backbone areas are always the most preferred.     o The other paths, intra-area backbone paths and inter-area paths,       are of equal preference. */ -static int -ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1, -		     struct ospf_route *r2) +static int ospf_asbr_route_cmp(struct ospf *ospf, struct ospf_route *r1, +			       struct ospf_route *r2)  { -  u_char r1_type, r2_type; +	u_char r1_type, r2_type; -  r1_type = r1->path_type; -  r2_type = r2->path_type; +	r1_type = r1->path_type; +	r2_type = r2->path_type; -  /* r1/r2 itself is backbone, and it's Inter-area path. */ -  if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id)) -    r1_type = OSPF_PATH_INTER_AREA; -  if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id)) -    r2_type = OSPF_PATH_INTER_AREA; +	/* r1/r2 itself is backbone, and it's Inter-area path. */ +	if (OSPF_IS_AREA_ID_BACKBONE(r1->u.std.area_id)) +		r1_type = OSPF_PATH_INTER_AREA; +	if (OSPF_IS_AREA_ID_BACKBONE(r2->u.std.area_id)) +		r2_type = OSPF_PATH_INTER_AREA; -  return (r1_type - r2_type); +	return (r1_type - r2_type);  }  /* Compare two routes.   ret <  0 -- r1 is better.   ret == 0 -- r1 and r2 are the same.   ret >  0 -- r2 is better. */ -int -ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1, -		struct ospf_route *r2) +int ospf_route_cmp(struct ospf *ospf, struct ospf_route *r1, +		   struct ospf_route *r2)  { -  int ret = 0; - -  /* Path types of r1 and r2 are not the same. */ -  if ((ret = (r1->path_type - r2->path_type))) -    return ret; - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("Route[Compare]: Path types are the same."); -  /* Path types are the same, compare any cost. */ -  switch (r1->path_type) -    { -    case OSPF_PATH_INTRA_AREA: -    case OSPF_PATH_INTER_AREA: -      break; -    case OSPF_PATH_TYPE1_EXTERNAL: -      if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) -	{ -	  ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr); -	  if (ret != 0) -	    return ret; -	} -      break; -    case OSPF_PATH_TYPE2_EXTERNAL: -      if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost))) -	return ret; - -      if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) -	{ -	  ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr); -	  if (ret != 0) -	    return ret; +	int ret = 0; + +	/* Path types of r1 and r2 are not the same. */ +	if ((ret = (r1->path_type - r2->path_type))) +		return ret; + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("Route[Compare]: Path types are the same."); +	/* Path types are the same, compare any cost. */ +	switch (r1->path_type) { +	case OSPF_PATH_INTRA_AREA: +	case OSPF_PATH_INTER_AREA: +		break; +	case OSPF_PATH_TYPE1_EXTERNAL: +		if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) { +			ret = ospf_asbr_route_cmp(ospf, r1->u.ext.asbr, +						  r2->u.ext.asbr); +			if (ret != 0) +				return ret; +		} +		break; +	case OSPF_PATH_TYPE2_EXTERNAL: +		if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost))) +			return ret; + +		if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) { +			ret = ospf_asbr_route_cmp(ospf, r1->u.ext.asbr, +						  r2->u.ext.asbr); +			if (ret != 0) +				return ret; +		} +		break;  	} -      break; -    }       -  /* Anyway, compare the costs. */ -  return (r1->cost - r2->cost); +	/* Anyway, compare the costs. */ +	return (r1->cost - r2->cost);  } -static int -ospf_path_exist (struct list *plist, struct in_addr nexthop, -		 struct ospf_interface *oi) +static int ospf_path_exist(struct list *plist, struct in_addr nexthop, +			   struct ospf_interface *oi)  { -  struct listnode *node, *nnode; -  struct ospf_path *path; +	struct listnode *node, *nnode; +	struct ospf_path *path; -  for (ALL_LIST_ELEMENTS (plist, node, nnode, path)) -    if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && -	path->ifindex == oi->ifp->ifindex) -      return 1; +	for (ALL_LIST_ELEMENTS(plist, node, nnode, path)) +		if (IPV4_ADDR_SAME(&path->nexthop, &nexthop) +		    && path->ifindex == oi->ifp->ifindex) +			return 1; -  return 0; +	return 0;  } -void -ospf_route_copy_nexthops_from_vertex (struct ospf_route *to, -				      struct vertex *v) +void ospf_route_copy_nexthops_from_vertex(struct ospf_route *to, +					  struct vertex *v)  { -  struct listnode *node; -  struct ospf_path *path; -  struct vertex_nexthop *nexthop; -  struct vertex_parent *vp; - -  assert (to->paths); - -  for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp)) -    { -      nexthop = vp->nexthop; -       -      if (nexthop->oi != NULL)  -	{ -	  if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi)) -	    { -	      path = ospf_path_new (); -	      path->nexthop = nexthop->router; -	      path->ifindex = nexthop->oi->ifp->ifindex; -              if (CHECK_FLAG(nexthop->oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) -                path->unnumbered = 1; -	      listnode_add (to->paths, path); -	    } +	struct listnode *node; +	struct ospf_path *path; +	struct vertex_nexthop *nexthop; +	struct vertex_parent *vp; + +	assert(to->paths); + +	for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) { +		nexthop = vp->nexthop; + +		if (nexthop->oi != NULL) { +			if (!ospf_path_exist(to->paths, nexthop->router, +					     nexthop->oi)) { +				path = ospf_path_new(); +				path->nexthop = nexthop->router; +				path->ifindex = nexthop->oi->ifp->ifindex; +				if (CHECK_FLAG(nexthop->oi->connected->flags, +					       ZEBRA_IFA_UNNUMBERED)) +					path->unnumbered = 1; +				listnode_add(to->paths, path); +			} +		}  	} -    }  } -struct ospf_path * -ospf_path_lookup (struct list *plist, struct ospf_path *path) +struct ospf_path *ospf_path_lookup(struct list *plist, struct ospf_path *path)  { -  struct listnode *node; -  struct ospf_path *op; - -  for (ALL_LIST_ELEMENTS_RO (plist, node, op)) -  { -    if (!IPV4_ADDR_SAME (&op->nexthop, &path->nexthop)) -      continue; -    if (!IPV4_ADDR_SAME (&op->adv_router, &path->adv_router)) -      continue; -    if (op->ifindex != path->ifindex) -      continue; -    return op; -  } -  return NULL; +	struct listnode *node; +	struct ospf_path *op; + +	for (ALL_LIST_ELEMENTS_RO(plist, node, op)) { +		if (!IPV4_ADDR_SAME(&op->nexthop, &path->nexthop)) +			continue; +		if (!IPV4_ADDR_SAME(&op->adv_router, &path->adv_router)) +			continue; +		if (op->ifindex != path->ifindex) +			continue; +		return op; +	} +	return NULL;  } -void -ospf_route_copy_nexthops (struct ospf_route *to, struct list *from) +void ospf_route_copy_nexthops(struct ospf_route *to, struct list *from)  { -  struct listnode *node, *nnode; -  struct ospf_path *path; +	struct listnode *node, *nnode; +	struct ospf_path *path; -  assert (to->paths); +	assert(to->paths); -  for (ALL_LIST_ELEMENTS (from, node, nnode, path)) -    /* The same routes are just discarded. */ -    if (!ospf_path_lookup (to->paths, path)) -      listnode_add (to->paths, ospf_path_dup (path)); +	for (ALL_LIST_ELEMENTS(from, node, nnode, path)) +		/* The same routes are just discarded. */ +		if (!ospf_path_lookup(to->paths, path)) +			listnode_add(to->paths, ospf_path_dup(path));  } -void -ospf_route_subst_nexthops (struct ospf_route *to, struct list *from) +void ospf_route_subst_nexthops(struct ospf_route *to, struct list *from)  { -  list_delete_all_node (to->paths); -  ospf_route_copy_nexthops (to, from); +	list_delete_all_node(to->paths); +	ospf_route_copy_nexthops(to, from);  } -void -ospf_route_subst (struct route_node *rn, struct ospf_route *new_or, -		  struct ospf_route *over) +void ospf_route_subst(struct route_node *rn, struct ospf_route *new_or, +		      struct ospf_route *over)  { -  route_lock_node (rn); -  ospf_route_free (rn->info); +	route_lock_node(rn); +	ospf_route_free(rn->info); -  ospf_route_copy_nexthops (new_or, over->paths); -  rn->info = new_or; -  route_unlock_node (rn); +	ospf_route_copy_nexthops(new_or, over->paths); +	rn->info = new_or; +	route_unlock_node(rn);  } -void -ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p, -		struct ospf_route *new_or, struct ospf_route *over) +void ospf_route_add(struct route_table *rt, struct prefix_ipv4 *p, +		    struct ospf_route *new_or, struct ospf_route *over)  { -  struct route_node *rn; +	struct route_node *rn; -  rn = route_node_get (rt, (struct prefix *) p); +	rn = route_node_get(rt, (struct prefix *)p); -  ospf_route_copy_nexthops (new_or, over->paths); +	ospf_route_copy_nexthops(new_or, over->paths); + +	if (rn->info) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug("ospf_route_add(): something's wrong !"); +		route_unlock_node(rn); +		return; +	} -  if (rn->info) -    { -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug ("ospf_route_add(): something's wrong !"); -      route_unlock_node (rn); -      return; -    } +	rn->info = new_or; +} -  rn->info = new_or; +void ospf_prune_unreachable_networks(struct route_table *rt) +{ +	struct route_node *rn, *next; +	struct ospf_route * or ; + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("Pruning unreachable networks"); + +	for (rn = route_top(rt); rn; rn = next) { +		next = route_next(rn); +		if (rn->info != NULL) { +			or = rn->info; +			if (listcount(or->paths) == 0) { +				if (IS_DEBUG_OSPF_EVENT) +					zlog_debug("Pruning route to %s/%d", +						   inet_ntoa(rn->p.u.prefix4), +						   rn->p.prefixlen); + +				ospf_route_free(or); +				rn->info = NULL; +				route_unlock_node(rn); +			} +		} +	}  } -void -ospf_prune_unreachable_networks (struct route_table *rt) +void ospf_prune_unreachable_routers(struct route_table *rtrs)  { -  struct route_node *rn, *next; -  struct ospf_route *or; +	struct route_node *rn, *next; +	struct ospf_route * or ; +	struct listnode *node, *nnode; +	struct list *paths; + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("Pruning unreachable routers"); + +	for (rn = route_top(rtrs); rn; rn = next) { +		next = route_next(rn); +		if ((paths = rn->info) == NULL) +			continue; + +		for (ALL_LIST_ELEMENTS(paths, node, nnode, or)) { +			if (listcount(or->paths) == 0) { +				if (IS_DEBUG_OSPF_EVENT) { +					zlog_debug("Pruning route to rtr %s", +						   inet_ntoa(rn->p.u.prefix4)); +					zlog_debug( +						"               via area %s", +						inet_ntoa(or->u.std.area_id)); +				} + +				listnode_delete(paths, or); +				ospf_route_free(or); +			} +		} -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("Pruning unreachable networks"); +		if (listcount(paths) == 0) { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug("Pruning router node %s", +					   inet_ntoa(rn->p.u.prefix4)); -  for (rn = route_top (rt); rn; rn = next) -    { -      next = route_next (rn); -      if (rn->info != NULL) -	{ -	  or = rn->info; -	  if (listcount (or->paths) == 0) -	    { -	      if (IS_DEBUG_OSPF_EVENT) -		zlog_debug ("Pruning route to %s/%d", -			   inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen); - -	      ospf_route_free (or); -	      rn->info = NULL; -	      route_unlock_node (rn); -	    } +			list_delete(paths); +			rn->info = NULL; +			route_unlock_node(rn); +		}  	} -    }  } -void -ospf_prune_unreachable_routers (struct route_table *rtrs) +int ospf_add_discard_route(struct route_table *rt, struct ospf_area *area, +			   struct prefix_ipv4 *p)  { -  struct route_node *rn, *next; -  struct ospf_route *or; -  struct listnode *node, *nnode; -  struct list *paths; +	struct route_node *rn; +	struct ospf_route * or, *new_or; -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("Pruning unreachable routers"); +	rn = route_node_get(rt, (struct prefix *)p); -  for (rn = route_top (rtrs); rn; rn = next) -    { -      next = route_next (rn); -      if ((paths = rn->info) == NULL) -	continue; +	if (rn == NULL) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug( +				"ospf_add_discard_route(): router installation error"); +		return 0; +	} -      for (ALL_LIST_ELEMENTS (paths, node, nnode, or)) +	if (rn->info) /* If the route to the same destination is found */  	{ -	  if (listcount (or->paths) == 0) -	    { -	      if (IS_DEBUG_OSPF_EVENT) -		{ -		  zlog_debug ("Pruning route to rtr %s", -			     inet_ntoa (rn->p.u.prefix4)); -		  zlog_debug ("               via area %s", -			     inet_ntoa (or->u.std.area_id)); -		} +		route_unlock_node(rn); -	      listnode_delete (paths, or); -	      ospf_route_free (or); -	    } -	} +		or = rn->info; -      if (listcount (paths) == 0) -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4)); +		if (or->path_type == OSPF_PATH_INTRA_AREA) { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"ospf_add_discard_route(): " +					"an intra-area route exists"); +			return 0; +		} -	  list_delete (paths); -	  rn->info = NULL; -	  route_unlock_node (rn); -	} -    } -} +		if (or->type == OSPF_DESTINATION_DISCARD) { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"ospf_add_discard_route(): " +					"discard entry already installed"); +			return 0; +		} -int -ospf_add_discard_route (struct route_table *rt, struct ospf_area *area, -			struct prefix_ipv4 *p) -{ -  struct route_node *rn; -  struct ospf_route *or, *new_or; +		ospf_route_free(rn->info); +	} -  rn = route_node_get (rt, (struct prefix *) p); +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug( +			"ospf_add_discard_route(): " +			"adding %s/%d", +			inet_ntoa(p->prefix), p->prefixlen); -  if (rn == NULL) -    { -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug ("ospf_add_discard_route(): router installation error"); -      return 0; -    } +	new_or = ospf_route_new(); +	new_or->type = OSPF_DESTINATION_DISCARD; +	new_or->id.s_addr = 0; +	new_or->cost = 0; +	new_or->u.std.area_id = area->area_id; +	new_or->u.std.external_routing = area->external_routing; +	new_or->path_type = OSPF_PATH_INTER_AREA; +	rn->info = new_or; -  if (rn->info) /* If the route to the same destination is found */ -    { -      route_unlock_node (rn); +	ospf_zebra_add_discard(p); -      or = rn->info; +	return 1; +} -      if (or->path_type == OSPF_PATH_INTRA_AREA) -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("ospf_add_discard_route(): " -		       "an intra-area route exists"); -	  return 0; +void ospf_delete_discard_route(struct route_table *rt, struct prefix_ipv4 *p) +{ +	struct route_node *rn; +	struct ospf_route * or ; + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug( +			"ospf_delete_discard_route(): " +			"deleting %s/%d", +			inet_ntoa(p->prefix), p->prefixlen); + +	rn = route_node_lookup(rt, (struct prefix *)p); + +	if (rn == NULL) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug( +				"ospf_delete_discard_route(): no route found"); +		return;  	} -      if (or->type == OSPF_DESTINATION_DISCARD) -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("ospf_add_discard_route(): " -		       "discard entry already installed"); -	  return 0; +	or = rn->info; + +	if (or->path_type == OSPF_PATH_INTRA_AREA) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug( +				"ospf_delete_discard_route(): " +				"an intra-area route exists"); +		return;  	} -      ospf_route_free (rn->info); -  } +	if (or->type != OSPF_DESTINATION_DISCARD) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug( +				"ospf_delete_discard_route(): " +				"not a discard entry"); +		return; +	} -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("ospf_add_discard_route(): " -		"adding %s/%d", inet_ntoa (p->prefix), p->prefixlen); +	/* free the route entry and the route node */ +	ospf_route_free(rn->info); -  new_or = ospf_route_new (); -  new_or->type = OSPF_DESTINATION_DISCARD; -  new_or->id.s_addr = 0; -  new_or->cost = 0; -  new_or->u.std.area_id = area->area_id; -  new_or->u.std.external_routing = area->external_routing; -  new_or->path_type = OSPF_PATH_INTER_AREA; -  rn->info = new_or; +	rn->info = NULL; +	route_unlock_node(rn); +	route_unlock_node(rn); -  ospf_zebra_add_discard (p); +	/* remove the discard entry from the rib */ +	ospf_zebra_delete_discard(p); -  return 1; -} - -void -ospf_delete_discard_route (struct route_table *rt, struct prefix_ipv4 *p) -{ -  struct route_node *rn; -  struct ospf_route *or; - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("ospf_delete_discard_route(): " -		"deleting %s/%d", inet_ntoa (p->prefix), p->prefixlen); - -  rn = route_node_lookup (rt, (struct prefix*)p); - -  if (rn == NULL) -    { -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug("ospf_delete_discard_route(): no route found"); -      return; -    } - -  or = rn->info; - -  if (or->path_type == OSPF_PATH_INTRA_AREA) -    { -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug ("ospf_delete_discard_route(): " -		    "an intra-area route exists"); -      return; -    } - -  if (or->type != OSPF_DESTINATION_DISCARD) -    { -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug ("ospf_delete_discard_route(): " -		    "not a discard entry"); -      return; -    } - -  /* free the route entry and the route node */ -  ospf_route_free (rn->info); - -  rn->info = NULL; -  route_unlock_node (rn); -  route_unlock_node (rn); - -  /* remove the discard entry from the rib */ -  ospf_zebra_delete_discard(p); - -  return; +	return;  } -  | 
