Commit c10421d3 authored by Martin Mares's avatar Martin Mares
Browse files

More changes to the kernel syncer.

o  Now compatible with filtering.
o  Learning of kernel routes supported only on CONFIG_SELF_CONSCIOUS
   systems (on the others it's impossible to get it semantically correct).
o  Learning now stores all of its routes in a separate fib and selects
   the ones the kernel really uses for forwarding packets.
o  Better treatment of CONFIG_AUTO_ROUTES ports.
o  Lots of internal changes.
parent 69ec9087
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -140,18 +140,20 @@ typedef struct rte {
    struct {
    } bgp;
#endif
    struct {				/* Routes internally generated by krt sync */
      int src;				/* Alleged route source (see krt.h) */
    } krt_sync;
    struct {				/* Routes generated by krt sync (both temporary and inherited ones) */
      s8 src;				/* Alleged route source (see krt.h) */
      u8 proto;				/* Kernel source protocol ID */
      u8 type;				/* Kernel route type */
      u8 seen;				/* Seen during last scan */
      u32 metric;			/* Kernel metric */
    } krt;
  } u;
} rte;

#define REF_CHOSEN 1			/* Currently chosen route */

extern rtable master_table;

void rt_init(void);
void rt_setup(rtable *, char *);
void rt_setup(pool *, rtable *, char *);
net *net_find(rtable *tab, unsigned tos, ip_addr addr, unsigned len);
net *net_get(rtable *tab, unsigned tos, ip_addr addr, unsigned len);
rte *rte_find(net *net, struct proto *p);
+7 −7
Original line number Diff line number Diff line
@@ -38,10 +38,10 @@ rte_init(struct fib_node *N)
}

void
rt_setup(rtable *t, char *name)
rt_setup(pool *p, rtable *t, char *name)
{
  bzero(t, sizeof(*t));
  fib_init(&t->fib, &root_pool, sizeof(rte), 0, rte_init);
  fib_init(&t->fib, p, sizeof(rte), 0, rte_init);
  t->name = name;
}

@@ -67,7 +67,7 @@ net_get(rtable *tab, unsigned tos, ip_addr mask, unsigned len)
      while (tab->sibling)
	tab = tab->sibling;
      t = mb_alloc(&root_pool, sizeof(rtable));
      rt_setup(t, NULL);
      rt_setup(&root_pool, t, NULL);	/* FIXME: Either delete all the TOS logic or use the right pool */
      tab->sibling = t;
      t->tos = tos;
    }
@@ -305,10 +305,10 @@ rte_dump(rte *e)
    debug("%1I/%2d ", n->n.prefix, n->n.pxlen);
  else
    debug("??? ");
  debug("PF=%02x pref=%d lm=%d ", e->pflags, e->pref, now-e->lastmod);
  debug("KF=%02x PF=%02x pref=%d lm=%d ", n->n.flags, e->pflags, e->pref, now-e->lastmod);
  rta_dump(e->attrs);
  if (e->flags & REF_CHOSEN)
    debug(" [*]");
  if (e->attrs->proto->proto->dump_attrs)
    e->attrs->proto->proto->dump_attrs(e);
  debug("\n");
}

@@ -357,7 +357,7 @@ rt_init(void)
{
  rta_init();
  rt_table_pool = rp_new(&root_pool, "Routing tables");
  rt_setup(&master_table, "master");
  rt_setup(rt_table_pool, &master_table, "master");
  rte_slab = sl_new(rt_table_pool, sizeof(rte));
  rt_last_gc = now;
  rt_gc_event = ev_new(rt_table_pool);
+1 −1
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ krt_parse_entry(byte *ent, struct krt_proto *p)

  e = rte_get_temp(&a);
  e->net = net;
  e->u.krt_sync.src = KRT_SRC_UNKNOWN;
  e->u.krt.src = KRT_SRC_UNKNOWN;
  krt_got_route(p, e);
}

