Commit 4e276a89 authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka
Browse files

Merged multipath and single-path data structures.

Dropped struct mpnh and mpnh_*()
Now struct nexthop exists, nexthop_*(), and also included struct nexthop
into struct rta.

Also converted RTD_DEVICE and RTD_ROUTER to RTD_UNICAST. If it is needed
to distinguish between these two cases, RTD_DEVICE is equivalent to
IPA_ZERO(a->nh.gw), RTD_ROUTER is then IPA_NONZERO(a->nh.gw).

From now on, we also explicitely want C99 compatible compiler. We assume
that this 20-year norm should be known almost everywhere.
parent b7605d5c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ if test "$ac_test_CFLAGS" != set ; then
	bird_cflags_default=yes
fi

AC_PROG_CC
AC_PROG_CC_C99
if test -z "$GCC" ; then
	AC_MSG_ERROR([This program requires the GNU C Compiler.])
+10 −10
Original line number Diff line number Diff line
@@ -900,15 +900,15 @@ interpret(struct f_inst *what)
      switch (what->a2.i)
      {
      case SA_FROM:	res.val.ip = rta->from; break;
      case SA_GW:	res.val.ip = rta->gw; break;
      case SA_GW:	res.val.ip = rta->nh.gw; break;
      case SA_NET:	res.val.net = (*f_rte)->net->n.addr; break;
      case SA_PROTO:	res.val.s = rta->src->proto->name; break;
      case SA_SOURCE:	res.val.i = rta->source; break;
      case SA_SCOPE:	res.val.i = rta->scope; break;
      case SA_CAST:	res.val.i = rta->cast; break;
      case SA_DEST:	res.val.i = rta->dest; break;
      case SA_IFNAME:	res.val.s = rta->iface ? rta->iface->name : ""; break;
      case SA_IFINDEX:	res.val.i = rta->iface ? rta->iface->index : 0; break;
      case SA_IFNAME:	res.val.s = rta->nh.iface ? rta->nh.iface->name : ""; break;
      case SA_IFINDEX:	res.val.i = rta->nh.iface ? rta->nh.iface->index : 0; break;

      default:
	bug("Invalid static attribute access (%x)", res.type);
@@ -938,10 +938,10 @@ interpret(struct f_inst *what)
	  if (!n || (n->scope == SCOPE_HOST))
	    runtime( "Invalid gw address" );

	  rta->dest = RTD_ROUTER;
	  rta->gw = ip;
	  rta->iface = n->iface;
	  rta->nexthops = NULL;
	  rta->dest = RTD_UNICAST;
	  rta->nh.gw = ip;
	  rta->nh.iface = n->iface;
	  rta->nh.next = NULL;
	  rta->hostentry = NULL;
	}
	break;
@@ -956,9 +956,9 @@ interpret(struct f_inst *what)
	  runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );

	rta->dest = i;
	rta->gw = IPA_NONE;
	rta->iface = NULL;
	rta->nexthops = NULL;
	rta->nh.gw = IPA_NONE;
	rta->nh.iface = NULL;
	rta->nh.next = NULL;
	rta->hostentry = NULL;
	break;

+1 −1
Original line number Diff line number Diff line
@@ -79,7 +79,7 @@ CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIREC
	RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL)
CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE, UNDEFINED)
CF_ENUM(T_ENUM_RTC, RTC_, UNICAST, BROADCAST, MULTICAST, ANYCAST)
CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT, MULTIPATH)
CF_ENUM(T_ENUM_RTD, RTD_, UNICAST, BLACKHOLE, UNREACHABLE, PROHIBIT)
CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)

%type <i32> idval
+22 −23
Original line number Diff line number Diff line
@@ -195,7 +195,7 @@ struct hostentry {
  unsigned hash_key;			/* Hash key */
  unsigned uc;				/* Use count */
  struct rta *src;			/* Source rta entry */
  ip_addr gw;				/* Chosen next hop */
  struct nexthop *nh;			/* Chosen next hop */
  byte dest;				/* Chosen route destination type (RTD_...) */
  u32 igp_metric;			/* Chosen route IGP metric */
};
@@ -332,11 +332,11 @@ void rt_show(struct rt_show_data *);
 *	construction of BGP route attribute lists.
 */

