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.
This commit is contained in:
parent
2feaa6931b
commit
4adcb9df1b
4 changed files with 34 additions and 10 deletions
|
@ -2388,6 +2388,17 @@ limitations can be overcome using another routing table and the pipe protocol.
|
||||||
protocol work with. Available only on systems supporting multiple
|
protocol work with. Available only on systems supporting multiple
|
||||||
routing tables.
|
routing tables.
|
||||||
|
|
||||||
|
<tag>metric <m/number/</tag> (Linux)
|
||||||
|
Use specified value as a kernel metric (priority) for all routes sent to
|
||||||
|
the kernel. When multiple routes for the same network are in the kernel
|
||||||
|
routing table, the Linux kernel chooses one with lower metric. Also,
|
||||||
|
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). Metric 0 has a
|
||||||
|
special meaning of undefined metric, in which either OS default is used,
|
||||||
|
or per-route metric can be set using <cf/krt_metric/ attribute. Default:
|
||||||
|
0 (undefined).
|
||||||
|
|
||||||
<tag>graceful restart <m/switch/</tag>
|
<tag>graceful restart <m/switch/</tag>
|
||||||
Participate in graceful restart recovery. If this option is enabled and
|
Participate in graceful restart recovery. If this option is enabled and
|
||||||
a graceful restart recovery is active, the Kernel protocol will defer
|
a graceful restart recovery is active, the Kernel protocol will defer
|
||||||
|
@ -2420,9 +2431,11 @@ these attributes:
|
||||||
route. See /etc/iproute2/rt_protos for common values. On BSD, it is
|
route. See /etc/iproute2/rt_protos for common values. On BSD, it is
|
||||||
based on STATIC and PROTOx flags. The attribute is read-only.
|
based on STATIC and PROTOx flags. The attribute is read-only.
|
||||||
|
|
||||||
<tag>int <cf/krt_metric/</tag>
|
<tag>int <cf/krt_metric/</tag> (Linux)
|
||||||
The kernel metric of the route. When multiple same routes are in a
|
The kernel metric of the route. When multiple same routes are in a
|
||||||
kernel routing table, the Linux kernel chooses one with lower metric.
|
kernel routing table, the Linux kernel chooses one with lower metric.
|
||||||
|
Note that preferred way to set kernel metric is to use protocol option
|
||||||
|
<cf/metric/, unless per-route metric values are needed.
|
||||||
|
|
||||||
<tag>ip <cf/krt_prefsrc/</tag> (Linux)
|
<tag>ip <cf/krt_prefsrc/</tag> (Linux)
|
||||||
The preferred source address. Used in source address selection for
|
The preferred source address. Used in source address selection for
|
||||||
|
|
|
@ -88,6 +88,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; }
|
||||||
|
|
||||||
struct krt_params {
|
struct krt_params {
|
||||||
u32 table_id; /* Kernel table ID we sync with */
|
u32 table_id; /* Kernel table ID we sync with */
|
||||||
|
u32 metric; /* Kernel metric used for all routes */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct krt_state {
|
struct krt_state {
|
||||||
|
|
|
@ -10,8 +10,8 @@ CF_HDR
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(KERNEL, TABLE, KRT_PREFSRC, KRT_REALM, KRT_MTU, KRT_WINDOW, KRT_RTT,
|
CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, KRT_MTU, KRT_WINDOW,
|
||||||
KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
|
KRT_RTT, KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
|
||||||
KRT_HOPLIMIT, KRT_INITCWND, KRT_RTO_MIN, KRT_INITRWND, KRT_QUICKACK,
|
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_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR,
|
||||||
KRT_LOCK_SSTRESH, KRT_LOCK_CWND, KRT_LOCK_ADVMSS, KRT_LOCK_REORDERING,
|
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 ';')
|
CF_ADDTO(kern_proto, kern_proto kern_sys_item ';')
|
||||||
|
|
||||||
kern_sys_item:
|
kern_sys_item:
|
||||||
KERNEL TABLE expr {
|
KERNEL TABLE expr { THIS_KRT->sys.table_id = $3; }
|
||||||
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); })
|
CF_ADDTO(dynamic_attr, KRT_PREFSRC { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_KRT_PREFSRC); })
|
||||||
|
|
|
@ -880,6 +880,8 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
|
||||||
eattr *ea;
|
eattr *ea;
|
||||||
net *net = e->net;
|
net *net = e->net;
|
||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
|
u32 priority = 0;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct nlmsghdr h;
|
struct nlmsghdr h;
|
||||||
struct rtmsg r;
|
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
|
else
|
||||||
nl_add_attr_u32(&r.h, sizeof(r), RTA_TABLE, krt_table_id(p));
|
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 */
|
/* For route delete, we do not specify remaining route attributes */
|
||||||
if (op == NL_OP_DELETE)
|
if (op == NL_OP_DELETE)
|
||||||
goto dest;
|
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))
|
if (ea = ea_find(eattrs, EA_KRT_PREFSRC))
|
||||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
|
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
|
int
|
||||||
krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o)
|
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
|
void
|
||||||
krt_sys_init_config(struct krt_config *cf)
|
krt_sys_init_config(struct krt_config *cf)
|
||||||
{
|
{
|
||||||
cf->sys.table_id = RT_TABLE_MAIN;
|
cf->sys.table_id = RT_TABLE_MAIN;
|
||||||
|
cf->sys.metric = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
|
krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
|
||||||
{
|
{
|
||||||
d->sys.table_id = s->sys.table_id;
|
d->sys.table_id = s->sys.table_id;
|
||||||
|
d->sys.metric = s->sys.metric;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *krt_metrics_names[KRT_METRICS_MAX] = {
|
static const char *krt_metrics_names[KRT_METRICS_MAX] = {
|
||||||
|
|
Loading…
Reference in a new issue