]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Nest: Use rtable for neighbor lookup
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Fri, 31 May 2019 19:23:32 +0000 (21:23 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Fri, 31 May 2019 19:23:32 +0000 (21:23 +0200)
Implicitly define rtables 'local4' and 'local6' and a pair of direct
protocols to fill them. Use modified net_route() for neighbor
lookup to avoid iterating over all interfaces.

conf/conf.h
nest/config.Y
nest/neighbor.c
nest/proto.c
nest/protocol.h
nest/rt-dev.c
nest/rt-dev.h
nest/rt-table.c

index f174d352d22a62c490d13ca665ddc96acc84615d..a2c09282d21ed0f26829f844bed95a33f0d244d8 100644 (file)
@@ -30,6 +30,8 @@ struct config {
   char *syslog_name;                   /* Name used for syslog (NULL -> no syslog) */
   struct rtable_config *def_tables[NET_MAX]; /* Default routing tables for each network */
   struct iface_patt *router_id_from;   /* Configured list of router ID iface patterns */
+  struct rtable_config *local4;
+  struct rtable_config *local6;
 
   u32 router_id;                       /* Our Router ID */
   unsigned proto_default_debug;                /* Default protocol debug mask */
index 5cfadecf08e2675145d9a94d0efcb5bf87c876ff..0650be0444c7d1958976f4ccfb44f72f07255cb1 100644 (file)
@@ -74,7 +74,7 @@ CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENER
 CF_KEYWORDS(BGP, PASSWORDS, DESCRIPTION, SORTED, ORDERED)
 CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
 CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US)
-CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS, STATISTICS)
+CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS, STATISTICS, NETWORKS, ADDRESSES)
 
 /* For r_args_channel */
 CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC)
index 4f93e29e74306e21bf7ec5ac2f0fa2f65f761859..085d3f59b112c1c8d2869d7d479af3aa80b815b8 100644 (file)
@@ -122,6 +122,8 @@ neigh_find(struct proto *p, ip_addr *a, unsigned flags)
   return neigh_find2(p, a, NULL, flags);
 }
 
+struct iface * net_route_ifa(const ip_addr *a, struct iface *vrf);
+
 
 neighbor *
 neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
@@ -153,13 +155,11 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
        scope = class & IADDR_SCOPE_MASK;
     }
   else
-    WALK_LIST(i, iface_list)
-      if ((!p->vrf || p->vrf == i->master) &&
+    {
+      if ((i = net_route_ifa(a, p->vrf)) &&
          ((scope = if_connected(a, i, &addr)) >= 0))
-       {
-         ifa = i;
-         break;
-       }
+       ifa = i;
+    }
 
   /* scope < 0 means i don't know neighbor */
   /* scope >= 0 implies ifa != NULL */
index 4dab562dfe92b3ce0dbc16aab1085430ca2b2a12..38c251a50204288034c07fb24c5085c20fecb63a 100644 (file)
@@ -737,6 +737,7 @@ proto_new(struct proto_config *cf)
   p->proto = cf->protocol;
   p->net_type = cf->net_type;
   p->disabled = cf->disabled;
+  p->hidden = cf->hidden;
   p->hash_key = random_u32();
   cf->proto = p;
 
@@ -1025,7 +1026,13 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty
 
   DBG("Protocol start\n");
 
-  /* Start device protocol first */
+
+  /* Start direct protocols first */
+  WALK_LIST_DELSAFE(p, n, proto_list)
+    if (p->proto == &proto_device)
+      proto_rethink_goal(p);
+
+  /* Start device protocol second */
   if (first_dev_proto)
     proto_rethink_goal(first_dev_proto);
 
@@ -1903,7 +1910,7 @@ proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uintptr_t, int), u
   int cnt = 0;
 
   WALK_LIST(p, proto_list)
-    if (!patt || patmatch(patt, p->name))
+    if ((!patt || patmatch(patt, p->name)) && !p->hidden)
       cmd(p, arg, cnt++);
 
   if (!cnt)
