]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Static: Support for dual-AF IGP tables
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Thu, 30 Mar 2017 11:29:34 +0000 (13:29 +0200)
committerJan Moskyto Matejka <mq@ucw.cz>
Wed, 12 Apr 2017 14:04:22 +0000 (16:04 +0200)
When recursive routes with hybrid next hops (e.g. IPv6 route with IPv4 next
hop) are allowed, we need both IPv4 and IPv6 IGP tables.

proto/bgp/bgp.c
proto/static/config.Y
proto/static/static.c
proto/static/static.h

index 01ac5453ae237cd9d90c8af90c88380f25324c7d..86f7be1bc87c09c588c519abe318e2234bec7a58 100644 (file)
@@ -1732,6 +1732,8 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF)
   return same;
 }
 
+#define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL )
+
 static int
 bgp_channel_reconfigure(struct channel *C, struct channel_config *CC)
 {
@@ -1746,12 +1748,8 @@ bgp_channel_reconfigure(struct channel *C, struct channel_config *CC)
     return 0;
 
   /* Check change in IGP tables */
-  rtable *old4 = old->igp_table_ip4 ? old->igp_table_ip4->table : NULL;
-  rtable *old6 = old->igp_table_ip6 ? old->igp_table_ip6->table : NULL;
-  rtable *new4 = new->igp_table_ip4 ? new->igp_table_ip4->table : NULL;
-  rtable *new6 = new->igp_table_ip6 ? new->igp_table_ip6->table : NULL;
-
-  if ((old4 != new4) || (old6 != new6))
+  if ((IGP_TABLE(old, ip4) != IGP_TABLE(new, ip4)) ||
+      (IGP_TABLE(old, ip6) != IGP_TABLE(new, ip6)))
     return 0;
 
   c->cf = new;
index cd8bfcecb927b19eca8e9af05d22f18f99bbfc0e..6643ba69916ca4b5c2f65ffa103286f479dd651d 100644 (file)
@@ -59,7 +59,14 @@ static_proto:
  | static_proto proto_item ';'
  | static_proto proto_channel ';' { this_proto->net_type = $2->net_type; }
  | static_proto CHECK LINK bool ';' { STATIC_CFG->check_link = $4; }
- | static_proto IGP TABLE rtable ';' { STATIC_CFG->igp_table = $4; }
+ | static_proto IGP TABLE rtable ';' {
+    if ($4->addr_type == NET_IP4)
+      STATIC_CFG->igp_table_ip4 = $4;
+    else if ($4->addr_type == NET_IP6)
+      STATIC_CFG->igp_table_ip6 = $4;
+    else
+      cf_error("Incompatible IGP table type");
+   }
  | static_proto stat_route stat_route_opt_list ';' { static_route_finish(); }
  ;
 
index adefa0b2141b36eec010aaf80d0ff51dcb28499d..f74ecee04952758350fde6e7b775575a3030e25f 100644 (file)
 
 static linpool *static_lp;
 
-static inline rtable *
-p_igp_table(struct static_proto *p)
-{
-  struct static_config *cf = (void *) p->p.cf;
-  return cf->igp_table ? cf->igp_table->table : p->p.main_channel->table;
-}
-
 static void
 static_announce_rte(struct static_proto *p, struct static_route *r)
 {
@@ -95,7 +88,10 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
   }
 
   if (r->dest == RTDX_RECURSIVE)
-    rta_set_recursive_next_hop(p->p.main_channel->table, a, p_igp_table(p), r->via, IPA_NONE, r->mls);
+  {
+    rtable *tab = ipa_is_ip4(r->via) ? p->igp_table_ip4 : p->igp_table_ip6;
+    rta_set_recursive_next_hop(p->p.main_channel->table, a, tab, r->via, IPA_NONE, r->mls);
+  }
 
   /* Already announced */
   if (r->state == SRS_CLEAN)
@@ -370,6 +366,16 @@ static_postconfig(struct proto_config *CF)
   if (EMPTY_LIST(CF->channels))
     cf_error("Channel not specified");
 
+  struct channel_config *cc = proto_cf_main_channel(CF);
+
+  if (!cf->igp_table_ip4)
+    cf->igp_table_ip4 = (cc->table->addr_type == NET_IP4) ?
+      cc->table : cf->c.global->def_tables[NET_IP4];
+
+  if (!cf->igp_table_ip6)
+    cf->igp_table_ip6 = (cc->table->addr_type == NET_IP6) ?
+      cc->table : cf->c.global->def_tables[NET_IP6];
+
   WALK_LIST(r, cf->routes)
     if (r->net && (r->net->type != CF->net_type))
       cf_error("Route %N incompatible with channel type", r->net);
@@ -379,14 +385,20 @@ static struct proto *
 static_init(struct proto_config *CF)
 {
   struct proto *P = proto_new(CF);
-  // struct static_proto *p = (void *) P;
-  // struct static_config *cf = (void *) CF;
+  struct static_proto *p = (void *) P;
+  struct static_config *cf = (void *) CF;
 
   P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
 
   P->neigh_notify = static_neigh_notify;
   P->rte_mergable = static_rte_mergable;
 
+  if (cf->igp_table_ip4)
+    p->igp_table_ip4 = cf->igp_table_ip4->table;
+
+  if (cf->igp_table_ip6)
+    p->igp_table_ip6 = cf->igp_table_ip6->table;
+
   return P;
 }
 
@@ -400,8 +412,11 @@ static_start(struct proto *P)
   if (!static_lp)
     static_lp = lp_new(&root_pool, 1008);
 
-  if (cf->igp_table)
-    rt_lock_table(cf->igp_table->table);
+  if (p->igp_table_ip4)
+    rt_lock_table(p->igp_table_ip4);
+
+  if (p->igp_table_ip6)
+    rt_lock_table(p->igp_table_ip6);
 
   p->event = ev_new(p->p.pool);
   p->event->hook = static_announce_marked;
@@ -435,10 +450,13 @@ static_shutdown(struct proto *P)
 static void
 static_cleanup(struct proto *P)
 {
-  struct static_config *cf = (void *) P->cf;
+  struct static_proto *p = (void *) P;
+
+  if (p->igp_table_ip4)
+    rt_unlock_table(p->igp_table_ip4);
 
-  if (cf->igp_table)
-    rt_unlock_table(cf->igp_table->table);
+  if (p->igp_table_ip6)
+    rt_unlock_table(p->igp_table_ip6);
 }
 
 static void
@@ -465,11 +483,7 @@ static_dump(struct proto *P)
     static_dump_rte(r);
 }
 
