]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Nest: Changed struct network * in struct rte to const net_addr *. [WIP] mq-route-net-addr
authorMaria Matejka <mq@jmq.cz>
Tue, 30 Oct 2018 19:57:38 +0000 (20:57 +0100)
committerMaria Matejka <mq@ucw.cz>
Thu, 20 Dec 2018 12:19:49 +0000 (13:19 +0100)
This allows filtering the route without even touching the table on
import. Therefore rejected routes don't mess with the table in any way.
Only accepted routes are linked to the table.

Kernel protocol still uses a dirty hack to get routes synchronized. This
should be sanitized in future to allow proper concurrency.

filter/filter.c
nest/route.h
nest/rt-show.c
nest/rt-table.c
proto/bgp/attrs.c
proto/mrt/mrt.c
proto/radv/radv.c
sysdep/bsd/krt-sock.c
sysdep/linux/netlink.c
sysdep/unix/krt.c
sysdep/unix/krt.h

index 37cf16a3857edd63eb8e8410e4881ef973de9762..d3c60a97863d9d4c051c11319c8935cfc15d1c6c 100644 (file)
@@ -942,7 +942,7 @@ interpret(struct f_inst *what)
       {
       case SA_FROM:    res.val.ip = rta->from; 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_NET:     res.val.net = (*f_rte)->netA; 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;
@@ -1531,7 +1531,7 @@ interpret(struct f_inst *what)
     {
       ACCESS_RTE;
       ACCESS_EATTRS;
-      v1.val.net = (*f_rte)->net->n.addr;
+      v1.val.net = (*f_rte)->netA;
 
       /* We ignore temporary attributes, probably not a problem here */
       /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
index 8dfbb3762713a1c54751c20ebfcff12bc6af1b5e..6b6c9cec16d8199d80897db2e2d98ba49221e30e 100644 (file)
@@ -207,7 +207,7 @@ struct hostentry {
 
 typedef struct rte {
   struct rte *next;
-  net *net;                            /* Network this RTE belongs to */
+  const net_addr *netA;                        /* Network this RTE belongs to */
   struct channel *sender;              /* Channel used to send the route to the routing table */
   struct rta *attrs;                   /* Attributes of this route */
   byte flags;                          /* Flags (REF_...) */
@@ -258,6 +258,8 @@ typedef struct rte {
 #define REF_DISCARD    8               /* Route is scheduled for discard */
 #define REF_MODIFY     16              /* Route is scheduled for modify */
 
+#define RTE_NET(e)     (((e)->flags & REF_COW) ? SKIP_BACK(struct network, n, SKIP_BACK(struct fib_node, addr, (e)->netA)) : NULL)
+
 /* Route is valid for propagation (may depend on other flags in the future), accepts NULL */
 static inline int rte_is_valid(rte *r) { return r && !(r->flags & REF_FILTERED); }
 
index c7bcdf2f6c98546cfd8705817389920513ff81ac..024b56233a7663cfebe06039f0daeabb61c6d9b4 100644 (file)
@@ -34,8 +34,9 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
   byte from[IPA_MAX_TEXT_LENGTH+8];
   byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
   rta *a = e->attrs;
-  int primary = (e->net->routes == e);
-  int sync_error = (e->net->n.flags & KRF_SYNC_ERROR);
+  net *nn = RTE_NET(e);
+  int primary = nn && (nn->routes == e);
+  int sync_error = nn && (nn->n.flags & KRF_SYNC_ERROR);
   void (*get_route_info)(struct rte *, byte *buf);
   struct nexthop *nh;
 
index 1cb8d2a179b40df1cbd2c8baa1aacf0b537bd15f..5f910dcde6f9c1ec0d7a1009092d28c4ff25eda8 100644 (file)
@@ -376,7 +376,7 @@ rte_mergable(rte *pri, rte *sec)
 static void
 rte_trace(struct proto *p, rte *e, int dir, char *msg)
 {
-  log(L_TRACE "%s %c %s %N %s", p->name, dir, msg, e->net->n.addr, rta_dest_name(e->attrs->dest));
+  log(L_TRACE "%s %c %s %N %s", p->name, dir, msg, e->netA, rta_dest_name(e->attrs->dest));
 }
 
 static inline void
@@ -923,36 +923,36 @@ static inline int
 rte_validate(rte *e)
 {
   int c;
-  net *n = e->net;
+  const net_addr *n = e->netA;
 
-  if (!net_validate(n->n.addr))
+  if (!net_validate(n))
   {
     log(L_WARN "Ignoring bogus prefix %N received via %s",
-       n->n.addr, e->sender->proto->name);
+       n, e->sender->proto->name);
     return 0;
   }
 
   /* FIXME: better handling different nettypes */
-  c = !net_is_flow(n->n.addr) ?
-    net_classify(n->n.addr): (IADDR_HOST | SCOPE_UNIVERSE);
+  c = !net_is_flow(n) ?
+    net_classify(n): (IADDR_HOST | SCOPE_UNIVERSE);
   if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
   {
     log(L_WARN "Ignoring bogus route %N received via %s",
-       n->n.addr, e->sender->proto->name);
+       n, e->sender->proto->name);
     return 0;
   }
 
-  if (net_type_match(n->n.addr, NB_DEST) == !e->attrs->dest)
+  if (net_type_match(n, NB_DEST) == !e->attrs->dest)
   {
     log(L_WARN "Ignoring route %N with invalid dest %d received via %s",
-       n->n.addr, e->attrs->dest, e->sender->proto->name);
+       n, e->attrs->dest, e->sender->proto->name);
     return 0;
   }
 
   if ((e->attrs->dest == RTD_UNICAST) && !nexthop_is_sorted(&(e->attrs->nh)))
   {
     log(L_WARN "Ignoring unsorted multipath route %N received via %s",
-       n->n.addr, e->sender->proto->name);
+       n, e->sender->proto->name);
     return 0;
   }
 
@@ -1346,9 +1346,7 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
   rte_update_lock();
   if (new)
     {
-      nn = net_get(c->table, n);
-
-      new->net = nn;
+      new->netA = n;
       new->sender = c;
 
       if (!new->pref)
@@ -1397,6 +1395,8 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
       if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
        new->attrs = rta_lookup(new->attrs);
       new->flags |= REF_COW;
+
+      new->netA = (nn = net_get(c->table, n))->n.addr;
     }
   else
     {
@@ -1420,7 +1420,12 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
  drop:
   rte_free(new);
   new = NULL;
-  goto recalc;
+
+  if ((nn = net_find(c->table, n)) && src)
+    goto recalc;
+
+  rte_update_unlock();
+  return;
 }
 
 /* Independent call to rte_announce(), used from next hop
@@ -1435,16 +1440,16 @@ rte_announce_i(rtable *tab, unsigned type, net *net, rte *new, rte *old,
 }
 
 static inline void
-rte_discard(rte *old)  /* Non-filtered route deletion, used during garbage collection */
+rte_discard(net *n, rte *old)  /* Non-filtered route deletion, used during garbage collection */
 {
   rte_update_lock();
-  rte_recalculate(old->sender, old->net, NULL, old->attrs->src);
+  rte_recalculate(old->sender, n, NULL, old->attrs->src);
   rte_update_unlock();
 }
 
 /* Modify existing route by protocol hook, used for long-lived graceful restart */
 static inline void
-rte_modify(rte *old)
+rte_modify(net *n, rte *old)
 {
   rte_update_lock();
 
@@ -1458,7 +1463,7 @@ rte_modify(rte *old)
       new->flags = (old->flags & ~REF_MODIFY) | REF_COW;
     }
 
-    rte_recalculate(old->sender, old->net, new, old->attrs->src);
+    rte_recalculate(old->sender, n, new, old->attrs->src);
   }
 
   rte_update_unlock();
@@ -1580,9 +1585,13 @@ rt_modify_stale(rtable *t, struct channel *c)
 void
 rte_dump(rte *e)
 {
-  net *n = e->net;
-  debug("%-1N ", n->n.addr);
-  debug("KF=%02x PF=%02x pref=%d ", n->n.flags, e->pflags, e->pref);
+  debug("%-1N ", e->netA);
+  net *n = RTE_NET(e);
+  if (n)
+    debug("KF=%02x PF=%02x pref=%d ", n->n.flags, e->pflags, e->pref);
+  else
+    debug("outside fib, PF=%02x pref=%d ", e->pflags, e->pref);
+
   rta_dump(e->attrs);
   if (e->attrs->src->proto->proto->dump_attrs)
     e->attrs->src->proto->proto->dump_attrs(e);
@@ -1769,7 +1778,7 @@ again:
                return;
              }
 
-           rte_discard(e);
+           rte_discard(n, e);
            limit--;
 
            goto rescan;
@@ -1784,7 +1793,7 @@ again:
                return;
              }
 
