summaryrefslogtreecommitdiff
path: root/sysdep/linux
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2016-09-15 14:59:06 +0200
committerOndrej Zajicek (work) <santiago@crfreenet.org>2016-09-15 14:59:06 +0200
commit4adcb9df1bf551cc5fd1145c09af1843fdc4fe85 (patch)
tree569aa0d159e63ea73b40a041300079f81538b34b /sysdep/linux
parent2feaa6931bfe39eba696b33b0c8aac13d313b223 (diff)
KRT: Add kernel metric protocol option
Kernel routes with different metrics do not clash with each other, therefore using dedicated metric value is a reliable way to avoid overwriting routes from other sources (e.g. kernel device routes). Although kernel route metric could already be set as a route attribute by filters, that is not consistent with the way how Linux kernel handles route metric - not just a route attribute, but a part of a route key.
Diffstat (limited to 'sysdep/linux')
-rw-r--r--sysdep/linux/krt-sys.h1
-rw-r--r--sysdep/linux/netlink.Y9
-rw-r--r--sysdep/linux/netlink.c19
3 files changed, 20 insertions, 9 deletions
diff --git a/sysdep/linux/krt-sys.h b/sysdep/linux/krt-sys.h
index 076870f5..96688e34 100644
--- a/sysdep/linux/krt-sys.h
+++ b/sysdep/linux/krt-sys.h
@@ -88,6 +88,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; }
struct krt_params {
u32 table_id; /* Kernel table ID we sync with */
+ u32 metric; /* Kernel metric used for all routes */
};
struct krt_state {
diff --git a/sysdep/linux/netlink.Y b/sysdep/linux/netlink.Y
index e9c225a2..a1c22f3e 100644
--- a/sysdep/linux/netlink.Y
+++ b/sysdep/linux/netlink.Y
@@ -10,8 +10,8 @@ CF_HDR
CF_DECLS
-CF_KEYWORDS(KERNEL, TABLE, KRT_PREFSRC, KRT_REALM, KRT_MTU, KRT_WINDOW, KRT_RTT,
- KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
+CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, KRT_MTU, KRT_WINDOW,
+ KRT_RTT, KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
KRT_HOPLIMIT, KRT_INITCWND, KRT_RTO_MIN, KRT_INITRWND, KRT_QUICKACK,
KRT_LOCK_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR,
KRT_LOCK_SSTRESH, KRT_LOCK_CWND, KRT_LOCK_ADVMSS, KRT_LOCK_REORDERING,
@@ -22,9 +22,8 @@ CF_GRAMMAR
CF_ADDTO(kern_proto, kern_proto kern_sys_item ';')
kern_sys_item:
- KERNEL TABLE expr {
- THIS_KRT->sys.table_id = $3;
- }
+ KERNEL TABLE expr { THIS_KRT->sys.table_id = $3; }
+ | METRIC expr { THIS_KRT->sys.metric = $2; }
;
CF_ADDTO(dynamic_attr, KRT_PREFSRC { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_KRT_PREFSRC); })
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 1ab1cda1..9bdcc0d2 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -880,6 +880,8 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
eattr *ea;
net *net = e->net;
rta *a = e->attrs;
+ u32 priority = 0;
+
struct {
struct nlmsghdr h;
struct rtmsg r;
@@ -912,13 +914,20 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
else
nl_add_attr_u32(&r.h, sizeof(r), RTA_TABLE, krt_table_id(p));
+ if (a->source == RTS_DUMMY)
+ priority = e->u.krt.metric;
+ else if (KRT_CF->sys.metric)
+ priority = KRT_CF->sys.metric;
+ else if ((op != NL_OP_DELETE) && (ea = ea_find(eattrs, EA_KRT_METRIC)))
+ priority = ea->u.data;
+
+ if (priority)
+ nl_add_attr_u32(&r.h, sizeof(r), RTA_PRIORITY, priority);
+
/* For route delete, we do not specify remaining route attributes */
if (op == NL_OP_DELETE)
goto dest;
- if (ea = ea_find(eattrs, EA_KRT_METRIC))
- nl_add_attr_u32(&r.h, sizeof(r), RTA_PRIORITY, ea->u.data);
-
if (ea = ea_find(eattrs, EA_KRT_PREFSRC))
nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
@@ -1585,19 +1594,21 @@ krt_sys_shutdown(struct krt_proto *p)
int
krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o)
{
- return n->sys.table_id == o->sys.table_id;
+ return (n->sys.table_id == o->sys.table_id) && (n->sys.metric == o->sys.metric);
}
void
krt_sys_init_config(struct krt_config *cf)
{
cf->sys.table_id = RT_TABLE_MAIN;
+ cf->sys.metric = 0;
}
void
krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
{
d->sys.table_id = s->sys.table_id;
+ d->sys.metric = s->sys.metric;
}
static const char *krt_metrics_names[KRT_METRICS_MAX] = {