/* Multipath next-hop */
struct mpnh {
/* Nexthop structure */
struct nexthop {
  ip_addr gw;				/* Next hop */
  struct iface *iface;			/* Outgoing interface */
  struct mpnh *next;
  struct nexthop *next;
  byte weight;
};

@@ -353,20 +353,19 @@ typedef struct rta {
  struct rta *next, **pprev;		/* Hash chain */
  u32 uc;				/* Use count */
  u32 hash_key;				/* Hash over important fields */
  struct mpnh *nexthops;		/* Next-hops for multipath routes */
  struct ea_list *eattrs;		/* Extended Attribute chain */
  struct rte_src *src;			/* Route source that created the route */
  struct hostentry *hostentry;		/* Hostentry for recursive next-hops */
  struct iface *iface;			/* Outgoing interface */
  ip_addr gw;				/* Next hop */
  ip_addr from;				/* Advertising router */
  u32 igp_metric;			/* IGP metric to next hop (for iBGP routes) */
  byte source;				/* Route source (RTS_...) */
  byte scope;				/* Route scope (SCOPE_... -- see ip.h) */
  byte cast;				/* Casting type (RTC_...) */
  byte dest;				/* Route destination type (RTD_...) */
  byte flags;				/* Route flags (RTF_...), now unused */
  byte aflags;				/* Attribute cache flags (RTAF_...) */
  u32 bf[0];
  u32 source:6;				/* Route source (RTS_...) */
  u32 scope:6;				/* Route scope (SCOPE_... -- see ip.h) */
  u32 cast:6;				/* Casting type (RTC_...) */
  u32 dest:6;				/* Route destination type (RTD_...) */
//  u32 eflags:8;				/* Flags (RTAF_...) */
  u32 aflags:8;
  struct nexthop nh;			/* Next hop */
} rta;

#define RTS_DUMMY 0			/* Dummy route to be removed soon */
@@ -391,12 +390,10 @@ typedef struct rta {
#define RTC_MULTICAST 2
#define RTC_ANYCAST 3			/* IPv6 Anycast */

#define RTD_ROUTER 0			/* Next hop is neighbor router */
#define RTD_DEVICE 1			/* Points to device */
#define RTD_UNICAST 0			/* Next hop is neighbor router */
#define RTD_BLACKHOLE 2			/* Silently drop packets */
#define RTD_UNREACHABLE 3		/* Reject as unreachable */
#define RTD_PROHIBIT 4			/* Administratively prohibited */
#define RTD_MULTIPATH 5			/* Multipath route (nexthops != NULL) */
#define RTD_NONE 6			/* Invalid RTD */

					/* Flags for net->n.flags, used by kernel syncer */
@@ -411,7 +408,7 @@ typedef struct rta {

/* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */
static inline int rte_is_reachable(rte *r)
{ uint d = r->attrs->dest; return (d == RTD_ROUTER) || (d == RTD_DEVICE) || (d == RTD_MULTIPATH); }
{ uint d = r->attrs->dest; return (d == RTD_UNICAST); }


/*
@@ -516,12 +513,14 @@ uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */
ea_list *ea_append(ea_list *to, ea_list *what);
void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);

int mpnh__same(struct mpnh *x, struct mpnh *y); /* Compare multipath nexthops */
static inline int mpnh_same(struct mpnh *x, struct mpnh *y)
{ return (x == y) || mpnh__same(x, y); }
struct mpnh *mpnh_merge(struct mpnh *x, struct mpnh *y, int rx, int ry, int max, linpool *lp);
void mpnh_insert(struct mpnh **n, struct mpnh *y);
int mpnh_is_sorted(struct mpnh *x);
int nexthop__same(struct nexthop *x, struct nexthop *y); /* Compare multipath nexthops */
static inline int nexthop_same(struct nexthop *x, struct nexthop *y)
{ return (x == y) || nexthop__same(x, y); }
struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp);
static inline void nexthop_link(struct rta *a, struct nexthop *from)
{ a->nh.gw = from->gw; a->nh.iface = from->iface; a->nh.weight = from->weight; a->nh.next = from->next; }
void nexthop_insert(struct nexthop *n, struct nexthop *y);
int nexthop_is_sorted(struct nexthop *x);

void rta_init(void);
rta *rta_lookup(rta *);			/* Get rta equivalent to this one, uc++ */
+63 −56
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@
pool *rta_pool;

static slab *rta_slab;
static slab *mpnh_slab;
static slab *nexthop_slab;
static slab *rte_src_slab;

static struct idm src_ids;
@@ -144,7 +144,7 @@ rt_prune_sources(void)
 */

static inline u32
mpnh_hash(struct mpnh *x)
nexthop_hash(struct nexthop *x)
{
  u32 h = 0;
  for (; x; x = x->next)
@@ -154,7 +154,7 @@ mpnh_hash(struct mpnh *x)
}

int
mpnh__same(struct mpnh *x, struct mpnh *y)
nexthop__same(struct nexthop *x, struct nexthop *y)
{
  for (; x && y; x = x->next, y = y->next)
    if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight))
