]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
KRT: Using obligatory export table when non-trivial filters are applied.
authorMaria Matejka <mq@ucw.cz>
Sat, 20 Mar 2021 20:14:54 +0000 (21:14 +0100)
committerMaria Matejka <mq@ucw.cz>
Sat, 20 Mar 2021 22:24:12 +0000 (23:24 +0100)
When the kernel filter is anything more sophisticated than FILTER_ACCEPT
or FILTER_REJECT, we should ensure that the old route being sent to the
kernel protocol is really what was sent there before. This fixes the old
misbehavior when an unfiltered old route was used.

filter/filter.h
nest/protocol.h
sysdep/unix/krt.Y
sysdep/unix/krt.c

index 26c1037b71f815491019220636cd4222e0096861..77d39bbff1aed29a13167746aba1279650f1d070 100644 (file)
@@ -68,6 +68,8 @@ void filters_dump_all(void);
 #define FILTER_REJECT ((struct filter *) 1)
 #define FILTER_UNDEF  ((struct filter *) 2)    /* Used in BGP */
 
+#define TRIVIAL_FILTER(f)   (((f) == FILTER_REJECT) || ((f) == FILTER_ACCEPT))
+
 #define FF_SILENT 2                    /* Silent filter execution */
 
 /* Custom route attributes */
index 817fd35a3834de953df3e534d9de9da809147a37..ef7334adcc32db7e2d9fde16a5b66e51ab686508 100644 (file)
@@ -471,7 +471,7 @@ struct channel_class {
 #endif
 };
 
-extern struct channel_class channel_bgp;
+extern struct channel_class channel_bgp, channel_krt;
 
 struct channel_config {
   node n;
index 95b54d65dae1454bc09fcbbdd7d4bfff3677cd43..623cbd92dc702a4fac0a43c6022141fc89962b7b 100644 (file)
@@ -33,6 +33,7 @@ CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, GRACEFUL, RESTAR
 CF_KEYWORDS(INTERFACE, PREFERRED)
 
 %type <i> kern_mp_limit
+%type <cc> kern_channel_start kern_proto_channel
 
 CF_GRAMMAR
 
@@ -53,9 +54,17 @@ kern_mp_limit:
  | LIMIT expr  { $$ = $2; if (($2 <= 0) || ($2 > 255)) cf_error("Merge paths limit must be in range 1-255"); }
  ;
 
+kern_channel_start: net_type
+{
+  $$ = this_channel = channel_config_get(&channel_krt, net_label[$1], $1, this_proto);
+  this_proto->net_type = $1;
+};
+
+kern_proto_channel: kern_channel_start channel_opt_list channel_end;
+
 kern_item:
    proto_item
- | proto_channel { this_proto->net_type = $1->net_type; }
+ | kern_proto_channel
  | PERSIST bool { THIS_KRT->persist = $2; }
  | SCAN TIME expr {
       /* Scan time of 0 means scan on startup only */
index 9485e02e30bb7ddfc4fee6478c0f7943a0061f1f..527d8b3ffa4d4dbcc4c8f33ed4f66166e8116621 100644 (file)
@@ -1033,6 +1033,11 @@ krt_start(struct proto *P)
   default: log(L_ERR "KRT: Tried to start with strange net type: %d", p->p.net_type); return PS_START; break;
   }
 
+  /* If it is needed, setup out table automagically */
+  if (!TRIVIAL_FILTER(p->p.main_channel->out_filter))
+    channel_setup_out_table(p->p.main_channel);
+
+
   bmap_init(&p->sync_map, p->p.pool, 1024);
   bmap_init(&p->seen_map, p->p.pool, 1024);
   add_tail(&krt_proto_list, &p->krt_node);
@@ -1079,6 +1084,15 @@ krt_shutdown(struct proto *P)
   return PS_DOWN;
 }
 
+static int
+krt_channel_reconfigure(struct channel *C, struct channel_config *CC, int *import_changed UNUSED, int *export_changed)
+{
+  if (!*export_changed)
+    return 1;
+
+  return (TRIVIAL_FILTER(C->out_filter) == TRIVIAL_FILTER(CC->out_filter));
+}
+
 static int
 krt_reconfigure(struct proto *p, struct proto_config *CF)
 {
@@ -1151,6 +1165,12 @@ krt_get_attr(const eattr *a, byte *buf, int buflen)
 #define MAYBE_MPLS     0
 #endif
 
+struct channel_class channel_krt = {
+  .channel_size = sizeof(struct channel),
+  .config_size = sizeof(struct channel_config),
+  .reconfigure = krt_channel_reconfigure,
+};
+
 struct protocol proto_unix_kernel = {
   .name =              "Kernel",
   .template =          "kernel%d",