summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Ĺ orejs <mail@sorejs.eu>2023-10-06 04:31:19 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2023-10-06 04:55:56 +0200
commite83beb70bd14923cece5b35411606ade6fb8fbee (patch)
tree7433fd0d7a57c5d2190ece9b43516f132976a880
parent57aa077227d1f2440dc1b2bb6cbbebd418a6b898 (diff)
downloadbird-e83beb70bd14923cece5b35411606ade6fb8fbee.tar.gz
KRT: Allow to learn routes with RTPROT_KERNEL
The Kernel protocol, even with the option 'learn' enabled, ignores direct routes created by the OS kernel (on Linux these are routes with rtm_protocol == RTPROT_KERNEL). Implement optional behavior where both OS kernel and third-party routes are learned, it can be enabled by 'learn all' option. Minor changes by committer.
-rw-r--r--doc/bird.sgml11
-rw-r--r--sysdep/linux/netlink.c2
-rw-r--r--sysdep/unix/krt.Y8
-rw-r--r--sysdep/unix/krt.c13
-rw-r--r--sysdep/unix/krt.h4
5 files changed, 28 insertions, 10 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml
index 5e795450..d5bc8d57 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -3764,9 +3764,8 @@ on the <cf/learn/ switch, such routes are either ignored or accepted to our
table).
<p>Note that routes created by OS kernel itself, namely direct routes
-representing IP subnets of associated interfaces, are not imported even with
-<cf/learn/ enabled. You can use <ref id="direct" name="Direct protocol"> to
-generate these direct routes.
+representing IP subnets of associated interfaces, are imported only with
+<cf/learn all/ enabled.
<p>If your OS supports only a single routing table, you can configure only one
instance of the Kernel protocol. If it supports multiple tables (in order to
@@ -3797,10 +3796,12 @@ channels.
Time in seconds between two consecutive scans of the kernel routing
table.
- <tag><label id="krt-learn">learn <m/switch/</tag>
+ <tag><label id="krt-learn">learn <m/switch/|all</tag>
Enable learning of routes added to the kernel routing tables by other
routing daemons or by the system administrator. This is possible only on
- systems which support identification of route authorship.
+ systems which support identification of route authorship. By default,
+ routes created by kernel (marked as "proto kernel") are not imported.
+ Use <cf/learn all/ option to import even these routes.
<tag><label id="krt-kernel-table">kernel table <m/number/</tag>
Select which kernel table should this particular instance of the Kernel
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 1af78766..29446cab 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -1598,7 +1598,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
case RTPROT_KERNEL:
krt_src = KRT_SRC_KERNEL;
- return;
+ break;
case RTPROT_BIRD:
if (!s->scan)
diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y
index 5af6a4c8..90297d3f 100644
--- a/sysdep/unix/krt.Y
+++ b/sysdep/unix/krt.Y
@@ -32,6 +32,7 @@ CF_DECLS
CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, GRACEFUL, RESTART, KRT_SOURCE, KRT_METRIC, MERGE, PATHS)
CF_KEYWORDS(INTERFACE, PREFERRED)
+%type <i> kern_learn
%type <i> kern_mp_limit
%type <cc> kern_channel
@@ -49,6 +50,11 @@ kern_proto_start: proto_start KERNEL {
kern_proto: kern_proto_start proto_name '{' ;
kern_proto: kern_proto kern_item ';' ;
+kern_learn:
+ bool { $$ = $1 ? KRT_LEARN_ALIEN : KRT_LEARN_NONE; }
+ | ALL { $$ = KRT_LEARN_ALL; }
+ ;
+
kern_mp_limit:
/* empty */ { $$ = KRT_DEFAULT_ECMP_LIMIT; }
| LIMIT expr { $$ = $2; if (($2 <= 0) || ($2 > 255)) cf_error("Merge paths limit must be in range 1-255"); }
@@ -68,7 +74,7 @@ kern_item:
/* Scan time of 0 means scan on startup only */
THIS_KRT->scan_time = $3 S_;
}
- | LEARN bool {
+ | LEARN kern_learn {
THIS_KRT->learn = $2;
#ifndef KRT_ALLOW_LEARN
if ($2)
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 9f95247f..3a4b24dc 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -639,12 +639,14 @@ krt_got_route(struct krt_proto *p, rte *e, s8 src)
#ifdef KRT_ALLOW_LEARN
switch (src)
{
- case KRT_SRC_KERNEL:
- goto ignore;
-
case KRT_SRC_REDIRECT:
goto delete;
+ case KRT_SRC_KERNEL:
+ if (KRT_CF->learn != KRT_LEARN_ALL)
+ goto ignore;
+ /* fallthrough */
+
case KRT_SRC_ALIEN:
if (KRT_CF->learn)
krt_learn_scan(p, e);
@@ -780,6 +782,11 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
break;
#ifdef KRT_ALLOW_LEARN
+ case KRT_SRC_KERNEL:
+ if (KRT_CF->learn != KRT_LEARN_ALL)
+ break;
+ /* fallthrough */
+
case KRT_SRC_ALIEN:
if (KRT_CF->learn)
{
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index 18a206e6..e25f0b12 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -27,6 +27,10 @@ struct kif_proto;
#define KRT_REF_SEEN 0x1 /* Seen in table */
#define KRT_REF_BEST 0x2 /* Best in table */
+#define KRT_LEARN_NONE 0 /* Do not learn */
+#define KRT_LEARN_ALIEN 1 /* Learn KRT_SRC_ALIEN routes */
+#define KRT_LEARN_ALL 2 /* Learn both KRT_SRC_ALIEN and KRT_SRC_KERNEL routes */
+
/* Whenever we recognize our own routes, we allow learing of foreign routes */
#ifdef CONFIG_SELF_CONSCIOUS