mirror of
				https://gitlab.labs.nic.cz/labs/bird.git
				synced 2024-05-11 16:54:54 +00:00 
			
		
		
		
	Merge branch 'mq-aggregator-for-v3' into thread-next
This commit is contained in:
		
							
								
								
									
										167
									
								
								nest/mpls.c
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								nest/mpls.c
									
									
									
									
									
								
							@@ -76,8 +76,6 @@
 | 
			
		||||
 * and withdrawal of MPLS routes.
 | 
			
		||||
 *
 | 
			
		||||
 * TODO:
 | 
			
		||||
 *  - protocols should do route refresh instead of restart when reconfiguration
 | 
			
		||||
 *    requires changing labels (e.g. different label range)
 | 
			
		||||
 *  - special handling of reserved labels
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@@ -254,7 +252,8 @@ mpls_reconfigure_domain(struct mpls_domain *m, struct mpls_domain_config *cf)
 | 
			
		||||
 | 
			
		||||
  struct mpls_range *r, *r2;
 | 
			
		||||
  WALK_LIST_DELSAFE(r, r2, old_ranges)
 | 
			
		||||
    mpls_remove_range(r);
 | 
			
		||||
    if (!r->removed)
 | 
			
		||||
      mpls_remove_range(r);
 | 
			
		||||
 | 
			
		||||
  add_tail_list(&m->ranges, &old_ranges);
 | 
			
		||||
 | 
			
		||||
@@ -384,7 +383,7 @@ mpls_find_range_(list *l, const char *name)
 | 
			
		||||
  struct mpls_range *r;
 | 
			
		||||
 | 
			
		||||
  WALK_LIST(r, *l)
 | 
			
		||||
    if (!strcmp(r->name, name))
 | 
			
		||||
    if (!strcmp(r->name, name) && !r->removed)
 | 
			
		||||
      return r;
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
@@ -415,7 +414,6 @@ mpls_free_range(struct mpls_range *r)
 | 
			
		||||
  ASSERT(r->use_count == 0);
 | 
			
		||||
  ASSERT(r->label_count == 0);
 | 
			
		||||
 | 
			
		||||
  r->cf->range = NULL;
 | 
			
		||||
  rem_node(&r->n);
 | 
			
		||||
  mb_free(r);
 | 
			
		||||
}
 | 
			
		||||
@@ -423,7 +421,11 @@ mpls_free_range(struct mpls_range *r)
 | 
			
		||||
static void
 | 
			
		||||