+25 −14
Original line number Diff line number Diff line
@@ -276,7 +276,7 @@ nl_parse_link(struct nlmsghdr *h, int scan)
  ifi = if_find_by_index(i->ifi_index);
  if (!new)
    {
      DBG("KRT: IF%d(%s) goes down\n", i->ifi_index, name);
      DBG("KIF: IF%d(%s) goes down\n", i->ifi_index, name);
      if (ifi && !scan)
	{
	  memcpy(&f, ifi, sizeof(struct iface));
@@ -286,7 +286,7 @@ nl_parse_link(struct nlmsghdr *h, int scan)
    }
  else
    {
      DBG("KRT: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i->ifi_index, name, mtu, i->ifi_flags);
      DBG("KIF: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i->ifi_index, name, mtu, i->ifi_flags);
      if (ifi)
	memcpy(&f, ifi, sizeof(f));
      else
@@ -332,14 +332,14 @@ nl_parse_addr(struct nlmsghdr *h)
    }
  if (i->ifa_flags & IFA_F_SECONDARY)
    {
      DBG("KRT: Received address message for secondary address which is not supported.\n"); /* FIXME */
      DBG("KIF: Received address message for secondary address which is not supported.\n"); /* FIXME */
      return;
    }

  ifi = if_find_by_index(i->ifa_index);
  if (!ifi)
    {
      log(L_ERR "KRT: Received address message for unknown interface %d\n", i->ifa_index);
      log(L_ERR "KIF: Received address message for unknown interface %d\n", i->ifa_index);
      return;
    }
  memcpy(&f, ifi, sizeof(f));
@@ -347,14 +347,14 @@ nl_parse_addr(struct nlmsghdr *h)
  if (i->ifa_prefixlen > 32 || i->ifa_prefixlen == 31 ||
      (f.flags & IF_UNNUMBERED) && i->ifa_prefixlen != 32)
    {
      log(L_ERR "KRT: Invalid prefix length for interface %s: %d\n", f.name, i->ifa_prefixlen);
      log(L_ERR "KIF: Invalid prefix length for interface %s: %d\n", f.name, i->ifa_prefixlen);
      new = 0;
    }

  f.ip = f.brd = f.opposite = IPA_NONE;
  if (!new)
    {
      DBG("KRT: IF%d IP address deleted\n");
      DBG("KIF: IF%d IP address deleted\n");
      f.pxlen = 0;
    }
  else
@@ -374,7 +374,7 @@ nl_parse_addr(struct nlmsghdr *h)
	}
      /* else a NBMA link */
      f.prefix = ipa_and(f.ip, ipa_mkmask(f.pxlen));
      DBG("KRT: IF%d IP address set to %I, net %I/%d, brd %I, opp %I\n", f.index, f.ip, f.prefix, f.pxlen, f.brd, f.opposite);
      DBG("KIF: IF%d IP address set to %I, net %I/%d, brd %I, opp %I\n", f.index, f.ip, f.prefix, f.pxlen, f.brd, f.opposite);
    }
  if_update(&f);
}
@@ -485,12 +485,8 @@ nl_send_route(rte *e, int new)
}

void
krt_set_notify(struct proto *p, net *n, rte *new, rte *old)
krt_set_notify(struct krt_proto *p, net *n, rte *new, rte *old)
{
  if (old && !krt_capable(old))
    old = NULL;
  if (new && !krt_capable(new))
    new = NULL;
  if (old && new && old->attrs->tos == new->attrs->tos)
    {
      /* FIXME: Priorities should be identical as well, but we don't use them yet. */
@@ -546,6 +542,7 @@ nl_parse_route(struct krt_proto *p, struct nlmsghdr *h, int scan)
    return;
  if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
      (a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
      (a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
      (a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)))
    {
      log(L_ERR "nl_parse_route: Malformed message received");
@@ -649,9 +646,22 @@ nl_parse_route(struct krt_proto *p, struct nlmsghdr *h, int scan)
      DBG("KRT: Ignoring route with type=%d\n", i->rtm_type);
      return;
    }

  if (i->rtm_scope != RT_SCOPE_UNIVERSE)	/* FIXME: Other scopes? */
    {
      DBG("KRT: Ignoring route with scope=%d\n", i->rtm_scope);
      return;
    }

  e = rte_get_temp(&ra);
  e->net = net;
  e->u.krt_sync.src = src;
  e->u.krt.src = src;
  e->u.krt.proto = i->rtm_protocol;
  e->u.krt.type = i->rtm_type;
  if (a[RTA_PRIORITY])
    memcpy(&e->u.krt.metric, RTA_DATA(a[RTA_PRIORITY]), sizeof(e->u.krt.metric));
  else
    e->u.krt.metric = 0;
  if (scan)
    krt_got_route(p, e);
  else
@@ -797,7 +807,7 @@ krt_scan_start(struct krt_proto *p)
{
  init_list(&p->scan.temp_ifs);
  nl_open();
  if (KRT_CF->scan.async)
  if (KRT_CF->scan.async)	/* FIXME: Async is for debugging only. Get rid of it some day. */
    nl_open_async(p);
}

@@ -810,4 +820,5 @@ void
krt_if_start(struct kif_proto *p)
{
  nl_open();
  /* FIXME: nl_open_async() after scan.async is gone */
}
+8 −30
Original line number Diff line number Diff line
@@ -77,41 +77,19 @@ krt_ioctl(int ioc, rte *e, char *name)
    log(L_ERR "%s(%I/%d): %m", name, net->n.prefix, net->n.pxlen);
}

static inline void
krt_remove_route(rte *old)
void
krt_set_notify(struct krt_proto *p, net *net, rte *new, rte *old)
{
  net *net = old->net;

  if (!krt_capable(old))
  if (old)
    {
      DBG("krt_remove_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
      return;
    }
      DBG("krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
      krt_ioctl(SIOCDELRT, old, "SIOCDELRT");
    }

static inline void
krt_add_route(rte *new)
{
  net *net = new->net;

  if (!krt_capable(new))
  if (new)
    {
      DBG("krt_add_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
      return;
    }
      DBG("krt_add_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
      krt_ioctl(SIOCADDRT, new, "SIOCADDRT");
    }

void
krt_set_notify(struct proto *x, net *net, rte *new, rte *old)
{
  if (old)
    krt_remove_route(old);
  if (new)
    krt_add_route(new);
}

void
Loading