Commit 54ac17dc authored by Jan Maria Matejka's avatar Jan Maria Matejka
Browse files

Nest: Removed rte_get_temp(), rte_update() now does its own copy.

This changes behaviour of rte_update() and rte_update2().

Formerly, the caller of rte_update2() took care of caching rta and
allocating rte; then rte_update2() freed the structures if it didn't use them.

Now rte_update2() does the permanent/global copies of rte+rta itself.
Allocation of rte+rta passed to rte_update2() is considered temporary
and the caller is also responsible to free these structures properly.
This is true for any kind of allocation: rte_update2() will always
allocate its own copy of the data passed (either really or just by
raising usecount in rta cache).

It is now possible (and in many protocols now used) to allocate rte+rta
on stack and pass them to rte_update(). It will deal with them correctly.
parent 9a5557ea
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -306,6 +306,7 @@ void rte_free(rte *);
rte *rte_do_cow(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);
rte *rte_clone(rte *);
void rt_dump(rtable *);
void rt_dump_all(void);
int rt_feed_channel(struct channel *c);
@@ -617,6 +618,7 @@ static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a
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; }
int rta_same(rta *x, rta *y);
void rta__free(rta *r);
static inline void rta_free(rta *r) { if (r && !--r->uc) rta__free(r); }
rta *rta_do_cow(rta *o, linpool *lp);
+1 −1
Original line number Diff line number Diff line
@@ -1062,7 +1062,7 @@ rta_hash(rta *a)
  return mem_hash_value(&h) ^ nexthop_hash(&(a->nh)) ^ ea_hash(a->eattrs);
}

static inline int
int
rta_same(rta *x, rta *y)
{
  return (x->src == y->src &&
+6 −7
Original line number Diff line number Diff line
@@ -71,9 +71,6 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
    }
  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))
@@ -90,10 +87,12 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
	.nh.iface = ad->iface,
      };

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

      rte_update2(c, net, &e, src);
    }
}

+19 −25
Original line number Diff line number Diff line
@@ -261,34 +261,33 @@ 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;
  memcpy(e, r, sizeof(rte));
  e->attrs = rta_clone(r->attrs);
  e->flags = 0;
  e->pref = 0;
  return e;
}

/**
 * rte_clone - do a complete copy of given rte
 * @e: route to clone
 */

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

  memcpy(e, r, sizeof(rte));

  if (rta_is_cached(r->attrs))
    e->attrs = rta_clone(r->attrs);
  e->flags = 0;
  else
    e->attrs = rta_lookup(r->attrs);

  return e;
}

@@ -1274,11 +1273,8 @@ rte_unhide_dummy_routes(net *net, rte **dummy)
 *
 * 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().
 * sequence is to build route attributes first, allocate a temporary &rte, fill in all
 * the appropriate data and 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
@@ -1367,9 +1363,8 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
		src->proto->store_tmp_attrs(new);
	    }
	}
      if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
	new->attrs = rta_lookup(new->attrs);
      new->flags |= REF_COW;

      new = rte_clone(new);
    }
  else
    {
@@ -1391,7 +1386,6 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
  return;

 drop:
  rte_free(new);
  new = NULL;
  goto recalc;
}
+17 −13
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 = 0;
    rte rte = {
      .attrs = &a0,
      .u.babel = {
	  .seqno = r->seqno,
	  .metric = r->metric,
	  .router_id = r->router_id,
      },
      .pflags = 0,
    };

    e->unreachable = 0;
    rte_update2(c, e->n.addr, rte, p->p.main_source);
    rte_update2(c, e->n.addr, &rte, p->p.main_source);
  }
  else if (e->valid && (e->router_id != p->router_id))
  {
@@ -660,14 +663,15 @@ 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 rte = {
      .attrs = &a0,
      .u.babel = {},
      .pflags = 0,
      .pref = 1,
    };

    e->unreachable = 1;
    rte_update2(c, e->n.addr, rte, p->p.main_source);
    rte_update2(c, e->n.addr, &rte, p->p.main_source);
  }
  else
  {
Loading