-           rte_modify(e);
+           rte_modify(n, e);
            limit--;
 
            goto rescan;
@@ -2360,7 +2369,7 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr
   /* Insert the new rte */
   rte *e = rte_do_cow(new);
   e->flags |= REF_COW;
-  e->net = net;
+  e->netA = net->n.addr;
   e->sender = c;
   e->lastmod = current_time();
   e->next = *pos;
index cbb2203835876c2b8153434e995aebafb2433e27..b68c6feefb8fd0cb3dd49aa0c048a41ad9df5bca 100644 (file)
@@ -627,7 +627,7 @@ bgp_decode_large_community(struct bgp_parse_state *s, uint code UNUSED, uint fla
 static void
 bgp_export_mpls_label_stack(struct bgp_export_state *s, eattr *a)
 {
-  net_addr *n = s->route->net->n.addr;
+  const net_addr *n = s->route->netA;
   u32 *labels = (u32 *) a->u.ptr->data;
   uint lnum = a->u.ptr->length / 4;
 
index 95014958a60069b6650f739256a6f994d9883201..d21bbe8f384ee702864e09e1d5942f95111d394f 100644 (file)
@@ -459,7 +459,7 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r)
 
     if (alen < 0)
     {
-      mrt_log(s, "Attribute list too long for %N", r->net->n.addr);
+      mrt_log(s, "Attribute list too long for %N", r->netA);
       alen = 0;
     }
 
index 990b602494540fbadb8f30632573c612e6494edb..33225bc71b00bce8cc149e18599c6a35116c18d5 100644 (file)
@@ -390,9 +390,9 @@ radv_trigger_valid(struct radv_config *cf)
 }
 
 static inline int
