Commit 1675ecbb authored by Maria Matejka's avatar Maria Matejka
Browse files

Route import API redefinition.

Hidden rte_get_temp() into rte_update().
Split rte_update() / rte_withdraw().
parent 2e1484e4
Loading
Loading
Loading
Loading
+0 −14
Original line number Diff line number Diff line
@@ -624,18 +624,4 @@ void *channel_config_new(const struct channel_class *cc, const char *name, uint
void *channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto);
int channel_reconfigure(struct channel *c, struct channel_config *cf);


/* Moved from route.h to avoid dependency conflicts */
static inline void rte_update(struct proto *p, const net_addr *n, rte *new) { rte_update2(p->main_channel, n, new, p->main_source); }

static inline void
rte_update3(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
{
  if (c->in_table && !rte_update_in(c, n, new, src))
    return;

  rte_update2(c, n, new, src);
}


#endif
+46 −4
Original line number Diff line number Diff line
@@ -280,6 +280,51 @@ static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED);
#define RIC_REJECT	-1		/* Rejected by protocol */
#define RIC_DROP	-2		/* Silently dropped by protocol */

/**
 * rte_update - enter a new update to a routing table
 * @c: channel doing the update
 * @net: network address
 * @rte: a &rte representing the new route
 *
 * This function imports a new route to the appropriate table (via the channel).
 * Table keys are @net (obligatory) and @rte->attrs->src.
 * Both the @net and @rte pointers can be local.
 *
 * The route attributes (@rte->attrs) are obligatory. They can be also allocated
 * locally. Anyway, if you use an already-cached attribute object, you shall
 * call rta_clone() on that object yourself. (This semantics may change in future.)
 *
 * If the route attributes are local, you may set @rte->attrs->src to NULL, then
 * the protocol's default route source will be supplied.
 *
 * When rte_update() gets a route, it automatically validates it. This includes
 * checking for validity of the given network and next hop addresses and also
 * checking for host-scope or link-scope routes. Then the import filters are
 * processed and if accepted, the route is passed to route table recalculation.
 *
 * The accepted routes are then inserted into the table, replacing the old route
 * (key is the @net together with @rte->attrs->src). Then the route is announced
 * to all the channels connected to the table using the standard export mechanism.
 *
 * All memory used for temporary allocations is taken from a special linpool
 * @rte_update_pool and freed when rte_update() finishes.
 */
void rte_update(struct channel *c, net_addr *net, struct rte *rte);

/**
 * rte_withdraw - withdraw a route from a routing table
 * @c: channel doing the withdraw
 * @net: network address
 * @src: the route source identifier
 *
 * This function withdraws a previously announced route from the table.
 * No import filter is called. This function is idempotent. If no route
 * is found under the given key, it does nothing.
 *
 * If @src is NULL, the protocol's default route source is used.
 */
void rte_withdraw(struct channel *c, net_addr *net, struct rte_src *src);

extern list routing_tables;
struct config;