@@ -164,7 +164,7 @@ mpnh__same(struct mpnh *x, struct mpnh *y)
}

static int
mpnh_compare_node(struct mpnh *x, struct mpnh *y)
nexthop_compare_node(struct nexthop *x, struct nexthop *y)
{
  int r;

@@ -185,10 +185,10 @@ mpnh_compare_node(struct mpnh *x, struct mpnh *y)
  return ((int) x->iface->index) - ((int) y->iface->index);
}

static inline struct mpnh *
mpnh_copy_node(const struct mpnh *src, linpool *lp)
static inline struct nexthop *
nexthop_copy_node(const struct nexthop *src, linpool *lp)
{
  struct mpnh *n = lp_alloc(lp, sizeof(struct mpnh));
  struct nexthop *n = lp_alloc(lp, sizeof(struct nexthop));
  n->gw = src->gw;
  n->iface = src->iface;
  n->next = NULL;
@@ -197,7 +197,7 @@ mpnh_copy_node(const struct mpnh *src, linpool *lp)
}

/**
 * mpnh_merge - merge nexthop lists
 * nexthop_merge - merge nexthop lists
 * @x: list 1
 * @y: list 2
 * @rx: reusability of list @x
@@ -205,7 +205,7 @@ mpnh_copy_node(const struct mpnh *src, linpool *lp)
 * @max: max number of nexthops
 * @lp: linpool for allocating nexthops
 *
 * The mpnh_merge() function takes two nexthop lists @x and @y and merges them,
 * The nexthop_merge() function takes two nexthop lists @x and @y and merges them,
 * eliminating possible duplicates. The input lists must be sorted and the
 * result is sorted too. The number of nexthops in result is limited by @max.
 * New nodes are allocated from linpool @lp.
@@ -218,28 +218,28 @@ mpnh_copy_node(const struct mpnh *src, linpool *lp)
 * resulting list is no longer needed. When reusability is not set, the
 * corresponding lists are not modified nor linked from the resulting list.
 */