-radv_net_match_trigger(struct radv_config *cf, net *n)
+radv_net_match_trigger(struct radv_config *cf, const net_addr *n)
 {
-  return radv_trigger_valid(cf) && net_equal(n->n.addr, &cf->trigger);
+  return radv_trigger_valid(cf) && net_equal(n, &cf->trigger);
 }
 
 int
@@ -401,7 +401,7 @@ radv_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
   // struct radv_proto *p = (struct radv_proto *) P;
   struct radv_config *cf = (struct radv_config *) (P->cf);
 
-  if (radv_net_match_trigger(cf, (*new)->net))
+  if (radv_net_match_trigger(cf, (*new)->netA))
     return RIC_PROCESS;
 
   if (cf->propagate_routes)
@@ -418,7 +418,7 @@ radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte
   struct radv_route *rt;
   eattr *ea;
 
-  if (radv_net_match_trigger(cf, n))
+  if (radv_net_match_trigger(cf, n->n.addr))
   {
     u8 old_active = p->active;
     p->active = !!new;
index e646c41429741ae1b88a3d1545a5f16c6121e123..ae7ce0e499f97372ad4a12c25f54303c3887056b 100644 (file)
@@ -199,7 +199,7 @@ sockaddr_fill_dl(struct sockaddr_dl *sa, struct iface *ifa)
 static int
 krt_send_route(struct krt_proto *p, int cmd, rte *e)
 {
-  net *net = e->net;
+  const net_addr *n = e->netA;
   rta *a = e->attrs;
   static int msg_seq;
   struct iface *j, *i = a->nh.iface;
@@ -208,7 +208,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
   char *body = (char *)msg.buf;
   sockaddr gate, mask, dst;
 
-  DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw);
+  DBG("krt-sock: send %N via %I\n", n, a->gw);
 
   bzero(&msg,sizeof (struct rt_msghdr));
   msg.rtm.rtm_version = RTM_VERSION;
@@ -218,7 +218,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
   msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1;
 
   /* XXXX */
-  if (net_pxlen(net->n.addr) == net_max_prefix_length[net->n.addr->type])
+  if (net_pxlen(n) == net_max_prefix_length[n->type])
     msg.rtm.rtm_flags |= RTF_HOST;
   else
     msg.rtm.rtm_addrs |= RTA_NETMASK;
@@ -260,7 +260,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
 
   int af = AF_UNSPEC;
 
-  switch (net->n.addr->type) {
+  switch (n->type) {
     case NET_IP4:
       af = AF_INET;
       break;
@@ -268,12 +268,12 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
       af = AF_INET6;
       break;
     default:
-      log(L_ERR "KRT: Not sending route %N to kernel", net->n.addr);
+      log(L_ERR "KRT: Not sending route %N to kernel", n);
       return -1;
   }
 
-  sockaddr_fill(&dst,  af, net_prefix(net->n.addr), NULL, 0);
-  sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0);
+  sockaddr_fill(&dst,  af, net_prefix(n), NULL, 0);
+  sockaddr_fill(&mask, af, net_pxmask(n), NULL, 0);
 
   switch (a->dest)
   {
@@ -303,7 +303,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
 
 #if __OpenBSD__
     /* Keeping temporarily old code for OpenBSD */
-    struct ifa *addr = (net->n.addr->type == NET_IP4) ? i->addr4 : (i->addr6 ?: i->llv6);
+    struct ifa *addr = (n->type == NET_IP4) ? i->addr4 : (i->addr6 ?: i->llv6);
 
     if (!addr)
     {
@@ -339,15 +339,15 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
   msg.rtm.rtm_msglen = l;
 
   if ((l = write(p->sys.sk->fd, (char *)&msg, l)) < 0) {
-    log(L_ERR "KRT: Error sending route %N to kernel: %m", net->n.addr);
+    log(L_ERR "KRT: Error sending route %N to kernel: %m", n);
     return -1;
   }
 
   return 0;
 }
 
-void
-krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
+int
+krt_replace_rte(struct krt_proto *p, rte *new, rte *old)
 {
   int err = 0;
 
@@ -357,10 +357,7 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
   if (new)
     err = krt_send_route(p, RTM_ADD, new);
 
-  if (err < 0)
-    n->n.flags |= KRF_SYNC_ERROR;
-  else
-    n->n.flags &= ~KRF_SYNC_ERROR;
+  return (err >= 0);
 }
 
 #define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
@@ -372,7 +369,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
 
   int ipv6;
   rte *e;
-  net *net;
   sockaddr dst, gate, mask;
   ip_addr idst, igate, imask;
   net_addr ndst;
@@ -489,8 +485,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
   else
     src = KRT_SRC_KERNEL;
 
-  net = net_get(p->p.main_channel->table, &ndst);
-
   rta a = {
     .src = p->p.main_source,
     .source = RTS_INHERIT,
@@ -518,7 +512,7 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
   if (!a.nh.iface)
     {
       log(L_ERR "KRT: Received route %N with unknown ifindex %u",
-         net->n.addr, msg->rtm.rtm_index);
+         &ndst, msg->rtm.rtm_index);
       return;
     }
 
@@ -541,14 +535,14 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
           return;
 
        log(L_ERR "KRT: Received route %N with strange next-hop %I",
-           net->n.addr, a.nh.gw);
+           &ndst, a.nh.gw);
        return;
       }
   }
 
  done:
   e = rte_get_temp(&a);