@@ -1943,7 +1950,7 @@ proto_get_named(struct symbol *sym, struct protocol *pr)
   {
     p = NULL;
     WALK_LIST(q, proto_list)
-      if ((q->proto == pr) && (q->proto_state != PS_DOWN))
+      if ((q->proto == pr) && (q->proto_state != PS_DOWN) && !q->hidden)
       {
        if (p)
          cf_error("There are multiple %s protocols running", pr->name);
index 058f362d346c10de499358d271e284b52de31f79..8c8700848bedc8fb02103216cc391f8e4843861f 100644 (file)
@@ -96,6 +96,7 @@ struct proto_config {
   int class;                           /* SYM_PROTO or SYM_TEMPLATE */
   u8 net_type;                         /* Protocol network type (NET_*), 0 for undefined */
   u8 disabled;                         /* Protocol enabled/disabled by default */
+  byte hidden;                         /* Protocol not showed in show protocols */
   u32 debug, mrtdump;                  /* Debugging bitfields, both use D_* constants */
   u32 router_id;                       /* Protocol specific router ID */
 
@@ -160,6 +161,7 @@ struct proto {
   byte gr_recovery;                    /* Protocol should participate in graceful restart recovery */
   byte down_sched;                     /* Shutdown is scheduled for later (PDS_*) */
   byte down_code;                      /* Reason for shutdown (PDC_* codes) */
+  byte hidden;                         /* Protocol not showed in show protocols */
   u32 hash_key;                                /* Random key used for hashing of neighbors */
   btime last_state_change;             /* Time of last state transition */
   char *last_state_name_announced;     /* Last state name we've announced to the user */
index 66f458e7fc3c40ff896a3f2e4319a50de294974c..2b7c0186b1b55f64ff194628a962b8371fd38ca1 100644 (file)
@@ -54,6 +54,12 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
   if (!c)
     return;
 
+  if (cf->host_ip)
+  {
+    net = alloca(sizeof(net_addr));
+    net_fill_ip_host(net, ad->ip);
+  }
+
   /* For IPv6 SADR, replace regular prefix with SADR prefix */
   if (c->net_type == NET_IP6_SADR)
   {
index 5d91242a144f715b3170551b8f83c591c97a594c..695e13515a1d246ad2a35657e273bd0574973db0 100644 (file)
@@ -13,6 +13,7 @@ struct rt_dev_config {
   struct proto_config c;
   list iface_list;             /* list of struct iface_patt */
   int check_link;
+  int host_ip;                 /* Annunce local IP instead of prefix */
 
   struct channel_config *ip4_channel;
   struct channel_config *ip6_channel;
index 47a08d2ae99539a27e976d3aa23733e2b07df3f8..001cfd10756f682645e007502d4d37289c7dc93b 100644 (file)
@@ -34,6 +34,7 @@
 #include "nest/route.h"
 #include "nest/protocol.h"
 #include "nest/iface.h"
+#include "nest/rt-dev.h"
 #include "nest/cli.h"
 #include "lib/resource.h"
 #include "lib/event.h"
@@ -171,6 +172,87 @@ net_route(rtable *tab, const net_addr *n)
   }
 }
 
+static inline struct iface *
+net_route_ifa4(rtable *t, net_addr_ip4 *a, struct iface *vrf)
+{
+  while (1)
+  {
+    if (!BIT32_TEST(t->pxlens, a->pxlen))
+      goto next;
+
+    net *n = net_find(t, (net_addr *) a);
+
+    if (!n)
+      goto next;
+
+    for (rte *e = n->routes; e; e = e->next)
+    {
+      struct iface *i = e->attrs->nh.iface;
+      if (rte_is_valid(e) &&
+         (e->attrs->dest == RTD_UNICAST) &&
+         (!vrf || vrf == i->master))
+       return i;
+    }
+
+  next:
+    if (!a->pxlen)
+      return NULL;
+
+    a->pxlen--;
+    ip4_clrbit(&a->prefix, a->pxlen);
+  }
+}
+
+static inline struct iface *
+net_route_ifa6(rtable *t, net_addr_ip6 *a, struct iface *vrf)
+{
+  while (1)
+  {
+    if (!BIT32_TEST(t->pxlens, a->pxlen))
+      goto next;
+
+    net *n = net_find(t, (net_addr *) a);
+
+    if (!n)
+      goto next;
+
+    for (rte *e = n->routes; e; e = e->next)
+    {
+      struct iface *i = e->attrs->nh.iface;
+      if (rte_is_valid(e) &&
+         (e->attrs->dest == RTD_UNICAST) &&
+         (!vrf || vrf == i->master))
+       return i;
+    }
+
+  next:
+    if (!a->pxlen)
+      return NULL;
+
+    a->pxlen--;
+    ip6_clrbit(&a->prefix, a->pxlen);
+  }
+}
+
+struct iface *
+net_route_ifa(const ip_addr *a, struct iface *vrf)
+{
+  net_addr n0;
+  net_fill_ip_host(&n0, *a);
+
+  switch (n0.type)
+  {
+  case NET_IP4:
+    return net_route_ifa4(config->local4->table, (net_addr_ip4 *) &n0, vrf);
+
+  case NET_IP6:
+    return net_route_ifa6(config->local6->table, (net_addr_ip6 *) &n0, vrf);
+
+  default:
+    return NULL;
+  }
+}
+
 
 static int
 net_roa_check_ip4(rtable *tab, const net_addr_ip4 *px, u32 asn)
@@ -1821,6 +1903,50 @@ rt_preconfig(struct config *c)
 
   rt_new_table(cf_get_symbol("master4"), NET_IP4);
   rt_new_table(cf_get_symbol("master6"), NET_IP6);
+
+  c->local4 = rt_new_table(cf_get_symbol("local4"), NET_IP4);
+  c->local6 = rt_new_table(cf_get_symbol("local6"), NET_IP6);
+
+
+  /* Define two direct protocols and connect them to local tables */
+
+  struct symbol *s;
+  struct rt_dev_config *dev;
+  static struct channel_config *cc;
+
+  s = cf_get_symbol("networks");
+  dev = proto_config_new(&proto_device, SYM_PROTO);
+  init_list(&dev->iface_list);
+  cf_define_symbol(s, SYM_PROTO, dev);
+  dev->c.name = s->name;
+  dev->c.hidden = 1;
+  // dev->c.debug = D_EVENTS | D_STATES | D_IFACES;
+
+  cc = channel_config_get(NULL, net_label[NET_IP4], NET_IP4, &dev->c);
+  cc->table = c->local4;
+
+  cc = channel_config_get(NULL, net_label[NET_IP6], NET_IP6, &dev->c);
+  cc->table = c->local6;
+
+  proto_device.postconfig(&dev->c);
+
+
+  s = cf_get_symbol("addresses");
+  dev = proto_config_new(&proto_device, SYM_PROTO);
+  init_list(&dev->iface_list);
+  cf_define_symbol(s, SYM_PROTO, dev);
+  dev->c.name = s->name;
+  dev->c.hidden = 1;
+  // dev->c.debug = D_EVENTS | D_STATES | D_IFACES;
+  dev->host_ip = 1;
+
+  cc = channel_config_get(NULL, net_label[NET_IP4], NET_IP4, &dev->c);
+  cc->table = c->local4;
+
+  cc = channel_config_get(NULL, net_label[NET_IP6], NET_IP6, &dev->c);
+  cc->table = c->local6;
+
+  proto_device.postconfig(&dev->c);
 }