mpls_remove_range(struct mpls_range *r)
 | 
			
		||||
{
 | 
			
		||||
  ASSERT(!r->removed);
 | 
			
		||||
 | 
			
		||||
  r->removed = 1;
 | 
			
		||||
  r->cf->range = NULL;
 | 
			
		||||
  r->cf = NULL;
 | 
			
		||||
 | 
			
		||||
  if (!r->use_count)
 | 
			
		||||
    mpls_free_range(r);
 | 
			
		||||
@@ -515,6 +517,26 @@ mpls_free_label(struct mpls_domain *m, struct mpls_handle *h, uint n)
 | 
			
		||||
  h->label_count--;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mpls_move_label(struct mpls_domain *m, struct mpls_handle *fh, struct mpls_handle *th, uint n)
 | 
			
		||||
{
 | 
			
		||||
  struct mpls_range *fr = fh->range;
 | 
			
		||||
  struct mpls_range *tr = th->range;
 | 
			
		||||
 | 
			
		||||
  ASSERT(lmap_test(&m->labels, n));
 | 
			
		||||
  ASSERT((n >= fr->lo) && (n < fr->hi));
 | 
			
		||||
  ASSERT((n >= tr->lo) && (n < tr->hi));
 | 
			
		||||
 | 
			
		||||
  ASSERT(fr->label_count);
 | 
			
		||||
  fr->label_count--;
 | 
			
		||||
 | 
			
		||||
  ASSERT(fh->label_count);
 | 
			
		||||
  fh->label_count--;
 | 
			
		||||
 | 
			
		||||
  tr->label_count++;
 | 
			
		||||
  th->label_count++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *	MPLS channel
 | 
			
		||||
@@ -561,16 +583,32 @@ mpls_channel_cleanup(struct channel *C)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
mpls_channel_reconfigure(struct channel *C, struct channel_config *CC, int *import_changed UNUSED, int *export_changed UNUSED)
 | 
			
		||||
mpls_channel_reconfigure(struct channel *C, struct channel_config *CC, int *import_changed, int *export_changed UNUSED)
 | 
			
		||||
{
 | 
			
		||||
  struct mpls_channel *c = (void *) C;
 | 
			
		||||
  struct mpls_channel_config *new = (void *) CC;
 | 
			
		||||
 | 
			
		||||
  if ((new->domain->domain != c->domain) ||
 | 
			
		||||
      (new->range->range != c->range) ||
 | 
			
		||||
      (new->label_policy != c->label_policy))
 | 
			
		||||
  if (new->domain->domain != c->domain)
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
  if (new->range->range != c->range)
 | 
			
		||||
  {
 | 
			
		||||
    if (c->c.channel_state != CS_DOWN)
 | 
			
		||||
      mpls_unlock_range(c->range);
 | 
			
		||||
 | 
			
		||||
    c->range = new->range->range;
 | 
			
		||||
    *import_changed = 1;
 | 
			
		||||
 | 
			
		||||
    if (c->c.channel_state != CS_DOWN)
 | 
			
		||||
      mpls_lock_range(c->range);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (new->label_policy != c->label_policy)
 | 
			
		||||
  {
 | 
			
		||||
    c->label_policy = new->label_policy;
 | 
			
		||||
    *import_changed = 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -639,6 +677,7 @@ HASH_DEFINE_REHASH_FN(RTA, struct mpls_fec)
 | 
			
		||||
HASH_DEFINE_REHASH_FN(LABEL, struct mpls_fec)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void mpls_unlink_fec(struct mpls_fec_map *m, struct mpls_fec *fec);
 | 
			
		||||
static void mpls_withdraw_fec(struct mpls_fec_map *m, struct mpls_fec *fec);
 | 
			
		||||
static struct ea_storage * mpls_get_key_attrs(struct mpls_fec_map *m, ea_list *src);
 | 
			
		||||
 | 
			
		||||
@@ -665,6 +704,67 @@ mpls_fec_map_new(pool *pp, struct channel *C, uint rts)
 | 
			
		||||
  return m;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mpls_fec_map_reconfigure(struct mpls_fec_map *m, struct channel *C)
 | 
			
		||||
{
 | 
			
		||||
  struct mpls_channel *c = (void *) C;
 | 
			
		||||
 | 
			
		||||
  struct mpls_handle *old_d = NULL;
 | 
			
		||||
  struct mpls_handle *old_s = NULL;
 | 
			
		||||
 | 
			
		||||
  /* Reallocate dynamic handle */
 | 
			
		||||
  if (m->handle->range != c->range)
 | 
			
		||||
  {
 | 
			
		||||
    old_d = m->handle;
 | 
			
		||||
    m->handle = mpls_new_handle(m->domain, c->range);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Reallocate static handle */
 | 
			
		||||
  if (m->static_handle && (m->static_handle->range != m->domain->cf->static_range->range))
 | 
			
		||||
  {
 | 
			
		||||
    old_s = m->static_handle;
 | 
			
		||||
    m->static_handle = mpls_new_handle(m->domain, m->domain->cf->static_range->range);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Skip rest if there is no change */
 | 
			
		||||
  if (!old_d && !old_s)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* Process existing FECs */
 | 
			
		||||
  HASH_WALK(m->label_hash, next_l, fec)
 | 
			
		||||
  {
 | 
			
		||||
    /* Skip already dead FECs */
 | 
			
		||||
    if (fec->policy == MPLS_POLICY_NONE)
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    /* Skip FECs with valid handle */
 | 
			
		||||
    if ((fec->handle == m->handle) || (fec->handle == m->static_handle))
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    /* Try new handle for the FEC */
 | 
			
		||||
    struct mpls_handle *new = (fec->policy != MPLS_POLICY_STATIC) ? m->handle : m->static_handle;
 | 
			
		||||
    if ((fec->label >= new->range->lo) && (fec->label < new->range->hi))
 | 
			
		||||
    {
 | 
			
		||||
      mpls_move_label(m->domain, fec->handle, new, fec->label);
 | 
			
		||||
      fec->handle = new;
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Unlink the FEC while keep it in the label hash */
 | 
			
		||||
    mpls_unlink_fec(m, fec);
 | 
			
		||||
    fec->policy = MPLS_POLICY_NONE;
 | 
			
		||||
  }
 | 
			
		||||
  HASH_WALK_END;
 | 
			
		||||
 | 
			
		||||
  /* Remove old unused handles */
 | 
			
		||||
 | 
			
		||||
  if (old_d && !old_d->label_count)
 | 
			
		||||
    mpls_free_handle(m->domain, old_d);
 | 
			
		||||
 | 
			
		||||
  if (old_s && !old_s->label_count)
 | 
			
		||||
    mpls_free_handle(m->domain, old_s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mpls_fec_map_free(struct mpls_fec_map *m)
 | 
			
		||||
{
 | 
			
		||||
@@ -682,8 +782,10 @@ mpls_fec_map_free(struct mpls_fec_map *m)
 | 
			
		||||
  /* Free allocated labels */
 | 
			
		||||
  HASH_WALK(m->label_hash, next_l, fec)
 | 
			
		||||
  {
 | 
			
		||||
    struct mpls_handle *h = (fec->policy != MPLS_POLICY_STATIC) ? m->handle : m->static_handle;
 | 
			
		||||
    mpls_free_label(m->domain, h, fec->label);
 | 
			
		||||
    mpls_free_label(m->domain, fec->handle, fec->label);
 | 
			
		||||
 | 
			
		||||
    if (!fec->policy && !fec->handle->label_count)
 | 
			
		||||
      mpls_free_handle(m->domain, fec->handle);
 | 
			
		||||
  }
 | 
			
		||||
  HASH_WALK_END;
 | 
			
		||||
 | 
			
		||||
@@ -719,12 +821,12 @@ mpls_get_fec_by_label(struct mpls_fec_map *m, u32 label)
 | 
			
		||||
{
 | 
			
		||||
  struct mpls_fec *fec = HASH_FIND(m->label_hash, LABEL, label);
 | 
			
		||||
 | 
			
		||||
  if (!m->static_handle)
 | 
			
		||||
    m->static_handle = mpls_new_handle(m->domain, m->domain->cf->static_range->range);
 | 
			
		||||
 | 
			
		||||
  if (fec)
 | 
			
		||||
    return (fec->policy == MPLS_POLICY_STATIC) ? fec : NULL;
 | 
			
		||||
 | 
			
		||||
  if (!m->static_handle)
 | 
			
		||||
    m->static_handle = mpls_new_handle(m->domain, m->domain->cf->static_range->range);
 | 
			
		||||
 | 
			
		||||
  label = mpls_new_label(m->domain, m->static_handle, label);
 | 
			
		||||
 | 
			
		||||
  if (!label)
 | 
			
		||||
@@ -734,6 +836,7 @@ mpls_get_fec_by_label(struct mpls_fec_map *m, u32 label)
 | 
			
		||||
 | 
			
		||||
  fec->label = label;
 | 
			
		||||
  fec->policy = MPLS_POLICY_STATIC;
 | 
			
		||||
  fec->handle = m->static_handle;
 | 
			
		||||
 | 
			
		||||
  DBG("New FEC lab %u\n", fec->label);
 | 
			
		||||
 | 
			
		||||
@@ -767,6 +870,7 @@ mpls_get_fec_by_net(struct mpls_fec_map *m, const net_addr *net, u32 path_id)
 | 
			
		||||
 | 
			
		||||
  fec->label = label;
 | 
			
		||||
  fec->policy = MPLS_POLICY_PREFIX;
 | 
			
		||||
  fec->handle = m->handle;
 | 
			
		||||
 | 
			
		||||
  DBG("New FEC net %u\n", fec->label);
 | 
			
		||||
 | 
			
		||||
@@ -807,6 +911,7 @@ mpls_get_fec_by_destination(struct mpls_fec_map *m, ea_list *dest)
 | 
			
		||||
 | 
			
		||||
  fec->label = label;
 | 
			
		||||
  fec->policy = MPLS_POLICY_AGGREGATE;
 | 
			
		||||
  fec->handle = m->handle;
 | 
			
		||||
 | 
			
		||||
  DBG("New FEC rta %u\n", fec->label);
 | 
			
		||||
 | 
			
		||||
@@ -833,6 +938,7 @@ mpls_get_fec_for_vrf(struct mpls_fec_map *m)
 | 
			
		||||
 | 
			
		||||
  fec->label = label;
 | 
			
		||||
  fec->policy = MPLS_POLICY_VRF;
 | 
			
		||||
  fec->handle = m->handle;
 | 
			
		||||
  fec->iface = m->vrf_iface;
 | 
			
		||||
 | 
			
		||||
  DBG("New FEC vrf %u\n", fec->label);
 | 
			
		||||
@@ -843,21 +949,12 @@ mpls_get_fec_for_vrf(struct mpls_fec_map *m)
 | 
			
		||||
  return fec;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mpls_free_fec(struct mpls_fec_map *m, struct mpls_fec *fec)
 | 
			
		||||
static void
 | 
			
		||||
mpls_unlink_fec(struct mpls_fec_map *m, struct mpls_fec *fec)
 | 
			
		||||
{
 | 
			
		||||
  if (fec->state != MPLS_FEC_DOWN)
 | 
			
		||||
    mpls_withdraw_fec(m, fec);
 | 
			
		||||
 | 
			
		||||
  DBG("Free FEC %u\n", fec->label);
 | 
			
		||||
 | 
			
		||||
  struct mpls_handle *h = (fec->policy != MPLS_POLICY_STATIC) ? m->handle : m->static_handle;
 | 
			
		||||
  mpls_free_label(m->domain, h, fec->label);
 | 
			
		||||
 | 
			
		||||
  HASH_REMOVE2(m->label_hash, LABEL, m->pool, fec);
 | 
			
		||||
 | 
			
		||||
  switch (fec->policy)
 | 
			
		||||
  {
 | 
			
		||||
  case MPLS_POLICY_NONE:
 | 
			
		||||
  case MPLS_POLICY_STATIC:
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
@@ -878,6 +975,24 @@ mpls_free_fec(struct mpls_fec_map *m, struct mpls_fec *fec)
 | 
			
		||||
  default:
 | 
			
		||||
    bug("Unknown fec type");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mpls_free_fec(struct mpls_fec_map *m, struct mpls_fec *fec)
 | 
			
		||||
{
 | 
			
		||||
  if (fec->state != MPLS_FEC_DOWN)
 | 
			
		||||
    mpls_withdraw_fec(m, fec);
 | 
			
		||||
 | 
			
		||||
  DBG("Free FEC %u\n", fec->label);
 | 
			
		||||
 | 
			
		||||
  mpls_free_label(m->domain, fec->handle, fec->label);
 | 
			
		||||
 | 
			
		||||
  if (!fec->policy && !fec->handle->label_count)
 | 
			
		||||
      mpls_free_handle(m->domain, fec->handle);
 | 
			
		||||
 | 
			
		||||
  HASH_REMOVE2(m->label_hash, LABEL, m->pool, fec);
 | 
			
		||||
 | 
			
		||||
  mpls_unlink_fec(m, fec);
 | 
			
		||||
 | 
			
		||||
  sl_free(fec);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -93,6 +93,7 @@ void mpls_preconfig(struct config *c);
 | 
			
		||||
void mpls_commit(struct config *new, struct config *old);
 | 
			
		||||
uint mpls_new_label(struct mpls_domain *m, struct mpls_handle *h, uint n);
 | 
			
		||||
void mpls_free_label(struct mpls_domain *m, struct mpls_handle *h, uint n);
 | 
			
		||||
void mpls_move_label(struct mpls_domain *m, struct mpls_handle *fh, struct mpls_handle *th, uint n);
 | 
			
		||||
 | 
			
		||||
static inline struct mpls_domain_config *cf_default_mpls_domain(struct config *cfg)
 | 
			
		||||
{ return EMPTY_LIST(cfg->mpls_domains) ? NULL : HEAD(cfg->mpls_domains); }
 | 
			
		||||
@@ -132,6 +133,8 @@ struct mpls_fec {
 | 
			
		||||
  u8 state;				/* FEC state (MPLS_FEC_*) */
 | 
			
		||||
  u8 policy;				/* Label policy (MPLS_POLICY_*) */
 | 
			
		||||
 | 
			
		||||
  struct mpls_handle *handle;		/* Handle holding the label */
 | 
			
		||||
 | 
			
		||||
  struct mpls_fec *next_k;		/* Next in mpls_fec.net_hash/rta_hash */
 | 
			
		||||
  struct mpls_fec *next_l;		/* Next in mpls_fec.label_hash */
 | 
			
		||||
  union {				/* Primary key */
 | 
			
		||||
@@ -151,7 +154,7 @@ struct mpls_fec_map {
 | 
			
		||||
 | 
			
		||||
  struct channel *channel;		/* MPLS channel for FEC announcement */
 | 
			
		||||
  struct mpls_domain *domain;		/* MPLS domain, keeping reference */
 | 
			
		||||
  struct mpls_handle *handle;		/* Handle for allocation of labels */
 | 
			
		||||
  struct mpls_handle *handle;		/* Handle for dynamic allocation of labels */
 | 
			
		||||
  struct mpls_handle *static_handle;	/* Handle for static label allocations, optional */
 | 
			
		||||
  struct iface *vrf_iface;
 | 
			
		||||
 | 
			
		||||
@@ -160,6 +163,7 @@ struct mpls_fec_map {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct mpls_fec_map *mpls_fec_map_new(pool *p, struct channel *c, uint rts);
 | 
			
		||||
void mpls_fec_map_reconfigure(struct mpls_fec_map *m, struct channel *C);
 | 
			
		||||
void mpls_fec_map_free(struct mpls_fec_map *m);
 | 
			
		||||
struct mpls_fec *mpls_find_fec_by_label(struct mpls_fec_map *x, u32 label);
 | 
			
		||||
struct mpls_fec *mpls_get_fec_by_label(struct mpls_fec_map *m, u32 label);
 | 
			
		||||
 
 | 
			
		||||
@@ -1544,7 +1544,7 @@ proto_setup_mpls_map(struct proto *p, uint rts)
 | 
			
		||||
  }
 | 
			
		||||
  else if (m && c)
 | 
			
		||||
  {
 | 
			
		||||
    // mpls_fec_map_reconfigure(m, c);
 | 
			
		||||
    mpls_fec_map_reconfigure(m, c);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user