-  e->net = net;
+  e->netA = &ndst;
   e->u.krt.src = src;
   e->u.krt.proto = src2;
   e->u.krt.seen = 0;
index 834504d07b5d2ee4c81740c31c6084e6b922afd8..557bd15074622b06c925ea371b03e539482a5e5b 100644 (file)
@@ -104,7 +104,7 @@ struct nl_parse_state
   int scan;
   int merge;
 
-  net *net;
+  const net_addr *netA;
   rta *attrs;
   struct krt_proto *proto;
   s8 new;
@@ -1180,7 +1180,7 @@ static int
 nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
 {
   eattr *ea;
-  net *net = e->net;
+  const net_addr *n = e->netA;
   rta *a = e->attrs;
   ea_list *eattrs = a->eattrs;
   int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(&(a->nh));
@@ -1195,7 +1195,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
   int rsize = sizeof(*r) + bufsize;
   r = alloca(rsize);
 
-  DBG("nl_send_route(%N,op=%x)\n", net->n.addr, op);
+  DBG("nl_send_route(%N,op=%x)\n", n, op);
 
   bzero(&r->h, sizeof(r->h));
   bzero(&r->r, sizeof(r->r));
@@ -1204,7 +1204,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
   r->h.nlmsg_flags = op | NLM_F_REQUEST | NLM_F_ACK;
 
   r->r.rtm_family = p->af;
-  r->r.rtm_dst_len = net_pxlen(net->n.addr);
+  r->r.rtm_dst_len = net_pxlen(n);
   r->r.rtm_protocol = RTPROT_BIRD;
   r->r.rtm_scope = RT_SCOPE_NOWHERE;
 #ifdef HAVE_MPLS_KERNEL
@@ -1216,7 +1216,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
      * 2) Never use RTA_PRIORITY
      */
 
