]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Handle export table internally
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 5 Feb 2020 22:59:54 +0000 (23:59 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 5 Feb 2020 22:59:54 +0000 (23:59 +0100)
Handle export table internally in BGP protocol instead of in
channel and put there exported route after full BGP processing.

nest/protocol.h
nest/rt-table.c
proto/bgp/attrs.c
proto/bgp/bgp.c

index 4d8584f2b7b29c17e4cc7c51299099ace30536d8..85aeec997c318290919c99871de16b0c349f154c 100644 (file)
@@ -521,6 +521,7 @@ struct channel {
   struct fib_iterator reload_fit;      /* Iterator in in_table used during reloading */
   u8 reload_active;                    /* Iterator reload_fit is linked */
 
+  u8 out_table_int;                    /* Update of out_table is handled internally by protocol */
   struct rtable *out_table;            /* Internal table for exported routes */
 };
 
index fe402cbabfbd6527364e85efed34f5db288452d9..5983bd4c4c23f520b7466526b5c509cd11678fa9 100644 (file)
@@ -612,7 +612,8 @@ do_rt_notify(struct channel *c, net *net, rte *new, rte *old, ea_list *tmpa, int
        }
     }
 
-  if (c->out_table && !rte_update_out(c, net->n.addr, new, old, &old_free, refeed))
+  if (c->out_table && !c->out_table_int &&
+      !rte_update_out(c, net->n.addr, new, old, &old_free, refeed))
     return;
 
   /* Use route from export_table as old */
index 8132a2c989fb60a6761882b430c04e3ed7fd2b10..be3c9d20b2dd64f5685f4ee4e6c1318023527315 100644 (file)
@@ -1553,6 +1553,33 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea
   {
     attrs = bgp_update_attrs(p, c, new, attrs, bgp_linpool2);
 
+    if (c->c.out_table && c->c.out_table_int)
+    {
+      rte *old_free = NULL;
+      rte *new1 = NULL;
+
+      /* Prepare new1 as final route after bgp_update_attrs() attribute changes */
+      if (attrs)
+      {
+       new1 = rte_cow_rta(new, bgp_linpool2);
+       new1->attrs->eattrs = attrs;
+      }
+
+      /* Update out_table, we use 'new' as 'old' to ensure it is non-NULL */
+      int drop = !rte_update_out(C, n->n.addr, new1, new, &old_free, new == old);
+
+      if (new1 != new)
+       rte_free(new1);
+      if (old_free)
+       rte_free(old_free);
+
+      if (drop)
+      {
+       lp_flush(bgp_linpool2);
+       return;
+      }
+    }
+
     /* If attributes are invalid, we fail back to withdraw */
     buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c);
     path = new->attrs->src->global_id;
@@ -1561,6 +1588,17 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea
   }
   else
   {
+    if (c->c.out_table && c->c.out_table_int)
+    {
+      rte *old_free = NULL;
+
+      if (!rte_update_out(C, n->n.addr, new, old, &old_free, 0))
+       return;
+
+      if (old_free)
+       rte_free(old_free);
+    }
+
     buck = bgp_get_withdraw_bucket(c);
     path = old->attrs->src->global_id;
   }
index c3ae2ab1c0100491186743e95eac346d05abfb6c..2b511af0864912516cde278b2549f4844e83d4c2 100644 (file)
@@ -1543,7 +1543,10 @@ bgp_channel_start(struct channel *C)
    channel_setup_in_table(C);
 
   if (c->cf->export_table)
+  {
     channel_setup_out_table(C);
+    C->out_table_int = 1;
+  }
 
   c->next_hop_addr = c->cf->next_hop_addr;
   c->link_addr = IPA_NONE;