Commit 74a38adb authored by Maria Matejka's avatar Maria Matejka
Browse files

Merge branch 'master' of gitlab.labs.nic.cz:labs/bird

parents 1322e205 2872ab92
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -246,18 +246,33 @@ void
ospf_stop_gr_recovery(struct ospf_proto *p)
{
  p->gr_recovery = 0;
  p->gr_cleanup = 1;
  p->gr_timeout = 0;
  channel_graceful_restart_unlock(p->p.main_channel);

  /* Reorigination of router/network LSAs is already scheduled */
  ospf_mark_lsadb(p);

  /*
   * NOTE: We should move channel_graceful_restart_unlock() to the end of
   * ospf_disp() in order to have local LSA reorigination / LSAdb cleanup /
   * routing table recomputation before official end of GR. It does not matter
   * when we are single-threaded.
   */
  /* Rest is done in ospf_cleanup_gr_recovery() */
}

static void
ospf_cleanup_gr_recovery(struct ospf_proto *p)
{
  struct top_hash_entry *en;

  /* Flush dirty LSAa except external ones, these will be handled by feed */
  WALK_SLIST(en, p->lsal)
    if (en->gr_dirty)
    {
      if ((en->lsa_type == LSA_T_EXT) || (en->lsa_type == LSA_T_NSSA))
	en->mode = LSA_M_EXPORT;
      else
	ospf_flush_lsa(p, en);
    }

  /* End graceful restart on channel, will also schedule feed */
  channel_graceful_restart_unlock(p->p.main_channel);

  p->gr_cleanup = 0;
}

static int
@@ -361,6 +376,8 @@ ospf_init(struct proto_config *CF)
  P->ifa_notify = cf->ospf2 ? ospf_ifa_notify2 : ospf_ifa_notify3;
  P->preexport = ospf_preexport;
  P->reload_routes = ospf_reload_routes;
  P->feed_begin = ospf_feed_begin;
  P->feed_end = ospf_feed_end;
  P->make_tmp_attrs = ospf_make_tmp_attrs;
  P->store_tmp_attrs = ospf_store_tmp_attrs;
  P->rte_better = ospf_rte_better;
@@ -436,6 +453,7 @@ ospf_disp(timer * timer)
{
  struct ospf_proto *p = timer->data;

  /* Check for end of graceful restart */
  if (p->gr_recovery)
    ospf_update_gr_recovery(p);

@@ -448,6 +466,10 @@ ospf_disp(timer * timer)
  /* Calculate routing table */
  if (p->calcrt)
    ospf_rt_spf(p);

  /* Cleanup after graceful restart */
  if (p->gr_cleanup)
    ospf_cleanup_gr_recovery(p);
}


+2 −1
Original line number Diff line number Diff line
@@ -223,7 +223,8 @@ struct ospf_proto
  int areano;			/* Number of area I belong to */
  int padj;			/* Number of neighbors in Exchange or Loading state */
  int gr_count;			/* Number of neighbors in graceful restart state */
  int gr_recovery;		/* Graceful restart recovery is active */
  u8 gr_recovery;		/* Graceful restart recovery is active */
  u8 gr_cleanup;		/* GR cleanup scheduled */
  btime gr_timeout;		/* The end time of grace restart recovery */
  struct fib rtf;		/* Routing table */
  struct idm idm;		/* OSPFv3 LSA ID map */
+2 −2
Original line number Diff line number Diff line
@@ -1640,7 +1640,7 @@ ospf_rt_reset(struct ospf_proto *p)
    en->lb = IPA_NONE;

    if (en->mode == LSA_M_RTCALC)
      en->mode = LSA_M_STALE;
      en->mode = LSA_M_RTCALC_STALE;
  }

  WALK_LIST(oa, p->area_list)
@@ -2117,7 +2117,7 @@ again2:

  /* Cleanup stale LSAs */
  WALK_SLIST(en, p->lsal)
    if (en->mode == LSA_M_STALE)
    if (en->mode == LSA_M_RTCALC_STALE)
      ospf_flush_lsa(p, en);
}