-    u32 label = net_mpls(net->n.addr);
+    u32 label = net_mpls(n);
     nl_add_attr_mpls(&r->h, rsize, RTA_DST, 1, &label);
     r->r.rtm_scope = RT_SCOPE_UNIVERSE;
     r->r.rtm_type = RTN_UNICAST;
@@ -1224,12 +1224,12 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
   else
 #endif
   {
-    nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(net->n.addr));
+    nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(n));
 
     /* Add source address for IPv6 SADR routes */
-    if (net->n.addr->type == NET_IP6_SADR)
+    if (n->type == NET_IP6_SADR)
     {
-      net_addr_ip6_sadr *a = (void *) &net->n.addr;
+      net_addr_ip6_sadr *a = (void *) n;
       nl_add_attr_ip6(&r->h, rsize, RTA_SRC, a->src_prefix);
       r->r.rtm_src_len = a->src_pxlen;
     }
@@ -1364,8 +1364,8 @@ nl_delete_rte(struct krt_proto *p, rte *e)
   return err;
 }
 
-void
-krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
+int
+krt_replace_rte(struct krt_proto *p, rte *new, rte *old)
 {
   int err = 0;
 
@@ -1386,21 +1386,18 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
   if (new)
     err = nl_add_rte(p, new);
 
-  if (err < 0)
-    n->n.flags |= KRF_SYNC_ERROR;
-  else
-    n->n.flags &= ~KRF_SYNC_ERROR;
+  return (err >= 0);
 }
 
 static int