-static inline rtable *
-cf_igp_table(struct static_config *cf)
-{
-  return cf->igp_table ? cf->igp_table->table : NULL;
-}
+#define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL )
 
 static inline int
 static_cmp_rte(const void *X, const void *Y)
@@ -486,7 +500,9 @@ static_reconfigure(struct proto *P, struct proto_config *CF)
   struct static_config *n = (void *) CF;
   struct static_route *r, *r2, *or, *nr;
 
-  if (cf_igp_table(o) != cf_igp_table(n))
+  /* Check change in IGP tables */
+  if ((IGP_TABLE(o, ip4) != IGP_TABLE(n, ip4)) ||
+      (IGP_TABLE(o, ip6) != IGP_TABLE(n, ip6)))
     return 0;
 
   if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)))
index 0976a9c98f49856553b6d9c6290af34244fb87b3..c84dfa98f34feed0abf94d9a0ddf0ffc20e77836 100644 (file)
@@ -17,7 +17,8 @@ struct static_config {
   struct proto_config c;
   list routes;                         /* List of static routes (struct static_route) */
   int check_link;                      /* Whether iface link state is used */
-  struct rtable_config *igp_table;     /* Table used for recursive next hop lookups */
+  struct rtable_config *igp_table_ip4; /* Table for recursive IPv4 next hop lookups */
+  struct rtable_config *igp_table_ip6; /* Table for recursive IPv6 next hop lookups */
 };
 
 struct static_proto {
@@ -25,6 +26,8 @@ struct static_proto {
 
   struct event *event;                 /* Event for announcing updated routes */
   BUFFER(struct static_route *) marked;        /* Routes marked for reannouncement */
+  rtable *igp_table_ip4;               /* Table for recursive IPv4 next hop lookups */
+  rtable *igp_table_ip6;               /* Table for recursive IPv6 next hop lookups */
 };
 
 struct static_route {