struct mpnh *
mpnh_merge(struct mpnh *x, struct mpnh *y, int rx, int ry, int max, linpool *lp)
struct nexthop *
nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp)
{
  struct mpnh *root = NULL;
  struct mpnh **n = &root;
  struct nexthop *root = NULL;
  struct nexthop **n = &root;

  while ((x || y) && max--)
  {
    int cmp = mpnh_compare_node(x, y);
    int cmp = nexthop_compare_node(x, y);
    if (cmp < 0)
    {
      *n = rx ? x : mpnh_copy_node(x, lp);
      *n = rx ? x : nexthop_copy_node(x, lp);
      x = x->next;
    }
    else if (cmp > 0)
    {
      *n = ry ? y : mpnh_copy_node(y, lp);
      *n = ry ? y : nexthop_copy_node(y, lp);
      y = y->next;
    }
    else
    {
      *n = rx ? x : (ry ? y : mpnh_copy_node(x, lp));
      *n = rx ? x : (ry ? y : nexthop_copy_node(x, lp));
      x = x->next;
      y = y->next;
    }
@@ -251,43 +251,55 @@ mpnh_merge(struct mpnh *x, struct mpnh *y, int rx, int ry, int max, linpool *lp)
}

void
mpnh_insert(struct mpnh **n, struct mpnh *x)
nexthop_insert(struct nexthop *n, struct nexthop *x)
{
  for (; *n; n = &((*n)->next))
  struct nexthop tmp;
  memcpy(&tmp, n, sizeof(struct nexthop));
  if (nexthop_compare_node(n, x) > 0) /* Insert to the included nexthop */
  {
    int cmp = mpnh_compare_node(*n, x);
    memcpy(n, x, sizeof(struct nexthop));
    memcpy(x, &tmp, sizeof(struct nexthop));
    n->next = x;
    return;
  }

  for (struct nexthop **nn = &(n->next); *nn; nn = &((*nn)->next))
  {
    int cmp = nexthop_compare_node(*nn, x);

    if (cmp < 0)
      continue;
    else if (cmp > 0)
      break;
    else
    
    if (cmp > 0)
    {
      x->next = *nn;
      *nn = x;
    }
    
    return;
  }

  x->next = *n;
  *n = x;
}

int
mpnh_is_sorted(struct mpnh *x)
nexthop_is_sorted(struct nexthop *x)
{
  for (; x && x->next; x = x->next)
    if (mpnh_compare_node(x, x->next) >= 0)
    if (nexthop_compare_node(x, x->next) >= 0)
      return 0;

  return 1;
}

static struct mpnh *
mpnh_copy(struct mpnh *o)
static struct nexthop *
nexthop_copy(struct nexthop *o)
{
  struct mpnh *first = NULL;
  struct mpnh **last = &first;
  struct nexthop *first = NULL;
  struct nexthop **last = &first;

  for (; o; o = o->next)
    {
      struct mpnh *n = sl_alloc(mpnh_slab);
      struct nexthop *n = sl_alloc(nexthop_slab);
      n->gw = o->gw;
      n->iface = o->iface;
      n->next = NULL;
@@ -301,14 +313,14 @@ mpnh_copy(struct mpnh *o)
}

static void
mpnh_free(struct mpnh *o)
nexthop_free(struct nexthop *o)
{
  struct mpnh *n;
  struct nexthop *n;

  while (o)
    {
      n = o->next;
      sl_free(mpnh_slab, o);
      sl_free(nexthop_slab, o);
      o = n;
    }
}
@@ -994,19 +1006,12 @@ rta_hash(rta *a)
#define MIX(f) mem_hash_mix(&h, &(a->f), sizeof(a->f));
  MIX(src);
  MIX(hostentry);
  MIX(iface);
  MIX(gw);
  MIX(from);
  MIX(igp_metric);
  MIX(source);
  MIX(scope);
  MIX(cast);
  MIX(dest);
  MIX(flags);
  MIX(aflags);
  mem_hash_mix(&h, a->bf, sizeof(u32));
#undef MIX

  return mem_hash_value(&h) ^ mpnh_hash(a->nexthops) ^ ea_hash(a->eattrs);
  return mem_hash_value(&h) ^ nexthop_hash(&(a->nh)) ^ ea_hash(a->eattrs);
}

static inline int
@@ -1017,13 +1022,12 @@ rta_same(rta *x, rta *y)
	  x->scope == y->scope &&
	  x->cast == y->cast &&
	  x->dest == y->dest &&
	  x->flags == y->flags &&
	  x->igp_metric == y->igp_metric &&
	  ipa_equal(x->gw, y->gw) &&
	  ipa_equal(x->nh.gw, y->nh.gw) &&
	  ipa_equal(x->from, y->from) &&
	  x->iface == y->iface &&
	  x->nh.iface == y->nh.iface &&
	  x->hostentry == y->hostentry &&
	  mpnh_same(x->nexthops, y->nexthops) &&
	  nexthop_same(&(x->nh), &(y->nh)) &&
	  ea_same(x->eattrs, y->eattrs));
}

@@ -1034,7 +1038,7 @@ rta_copy(rta *o)

  memcpy(r, o, sizeof(rta));
  r->uc = 1;
  r->nexthops = mpnh_copy(o->nexthops);
  r->nh.next = nexthop_copy(o->nh.next);
  r->eattrs = ea_list_copy(o->eattrs);
  return r;
}
@@ -1130,7 +1134,8 @@ rta__free(rta *a)
  a->aflags = 0;		/* Poison the entry */
  rt_unlock_hostentry(a->hostentry);
  rt_unlock_source(a->src);
  mpnh_free(a->nexthops);
  if (a->nh.next)
    nexthop_free(a->nh.next);
  ea_free(a->eattrs);
  sl_free(rta_slab, a);
}
@@ -1167,10 +1172,12 @@ rta_dump(rta *a)
  if (!(a->aflags & RTAF_CACHED))
    debug(" !CACHED");
  debug(" <-%I", a->from);
  if (a->dest == RTD_ROUTER)
    debug(" ->%I", a->gw);
  if (a->dest == RTD_DEVICE || a->dest == RTD_ROUTER)
    debug(" [%s]", a->iface ? a->iface->name : "???" );
  if (a->dest == RTD_UNICAST)
    for (struct nexthop *nh = &(a->nh); nh; nh = nh->next)
      {
	if (ipa_nonzero(nh->gw)) debug(" ->%I", nh->gw);
	debug(" [%s]", nh->iface ? nh->iface->name : "???");
      }
  if (a->eattrs)
    {
      debug(" EA: ");
@@ -1228,7 +1235,7 @@ rta_init(void)
{
  rta_pool = rp_new(&root_pool, "Attributes");
  rta_slab = sl_new(rta_pool, sizeof(rta));
  mpnh_slab = sl_new(rta_pool, sizeof(struct mpnh));
  nexthop_slab = sl_new(rta_pool, sizeof(struct nexthop));
  rta_alloc_hash();
  rte_src_init();
}
Loading