-nl_mergable_route(struct nl_parse_state *s, net *net, struct krt_proto *p, uint priority, uint krt_type)
+nl_mergable_route(struct nl_parse_state *s, const net_addr *netA, struct krt_proto *p, uint priority, uint krt_type)
 {
   /* Route merging must be active */
   if (!s->merge)
     return 0;
 
   /* Saved and new route must have same network, proto/table, and priority */
-  if ((s->net != net) || (s->proto != p) || (s->krt_metric != priority))
+  if (!net_equal(s->netA, netA) || (s->proto != p) || (s->krt_metric != priority))
     return 0;
 
   /* Both must be regular unicast routes */
@@ -1414,7 +1411,7 @@ static void
 nl_announce_route(struct nl_parse_state *s)
 {
   rte *e = rte_get_temp(s->attrs);
-  e->net = s->net;
+  e->netA = s->netA;
   e->u.krt.src = s->krt_src;
   e->u.krt.proto = s->krt_proto;
   e->u.krt.seen = 0;
@@ -1426,7 +1423,7 @@ nl_announce_route(struct nl_parse_state *s)
   else
     krt_got_route_async(s->proto, e, s->new);
 
-  s->net = NULL;
+  s->netA = NULL;
   s->attrs = NULL;
   s->proto = NULL;
   lp_flush(s->pool);
@@ -1444,7 +1441,7 @@ nl_parse_begin(struct nl_parse_state *s, int scan, int merge)
 static inline void
 nl_parse_end(struct nl_parse_state *s)
 {
-  if (s->net)
+  if (s->netA)
     nl_announce_route(s);
 }
 
@@ -1571,18 +1568,21 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
       krt_src = KRT_SRC_ALIEN;
     }
 
-  net_addr *n = &dst;
+  net_addr *nloc;
   if (p->p.net_type == NET_IP6_SADR)
-  {
-    n = alloca(sizeof(net_addr_ip6_sadr));
-    net_fill_ip6_sadr(n, net6_prefix(&dst), net6_pxlen(&dst),
-                     net6_prefix(&src), net6_pxlen(&src));
-  }
+    {
+      nloc = alloca(sizeof(net_addr_ip6_sadr));
+      net_fill_ip6_sadr(nloc, net6_prefix(&dst), net6_pxlen(&dst),
+                       net6_prefix(&src), net6_pxlen(&src));
+    }
+  else
+    nloc = &dst;
 
-  net *net = net_get(p->p.main_channel->table, n);
+  if (s->netA && !nl_mergable_route(s, nloc, p, priority, i->rtm_type))
+    nl_announce_route(s); /* Here is the s->pool flushed! */
 
-  if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type))
-    nl_announce_route(s);
+  net_addr *n = lp_alloc(s->pool, dst.length);
+  net_copy(n, nloc);
 
   rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE);
   ra->src = p->p.main_source;
@@ -1599,7 +1599,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
          struct nexthop *nh = nl_parse_multipath(s, p, a[RTA_MULTIPATH], i->rtm_family);
          if (!nh)
            {
-             log(L_ERR "KRT: Received strange multipath route %N", net->n.addr);
+             log(L_ERR "KRT: Received strange multipath route %N", n);
              return;
            }
 
@@ -1610,7 +1610,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
       ra->nh.iface = if_find_by_index(oif);
       if (!ra->nh.iface)
        {
-         log(L_ERR "KRT: Received route %N with unknown ifindex %u", net->n.addr, oif);
+         log(L_ERR "KRT: Received route %N with unknown ifindex %u", n, oif);
          return;
        }
 
@@ -1640,7 +1640,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
                           (ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0);
          if (!nbr || (nbr->scope == SCOPE_HOST))
            {
-             log(L_ERR "KRT: Received route %N with strange next-hop %I", net->n.addr,
+             log(L_ERR "KRT: Received route %N with strange next-hop %I", n,
                   ra->nh.gw);
              return;
            }
@@ -1745,7 +1745,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
 
       if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0)
         {
-         log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net->n.addr);
+         log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", n);
          return;
        }
 
@@ -1776,10 +1776,10 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
    * Otherwise, we ignore additional next hops in nexthop_insert().
    */
 
