From a401840d1138dbba671ea1af533be2f3f01de73b Mon Sep 17 00:00:00 2001 From: Alexander V. Chernikov Date: Thu, 21 Feb 2013 00:14:49 +0000 Subject: [PATCH 1/1] Add MRT patch --- sysdep/bsd/Modules | 1 + sysdep/bsd/fib.Y | 29 +++++++++++++ sysdep/bsd/krt-sock.c | 105 +++++++++++++++++++++++++++++++++++++++++------- sysdep/bsd/krt-sys.h | 2 + sysdep/cf/bsd-v6.h | 1 + sysdep/cf/bsd.h | 1 + sysdep/unix/krt.c | 10 +++-- sysdep/unix/krt.h | 1 + 8 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 sysdep/bsd/fib.Y diff --git a/sysdep/bsd/Modules b/sysdep/bsd/Modules index 3729587..80878a7 100644 --- sysdep/bsd/Modules +++ sysdep/bsd/Modules @@ -1,3 +1,4 @@ krt-sock.c krt-sys.h sysio.h +fib.Y diff --git a/sysdep/bsd/fib.Y b/sysdep/bsd/fib.Y new file mode 100644 index 0000000..cbb788f --- /dev/null +++ sysdep/bsd/fib.Y @@ -0,0 +1,29 @@ +/* + * BIRD -- FreeBSD rtsock configuration + * + * (c) 2011 Alexander V. Chernikov + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +CF_HDR + +CF_DECLS + +CF_KEYWORDS(ASYNC, KERNEL, TABLE, KRT_PREFSRC, KRT_REALM) + +CF_GRAMMAR + +CF_ADDTO(kern_proto, kern_proto rtsock_item ';') + +rtsock_item: + KERNEL TABLE expr { + if ($3 < 0 || $3 >= max_fib_num()) + cf_error("Kernel routing table number out of range"); + THIS_KRT->sys.table_id = $3; + } + ; + +CF_CODE + +CF_END diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index ae5638e..af69458 100644 --- sysdep/bsd/krt-sock.c +++ sysdep/bsd/krt-sock.c @@ -37,6 +37,9 @@ #endif +int my_fib_get(void); +int my_fib_set(int); + #ifndef RTAX_MAX #define RTAX_MAX 8 #endif @@ -48,8 +51,6 @@ struct ks_msg }; -static int rt_sock = 0; - int krt_capable(rte *e) { @@ -108,6 +109,51 @@ fill_mpls_sockaddr(struct sockaddr_mpls *sm, struct bird_mpls_entry *me) } #endif + +int +max_fib_num() +{ + int fibs = 1; + size_t fibs_len = sizeof(fibs); + if (sysctlbyname("net.fibs", &fibs, &fibs_len, NULL, 0) == -1) + { + log(L_ERR "KRT: unable to get fib number, assuming 1. error: %s", strerror(errno)); + return 1; + } + + log(L_TRACE "Max fibs: %d", fibs); + return fibs; +} + +int +my_fib_get() +{ + int fib = 0; + size_t fib_len = sizeof(fib); + if (sysctlbyname("net.my_fibnum", &fib, &fib_len, NULL, 0) == -1) + { + log(L_ERR "KRT: unable to get fib number, assuming 0. error: %s", strerror(errno)); + return 0; + } + + return fib; +} + +int +my_fib_set(int fib) +{ + int old_fib = my_fib_get(); + + if ((fib != old_fib) && (setfib(fib) == -1)) + { + log(L_ERR "KRT: setfib(%d) failed: %s", fib, strerror(errno)); + die("Cannot set fib for kernel socket"); + } + + return old_fib; +} + + #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) @@ -124,7 +170,7 @@ fill_mpls_sockaddr(struct sockaddr_mpls *sm, struct bird_mpls_entry *me) body += l;} static int -krt_sock_send(int cmd, rte *e) +krt_sock_send(struct krt_proto *p, int cmd, rte *e) { net *net = e->net; rta *a = e->attrs; @@ -265,7 +311,7 @@ krt_sock_send(int cmd, rte *e) l = body - (char *)&msg; msg.rtm.rtm_msglen = l; - if ((l = write(rt_sock, (char *)&msg, l)) < 0) { + if ((l = write(p->rt_sock, (char *)&msg, l)) < 0) { log(L_ERR "KRT: Error sending route %F to kernel", &net->n); return -1; } @@ -274,7 +320,7 @@ krt_sock_send(int cmd, rte *e) } void -krt_replace_rte(struct krt_proto *p UNUSED, net *n, rte *new, rte *old, +krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs UNUSED) { int err = 0; @@ -282,12 +328,12 @@ krt_replace_rte(struct krt_proto *p UNUSED, net *n, rte *new, rte *old, if (old) { DBG("krt_remove_route(%F)\n", &n->n); - krt_sock_send(RTM_DELETE, old); + krt_sock_send(p, RTM_DELETE, old); } if (new) { DBG("krt_add_route(%F)\n", &n->n); - krt_sock_send(RTM_ADD, new); + krt_sock_send(p, RTM_ADD, new); } if (err < 0) @@ -707,6 +753,8 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd) size_t obl, needed; struct ks_msg *m; int retries = 3; + struct krt_config *c; + int fib = 0, old_fib = 0; mib[0] = CTL_NET; mib[1] = PF_ROUTE; @@ -715,6 +763,18 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd) mib[4] = cmd; mib[5] = 0; + if (p->proto == &proto_unix_kernel) + { + c = (struct krt_config *)p->cf; + fib = c->sys.table_id; + + DBG("KRT: Setting fib to %d for route dump\n", fib); + if (p->debug & D_ROUTES) + log(L_TRACE "Setting fib to %d for route dump", fib); + + old_fib = my_fib_set(fib); + } + try: if (sysctl(mib, 6 , NULL , &needed, NULL, 0) < 0) die("krt_sysctl_scan 1: %m"); @@ -739,6 +799,7 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd) goto try; log(L_ERR "KRT: Route scan failed"); + my_fib_set(old_fib); return; } die("krt_sysctl_scan 2: %m"); @@ -749,6 +810,8 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd) m = (struct ks_msg *)next; krt_read_msg(p, m, 1); } + + my_fib_set(old_fib); } static byte *krt_buffer = NULL; @@ -789,25 +852,32 @@ void krt_sys_start(struct krt_proto *x, int first UNUSED) { sock *sk_rt; - static int ks_open_tried = 0; + struct krt_config *c; + int fib = 0, old_fib = 0; - if (ks_open_tried) - return; + if (x->p.proto == &proto_unix_kernel) + { + c = (struct krt_config *)x->p.cf; + fib = c->sys.table_id; - ks_open_tried = 1; + DBG("KRT: Opening kernel socket to fib %d\n", fib); - DBG("KRT: Opening kernel socket\n"); + old_fib = my_fib_set(fib); + } - if( (rt_sock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0) + if( (x->rt_sock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0) die("Cannot open kernel socket for routes"); sk_rt = sk_new(krt_pool); sk_rt->type = SK_MAGIC; sk_rt->rx_hook = krt_sock_hook; - sk_rt->fd = rt_sock; + sk_rt->fd = x->rt_sock; sk_rt->data = x; if (sk_open(sk_rt)) bug("krt-sock: sk_open failed"); + + /* Rollback fib */ + my_fib_set(old_fib); } void @@ -816,8 +886,11 @@ krt_sys_shutdown(struct krt_proto *x UNUSED, int last UNUSED) if (!krt_buffer) return; - mb_free(krt_buffer); - krt_buffer = NULL; + if (last) + { + mb_free(krt_buffer); + krt_buffer = NULL; + } } diff --git a/sysdep/bsd/krt-sys.h b/sysdep/bsd/krt-sys.h index 88915dd..8f94b8a 100644 --- sysdep/bsd/krt-sys.h +++ sysdep/bsd/krt-sys.h @@ -31,11 +31,13 @@ static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_c /* Kernel routes */ struct krt_params { + int table_id; }; struct krt_status { }; +int max_fib_num(void); static inline void krt_sys_init(struct krt_proto *p UNUSED) { } static inline int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n UNUSED, struct krt_config *o UNUSED) { return 1; } diff --git a/sysdep/cf/bsd-v6.h b/sysdep/cf/bsd-v6.h index b7f25f6..3403299 100644 --- sysdep/cf/bsd-v6.h +++ sysdep/cf/bsd-v6.h @@ -10,6 +10,7 @@ #define CONFIG_AUTO_ROUTES #define CONFIG_SELF_CONSCIOUS +#define CONFIG_MULTIPLE_TABLES #define CONFIG_SKIP_MC_BIND diff --git a/sysdep/cf/bsd.h b/sysdep/cf/bsd.h index e7cc135..1101b22 100644 --- sysdep/cf/bsd.h +++ sysdep/cf/bsd.h @@ -8,6 +8,7 @@ #define CONFIG_AUTO_ROUTES #define CONFIG_SELF_CONSCIOUS +#define CONFIG_MULTIPLE_TABLES #define CONFIG_SKIP_MC_BIND diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index fed9c32..86a0973 100644 --- sysdep/unix/krt.c +++ sysdep/unix/krt.c @@ -577,9 +577,9 @@ krt_dump_attrs(rte *e) #ifdef CONFIG_ALL_TABLES_AT_ONCE static timer *krt_scan_timer; -static int krt_instance_count; static list krt_instance_list; #endif +static int krt_instance_count; static void krt_flush_routes(struct krt_proto *p, struct rtable *t) @@ -982,6 +982,7 @@ krt_start(struct proto *P) add_tail(&krt_instance_list, &p->instance_node); #else p->krt_pool = P->pool; + krt_instance_count++; #endif #ifdef KRT_ALLOW_LEARN @@ -1031,11 +1032,12 @@ krt_shutdown(struct proto *P) struct krt_proto *p = (struct krt_proto *) P; int last = 1; -#ifdef CONFIG_ALL_TABLES_AT_ONCE - rem_node(&p->instance_node); if (--krt_instance_count) last = 0; - else + +#ifdef CONFIG_ALL_TABLES_AT_ONCE + rem_node(&p->instance_node); + if (!krt_instance_count) #endif tm_stop(p->scan_timer); diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 14fb54a..0bac4a3 100644 --- sysdep/unix/krt.h +++ sysdep/unix/krt.h @@ -81,6 +81,7 @@ struct krt_proto { #ifdef CONFIG_ALL_TABLES_AT_ONCE node instance_node; /* Node in krt instance list */ #endif + int rt_sock; /* Routing socket descriptor */ int initialized; /* First scan has already been finished */ }; -- 1.7.3.2