+21 −12
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ ospf_install_lsa(struct ospf_proto *p, struct ospf_lsa_header *lsa, u32 type, u3
  en->lsa = *lsa;
  en->init_age = en->lsa.age;
  en->inst_time = current_time();
  en->gr_dirty = p->gr_recovery && (lsa->rt == p->router_id);

  /*
   * We do not set en->mode. It is either default LSA_M_BASIC, or in a special
@@ -246,7 +247,7 @@ ospf_do_originate_lsa(struct ospf_proto *p, struct top_hash_entry *en, void *lsa
  en->lsa.age = 0;
  en->init_age = 0;
  en->inst_time = current_time();
  en->dirty = 0;
  en->gr_dirty = 0;
  lsa_generate_checksum(&en->lsa, en->lsa_body);

  OSPF_TRACE(D_EVENTS, "Originating LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
@@ -329,7 +330,7 @@ ospf_originate_lsa(struct ospf_proto *p, struct ospf_new_lsa *lsa)
      (lsa_length == en->lsa.length) &&
      !memcmp(lsa_body, en->lsa_body, lsa_blen) &&
      (!ospf_is_v2(p) || (lsa->opts == lsa_get_options(&en->lsa))) &&
      !en->dirty)
      !en->gr_dirty)
    goto drop;

  lsa_body = lsab_flush(p);
@@ -422,6 +423,7 @@ void
ospf_flush_lsa(struct ospf_proto *p, struct top_hash_entry *en)
{
  en->nf = NULL;
  en->gr_dirty = 0;

  if (en->next_lsa_body)
  {
@@ -520,12 +522,6 @@ ospf_update_lsadb(struct ospf_proto *p)
      continue;
    }

    if (en->dirty)
    {
      ospf_flush_lsa(p, en);
      continue;
    }

    if ((en->lsa.rt == p->router_id) && (real_age >= LSREFRESHTIME))
    {
      ospf_refresh_lsa(p, en);
@@ -543,14 +539,27 @@ ospf_update_lsadb(struct ospf_proto *p)
}

void
ospf_mark_lsadb(struct ospf_proto *p)
ospf_feed_begin(struct channel *C, int initial UNUSED)
{
  struct ospf_proto *p = (struct ospf_proto *) C->proto;
  struct top_hash_entry *en;

  /* Mark all local LSAs as dirty */
  /* Mark all external LSAs as stale */
  WALK_SLIST(en, p->lsal)
    if (en->lsa.rt == p->router_id)
      en->dirty = 1;
    if (en->mode == LSA_M_EXPORT)
      en->mode = LSA_M_EXPORT_STALE;
}

void
ospf_feed_end(struct channel *C)
{
  struct ospf_proto *p = (struct ospf_proto *) C->proto;
  struct top_hash_entry *en;

  /* Flush stale LSAs */
  WALK_SLIST(en, p->lsal)
    if (en->mode == LSA_M_EXPORT_STALE)
      ospf_flush_lsa(p, en);
}

static u32
+20 −11
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ struct top_hash_entry
  u32 lb_id;			/* Interface ID of link back iface (for bcast or NBMA networks) */
  u32 dist;			/* Distance from the root */
  int ret_count;		/* Number of retransmission lists referencing the entry */
  u8 dirty;			/* Will be flushed during next LSAdb update unless reoriginated*/
  u8 gr_dirty;			/* Local LSA received during GR, will be removed unless reoriginated */
  u8 color;
#define OUTSPF 0
#define CANDIDATE 1
@@ -118,7 +118,8 @@ struct top_hash_entry
#define LSA_M_BASIC		0
#define LSA_M_EXPORT		1
#define LSA_M_RTCALC		2
#define LSA_M_STALE	3
#define LSA_M_EXPORT_STALE	3
#define LSA_M_RTCALC_STALE	4

/*
 * LSA entry modes:
@@ -128,9 +129,13 @@ struct top_hash_entry
 * routing table calculation is scheduled. This is also the mode used for LSAs
 * received from neighbors. Example: Router-LSAs, Network-LSAs.
 *
 * LSA_M_EXPORT - like LSA_M_BASIC, but the routing table calculation does not
 * depend on the LSA. Therefore, the calculation is not scheduled when the LSA
 * is changed. Example: AS-external-LSAs for exported routes.
 * LSA_M_EXPORT - The LSA is originated using ospf_originate_lsa() as a
 * consequence of route export to the OSPF instance. It has to be reoriginated
 * during each channel feed, otherwise it is flushed automatically at the end of
 * the feed. May be originated and flushed asynchronously. Also, routing table
 * calculation does not depend on the LSA. Therefore, the routing table
 * calculation is not scheduled when the LSA is changed. Example:
 * AS-external-LSAs for exported routes.
 *
 * LSA_M_RTCALC - The LSA has to be requested using ospf_originate_lsa() during
 * each routing table calculation, otherwise it is flushed automatically at the
@@ -138,8 +143,11 @@ struct top_hash_entry
 * source for it. Therefore, the calculation is not scheduled when the LSA is
 * changed. Example: Summary-LSAs.
 *
 * LSA_M_STALE - Temporary state for LSA_M_RTCALC that is not requested during
 * the current routing table calculation.
 * LSA_M_EXPORT_STALE - Temporary state for LSA_M_EXPORT that is not requested
 * during current external route feed.
 *
 * LSA_M_RTCALC_STALE - Temporary state for LSA_M_RTCALC that is not requested
 * during current routing table calculation.
 *
 *
 * Note that we do not schedule the routing table calculation when the age of
@@ -181,7 +189,8 @@ struct top_hash_entry * ospf_originate_lsa(struct ospf_proto *p, struct ospf_new
void ospf_advance_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_lsa_header *lsa, u32 type, u32 domain, void *body);
void ospf_flush_lsa(struct ospf_proto *p, struct top_hash_entry *en);
void ospf_update_lsadb(struct ospf_proto *p);
void ospf_mark_lsadb(struct ospf_proto *p);
void ospf_feed_begin(struct channel *C, int initial);
void ospf_feed_end(struct channel *C);

static inline void ospf_flush2_lsa(struct ospf_proto *p, struct top_hash_entry **en)
{ if (*en) { ospf_flush_lsa(p, *en); *en = NULL; } }