Commit 094d2bdb authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Implements ADD-PATH extension for BGP.

Allows to send and receive multiple routes for one network by one BGP
session. Also contains necessary core changes to support this (routing
tables accepting several routes for one network from one protocol).
It needs some more cleanup before merging to the master branch.
parent d760229a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -831,7 +831,7 @@ interpret(struct f_inst *what)
	res.val.i = * ((char *) rta + what->a2.i);
	break;
      case T_STRING:	/* Warning: this is a special case for proto attribute */
	res.val.s = rta->proto->name;
	res.val.s = rta->src->proto->name;
	break;
      case T_PREFIX:	/* Warning: this works only for prefix of network */
	{
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@

#include <stdarg.h>
#include <string.h>
#include <strings.h>

int bsprintf(char *str, const char *fmt, ...);
int bvsprintf(char *str, const char *fmt, va_list args);
+13 −0
Original line number Diff line number Diff line
@@ -219,6 +219,7 @@ proto_free_ahooks(struct proto *p)
  p->main_ahook = NULL;
}


/**
 * proto_config_new - create a new protocol configuration
 * @pr: protocol the configuration will belong to
@@ -791,11 +792,15 @@ proto_schedule_feed(struct proto *p, int initial)
  /* Connect protocol to routing table */
  if (initial && !p->proto->multitable)
    {
      p->main_source = rt_get_source(p, 0);
      rt_lock_source(p->main_source);

      p->main_ahook = proto_add_announce_hook(p, p->table, &p->stats);
      p->main_ahook->in_filter = p->cf->in_filter;
      p->main_ahook->out_filter = p->cf->out_filter;
      p->main_ahook->in_limit = p->cf->in_limit;
      p->main_ahook->out_limit = p->cf->out_limit;

      proto_reset_limit(p->main_ahook->in_limit);
      proto_reset_limit(p->main_ahook->out_limit);
    }
@@ -844,6 +849,8 @@ proto_flush_loop(void *unused UNUSED)
      return;
    }

  rt_prune_sources();

 again:
  WALK_LIST(p, flush_proto_list)
    if (p->flushing)
@@ -1040,6 +1047,12 @@ proto_notify_state(struct proto *p, unsigned ps)
      if ((cs == FS_FEEDING) || (cs == FS_HAPPY))
	proto_schedule_flush(p);

      if (p->proto->multitable)
	{
	  rt_unlock_source(p->main_source);
	  p->main_source = NULL;
	}

      neigh_prune(); // FIXME convert neighbors to resource?
      rfree(p->pool);
      p->pool = NULL;
+2 −1
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ struct proto {
  int (*reload_routes)(struct proto *);

  /*
   *	Routing entry hooks (called only for rte's belonging to this protocol):
   *	Routing entry hooks (called only for routes belonging to this protocol):
   *
   *	   rte_recalculate Called at the beginning of the best route selection  
   *	   rte_better	Compare two rte's and decide which one is better (1=first, 0=second).
@@ -199,6 +199,7 @@ struct proto {
  void (*rte_remove)(struct network *, struct rte *);

  struct rtable *table;			/* Our primary routing table */
  struct rte_src *main_source;		/* Primary route source */
  struct announce_hook *main_ahook;	/* Primary announcement hook */
  struct announce_hook *ahooks;		/* Announcement hooks for this protocol */

+21 −4
Original line number Diff line number Diff line
@@ -237,10 +237,10 @@ void rt_unlock_table(rtable *);
void rt_setup(pool *, rtable *, char *, struct rtable_config *);
static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_find(&tab->fib, &addr, len); }
static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }
rte *rte_find(net *net, struct proto *p);
rte *rte_find(net *net, struct rte_src *src);
rte *rte_get_temp(struct rta *);
void rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src);
static inline void rte_update(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new) { rte_update2(p->main_ahook, net, new, src); }
void rte_update2(struct announce_hook *ah, net *net, rte *new, struct rte_src *src);
static inline void rte_update(struct proto *p, net *net, rte *new) { rte_update2(p->main_ahook, net, new, p->main_source); }
void rte_discard(rtable *tab, rte *old);
void rte_dump(rte *);
void rte_free(rte *);
@@ -286,9 +286,18 @@ struct mpnh {
  unsigned char weight;
};

struct rte_src {
  struct rte_src *next;			/* Hash chain */
  struct proto *proto;			/* Protocol the source is based on */
  u32 private_id;			/* Private ID, assigned by the protocol */
  u32 global_id;			/* Globally unique ID of the source */
  unsigned uc;				/* Use count */
};


typedef struct rta {
  struct rta *next, **pprev;		/* Hash chain */
  struct proto *proto;			/* Protocol instance that originally created the route */
  struct rte_src *src;			/* Route source that created the route */
  unsigned uc;				/* Use count */
  byte source;				/* Route source (RTS_...) */
  byte scope;				/* Route scope (SCOPE_... -- see ip.h) */
@@ -403,6 +412,13 @@ typedef struct ea_list {
#define EALF_BISECT 2			/* Use interval bisection for searching */
#define EALF_CACHED 4			/* Attributes belonging to cached rta */

struct rte_src *rt_find_source(struct proto *p, u32 id);
struct rte_src *rt_get_source(struct proto *p, u32 id);
static inline void rt_lock_source(struct rte_src *src) { src->uc++; }
static inline void rt_unlock_source(struct rte_src *src) { src->uc--; }
void rt_prune_sources(void);


eattr *ea_find(ea_list *, unsigned ea);
int ea_get_int(ea_list *, unsigned ea, int def);
void ea_dump(ea_list *);
@@ -419,6 +435,7 @@ static inline int mpnh_same(struct mpnh *x, struct mpnh *y)

void rta_init(void);
rta *rta_lookup(rta *);			/* Get rta equivalent to this one, uc++ */
static inline int rta_is_cached(rta *r) { return r->aflags & RTAF_CACHED; }
static inline rta *rta_clone(rta *r) { r->uc++; return r; }
void rta__free(rta *r);
static inline void rta_free(rta *r) { if (r && !--r->uc) rta__free(r); }
Loading