From 9ba2798c65c02254ec000ab03a76fbbaae1ddc97 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Fri, 23 Mar 2012 01:17:02 +0100 Subject: [PATCH] Adds krt_metric linux route attribute. --- doc/bird.sgml | 6 +++++- sysdep/linux/netlink/netlink.c | 5 ++++- sysdep/unix/krt.Y | 5 +++-- sysdep/unix/krt.c | 25 ++++++++++++++++++++++--- sysdep/unix/krt.h | 5 +++-- 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/doc/bird.sgml b/doc/bird.sgml index 5f478066..5244fc39 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1653,12 +1653,16 @@ are translated to appropriate system (and OS-specific) route attributes. We support these attributes: - int The source of the imported + int The original source of the imported kernel route. The value is system-dependent. On Linux, it is a value of the protocol field of the route. See /etc/iproute2/rt_protos for common values. On BSD, it is based on STATIC and PROTOx flags. The attribute is read-only. + int The kernel metric of + the route. When multiple same routes are in a kernel routing + table, the Linux kernel chooses one with lower metric. + ip (Linux) The preferred source address. Used in source address selection for outgoing packets. Have to be one of IP addresses of the router. diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c index 17c369ea..a0743da7 100644 --- a/sysdep/linux/netlink/netlink.c +++ b/sysdep/linux/netlink/netlink.c @@ -639,6 +639,9 @@ nl_send_route(struct krt_proto *p, rte *e, int new) r.r.rtm_scope = RT_SCOPE_UNIVERSE; nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix); + if (ea = ea_find(a->eattrs, EA_KRT_METRIC)) + nl_add_attr_u32(&r.h, sizeof(r), RTA_PRIORITY, ea->u.data); + if (ea = ea_find(a->eattrs, EA_KRT_PREFSRC)) nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data); @@ -886,7 +889,7 @@ nl_parse_route(struct nlmsghdr *h, int scan) e->u.krt.type = i->rtm_type; if (a[RTA_PRIORITY]) - memcpy(&e->u.krt.metric, RTA_DATA(a[RTA_PRIORITY]), sizeof(e->u.krt.metric)); + memcpy(&e->u.krt.metric, RTA_DATA(a[RTA_PRIORITY]), sizeof(e->u.krt.metric)); else e->u.krt.metric = 0; diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y index 2c45c5fe..c0141f57 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, KRT_SOURCE) +CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, KRT_SOURCE, KRT_METRIC) CF_GRAMMAR @@ -90,7 +90,8 @@ kif_item: } ; -CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SOURCE); }) +CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_SOURCE); }) +CF_ADDTO(dynamic_attr, KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_METRIC); }) CF_CODE diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index de1188a1..f4bfca78 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -907,22 +907,36 @@ krt_shutdown(struct proto *P) return PS_DOWN; } -struct ea_list * +static struct ea_list * krt_make_tmp_attrs(struct rte *rt, struct linpool *pool) { - struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 1 * sizeof(eattr)); + struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr)); l->next = NULL; l->flags = EALF_SORTED; - l->count = 1; + l->count = 2; + l->attrs[0].id = EA_KRT_SOURCE; l->attrs[0].flags = 0; l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP; l->attrs[0].u.data = rt->u.krt.proto; + l->attrs[1].id = EA_KRT_METRIC; + l->attrs[1].flags = 0; + l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP; + l->attrs[1].u.data = rt->u.krt.metric; + return l; } +static void +krt_store_tmp_attrs(struct rte *rt, struct ea_list *attrs) +{ + /* EA_KRT_SOURCE is read-only */ + rt->u.krt.metric = ea_get_int(attrs, EA_KRT_METRIC, 0); +} + + static struct proto * krt_init(struct proto_config *c) { @@ -930,6 +944,7 @@ krt_init(struct proto_config *c) p->p.accept_ra_types = RA_OPTIMAL; p->p.make_tmp_attrs = krt_make_tmp_attrs; + p->p.store_tmp_attrs = krt_store_tmp_attrs; p->p.import_control = krt_import_control; p->p.rt_notify = krt_notify; @@ -973,6 +988,10 @@ krt_get_attr(eattr * a, byte * buf, int buflen UNUSED) bsprintf(buf, "source"); return GA_NAME; + case EA_KRT_METRIC: + bsprintf(buf, "metric"); + return GA_NAME; + case EA_KRT_PREFSRC: bsprintf(buf, "prefsrc"); return GA_NAME; diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index aa1eccaa..d859c5b8 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -29,8 +29,9 @@ struct kif_proto; #define KRF_IGNORE 4 /* To be ignored */ #define EA_KRT_SOURCE EA_CODE(EAP_KRT, 0) -#define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 1) -#define EA_KRT_REALM EA_CODE(EAP_KRT, 2) +#define EA_KRT_METRIC EA_CODE(EAP_KRT, 1) +#define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 2) +#define EA_KRT_REALM EA_CODE(EAP_KRT, 3) /* Whenever we recognize our own routes, we allow learing of foreign routes */