summaryrefslogtreecommitdiff
path: root/sysdep
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2015-06-08 02:20:43 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2015-06-08 02:24:08 +0200
commit8d9eef17713a9b38cd42bd59c4ce76c3ef6c2fc2 (patch)
tree3115be5be954d6bbfd05db675b4a5508a50ed9d2 /sysdep
parentdb027a41d47b8fc52b65067ccabe2024554e53ca (diff)
BGP multipath support
Kernel option 'merge paths' allows to merge routes exported to kernel protocol (currently BGP and static routes) to multipath routes.
Diffstat (limited to 'sysdep')
-rw-r--r--sysdep/unix/krt.Y4
-rw-r--r--sysdep/unix/krt.c17
-rw-r--r--sysdep/unix/krt.h3
3 files changed, 18 insertions, 6 deletions
diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y
index 630cda38..e036081d 100644
--- a/sysdep/unix/krt.Y
+++ b/sysdep/unix/krt.Y
@@ -17,7 +17,7 @@ CF_DEFINES
CF_DECLS
-CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, GRACEFUL, RESTART, KRT_SOURCE, KRT_METRIC)
+CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, GRACEFUL, RESTART, KRT_SOURCE, KRT_METRIC, MERGE, PATHS)
CF_GRAMMAR
@@ -47,6 +47,8 @@ kern_item:
}
| DEVICE ROUTES bool { THIS_KRT->devroutes = $3; }
| GRACEFUL RESTART bool { THIS_KRT->graceful_restart = $3; }
+ | MERGE PATHS bool { THIS_KRT->merge_paths = $3 ? KRT_DEFAULT_ECMP_LIMIT : 0; }
+ | MERGE PATHS bool LIMIT expr { THIS_KRT->merge_paths = $3 ? $5 : 0; if (($5 <= 0) || ($5 > 255)) cf_error("Merge paths limit must be in range 1-255"); }
;
/* Kernel interface protocol */
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index d8d28c7c..2eab5cb2 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -595,9 +595,13 @@ krt_flush_routes(struct krt_proto *p)
static struct rte *
krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa)
{
- struct filter *filter = p->p.main_ahook->out_filter;
+ struct announce_hook *ah = p->p.main_ahook;
+ struct filter *filter = ah->out_filter;
rte *rt;
+ if (p->p.accept_ra_types == RA_MERGED)
+ return rt_export_merged(ah, net, rt_free, tmpa, 1);
+
rt = net->routes;
*rt_free = NULL;
@@ -1091,11 +1095,13 @@ krt_rte_same(rte *a, rte *b)
struct krt_config *krt_cf;
static struct proto *
-krt_init(struct proto_config *c)
+krt_init(struct proto_config *C)
{
- struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
+ struct krt_proto *p = proto_new(C, sizeof(struct krt_proto));
+ struct krt_config *c = (struct krt_config *) C;
- p->p.accept_ra_types = RA_OPTIMAL;
+ p->p.accept_ra_types = c->merge_paths ? RA_MERGED : RA_OPTIMAL;
+ p->p.merge_limit = c->merge_paths;
p->p.import_control = krt_import_control;
p->p.rt_notify = krt_rt_notify;
p->p.if_notify = krt_if_notify;
@@ -1161,7 +1167,8 @@ krt_reconfigure(struct proto *p, struct proto_config *new)
return 0;
/* persist, graceful restart need not be the same */
- return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes;
+ return o->scan_time == n->scan_time && o->learn == n->learn &&
+ o->devroutes == n->devroutes && o->merge_paths == n->merge_paths;
}
static void
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index 1940cbcd..9d5d4e8c 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -26,6 +26,8 @@ struct kif_proto;
#define KRF_DELETE 3 /* Should be deleted */
#define KRF_IGNORE 4 /* To be ignored */
+#define KRT_DEFAULT_ECMP_LIMIT 16
+
#define EA_KRT_SOURCE EA_CODE(EAP_KRT, 0)
#define EA_KRT_METRIC EA_CODE(EAP_KRT, 1)
@@ -47,6 +49,7 @@ struct krt_config {
int learn; /* Learn routes from other sources */
int devroutes; /* Allow export of device routes */
int graceful_restart; /* Regard graceful restart recovery */
+ int merge_paths; /* Exported routes are merged for ECMP */
};
struct krt_proto {