@@ -296,9 +341,6 @@ static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) f
void *net_route(rtable *tab, const net_addr *n);
int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
rte *rte_find(net *net, struct rte_src *src);
rte *rte_get_temp(struct rta *);
void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
/* rte_update() moved to protocol.h to avoid dependency conflicts */
int rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter);
rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent);
void rt_refresh_begin(rtable *t, struct channel *c);
@@ -308,6 +350,7 @@ void rt_schedule_prune(rtable *t);
void rte_dump(rte *);
void rte_free(rte *);
rte *rte_do_cow(rte *);
rte *rte_store(rte *);
static inline rte * rte_cow(rte *r) { return (r->flags & REF_COW) ? rte_do_cow(r) : r; }
rte *rte_cow_rta(rte *r, linpool *lp);
void rte_init_tmp_attrs(struct rte *r, linpool *lp, uint max);
@@ -318,7 +361,6 @@ void rt_dump(rtable *);
void rt_dump_all(void);
int rt_feed_channel(struct channel *c);
void rt_feed_channel_abort(struct channel *c);
int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
int rt_reload_channel(struct channel *c);
void rt_reload_channel_abort(struct channel *c);
void rt_prune_sync(rtable *t, int all);
+7 −14
Original line number Diff line number Diff line
@@ -66,34 +66,27 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
      DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip);

      /* Use iface ID as local source ID */
      struct rte_src *src = rt_get_source(P, ad->iface->index);
      rte_update2(c, net, NULL, src);
      rte_withdraw(c, net, rt_get_source(P, ad->iface->index));
    }
  else if (flags & IF_CHANGE_UP)
    {
      rta *a;
      rte *e;

      DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);

      if (cf->check_link && !(ad->iface->flags & IF_LINK_UP))
	return;

      /* Use iface ID as local source ID */
      struct rte_src *src = rt_get_source(P, ad->iface->index);

      rta a0 = {
	.src = src,
	/* Use iface ID as local source ID */
	.src = rt_get_source(P, ad->iface->index),
	.source = RTS_DEVICE,
	.scope = SCOPE_UNIVERSE,
	.dest = RTD_UNICAST,
	.nh.iface = ad->iface,
      };

      a = rta_lookup(&a0);
      e = rte_get_temp(a);
      e->pflags = 0;
      rte_update2(c, net, e, src);
      rte e0 = {
	.attrs = rta_lookup(&a0),
      };
      rte_update(c, net, &e0);
    }
}

+41 −61
Original line number Diff line number Diff line
@@ -267,35 +267,26 @@ rte_find(net *net, struct rte_src *src)
  return e;
}

/**
 * rte_get_temp - get a temporary &rte
 * @a: attributes to assign to the new route (a &rta; in case it's
 * un-cached, rte_update() will create a cached copy automatically)
 *
 * Create a temporary &rte and bind it with the attributes @a.
 * Also set route preference to the default preference set for
 * the protocol.
 */
rte *
rte_get_temp(rta *a)
rte_do_cow(rte *r)
{
  rte *e = sl_alloc(rte_slab);

  e->attrs = a;
  e->id = 0;
  memcpy(e, r, sizeof(rte));
  e->attrs = rta_clone(r->attrs);
  e->flags = 0;
  e->pref = 0;
  return e;
}

rte *
rte_do_cow(rte *r)
rte_store(rte *r)
{
  rte *e = sl_alloc(rte_slab);

  memcpy(e, r, sizeof(rte));
  if (e->attrs->aflags & RTAF_CACHED)
    e->attrs = rta_clone(r->attrs);
  e->flags = 0;
  else
    e->attrs = rta_lookup(r->attrs);
  return e;
}

@@ -1382,49 +1373,7 @@ rte_unhide_dummy_routes(net *net, rte **dummy)
  }
}

/**
 * rte_update - enter a new update to a routing table
 * @table: table to be updated
 * @c: channel doing the update
 * @net: network node
 * @p: protocol submitting the update
 * @src: protocol originating the update
 * @new: a &rte representing the new route or %NULL for route removal.
 *
 * This function is called by the routing protocols whenever they discover
 * a new route or wish to update/remove an existing route. The right announcement
 * sequence is to build route attributes first (either un-cached with @aflags set
 * to zero or a cached one using rta_lookup(); in this case please note that
 * you need to increase the use count of the attributes yourself by calling
 * rta_clone()), call rte_get_temp() to obtain a temporary &rte, fill in all
 * the appropriate data and finally submit the new &rte by calling rte_update().
 *
 * @src specifies the protocol that originally created the route and the meaning
 * of protocol-dependent data of @new. If @new is not %NULL, @src have to be the
 * same value as @new->attrs->proto. @p specifies the protocol that called
 * rte_update(). In most cases it is the same protocol as @src. rte_update()
 * stores @p in @new->sender;
 *
 * When rte_update() gets any route, it automatically validates it (checks,
 * whether the network and next hop address are valid IP addresses and also
 * whether a normal routing protocol doesn't try to smuggle a host or link
 * scope route to the table), converts all protocol dependent attributes stored
 * in the &rte to temporary extended attributes, consults import filters of the
 * protocol to see if the route should be accepted and/or its attributes modified,
 * stores the temporary attributes back to the &rte.
 *
 * Now, having a "public" version of the route, we
 * automatically find any old route defined by the protocol @src
 * for network @n, replace it by the new one (or removing it if @new is %NULL),
 * recalculate the optimal route for this destination and finally broadcast
 * the change (if any) to all routing protocols by calling rte_announce().
 *
 * All memory used for attribute lists and other temporary allocations is taken
 * from a special linear pool @rte_update_pool and freed when rte_update()
 * finishes.
 */

