diff options
Diffstat (limited to 'ospfd/ospf_lsa.c')
| -rw-r--r-- | ospfd/ospf_lsa.c | 6436 | 
1 files changed, 3187 insertions, 3249 deletions
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 835d321bb4..68adf2e10b 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -31,7 +31,7 @@  #include "log.h"  #include "thread.h"  #include "hash.h" -#include "sockunion.h"		/* for inet_aton() */ +#include "sockunion.h" /* for inet_aton() */  #include "checksum.h"  #include "ospfd/ospfd.h" @@ -51,1483 +51,1442 @@  #include "ospfd/ospf_zebra.h" -u_int32_t -get_metric (u_char *metric) +u_int32_t get_metric(u_char *metric)  { -  u_int32_t m; -  m = metric[0]; -  m = (m << 8) + metric[1]; -  m = (m << 8) + metric[2]; -  return m; +	u_int32_t m; +	m = metric[0]; +	m = (m << 8) + metric[1]; +	m = (m << 8) + metric[2]; +	return m;  } -struct timeval -int2tv (int a) +struct timeval int2tv(int a)  { -  struct timeval ret; +	struct timeval ret; -  ret.tv_sec = a; -  ret.tv_usec = 0; +	ret.tv_sec = a; +	ret.tv_usec = 0; -  return ret; +	return ret;  } -struct timeval -msec2tv (int a) +struct timeval msec2tv(int a)  { -  struct timeval ret; +	struct timeval ret; -  ret.tv_sec = a/1000; -  ret.tv_usec = (a%1000) * 1000; +	ret.tv_sec = a / 1000; +	ret.tv_usec = (a % 1000) * 1000; -  return ret; +	return ret;  } -int -ospf_lsa_refresh_delay (struct ospf_lsa *lsa) +int ospf_lsa_refresh_delay(struct ospf_lsa *lsa)  { -  struct timeval delta; -  int delay = 0; +	struct timeval delta; +	int delay = 0; -  if (monotime_since (&lsa->tv_orig, &delta) < OSPF_MIN_LS_INTERVAL * 1000LL) -    { -      struct timeval minv = msec2tv (OSPF_MIN_LS_INTERVAL); -      timersub (&minv, &delta, &minv); +	if (monotime_since(&lsa->tv_orig, &delta) +	    < OSPF_MIN_LS_INTERVAL * 1000LL) { +		struct timeval minv = msec2tv(OSPF_MIN_LS_INTERVAL); +		timersub(&minv, &delta, &minv); -      /* TBD: remove padding to full sec, return timeval instead */ -      delay = minv.tv_sec + !!minv.tv_usec; +		/* TBD: remove padding to full sec, return timeval instead */ +		delay = minv.tv_sec + !!minv.tv_usec; -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        zlog_debug ("LSA[Type%d:%s]: Refresh timer delay %d seconds", -	           lsa->data->type, inet_ntoa (lsa->data->id), delay); +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type%d:%s]: Refresh timer delay %d seconds", +				lsa->data->type, inet_ntoa(lsa->data->id), +				delay); -      assert (delay > 0); -    } +		assert(delay > 0); +	} -  return delay; +	return delay;  } -int -get_age (struct ospf_lsa *lsa) +int get_age(struct ospf_lsa *lsa)  { -  struct timeval rel; +	struct timeval rel; -  monotime_since (&lsa->tv_recv, &rel); -  return ntohs (lsa->data->ls_age) + rel.tv_sec; +	monotime_since(&lsa->tv_recv, &rel); +	return ntohs(lsa->data->ls_age) + rel.tv_sec;  }  /* Fletcher Checksum -- Refer to RFC1008. */ -/* All the offsets are zero-based. The offsets in the RFC1008 are  +/* All the offsets are zero-based. The offsets in the RFC1008 are     one-based. */ -u_int16_t -ospf_lsa_checksum (struct lsa_header *lsa) +u_int16_t ospf_lsa_checksum(struct lsa_header *lsa)  { -  u_char *buffer = (u_char *) &lsa->options; -  int options_offset = buffer - (u_char *) &lsa->ls_age; /* should be 2 */ +	u_char *buffer = (u_char *)&lsa->options; +	int options_offset = buffer - (u_char *)&lsa->ls_age; /* should be 2 */ -  /* Skip the AGE field */ -  u_int16_t len = ntohs(lsa->length) - options_offset;  +	/* Skip the AGE field */ +	u_int16_t len = ntohs(lsa->length) - options_offset; -  /* Checksum offset starts from "options" field, not the beginning of the -     lsa_header struct. The offset is 14, rather than 16. */ -  int checksum_offset = (u_char *) &lsa->checksum - buffer; +	/* Checksum offset starts from "options" field, not the beginning of the +	   lsa_header struct. The offset is 14, rather than 16. */ +	int checksum_offset = (u_char *)&lsa->checksum - buffer; -  return fletcher_checksum(buffer, len, checksum_offset); +	return fletcher_checksum(buffer, len, checksum_offset);  } -int -ospf_lsa_checksum_valid (struct lsa_header *lsa) +int ospf_lsa_checksum_valid(struct lsa_header *lsa)  { -  u_char *buffer = (u_char *) &lsa->options; -  int options_offset = buffer - (u_char *) &lsa->ls_age; /* should be 2 */ +	u_char *buffer = (u_char *)&lsa->options; +	int options_offset = buffer - (u_char *)&lsa->ls_age; /* should be 2 */ -  /* Skip the AGE field */ -  u_int16_t len = ntohs(lsa->length) - options_offset; +	/* Skip the AGE field */ +	u_int16_t len = ntohs(lsa->length) - options_offset; -  return(fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE) == 0); +	return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE) +		== 0);  } -  /* Create OSPF LSA. */ -struct ospf_lsa * -ospf_lsa_new () +struct ospf_lsa *ospf_lsa_new()  { -  struct ospf_lsa *new; +	struct ospf_lsa *new; -  new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa)); +	new = XCALLOC(MTYPE_OSPF_LSA, sizeof(struct ospf_lsa)); -  new->flags = 0; -  new->lock = 1; -  new->retransmit_counter = 0; -  monotime(&new->tv_recv); -  new->tv_orig = new->tv_recv; -  new->refresh_list = -1; -   -  return new; +	new->flags = 0; +	new->lock = 1; +	new->retransmit_counter = 0; +	monotime(&new->tv_recv); +	new->tv_orig = new->tv_recv; +	new->refresh_list = -1; + +	return new;  }  /* Duplicate OSPF LSA. */ -struct ospf_lsa * -ospf_lsa_dup (struct ospf_lsa *lsa) +struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *lsa)  { -  struct ospf_lsa *new; +	struct ospf_lsa *new; -  if (lsa == NULL) -    return NULL; +	if (lsa == NULL) +		return NULL; -  new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa)); +	new = XCALLOC(MTYPE_OSPF_LSA, sizeof(struct ospf_lsa)); -  memcpy (new, lsa, sizeof (struct ospf_lsa)); -  UNSET_FLAG (new->flags, OSPF_LSA_DISCARD); -  new->lock = 1; -  new->retransmit_counter = 0; -  new->data = ospf_lsa_data_dup (lsa->data); +	memcpy(new, lsa, sizeof(struct ospf_lsa)); +	UNSET_FLAG(new->flags, OSPF_LSA_DISCARD); +	new->lock = 1; +	new->retransmit_counter = 0; +	new->data = ospf_lsa_data_dup(lsa->data); -  /* kevinm: Clear the refresh_list, otherwise there are going -     to be problems when we try to remove the LSA from the -     queue (which it's not a member of.) -     XXX: Should we add the LSA to the refresh_list queue? */ -  new->refresh_list = -1; +	/* kevinm: Clear the refresh_list, otherwise there are going +	   to be problems when we try to remove the LSA from the +	   queue (which it's not a member of.) +	   XXX: Should we add the LSA to the refresh_list queue? */ +	new->refresh_list = -1; -  if (IS_DEBUG_OSPF (lsa, LSA)) -    zlog_debug ("LSA: duplicated %p (new: %p)", (void *)lsa, (void *)new); +	if (IS_DEBUG_OSPF(lsa, LSA)) +		zlog_debug("LSA: duplicated %p (new: %p)", (void *)lsa, +			   (void *)new); -  return new; +	return new;  }  /* Free OSPF LSA. */ -void -ospf_lsa_free (struct ospf_lsa *lsa) +void ospf_lsa_free(struct ospf_lsa *lsa)  { -  assert (lsa->lock == 0); -   -  if (IS_DEBUG_OSPF (lsa, LSA)) -    zlog_debug ("LSA: freed %p", (void *)lsa); +	assert(lsa->lock == 0); + +	if (IS_DEBUG_OSPF(lsa, LSA)) +		zlog_debug("LSA: freed %p", (void *)lsa); -  /* Delete LSA data. */ -  if (lsa->data != NULL) -    ospf_lsa_data_free (lsa->data); +	/* Delete LSA data. */ +	if (lsa->data != NULL) +		ospf_lsa_data_free(lsa->data); -  assert (lsa->refresh_list < 0); +	assert(lsa->refresh_list < 0); -  memset (lsa, 0, sizeof (struct ospf_lsa));  -  XFREE (MTYPE_OSPF_LSA, lsa); +	memset(lsa, 0, sizeof(struct ospf_lsa)); +	XFREE(MTYPE_OSPF_LSA, lsa);  }  /* Lock LSA. */ -struct ospf_lsa * -ospf_lsa_lock (struct ospf_lsa *lsa) +struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *lsa)  { -  lsa->lock++; -  return lsa; +	lsa->lock++; +	return lsa;  }  /* Unlock LSA. */ -void -ospf_lsa_unlock (struct ospf_lsa **lsa) +void ospf_lsa_unlock(struct ospf_lsa **lsa)  { -  /* This is sanity check. */ -  if (!lsa || !*lsa) -    return; -   -  (*lsa)->lock--; +	/* This is sanity check. */ +	if (!lsa || !*lsa) +		return; -  assert ((*lsa)->lock >= 0); +	(*lsa)->lock--; -  if ((*lsa)->lock == 0) -    { -      assert (CHECK_FLAG ((*lsa)->flags, OSPF_LSA_DISCARD)); -      ospf_lsa_free (*lsa); -      *lsa = NULL; -    } +	assert((*lsa)->lock >= 0); + +	if ((*lsa)->lock == 0) { +		assert(CHECK_FLAG((*lsa)->flags, OSPF_LSA_DISCARD)); +		ospf_lsa_free(*lsa); +		*lsa = NULL; +	}  }  /* Check discard flag. */ -void -ospf_lsa_discard (struct ospf_lsa *lsa) +void ospf_lsa_discard(struct ospf_lsa *lsa)  { -  if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD)) -    { -      SET_FLAG (lsa->flags, OSPF_LSA_DISCARD); -      ospf_lsa_unlock (&lsa); -    } +	if (!CHECK_FLAG(lsa->flags, OSPF_LSA_DISCARD)) { +		SET_FLAG(lsa->flags, OSPF_LSA_DISCARD); +		ospf_lsa_unlock(&lsa); +	}  }  /* Create LSA data. */ -struct lsa_header * -ospf_lsa_data_new (size_t size) +struct lsa_header *ospf_lsa_data_new(size_t size)  { -  return XCALLOC (MTYPE_OSPF_LSA_DATA, size); +	return XCALLOC(MTYPE_OSPF_LSA_DATA, size);  }  /* Duplicate LSA data. */ -struct lsa_header * -ospf_lsa_data_dup (struct lsa_header *lsah) +struct lsa_header *ospf_lsa_data_dup(struct lsa_header *lsah)  { -  struct lsa_header *new; +	struct lsa_header *new; -  new = ospf_lsa_data_new (ntohs (lsah->length)); -  memcpy (new, lsah, ntohs (lsah->length)); +	new = ospf_lsa_data_new(ntohs(lsah->length)); +	memcpy(new, lsah, ntohs(lsah->length)); -  return new; +	return new;  }  /* Free LSA data. */ -void -ospf_lsa_data_free (struct lsa_header *lsah) +void ospf_lsa_data_free(struct lsa_header *lsah)  { -  if (IS_DEBUG_OSPF (lsa, LSA)) -    zlog_debug ("LSA[Type%d:%s]: data freed %p", -	       lsah->type, inet_ntoa (lsah->id), (void *)lsah); +	if (IS_DEBUG_OSPF(lsa, LSA)) +		zlog_debug("LSA[Type%d:%s]: data freed %p", lsah->type, +			   inet_ntoa(lsah->id), (void *)lsah); -  XFREE (MTYPE_OSPF_LSA_DATA, lsah); +	XFREE(MTYPE_OSPF_LSA_DATA, lsah);  }  /* LSA general functions. */ -const char * -dump_lsa_key (struct ospf_lsa *lsa) +const char *dump_lsa_key(struct ospf_lsa *lsa)  { -  static char buf[] = { -    "Type255,id(255.255.255.255),ar(255.255.255.255)" -  }; -  struct lsa_header *lsah; +	static char buf[] = {"Type255,id(255.255.255.255),ar(255.255.255.255)"}; +	struct lsa_header *lsah; -  if (lsa != NULL && (lsah = lsa->data) != NULL) -    { -      char id[INET_ADDRSTRLEN], ar[INET_ADDRSTRLEN]; -      strcpy (id, inet_ntoa (lsah->id)); -      strcpy (ar, inet_ntoa (lsah->adv_router)); +	if (lsa != NULL && (lsah = lsa->data) != NULL) { +		char id[INET_ADDRSTRLEN], ar[INET_ADDRSTRLEN]; +		strcpy(id, inet_ntoa(lsah->id)); +		strcpy(ar, inet_ntoa(lsah->adv_router)); -      sprintf (buf, "Type%d,id(%s),ar(%s)", lsah->type, id, ar); -    } -  else -    strcpy (buf, "NULL"); +		sprintf(buf, "Type%d,id(%s),ar(%s)", lsah->type, id, ar); +	} else +		strcpy(buf, "NULL"); -  return buf; +	return buf;  } -u_int32_t -lsa_seqnum_increment (struct ospf_lsa *lsa) +u_int32_t lsa_seqnum_increment(struct ospf_lsa *lsa)  { -  u_int32_t seqnum; +	u_int32_t seqnum; -  seqnum = ntohl (lsa->data->ls_seqnum) + 1; +	seqnum = ntohl(lsa->data->ls_seqnum) + 1; -  return htonl (seqnum); +	return htonl(seqnum);  } -void -lsa_header_set (struct stream *s, u_char options, -		u_char type, struct in_addr id, struct in_addr router_id) +void lsa_header_set(struct stream *s, u_char options, u_char type, +		    struct in_addr id, struct in_addr router_id)  { -  struct lsa_header *lsah; +	struct lsa_header *lsah; -  lsah = (struct lsa_header *) STREAM_DATA (s); +	lsah = (struct lsa_header *)STREAM_DATA(s); -  lsah->ls_age = htons (OSPF_LSA_INITIAL_AGE); -  lsah->options = options; -  lsah->type = type; -  lsah->id = id; -  lsah->adv_router = router_id; -  lsah->ls_seqnum = htonl (OSPF_INITIAL_SEQUENCE_NUMBER); +	lsah->ls_age = htons(OSPF_LSA_INITIAL_AGE); +	lsah->options = options; +	lsah->type = type; +	lsah->id = id; +	lsah->adv_router = router_id; +	lsah->ls_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER); -  stream_forward_endp (s, OSPF_LSA_HEADER_SIZE); +	stream_forward_endp(s, OSPF_LSA_HEADER_SIZE);  }  /* router-LSA related functions. */  /* Get router-LSA flags. */ -static u_char -router_lsa_flags (struct ospf_area *area) -{ -  u_char flags; - -  flags = area->ospf->flags; - -  /* Set virtual link flag. */ -  if (ospf_full_virtual_nbrs (area)) -    SET_FLAG (flags, ROUTER_LSA_VIRTUAL); -  else -    /* Just sanity check */ -    UNSET_FLAG (flags, ROUTER_LSA_VIRTUAL); - -  /* Set Shortcut ABR behabiour flag. */ -  UNSET_FLAG (flags, ROUTER_LSA_SHORTCUT); -  if (area->ospf->abr_type == OSPF_ABR_SHORTCUT) -    if (!OSPF_IS_AREA_BACKBONE (area)) -      if ((area->shortcut_configured == OSPF_SHORTCUT_DEFAULT && -	   area->ospf->backbone == NULL) || -	  area->shortcut_configured == OSPF_SHORTCUT_ENABLE) -	SET_FLAG (flags, ROUTER_LSA_SHORTCUT); - -  /* ASBR can't exit in stub area. */ -  if (area->external_routing == OSPF_AREA_STUB) -    UNSET_FLAG (flags, ROUTER_LSA_EXTERNAL); -  /* If ASBR set External flag */ -  else if (IS_OSPF_ASBR (area->ospf)) -    SET_FLAG (flags, ROUTER_LSA_EXTERNAL); - -  /* Set ABR dependent flags */ -  if (IS_OSPF_ABR (area->ospf)) -    { -      SET_FLAG (flags,  ROUTER_LSA_BORDER); -      /* If Area is NSSA and we are both ABR and unconditional translator,  -       * set Nt bit to inform other routers. -       */ -      if ( (area->external_routing == OSPF_AREA_NSSA) -           && (area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS)) -        SET_FLAG (flags, ROUTER_LSA_NT); -    } -  return flags; +static u_char router_lsa_flags(struct ospf_area *area) +{ +	u_char flags; + +	flags = area->ospf->flags; + +	/* Set virtual link flag. */ +	if (ospf_full_virtual_nbrs(area)) +		SET_FLAG(flags, ROUTER_LSA_VIRTUAL); +	else +		/* Just sanity check */ +		UNSET_FLAG(flags, ROUTER_LSA_VIRTUAL); + +	/* Set Shortcut ABR behabiour flag. */ +	UNSET_FLAG(flags, ROUTER_LSA_SHORTCUT); +	if (area->ospf->abr_type == OSPF_ABR_SHORTCUT) +		if (!OSPF_IS_AREA_BACKBONE(area)) +			if ((area->shortcut_configured == OSPF_SHORTCUT_DEFAULT +			     && area->ospf->backbone == NULL) +			    || area->shortcut_configured +				       == OSPF_SHORTCUT_ENABLE) +				SET_FLAG(flags, ROUTER_LSA_SHORTCUT); + +	/* ASBR can't exit in stub area. */ +	if (area->external_routing == OSPF_AREA_STUB) +		UNSET_FLAG(flags, ROUTER_LSA_EXTERNAL); +	/* If ASBR set External flag */ +	else if (IS_OSPF_ASBR(area->ospf)) +		SET_FLAG(flags, ROUTER_LSA_EXTERNAL); + +	/* Set ABR dependent flags */ +	if (IS_OSPF_ABR(area->ospf)) { +		SET_FLAG(flags, ROUTER_LSA_BORDER); +		/* If Area is NSSA and we are both ABR and unconditional +		 * translator, +		 * set Nt bit to inform other routers. +		 */ +		if ((area->external_routing == OSPF_AREA_NSSA) +		    && (area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS)) +			SET_FLAG(flags, ROUTER_LSA_NT); +	} +	return flags;  }  /* Lookup neighbor other than myself.     And check neighbor count,     Point-to-Point link must have only 1 neighbor. */ -struct ospf_neighbor * -ospf_nbr_lookup_ptop (struct ospf_interface *oi) +struct ospf_neighbor *ospf_nbr_lookup_ptop(struct ospf_interface *oi)  { -  struct ospf_neighbor *nbr = NULL; -  struct route_node *rn; +	struct ospf_neighbor *nbr = NULL; +	struct route_node *rn; -  /* Search neighbor, there must be one of two nbrs. */ -  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) -    if ((nbr = rn->info)) -      if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) -	if (nbr->state == NSM_Full) -	  { -	    route_unlock_node (rn); -	    break; -	  } +	/* Search neighbor, there must be one of two nbrs. */ +	for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) +		if ((nbr = rn->info)) +			if (!IPV4_ADDR_SAME(&nbr->router_id, +					    &oi->ospf->router_id)) +				if (nbr->state == NSM_Full) { +					route_unlock_node(rn); +					break; +				} -  /* PtoP link must have only 1 neighbor. */ -  if (ospf_nbr_count (oi, 0) > 1) -    zlog_warn ("Point-to-Point link has more than 1 neighobrs."); +	/* PtoP link must have only 1 neighbor. */ +	if (ospf_nbr_count(oi, 0) > 1) +		zlog_warn("Point-to-Point link has more than 1 neighobrs."); -  return nbr; +	return nbr;  }  /* Determine cost of link, taking RFC3137 stub-router support into   * consideration   */ -static u_int16_t -ospf_link_cost (struct ospf_interface *oi) +static u_int16_t ospf_link_cost(struct ospf_interface *oi)  { -  /* RFC3137 stub router support */ -  if (!CHECK_FLAG (oi->area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) -    return oi->output_cost; -  else -    return OSPF_OUTPUT_COST_INFINITE; +	/* RFC3137 stub router support */ +	if (!CHECK_FLAG(oi->area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) +		return oi->output_cost; +	else +		return OSPF_OUTPUT_COST_INFINITE;  }  /* Set a link information. */ -static char -link_info_set (struct stream *s, struct in_addr id, -	       struct in_addr data, u_char type, u_char tos, u_int16_t cost) -{ -  /* LSA stream is initially allocated to OSPF_MAX_LSA_SIZE, suits -   * vast majority of cases. Some rare routers with lots of links need more. -   * we try accomodate those here. -   */ -  if (STREAM_WRITEABLE(s) < OSPF_ROUTER_LSA_LINK_SIZE) -    { -      size_t ret = OSPF_MAX_LSA_SIZE; -       -      /* Can we enlarge the stream still? */ -      if (STREAM_SIZE(s) == OSPF_MAX_LSA_SIZE) -        { -          /* we futz the size here for simplicity, really we need to account -           * for just: -           * IP Header - (sizeof (struct ip)) -           * OSPF Header - OSPF_HEADER_SIZE -           * LSA Header - OSPF_LSA_HEADER_SIZE -           * MD5 auth data, if MD5 is configured - OSPF_AUTH_MD5_SIZE. -           * -           * Simpler just to subtract OSPF_MAX_LSA_SIZE though. -           */ -          ret = stream_resize (s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE); -        } -       -      if (ret == OSPF_MAX_LSA_SIZE) -        { -          zlog_warn ("%s: Out of space in LSA stream, left %zd, size %zd", -                     __func__, STREAM_REMAIN (s), STREAM_SIZE (s)); -          return 0; -        } -    } -   -  /* TOS based routing is not supported. */ -  stream_put_ipv4 (s, id.s_addr);		/* Link ID. */ -  stream_put_ipv4 (s, data.s_addr);		/* Link Data. */ -  stream_putc (s, type);			/* Link Type. */ -  stream_putc (s, tos);				/* TOS = 0. */ -  stream_putw (s, cost);			/* Link Cost. */ -   -  return 1; +static char link_info_set(struct stream *s, struct in_addr id, +			  struct in_addr data, u_char type, u_char tos, +			  u_int16_t cost) +{ +	/* LSA stream is initially allocated to OSPF_MAX_LSA_SIZE, suits +	 * vast majority of cases. Some rare routers with lots of links need +	 * more. +	 * we try accomodate those here. +	 */ +	if (STREAM_WRITEABLE(s) < OSPF_ROUTER_LSA_LINK_SIZE) { +		size_t ret = OSPF_MAX_LSA_SIZE; + +		/* Can we enlarge the stream still? */ +		if (STREAM_SIZE(s) == OSPF_MAX_LSA_SIZE) { +			/* we futz the size here for simplicity, really we need +			 * to account +			 * for just: +			 * IP Header - (sizeof (struct ip)) +			 * OSPF Header - OSPF_HEADER_SIZE +			 * LSA Header - OSPF_LSA_HEADER_SIZE +			 * MD5 auth data, if MD5 is configured - +			 * OSPF_AUTH_MD5_SIZE. +			 * +			 * Simpler just to subtract OSPF_MAX_LSA_SIZE though. +			 */ +			ret = stream_resize( +				s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE); +		} + +		if (ret == OSPF_MAX_LSA_SIZE) { +			zlog_warn( +				"%s: Out of space in LSA stream, left %zd, size %zd", +				__func__, STREAM_REMAIN(s), STREAM_SIZE(s)); +			return 0; +		} +	} + +	/* TOS based routing is not supported. */ +	stream_put_ipv4(s, id.s_addr);   /* Link ID. */ +	stream_put_ipv4(s, data.s_addr); /* Link Data. */ +	stream_putc(s, type);		 /* Link Type. */ +	stream_putc(s, tos);		 /* TOS = 0. */ +	stream_putw(s, cost);		 /* Link Cost. */ + +	return 1;  }  /* Describe Point-to-Point link (Section 12.4.1.1). */ -static int -lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi) -{ -  int links = 0; -  struct ospf_neighbor *nbr; -  struct in_addr id, mask, data; -  u_int16_t cost = ospf_link_cost (oi); - -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    zlog_debug ("LSA[Type1]: Set link Point-to-Point"); - -  if ((nbr = ospf_nbr_lookup_ptop (oi))) -    if (nbr->state == NSM_Full) -      { -        if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) -          { -            /* For unnumbered point-to-point networks, the Link Data field -               should specify the interface's MIB-II ifIndex value. */ -            data.s_addr = htonl(oi->ifp->ifindex); -            links += link_info_set (s, nbr->router_id, data, -                                    LSA_LINK_TYPE_POINTOPOINT, 0, cost); -          } -        else -          { -            links += link_info_set (s, nbr->router_id, -                                    oi->address->u.prefix4, -                                    LSA_LINK_TYPE_POINTOPOINT, 0, cost); -          } -      } - -  /* no need for a stub link for unnumbered interfaces */ -  if (!CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) -    { -      /* Regardless of the state of the neighboring router, we must -         add a Type 3 link (stub network). -         N.B. Options 1 & 2 share basically the same logic. */ -      masklen2ip (oi->address->prefixlen, &mask); -      id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr & mask.s_addr; -      links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, -                              oi->output_cost); -    } - -  return links; +static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi) +{ +	int links = 0; +	struct ospf_neighbor *nbr; +	struct in_addr id, mask, data; +	u_int16_t cost = ospf_link_cost(oi); + +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +		zlog_debug("LSA[Type1]: Set link Point-to-Point"); + +	if ((nbr = ospf_nbr_lookup_ptop(oi))) +		if (nbr->state == NSM_Full) { +			if (CHECK_FLAG(oi->connected->flags, +				       ZEBRA_IFA_UNNUMBERED)) { +				/* For unnumbered point-to-point networks, the +				   Link Data field +				   should specify the interface's MIB-II ifIndex +				   value. */ +				data.s_addr = htonl(oi->ifp->ifindex); +				links += link_info_set( +					s, nbr->router_id, data, +					LSA_LINK_TYPE_POINTOPOINT, 0, cost); +			} else { +				links += link_info_set( +					s, nbr->router_id, +					oi->address->u.prefix4, +					LSA_LINK_TYPE_POINTOPOINT, 0, cost); +			} +		} + +	/* no need for a stub link for unnumbered interfaces */ +	if (!CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) { +		/* Regardless of the state of the neighboring router, we must +		   add a Type 3 link (stub network). +		   N.B. Options 1 & 2 share basically the same logic. */ +		masklen2ip(oi->address->prefixlen, &mask); +		id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr +			    & mask.s_addr; +		links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, +				       oi->output_cost); +	} + +	return links;  }  /* Describe Broadcast Link. */ -static int -lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi) -{ -  struct ospf_neighbor *dr; -  struct in_addr id, mask; -  u_int16_t cost = ospf_link_cost (oi); -   -  /* Describe Type 3 Link. */ -  if (oi->state == ISM_Waiting) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        zlog_debug ("LSA[Type1]: Interface %s is in state Waiting. " -                    "Adding stub interface", oi->ifp->name); -      masklen2ip (oi->address->prefixlen, &mask); -      id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; -      return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, -                            oi->output_cost); -    } - -  dr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi)); -  /* Describe Type 2 link. */ -  if (dr && (dr->state == NSM_Full || -	     IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) && -      ospf_nbr_count (oi, NSM_Full) > 0) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        zlog_debug ("LSA[Type1]: Interface %s has a DR. " -                    "Adding transit interface", oi->ifp->name); -      return link_info_set (s, DR (oi), oi->address->u.prefix4, -                            LSA_LINK_TYPE_TRANSIT, 0, cost); -    } -  /* Describe type 3 link. */ -  else -    { -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        zlog_debug ("LSA[Type1]: Interface %s has no DR. " -                    "Adding stub interface", oi->ifp->name); -      masklen2ip (oi->address->prefixlen, &mask); -      id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; -      return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, -                            oi->output_cost); -    } -} - -static int -lsa_link_loopback_set (struct stream *s, struct ospf_interface *oi) -{ -  struct in_addr id, mask; -   -  /* Describe Type 3 Link. */ -  if (oi->state != ISM_Loopback) -    return 0; - -  mask.s_addr = 0xffffffff; -  id.s_addr = oi->address->u.prefix4.s_addr; -  return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0); +static int lsa_link_broadcast_set(struct stream *s, struct ospf_interface *oi) +{ +	struct ospf_neighbor *dr; +	struct in_addr id, mask; +	u_int16_t cost = ospf_link_cost(oi); + +	/* Describe Type 3 Link. */ +	if (oi->state == ISM_Waiting) { +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type1]: Interface %s is in state Waiting. " +				"Adding stub interface", +				oi->ifp->name); +		masklen2ip(oi->address->prefixlen, &mask); +		id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; +		return link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, +				     oi->output_cost); +	} + +	dr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi)); +	/* Describe Type 2 link. */ +	if (dr && (dr->state == NSM_Full +		   || IPV4_ADDR_SAME(&oi->address->u.prefix4, &DR(oi))) +	    && ospf_nbr_count(oi, NSM_Full) > 0) { +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type1]: Interface %s has a DR. " +				"Adding transit interface", +				oi->ifp->name); +		return link_info_set(s, DR(oi), oi->address->u.prefix4, +				     LSA_LINK_TYPE_TRANSIT, 0, cost); +	} +	/* Describe type 3 link. */ +	else { +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type1]: Interface %s has no DR. " +				"Adding stub interface", +				oi->ifp->name); +		masklen2ip(oi->address->prefixlen, &mask); +		id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; +		return link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, +				     oi->output_cost); +	} +} + +static int lsa_link_loopback_set(struct stream *s, struct ospf_interface *oi) +{ +	struct in_addr id, mask; + +	/* Describe Type 3 Link. */ +	if (oi->state != ISM_Loopback) +		return 0; + +	mask.s_addr = 0xffffffff; +	id.s_addr = oi->address->u.prefix4.s_addr; +	return link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);  }  /* Describe Virtual Link. */ -static int -lsa_link_virtuallink_set (struct stream *s, struct ospf_interface *oi) +static int lsa_link_virtuallink_set(struct stream *s, struct ospf_interface *oi)  { -  struct ospf_neighbor *nbr; -  u_int16_t cost = ospf_link_cost (oi); +	struct ospf_neighbor *nbr; +	u_int16_t cost = ospf_link_cost(oi); -  if (oi->state == ISM_PointToPoint) -    if ((nbr = ospf_nbr_lookup_ptop (oi))) -      if (nbr->state == NSM_Full) -	{ -	  return link_info_set (s, nbr->router_id, oi->address->u.prefix4, -			        LSA_LINK_TYPE_VIRTUALLINK, 0, cost); -	} +	if (oi->state == ISM_PointToPoint) +		if ((nbr = ospf_nbr_lookup_ptop(oi))) +			if (nbr->state == NSM_Full) { +				return link_info_set(s, nbr->router_id, +						     oi->address->u.prefix4, +						     LSA_LINK_TYPE_VIRTUALLINK, +						     0, cost); +			} -  return 0; +	return 0;  }  #define lsa_link_nbma_set(S,O)  lsa_link_broadcast_set (S, O) -/* this function add for support point-to-multipoint ,see rfc2328  +/* this function add for support point-to-multipoint ,see rfc2328  12.4.1.4.*/  /* from "edward rrr" <edward_rrr@hotmail.com>     http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */ -static int -lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) -{ -  int links = 0; -  struct route_node *rn; -  struct ospf_neighbor *nbr = NULL; -  struct in_addr id, mask; -  u_int16_t cost = ospf_link_cost (oi); - -  mask.s_addr = 0xffffffff; -  id.s_addr = oi->address->u.prefix4.s_addr; -  links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0); - -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    zlog_debug ("PointToMultipoint: running ptomultip_set"); - -  /* Search neighbor, */ -  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) -    if ((nbr = rn->info) != NULL) -      /* Ignore myself. */ -      if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) -	if (nbr->state == NSM_Full) - -	  { -	    links += link_info_set (s, nbr->router_id, oi->address->u.prefix4, -			            LSA_LINK_TYPE_POINTOPOINT, 0, cost); -            if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - 	      zlog_debug ("PointToMultipoint: set link to %s", -		         inet_ntoa(oi->address->u.prefix4)); -	  } -   -  return links; +static int lsa_link_ptomp_set(struct stream *s, struct ospf_interface *oi) +{ +	int links = 0; +	struct route_node *rn; +	struct ospf_neighbor *nbr = NULL; +	struct in_addr id, mask; +	u_int16_t cost = ospf_link_cost(oi); + +	mask.s_addr = 0xffffffff; +	id.s_addr = oi->address->u.prefix4.s_addr; +	links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, 0); + +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +		zlog_debug("PointToMultipoint: running ptomultip_set"); + +	/* Search neighbor, */ +	for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) +		if ((nbr = rn->info) != NULL) +			/* Ignore myself. */ +			if (!IPV4_ADDR_SAME(&nbr->router_id, +					    &oi->ospf->router_id)) +				if (nbr->state == NSM_Full) + +				{ +					links += link_info_set( +						s, nbr->router_id, +						oi->address->u.prefix4, +						LSA_LINK_TYPE_POINTOPOINT, 0, +						cost); +					if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +						zlog_debug( +							"PointToMultipoint: set link to %s", +							inet_ntoa( +								oi->address->u +									.prefix4)); +				} + +	return links;  }  /* Set router-LSA link information. */ -static int -router_lsa_link_set (struct stream *s, struct ospf_area *area) -{ -  struct listnode *node; -  struct ospf_interface *oi; -  int links = 0; - -  for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) -    { -      struct interface *ifp = oi->ifp; - -      /* Check interface is up, OSPF is enable. */ -      if (if_is_operative (ifp)) -	{ -	  if (oi->state != ISM_Down) -	    { -	      oi->lsa_pos_beg = links; -	      /* Describe each link. */ -	      switch (oi->type) -		{ -		case OSPF_IFTYPE_POINTOPOINT: -		  links += lsa_link_ptop_set (s, oi); -		  break; -		case OSPF_IFTYPE_BROADCAST: -		  links += lsa_link_broadcast_set (s, oi); -		  break; -		case OSPF_IFTYPE_NBMA: -		  links += lsa_link_nbma_set (s, oi); -		  break; -		case OSPF_IFTYPE_POINTOMULTIPOINT: -		  links += lsa_link_ptomp_set (s, oi); -		  break; -		case OSPF_IFTYPE_VIRTUALLINK: -		  links += lsa_link_virtuallink_set (s, oi); -		  break; -		case OSPF_IFTYPE_LOOPBACK: -		  links += lsa_link_loopback_set (s, oi);  +static int router_lsa_link_set(struct stream *s, struct ospf_area *area) +{ +	struct listnode *node; +	struct ospf_interface *oi; +	int links = 0; + +	for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi)) { +		struct interface *ifp = oi->ifp; + +		/* Check interface is up, OSPF is enable. */ +		if (if_is_operative(ifp)) { +			if (oi->state != ISM_Down) { +				oi->lsa_pos_beg = links; +				/* Describe each link. */ +				switch (oi->type) { +				case OSPF_IFTYPE_POINTOPOINT: +					links += lsa_link_ptop_set(s, oi); +					break; +				case OSPF_IFTYPE_BROADCAST: +					links += lsa_link_broadcast_set(s, oi); +					break; +				case OSPF_IFTYPE_NBMA: +					links += lsa_link_nbma_set(s, oi); +					break; +				case OSPF_IFTYPE_POINTOMULTIPOINT: +					links += lsa_link_ptomp_set(s, oi); +					break; +				case OSPF_IFTYPE_VIRTUALLINK: +					links += +						lsa_link_virtuallink_set(s, oi); +					break; +				case OSPF_IFTYPE_LOOPBACK: +					links += lsa_link_loopback_set(s, oi); +				} +				oi->lsa_pos_end = links; +			}  		} -	      oi->lsa_pos_end = links; -	    }  	} -    } -  return links; +	return links;  }  /* Set router-LSA body. */ -static void -ospf_router_lsa_body_set (struct stream *s, struct ospf_area *area) -{ -  unsigned long putp; -  u_int16_t cnt; - -  /* Set flags. */ -  stream_putc (s, router_lsa_flags (area)); - -  /* Set Zero fields. */ -  stream_putc (s, 0); - -  /* Keep pointer to # links. */ -  putp = stream_get_endp(s); - -  /* Forward word */ -  stream_putw(s, 0); - -  /* Set all link information. */ -  cnt = router_lsa_link_set (s, area); - -  /* Set # of links here. */ -  stream_putw_at (s, putp, cnt); -} - -static int -ospf_stub_router_timer (struct thread *t) -{ -  struct ospf_area *area = THREAD_ARG (t); -   -  area->t_stub_router = NULL; -   -  SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED); -   -  /* clear stub route state and generate router-lsa refresh, don't -   * clobber an administratively set stub-router state though. -   */ -  if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) -    return 0; -   -  UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); -   -  ospf_router_lsa_update_area (area); -   -  return 0; -} - -static void -ospf_stub_router_check (struct ospf_area *area) -{ -  /* area must either be administratively configured to be stub -   * or startup-time stub-router must be configured and we must in a pre-stub -   * state. -   */ -  if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) -    { -      SET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); -      return; -    } -   -  /* not admin-stubbed, check whether startup stubbing is configured and -   * whether it's not been done yet -   */ -  if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED)) -    return; -   -  if (area->ospf->stub_router_startup_time == OSPF_STUB_ROUTER_UNCONFIGURED) -    { -      /* stub-router is hence done forever for this area, even if someone -       * tries configure it (take effect next restart). -       */ -      SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED); -      return; -    } -   -  /* startup stub-router configured and not yet done */ -  SET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); -   -  OSPF_AREA_TIMER_ON (area->t_stub_router, ospf_stub_router_timer, -                      area->ospf->stub_router_startup_time); -} -  +static void ospf_router_lsa_body_set(struct stream *s, struct ospf_area *area) +{ +	unsigned long putp; +	u_int16_t cnt; + +	/* Set flags. */ +	stream_putc(s, router_lsa_flags(area)); + +	/* Set Zero fields. */ +	stream_putc(s, 0); + +	/* Keep pointer to # links. */ +	putp = stream_get_endp(s); + +	/* Forward word */ +	stream_putw(s, 0); + +	/* Set all link information. */ +	cnt = router_lsa_link_set(s, area); + +	/* Set # of links here. */ +	stream_putw_at(s, putp, cnt); +} + +static int ospf_stub_router_timer(struct thread *t) +{ +	struct ospf_area *area = THREAD_ARG(t); + +	area->t_stub_router = NULL; + +	SET_FLAG(area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED); + +	/* clear stub route state and generate router-lsa refresh, don't +	 * clobber an administratively set stub-router state though. +	 */ +	if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) +		return 0; + +	UNSET_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); + +	ospf_router_lsa_update_area(area); + +	return 0; +} + +static void ospf_stub_router_check(struct ospf_area *area) +{ +	/* area must either be administratively configured to be stub +	 * or startup-time stub-router must be configured and we must in a +	 * pre-stub +	 * state. +	 */ +	if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) { +		SET_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); +		return; +	} + +	/* not admin-stubbed, check whether startup stubbing is configured and +	 * whether it's not been done yet +	 */ +	if (CHECK_FLAG(area->stub_router_state, +		       OSPF_AREA_WAS_START_STUB_ROUTED)) +		return; + +	if (area->ospf->stub_router_startup_time +	    == OSPF_STUB_ROUTER_UNCONFIGURED) { +		/* stub-router is hence done forever for this area, even if +		 * someone +		 * tries configure it (take effect next restart). +		 */ +		SET_FLAG(area->stub_router_state, +			 OSPF_AREA_WAS_START_STUB_ROUTED); +		return; +	} + +	/* startup stub-router configured and not yet done */ +	SET_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); + +	OSPF_AREA_TIMER_ON(area->t_stub_router, ospf_stub_router_timer, +			   area->ospf->stub_router_startup_time); +} +  /* Create new router-LSA. */ -static struct ospf_lsa * -ospf_router_lsa_new (struct ospf_area *area) -{ -  struct ospf *ospf = area->ospf; -  struct stream *s; -  struct lsa_header *lsah; -  struct ospf_lsa *new; -  int length; - -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    zlog_debug ("LSA[Type1]: Create router-LSA instance"); - -  /* check whether stub-router is desired, and if this is the first  -   * router LSA. -   */ -  ospf_stub_router_check (area); -   -  /* Create a stream for LSA. */ -  s = stream_new (OSPF_MAX_LSA_SIZE); -  /* Set LSA common header fields. */ -  lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_OPTIONS_NSSA_GET (area), -		  OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id); - -  /* Set router-LSA body fields. */ -  ospf_router_lsa_body_set (s, area); - -  /* Set length. */ -  length = stream_get_endp (s); -  lsah = (struct lsa_header *) STREAM_DATA (s); -  lsah->length = htons (length); - -  /* Now, create OSPF LSA instance. */ -  if ( (new = ospf_lsa_new ()) == NULL) -    { -      zlog_err ("%s: Unable to create new lsa", __func__); -      return NULL; -    } -   -  new->area = area; -  SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); - -  /* Copy LSA data to store, discard stream. */ -  new->data = ospf_lsa_data_new (length); -  memcpy (new->data, lsah, length); -  stream_free (s); - -  return new; +static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area) +{ +	struct ospf *ospf = area->ospf; +	struct stream *s; +	struct lsa_header *lsah; +	struct ospf_lsa *new; +	int length; + +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +		zlog_debug("LSA[Type1]: Create router-LSA instance"); + +	/* check whether stub-router is desired, and if this is the first +	 * router LSA. +	 */ +	ospf_stub_router_check(area); + +	/* Create a stream for LSA. */ +	s = stream_new(OSPF_MAX_LSA_SIZE); +	/* Set LSA common header fields. */ +	lsa_header_set(s, LSA_OPTIONS_GET(area) | LSA_OPTIONS_NSSA_GET(area), +		       OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id); + +	/* Set router-LSA body fields. */ +	ospf_router_lsa_body_set(s, area); + +	/* Set length. */ +	length = stream_get_endp(s); +	lsah = (struct lsa_header *)STREAM_DATA(s); +	lsah->length = htons(length); + +	/* Now, create OSPF LSA instance. */ +	if ((new = ospf_lsa_new()) == NULL) { +		zlog_err("%s: Unable to create new lsa", __func__); +		return NULL; +	} + +	new->area = area; +	SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); + +	/* Copy LSA data to store, discard stream. */ +	new->data = ospf_lsa_data_new(length); +	memcpy(new->data, lsah, length); +	stream_free(s); + +	return new;  }  /* Originate Router-LSA. */ -static struct ospf_lsa * -ospf_router_lsa_originate (struct ospf_area *area) +static struct ospf_lsa *ospf_router_lsa_originate(struct ospf_area *area)  { -  struct ospf_lsa *new; -   -  /* Create new router-LSA instance. */ -  if ( (new = ospf_router_lsa_new (area)) == NULL) -    { -      zlog_err ("%s: ospf_router_lsa_new returned NULL", __func__); -      return NULL; -    } +	struct ospf_lsa *new; -  /* Sanity check. */ -  if (new->data->adv_router.s_addr == 0) -    { -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug ("LSA[Type1]: AdvRouter is 0, discard"); -      ospf_lsa_discard (new); -      return NULL; -    } +	/* Create new router-LSA instance. */ +	if ((new = ospf_router_lsa_new(area)) == NULL) { +		zlog_err("%s: ospf_router_lsa_new returned NULL", __func__); +		return NULL; +	} + +	/* Sanity check. */ +	if (new->data->adv_router.s_addr == 0) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug("LSA[Type1]: AdvRouter is 0, discard"); +		ospf_lsa_discard(new); +		return NULL; +	} -  /* Install LSA to LSDB. */ -  new = ospf_lsa_install (area->ospf, NULL, new); +	/* Install LSA to LSDB. */ +	new = ospf_lsa_install(area->ospf, NULL, new); -  /* Update LSA origination count. */ -  area->ospf->lsa_originate_count++; +	/* Update LSA origination count. */ +	area->ospf->lsa_originate_count++; -  /* Flooding new LSA through area. */ -  ospf_flood_through_area (area, NULL, new); +	/* Flooding new LSA through area. */ +	ospf_flood_through_area(area, NULL, new); -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    { -      zlog_debug ("LSA[Type%d:%s]: Originate router-LSA %p", -		 new->data->type, inet_ntoa (new->data->id), (void *)new); -      ospf_lsa_header_dump (new->data); -    } +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +		zlog_debug("LSA[Type%d:%s]: Originate router-LSA %p", +			   new->data->type, inet_ntoa(new->data->id), +			   (void *)new); +		ospf_lsa_header_dump(new->data); +	} -  return new; +	return new;  }  /* Refresh router-LSA. */ -static struct ospf_lsa * -ospf_router_lsa_refresh (struct ospf_lsa *lsa) -{ -  struct ospf_area *area = lsa->area; -  struct ospf_lsa *new; - -  /* Sanity check. */ -  assert (lsa->data); +static struct ospf_lsa *ospf_router_lsa_refresh(struct ospf_lsa *lsa) +{ +	struct ospf_area *area = lsa->area; +	struct ospf_lsa *new; + +	/* Sanity check. */ +	assert(lsa->data); -  /* Delete LSA from neighbor retransmit-list. */ -  ospf_ls_retransmit_delete_nbr_area (area, lsa); +	/* Delete LSA from neighbor retransmit-list. */ +	ospf_ls_retransmit_delete_nbr_area(area, lsa); -  /* Unregister LSA from refresh-list */ -  ospf_refresher_unregister_lsa (area->ospf, lsa); -   -  /* Create new router-LSA instance. */ -  if ( (new = ospf_router_lsa_new (area)) == NULL) -    { -      zlog_err ("%s: ospf_router_lsa_new returned NULL", __func__); -      return NULL; -    } -   -  new->data->ls_seqnum = lsa_seqnum_increment (lsa); +	/* Unregister LSA from refresh-list */ +	ospf_refresher_unregister_lsa(area->ospf, lsa); -  ospf_lsa_install (area->ospf, NULL, new); +	/* Create new router-LSA instance. */ +	if ((new = ospf_router_lsa_new(area)) == NULL) { +		zlog_err("%s: ospf_router_lsa_new returned NULL", __func__); +		return NULL; +	} + +	new->data->ls_seqnum = lsa_seqnum_increment(lsa); -  /* Flood LSA through area. */ -  ospf_flood_through_area (area, NULL, new); +	ospf_lsa_install(area->ospf, NULL, new); -  /* Debug logging. */ -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    { -      zlog_debug ("LSA[Type%d:%s]: router-LSA refresh", -		 new->data->type, inet_ntoa (new->data->id)); -      ospf_lsa_header_dump (new->data); -    } +	/* Flood LSA through area. */ +	ospf_flood_through_area(area, NULL, new); + +	/* Debug logging. */ +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +		zlog_debug("LSA[Type%d:%s]: router-LSA refresh", +			   new->data->type, inet_ntoa(new->data->id)); +		ospf_lsa_header_dump(new->data); +	} -  return NULL; +	return NULL;  } -int -ospf_router_lsa_update_area (struct ospf_area *area) +int ospf_router_lsa_update_area(struct ospf_area *area)  { -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("[router-LSA]: (router-LSA area update)"); +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("[router-LSA]: (router-LSA area update)"); -  /* Now refresh router-LSA. */ -  if (area->router_lsa_self) -    ospf_lsa_refresh (area->ospf, area->router_lsa_self); -  /* Newly originate router-LSA. */ -  else -    ospf_router_lsa_originate (area); +	/* Now refresh router-LSA. */ +	if (area->router_lsa_self) +		ospf_lsa_refresh(area->ospf, area->router_lsa_self); +	/* Newly originate router-LSA. */ +	else +		ospf_router_lsa_originate(area); -  return 0; +	return 0;  } -int -ospf_router_lsa_update (struct ospf *ospf) +int ospf_router_lsa_update(struct ospf *ospf)  { -  struct listnode *node, *nnode; -  struct ospf_area *area; +	struct listnode *node, *nnode; +	struct ospf_area *area; -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    zlog_debug ("Timer[router-LSA Update]: (timer expire)"); +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +		zlog_debug("Timer[router-LSA Update]: (timer expire)"); -  for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) -    { -      struct ospf_lsa *lsa = area->router_lsa_self; -      struct router_lsa *rl; -      const char *area_str; +	for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { +		struct ospf_lsa *lsa = area->router_lsa_self; +		struct router_lsa *rl; +		const char *area_str; -      /* Keep Area ID string. */ -      area_str = AREA_NAME (area); +		/* Keep Area ID string. */ +		area_str = AREA_NAME(area); -      /* If LSA not exist in this Area, originate new. */ -      if (lsa == NULL) -        { -	  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -	    zlog_debug("LSA[Type1]: Create router-LSA for Area %s", area_str); +		/* If LSA not exist in this Area, originate new. */ +		if (lsa == NULL) { +			if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +				zlog_debug( +					"LSA[Type1]: Create router-LSA for Area %s", +					area_str); -	  ospf_router_lsa_originate (area); -        } -      /* If router-ID is changed, Link ID must change. -	 First flush old LSA, then originate new. */ -      else if (!IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id)) -	{ -	  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -	    zlog_debug("LSA[Type%d:%s]: Refresh router-LSA for Area %s", -		      lsa->data->type, inet_ntoa (lsa->data->id), area_str); -          ospf_refresher_unregister_lsa (ospf, lsa); -	  ospf_lsa_flush_area (lsa, area); -	  ospf_lsa_unlock (&area->router_lsa_self); -	  area->router_lsa_self = NULL; - -	  /* Refresh router-LSA, (not install) and flood through area. */ -	  ospf_router_lsa_update_area (area); -	} -      else -	{ -	  rl = (struct router_lsa *) lsa->data; -	  /* Refresh router-LSA, (not install) and flood through area. */ -	  if (rl->flags != ospf->flags) -	    ospf_router_lsa_update_area (area); +			ospf_router_lsa_originate(area); +		} +		/* If router-ID is changed, Link ID must change. +		   First flush old LSA, then originate new. */ +		else if (!IPV4_ADDR_SAME(&lsa->data->id, &ospf->router_id)) { +			if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +				zlog_debug( +					"LSA[Type%d:%s]: Refresh router-LSA for Area %s", +					lsa->data->type, +					inet_ntoa(lsa->data->id), area_str); +			ospf_refresher_unregister_lsa(ospf, lsa); +			ospf_lsa_flush_area(lsa, area); +			ospf_lsa_unlock(&area->router_lsa_self); +			area->router_lsa_self = NULL; + +			/* Refresh router-LSA, (not install) and flood through +			 * area. */ +			ospf_router_lsa_update_area(area); +		} else { +			rl = (struct router_lsa *)lsa->data; +			/* Refresh router-LSA, (not install) and flood through +			 * area. */ +			if (rl->flags != ospf->flags) +				ospf_router_lsa_update_area(area); +		}  	} -    } -  return 0; +	return 0;  }  /* network-LSA related functions. */  /* Originate Network-LSA. */ -static void -ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi) +static void ospf_network_lsa_body_set(struct stream *s, +				      struct ospf_interface *oi)  { -  struct in_addr mask; -  struct route_node *rn; -  struct ospf_neighbor *nbr; +	struct in_addr mask; +	struct route_node *rn; +	struct ospf_neighbor *nbr; -  masklen2ip (oi->address->prefixlen, &mask); -  stream_put_ipv4 (s, mask.s_addr); +	masklen2ip(oi->address->prefixlen, &mask); +	stream_put_ipv4(s, mask.s_addr); -  /* The network-LSA lists those routers that are fully adjacent to -    the Designated Router; each fully adjacent router is identified by -    its OSPF Router ID.  The Designated Router includes itself in this -    list. RFC2328, Section 12.4.2 */ +	/* The network-LSA lists those routers that are fully adjacent to +	  the Designated Router; each fully adjacent router is identified by +	  its OSPF Router ID.  The Designated Router includes itself in this +	  list. RFC2328, Section 12.4.2 */ -  for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) -    if ((nbr = rn->info) != NULL) -      if (nbr->state == NSM_Full || nbr == oi->nbr_self) -	stream_put_ipv4 (s, nbr->router_id.s_addr); +	for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) +		if ((nbr = rn->info) != NULL) +			if (nbr->state == NSM_Full || nbr == oi->nbr_self) +				stream_put_ipv4(s, nbr->router_id.s_addr);  } -static struct ospf_lsa * -ospf_network_lsa_new (struct ospf_interface *oi) -{ -  struct stream *s; -  struct ospf_lsa *new; -  struct lsa_header *lsah; -  struct ospf_if_params *oip; -  int length; - -  /* If there are no neighbours on this network (the net is stub), -     the router does not originate network-LSA (see RFC 12.4.2) */ -  if (oi->full_nbrs == 0) -    return NULL; -   -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    zlog_debug ("LSA[Type2]: Create network-LSA instance"); - -  /* Create new stream for LSA. */ -  s = stream_new (OSPF_MAX_LSA_SIZE); -  lsah = (struct lsa_header *) STREAM_DATA (s); - -  lsa_header_set (s, (OPTIONS (oi) | LSA_OPTIONS_GET (oi->area)), -		  OSPF_NETWORK_LSA, DR (oi), oi->ospf->router_id); - -  /* Set network-LSA body fields. */ -  ospf_network_lsa_body_set (s, oi); - -  /* Set length. */ -  length = stream_get_endp (s); -  lsah->length = htons (length); - -  /* Create OSPF LSA instance. */ -  if ( (new = ospf_lsa_new ()) == NULL) -    { -      zlog_err ("%s: ospf_lsa_new returned NULL", __func__); -      return NULL; -    } -   -  new->area = oi->area; -  SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); - -  /* Copy LSA to store. */ -  new->data = ospf_lsa_data_new (length); -  memcpy (new->data, lsah, length); -  stream_free (s); -   -  /* Remember prior network LSA sequence numbers, even if we stop -   * originating one for this oi, to try avoid re-originating LSAs with a -   * prior sequence number, and thus speed up adjency forming & convergence. -   */ -  if ((oip = ospf_lookup_if_params (oi->ifp, oi->address->u.prefix4))) -    { -      new->data->ls_seqnum = oip->network_lsa_seqnum; -      new->data->ls_seqnum = lsa_seqnum_increment (new); -    } -  else -    { -      oip = ospf_get_if_params (oi->ifp, oi->address->u.prefix4); -      ospf_if_update_params (oi->ifp, oi->address->u.prefix4); -    } -  oip->network_lsa_seqnum = new->data->ls_seqnum; -   -  return new; +static struct ospf_lsa *ospf_network_lsa_new(struct ospf_interface *oi) +{ +	struct stream *s; +	struct ospf_lsa *new; +	struct lsa_header *lsah; +	struct ospf_if_params *oip; +	int length; + +	/* If there are no neighbours on this network (the net is stub), +	   the router does not originate network-LSA (see RFC 12.4.2) */ +	if (oi->full_nbrs == 0) +		return NULL; + +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +		zlog_debug("LSA[Type2]: Create network-LSA instance"); + +	/* Create new stream for LSA. */ +	s = stream_new(OSPF_MAX_LSA_SIZE); +	lsah = (struct lsa_header *)STREAM_DATA(s); + +	lsa_header_set(s, (OPTIONS(oi) | LSA_OPTIONS_GET(oi->area)), +		       OSPF_NETWORK_LSA, DR(oi), oi->ospf->router_id); + +	/* Set network-LSA body fields. */ +	ospf_network_lsa_body_set(s, oi); + +	/* Set length. */ +	length = stream_get_endp(s); +	lsah->length = htons(length); + +	/* Create OSPF LSA instance. */ +	if ((new = ospf_lsa_new()) == NULL) { +		zlog_err("%s: ospf_lsa_new returned NULL", __func__); +		return NULL; +	} + +	new->area = oi->area; +	SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); + +	/* Copy LSA to store. */ +	new->data = ospf_lsa_data_new(length); +	memcpy(new->data, lsah, length); +	stream_free(s); + +	/* Remember prior network LSA sequence numbers, even if we stop +	 * originating one for this oi, to try avoid re-originating LSAs with a +	 * prior sequence number, and thus speed up adjency forming & +	 * convergence. +	 */ +	if ((oip = ospf_lookup_if_params(oi->ifp, oi->address->u.prefix4))) { +		new->data->ls_seqnum = oip->network_lsa_seqnum; +		new->data->ls_seqnum = lsa_seqnum_increment(new); +	} else { +		oip = ospf_get_if_params(oi->ifp, oi->address->u.prefix4); +		ospf_if_update_params(oi->ifp, oi->address->u.prefix4); +	} +	oip->network_lsa_seqnum = new->data->ls_seqnum; + +	return new;  }  /* Originate network-LSA. */ -void -ospf_network_lsa_update (struct ospf_interface *oi) +void ospf_network_lsa_update(struct ospf_interface *oi)  { -  struct ospf_lsa *new; -   -  if (oi->network_lsa_self != NULL) -    { -      ospf_lsa_refresh (oi->ospf, oi->network_lsa_self); -      return; -    } -   -  /* Create new network-LSA instance. */ -  new = ospf_network_lsa_new (oi); -  if (new == NULL) -    return; +	struct ospf_lsa *new; -  /* Install LSA to LSDB. */ -  new = ospf_lsa_install (oi->ospf, oi, new); +	if (oi->network_lsa_self != NULL) { +		ospf_lsa_refresh(oi->ospf, oi->network_lsa_self); +		return; +	} + +	/* Create new network-LSA instance. */ +	new = ospf_network_lsa_new(oi); +	if (new == NULL) +		return; -  /* Update LSA origination count. */ -  oi->ospf->lsa_originate_count++; +	/* Install LSA to LSDB. */ +	new = ospf_lsa_install(oi->ospf, oi, new); -  /* Flooding new LSA through area. */ -  ospf_flood_through_area (oi->area, NULL, new); +	/* Update LSA origination count. */ +	oi->ospf->lsa_originate_count++; -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    { -      zlog_debug ("LSA[Type%d:%s]: Originate network-LSA %p", -		 new->data->type, inet_ntoa (new->data->id), (void *)new); -      ospf_lsa_header_dump (new->data); -    } +	/* Flooding new LSA through area. */ +	ospf_flood_through_area(oi->area, NULL, new); + +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +		zlog_debug("LSA[Type%d:%s]: Originate network-LSA %p", +			   new->data->type, inet_ntoa(new->data->id), +			   (void *)new); +		ospf_lsa_header_dump(new->data); +	} -  return; +	return;  } -static struct ospf_lsa * -ospf_network_lsa_refresh (struct ospf_lsa *lsa) -{ -  struct ospf_area *area = lsa->area; -  struct ospf_lsa *new, *new2; -  struct ospf_if_params *oip; -  struct ospf_interface *oi; -   -  assert (lsa->data); -   -  /* Retrieve the oi for the network LSA */ -  oi = ospf_if_lookup_by_local_addr (area->ospf, NULL, lsa->data->id); -  if (oi == NULL) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        { -          zlog_debug ("LSA[Type%d:%s]: network-LSA refresh: " -                      "no oi found, ick, ignoring.", -		      lsa->data->type, inet_ntoa (lsa->data->id)); -          ospf_lsa_header_dump (lsa->data); -        } -      return NULL; -    } -  /* Delete LSA from neighbor retransmit-list. */ -  ospf_ls_retransmit_delete_nbr_area (area, lsa); - -  /* Unregister LSA from refresh-list */ -  ospf_refresher_unregister_lsa (area->ospf, lsa); -   -  /* Create new network-LSA instance. */ -  new = ospf_network_lsa_new (oi); -  if (new == NULL) -    return NULL; -   -  oip = ospf_lookup_if_params (oi->ifp, oi->address->u.prefix4); -  assert (oip != NULL); -  oip->network_lsa_seqnum = new->data->ls_seqnum = lsa_seqnum_increment (lsa); - -  new2 = ospf_lsa_install (area->ospf, oi, new); -   -  assert (new2 == new); -   -  /* Flood LSA through aera. */ -  ospf_flood_through_area (area, NULL, new); - -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    { -      zlog_debug ("LSA[Type%d:%s]: network-LSA refresh", -		 new->data->type, inet_ntoa (new->data->id)); -      ospf_lsa_header_dump (new->data); -    } - -  return new; -} - -static void -stream_put_ospf_metric (struct stream *s, u_int32_t metric_value) -{ -  u_int32_t metric; -  char *mp; - -  /* Put 0 metric. TOS metric is not supported. */ -  metric = htonl (metric_value); -  mp = (char *) &metric; -  mp++; -  stream_put (s, mp, 3); +static struct ospf_lsa *ospf_network_lsa_refresh(struct ospf_lsa *lsa) +{ +	struct ospf_area *area = lsa->area; +	struct ospf_lsa *new, *new2; +	struct ospf_if_params *oip; +	struct ospf_interface *oi; + +	assert(lsa->data); + +	/* Retrieve the oi for the network LSA */ +	oi = ospf_if_lookup_by_local_addr(area->ospf, NULL, lsa->data->id); +	if (oi == NULL) { +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +			zlog_debug( +				"LSA[Type%d:%s]: network-LSA refresh: " +				"no oi found, ick, ignoring.", +				lsa->data->type, inet_ntoa(lsa->data->id)); +			ospf_lsa_header_dump(lsa->data); +		} +		return NULL; +	} +	/* Delete LSA from neighbor retransmit-list. */ +	ospf_ls_retransmit_delete_nbr_area(area, lsa); + +	/* Unregister LSA from refresh-list */ +	ospf_refresher_unregister_lsa(area->ospf, lsa); + +	/* Create new network-LSA instance. */ +	new = ospf_network_lsa_new(oi); +	if (new == NULL) +		return NULL; + +	oip = ospf_lookup_if_params(oi->ifp, oi->address->u.prefix4); +	assert(oip != NULL); +	oip->network_lsa_seqnum = new->data->ls_seqnum = +		lsa_seqnum_increment(lsa); + +	new2 = ospf_lsa_install(area->ospf, oi, new); + +	assert(new2 == new); + +	/* Flood LSA through aera. */ +	ospf_flood_through_area(area, NULL, new); + +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +		zlog_debug("LSA[Type%d:%s]: network-LSA refresh", +			   new->data->type, inet_ntoa(new->data->id)); +		ospf_lsa_header_dump(new->data); +	} + +	return new; +} + +static void stream_put_ospf_metric(struct stream *s, u_int32_t metric_value) +{ +	u_int32_t metric; +	char *mp; + +	/* Put 0 metric. TOS metric is not supported. */ +	metric = htonl(metric_value); +	mp = (char *)&metric; +	mp++; +	stream_put(s, mp, 3);  }  /* summary-LSA related functions. */ -static void -ospf_summary_lsa_body_set (struct stream *s, struct prefix *p, -			   u_int32_t metric) +static void ospf_summary_lsa_body_set(struct stream *s, struct prefix *p, +				      u_int32_t metric)  { -  struct in_addr mask; +	struct in_addr mask; -  masklen2ip (p->prefixlen, &mask); +	masklen2ip(p->prefixlen, &mask); -  /* Put Network Mask. */ -  stream_put_ipv4 (s, mask.s_addr); +	/* Put Network Mask. */ +	stream_put_ipv4(s, mask.s_addr); -  /* Set # TOS. */ -  stream_putc (s, (u_char) 0); +	/* Set # TOS. */ +	stream_putc(s, (u_char)0); -  /* Set metric. */ -  stream_put_ospf_metric (s, metric); +	/* Set metric. */ +	stream_put_ospf_metric(s, metric);  } -static struct ospf_lsa * -ospf_summary_lsa_new (struct ospf_area *area, struct prefix *p, -		      u_int32_t metric, struct in_addr id) +static struct ospf_lsa *ospf_summary_lsa_new(struct ospf_area *area, +					     struct prefix *p, u_int32_t metric, +					     struct in_addr id)  { -  struct stream *s; -  struct ospf_lsa *new; -  struct lsa_header *lsah; -  int length; +	struct stream *s; +	struct ospf_lsa *new; +	struct lsa_header *lsah; +	int length; -  if (id.s_addr == 0xffffffff) -    { -      /* Maybe Link State ID not available. */ -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        zlog_debug ("LSA[Type%d]: Link ID not available, can't originate", -                    OSPF_SUMMARY_LSA); -      return NULL; -    } +	if (id.s_addr == 0xffffffff) { +		/* Maybe Link State ID not available. */ +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type%d]: Link ID not available, can't originate", +				OSPF_SUMMARY_LSA); +		return NULL; +	} -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    zlog_debug ("LSA[Type3]: Create summary-LSA instance"); +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +		zlog_debug("LSA[Type3]: Create summary-LSA instance"); -  /* Create new stream for LSA. */ -  s = stream_new (OSPF_MAX_LSA_SIZE); -  lsah = (struct lsa_header *) STREAM_DATA (s); +	/* Create new stream for LSA. */ +	s = stream_new(OSPF_MAX_LSA_SIZE); +	lsah = (struct lsa_header *)STREAM_DATA(s); -  lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_SUMMARY_LSA, -		  id, area->ospf->router_id); +	lsa_header_set(s, LSA_OPTIONS_GET(area), OSPF_SUMMARY_LSA, id, +		       area->ospf->router_id); -  /* Set summary-LSA body fields. */ -  ospf_summary_lsa_body_set (s, p, metric); +	/* Set summary-LSA body fields. */ +	ospf_summary_lsa_body_set(s, p, metric); -  /* Set length. */ -  length = stream_get_endp (s); -  lsah->length = htons (length); +	/* Set length. */ +	length = stream_get_endp(s); +	lsah->length = htons(length); -  /* Create OSPF LSA instance. */ -  new = ospf_lsa_new (); -  new->area = area; -  SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); +	/* Create OSPF LSA instance. */ +	new = ospf_lsa_new(); +	new->area = area; +	SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); -  /* Copy LSA to store. */ -  new->data = ospf_lsa_data_new (length); -  memcpy (new->data, lsah, length); -  stream_free (s); +	/* Copy LSA to store. */ +	new->data = ospf_lsa_data_new(length); +	memcpy(new->data, lsah, length); +	stream_free(s); -  return new; +	return new;  }  /* Originate Summary-LSA. */ -struct ospf_lsa * -ospf_summary_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,  -			    struct ospf_area *area) -{ -  struct ospf_lsa *new; -  struct in_addr id; -   -  id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p); - -  if (id.s_addr == 0xffffffff) -    { -      /* Maybe Link State ID not available. */ -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        zlog_debug ("LSA[Type%d]: Link ID not available, can't originate", -                    OSPF_SUMMARY_LSA); -      return NULL; -    } -   -  /* Create new summary-LSA instance. */ -  if ( !(new = ospf_summary_lsa_new (area, (struct prefix *) p, metric, id))) -    return NULL; - -  /* Instlal LSA to LSDB. */ -  new = ospf_lsa_install (area->ospf, NULL, new); - -  /* Update LSA origination count. */ -  area->ospf->lsa_originate_count++; - -  /* Flooding new LSA through area. */ -  ospf_flood_through_area (area, NULL, new); - -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    { -      zlog_debug ("LSA[Type%d:%s]: Originate summary-LSA %p", -		 new->data->type, inet_ntoa (new->data->id), (void *)new); -      ospf_lsa_header_dump (new->data); -    } - -  return new; -} - -static struct ospf_lsa* -ospf_summary_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa) -{ -  struct ospf_lsa *new; -  struct summary_lsa *sl; -  struct prefix p; -   -  /* Sanity check. */ -  assert (lsa->data); - -  sl = (struct summary_lsa *)lsa->data; -  p.prefixlen = ip_masklen (sl->mask); -  new = ospf_summary_lsa_new (lsa->area, &p, GET_METRIC (sl->metric), -			      sl->header.id); -   -  if (!new) -    return NULL; -   -  new->data->ls_seqnum = lsa_seqnum_increment (lsa); - -  ospf_lsa_install (ospf, NULL, new); -   -  /* Flood LSA through AS. */ -  ospf_flood_through_area (new->area, NULL, new); - -  /* Debug logging. */ -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    { -      zlog_debug ("LSA[Type%d:%s]: summary-LSA refresh", -		 new->data->type, inet_ntoa (new->data->id)); -      ospf_lsa_header_dump (new->data); -    } -   -  return new; +struct ospf_lsa *ospf_summary_lsa_originate(struct prefix_ipv4 *p, +					    u_int32_t metric, +					    struct ospf_area *area) +{ +	struct ospf_lsa *new; +	struct in_addr id; + +	id = ospf_lsa_unique_id(area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p); + +	if (id.s_addr == 0xffffffff) { +		/* Maybe Link State ID not available. */ +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type%d]: Link ID not available, can't originate", +				OSPF_SUMMARY_LSA); +		return NULL; +	} + +	/* Create new summary-LSA instance. */ +	if (!(new = ospf_summary_lsa_new(area, (struct prefix *)p, metric, id))) +		return NULL; + +	/* Instlal LSA to LSDB. */ +	new = ospf_lsa_install(area->ospf, NULL, new); + +	/* Update LSA origination count. */ +	area->ospf->lsa_originate_count++; + +	/* Flooding new LSA through area. */ +	ospf_flood_through_area(area, NULL, new); + +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +		zlog_debug("LSA[Type%d:%s]: Originate summary-LSA %p", +			   new->data->type, inet_ntoa(new->data->id), +			   (void *)new); +		ospf_lsa_header_dump(new->data); +	} + +	return new; +} + +static struct ospf_lsa *ospf_summary_lsa_refresh(struct ospf *ospf, +						 struct ospf_lsa *lsa) +{ +	struct ospf_lsa *new; +	struct summary_lsa *sl; +	struct prefix p; + +	/* Sanity check. */ +	assert(lsa->data); + +	sl = (struct summary_lsa *)lsa->data; +	p.prefixlen = ip_masklen(sl->mask); +	new = ospf_summary_lsa_new(lsa->area, &p, GET_METRIC(sl->metric), +				   sl->header.id); + +	if (!new) +		return NULL; + +	new->data->ls_seqnum = lsa_seqnum_increment(lsa); + +	ospf_lsa_install(ospf, NULL, new); + +	/* Flood LSA through AS. */ +	ospf_flood_through_area(new->area, NULL, new); + +	/* Debug logging. */ +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +		zlog_debug("LSA[Type%d:%s]: summary-LSA refresh", +			   new->data->type, inet_ntoa(new->data->id)); +		ospf_lsa_header_dump(new->data); +	} + +	return new;  }  /* summary-ASBR-LSA related functions. */ -static void -ospf_summary_asbr_lsa_body_set (struct stream *s, struct prefix *p, -				u_int32_t metric) +static void ospf_summary_asbr_lsa_body_set(struct stream *s, struct prefix *p, +					   u_int32_t metric)  { -  /* Put Network Mask. */ -  stream_put_ipv4 (s, (u_int32_t) 0); +	/* Put Network Mask. */ +	stream_put_ipv4(s, (u_int32_t)0); -  /* Set # TOS. */ -  stream_putc (s, (u_char) 0); +	/* Set # TOS. */ +	stream_putc(s, (u_char)0); -  /* Set metric. */ -  stream_put_ospf_metric (s, metric); +	/* Set metric. */ +	stream_put_ospf_metric(s, metric);  } -static struct ospf_lsa * -ospf_summary_asbr_lsa_new (struct ospf_area *area, struct prefix *p, -			   u_int32_t metric, struct in_addr id) +static struct ospf_lsa *ospf_summary_asbr_lsa_new(struct ospf_area *area, +						  struct prefix *p, +						  u_int32_t metric, +						  struct in_addr id)  { -  struct stream *s; -  struct ospf_lsa *new; -  struct lsa_header *lsah; -  int length; +	struct stream *s; +	struct ospf_lsa *new; +	struct lsa_header *lsah; +	int length; -  if (id.s_addr == 0xffffffff) -    { -      /* Maybe Link State ID not available. */ -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        zlog_debug ("LSA[Type%d]: Link ID not available, can't originate", -                    OSPF_ASBR_SUMMARY_LSA); -      return NULL; -    } +	if (id.s_addr == 0xffffffff) { +		/* Maybe Link State ID not available. */ +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type%d]: Link ID not available, can't originate", +				OSPF_ASBR_SUMMARY_LSA); +		return NULL; +	} -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    zlog_debug ("LSA[Type3]: Create summary-LSA instance"); +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +		zlog_debug("LSA[Type3]: Create summary-LSA instance"); -  /* Create new stream for LSA. */ -  s = stream_new (OSPF_MAX_LSA_SIZE); -  lsah = (struct lsa_header *) STREAM_DATA (s); +	/* Create new stream for LSA. */ +	s = stream_new(OSPF_MAX_LSA_SIZE); +	lsah = (struct lsa_header *)STREAM_DATA(s); -  lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_ASBR_SUMMARY_LSA, -		  id, area->ospf->router_id); +	lsa_header_set(s, LSA_OPTIONS_GET(area), OSPF_ASBR_SUMMARY_LSA, id, +		       area->ospf->router_id); -  /* Set summary-LSA body fields. */ -  ospf_summary_asbr_lsa_body_set (s, p, metric); +	/* Set summary-LSA body fields. */ +	ospf_summary_asbr_lsa_body_set(s, p, metric); -  /* Set length. */ -  length = stream_get_endp (s); -  lsah->length = htons (length); +	/* Set length. */ +	length = stream_get_endp(s); +	lsah->length = htons(length); -  /* Create OSPF LSA instance. */ -  new = ospf_lsa_new (); -  new->area = area; -  SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); +	/* Create OSPF LSA instance. */ +	new = ospf_lsa_new(); +	new->area = area; +	SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); -  /* Copy LSA to store. */ -  new->data = ospf_lsa_data_new (length); -  memcpy (new->data, lsah, length); -  stream_free (s); +	/* Copy LSA to store. */ +	new->data = ospf_lsa_data_new(length); +	memcpy(new->data, lsah, length); +	stream_free(s); -  return new; +	return new;  }  /* Originate summary-ASBR-LSA. */ -struct ospf_lsa * -ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,  -				 struct ospf_area *area) -{ -  struct ospf_lsa *new; -  struct in_addr id; -   -  id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA, p); - -  if (id.s_addr == 0xffffffff) -    { -      /* Maybe Link State ID not available. */ -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        zlog_debug ("LSA[Type%d]: Link ID not available, can't originate", -                    OSPF_ASBR_SUMMARY_LSA); -      return NULL; -    } -   -  /* Create new summary-LSA instance. */ -  new = ospf_summary_asbr_lsa_new (area, (struct prefix *) p, metric, id); -  if (!new) -    return NULL; - -  /* Install LSA to LSDB. */ -  new = ospf_lsa_install (area->ospf, NULL, new); -   -  /* Update LSA origination count. */ -  area->ospf->lsa_originate_count++; - -  /* Flooding new LSA through area. */ -  ospf_flood_through_area (area, NULL, new); - -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    { -      zlog_debug ("LSA[Type%d:%s]: Originate summary-ASBR-LSA %p", -		 new->data->type, inet_ntoa (new->data->id), (void *)new); -      ospf_lsa_header_dump (new->data); -    } - -  return new; -} - -static struct ospf_lsa* -ospf_summary_asbr_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa) -{ -  struct ospf_lsa *new; -  struct summary_lsa *sl; -  struct prefix p; - -  /* Sanity check. */ -  assert (lsa->data); - -  sl = (struct summary_lsa *)lsa->data; -  p.prefixlen = ip_masklen (sl->mask); -  new = ospf_summary_asbr_lsa_new (lsa->area, &p, GET_METRIC (sl->metric), -				   sl->header.id); -  if (!new) -    return NULL; -   -  new->data->ls_seqnum = lsa_seqnum_increment (lsa); +struct ospf_lsa *ospf_summary_asbr_lsa_originate(struct prefix_ipv4 *p, +						 u_int32_t metric, +						 struct ospf_area *area) +{ +	struct ospf_lsa *new; +	struct in_addr id; + +	id = ospf_lsa_unique_id(area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA, +				p); + +	if (id.s_addr == 0xffffffff) { +		/* Maybe Link State ID not available. */ +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type%d]: Link ID not available, can't originate", +				OSPF_ASBR_SUMMARY_LSA); +		return NULL; +	} + +	/* Create new summary-LSA instance. */ +	new = ospf_summary_asbr_lsa_new(area, (struct prefix *)p, metric, id); +	if (!new) +		return NULL; + +	/* Install LSA to LSDB. */ +	new = ospf_lsa_install(area->ospf, NULL, new); -  ospf_lsa_install (ospf, NULL, new); -   -  /* Flood LSA through area. */ -  ospf_flood_through_area (new->area, NULL, new); +	/* Update LSA origination count. */ +	area->ospf->lsa_originate_count++; -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    { -      zlog_debug ("LSA[Type%d:%s]: summary-ASBR-LSA refresh", -		 new->data->type, inet_ntoa (new->data->id)); -      ospf_lsa_header_dump (new->data); -    } +	/* Flooding new LSA through area. */ +	ospf_flood_through_area(area, NULL, new); -  return new; +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +		zlog_debug("LSA[Type%d:%s]: Originate summary-ASBR-LSA %p", +			   new->data->type, inet_ntoa(new->data->id), +			   (void *)new); +		ospf_lsa_header_dump(new->data); +	} + +	return new; +} + +static struct ospf_lsa *ospf_summary_asbr_lsa_refresh(struct ospf *ospf, +						      struct ospf_lsa *lsa) +{ +	struct ospf_lsa *new; +	struct summary_lsa *sl; +	struct prefix p; + +	/* Sanity check. */ +	assert(lsa->data); + +	sl = (struct summary_lsa *)lsa->data; +	p.prefixlen = ip_masklen(sl->mask); +	new = ospf_summary_asbr_lsa_new(lsa->area, &p, GET_METRIC(sl->metric), +					sl->header.id); +	if (!new) +		return NULL; + +	new->data->ls_seqnum = lsa_seqnum_increment(lsa); + +	ospf_lsa_install(ospf, NULL, new); + +	/* Flood LSA through area. */ +	ospf_flood_through_area(new->area, NULL, new); + +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +		zlog_debug("LSA[Type%d:%s]: summary-ASBR-LSA refresh", +			   new->data->type, inet_ntoa(new->data->id)); +		ospf_lsa_header_dump(new->data); +	} + +	return new;  }  /* AS-external-LSA related functions. */  /* Get nexthop for AS-external-LSAs.  Return nexthop if its interface     is connected, else 0*/ -static struct in_addr -ospf_external_lsa_nexthop_get (struct ospf *ospf, struct in_addr nexthop) +static struct in_addr ospf_external_lsa_nexthop_get(struct ospf *ospf, +						    struct in_addr nexthop)  { -  struct in_addr fwd; -  struct prefix nh; -  struct listnode *node; -  struct ospf_interface *oi; +	struct in_addr fwd; +	struct prefix nh; +	struct listnode *node; +	struct ospf_interface *oi; + +	fwd.s_addr = 0; -  fwd.s_addr = 0; +	if (!nexthop.s_addr) +		return fwd; -  if (!nexthop.s_addr) -    return fwd; +	/* Check whether nexthop is covered by OSPF network. */ +	nh.family = AF_INET; +	nh.u.prefix4 = nexthop; +	nh.prefixlen = IPV4_MAX_BITLEN; -  /* Check whether nexthop is covered by OSPF network. */ -  nh.family = AF_INET; -  nh.u.prefix4 = nexthop; -  nh.prefixlen = IPV4_MAX_BITLEN; -   -  /* XXX/SCALE: If there were a lot of oi's on an ifp, then it'd be -   * better to make use of the per-ifp table of ois. -   */ -  for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) -    if (if_is_operative (oi->ifp)) -      if (oi->address->family == AF_INET) -        if (prefix_match (oi->address, &nh)) -          return nexthop; +	/* XXX/SCALE: If there were a lot of oi's on an ifp, then it'd be +	 * better to make use of the per-ifp table of ois. +	 */ +	for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) +		if (if_is_operative(oi->ifp)) +			if (oi->address->family == AF_INET) +				if (prefix_match(oi->address, &nh)) +					return nexthop; -  return fwd; +	return fwd;  }  /* NSSA-external-LSA related functions. */  /* Get 1st IP connection for Forward Addr */ -struct in_addr -ospf_get_ip_from_ifp (struct ospf_interface *oi) +struct in_addr ospf_get_ip_from_ifp(struct ospf_interface *oi)  { -  struct in_addr fwd; +	struct in_addr fwd; -  fwd.s_addr = 0; +	fwd.s_addr = 0; -  if (if_is_operative (oi->ifp)) -    return oi->address->u.prefix4; -   -  return fwd; +	if (if_is_operative(oi->ifp)) +		return oi->address->u.prefix4; + +	return fwd;  }  /* Get 1st IP connection for Forward Addr */ -struct in_addr -ospf_get_nssa_ip (struct ospf_area *area) -{ -  struct in_addr fwd; -  struct in_addr best_default; -  struct listnode *node; -  struct ospf_interface *oi; - -  fwd.s_addr = 0; -  best_default.s_addr = 0; - -  for (ALL_LIST_ELEMENTS_RO (area->ospf->oiflist, node, oi)) -    { -      if (if_is_operative (oi->ifp)) -	if (oi->area->external_routing == OSPF_AREA_NSSA) -	  if (oi->address && oi->address->family == AF_INET) -	    { -	      if (best_default.s_addr == 0) -		best_default = oi->address->u.prefix4; -	      if (oi->area == area) -		return oi->address->u.prefix4; -	    } -    } -  if (best_default.s_addr != 0) -    return best_default; +struct in_addr ospf_get_nssa_ip(struct ospf_area *area) +{ +	struct in_addr fwd; +	struct in_addr best_default; +	struct listnode *node; +	struct ospf_interface *oi; + +	fwd.s_addr = 0; +	best_default.s_addr = 0; + +	for (ALL_LIST_ELEMENTS_RO(area->ospf->oiflist, node, oi)) { +		if (if_is_operative(oi->ifp)) +			if (oi->area->external_routing == OSPF_AREA_NSSA) +				if (oi->address +				    && oi->address->family == AF_INET) { +					if (best_default.s_addr == 0) +						best_default = +							oi->address->u.prefix4; +					if (oi->area == area) +						return oi->address->u.prefix4; +				} +	} +	if (best_default.s_addr != 0) +		return best_default; -  if (best_default.s_addr != 0) -    return best_default; +	if (best_default.s_addr != 0) +		return best_default; -  return fwd; +	return fwd;  }  #define DEFAULT_DEFAULT_METRIC	             20 @@ -1536,841 +1495,840 @@ ospf_get_nssa_ip (struct ospf_area *area)  #define DEFAULT_METRIC_TYPE		     EXTERNAL_METRIC_TYPE_2 -int -metric_type (struct ospf *ospf, u_char src, u_short instance) +int metric_type(struct ospf *ospf, u_char src, u_short instance)  { -  struct ospf_redist *red; +	struct ospf_redist *red; -  red = ospf_redist_lookup(ospf, src, instance); +	red = ospf_redist_lookup(ospf, src, instance); -  return ((!red || red->dmetric.type < 0) ? -	  DEFAULT_METRIC_TYPE : red->dmetric.type); +	return ((!red || red->dmetric.type < 0) ? DEFAULT_METRIC_TYPE +						: red->dmetric.type);  } -int -metric_value (struct ospf *ospf, u_char src, u_short instance) +int metric_value(struct ospf *ospf, u_char src, u_short instance)  { -  struct ospf_redist *red; +	struct ospf_redist *red; -  red = ospf_redist_lookup(ospf, src, instance); -  if (!red || red->dmetric.value < 0) -    { -      if (src == DEFAULT_ROUTE) -	{ -	  if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA) -	    return DEFAULT_DEFAULT_ORIGINATE_METRIC; -	  else -	    return DEFAULT_DEFAULT_ALWAYS_METRIC; +	red = ospf_redist_lookup(ospf, src, instance); +	if (!red || red->dmetric.value < 0) { +		if (src == DEFAULT_ROUTE) { +			if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA) +				return DEFAULT_DEFAULT_ORIGINATE_METRIC; +			else +				return DEFAULT_DEFAULT_ALWAYS_METRIC; +		} else if (ospf->default_metric < 0) +			return DEFAULT_DEFAULT_METRIC; +		else +			return ospf->default_metric;  	} -      else if (ospf->default_metric < 0) -	return DEFAULT_DEFAULT_METRIC; -      else -	return ospf->default_metric; -    } -  return red->dmetric.value; +	return red->dmetric.value;  }  /* Set AS-external-LSA body. */ -static void -ospf_external_lsa_body_set (struct stream *s, struct external_info *ei, -			    struct ospf *ospf) -{ -  struct prefix_ipv4 *p = &ei->p; -  struct in_addr mask, fwd_addr; -  u_int32_t mvalue; -  int mtype; -  int type; -  u_short instance; - -  /* Put Network Mask. */ -  masklen2ip (p->prefixlen, &mask); -  stream_put_ipv4 (s, mask.s_addr); - -  /* If prefix is default, specify DEFAULT_ROUTE. */ -  type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type; -  instance = is_prefix_default (&ei->p) ? 0 : ei->instance; -   -  mtype = (ROUTEMAP_METRIC_TYPE (ei) != -1) ? -    ROUTEMAP_METRIC_TYPE (ei) : metric_type (ospf, type, instance); - -  mvalue = (ROUTEMAP_METRIC (ei) != -1) ? -    ROUTEMAP_METRIC (ei) : metric_value (ospf, type, instance); - -  /* Put type of external metric. */ -  stream_putc (s, (mtype == EXTERNAL_METRIC_TYPE_2 ? 0x80 : 0)); - -  /* Put 0 metric. TOS metric is not supported. */ -  stream_put_ospf_metric (s, mvalue); -   -  /* Get forwarding address to nexthop if on the Connection List, else 0. */ -  fwd_addr = ospf_external_lsa_nexthop_get (ospf, ei->nexthop); - -  /* Put forwarding address. */ -  stream_put_ipv4 (s, fwd_addr.s_addr); -   -  /* Put route tag */ -  stream_putl (s, ei->tag); +static void ospf_external_lsa_body_set(struct stream *s, +				       struct external_info *ei, +				       struct ospf *ospf) +{ +	struct prefix_ipv4 *p = &ei->p; +	struct in_addr mask, fwd_addr; +	u_int32_t mvalue; +	int mtype; +	int type; +	u_short instance; + +	/* Put Network Mask. */ +	masklen2ip(p->prefixlen, &mask); +	stream_put_ipv4(s, mask.s_addr); + +	/* If prefix is default, specify DEFAULT_ROUTE. */ +	type = is_prefix_default(&ei->p) ? DEFAULT_ROUTE : ei->type; +	instance = is_prefix_default(&ei->p) ? 0 : ei->instance; + +	mtype = (ROUTEMAP_METRIC_TYPE(ei) != -1) +			? ROUTEMAP_METRIC_TYPE(ei) +			: metric_type(ospf, type, instance); + +	mvalue = (ROUTEMAP_METRIC(ei) != -1) +			 ? ROUTEMAP_METRIC(ei) +			 : metric_value(ospf, type, instance); + +	/* Put type of external metric. */ +	stream_putc(s, (mtype == EXTERNAL_METRIC_TYPE_2 ? 0x80 : 0)); + +	/* Put 0 metric. TOS metric is not supported. */ +	stream_put_ospf_metric(s, mvalue); + +	/* Get forwarding address to nexthop if on the Connection List, else 0. +	 */ +	fwd_addr = ospf_external_lsa_nexthop_get(ospf, ei->nexthop); + +	/* Put forwarding address. */ +	stream_put_ipv4(s, fwd_addr.s_addr); + +	/* Put route tag */ +	stream_putl(s, ei->tag);  }  /* Create new external-LSA. */ -static struct ospf_lsa * -ospf_external_lsa_new (struct ospf *ospf, -		       struct external_info *ei, struct in_addr *old_id) -{ -  struct stream *s; -  struct lsa_header *lsah; -  struct ospf_lsa *new; -  struct in_addr id; -  int length; - -  if (ei == NULL) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -	zlog_debug ("LSA[Type5]: External info is NULL, can't originate"); -      return NULL; -    } - -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    zlog_debug ("LSA[Type5]: Originate AS-external-LSA instance"); - -  /* If old Link State ID is specified, refresh LSA with same ID. */ -  if (old_id) -    id = *old_id; -  /* Get Link State with unique ID. */ -  else -    { -      id = ospf_lsa_unique_id (ospf, ospf->lsdb, OSPF_AS_EXTERNAL_LSA, &ei->p); -      if (id.s_addr == 0xffffffff) -	{ -	  /* Maybe Link State ID not available. */ -	  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -	    zlog_debug ("LSA[Type5]: Link ID not available, can't originate"); -	  return NULL; -	} -    } - -  /* Create new stream for LSA. */ -  s = stream_new (OSPF_MAX_LSA_SIZE); -  lsah = (struct lsa_header *) STREAM_DATA (s); - -  /* Set LSA common header fields. */ -  lsa_header_set (s, OSPF_OPTION_E, OSPF_AS_EXTERNAL_LSA, -		  id, ospf->router_id); - -  /* Set AS-external-LSA body fields. */ -  ospf_external_lsa_body_set (s, ei, ospf); - -  /* Set length. */ -  length = stream_get_endp (s); -  lsah->length = htons (length); - -  /* Now, create OSPF LSA instance. */ -  new = ospf_lsa_new (); -  new->area = NULL; -  SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED); - -  /* Copy LSA data to store, discard stream. */ -  new->data = ospf_lsa_data_new (length); -  memcpy (new->data, lsah, length); -  stream_free (s); - -  return new; +static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf, +					      struct external_info *ei, +					      struct in_addr *old_id) +{ +	struct stream *s; +	struct lsa_header *lsah; +	struct ospf_lsa *new; +	struct in_addr id; +	int length; + +	if (ei == NULL) { +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type5]: External info is NULL, can't originate"); +		return NULL; +	} + +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +		zlog_debug("LSA[Type5]: Originate AS-external-LSA instance"); + +	/* If old Link State ID is specified, refresh LSA with same ID. */ +	if (old_id) +		id = *old_id; +	/* Get Link State with unique ID. */ +	else { +		id = ospf_lsa_unique_id(ospf, ospf->lsdb, OSPF_AS_EXTERNAL_LSA, +					&ei->p); +		if (id.s_addr == 0xffffffff) { +			/* Maybe Link State ID not available. */ +			if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +				zlog_debug( +					"LSA[Type5]: Link ID not available, can't originate"); +			return NULL; +		} +	} + +	/* Create new stream for LSA. */ +	s = stream_new(OSPF_MAX_LSA_SIZE); +	lsah = (struct lsa_header *)STREAM_DATA(s); + +	/* Set LSA common header fields. */ +	lsa_header_set(s, OSPF_OPTION_E, OSPF_AS_EXTERNAL_LSA, id, +		       ospf->router_id); + +	/* Set AS-external-LSA body fields. */ +	ospf_external_lsa_body_set(s, ei, ospf); + +	/* Set length. */ +	length = stream_get_endp(s); +	lsah->length = htons(length); + +	/* Now, create OSPF LSA instance. */ +	new = ospf_lsa_new(); +	new->area = NULL; +	SET_FLAG(new->flags, +		 OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED); + +	/* Copy LSA data to store, discard stream. */ +	new->data = ospf_lsa_data_new(length); +	memcpy(new->data, lsah, length); +	stream_free(s); + +	return new;  }  /* As Type-7 */ -static void -ospf_install_flood_nssa (struct ospf *ospf,  -			 struct ospf_lsa *lsa, struct external_info *ei) -{ -  struct ospf_lsa *new; -  struct as_external_lsa *extlsa; -  struct ospf_area *area; -  struct listnode *node, *nnode; - -  /* LSA may be a Type-5 originated via translation of a Type-7 LSA -   * which originated from an NSSA area. In which case it should not be  -   * flooded back to NSSA areas. -   */ -  if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) -    return; -     -  /* NSSA Originate or Refresh (If anyNSSA) - -  LSA is self-originated. And just installed as Type-5. -  Additionally, install as Type-7 LSDB for every attached NSSA. - -  P-Bit controls which ABR performs translation to outside world; If -  we are an ABR....do not set the P-bit, because we send the Type-5, -  not as the ABR Translator, but as the ASBR owner within the AS! - -  If we are NOT ABR, Flood through NSSA as Type-7 w/P-bit set.  The -  elected ABR Translator will see the P-bit, Translate, and re-flood. - -  Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to -  Type-5's to non-NSSA Areas.  (it will also attempt a re-install) */ - -  for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) -    { -      /* Don't install Type-7 LSA's into nonNSSA area */ -      if (area->external_routing != OSPF_AREA_NSSA) -        continue; - -      /* make lsa duplicate, lock=1 */ -      new = ospf_lsa_dup (lsa); -      new->area = area; -      new->data->type = OSPF_AS_NSSA_LSA; - -      /* set P-bit if not ABR */ -      if (! IS_OSPF_ABR (ospf)) -        { -	  SET_FLAG(new->data->options, OSPF_OPTION_NP); -        -	  /* set non-zero FWD ADDR -        -	  draft-ietf-ospf-nssa-update-09.txt -        -	  if the network between the NSSA AS boundary router and the -	  adjacent AS is advertised into OSPF as an internal OSPF route, -	  the forwarding address should be the next op address as is cu -	  currently done with type-5 LSAs.  If the intervening network is -	  not adversited into OSPF as an internal OSPF route and the -	  type-7 LSA's P-bit is set a forwarding address should be -	  selected from one of the router's active OSPF inteface addresses -	  which belong to the NSSA.  If no such addresses exist, then -	  no type-7 LSA's with the P-bit set should originate from this -	  router.   */ -        -	  /* kevinm: not updating lsa anymore, just new */ -	  extlsa = (struct as_external_lsa *)(new->data); -        -	  if (extlsa->e[0].fwd_addr.s_addr == 0) -	    extlsa->e[0].fwd_addr = ospf_get_nssa_ip(area); /* this NSSA area in ifp */ - -	  if (extlsa->e[0].fwd_addr.s_addr == 0)  -	  { -	    if (IS_DEBUG_OSPF_NSSA) -	      zlog_debug ("LSA[Type-7]: Could not build FWD-ADDR"); -	    ospf_lsa_discard (new); -	    return; -	  } -	} - -      /* install also as Type-7 */ -      ospf_lsa_install (ospf, NULL, new);   /* Remove Old, Lock New = 2 */ - -      /* will send each copy, lock=2+n */ -      ospf_flood_through_as (ospf, NULL, new); /* all attached NSSA's, no AS/STUBs */ -    } +static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa, +				    struct external_info *ei) +{ +	struct ospf_lsa *new; +	struct as_external_lsa *extlsa; +	struct ospf_area *area; +	struct listnode *node, *nnode; + +	/* LSA may be a Type-5 originated via translation of a Type-7 LSA +	 * which originated from an NSSA area. In which case it should not be +	 * flooded back to NSSA areas. +	 */ +	if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) +		return; + +	/* NSSA Originate or Refresh (If anyNSSA) + +	LSA is self-originated. And just installed as Type-5. +	Additionally, install as Type-7 LSDB for every attached NSSA. + +	P-Bit controls which ABR performs translation to outside world; If +	we are an ABR....do not set the P-bit, because we send the Type-5, +	not as the ABR Translator, but as the ASBR owner within the AS! + +	If we are NOT ABR, Flood through NSSA as Type-7 w/P-bit set.  The +	elected ABR Translator will see the P-bit, Translate, and re-flood. + +	Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to +	Type-5's to non-NSSA Areas.  (it will also attempt a re-install) */ + +	for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { +		/* Don't install Type-7 LSA's into nonNSSA area */ +		if (area->external_routing != OSPF_AREA_NSSA) +			continue; + +		/* make lsa duplicate, lock=1 */ +		new = ospf_lsa_dup(lsa); +		new->area = area; +		new->data->type = OSPF_AS_NSSA_LSA; + +		/* set P-bit if not ABR */ +		if (!IS_OSPF_ABR(ospf)) { +			SET_FLAG(new->data->options, OSPF_OPTION_NP); + +			/* set non-zero FWD ADDR + +			draft-ietf-ospf-nssa-update-09.txt + +			if the network between the NSSA AS boundary router and +			the +			adjacent AS is advertised into OSPF as an internal OSPF +			route, +			the forwarding address should be the next op address as +			is cu +			currently done with type-5 LSAs.  If the intervening +			network is +			not adversited into OSPF as an internal OSPF route and +			the +			type-7 LSA's P-bit is set a forwarding address should be +			selected from one of the router's active OSPF inteface +			addresses +			which belong to the NSSA.  If no such addresses exist, +			then +			no type-7 LSA's with the P-bit set should originate from +			this +			router.   */ + +			/* kevinm: not updating lsa anymore, just new */ +			extlsa = (struct as_external_lsa *)(new->data); + +			if (extlsa->e[0].fwd_addr.s_addr == 0) +				extlsa->e[0].fwd_addr = ospf_get_nssa_ip( +					area); /* this NSSA area in ifp */ + +			if (extlsa->e[0].fwd_addr.s_addr == 0) { +				if (IS_DEBUG_OSPF_NSSA) +					zlog_debug( +						"LSA[Type-7]: Could not build FWD-ADDR"); +				ospf_lsa_discard(new); +				return; +			} +		} + +		/* install also as Type-7 */ +		ospf_lsa_install(ospf, NULL, +				 new); /* Remove Old, Lock New = 2 */ + +		/* will send each copy, lock=2+n */ +		ospf_flood_through_as( +			ospf, NULL, new); /* all attached NSSA's, no AS/STUBs */ +	}  } -static struct ospf_lsa * -ospf_lsa_translated_nssa_new (struct ospf *ospf,  -                             struct ospf_lsa *type7) -{ - -  struct ospf_lsa *new; -  struct as_external_lsa *ext, *extnew; -  struct external_info ei; -   -  ext = (struct as_external_lsa *)(type7->data); - -  /* need external_info struct, fill in bare minimum */   -  ei.p.family = AF_INET; -  ei.p.prefix = type7->data->id; -  ei.p.prefixlen = ip_masklen (ext->mask); -  ei.type = ZEBRA_ROUTE_OSPF; -  ei.nexthop = ext->header.adv_router; -  ei.route_map_set.metric = -1; -  ei.route_map_set.metric_type = -1; -  ei.tag = 0; -   -  if ( (new = ospf_external_lsa_new (ospf, &ei, &type7->data->id)) == NULL) -  { -    if (IS_DEBUG_OSPF_NSSA) -      zlog_debug ("ospf_nssa_translate_originate(): Could not originate " -                 "Translated Type-5 for %s",  -                 inet_ntoa (ei.p.prefix)); -    return NULL; -  } - -  extnew = (struct as_external_lsa *)(new->data); -    -  /* copy over Type-7 data to new */ -  extnew->e[0].tos = ext->e[0].tos; -  extnew->e[0].route_tag = ext->e[0].route_tag; -  extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr; -  new->data->ls_seqnum = type7->data->ls_seqnum; - -  /* add translated flag, checksum and lock new lsa */ -  SET_FLAG (new->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7  */    -  new = ospf_lsa_lock (new); -   -  return new;  +static struct ospf_lsa *ospf_lsa_translated_nssa_new(struct ospf *ospf, +						     struct ospf_lsa *type7) +{ + +	struct ospf_lsa *new; +	struct as_external_lsa *ext, *extnew; +	struct external_info ei; + +	ext = (struct as_external_lsa *)(type7->data); + +	/* need external_info struct, fill in bare minimum */ +	ei.p.family = AF_INET; +	ei.p.prefix = type7->data->id; +	ei.p.prefixlen = ip_masklen(ext->mask); +	ei.type = ZEBRA_ROUTE_OSPF; +	ei.nexthop = ext->header.adv_router; +	ei.route_map_set.metric = -1; +	ei.route_map_set.metric_type = -1; +	ei.tag = 0; + +	if ((new = ospf_external_lsa_new(ospf, &ei, &type7->data->id)) +	    == NULL) { +		if (IS_DEBUG_OSPF_NSSA) +			zlog_debug( +				"ospf_nssa_translate_originate(): Could not originate " +				"Translated Type-5 for %s", +				inet_ntoa(ei.p.prefix)); +		return NULL; +	} + +	extnew = (struct as_external_lsa *)(new->data); + +	/* copy over Type-7 data to new */ +	extnew->e[0].tos = ext->e[0].tos; +	extnew->e[0].route_tag = ext->e[0].route_tag; +	extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr; +	new->data->ls_seqnum = type7->data->ls_seqnum; + +	/* add translated flag, checksum and lock new lsa */ +	SET_FLAG(new->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7  */ +	new = ospf_lsa_lock(new); + +	return new;  }  /* Originate Translated Type-5 for supplied Type-7 NSSA LSA */ -struct ospf_lsa * -ospf_translated_nssa_originate (struct ospf *ospf, struct ospf_lsa *type7) -{ -  struct ospf_lsa *new; -  struct as_external_lsa *extnew; -   -  /* we cant use ospf_external_lsa_originate() as we need to set -   * the OSPF_LSA_LOCAL_XLT flag, must originate by hand -   */ -   -  if ( (new = ospf_lsa_translated_nssa_new (ospf, type7)) == NULL) -    { -      if (IS_DEBUG_OSPF_NSSA) -        zlog_debug ("ospf_translated_nssa_originate(): Could not translate " -                 "Type-7, Id %s, to Type-5", -                 inet_ntoa (type7->data->id)); -      return NULL; -    } -     -  extnew = (struct as_external_lsa *)new; -   -  if (IS_DEBUG_OSPF_NSSA) -    { -      zlog_debug ("ospf_translated_nssa_originate(): " -                 "translated Type 7, installed:"); -      ospf_lsa_header_dump (new->data); -      zlog_debug ("   Network mask: %d",ip_masklen (extnew->mask)); -      zlog_debug ("   Forward addr: %s", inet_ntoa (extnew->e[0].fwd_addr)); -    } -   -  if ( (new = ospf_lsa_install (ospf, NULL, new)) == NULL) -    { -      if (IS_DEBUG_OSPF_NSSA) -        zlog_debug ("ospf_lsa_translated_nssa_originate(): " -                   "Could not install LSA " -                   "id %s", inet_ntoa (type7->data->id)); -      return NULL; -    } -     -  ospf->lsa_originate_count++; -  ospf_flood_through_as (ospf, NULL, new); - -  return new; +struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, +						struct ospf_lsa *type7) +{ +	struct ospf_lsa *new; +	struct as_external_lsa *extnew; + +	/* we cant use ospf_external_lsa_originate() as we need to set +	 * the OSPF_LSA_LOCAL_XLT flag, must originate by hand +	 */ + +	if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) { +		if (IS_DEBUG_OSPF_NSSA) +			zlog_debug( +				"ospf_translated_nssa_originate(): Could not translate " +				"Type-7, Id %s, to Type-5", +				inet_ntoa(type7->data->id)); +		return NULL; +	} + +	extnew = (struct as_external_lsa *)new; + +	if (IS_DEBUG_OSPF_NSSA) { +		zlog_debug( +			"ospf_translated_nssa_originate(): " +			"translated Type 7, installed:"); +		ospf_lsa_header_dump(new->data); +		zlog_debug("   Network mask: %d", ip_masklen(extnew->mask)); +		zlog_debug("   Forward addr: %s", +			   inet_ntoa(extnew->e[0].fwd_addr)); +	} + +	if ((new = ospf_lsa_install(ospf, NULL, new)) == NULL) { +		if (IS_DEBUG_OSPF_NSSA) +			zlog_debug( +				"ospf_lsa_translated_nssa_originate(): " +				"Could not install LSA " +				"id %s", +				inet_ntoa(type7->data->id)); +		return NULL; +	} + +	ospf->lsa_originate_count++; +	ospf_flood_through_as(ospf, NULL, new); + +	return new;  }  /* Refresh Translated from NSSA AS-external-LSA. */ -struct ospf_lsa * -ospf_translated_nssa_refresh (struct ospf *ospf, struct ospf_lsa *type7,  -                              struct ospf_lsa *type5) -{ -  struct ospf_lsa *new = NULL; -   -  /* Sanity checks. */ -  assert (type7 || type5); -  if (!(type7 || type5)) -    return NULL; -  if (type7) -    assert (type7->data); -  if (type5) -    assert (type5->data); -  assert (ospf->anyNSSA); - -  /* get required data according to what has been given */ -  if (type7 && type5 == NULL) -    { -      /* find the translated Type-5 for this Type-7 */ -      struct as_external_lsa *ext = (struct as_external_lsa *)(type7->data); -      struct prefix_ipv4 p =  -        {  -          .prefix = type7->data->id, -          .prefixlen = ip_masklen (ext->mask), -          .family = AF_INET, -        }; - -      type5 = ospf_external_info_find_lsa (ospf, &p); -    } -  else if (type5 && type7 == NULL) -    { -      /* find the type-7 from which supplied type-5 was translated, -       * ie find first type-7 with same LSA Id. -       */ -      struct listnode *ln, *lnn; -      struct route_node *rn; -      struct ospf_lsa *lsa; -      struct ospf_area *area; -           -      for (ALL_LIST_ELEMENTS (ospf->areas, ln, lnn, area)) -        { -          if (area->external_routing != OSPF_AREA_NSSA  -              && !type7) -            continue; -             -          LSDB_LOOP (NSSA_LSDB(area), rn, lsa) -            { -              if (lsa->data->id.s_addr == type5->data->id.s_addr) -                { -                  type7 = lsa; -                  break; -                } -            } -        } -    } - -  /* do we have type7? */ -  if (!type7) -    { -      if (IS_DEBUG_OSPF_NSSA) -        zlog_debug ("ospf_translated_nssa_refresh(): no Type-7 found for " -                   "Type-5 LSA Id %s", -                   inet_ntoa (type5->data->id)); -      return NULL; -    } - -  /* do we have valid translated type5? */ -  if (type5 == NULL || !CHECK_FLAG (type5->flags, OSPF_LSA_LOCAL_XLT) ) -    { -      if (IS_DEBUG_OSPF_NSSA) -        zlog_debug ("ospf_translated_nssa_refresh(): No translated Type-5 " -                   "found for Type-7 with Id %s", -                   inet_ntoa (type7->data->id)); -      return NULL; -    } - -  /* Delete LSA from neighbor retransmit-list. */ -  ospf_ls_retransmit_delete_nbr_as (ospf, type5); -   -  /* create new translated LSA */ -  if ( (new = ospf_lsa_translated_nssa_new (ospf, type7)) == NULL) -    { -      if (IS_DEBUG_OSPF_NSSA) -        zlog_debug ("ospf_translated_nssa_refresh(): Could not translate " -                   "Type-7 for %s to Type-5", -                   inet_ntoa (type7->data->id)); -      return NULL; -    } - -  if ( !(new = ospf_lsa_install (ospf, NULL, new)) ) -    { -      if (IS_DEBUG_OSPF_NSSA) -        zlog_debug ("ospf_translated_nssa_refresh(): Could not install " -                   "translated LSA, Id %s", -                   inet_ntoa (type7->data->id)); -      return NULL; -    } -   -  /* Flood LSA through area. */ -  ospf_flood_through_as (ospf, NULL, new); - -  return new; -} - -int -is_prefix_default (struct prefix_ipv4 *p) -{ -  struct prefix_ipv4 q; - -  q.family = AF_INET; -  q.prefix.s_addr = 0; -  q.prefixlen = 0; - -  return prefix_same ((struct prefix *) p, (struct prefix *) &q); +struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, +					      struct ospf_lsa *type7, +					      struct ospf_lsa *type5) +{ +	struct ospf_lsa *new = NULL; + +	/* Sanity checks. */ +	assert(type7 || type5); +	if (!(type7 || type5)) +		return NULL; +	if (type7) +		assert(type7->data); +	if (type5) +		assert(type5->data); +	assert(ospf->anyNSSA); + +	/* get required data according to what has been given */ +	if (type7 && type5 == NULL) { +		/* find the translated Type-5 for this Type-7 */ +		struct as_external_lsa *ext = +			(struct as_external_lsa *)(type7->data); +		struct prefix_ipv4 p = { +			.prefix = type7->data->id, +			.prefixlen = ip_masklen(ext->mask), +			.family = AF_INET, +		}; + +		type5 = ospf_external_info_find_lsa(ospf, &p); +	} else if (type5 && type7 == NULL) { +		/* find the type-7 from which supplied type-5 was translated, +		 * ie find first type-7 with same LSA Id. +		 */ +		struct listnode *ln, *lnn; +		struct route_node *rn; +		struct ospf_lsa *lsa; +		struct ospf_area *area; + +		for (ALL_LIST_ELEMENTS(ospf->areas, ln, lnn, area)) { +			if (area->external_routing != OSPF_AREA_NSSA && !type7) +				continue; + +			LSDB_LOOP(NSSA_LSDB(area), rn, lsa) +			{ +				if (lsa->data->id.s_addr +				    == type5->data->id.s_addr) { +					type7 = lsa; +					break; +				} +			} +		} +	} + +	/* do we have type7? */ +	if (!type7) { +		if (IS_DEBUG_OSPF_NSSA) +			zlog_debug( +				"ospf_translated_nssa_refresh(): no Type-7 found for " +				"Type-5 LSA Id %s", +				inet_ntoa(type5->data->id)); +		return NULL; +	} + +	/* do we have valid translated type5? */ +	if (type5 == NULL || !CHECK_FLAG(type5->flags, OSPF_LSA_LOCAL_XLT)) { +		if (IS_DEBUG_OSPF_NSSA) +			zlog_debug( +				"ospf_translated_nssa_refresh(): No translated Type-5 " +				"found for Type-7 with Id %s", +				inet_ntoa(type7->data->id)); +		return NULL; +	} + +	/* Delete LSA from neighbor retransmit-list. */ +	ospf_ls_retransmit_delete_nbr_as(ospf, type5); + +	/* create new translated LSA */ +	if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) { +		if (IS_DEBUG_OSPF_NSSA) +			zlog_debug( +				"ospf_translated_nssa_refresh(): Could not translate " +				"Type-7 for %s to Type-5", +				inet_ntoa(type7->data->id)); +		return NULL; +	} + +	if (!(new = ospf_lsa_install(ospf, NULL, new))) { +		if (IS_DEBUG_OSPF_NSSA) +			zlog_debug( +				"ospf_translated_nssa_refresh(): Could not install " +				"translated LSA, Id %s", +				inet_ntoa(type7->data->id)); +		return NULL; +	} + +	/* Flood LSA through area. */ +	ospf_flood_through_as(ospf, NULL, new); + +	return new; +} + +int is_prefix_default(struct prefix_ipv4 *p) +{ +	struct prefix_ipv4 q; + +	q.family = AF_INET; +	q.prefix.s_addr = 0; +	q.prefixlen = 0; + +	return prefix_same((struct prefix *)p, (struct prefix *)&q);  }  /* Originate an AS-external-LSA, install and flood. */ -struct ospf_lsa * -ospf_external_lsa_originate (struct ospf *ospf, struct external_info *ei) -{ -  struct ospf_lsa *new; - -  /* Added for NSSA project.... - -       External LSAs are originated in ASBRs as usual, but for NSSA systems. -     there is the global Type-5 LSDB and a Type-7 LSDB installed for -     every area.  The Type-7's are flooded to every IR and every ABR; We -     install the Type-5 LSDB so that the normal "refresh" code operates -     as usual, and flag them as not used during ASE calculations.  The -     Type-7 LSDB is used for calculations.  Each Type-7 has a Forwarding -     Address of non-zero. - -     If an ABR is the elected NSSA translator, following SPF and during -     the ABR task it will translate all the scanned Type-7's, with P-bit -     ON and not-self generated, and translate to Type-5's throughout the -     non-NSSA/STUB AS. - -     A difference in operation depends whether this ASBR is an ABR -     or not.  If not an ABR, the P-bit is ON, to indicate that any -     elected NSSA-ABR can perform its translation. - -     If an ABR, the P-bit is OFF;  No ABR will perform translation and -     this ASBR will flood the Type-5 LSA as usual. - -     For the case where this ASBR is not an ABR, the ASE calculations -     are based on the Type-5 LSDB;  The Type-7 LSDB exists just to -     demonstrate to the user that there are LSA's that belong to any -     attached NSSA. - -     Finally, it just so happens that when the ABR is translating every -     Type-7 into Type-5, it installs it into the Type-5 LSDB as an -     approved Type-5 (translated from Type-7);  at the end of translation -     if any Translated Type-5's remain unapproved, then they must be -     flushed from the AS. - -     */ -   -  /* Check the AS-external-LSA should be originated. */ -  if (!ospf_redistribute_check (ospf, ei, NULL)) -    return NULL; -   -  /* Create new AS-external-LSA instance. */ -  if ((new = ospf_external_lsa_new (ospf, ei, NULL)) == NULL) -    { -      if (IS_DEBUG_OSPF_EVENT) -	zlog_debug ("LSA[Type5:%s]: Could not originate AS-external-LSA", -		   inet_ntoa (ei->p.prefix)); -      return NULL; -    } - -  /* Install newly created LSA into Type-5 LSDB, lock = 1. */ -  ospf_lsa_install (ospf, NULL, new); - -  /* Update LSA origination count. */ -  ospf->lsa_originate_count++; - -  /* Flooding new LSA. only to AS (non-NSSA/STUB) */ -  ospf_flood_through_as (ospf, NULL, new); - -  /* If there is any attached NSSA, do special handling */ -  if (ospf->anyNSSA && -      /* stay away from translated LSAs! */ -      !(CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT))) -    ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */ - -  /* Debug logging. */ -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    { -      zlog_debug ("LSA[Type%d:%s]: Originate AS-external-LSA %p", -		 new->data->type, inet_ntoa (new->data->id), (void *)new); -      ospf_lsa_header_dump (new->data); -    } - -  return new; +struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf, +					     struct external_info *ei) +{ +	struct ospf_lsa *new; + +	/* Added for NSSA project.... + +	     External LSAs are originated in ASBRs as usual, but for NSSA +	   systems. +	   there is the global Type-5 LSDB and a Type-7 LSDB installed for +	   every area.  The Type-7's are flooded to every IR and every ABR; We +	   install the Type-5 LSDB so that the normal "refresh" code operates +	   as usual, and flag them as not used during ASE calculations.  The +	   Type-7 LSDB is used for calculations.  Each Type-7 has a Forwarding +	   Address of non-zero. + +	   If an ABR is the elected NSSA translator, following SPF and during +	   the ABR task it will translate all the scanned Type-7's, with P-bit +	   ON and not-self generated, and translate to Type-5's throughout the +	   non-NSSA/STUB AS. + +	   A difference in operation depends whether this ASBR is an ABR +	   or not.  If not an ABR, the P-bit is ON, to indicate that any +	   elected NSSA-ABR can perform its translation. + +	   If an ABR, the P-bit is OFF;  No ABR will perform translation and +	   this ASBR will flood the Type-5 LSA as usual. + +	   For the case where this ASBR is not an ABR, the ASE calculations +	   are based on the Type-5 LSDB;  The Type-7 LSDB exists just to +	   demonstrate to the user that there are LSA's that belong to any +	   attached NSSA. + +	   Finally, it just so happens that when the ABR is translating every +	   Type-7 into Type-5, it installs it into the Type-5 LSDB as an +	   approved Type-5 (translated from Type-7);  at the end of translation +	   if any Translated Type-5's remain unapproved, then they must be +	   flushed from the AS. + +	   */ + +	/* Check the AS-external-LSA should be originated. */ +	if (!ospf_redistribute_check(ospf, ei, NULL)) +		return NULL; + +	/* Create new AS-external-LSA instance. */ +	if ((new = ospf_external_lsa_new(ospf, ei, NULL)) == NULL) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug( +				"LSA[Type5:%s]: Could not originate AS-external-LSA", +				inet_ntoa(ei->p.prefix)); +		return NULL; +	} + +	/* Install newly created LSA into Type-5 LSDB, lock = 1. */ +	ospf_lsa_install(ospf, NULL, new); + +	/* Update LSA origination count. */ +	ospf->lsa_originate_count++; + +	/* Flooding new LSA. only to AS (non-NSSA/STUB) */ +	ospf_flood_through_as(ospf, NULL, new); + +	/* If there is any attached NSSA, do special handling */ +	if (ospf->anyNSSA && +	    /* stay away from translated LSAs! */ +	    !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT))) +		ospf_install_flood_nssa( +			ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */ + +	/* Debug logging. */ +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +		zlog_debug("LSA[Type%d:%s]: Originate AS-external-LSA %p", +			   new->data->type, inet_ntoa(new->data->id), +			   (void *)new); +		ospf_lsa_header_dump(new->data); +	} + +	return new;  }  /* Originate AS-external-LSA from external info with initial flag. */ -int -ospf_external_lsa_originate_timer (struct thread *thread) -{ -  struct ospf *ospf = THREAD_ARG (thread); -  struct route_node *rn; -  struct external_info *ei; -  struct route_table *rt; -  int type = THREAD_VAL (thread); -  struct list *ext_list; -  struct listnode *node; -  struct ospf_external *ext; - -  ospf->t_external_lsa = NULL; - -  ext_list = om->external[type]; -  if (!ext_list) -    return 0; - -  for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) -    /* Originate As-external-LSA from all type of distribute source. */ -    if ((rt = ext->external_info)) -      for (rn = route_top (rt); rn; rn = route_next (rn)) -        if ((ei = rn->info) != NULL) -          if (!is_prefix_default ((struct prefix_ipv4 *)&ei->p)) -            if (!ospf_external_lsa_originate (ospf, ei)) -              zlog_warn ("LSA: AS-external-LSA was not originated."); - -  return 0; -} - -static struct external_info * -ospf_default_external_info (struct ospf *ospf) -{ -  int type; -  struct route_node *rn; -  struct prefix_ipv4 p; -   -  p.family = AF_INET; -  p.prefix.s_addr = 0; -  p.prefixlen = 0; - -  /* First, lookup redistributed default route. */ -  for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) -    { -      struct list *ext_list; -      struct listnode *node; -      struct ospf_external *ext; - -      if (type == ZEBRA_ROUTE_OSPF) -        continue; - -      ext_list = om->external[type]; -      if (!ext_list) -        continue; - -      for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) -        { -          rn = route_node_lookup (ext->external_info, (struct prefix *) &p); -          if (rn != NULL) -            { -              route_unlock_node (rn); -              assert (rn->info); -              if (ospf_redistribute_check (ospf, rn->info, NULL)) -                return rn->info; -            } -        } -    } - -  return NULL; -} - -int -ospf_default_originate_timer (struct thread *thread) -{ -  struct prefix_ipv4 p; -  struct in_addr nexthop; -  struct external_info *ei; -  struct ospf *ospf; -   -  ospf = THREAD_ARG (thread); - -  p.family = AF_INET; -  p.prefix.s_addr = 0; -  p.prefixlen = 0; - -  if (ospf->default_originate == DEFAULT_ORIGINATE_ALWAYS) -    { -      /* If there is no default route via redistribute, -	 then originate AS-external-LSA with nexthop 0 (self). */ -      nexthop.s_addr = 0; -      ospf_external_info_add (DEFAULT_ROUTE, 0, p, 0, nexthop, 0); -    } - -  if ((ei = ospf_default_external_info (ospf))) -    ospf_external_lsa_originate (ospf, ei); -   -  return 0; +int ospf_external_lsa_originate_timer(struct thread *thread) +{ +	struct ospf *ospf = THREAD_ARG(thread); +	struct route_node *rn; +	struct external_info *ei; +	struct route_table *rt; +	int type = THREAD_VAL(thread); +	struct list *ext_list; +	struct listnode *node; +	struct ospf_external *ext; + +	ospf->t_external_lsa = NULL; + +	ext_list = om->external[type]; +	if (!ext_list) +		return 0; + +	for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) +		/* Originate As-external-LSA from all type of distribute source. +		 */ +		if ((rt = ext->external_info)) +			for (rn = route_top(rt); rn; rn = route_next(rn)) +				if ((ei = rn->info) != NULL) +					if (!is_prefix_default( +						    (struct prefix_ipv4 *)&ei +							    ->p)) +						if (!ospf_external_lsa_originate( +							    ospf, ei)) +							zlog_warn( +								"LSA: AS-external-LSA was not originated."); + +	return 0; +} + +static struct external_info *ospf_default_external_info(struct ospf *ospf) +{ +	int type; +	struct route_node *rn; +	struct prefix_ipv4 p; + +	p.family = AF_INET; +	p.prefix.s_addr = 0; +	p.prefixlen = 0; + +	/* First, lookup redistributed default route. */ +	for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { +		struct list *ext_list; +		struct listnode *node; +		struct ospf_external *ext; + +		if (type == ZEBRA_ROUTE_OSPF) +			continue; + +		ext_list = om->external[type]; +		if (!ext_list) +			continue; + +		for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { +			rn = route_node_lookup(ext->external_info, +					       (struct prefix *)&p); +			if (rn != NULL) { +				route_unlock_node(rn); +				assert(rn->info); +				if (ospf_redistribute_check(ospf, rn->info, +							    NULL)) +					return rn->info; +			} +		} +	} + +	return NULL; +} + +int ospf_default_originate_timer(struct thread *thread) +{ +	struct prefix_ipv4 p; +	struct in_addr nexthop; +	struct external_info *ei; +	struct ospf *ospf; + +	ospf = THREAD_ARG(thread); + +	p.family = AF_INET; +	p.prefix.s_addr = 0; +	p.prefixlen = 0; + +	if (ospf->default_originate == DEFAULT_ORIGINATE_ALWAYS) { +		/* If there is no default route via redistribute, +		   then originate AS-external-LSA with nexthop 0 (self). */ +		nexthop.s_addr = 0; +		ospf_external_info_add(DEFAULT_ROUTE, 0, p, 0, nexthop, 0); +	} + +	if ((ei = ospf_default_external_info(ospf))) +		ospf_external_lsa_originate(ospf, ei); + +	return 0;  }  /* Flush any NSSA LSAs for given prefix */ -void -ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p) -{ -  struct listnode *node, *nnode; -  struct ospf_lsa *lsa; -  struct ospf_area *area; - -  for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) -  { -    if (area->external_routing == OSPF_AREA_NSSA) -    { -      if (!(lsa = ospf_lsa_lookup (area, OSPF_AS_NSSA_LSA, p->prefix, -                                ospf->router_id)))  -      { -        if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))  -          zlog_debug ("LSA: There is no such AS-NSSA-LSA %s/%d in LSDB", -                    inet_ntoa (p->prefix), p->prefixlen); -        continue; -      } -      ospf_ls_retransmit_delete_nbr_area (area, lsa); -      if (!IS_LSA_MAXAGE (lsa))  -      { -        ospf_refresher_unregister_lsa (ospf, lsa); -        ospf_lsa_flush_area (lsa, area); -      } -    } -  } +void ospf_nssa_lsa_flush(struct ospf *ospf, struct prefix_ipv4 *p) +{ +	struct listnode *node, *nnode; +	struct ospf_lsa *lsa; +	struct ospf_area *area; + +	for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { +		if (area->external_routing == OSPF_AREA_NSSA) { +			if (!(lsa = ospf_lsa_lookup(area, OSPF_AS_NSSA_LSA, +						    p->prefix, +						    ospf->router_id))) { +				if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +					zlog_debug( +						"LSA: There is no such AS-NSSA-LSA %s/%d in LSDB", +						inet_ntoa(p->prefix), +						p->prefixlen); +				continue; +			} +			ospf_ls_retransmit_delete_nbr_area(area, lsa); +			if (!IS_LSA_MAXAGE(lsa)) { +				ospf_refresher_unregister_lsa(ospf, lsa); +				ospf_lsa_flush_area(lsa, area); +			} +		} +	}  }  /* Flush an AS-external-LSA from LSDB and routing domain. */ -void -ospf_external_lsa_flush (struct ospf *ospf, -			 u_char type, struct prefix_ipv4 *p, -			 ifindex_t ifindex /*, struct in_addr nexthop */) -{ -  struct ospf_lsa *lsa; - -  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -    zlog_debug ("LSA: Flushing AS-external-LSA %s/%d", -	       inet_ntoa (p->prefix), p->prefixlen); - -  /* First lookup LSA from LSDB. */ -  if (!(lsa = ospf_external_info_find_lsa (ospf, p))) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -	zlog_debug ("LSA: There is no such AS-external-LSA %s/%d in LSDB", -		   inet_ntoa (p->prefix), p->prefixlen); -      return; -    } - -  /* If LSA is selforiginated, not a translated LSA, and there is  -   * NSSA area, flush Type-7 LSA's at first.  -   */ -  if (IS_LSA_SELF(lsa) && (ospf->anyNSSA) -      && !(CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))) -    ospf_nssa_lsa_flush (ospf, p); - -  /* Sweep LSA from Link State Retransmit List. */ -  ospf_ls_retransmit_delete_nbr_as (ospf, lsa); - -  /* There must be no self-originated LSA in rtrs_external. */ +void ospf_external_lsa_flush(struct ospf *ospf, u_char type, +			     struct prefix_ipv4 *p, +			     ifindex_t ifindex /*, struct in_addr nexthop */) +{ +	struct ospf_lsa *lsa; + +	if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +		zlog_debug("LSA: Flushing AS-external-LSA %s/%d", +			   inet_ntoa(p->prefix), p->prefixlen); + +	/* First lookup LSA from LSDB. */ +	if (!(lsa = ospf_external_info_find_lsa(ospf, p))) { +		if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +			zlog_debug( +				"LSA: There is no such AS-external-LSA %s/%d in LSDB", +				inet_ntoa(p->prefix), p->prefixlen); +		return; +	} + +	/* If LSA is selforiginated, not a translated LSA, and there is +	 * NSSA area, flush Type-7 LSA's at first. +	 */ +	if (IS_LSA_SELF(lsa) && (ospf->anyNSSA) +	    && !(CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT))) +		ospf_nssa_lsa_flush(ospf, p); + +	/* Sweep LSA from Link State Retransmit List. */ +	ospf_ls_retransmit_delete_nbr_as(ospf, lsa); + +/* There must be no self-originated LSA in rtrs_external. */  #if 0    /* Remove External route from Zebra. */    ospf_zebra_delete ((struct prefix_ipv4 *) p, &nexthop);  #endif -  if (!IS_LSA_MAXAGE (lsa)) -    { -      /* Unregister LSA from Refresh queue. */ -      ospf_refresher_unregister_lsa (ospf, lsa); - -      /* Flush AS-external-LSA through AS. */ -      ospf_lsa_flush_as (ospf, lsa); -    } - -  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -    zlog_debug ("ospf_external_lsa_flush(): stop"); -} - -void -ospf_external_lsa_refresh_default (struct ospf *ospf) -{ -  struct prefix_ipv4 p; -  struct external_info *ei; -  struct ospf_lsa *lsa; - -  p.family = AF_INET; -  p.prefixlen = 0; -  p.prefix.s_addr = 0; - -  ei = ospf_default_external_info (ospf); -  lsa = ospf_external_info_find_lsa (ospf, &p); - -  if (ei) -    { -      if (lsa) -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", -		       (void *)lsa); -	  ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE); -	} -      else -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("LSA[Type5:0.0.0.0]: Originate AS-external-LSA"); -	  ospf_external_lsa_originate (ospf, ei); -	} -    } -  else -    { -      if (lsa) -	{ -	  if (IS_DEBUG_OSPF_EVENT) -	    zlog_debug ("LSA[Type5:0.0.0.0]: Flush AS-external-LSA"); -          ospf_refresher_unregister_lsa (ospf, lsa); -	  ospf_lsa_flush_as (ospf, lsa); -	} -    } -} - -void -ospf_external_lsa_refresh_type (struct ospf *ospf, u_char type, u_short instance, -                                int force) -{ -  struct route_node *rn; -  struct external_info *ei; -  struct ospf_external *ext; - -  if (type != DEFAULT_ROUTE) -    if ((ext = ospf_external_lookup(type, instance)) && -        EXTERNAL_INFO (ext)) -      /* Refresh each redistributed AS-external-LSAs. */ -      for (rn = route_top (EXTERNAL_INFO (ext)); rn; rn = route_next (rn)) -	if ((ei = rn->info)) -	  if (!is_prefix_default (&ei->p)) -	    { -	      struct ospf_lsa *lsa; - -	      if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p))) -		ospf_external_lsa_refresh (ospf, lsa, ei, force); -	      else -		ospf_external_lsa_originate (ospf, ei); -	    } +	if (!IS_LSA_MAXAGE(lsa)) { +		/* Unregister LSA from Refresh queue. */ +		ospf_refresher_unregister_lsa(ospf, lsa); + +		/* Flush AS-external-LSA through AS. */ +		ospf_lsa_flush_as(ospf, lsa); +	} + +	if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +		zlog_debug("ospf_external_lsa_flush(): stop"); +} + +void ospf_external_lsa_refresh_default(struct ospf *ospf) +{ +	struct prefix_ipv4 p; +	struct external_info *ei; +	struct ospf_lsa *lsa; + +	p.family = AF_INET; +	p.prefixlen = 0; +	p.prefix.s_addr = 0; + +	ei = ospf_default_external_info(ospf); +	lsa = ospf_external_info_find_lsa(ospf, &p); + +	if (ei) { +		if (lsa) { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", +					(void *)lsa); +			ospf_external_lsa_refresh(ospf, lsa, ei, +						  LSA_REFRESH_FORCE); +		} else { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"LSA[Type5:0.0.0.0]: Originate AS-external-LSA"); +			ospf_external_lsa_originate(ospf, ei); +		} +	} else { +		if (lsa) { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"LSA[Type5:0.0.0.0]: Flush AS-external-LSA"); +			ospf_refresher_unregister_lsa(ospf, lsa); +			ospf_lsa_flush_as(ospf, lsa); +		} +	} +} + +void ospf_external_lsa_refresh_type(struct ospf *ospf, u_char type, +				    u_short instance, int force) +{ +	struct route_node *rn; +	struct external_info *ei; +	struct ospf_external *ext; + +	if (type != DEFAULT_ROUTE) +		if ((ext = ospf_external_lookup(type, instance)) +		    && EXTERNAL_INFO(ext)) +			/* Refresh each redistributed AS-external-LSAs. */ +			for (rn = route_top(EXTERNAL_INFO(ext)); rn; +			     rn = route_next(rn)) +				if ((ei = rn->info)) +					if (!is_prefix_default(&ei->p)) { +						struct ospf_lsa *lsa; + +						if ((lsa = ospf_external_info_find_lsa( +							     ospf, &ei->p))) +							ospf_external_lsa_refresh( +								ospf, lsa, ei, +								force); +						else +							ospf_external_lsa_originate( +								ospf, ei); +					}  }  /* Refresh AS-external-LSA. */ -struct ospf_lsa * -ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa, -			   struct external_info *ei, int force) -{ -  struct ospf_lsa *new; -  int changed; -   -  /* Check the AS-external-LSA should be originated. */ -  if (!ospf_redistribute_check (ospf, ei, &changed)) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        zlog_debug ("LSA[Type%d:%s]: Could not be refreshed, " -                   "redist check fail",  -                   lsa->data->type, inet_ntoa (lsa->data->id)); -      ospf_external_lsa_flush (ospf, ei->type, &ei->p, -			       ei->ifindex /*, ei->nexthop */); -      return NULL; -    } - -  if (!changed && !force) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -        zlog_debug ("LSA[Type%d:%s]: Not refreshed, not changed/forced", -                   lsa->data->type, inet_ntoa (lsa->data->id)); -      return NULL; -    } - -  /* Delete LSA from neighbor retransmit-list. */ -  ospf_ls_retransmit_delete_nbr_as (ospf, lsa); - -  /* Unregister AS-external-LSA from refresh-list. */ -  ospf_refresher_unregister_lsa (ospf, lsa); - -  new = ospf_external_lsa_new (ospf, ei, &lsa->data->id); -   -  if (new == NULL) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -	zlog_debug ("LSA[Type%d:%s]: Could not be refreshed", lsa->data->type, -		   inet_ntoa (lsa->data->id)); -      return NULL; -    } -   -  new->data->ls_seqnum = lsa_seqnum_increment (lsa); - -  ospf_lsa_install (ospf, NULL, new);	/* As type-5. */ - -  /* Flood LSA through AS. */ -  ospf_flood_through_as (ospf, NULL, new); - -  /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */ -  if (ospf->anyNSSA && !(CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT))) -    ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood per new rules */ - -  /* Register self-originated LSA to refresh queue.  -   * Translated LSAs should not be registered, but refreshed upon  -   * refresh of the Type-7 -   */ -  if ( !CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT) ) -    ospf_refresher_register_lsa (ospf, new); - -  /* Debug logging. */ -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    { -      zlog_debug ("LSA[Type%d:%s]: AS-external-LSA refresh", -                 new->data->type, inet_ntoa (new->data->id)); -      ospf_lsa_header_dump (new->data); -    } - -  return new; +struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *ospf, +					   struct ospf_lsa *lsa, +					   struct external_info *ei, int force) +{ +	struct ospf_lsa *new; +	int changed; + +	/* Check the AS-external-LSA should be originated. */ +	if (!ospf_redistribute_check(ospf, ei, &changed)) { +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type%d:%s]: Could not be refreshed, " +				"redist check fail", +				lsa->data->type, inet_ntoa(lsa->data->id)); +		ospf_external_lsa_flush(ospf, ei->type, &ei->p, +					ei->ifindex /*, ei->nexthop */); +		return NULL; +	} + +	if (!changed && !force) { +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug( +				"LSA[Type%d:%s]: Not refreshed, not changed/forced", +				lsa->data->type, inet_ntoa(lsa->data->id)); +		return NULL; +	} + +	/* Delete LSA from neighbor retransmit-list. */ +	ospf_ls_retransmit_delete_nbr_as(ospf, lsa); + +	/* Unregister AS-external-LSA from refresh-list. */ +	ospf_refresher_unregister_lsa(ospf, lsa); + +	new = ospf_external_lsa_new(ospf, ei, &lsa->data->id); + +	if (new == NULL) { +		if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +			zlog_debug("LSA[Type%d:%s]: Could not be refreshed", +				   lsa->data->type, inet_ntoa(lsa->data->id)); +		return NULL; +	} + +	new->data->ls_seqnum = lsa_seqnum_increment(lsa); + +	ospf_lsa_install(ospf, NULL, new); /* As type-5. */ + +	/* Flood LSA through AS. */ +	ospf_flood_through_as(ospf, NULL, new); + +	/* If any attached NSSA, install as Type-7, flood to all NSSA Areas */ +	if (ospf->anyNSSA && !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT))) +		ospf_install_flood_nssa(ospf, new, +					ei); /* Install/Flood per new rules */ + +	/* Register self-originated LSA to refresh queue. +	 * Translated LSAs should not be registered, but refreshed upon +	 * refresh of the Type-7 +	 */ +	if (!CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)) +		ospf_refresher_register_lsa(ospf, new); + +	/* Debug logging. */ +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +		zlog_debug("LSA[Type%d:%s]: AS-external-LSA refresh", +			   new->data->type, inet_ntoa(new->data->id)); +		ospf_lsa_header_dump(new->data); +	} + +	return new;  } @@ -2378,114 +2336,109 @@ ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,  /* Install router-LSA to an area. */  static struct ospf_lsa * -ospf_router_lsa_install (struct ospf *ospf, struct ospf_lsa *new, -                         int rt_recalc) +ospf_router_lsa_install(struct ospf *ospf, struct ospf_lsa *new, int rt_recalc)  { -  struct ospf_area *area = new->area; +	struct ospf_area *area = new->area; -  /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs -     The entire routing table must be recalculated, starting with -     the shortest path calculations for each area (not just the -     area whose link-state database has changed).  -  */ +	/* RFC 2328 Section 13.2 Router-LSAs and network-LSAs +	   The entire routing table must be recalculated, starting with +	   the shortest path calculations for each area (not just the +	   area whose link-state database has changed). +	*/ -  if (IS_LSA_SELF (new)) -    { +	if (IS_LSA_SELF(new)) { -      /* Only install LSA if it is originated/refreshed by us. -       * If LSA was received by flooding, the RECEIVED flag is set so do -       * not link the LSA */ -      if (CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED)) -	return new; /* ignore stale LSA */ +		/* Only install LSA if it is originated/refreshed by us. +		 * If LSA was received by flooding, the RECEIVED flag is set so +		 * do +		 * not link the LSA */ +		if (CHECK_FLAG(new->flags, OSPF_LSA_RECEIVED)) +			return new; /* ignore stale LSA */ -      /* Set self-originated router-LSA. */ -      ospf_lsa_unlock (&area->router_lsa_self); -      area->router_lsa_self = ospf_lsa_lock (new); +		/* Set self-originated router-LSA. */ +		ospf_lsa_unlock(&area->router_lsa_self); +		area->router_lsa_self = ospf_lsa_lock(new); -      ospf_refresher_register_lsa (ospf, new); -    } -  if (rt_recalc) -    ospf_spf_calculate_schedule (ospf, SPF_FLAG_ROUTER_LSA_INSTALL); -  return new; +		ospf_refresher_register_lsa(ospf, new); +	} +	if (rt_recalc) +		ospf_spf_calculate_schedule(ospf, SPF_FLAG_ROUTER_LSA_INSTALL); +	return new;  } -#define OSPF_INTERFACE_TIMER_ON(T,F,V) \ -	if (!(T)) \ -	  (T) = thread_add_timer (master, (F), oi, (V)) +#define OSPF_INTERFACE_TIMER_ON(T, F, V)                                       \ +	if (!(T))                                                              \ +	(T) = thread_add_timer(master, (F), oi, (V))  /* Install network-LSA to an area. */ -static struct ospf_lsa * -ospf_network_lsa_install (struct ospf *ospf, -			  struct ospf_interface *oi,  -			  struct ospf_lsa *new, -			  int rt_recalc) -{ - -  /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs -     The entire routing table must be recalculated, starting with -     the shortest path calculations for each area (not just the -     area whose link-state database has changed).  -  */ -  if (IS_LSA_SELF (new)) -    { -      /* We supposed that when LSA is originated by us, we pass the int -	 for which it was originated. If LSA was received by flooding, -	 the RECEIVED flag is set, so we do not link the LSA to the int. */ -      if (CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED)) -	return new; /* ignore stale LSA */ - -      ospf_lsa_unlock (&oi->network_lsa_self); -      oi->network_lsa_self = ospf_lsa_lock (new); -      ospf_refresher_register_lsa (ospf, new); -    } -  if (rt_recalc) -    ospf_spf_calculate_schedule (ospf, SPF_FLAG_NETWORK_LSA_INSTALL); - -  return new; +static struct ospf_lsa *ospf_network_lsa_install(struct ospf *ospf, +						 struct ospf_interface *oi, +						 struct ospf_lsa *new, +						 int rt_recalc) +{ + +	/* RFC 2328 Section 13.2 Router-LSAs and network-LSAs +	   The entire routing table must be recalculated, starting with +	   the shortest path calculations for each area (not just the +	   area whose link-state database has changed). +	*/ +	if (IS_LSA_SELF(new)) { +		/* We supposed that when LSA is originated by us, we pass the +		   int +		   for which it was originated. If LSA was received by flooding, +		   the RECEIVED flag is set, so we do not link the LSA to the +		   int. */ +		if (CHECK_FLAG(new->flags, OSPF_LSA_RECEIVED)) +			return new; /* ignore stale LSA */ + +		ospf_lsa_unlock(&oi->network_lsa_self); +		oi->network_lsa_self = ospf_lsa_lock(new); +		ospf_refresher_register_lsa(ospf, new); +	} +	if (rt_recalc) +		ospf_spf_calculate_schedule(ospf, SPF_FLAG_NETWORK_LSA_INSTALL); + +	return new;  }  /* Install summary-LSA to an area. */  static struct ospf_lsa * -ospf_summary_lsa_install (struct ospf *ospf, struct ospf_lsa *new, -			  int rt_recalc) -{ -  if (rt_recalc && !IS_LSA_SELF (new)) -    { -      /* RFC 2328 Section 13.2 Summary-LSAs -	 The best route to the destination described by the summary- -	 LSA must be recalculated (see Section 16.5).  If this -	 destination is an AS boundary router, it may also be -	 necessary to re-examine all the AS-external-LSAs. -      */ +ospf_summary_lsa_install(struct ospf *ospf, struct ospf_lsa *new, int rt_recalc) +{ +	if (rt_recalc && !IS_LSA_SELF(new)) { +/* RFC 2328 Section 13.2 Summary-LSAs +   The best route to the destination described by the summary- +   LSA must be recalculated (see Section 16.5).  If this +   destination is an AS boundary router, it may also be +   necessary to re-examine all the AS-external-LSAs. +*/  #if 0        /* This doesn't exist yet... */        ospf_summary_incremental_update(new); */ -#else /* #if 0 */ -      ospf_spf_calculate_schedule (ospf, SPF_FLAG_SUMMARY_LSA_INSTALL); +#else  /* #if 0 */ +		ospf_spf_calculate_schedule(ospf, SPF_FLAG_SUMMARY_LSA_INSTALL);  #endif /* #if 0 */ -  -    } +	} -  if (IS_LSA_SELF (new)) -    ospf_refresher_register_lsa (ospf, new); +	if (IS_LSA_SELF(new)) +		ospf_refresher_register_lsa(ospf, new); -  return new; +	return new;  }  /* Install ASBR-summary-LSA to an area. */ -static struct ospf_lsa * -ospf_summary_asbr_lsa_install (struct ospf *ospf, struct ospf_lsa *new, -			       int rt_recalc) -{ -  if (rt_recalc && !IS_LSA_SELF (new)) -    { -      /* RFC 2328 Section 13.2 Summary-LSAs -	 The best route to the destination described by the summary- -	 LSA must be recalculated (see Section 16.5).  If this -	 destination is an AS boundary router, it may also be -	 necessary to re-examine all the AS-external-LSAs. -      */ +static struct ospf_lsa *ospf_summary_asbr_lsa_install(struct ospf *ospf, +						      struct ospf_lsa *new, +						      int rt_recalc) +{ +	if (rt_recalc && !IS_LSA_SELF(new)) { +/* RFC 2328 Section 13.2 Summary-LSAs +   The best route to the destination described by the summary- +   LSA must be recalculated (see Section 16.5).  If this +   destination is an AS boundary router, it may also be +   necessary to re-examine all the AS-external-LSAs. +*/  #if 0        /* These don't exist yet... */        ospf_summary_incremental_update(new); @@ -2493,428 +2446,421 @@ ospf_summary_asbr_lsa_install (struct ospf *ospf, struct ospf_lsa *new,  	 - RFC 2328 Section 16.5 implies it should be */        /* ospf_ase_calculate_schedule(); */  #else  /* #if 0 */ -      ospf_spf_calculate_schedule (ospf, SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL); +		ospf_spf_calculate_schedule(ospf, +					    SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL);  #endif /* #if 0 */ -    } +	} -  /* register LSA to refresh-list. */ -  if (IS_LSA_SELF (new)) -    ospf_refresher_register_lsa (ospf, new); +	/* register LSA to refresh-list. */ +	if (IS_LSA_SELF(new)) +		ospf_refresher_register_lsa(ospf, new); -  return new; +	return new;  }  /* Install AS-external-LSA. */ -static struct ospf_lsa * -ospf_external_lsa_install (struct ospf *ospf, struct ospf_lsa *new, -			   int rt_recalc) -{ -  ospf_ase_register_external_lsa (new, ospf); -  /* If LSA is not self-originated, calculate an external route. */ -  if (rt_recalc) -    { -      /* RFC 2328 Section 13.2 AS-external-LSAs -            The best route to the destination described by the AS- -            external-LSA must be recalculated (see Section 16.6). -      */ - -      if (!IS_LSA_SELF (new)) -        ospf_ase_incremental_update (ospf, new); -    } - -  if (new->data->type == OSPF_AS_NSSA_LSA) -    { -      /* There is no point to register selforiginate Type-7 LSA for -       * refreshing. We rely on refreshing Type-5 LSA's  -       */ -      if (IS_LSA_SELF (new)) -        return new; -      else -        { -          /* Try refresh type-5 translated LSA for this LSA, if one exists. -           * New translations will be taken care of by the abr_task. -           */  -          ospf_translated_nssa_refresh (ospf, new, NULL); -        } -    } - -  /* Register self-originated LSA to refresh queue.  -   * Leave Translated LSAs alone if NSSA is enabled -   */ -  if (IS_LSA_SELF (new) && !CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT ) ) -    ospf_refresher_register_lsa (ospf, new); - -  return new; -} - -void -ospf_discard_from_db (struct ospf *ospf, -		      struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) -{ -  struct ospf_lsa *old; -   -  if (!lsdb) -    { -      zlog_warn ("%s: Called with NULL lsdb!", __func__); -      if (!lsa) -        zlog_warn ("%s: and NULL LSA!", __func__); -      else -        zlog_warn ("LSA[Type%d:%s]: not associated with LSDB!", -                   lsa->data->type, inet_ntoa (lsa->data->id)); -      return; -    } -   -  old = ospf_lsdb_lookup (lsdb, lsa); - -  if (!old) -    return; - -  if (old->refresh_list >= 0) -    ospf_refresher_unregister_lsa (ospf, old); - -  switch (old->data->type) -    { -    case OSPF_AS_EXTERNAL_LSA: -      ospf_ase_unregister_external_lsa (old, ospf); -      ospf_ls_retransmit_delete_nbr_as (ospf, old); -      break; -    case OSPF_OPAQUE_AS_LSA: -      ospf_ls_retransmit_delete_nbr_as (ospf, old); -      break; -    case OSPF_AS_NSSA_LSA: -      ospf_ls_retransmit_delete_nbr_area (old->area, old); -      ospf_ase_unregister_external_lsa (old, ospf); -      break; -    default: -      ospf_ls_retransmit_delete_nbr_area (old->area, old); -      break; -    } - -  ospf_lsa_maxage_delete (ospf, old); -  ospf_lsa_discard (old); -} - -struct ospf_lsa * -ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, -		  struct ospf_lsa *lsa) -{ -  struct ospf_lsa *new = NULL; -  struct ospf_lsa *old = NULL; -  struct ospf_lsdb *lsdb = NULL; -  int rt_recalc; - -  /* Set LSDB. */ -  switch (lsa->data->type) -    { -      /* kevinm */ -    case OSPF_AS_NSSA_LSA: -      if (lsa->area) -	lsdb = lsa->area->lsdb; -      else -	lsdb = ospf->lsdb; -      break; -    case OSPF_AS_EXTERNAL_LSA: -    case OSPF_OPAQUE_AS_LSA: -      lsdb = ospf->lsdb; -      break; -    default: -      lsdb = lsa->area->lsdb; -      break; -    } - -  assert (lsdb); - -  /*  RFC 2328 13.2.  Installing LSAs in the database - -        Installing a new LSA in the database, either as the result of -        flooding or a newly self-originated LSA, may cause the OSPF -        routing table structure to be recalculated.  The contents of the -        new LSA should be compared to the old instance, if present.  If -        there is no difference, there is no need to recalculate the -        routing table. When comparing an LSA to its previous instance, -        the following are all considered to be differences in contents: - -            o   The LSA's Options field has changed. - -            o   One of the LSA instances has LS age set to MaxAge, and -                the other does not. - -            o   The length field in the LSA header has changed. - -            o   The body of the LSA (i.e., anything outside the 20-byte -                LSA header) has changed. Note that this excludes changes -                in LS Sequence Number and LS Checksum. - -  */ -  /* Look up old LSA and determine if any SPF calculation or incremental -     update is needed */ -  old = ospf_lsdb_lookup (lsdb, lsa); - -  /* Do comparision and record if recalc needed. */ -  rt_recalc = 0; -  if (  old == NULL || ospf_lsa_different(old, lsa)) -    rt_recalc = 1; - -  /* -     Sequence number check (Section 14.1 of rfc 2328) -     "Premature aging is used when it is time for a self-originated -      LSA's sequence number field to wrap.  At this point, the current -      LSA instance (having LS sequence number MaxSequenceNumber) must -      be prematurely aged and flushed from the routing domain before a -      new instance with sequence number equal to InitialSequenceNumber -      can be originated. " -   */ - -  if (ntohl(lsa->data->ls_seqnum) - 1 == OSPF_MAX_SEQUENCE_NUMBER) -    { -      if (ospf_lsa_is_self_originated(ospf, lsa)) -        { -          lsa->data->ls_seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER); -           -          if (!IS_LSA_MAXAGE(lsa)) -            lsa->flags |= OSPF_LSA_PREMATURE_AGE; -          lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); -      	 -          if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) -            { -      	      zlog_debug ("ospf_lsa_install() Premature Aging " -		         "lsa 0x%p, seqnum 0x%x", -		         (void *)lsa, ntohl(lsa->data->ls_seqnum)); -      	      ospf_lsa_header_dump (lsa->data); -            } -        } -      else -        { -          if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -            { -      	      zlog_debug ("ospf_lsa_install() got an lsa with seq 0x80000000 " -		         "that was not self originated. Ignoring\n"); -      	      ospf_lsa_header_dump (lsa->data); -            } -	  return old; -        } -    } - -  /* discard old LSA from LSDB */ -  if (old != NULL) -    ospf_discard_from_db (ospf, lsdb, lsa); - -  /* Calculate Checksum if self-originated?. */ -  if (IS_LSA_SELF (lsa)) -    ospf_lsa_checksum (lsa->data); - -  /* Insert LSA to LSDB. */ -  ospf_lsdb_add (lsdb, lsa); -  lsa->lsdb = lsdb; - -  /* Do LSA specific installation process. */ -  switch (lsa->data->type) -    { -    case OSPF_ROUTER_LSA: -      new = ospf_router_lsa_install (ospf, lsa, rt_recalc); -      break; -    case OSPF_NETWORK_LSA: -      assert (oi); -      new = ospf_network_lsa_install (ospf, oi, lsa, rt_recalc); -      break; -    case OSPF_SUMMARY_LSA: -      new = ospf_summary_lsa_install (ospf, lsa, rt_recalc); -      break; -    case OSPF_ASBR_SUMMARY_LSA: -      new = ospf_summary_asbr_lsa_install (ospf, lsa, rt_recalc); -      break; -    case OSPF_AS_EXTERNAL_LSA: -      new = ospf_external_lsa_install (ospf, lsa, rt_recalc); -      break; -    case OSPF_OPAQUE_LINK_LSA: -      if (IS_LSA_SELF (lsa)) -	lsa->oi = oi; /* Specify outgoing ospf-interface for this LSA. */ -      else -        { -          /* Incoming "oi" for this LSA has set at LSUpd reception. */ -        } -      /* Fallthrough */ -    case OSPF_OPAQUE_AREA_LSA: -    case OSPF_OPAQUE_AS_LSA: -      new = ospf_opaque_lsa_install (lsa, rt_recalc); -      break; -    case OSPF_AS_NSSA_LSA: -      new = ospf_external_lsa_install (ospf, lsa, rt_recalc); -    default: /* type-6,8,9....nothing special */ -      break; -    } - -  if (new == NULL) -    return new;  /* Installation failed, cannot proceed further -- endo. */ - -  /* Debug logs. */ -  if (IS_DEBUG_OSPF (lsa, LSA_INSTALL)) -    { -      char area_str[INET_ADDRSTRLEN]; - -      switch (lsa->data->type) -        { -        case OSPF_AS_EXTERNAL_LSA: -        case OSPF_OPAQUE_AS_LSA: -        case OSPF_AS_NSSA_LSA: -          zlog_debug ("LSA[%s]: Install %s", -                 dump_lsa_key (new), -                 lookup_msg(ospf_lsa_type_msg, new->data->type, NULL)); -          break; -        default: -	  strcpy (area_str, inet_ntoa (new->area->area_id)); -          zlog_debug ("LSA[%s]: Install %s to Area %s", -                 dump_lsa_key (new), -                 lookup_msg(ospf_lsa_type_msg, new->data->type, NULL), area_str); -          break; -        } -    } - -  /*  -     If received LSA' ls_age is MaxAge, or lsa is being prematurely aged -     (it's getting flushed out of the area), set LSA on MaxAge LSA list.  -   */ -  if (IS_LSA_MAXAGE (new)) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_INSTALL)) -        zlog_debug ("LSA[Type%d:%s]: Install LSA 0x%p, MaxAge", -                   new->data->type, -                   inet_ntoa (new->data->id), -                   (void *)lsa); -      ospf_lsa_maxage (ospf, lsa); -    } - -  return new; -} - - -int -ospf_check_nbr_status (struct ospf *ospf) -{ -  struct listnode *node, *nnode; -  struct ospf_interface *oi; -   -  for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) -    { -      struct route_node *rn; -      struct ospf_neighbor *nbr; - -      if (ospf_if_is_enable (oi)) -	for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) -          if ((nbr = rn->info) != NULL) -	    if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading) -	      { -		route_unlock_node (rn); -		return 0; -	      } -    } - -  return 1; -} - - - -static int -ospf_maxage_lsa_remover (struct thread *thread) -{ -  struct ospf *ospf = THREAD_ARG (thread); -  struct ospf_lsa *lsa; -  struct route_node *rn; -  int reschedule = 0; - -  ospf->t_maxage = NULL; - -  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -    zlog_debug ("LSA[MaxAge]: remover Start"); - -  reschedule = !ospf_check_nbr_status (ospf); - -  if (!reschedule) -    for (rn = route_top(ospf->maxage_lsa); rn; rn = route_next(rn)) -      { -	if ((lsa = rn->info) == NULL) -	  { -	    continue; -	  } - -        /* There is at least one neighbor from which we still await an ack -         * for that LSA, so we are not allowed to remove it from our lsdb yet -         * as per RFC 2328 section 14 para 4 a) */ -        if (lsa->retransmit_counter > 0) -          { -            reschedule = 1; -            continue; -          } -         -        /* TODO: maybe convert this function to a work-queue */ -        if (thread_should_yield (thread)) -          { -            OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 0); -            route_unlock_node(rn); /* route_top/route_next */ -            return 0; -          } -           -        /* Remove LSA from the LSDB */ -        if (IS_LSA_SELF (lsa)) -          if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -            zlog_debug ("LSA[Type%d:%s]: LSA 0x%lx is self-originated: ", -                       lsa->data->type, inet_ntoa (lsa->data->id), (u_long)lsa); - -        if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -          zlog_debug ("LSA[Type%d:%s]: MaxAge LSA removed from list", -                     lsa->data->type, inet_ntoa (lsa->data->id)); - -	if (CHECK_FLAG (lsa->flags, OSPF_LSA_PREMATURE_AGE)) -          { -            if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -              zlog_debug ("originating new lsa for lsa 0x%p\n", (void *)lsa); -            ospf_lsa_refresh (ospf, lsa); -          } - -	/* Remove from lsdb. */ -	if (lsa->lsdb) -	  { -	    ospf_discard_from_db (ospf, lsa->lsdb, lsa); -	    ospf_lsdb_delete (lsa->lsdb, lsa); -          } -        else -          zlog_warn ("%s: LSA[Type%d:%s]: No associated LSDB!", __func__, -                     lsa->data->type, inet_ntoa (lsa->data->id)); -      } - -  /*    A MaxAge LSA must be removed immediately from the router's link -        state database as soon as both a) it is no longer contained on any -        neighbor Link state retransmission lists and b) none of the router's -        neighbors are in states Exchange or Loading. */ -  if (reschedule) -    OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, -                   ospf->maxage_delay); - -  return 0; -} - -void -ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa) -{ -  struct route_node *rn; -  struct prefix_ptr lsa_prefix; - -  lsa_prefix.family = 0; -  lsa_prefix.prefixlen = sizeof(lsa_prefix.prefix) * CHAR_BIT; -  lsa_prefix.prefix = (uintptr_t) lsa; - -  if ((rn = route_node_lookup(ospf->maxage_lsa, -			      (struct prefix *)&lsa_prefix))) -    { -      if (rn->info == lsa) -	{ -	  UNSET_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE); -	  ospf_lsa_unlock (&lsa); /* maxage_lsa */ -	  rn->info = NULL; -	  route_unlock_node (rn); /* unlock node because lsa is deleted */ -	} -      route_unlock_node (rn); /* route_node_lookup */ -    } +static struct ospf_lsa *ospf_external_lsa_install(struct ospf *ospf, +						  struct ospf_lsa *new, +						  int rt_recalc) +{ +	ospf_ase_register_external_lsa(new, ospf); +	/* If LSA is not self-originated, calculate an external route. */ +	if (rt_recalc) { +		/* RFC 2328 Section 13.2 AS-external-LSAs +		      The best route to the destination described by the AS- +		      external-LSA must be recalculated (see Section 16.6). +		*/ + +		if (!IS_LSA_SELF(new)) +			ospf_ase_incremental_update(ospf, new); +	} + +	if (new->data->type == OSPF_AS_NSSA_LSA) { +		/* There is no point to register selforiginate Type-7 LSA for +		 * refreshing. We rely on refreshing Type-5 LSA's +		 */ +		if (IS_LSA_SELF(new)) +			return new; +		else { +			/* Try refresh type-5 translated LSA for this LSA, if +			 * one exists. +			 * New translations will be taken care of by the +			 * abr_task. +			 */ +			ospf_translated_nssa_refresh(ospf, new, NULL); +		} +	} + +	/* Register self-originated LSA to refresh queue. +	 * Leave Translated LSAs alone if NSSA is enabled +	 */ +	if (IS_LSA_SELF(new) && !CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)) +		ospf_refresher_register_lsa(ospf, new); + +	return new; +} + +void ospf_discard_from_db(struct ospf *ospf, struct ospf_lsdb *lsdb, +			  struct ospf_lsa *lsa) +{ +	struct ospf_lsa *old; + +	if (!lsdb) { +		zlog_warn("%s: Called with NULL lsdb!", __func__); +		if (!lsa) +			zlog_warn("%s: and NULL LSA!", __func__); +		else +			zlog_warn("LSA[Type%d:%s]: not associated with LSDB!", +				  lsa->data->type, inet_ntoa(lsa->data->id)); +		return; +	} + +	old = ospf_lsdb_lookup(lsdb, lsa); + +	if (!old) +		return; + +	if (old->refresh_list >= 0) +		ospf_refresher_unregister_lsa(ospf, old); + +	switch (old->data->type) { +	case OSPF_AS_EXTERNAL_LSA: +		ospf_ase_unregister_external_lsa(old, ospf); +		ospf_ls_retransmit_delete_nbr_as(ospf, old); +		break; +	case OSPF_OPAQUE_AS_LSA: +		ospf_ls_retransmit_delete_nbr_as(ospf, old); +		break; +	case OSPF_AS_NSSA_LSA: +		ospf_ls_retransmit_delete_nbr_area(old->area, old); +		ospf_ase_unregister_external_lsa(old, ospf); +		break; +	default: +		ospf_ls_retransmit_delete_nbr_area(old->area, old); +		break; +	} + +	ospf_lsa_maxage_delete(ospf, old); +	ospf_lsa_discard(old); +} + +struct ospf_lsa *ospf_lsa_install(struct ospf *ospf, struct ospf_interface *oi, +				  struct ospf_lsa *lsa) +{ +	struct ospf_lsa *new = NULL; +	struct ospf_lsa *old = NULL; +	struct ospf_lsdb *lsdb = NULL; +	int rt_recalc; + +	/* Set LSDB. */ +	switch (lsa->data->type) { +	/* kevinm */ +	case OSPF_AS_NSSA_LSA: +		if (lsa->area) +			lsdb = lsa->area->lsdb; +		else +			lsdb = ospf->lsdb; +		break; +	case OSPF_AS_EXTERNAL_LSA: +	case OSPF_OPAQUE_AS_LSA: +		lsdb = ospf->lsdb; +		break; +	default: +		lsdb = lsa->area->lsdb; +		break; +	} + +	assert(lsdb); + +	/*  RFC 2328 13.2.  Installing LSAs in the database + +	      Installing a new LSA in the database, either as the result of +	      flooding or a newly self-originated LSA, may cause the OSPF +	      routing table structure to be recalculated.  The contents of the +	      new LSA should be compared to the old instance, if present.  If +	      there is no difference, there is no need to recalculate the +	      routing table. When comparing an LSA to its previous instance, +	      the following are all considered to be differences in contents: + +		  o   The LSA's Options field has changed. + +		  o   One of the LSA instances has LS age set to MaxAge, and +		      the other does not. + +		  o   The length field in the LSA header has changed. + +		  o   The body of the LSA (i.e., anything outside the 20-byte +		      LSA header) has changed. Note that this excludes changes +		      in LS Sequence Number and LS Checksum. + +	*/ +	/* Look up old LSA and determine if any SPF calculation or incremental +	   update is needed */ +	old = ospf_lsdb_lookup(lsdb, lsa); + +	/* Do comparision and record if recalc needed. */ +	rt_recalc = 0; +	if (old == NULL || ospf_lsa_different(old, lsa)) +		rt_recalc = 1; + +	/* +	   Sequence number check (Section 14.1 of rfc 2328) +	   "Premature aging is used when it is time for a self-originated +	    LSA's sequence number field to wrap.  At this point, the current +	    LSA instance (having LS sequence number MaxSequenceNumber) must +	    be prematurely aged and flushed from the routing domain before a +	    new instance with sequence number equal to InitialSequenceNumber +	    can be originated. " +	 */ + +	if (ntohl(lsa->data->ls_seqnum) - 1 == OSPF_MAX_SEQUENCE_NUMBER) { +		if (ospf_lsa_is_self_originated(ospf, lsa)) { +			lsa->data->ls_seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER); + +			if (!IS_LSA_MAXAGE(lsa)) +				lsa->flags |= OSPF_LSA_PREMATURE_AGE; +			lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + +			if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) { +				zlog_debug( +					"ospf_lsa_install() Premature Aging " +					"lsa 0x%p, seqnum 0x%x", +					(void *)lsa, +					ntohl(lsa->data->ls_seqnum)); +				ospf_lsa_header_dump(lsa->data); +			} +		} else { +			if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { +				zlog_debug( +					"ospf_lsa_install() got an lsa with seq 0x80000000 " +					"that was not self originated. Ignoring\n"); +				ospf_lsa_header_dump(lsa->data); +			} +			return old; +		} +	} + +	/* discard old LSA from LSDB */ +	if (old != NULL) +		ospf_discard_from_db(ospf, lsdb, lsa); + +	/* Calculate Checksum if self-originated?. */ +	if (IS_LSA_SELF(lsa)) +		ospf_lsa_checksum(lsa->data); + +	/* Insert LSA to LSDB. */ +	ospf_lsdb_add(lsdb, lsa); +	lsa->lsdb = lsdb; + +	/* Do LSA specific installation process. */ +	switch (lsa->data->type) { +	case OSPF_ROUTER_LSA: +		new = ospf_router_lsa_install(ospf, lsa, rt_recalc); +		break; +	case OSPF_NETWORK_LSA: +		assert(oi); +		new = ospf_network_lsa_install(ospf, oi, lsa, rt_recalc); +		break; +	case OSPF_SUMMARY_LSA: +		new = ospf_summary_lsa_install(ospf, lsa, rt_recalc); +		break; +	case OSPF_ASBR_SUMMARY_LSA: +		new = ospf_summary_asbr_lsa_install(ospf, lsa, rt_recalc); +		break; +	case OSPF_AS_EXTERNAL_LSA: +		new = ospf_external_lsa_install(ospf, lsa, rt_recalc); +		break; +	case OSPF_OPAQUE_LINK_LSA: +		if (IS_LSA_SELF(lsa)) +			lsa->oi = oi; /* Specify outgoing ospf-interface for +					 this LSA. */ +		else { +			/* Incoming "oi" for this LSA has set at LSUpd +			 * reception. */ +		} +	/* Fallthrough */ +	case OSPF_OPAQUE_AREA_LSA: +	case OSPF_OPAQUE_AS_LSA: +		new = ospf_opaque_lsa_install(lsa, rt_recalc); +		break; +	case OSPF_AS_NSSA_LSA: +		new = ospf_external_lsa_install(ospf, lsa, rt_recalc); +	default: /* type-6,8,9....nothing special */ +		break; +	} + +	if (new == NULL) +		return new; /* Installation failed, cannot proceed further -- +			       endo. */ + +	/* Debug logs. */ +	if (IS_DEBUG_OSPF(lsa, LSA_INSTALL)) { +		char area_str[INET_ADDRSTRLEN]; + +		switch (lsa->data->type) { +		case OSPF_AS_EXTERNAL_LSA: +		case OSPF_OPAQUE_AS_LSA: +		case OSPF_AS_NSSA_LSA: +			zlog_debug("LSA[%s]: Install %s", dump_lsa_key(new), +				   lookup_msg(ospf_lsa_type_msg, +					      new->data->type, NULL)); +			break; +		default: +			strcpy(area_str, inet_ntoa(new->area->area_id)); +			zlog_debug("LSA[%s]: Install %s to Area %s", +				   dump_lsa_key(new), +				   lookup_msg(ospf_lsa_type_msg, +					      new->data->type, NULL), +				   area_str); +			break; +		} +	} + +	/* +	   If received LSA' ls_age is MaxAge, or lsa is being prematurely aged +	   (it's getting flushed out of the area), set LSA on MaxAge LSA list. +	 */ +	if (IS_LSA_MAXAGE(new)) { +		if (IS_DEBUG_OSPF(lsa, LSA_INSTALL)) +			zlog_debug("LSA[Type%d:%s]: Install LSA 0x%p, MaxAge", +				   new->data->type, inet_ntoa(new->data->id), +				   (void *)lsa); +		ospf_lsa_maxage(ospf, lsa); +	} + +	return new; +} + + +int ospf_check_nbr_status(struct ospf *ospf) +{ +	struct listnode *node, *nnode; +	struct ospf_interface *oi; + +	for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) { +		struct route_node *rn; +		struct ospf_neighbor *nbr; + +		if (ospf_if_is_enable(oi)) +			for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) +				if ((nbr = rn->info) != NULL) +					if (nbr->state == NSM_Exchange +					    || nbr->state == NSM_Loading) { +						route_unlock_node(rn); +						return 0; +					} +	} + +	return 1; +} + + +static int ospf_maxage_lsa_remover(struct thread *thread) +{ +	struct ospf *ospf = THREAD_ARG(thread); +	struct ospf_lsa *lsa; +	struct route_node *rn; +	int reschedule = 0; + +	ospf->t_maxage = NULL; + +	if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +		zlog_debug("LSA[MaxAge]: remover Start"); + +	reschedule = !ospf_check_nbr_status(ospf); + +	if (!reschedule) +		for (rn = route_top(ospf->maxage_lsa); rn; +		     rn = route_next(rn)) { +			if ((lsa = rn->info) == NULL) { +				continue; +			} + +			/* There is at least one neighbor from which we still +			 * await an ack +			 * for that LSA, so we are not allowed to remove it from +			 * our lsdb yet +			 * as per RFC 2328 section 14 para 4 a) */ +			if (lsa->retransmit_counter > 0) { +				reschedule = 1; +				continue; +			} + +			/* TODO: maybe convert this function to a work-queue */ +			if (thread_should_yield(thread)) { +				OSPF_TIMER_ON(ospf->t_maxage, +					      ospf_maxage_lsa_remover, 0); +				route_unlock_node( +					rn); /* route_top/route_next */ +				return 0; +			} + +			/* Remove LSA from the LSDB */ +			if (IS_LSA_SELF(lsa)) +				if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +					zlog_debug( +						"LSA[Type%d:%s]: LSA 0x%lx is self-originated: ", +						lsa->data->type, +						inet_ntoa(lsa->data->id), +						(u_long)lsa); + +			if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +				zlog_debug( +					"LSA[Type%d:%s]: MaxAge LSA removed from list", +					lsa->data->type, +					inet_ntoa(lsa->data->id)); + +			if (CHECK_FLAG(lsa->flags, OSPF_LSA_PREMATURE_AGE)) { +				if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +					zlog_debug( +						"originating new lsa for lsa 0x%p\n", +						(void *)lsa); +				ospf_lsa_refresh(ospf, lsa); +			} + +			/* Remove from lsdb. */ +			if (lsa->lsdb) { +				ospf_discard_from_db(ospf, lsa->lsdb, lsa); +				ospf_lsdb_delete(lsa->lsdb, lsa); +			} else +				zlog_warn( +					"%s: LSA[Type%d:%s]: No associated LSDB!", +					__func__, lsa->data->type, +					inet_ntoa(lsa->data->id)); +		} + +	/*    A MaxAge LSA must be removed immediately from the router's link +	      state database as soon as both a) it is no longer contained on any +	      neighbor Link state retransmission lists and b) none of the +	   router's +	      neighbors are in states Exchange or Loading. */ +	if (reschedule) +		OSPF_TIMER_ON(ospf->t_maxage, ospf_maxage_lsa_remover, +			      ospf->maxage_delay); + +	return 0; +} + +void ospf_lsa_maxage_delete(struct ospf *ospf, struct ospf_lsa *lsa) +{ +	struct route_node *rn; +	struct prefix_ptr lsa_prefix; + +	lsa_prefix.family = 0; +	lsa_prefix.prefixlen = sizeof(lsa_prefix.prefix) * CHAR_BIT; +	lsa_prefix.prefix = (uintptr_t)lsa; + +	if ((rn = route_node_lookup(ospf->maxage_lsa, +				    (struct prefix *)&lsa_prefix))) { +		if (rn->info == lsa) { +			UNSET_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE); +			ospf_lsa_unlock(&lsa); /* maxage_lsa */ +			rn->info = NULL; +			route_unlock_node( +				rn); /* unlock node because lsa is deleted */ +		} +		route_unlock_node(rn); /* route_node_lookup */ +	}  }  /* Add LSA onto the MaxAge list, and schedule for removal. @@ -2922,841 +2868,833 @@ ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa)   * care of elsewhere, see, e.g., ospf_lsa_flush* (which are callers of this   * function).   */ -void -ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa) -{ -  struct prefix_ptr lsa_prefix; -  struct route_node *rn; - -  /* When we saw a MaxAge LSA flooded to us, we put it on the list -     and schedule the MaxAge LSA remover. */ -  if (CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE)) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -	zlog_debug ("LSA[Type%d:%s]: %p already exists on MaxAge LSA list", -		   lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa); -      return; -    } - -  lsa_prefix.family = 0; -  lsa_prefix.prefixlen = sizeof(lsa_prefix.prefix) * CHAR_BIT; -  lsa_prefix.prefix = (uintptr_t) lsa; - -  if ((rn = route_node_get (ospf->maxage_lsa, -			    (struct prefix *)&lsa_prefix)) != NULL) -    { -      if (rn->info != NULL) -	{ -	  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -	    zlog_debug ("LSA[%s]: found LSA (%p) in table for LSA %p %d", -			dump_lsa_key (lsa), rn->info, (void *)lsa, -			lsa_prefix.prefixlen); -	  route_unlock_node (rn); -	} -      else -	{ -	  rn->info = ospf_lsa_lock(lsa); -	  SET_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE); -	} -    } -  else -    { -      zlog_err("Unable to allocate memory for maxage lsa\n"); -      assert(0); -    } - -  if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -    zlog_debug ("LSA[%s]: MaxAge LSA remover scheduled.", dump_lsa_key (lsa)); - -  OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, -                 ospf->maxage_delay); -} - -static int -ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa) -{ -  /* Stay away from any Local Translated Type-7 LSAs */ -  if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) -    return 0; - -  if (IS_LSA_MAXAGE (lsa)) -    /* Self-originated LSAs should NOT time-out instead, -       they're flushed and submitted to the max_age list explicitly. */ -    if (!ospf_lsa_is_self_originated (ospf, lsa)) -      { -	if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) -	  zlog_debug("LSA[%s]: is MaxAge", dump_lsa_key (lsa)); - -        switch (lsa->data->type) -          { -          case OSPF_OPAQUE_LINK_LSA: -          case OSPF_OPAQUE_AREA_LSA: -          case OSPF_OPAQUE_AS_LSA: -            /* -             * As a general rule, whenever network topology has changed -             * (due to an LSA removal in this case), routing recalculation -             * should be triggered. However, this is not true for opaque -             * LSAs. Even if an opaque LSA instance is going to be removed -             * from the routing domain, it does not mean a change in network -             * topology, and thus, routing recalculation is not needed here. -             */ -            break; -          case OSPF_AS_EXTERNAL_LSA: -          case OSPF_AS_NSSA_LSA: -	    ospf_ase_incremental_update (ospf, lsa); -            break; -          default: -	    ospf_spf_calculate_schedule (ospf, SPF_FLAG_MAXAGE); -            break; -          } -	ospf_lsa_maxage (ospf, lsa); -      } - -  if (IS_LSA_MAXAGE (lsa) && !ospf_lsa_is_self_originated (ospf, lsa)) -    if (LS_AGE (lsa) > OSPF_LSA_MAXAGE + 30) -      printf ("Eek! Shouldn't happen!\n"); - -  return 0; +void ospf_lsa_maxage(struct ospf *ospf, struct ospf_lsa *lsa) +{ +	struct prefix_ptr lsa_prefix; +	struct route_node *rn; + +	/* When we saw a MaxAge LSA flooded to us, we put it on the list +	   and schedule the MaxAge LSA remover. */ +	if (CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE)) { +		if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +			zlog_debug( +				"LSA[Type%d:%s]: %p already exists on MaxAge LSA list", +				lsa->data->type, inet_ntoa(lsa->data->id), +				(void *)lsa); +		return; +	} + +	lsa_prefix.family = 0; +	lsa_prefix.prefixlen = sizeof(lsa_prefix.prefix) * CHAR_BIT; +	lsa_prefix.prefix = (uintptr_t)lsa; + +	if ((rn = route_node_get(ospf->maxage_lsa, +				 (struct prefix *)&lsa_prefix)) +	    != NULL) { +		if (rn->info != NULL) { +			if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +				zlog_debug( +					"LSA[%s]: found LSA (%p) in table for LSA %p %d", +					dump_lsa_key(lsa), rn->info, +					(void *)lsa, lsa_prefix.prefixlen); +			route_unlock_node(rn); +		} else { +			rn->info = ospf_lsa_lock(lsa); +			SET_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE); +		} +	} else { +		zlog_err("Unable to allocate memory for maxage lsa\n"); +		assert(0); +	} + +	if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +		zlog_debug("LSA[%s]: MaxAge LSA remover scheduled.", +			   dump_lsa_key(lsa)); + +	OSPF_TIMER_ON(ospf->t_maxage, ospf_maxage_lsa_remover, +		      ospf->maxage_delay); +} + +static int ospf_lsa_maxage_walker_remover(struct ospf *ospf, +					  struct ospf_lsa *lsa) +{ +	/* Stay away from any Local Translated Type-7 LSAs */ +	if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) +		return 0; + +	if (IS_LSA_MAXAGE(lsa)) +		/* Self-originated LSAs should NOT time-out instead, +		   they're flushed and submitted to the max_age list explicitly. +		   */ +		if (!ospf_lsa_is_self_originated(ospf, lsa)) { +			if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) +				zlog_debug("LSA[%s]: is MaxAge", +					   dump_lsa_key(lsa)); + +			switch (lsa->data->type) { +			case OSPF_OPAQUE_LINK_LSA: +			case OSPF_OPAQUE_AREA_LSA: +			case OSPF_OPAQUE_AS_LSA: +				/* +				 * As a general rule, whenever network topology +				 * has changed +				 * (due to an LSA removal in this case), routing +				 * recalculation +				 * should be triggered. However, this is not +				 * true for opaque +				 * LSAs. Even if an opaque LSA instance is going +				 * to be removed +				 * from the routing domain, it does not mean a +				 * change in network +				 * topology, and thus, routing recalculation is +				 * not needed here. +				 */ +				break; +			case OSPF_AS_EXTERNAL_LSA: +			case OSPF_AS_NSSA_LSA: +				ospf_ase_incremental_update(ospf, lsa); +				break; +			default: +				ospf_spf_calculate_schedule(ospf, +							    SPF_FLAG_MAXAGE); +				break; +			} +			ospf_lsa_maxage(ospf, lsa); +		} + +	if (IS_LSA_MAXAGE(lsa) && !ospf_lsa_is_self_originated(ospf, lsa)) +		if (LS_AGE(lsa) > OSPF_LSA_MAXAGE + 30) +			printf("Eek! Shouldn't happen!\n"); + +	return 0;  }  /* Periodical check of MaxAge LSA. */ -int -ospf_lsa_maxage_walker (struct thread *thread) -{ -  struct ospf *ospf = THREAD_ARG (thread); -  struct route_node *rn; -  struct ospf_lsa *lsa; -  struct ospf_area *area; -  struct listnode *node, *nnode; - -  ospf->t_maxage_walker = NULL; - -  for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) -    { -      LSDB_LOOP (ROUTER_LSDB (area), rn, lsa) -	ospf_lsa_maxage_walker_remover (ospf, lsa); -      LSDB_LOOP (NETWORK_LSDB (area), rn, lsa) -	ospf_lsa_maxage_walker_remover (ospf, lsa); -      LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) -	ospf_lsa_maxage_walker_remover (ospf, lsa); -      LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) -	ospf_lsa_maxage_walker_remover (ospf, lsa); -      LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) -	ospf_lsa_maxage_walker_remover (ospf, lsa); -      LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) -	ospf_lsa_maxage_walker_remover (ospf, lsa); -      LSDB_LOOP (NSSA_LSDB (area), rn, lsa) -        ospf_lsa_maxage_walker_remover (ospf, lsa); -    } - -  /* for AS-external-LSAs. */ -  if (ospf->lsdb) -    { -      LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) -	ospf_lsa_maxage_walker_remover (ospf, lsa); -      LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) -	ospf_lsa_maxage_walker_remover (ospf, lsa); -    } - -  OSPF_TIMER_ON (ospf->t_maxage_walker, ospf_lsa_maxage_walker, -		 OSPF_LSA_MAXAGE_CHECK_INTERVAL); -  return 0; -} - -struct ospf_lsa * -ospf_lsa_lookup_by_prefix (struct ospf_lsdb *lsdb, u_char type, -			   struct prefix_ipv4 *p, struct in_addr router_id) -{ -  struct ospf_lsa *lsa; -  struct in_addr mask, id; -  struct lsa_header_mask -  { -    struct lsa_header header; -    struct in_addr mask; -  } *hmask; - -  lsa = ospf_lsdb_lookup_by_id (lsdb, type, p->prefix, router_id); -  if (lsa == NULL) -    return NULL; - -  masklen2ip (p->prefixlen, &mask); - -  hmask = (struct lsa_header_mask *) lsa->data; - -  if (mask.s_addr != hmask->mask.s_addr) -    { -      id.s_addr = p->prefix.s_addr | (~mask.s_addr); -      lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, router_id); -      if (!lsa) -        return NULL; -    } - -  return lsa; -} - -struct ospf_lsa * -ospf_lsa_lookup (struct ospf_area *area, u_int32_t type, -                 struct in_addr id, struct in_addr adv_router) -{ -  struct ospf *ospf = ospf_lookup(); -  assert(ospf); - -  switch (type) -    { -    case OSPF_ROUTER_LSA: -    case OSPF_NETWORK_LSA: -    case OSPF_SUMMARY_LSA: -    case OSPF_ASBR_SUMMARY_LSA: -    case OSPF_AS_NSSA_LSA: -    case OSPF_OPAQUE_LINK_LSA: -    case OSPF_OPAQUE_AREA_LSA: -      return ospf_lsdb_lookup_by_id (area->lsdb, type, id, adv_router); -    case OSPF_AS_EXTERNAL_LSA: -    case OSPF_OPAQUE_AS_LSA: -      return ospf_lsdb_lookup_by_id (ospf->lsdb, type, id, adv_router); -    default: -      break; -    } - -  return NULL; -} - -struct ospf_lsa * -ospf_lsa_lookup_by_id (struct ospf_area *area, u_int32_t type,  -                       struct in_addr id) -{ -  struct ospf_lsa *lsa; -  struct route_node *rn; - -  switch (type) -    { -    case OSPF_ROUTER_LSA: -      return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id); -    case OSPF_NETWORK_LSA: -      for (rn = route_top (NETWORK_LSDB (area)); rn; rn = route_next (rn)) -	if ((lsa = rn->info)) -	  if (IPV4_ADDR_SAME (&lsa->data->id, &id)) -	    { -	      route_unlock_node (rn); -	      return lsa; -	    } -      break; -    case OSPF_SUMMARY_LSA: -    case OSPF_ASBR_SUMMARY_LSA: -      /* Currently not used. */ -      assert (1); -      return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id); -    case OSPF_AS_EXTERNAL_LSA: -    case OSPF_AS_NSSA_LSA: -    case OSPF_OPAQUE_LINK_LSA: -    case OSPF_OPAQUE_AREA_LSA: -    case OSPF_OPAQUE_AS_LSA: -      /* Currently not used. */ -      break; -    default: -      break; -    } - -  return NULL; -} - -struct ospf_lsa * -ospf_lsa_lookup_by_header (struct ospf_area *area, struct lsa_header *lsah) -{ -  struct ospf_lsa *match; - -  /* -   * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11) -   * is redefined to have two subfields; opaque-type and opaque-id. -   * However, it is harmless to treat the two sub fields together, as if -   * they two were forming a unique LSA-ID. -   */ - -  match = ospf_lsa_lookup (area, lsah->type, lsah->id, lsah->adv_router); - -  if (match == NULL) -    if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA) -      zlog_debug ("LSA[Type%d:%s]: Lookup by header, NO MATCH", -		 lsah->type, inet_ntoa (lsah->id)); - -  return match; +int ospf_lsa_maxage_walker(struct thread *thread) +{ +	struct ospf *ospf = THREAD_ARG(thread); +	struct route_node *rn; +	struct ospf_lsa *lsa; +	struct ospf_area *area; +	struct listnode *node, *nnode; + +	ospf->t_maxage_walker = NULL; + +	for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { +		LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) +		ospf_lsa_maxage_walker_remover(ospf, lsa); +		LSDB_LOOP(NETWORK_LSDB(area), rn, lsa) +		ospf_lsa_maxage_walker_remover(ospf, lsa); +		LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) +		ospf_lsa_maxage_walker_remover(ospf, lsa); +		LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) +		ospf_lsa_maxage_walker_remover(ospf, lsa); +		LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) +		ospf_lsa_maxage_walker_remover(ospf, lsa); +		LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) +		ospf_lsa_maxage_walker_remover(ospf, lsa); +		LSDB_LOOP(NSSA_LSDB(area), rn, lsa) +		ospf_lsa_maxage_walker_remover(ospf, lsa); +	} + +	/* for AS-external-LSAs. */ +	if (ospf->lsdb) { +		LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) +		ospf_lsa_maxage_walker_remover(ospf, lsa); +		LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa) +		ospf_lsa_maxage_walker_remover(ospf, lsa); +	} + +	OSPF_TIMER_ON(ospf->t_maxage_walker, ospf_lsa_maxage_walker, +		      OSPF_LSA_MAXAGE_CHECK_INTERVAL); +	return 0; +} + +struct ospf_lsa *ospf_lsa_lookup_by_prefix(struct ospf_lsdb *lsdb, u_char type, +					   struct prefix_ipv4 *p, +					   struct in_addr router_id) +{ +	struct ospf_lsa *lsa; +	struct in_addr mask, id; +	struct lsa_header_mask { +		struct lsa_header header; +		struct in_addr mask; +	} * hmask; + +	lsa = ospf_lsdb_lookup_by_id(lsdb, type, p->prefix, router_id); +	if (lsa == NULL) +		return NULL; + +	masklen2ip(p->prefixlen, &mask); + +	hmask = (struct lsa_header_mask *)lsa->data; + +	if (mask.s_addr != hmask->mask.s_addr) { +		id.s_addr = p->prefix.s_addr | (~mask.s_addr); +		lsa = ospf_lsdb_lookup_by_id(lsdb, type, id, router_id); +		if (!lsa) +			return NULL; +	} + +	return lsa; +} + +struct ospf_lsa *ospf_lsa_lookup(struct ospf_area *area, u_int32_t type, +				 struct in_addr id, struct in_addr adv_router) +{ +	struct ospf *ospf = ospf_lookup(); +	assert(ospf); + +	switch (type) { +	case OSPF_ROUTER_LSA: +	case OSPF_NETWORK_LSA: +	case OSPF_SUMMARY_LSA: +	case OSPF_ASBR_SUMMARY_LSA: +	case OSPF_AS_NSSA_LSA: +	case OSPF_OPAQUE_LINK_LSA: +	case OSPF_OPAQUE_AREA_LSA: +		return ospf_lsdb_lookup_by_id(area->lsdb, type, id, adv_router); +	case OSPF_AS_EXTERNAL_LSA: +	case OSPF_OPAQUE_AS_LSA: +		return ospf_lsdb_lookup_by_id(ospf->lsdb, type, id, adv_router); +	default: +		break; +	} + +	return NULL; +} + +struct ospf_lsa *ospf_lsa_lookup_by_id(struct ospf_area *area, u_int32_t type, +				       struct in_addr id) +{ +	struct ospf_lsa *lsa; +	struct route_node *rn; + +	switch (type) { +	case OSPF_ROUTER_LSA: +		return ospf_lsdb_lookup_by_id(area->lsdb, type, id, id); +	case OSPF_NETWORK_LSA: +		for (rn = route_top(NETWORK_LSDB(area)); rn; +		     rn = route_next(rn)) +			if ((lsa = rn->info)) +				if (IPV4_ADDR_SAME(&lsa->data->id, &id)) { +					route_unlock_node(rn); +					return lsa; +				} +		break; +	case OSPF_SUMMARY_LSA: +	case OSPF_ASBR_SUMMARY_LSA: +		/* Currently not used. */ +		assert(1); +		return ospf_lsdb_lookup_by_id(area->lsdb, type, id, id); +	case OSPF_AS_EXTERNAL_LSA: +	case OSPF_AS_NSSA_LSA: +	case OSPF_OPAQUE_LINK_LSA: +	case OSPF_OPAQUE_AREA_LSA: +	case OSPF_OPAQUE_AS_LSA: +		/* Currently not used. */ +		break; +	default: +		break; +	} + +	return NULL; +} + +struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *area, +					   struct lsa_header *lsah) +{ +	struct ospf_lsa *match; + +	/* +	 * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11) +	 * is redefined to have two subfields; opaque-type and opaque-id. +	 * However, it is harmless to treat the two sub fields together, as if +	 * they two were forming a unique LSA-ID. +	 */ + +	match = ospf_lsa_lookup(area, lsah->type, lsah->id, lsah->adv_router); + +	if (match == NULL) +		if (IS_DEBUG_OSPF(lsa, LSA) == OSPF_DEBUG_LSA) +			zlog_debug("LSA[Type%d:%s]: Lookup by header, NO MATCH", +				   lsah->type, inet_ntoa(lsah->id)); + +	return match;  }  /* return +n, l1 is more recent.     return -n, l2 is more recent.     return 0, l1 and l2 is identical. */ -int -ospf_lsa_more_recent (struct ospf_lsa *l1, struct ospf_lsa *l2) -{ -  int r; -  int x, y; - -  if (l1 == NULL && l2 == NULL) -    return 0; -  if (l1 == NULL) -    return -1; -  if (l2 == NULL) -    return 1; - -  /* compare LS sequence number. */ -  x = (int) ntohl (l1->data->ls_seqnum); -  y = (int) ntohl (l2->data->ls_seqnum); -  if (x > y) -    return 1; -  if (x < y) -    return -1; - -  /* compare LS checksum. */ -  r = ntohs (l1->data->checksum) - ntohs (l2->data->checksum); -  if (r) -    return r; - -  /* compare LS age. */ -  if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2)) -    return 1; -  else if (!IS_LSA_MAXAGE (l1) && IS_LSA_MAXAGE (l2)) -    return -1; - -  /* compare LS age with MaxAgeDiff. */ -  if (LS_AGE (l1) - LS_AGE (l2) > OSPF_LSA_MAXAGE_DIFF) -    return -1; -  else if (LS_AGE (l2) - LS_AGE (l1) > OSPF_LSA_MAXAGE_DIFF) -    return 1; - -  /* LSAs are identical. */ -  return 0; +int ospf_lsa_more_recent(struct ospf_lsa *l1, struct ospf_lsa *l2) +{ +	int r; +	int x, y; + +	if (l1 == NULL && l2 == NULL) +		return 0; +	if (l1 == NULL) +		return -1; +	if (l2 == NULL) +		return 1; + +	/* compare LS sequence number. */ +	x = (int)ntohl(l1->data->ls_seqnum); +	y = (int)ntohl(l2->data->ls_seqnum); +	if (x > y) +		return 1; +	if (x < y) +		return -1; + +	/* compare LS checksum. */ +	r = ntohs(l1->data->checksum) - ntohs(l2->data->checksum); +	if (r) +		return r; + +	/* compare LS age. */ +	if (IS_LSA_MAXAGE(l1) && !IS_LSA_MAXAGE(l2)) +		return 1; +	else if (!IS_LSA_MAXAGE(l1) && IS_LSA_MAXAGE(l2)) +		return -1; + +	/* compare LS age with MaxAgeDiff. */ +	if (LS_AGE(l1) - LS_AGE(l2) > OSPF_LSA_MAXAGE_DIFF) +		return -1; +	else if (LS_AGE(l2) - LS_AGE(l1) > OSPF_LSA_MAXAGE_DIFF) +		return 1; + +	/* LSAs are identical. */ +	return 0;  }  /* If two LSAs are different, return 1, otherwise return 0. */ -int -ospf_lsa_different (struct ospf_lsa *l1, struct ospf_lsa *l2) +int ospf_lsa_different(struct ospf_lsa *l1, struct ospf_lsa *l2)  { -  char *p1, *p2; -  assert (l1); -  assert (l2); -  assert (l1->data); -  assert (l2->data); +	char *p1, *p2; +	assert(l1); +	assert(l2); +	assert(l1->data); +	assert(l2->data); -  if (l1->data->options != l2->data->options) -    return 1; +	if (l1->data->options != l2->data->options) +		return 1; -  if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2)) -    return 1; +	if (IS_LSA_MAXAGE(l1) && !IS_LSA_MAXAGE(l2)) +		return 1; -  if (IS_LSA_MAXAGE (l2) && !IS_LSA_MAXAGE (l1)) -    return 1; +	if (IS_LSA_MAXAGE(l2) && !IS_LSA_MAXAGE(l1)) +		return 1; -  if (l1->data->length != l2->data->length) -    return 1; +	if (l1->data->length != l2->data->length) +		return 1; -  if (l1->data->length ==  0) -    return 1; +	if (l1->data->length == 0) +		return 1; -  if (CHECK_FLAG ((l1->flags ^ l2->flags), OSPF_LSA_RECEIVED)) -    return 1; /* May be a stale LSA in the LSBD */ +	if (CHECK_FLAG((l1->flags ^ l2->flags), OSPF_LSA_RECEIVED)) +		return 1; /* May be a stale LSA in the LSBD */ -  assert ( ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE); +	assert(ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE); -  p1 = (char *) l1->data; -  p2 = (char *) l2->data; +	p1 = (char *)l1->data; +	p2 = (char *)l2->data; -  if (memcmp (p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE, -              ntohs( l1->data->length ) - OSPF_LSA_HEADER_SIZE) != 0) -    return 1; +	if (memcmp(p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE, +		   ntohs(l1->data->length) - OSPF_LSA_HEADER_SIZE) +	    != 0) +		return 1; -  return 0; +	return 0;  }  #ifdef ORIGINAL_CODING -void -ospf_lsa_flush_self_originated (struct ospf_neighbor *nbr, -                                struct ospf_lsa *self, -                                struct ospf_lsa *new) -{ -  u_int32_t seqnum; - -  /* Adjust LS Sequence Number. */ -  seqnum = ntohl (new->data->ls_seqnum) + 1; -  self->data->ls_seqnum = htonl (seqnum); - -  /* Recalculate LSA checksum. */ -  ospf_lsa_checksum (self->data); - -  /* Reflooding LSA. */ -  /*  RFC2328  Section 13.3 -	    On non-broadcast networks, separate	Link State Update -	    packets must be sent, as unicasts, to each adjacent	neighbor -	    (i.e., those in state Exchange or greater).	 The destination -	    IP addresses for these packets are the neighbors' IP -	    addresses.   */ -  if (nbr->oi->type == OSPF_IFTYPE_NBMA) -    { -      struct route_node *rn; -      struct ospf_neighbor *onbr; - -      for (rn = route_top (nbr->oi->nbrs); rn; rn = route_next (rn)) -	if ((onbr = rn->info) != NULL) -	  if (onbr != nbr->oi->nbr_self && onbr->status >= NSM_Exchange) -	    ospf_ls_upd_send_lsa (onbr, self, OSPF_SEND_PACKET_DIRECT); -    } -  else -  ospf_ls_upd_send_lsa (nbr, self, OSPF_SEND_PACKET_INDIRECT); - -  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -    zlog_debug ("LSA[Type%d:%s]: Flush self-originated LSA", -	       self->data->type, inet_ntoa (self->data->id)); -} -#else /* ORIGINAL_CODING */ -int -ospf_lsa_flush_schedule (struct ospf *ospf, struct ospf_lsa *lsa) -{ -  if (lsa == NULL || !IS_LSA_SELF (lsa)) -    return 0; - -  if (IS_DEBUG_OSPF_EVENT) -    zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id)); - -  /* Force given lsa's age to MaxAge. */ -  lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - -  switch (lsa->data->type) -    { -    /* Opaque wants to be notified of flushes */ -    case OSPF_OPAQUE_LINK_LSA: -    case OSPF_OPAQUE_AREA_LSA: -    case OSPF_OPAQUE_AS_LSA: -      ospf_opaque_lsa_refresh (lsa); -      break; -    default: -      ospf_refresher_unregister_lsa (ospf, lsa); -      ospf_lsa_flush (ospf, lsa); -      break; -    } - -  return 0; -} - -void -ospf_flush_self_originated_lsas_now (struct ospf *ospf) -{ -  struct listnode *node, *nnode; -  struct listnode *node2, *nnode2; -  struct ospf_area *area; -  struct ospf_interface *oi; -  struct ospf_lsa *lsa; -  struct route_node *rn; -  int need_to_flush_ase = 0; - -  for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) -    { -      if ((lsa = area->router_lsa_self) != NULL) -        { -          if (IS_DEBUG_OSPF_EVENT) -            zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", -                        lsa->data->type, inet_ntoa (lsa->data->id)); -           -          ospf_refresher_unregister_lsa (ospf, lsa); -          ospf_lsa_flush_area (lsa, area); -          ospf_lsa_unlock (&area->router_lsa_self); -          area->router_lsa_self = NULL; -        } - -      for (ALL_LIST_ELEMENTS (area->oiflist, node2, nnode2, oi)) -        { -          if ((lsa = oi->network_lsa_self) != NULL -               &&   oi->state == ISM_DR -               &&   oi->full_nbrs > 0) -            { -              if (IS_DEBUG_OSPF_EVENT) -                zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", -                            lsa->data->type, inet_ntoa (lsa->data->id)); -               -              ospf_refresher_unregister_lsa (ospf, oi->network_lsa_self); -              ospf_lsa_flush_area (oi->network_lsa_self, area); -              ospf_lsa_unlock (&oi->network_lsa_self); -              oi->network_lsa_self = NULL; -            } - -          if (oi->type != OSPF_IFTYPE_VIRTUALLINK -          &&  area->external_routing == OSPF_AREA_DEFAULT) -            need_to_flush_ase = 1; -        } - -      LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) -	ospf_lsa_flush_schedule (ospf, lsa); -      LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) -	ospf_lsa_flush_schedule (ospf, lsa); -      LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) -	ospf_lsa_flush_schedule (ospf, lsa); -      LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) -	ospf_lsa_flush_schedule (ospf, lsa); -    } - -  if (need_to_flush_ase) -    { -      LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) -	ospf_lsa_flush_schedule (ospf, lsa); -      LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) -	ospf_lsa_flush_schedule (ospf, lsa); -    } - -  /* -   * Make sure that the MaxAge LSA remover is executed immediately, -   * without conflicting to other threads. -   */ -  if (ospf->t_maxage != NULL) -    { -      OSPF_TIMER_OFF (ospf->t_maxage); -      thread_execute (master, ospf_maxage_lsa_remover, ospf, 0); -    } - -  return; +void ospf_lsa_flush_self_originated(struct ospf_neighbor *nbr, +				    struct ospf_lsa *self, struct ospf_lsa *new) +{ +	u_int32_t seqnum; + +	/* Adjust LS Sequence Number. */ +	seqnum = ntohl(new->data->ls_seqnum) + 1; +	self->data->ls_seqnum = htonl(seqnum); + +	/* Recalculate LSA checksum. */ +	ospf_lsa_checksum(self->data); + +	/* Reflooding LSA. */ +	/*  RFC2328  Section 13.3 +		  On non-broadcast networks, separate	Link State Update +		  packets must be sent, as unicasts, to each adjacent	neighbor +		  (i.e., those in state Exchange or greater).	 The destination +		  IP addresses for these packets are the neighbors' IP +		  addresses.   */ +	if (nbr->oi->type == OSPF_IFTYPE_NBMA) { +		struct route_node *rn; +		struct ospf_neighbor *onbr; + +		for (rn = route_top(nbr->oi->nbrs); rn; rn = route_next(rn)) +			if ((onbr = rn->info) != NULL) +				if (onbr != nbr->oi->nbr_self +				    && onbr->status >= NSM_Exchange) +					ospf_ls_upd_send_lsa( +						onbr, self, +						OSPF_SEND_PACKET_DIRECT); +	} else +		ospf_ls_upd_send_lsa(nbr, self, OSPF_SEND_PACKET_INDIRECT); + +	if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +		zlog_debug("LSA[Type%d:%s]: Flush self-originated LSA", +			   self->data->type, inet_ntoa(self->data->id)); +} +#else  /* ORIGINAL_CODING */ +int ospf_lsa_flush_schedule(struct ospf *ospf, struct ospf_lsa *lsa) +{ +	if (lsa == NULL || !IS_LSA_SELF(lsa)) +		return 0; + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug( +			"LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", +			lsa->data->type, inet_ntoa(lsa->data->id)); + +	/* Force given lsa's age to MaxAge. */ +	lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + +	switch (lsa->data->type) { +	/* Opaque wants to be notified of flushes */ +	case OSPF_OPAQUE_LINK_LSA: +	case OSPF_OPAQUE_AREA_LSA: +	case OSPF_OPAQUE_AS_LSA: +		ospf_opaque_lsa_refresh(lsa); +		break; +	default: +		ospf_refresher_unregister_lsa(ospf, lsa); +		ospf_lsa_flush(ospf, lsa); +		break; +	} + +	return 0; +} + +void ospf_flush_self_originated_lsas_now(struct ospf *ospf) +{ +	struct listnode *node, *nnode; +	struct listnode *node2, *nnode2; +	struct ospf_area *area; +	struct ospf_interface *oi; +	struct ospf_lsa *lsa; +	struct route_node *rn; +	int need_to_flush_ase = 0; + +	for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { +		if ((lsa = area->router_lsa_self) != NULL) { +			if (IS_DEBUG_OSPF_EVENT) +				zlog_debug( +					"LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", +					lsa->data->type, +					inet_ntoa(lsa->data->id)); + +			ospf_refresher_unregister_lsa(ospf, lsa); +			ospf_lsa_flush_area(lsa, area); +			ospf_lsa_unlock(&area->router_lsa_self); +			area->router_lsa_self = NULL; +		} + +		for (ALL_LIST_ELEMENTS(area->oiflist, node2, nnode2, oi)) { +			if ((lsa = oi->network_lsa_self) != NULL +			    && oi->state == ISM_DR && oi->full_nbrs > 0) { +				if (IS_DEBUG_OSPF_EVENT) +					zlog_debug( +						"LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", +						lsa->data->type, +						inet_ntoa(lsa->data->id)); + +				ospf_refresher_unregister_lsa( +					ospf, oi->network_lsa_self); +				ospf_lsa_flush_area(oi->network_lsa_self, area); +				ospf_lsa_unlock(&oi->network_lsa_self); +				oi->network_lsa_self = NULL; +			} + +			if (oi->type != OSPF_IFTYPE_VIRTUALLINK +			    && area->external_routing == OSPF_AREA_DEFAULT) +				need_to_flush_ase = 1; +		} + +		LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) +		ospf_lsa_flush_schedule(ospf, lsa); +		LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) +		ospf_lsa_flush_schedule(ospf, lsa); +		LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) +		ospf_lsa_flush_schedule(ospf, lsa); +		LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) +		ospf_lsa_flush_schedule(ospf, lsa); +	} + +	if (need_to_flush_ase) { +		LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) +		ospf_lsa_flush_schedule(ospf, lsa); +		LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa) +		ospf_lsa_flush_schedule(ospf, lsa); +	} + +	/* +	 * Make sure that the MaxAge LSA remover is executed immediately, +	 * without conflicting to other threads. +	 */ +	if (ospf->t_maxage != NULL) { +		OSPF_TIMER_OFF(ospf->t_maxage); +		thread_execute(master, ospf_maxage_lsa_remover, ospf, 0); +	} + +	return;  }  #endif /* ORIGINAL_CODING */  /* If there is self-originated LSA, then return 1, otherwise return 0. */  /* An interface-independent version of ospf_lsa_is_self_originated */ -int  -ospf_lsa_is_self_originated (struct ospf *ospf, struct ospf_lsa *lsa) -{ -  struct listnode *node; -  struct ospf_interface *oi; - -  /* This LSA is already checked. */ -  if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED)) -    return IS_LSA_SELF (lsa); - -  /* Make sure LSA is self-checked. */ -  SET_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED); - -  /* AdvRouter and Router ID is the same. */ -  if (IPV4_ADDR_SAME (&lsa->data->adv_router, &ospf->router_id)) -    SET_FLAG (lsa->flags, OSPF_LSA_SELF); - -  /* LSA is router-LSA. */ -  else if (lsa->data->type == OSPF_ROUTER_LSA && -      IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id)) -    SET_FLAG (lsa->flags, OSPF_LSA_SELF); - -  /* LSA is network-LSA.  Compare Link ID with all interfaces. */ -  else if (lsa->data->type == OSPF_NETWORK_LSA) -    for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) -      { -	/* Ignore virtual link. */ -        if (oi->type != OSPF_IFTYPE_VIRTUALLINK) -	  if (oi->address->family == AF_INET) -	    if (IPV4_ADDR_SAME (&lsa->data->id, &oi->address->u.prefix4)) -	      { -		/* to make it easier later */ -		SET_FLAG (lsa->flags, OSPF_LSA_SELF); -		return IS_LSA_SELF (lsa); -	      } -      } - -  return IS_LSA_SELF (lsa); +int ospf_lsa_is_self_originated(struct ospf *ospf, struct ospf_lsa *lsa) +{ +	struct listnode *node; +	struct ospf_interface *oi; + +	/* This LSA is already checked. */ +	if (CHECK_FLAG(lsa->flags, OSPF_LSA_SELF_CHECKED)) +		return IS_LSA_SELF(lsa); + +	/* Make sure LSA is self-checked. */ +	SET_FLAG(lsa->flags, OSPF_LSA_SELF_CHECKED); + +	/* AdvRouter and Router ID is the same. */ +	if (IPV4_ADDR_SAME(&lsa->data->adv_router, &ospf->router_id)) +		SET_FLAG(lsa->flags, OSPF_LSA_SELF); + +	/* LSA is router-LSA. */ +	else if (lsa->data->type == OSPF_ROUTER_LSA +		 && IPV4_ADDR_SAME(&lsa->data->id, &ospf->router_id)) +		SET_FLAG(lsa->flags, OSPF_LSA_SELF); + +	/* LSA is network-LSA.  Compare Link ID with all interfaces. */ +	else if (lsa->data->type == OSPF_NETWORK_LSA) +		for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { +			/* Ignore virtual link. */ +			if (oi->type != OSPF_IFTYPE_VIRTUALLINK) +				if (oi->address->family == AF_INET) +					if (IPV4_ADDR_SAME( +						    &lsa->data->id, +						    &oi->address->u.prefix4)) { +						/* to make it easier later */ +						SET_FLAG(lsa->flags, +							 OSPF_LSA_SELF); +						return IS_LSA_SELF(lsa); +					} +		} + +	return IS_LSA_SELF(lsa);  }  /* Get unique Link State ID. */ -struct in_addr -ospf_lsa_unique_id (struct ospf *ospf, -		    struct ospf_lsdb *lsdb, u_char type, struct prefix_ipv4 *p) -{ -  struct ospf_lsa *lsa; -  struct in_addr mask, id; - -  id = p->prefix; - -  /* Check existence of LSA instance. */ -  lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, ospf->router_id); -  if (lsa) -    { -      struct as_external_lsa *al = (struct as_external_lsa *) lsa->data; -      if (ip_masklen (al->mask) == p->prefixlen) -	{ -	  if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -	    zlog_debug ("ospf_lsa_unique_id(): " -		       "Can't get Link State ID for %s/%d", -		       inet_ntoa (p->prefix), p->prefixlen); -	  /*	  id.s_addr = 0; */ -	  id.s_addr = 0xffffffff; -	  return id; -	} -      /* Masklen differs, then apply wildcard mask to Link State ID. */ -      else -	{ -	  masklen2ip (p->prefixlen, &mask); - -	  id.s_addr = p->prefix.s_addr | (~mask.s_addr); -	  lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, type, -				       id, ospf->router_id); -	  if (lsa) -	    { -	      if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) -		zlog_debug ("ospf_lsa_unique_id(): " -			   "Can't get Link State ID for %s/%d", -			   inet_ntoa (p->prefix), p->prefixlen); -	      /* 	      id.s_addr = 0; */ -	      id.s_addr = 0xffffffff; -	      return id; -	    } -	} -    } - -  return id; +struct in_addr ospf_lsa_unique_id(struct ospf *ospf, struct ospf_lsdb *lsdb, +				  u_char type, struct prefix_ipv4 *p) +{ +	struct ospf_lsa *lsa; +	struct in_addr mask, id; + +	id = p->prefix; + +	/* Check existence of LSA instance. */ +	lsa = ospf_lsdb_lookup_by_id(lsdb, type, id, ospf->router_id); +	if (lsa) { +		struct as_external_lsa *al = +			(struct as_external_lsa *)lsa->data; +		if (ip_masklen(al->mask) == p->prefixlen) { +			if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +				zlog_debug( +					"ospf_lsa_unique_id(): " +					"Can't get Link State ID for %s/%d", +					inet_ntoa(p->prefix), p->prefixlen); +			/*	  id.s_addr = 0; */ +			id.s_addr = 0xffffffff; +			return id; +		} +		/* Masklen differs, then apply wildcard mask to Link State ID. +		   */ +		else { +			masklen2ip(p->prefixlen, &mask); + +			id.s_addr = p->prefix.s_addr | (~mask.s_addr); +			lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, type, id, +						     ospf->router_id); +			if (lsa) { +				if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) +					zlog_debug( +						"ospf_lsa_unique_id(): " +						"Can't get Link State ID for %s/%d", +						inet_ntoa(p->prefix), +						p->prefixlen); +				/* 	      id.s_addr = 0; */ +				id.s_addr = 0xffffffff; +				return id; +			} +		} +	} + +	return id;  }  #define LSA_ACTION_FLOOD_AREA 1  #define LSA_ACTION_FLUSH_AREA 2 -struct lsa_action -{ -  u_char action; -  struct ospf_area *area; -  struct ospf_lsa *lsa; +struct lsa_action { +	u_char action; +	struct ospf_area *area; +	struct ospf_lsa *lsa;  }; -static int -ospf_lsa_action (struct thread *t) +static int ospf_lsa_action(struct thread *t)  { -  struct lsa_action *data; +	struct lsa_action *data; -  data = THREAD_ARG (t); +	data = THREAD_ARG(t); -  if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA) -    zlog_debug ("LSA[Action]: Performing scheduled LSA action: %d", -	       data->action); +	if (IS_DEBUG_OSPF(lsa, LSA) == OSPF_DEBUG_LSA) +		zlog_debug("LSA[Action]: Performing scheduled LSA action: %d", +			   data->action); -  switch (data->action) -    { -    case LSA_ACTION_FLOOD_AREA: -      ospf_flood_through_area (data->area, NULL, data->lsa); -      break; -    case LSA_ACTION_FLUSH_AREA: -      ospf_lsa_flush_area (data->lsa, data->area); -      break; -    } +	switch (data->action) { +	case LSA_ACTION_FLOOD_AREA: +		ospf_flood_through_area(data->area, NULL, data->lsa); +		break; +	case LSA_ACTION_FLUSH_AREA: +		ospf_lsa_flush_area(data->lsa, data->area); +		break; +	} -  ospf_lsa_unlock (&data->lsa); /* Message */ -  XFREE (MTYPE_OSPF_MESSAGE, data); -  return 0; +	ospf_lsa_unlock(&data->lsa); /* Message */ +	XFREE(MTYPE_OSPF_MESSAGE, data); +	return 0;  } -void -ospf_schedule_lsa_flood_area (struct ospf_area *area, struct ospf_lsa *lsa) +void ospf_schedule_lsa_flood_area(struct ospf_area *area, struct ospf_lsa *lsa)  { -  struct lsa_action *data; +	struct lsa_action *data; -  data = XCALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action)); -  data->action = LSA_ACTION_FLOOD_AREA; -  data->area = area; -  data->lsa  = ospf_lsa_lock (lsa); /* Message / Flood area */ +	data = XCALLOC(MTYPE_OSPF_MESSAGE, sizeof(struct lsa_action)); +	data->action = LSA_ACTION_FLOOD_AREA; +	data->area = area; +	data->lsa = ospf_lsa_lock(lsa); /* Message / Flood area */ -  thread_add_event(master, ospf_lsa_action, data, 0, NULL); +	thread_add_event(master, ospf_lsa_action, data, 0, NULL);  } -void -ospf_schedule_lsa_flush_area (struct ospf_area *area, struct ospf_lsa *lsa) +void ospf_schedule_lsa_flush_area(struct ospf_area *area, struct ospf_lsa *lsa)  { -  struct lsa_action *data; +	struct lsa_action *data; -  data = XCALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action)); -  data->action = LSA_ACTION_FLUSH_AREA; -  data->area = area; -  data->lsa  = ospf_lsa_lock (lsa); /* Message / Flush area */ +	data = XCALLOC(MTYPE_OSPF_MESSAGE, sizeof(struct lsa_action)); +	data->action = LSA_ACTION_FLUSH_AREA; +	data->area = area; +	data->lsa = ospf_lsa_lock(lsa); /* Message / Flush area */ -  thread_add_event(master, ospf_lsa_action, data, 0, NULL); +	thread_add_event(master, ospf_lsa_action, data, 0, NULL);  }  /* LSA Refreshment functions. */ -struct ospf_lsa * -ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa) -{ -  struct external_info *ei; -  struct ospf_lsa *new = NULL; -  assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF)); -  assert (IS_LSA_SELF (lsa)); -  assert (lsa->lock > 0); - -  switch (lsa->data->type) -    { -      /* Router and Network LSAs are processed differently. */ -    case OSPF_ROUTER_LSA: -      new = ospf_router_lsa_refresh (lsa); -      break; -    case OSPF_NETWORK_LSA:  -      new = ospf_network_lsa_refresh (lsa); -      break; -    case OSPF_SUMMARY_LSA: -      new = ospf_summary_lsa_refresh (ospf, lsa); -      break; -    case OSPF_ASBR_SUMMARY_LSA: -      new = ospf_summary_asbr_lsa_refresh (ospf, lsa); -      break; -    case OSPF_AS_EXTERNAL_LSA: -      /* Translated from NSSA Type-5s are refreshed when  -       * from refresh of Type-7 - do not refresh these directly. -       */ -      if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) -        break; -      ei = ospf_external_info_check (lsa); -      if (ei) -        new = ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE); -      else -        ospf_lsa_flush_as (ospf, lsa); -      break; -    case OSPF_OPAQUE_LINK_LSA: -    case OSPF_OPAQUE_AREA_LSA: -    case OSPF_OPAQUE_AS_LSA: -      new = ospf_opaque_lsa_refresh (lsa); -      break; -    default: -      break; -    } -  return new; -} - -void -ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa) -{ -  u_int16_t index, current_index; -   -  assert (lsa->lock > 0); -  assert (IS_LSA_SELF (lsa)); - -  if (lsa->refresh_list < 0) -    { -      int delay; -      int min_delay = OSPF_LS_REFRESH_TIME - (2 * OSPF_LS_REFRESH_JITTER); -      int max_delay = OSPF_LS_REFRESH_TIME - OSPF_LS_REFRESH_JITTER; - -      /* We want to refresh the LSA within OSPF_LS_REFRESH_TIME which is -       * 1800s. Use jitter so that we send the LSA sometime between 1680s -       * and 1740s. -       */ -      delay = (random() % (max_delay - min_delay)) + min_delay; - -      current_index = ospf->lsa_refresh_queue.index + (monotime(NULL) -                                                       - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY; -       -      index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY) -	      % (OSPF_LSA_REFRESHER_SLOTS); - -      if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) -	zlog_debug ("LSA[Refresh:Type%d:%s]: age %d, added to index %d", -		    lsa->data->type, inet_ntoa (lsa->data->id), LS_AGE (lsa), index); - -      if (!ospf->lsa_refresh_queue.qs[index]) -	ospf->lsa_refresh_queue.qs[index] = list_new (); - -      listnode_add (ospf->lsa_refresh_queue.qs[index], -                    ospf_lsa_lock (lsa)); /* lsa_refresh_queue */ -      lsa->refresh_list = index; - -      if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) -        zlog_debug ("LSA[Refresh:Type%d:%s]: ospf_refresher_register_lsa(): " -                   "setting refresh_list on lsa %p (slod %d)",  -		    lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa, index); -    } -} - -void -ospf_refresher_unregister_lsa (struct ospf *ospf, struct ospf_lsa *lsa) -{ -  assert (lsa->lock > 0); -  assert (IS_LSA_SELF (lsa)); -  if (lsa->refresh_list >= 0) -    { -      struct list *refresh_list = ospf->lsa_refresh_queue.qs[lsa->refresh_list]; -      listnode_delete (refresh_list, lsa); -      if (!listcount (refresh_list)) -	{ -	  list_free (refresh_list); -	  ospf->lsa_refresh_queue.qs[lsa->refresh_list] = NULL; -	} -      ospf_lsa_unlock (&lsa); /* lsa_refresh_queue */ -      lsa->refresh_list = -1; -    } -} - -int -ospf_lsa_refresh_walker (struct thread *t) -{ -  struct list *refresh_list; -  struct listnode *node, *nnode; -  struct ospf *ospf = THREAD_ARG (t); -  struct ospf_lsa *lsa; -  int i; -  struct list *lsa_to_refresh = list_new (); - -  if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) -    zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): start"); - -   -  i = ospf->lsa_refresh_queue.index; -   -  /* Note: if clock has jumped backwards, then time change could be negative, -     so we are careful to cast the expression to unsigned before taking -     modulus. */ -  ospf->lsa_refresh_queue.index = -   ((unsigned long)(ospf->lsa_refresh_queue.index + -		    (monotime(NULL) - ospf->lsa_refresher_started) -		    / OSPF_LSA_REFRESHER_GRANULARITY)) -		    % OSPF_LSA_REFRESHER_SLOTS; - -  if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) -    zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d", -	       ospf->lsa_refresh_queue.index); - -  for (;i != ospf->lsa_refresh_queue.index; -       i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS) -    { -      if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) -	zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): " -	           "refresh index %d", i); - -      refresh_list = ospf->lsa_refresh_queue.qs [i]; -       -      assert (i >= 0); - -      ospf->lsa_refresh_queue.qs [i] = NULL; - -      if (refresh_list) -	{ -	  for (ALL_LIST_ELEMENTS (refresh_list, node, nnode, lsa)) -	    { -	      if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) -		zlog_debug ("LSA[Refresh:Type%d:%s]: ospf_lsa_refresh_walker(): " -		           "refresh lsa %p (slot %d)", -			    lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa, i); - -	      assert (lsa->lock > 0); -	      list_delete_node (refresh_list, node); -	      lsa->refresh_list = -1; -	      listnode_add (lsa_to_refresh, lsa); -	    } -	  list_free (refresh_list); -	} -    } - -  ospf->t_lsa_refresher = NULL; -  thread_add_timer(master, ospf_lsa_refresh_walker, ospf, ospf->lsa_refresh_interval, -                   &ospf->t_lsa_refresher); -  ospf->lsa_refresher_started = monotime(NULL); - -  for (ALL_LIST_ELEMENTS (lsa_to_refresh, node, nnode, lsa)) -    { -      ospf_lsa_refresh (ospf, lsa); -      assert (lsa->lock > 0); -      ospf_lsa_unlock (&lsa); /* lsa_refresh_queue & temp for lsa_to_refresh*/ -    } -   -  list_delete (lsa_to_refresh); -   -  if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) -    zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): end"); -   -  return 0; +struct ospf_lsa *ospf_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa) +{ +	struct external_info *ei; +	struct ospf_lsa *new = NULL; +	assert(CHECK_FLAG(lsa->flags, OSPF_LSA_SELF)); +	assert(IS_LSA_SELF(lsa)); +	assert(lsa->lock > 0); + +	switch (lsa->data->type) { +	/* Router and Network LSAs are processed differently. */ +	case OSPF_ROUTER_LSA: +		new = ospf_router_lsa_refresh(lsa); +		break; +	case OSPF_NETWORK_LSA: +		new = ospf_network_lsa_refresh(lsa); +		break; +	case OSPF_SUMMARY_LSA: +		new = ospf_summary_lsa_refresh(ospf, lsa); +		break; +	case OSPF_ASBR_SUMMARY_LSA: +		new = ospf_summary_asbr_lsa_refresh(ospf, lsa); +		break; +	case OSPF_AS_EXTERNAL_LSA: +		/* Translated from NSSA Type-5s are refreshed when +		 * from refresh of Type-7 - do not refresh these directly. +		 */ +		if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) +			break; +		ei = ospf_external_info_check(lsa); +		if (ei) +			new = ospf_external_lsa_refresh(ospf, lsa, ei, +							LSA_REFRESH_FORCE); +		else +			ospf_lsa_flush_as(ospf, lsa); +		break; +	case OSPF_OPAQUE_LINK_LSA: +	case OSPF_OPAQUE_AREA_LSA: +	case OSPF_OPAQUE_AS_LSA: +		new = ospf_opaque_lsa_refresh(lsa); +		break; +	default: +		break; +	} +	return new;  } +void ospf_refresher_register_lsa(struct ospf *ospf, struct ospf_lsa *lsa) +{ +	u_int16_t index, current_index; + +	assert(lsa->lock > 0); +	assert(IS_LSA_SELF(lsa)); + +	if (lsa->refresh_list < 0) { +		int delay; +		int min_delay = +			OSPF_LS_REFRESH_TIME - (2 * OSPF_LS_REFRESH_JITTER); +		int max_delay = OSPF_LS_REFRESH_TIME - OSPF_LS_REFRESH_JITTER; + +		/* We want to refresh the LSA within OSPF_LS_REFRESH_TIME which +		 * is +		 * 1800s. Use jitter so that we send the LSA sometime between +		 * 1680s +		 * and 1740s. +		 */ +		delay = (random() % (max_delay - min_delay)) + min_delay; + +		current_index = ospf->lsa_refresh_queue.index +				+ (monotime(NULL) - ospf->lsa_refresher_started) +					  / OSPF_LSA_REFRESHER_GRANULARITY; + +		index = (current_index + delay / OSPF_LSA_REFRESHER_GRANULARITY) +			% (OSPF_LSA_REFRESHER_SLOTS); + +		if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) +			zlog_debug( +				"LSA[Refresh:Type%d:%s]: age %d, added to index %d", +				lsa->data->type, inet_ntoa(lsa->data->id), +				LS_AGE(lsa), index); + +		if (!ospf->lsa_refresh_queue.qs[index]) +			ospf->lsa_refresh_queue.qs[index] = list_new(); + +		listnode_add(ospf->lsa_refresh_queue.qs[index], +			     ospf_lsa_lock(lsa)); /* lsa_refresh_queue */ +		lsa->refresh_list = index; + +		if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) +			zlog_debug( +				"LSA[Refresh:Type%d:%s]: ospf_refresher_register_lsa(): " +				"setting refresh_list on lsa %p (slod %d)", +				lsa->data->type, inet_ntoa(lsa->data->id), +				(void *)lsa, index); +	} +} + +void ospf_refresher_unregister_lsa(struct ospf *ospf, struct ospf_lsa *lsa) +{ +	assert(lsa->lock > 0); +	assert(IS_LSA_SELF(lsa)); +	if (lsa->refresh_list >= 0) { +		struct list *refresh_list = +			ospf->lsa_refresh_queue.qs[lsa->refresh_list]; +		listnode_delete(refresh_list, lsa); +		if (!listcount(refresh_list)) { +			list_free(refresh_list); +			ospf->lsa_refresh_queue.qs[lsa->refresh_list] = NULL; +		} +		ospf_lsa_unlock(&lsa); /* lsa_refresh_queue */ +		lsa->refresh_list = -1; +	} +} + +int ospf_lsa_refresh_walker(struct thread *t) +{ +	struct list *refresh_list; +	struct listnode *node, *nnode; +	struct ospf *ospf = THREAD_ARG(t); +	struct ospf_lsa *lsa; +	int i; +	struct list *lsa_to_refresh = list_new(); + +	if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) +		zlog_debug("LSA[Refresh]: ospf_lsa_refresh_walker(): start"); + + +	i = ospf->lsa_refresh_queue.index; + +	/* Note: if clock has jumped backwards, then time change could be +	   negative, +	   so we are careful to cast the expression to unsigned before taking +	   modulus. */ +	ospf->lsa_refresh_queue.index = +		((unsigned long)(ospf->lsa_refresh_queue.index +				 + (monotime(NULL) +				    - ospf->lsa_refresher_started) +					   / OSPF_LSA_REFRESHER_GRANULARITY)) +		% OSPF_LSA_REFRESHER_SLOTS; + +	if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) +		zlog_debug( +			"LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d", +			ospf->lsa_refresh_queue.index); + +	for (; i != ospf->lsa_refresh_queue.index; +	     i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS) { +		if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) +			zlog_debug( +				"LSA[Refresh]: ospf_lsa_refresh_walker(): " +				"refresh index %d", +				i); + +		refresh_list = ospf->lsa_refresh_queue.qs[i]; + +		assert(i >= 0); + +		ospf->lsa_refresh_queue.qs[i] = NULL; + +		if (refresh_list) { +			for (ALL_LIST_ELEMENTS(refresh_list, node, nnode, +					       lsa)) { +				if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) +					zlog_debug( +						"LSA[Refresh:Type%d:%s]: ospf_lsa_refresh_walker(): " +						"refresh lsa %p (slot %d)", +						lsa->data->type, +						inet_ntoa(lsa->data->id), +						(void *)lsa, i); + +				assert(lsa->lock > 0); +				list_delete_node(refresh_list, node); +				lsa->refresh_list = -1; +				listnode_add(lsa_to_refresh, lsa); +			} +			list_free(refresh_list); +		} +	} + +	ospf->t_lsa_refresher = NULL; +	thread_add_timer(master, ospf_lsa_refresh_walker, ospf, +			 ospf->lsa_refresh_interval, &ospf->t_lsa_refresher); +	ospf->lsa_refresher_started = monotime(NULL); + +	for (ALL_LIST_ELEMENTS(lsa_to_refresh, node, nnode, lsa)) { +		ospf_lsa_refresh(ospf, lsa); +		assert(lsa->lock > 0); +		ospf_lsa_unlock( +			&lsa); /* lsa_refresh_queue & temp for lsa_to_refresh*/ +	} + +	list_delete(lsa_to_refresh); + +	if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) +		zlog_debug("LSA[Refresh]: ospf_lsa_refresh_walker(): end"); + +	return 0; +}  | 