-  if (!s->net)
+  if (!s->netA)
   {
     /* Store the new route */
-    s->net = net;
+    s->netA = n;
     s->attrs = ra;
     s->proto = p;
     s->new = new;
index ded5dfe4526c2d3193d9a5216e9eb61e27328a24..184898263275caa672ddfd589eaf18d9bab3b63e 100644 (file)
@@ -251,14 +251,14 @@ static inline void
 krt_trace_in(struct krt_proto *p, rte *e, char *msg)
 {
   if (p->p.debug & D_PACKETS)
-    log(L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg);
+    log(L_TRACE "%s: %N: %s", p->p.name, e->netA, msg);
 }
 
 static inline void
 krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg)
 {
   if (p->p.debug & D_PACKETS)
-    log_rl(f, L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg);
+    log_rl(f, L_TRACE "%s: %N: %s", p->p.name, e->netA, msg);
 }
 
 /*
@@ -298,26 +298,24 @@ krt_uptodate(rte *a, rte *b)
 static void
 krt_learn_announce_update(struct krt_proto *p, rte *e)
 {
-  net *n = e->net;
   rta *aa = rta_clone(e->attrs);
   rte *ee = rte_get_temp(aa);
   ee->pflags = 0;
   ee->u.krt = e->u.krt;
-  rte_update(&p->p, n->n.addr, ee);
+  rte_update(&p->p, e->netA, ee);
 }
 
 static void
-krt_learn_announce_delete(struct krt_proto *p, net *n)
+krt_learn_announce_delete(struct krt_proto *p, net_addr *n)
 {
-  rte_update(&p->p, n->n.addr, NULL);
+  rte_update(&p->p, n, NULL);
 }
 
 /* Called when alien route is discovered during scan */
 static void
 krt_learn_scan(struct krt_proto *p, rte *e)
 {
-  net *n0 = e->net;
-  net *n = net_get(&p->krt_table, n0->n.addr);
+  net *n = net_get(&p->krt_table, e->netA);
   rte *m, **mm;
 
   e->attrs = rta_lookup(e->attrs);
@@ -346,6 +344,7 @@ krt_learn_scan(struct krt_proto *p, rte *e)
   if (!m)
     {
       e->next = n->routes;
+      e->netA = n->n.addr;
       n->routes = e;
       e->u.krt.seen = 1;
     }
@@ -401,7 +400,7 @@ again:
        {
          DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen);
          if (old_best)
-           krt_learn_announce_delete(p, n);
+           krt_learn_announce_delete(p, n->n.addr);
 
          FIB_ITERATE_PUT(&fit);
          fib_delete(fib, n);
@@ -429,8 +428,7 @@ again:
 static void
 krt_learn_async(struct krt_proto *p, rte *e, int new)
 {
-  net *n0 = e->net;
-  net *n = net_get(&p->krt_table, n0->n.addr);
+  net *n = net_get(&p->krt_table, e->netA);
   rte *g, **gg, *best, **bestp, *old_best;
 
   e->attrs = rta_lookup(e->attrs);
@@ -458,6 +456,7 @@ krt_learn_async(struct krt_proto *p, rte *e, int new)
 
       e->next = n->routes;
       n->routes = e;
+      e->netA = n->n.addr;
     }
   else if (!g)
     {
@@ -499,7 +498,7 @@ krt_learn_async(struct krt_proto *p, rte *e, int new)
       if (best)
        krt_learn_announce_update(p, best);
       else
-       krt_learn_announce_delete(p, n);
+       krt_learn_announce_delete(p, n->n.addr);
     }
 }
 
@@ -539,6 +538,15 @@ krt_dump_attrs(rte *e)
  *     Routes
  */
 
+static void
+krt_replace_net_rte(struct krt_proto *p, net *net, rte *new, rte *old)
+{
+  if (krt_replace_rte(p, new, old))
+    net->n.flags &= ~KRF_SYNC_ERROR;
+  else
+    net->n.flags |= KRF_SYNC_ERROR;
+}
+
 static void
 krt_flush_routes(struct krt_proto *p)
 {
@@ -551,7 +559,7 @@ krt_flush_routes(struct krt_proto *p)
       if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED))
        {
          /* FIXME: this does not work if gw is changed in export filter */
-         krt_replace_rte(p, e->net, NULL, e);
+         krt_replace_net_rte(p, n, NULL, e);
          n->n.flags &= ~KRF_INSTALLED;
        }
     }