void
static void
rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
{
  struct proto *p = c->proto;
@@ -1528,6 +1477,37 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
  rte_update_unlock();
}

static int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);

void
rte_withdraw(struct channel *c, net_addr *n, struct rte_src *src)
{
  if (!src)
    src = c->proto->main_source;

  if (!c->in_table || rte_update_in(c, n, NULL, src))
    rte_update2(c, n, NULL, src ?: c->proto->main_source);
}

void
rte_update(struct channel *c, net_addr *n, struct rte *new)
{
  ASSERT(new);
  ASSERT(new->attrs);

  rte *e = sl_alloc(rte_slab);
  *e = *new;

  if (!e->attrs->src)
  {
    ASSERT(!rta_is_cached(e->attrs));
    e->attrs->src = c->proto->main_source;
  }

  if (!c->in_table || rte_update_in(c, n, e, e->attrs->src))
    rte_update2(c, n, e, e->attrs->src);
}

/* Independent call to rte_announce(), used from next hop
   recalculation, outside of rte_update(). new must be non-NULL */
static inline void
@@ -2415,7 +2395,7 @@ rt_feed_channel_abort(struct channel *c)
 *	Import table
 */

int
static int
rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
{
  struct rtable *tab = c->in_table;
+17 −15
Original line number Diff line number Diff line
@@ -640,15 +640,18 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
      .nh.iface = r->neigh->ifa->iface,
    };

    rta *a = rta_lookup(&a0);
    rte *rte = rte_get_temp(a);
    rte->u.babel.seqno = r->seqno;
    rte->u.babel.metric = r->metric;
    rte->u.babel.router_id = r->router_id;
    rte->pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID);
    rte e0 = {
      .attrs = rta_lookup(&a0),
      .u.babel = {
	.seqno = r->seqno,
	.metric = r->metric,
	.router_id = r->router_id,
      },
      .pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID),
    };

    e->unreachable = 0;
    rte_update2(c, e->n.addr, rte, p->p.main_source);
    rte_update(c, e->n.addr, &e0);
  }
  else if (e->valid && (e->router_id != p->router_id))
  {
@@ -660,20 +663,19 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
      .dest = RTD_UNREACHABLE,
    };

    rta *a = rta_lookup(&a0);
    rte *rte = rte_get_temp(a);
    memset(&rte->u.babel, 0, sizeof(rte->u.babel));
    rte->pflags = 0;
    rte->pref = 1;
    rte e0 = {
      .attrs = &a0,
      .pref = 1,
    };

    e->unreachable = 1;
    rte_update2(c, e->n.addr, rte, p->p.main_source);
    rte_update(c, e->n.addr, &e0);
  }
  else
  {
    /* Retraction */
    e->unreachable = 0;
    rte_update2(c, e->n.addr, NULL, p->p.main_source);
    rte_withdraw(c, e->n.addr, NULL);
  }
}

@@ -683,7 +685,7 @@ babel_announce_retraction(struct babel_proto *p, struct babel_entry *e)
{
  struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
  e->unreachable = 0;
  rte_update2(c, e->n.addr, NULL, p->p.main_source);
  rte_withdraw(c, e->n.addr, NULL);
}


Loading