@@ -621,8 +629,8 @@ krt_same_dest(rte *k, rte *e)
 void
 krt_got_route(struct krt_proto *p, rte *e)
 {
-  net *net = e->net;
   int verdict;
+  net *net = net_get(p->p.main_channel->table, e->netA);
 
 #ifdef KRT_ALLOW_LEARN
   switch (e->u.krt.src)
@@ -635,7 +643,7 @@ krt_got_route(struct krt_proto *p, rte *e)
       verdict = KRF_DELETE;
       goto sentenced;
 
-    case  KRT_SRC_ALIEN:
+    case KRT_SRC_ALIEN:
       if (KRT_CF->learn)
        krt_learn_scan(p, e);
       else
@@ -697,6 +705,7 @@ krt_got_route(struct krt_proto *p, rte *e)
       e->attrs = rta_lookup(a);
       e->next = net->routes;
       net->routes = e;
+      e->netA = net->n.addr;
     }
   else
     rte_free(e);
@@ -739,7 +748,7 @@ krt_prune(struct krt_proto *p)
          if (new && (n->n.flags & KRF_INSTALLED))
            {
              krt_trace_in(p, new, "reinstalling");
-             krt_replace_rte(p, n, new, NULL);
+             krt_replace_net_rte(p, n, new, NULL);
            }
          break;
        case KRF_SEEN:
@@ -748,11 +757,11 @@ krt_prune(struct krt_proto *p)
          break;
        case KRF_UPDATE:
          krt_trace_in(p, new, "updating");
-         krt_replace_rte(p, n, new, old);
+         krt_replace_net_rte(p, n, new, old);
          break;
        case KRF_DELETE:
          krt_trace_in(p, old, "deleting");
-         krt_replace_rte(p, n, NULL, old);
+         krt_replace_net_rte(p, n, NULL, old);
          break;
        default:
          bug("krt_prune: invalid route status");
@@ -779,8 +788,6 @@ krt_prune(struct krt_proto *p)
 void
 krt_got_route_async(struct krt_proto *p, rte *e, int new)
 {
-  net *net = e->net;
-
   switch (e->u.krt.src)
     {
     case KRT_SRC_BIRD:
@@ -791,7 +798,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new)
       if (new)
        {
          krt_trace_in(p, e, "[redirect] deleting");
-         krt_replace_rte(p, net, NULL, e);
+         krt_replace_rte(p, NULL, e);
        }
       /* If !new, it is probably echo of our deletion */
       break;
@@ -957,8 +964,9 @@ krt_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
      * We will remove KRT_INSTALLED flag, which stops such withdraw to be
      * processed in krt_rt_notify() and krt_replace_rte().
      */
-    if (e == e->net->routes)
-      e->net->n.flags &= ~KRF_INSTALLED;
+    struct network *n = RTE_NET(e);
+    if (e == n->routes)
+      n->n.flags &= ~KRF_INSTALLED;
 #endif
     return -1;
   }
@@ -984,7 +992,7 @@ krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net,
   else
     net->n.flags &= ~KRF_INSTALLED;
   if (p->initialized)          /* Before first scan we don't touch the routes */
-    krt_replace_rte(p, net, new, old);
+    krt_replace_net_rte(p, net, new, old);
 }
 
 static void
index 6ace2a869c26c362ed1cae970304ce819ba2c896..62e32cd85cfc50d59f6110c3a54d6ca6e7c6cf77 100644 (file)
@@ -139,7 +139,7 @@ void krt_sys_copy_config(struct krt_config *, struct krt_config *);
 
 int  krt_capable(rte *e);
 void krt_do_scan(struct krt_proto *);
-void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old);
+int krt_replace_rte(struct krt_proto *p, rte *new, rte *old);
 int krt_sys_get_attr(eattr *a, byte *buf, int buflen);