diff options
Diffstat (limited to 'sysdep/unix')
-rw-r--r-- | sysdep/unix/Modules | 10 | ||||
-rw-r--r-- | sysdep/unix/io.c | 2 | ||||
-rw-r--r-- | sysdep/unix/krt-iface.c | 233 | ||||
-rw-r--r-- | sysdep/unix/krt-iface.h | 23 | ||||
-rw-r--r-- | sysdep/unix/krt-set.c | 111 | ||||
-rw-r--r-- | sysdep/unix/krt-set.h | 21 | ||||
-rw-r--r-- | sysdep/unix/krt.Y | 21 | ||||
-rw-r--r-- | sysdep/unix/krt.c | 317 | ||||
-rw-r--r-- | sysdep/unix/krt.h | 62 | ||||
-rw-r--r-- | sysdep/unix/main.c | 2 | ||||
-rw-r--r-- | sysdep/unix/timer.h | 18 |
11 files changed, 225 insertions, 595 deletions
diff --git a/sysdep/unix/Modules b/sysdep/unix/Modules index 2666f9d6..2c6514df 100644 --- a/sysdep/unix/Modules +++ b/sysdep/unix/Modules @@ -10,13 +10,3 @@ random.c krt.c krt.h krt.Y - -#ifdef CONFIG_UNIX_IFACE -krt-iface.c -krt-iface.h -#endif - -#ifdef CONFIG_UNIX_SET -krt-set.c -krt-set.h -#endif diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 2dced67a..475d660c 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -950,7 +950,7 @@ int sk_join_group(sock *s, ip_addr maddr) { struct ipv6_mreq mreq; - + set_inaddr(&mreq.ipv6mr_multiaddr, maddr); #ifdef CONFIG_IPV6_GLIBC_20 diff --git a/sysdep/unix/krt-iface.c b/sysdep/unix/krt-iface.c deleted file mode 100644 index 69048ae8..00000000 --- a/sysdep/unix/krt-iface.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * BIRD -- Unix Interface Scanning and Syncing - * - * (c) 1998--2000 Martin Mares <mj@ucw.cz> - * (c) 2004 Ondrej Filip <feela@network.cz> - * - * Can be freely distributed and used under the terms of the GNU GPL. - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <net/if.h> -#include <sys/ioctl.h> -#include <errno.h> - -#undef LOCAL_DEBUG - -#include "nest/bird.h" -#include "nest/iface.h" -#include "nest/route.h" -#include "nest/protocol.h" -#include "lib/timer.h" -#include "lib/krt.h" -#include "lib/string.h" - -#include "unix.h" - -int if_scan_sock = -1; - -static void -scan_ifs(struct ifreq *r, int cnt) -{ - struct iface i, *pi; - struct ifa a; - char *err, *colon; - unsigned fl; - ip_addr netmask; - int l, scope; - sockaddr *sa; - - if_start_update(); - for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++) - { - int sec = 0; - bzero(&i, sizeof(i)); - bzero(&a, sizeof(a)); - if (colon = strchr(r->ifr_name, ':')) - { - /* It's an alias -- let's interpret it as a secondary interface address */ - sec = 1; - *colon = 0; - } - strncpy(i.name, r->ifr_name, sizeof(i.name) - 1); - - if(ioctl(if_scan_sock, SIOCGIFADDR,r)<0) continue; - - get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.ip, NULL, 1); - if (ipa_nonzero(a.ip)) - { - l = ipa_classify(a.ip); - if (l < 0 || !(l & IADDR_HOST)) - { - log(L_ERR "%s: Invalid interface address", i.name); - a.ip = IPA_NONE; - } - else - { - a.scope = l & IADDR_SCOPE_MASK; - if (a.scope == SCOPE_HOST) - i.flags |= IF_LOOPBACK | IF_IGNORE; - } - } - - if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0) - { - err = "SIOCGIFFLAGS"; - faulty: - log(L_ERR "%s(%s): %m", err, i.name); - bad: - i.flags = (i.flags & ~IF_ADMIN_UP) | IF_SHUTDOWN; - continue; - } - fl = r->ifr_flags; - if (fl & IFF_UP) - i.flags |= IF_ADMIN_UP; - - if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0) - { err = "SIOCGIFNETMASK"; goto faulty; } - get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &netmask, NULL, 0); - l = ipa_mklen(netmask); - if (l < 0) - { - log(L_ERR "%s: Invalid netmask (%x)", i.name, netmask); - goto bad; - } - a.pxlen = l; - - if (fl & IFF_POINTOPOINT) - { - a.flags |= IA_PEER; - if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0) - { err = "SIOCGIFDSTADDR"; goto faulty; } - get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL, 1); - a.prefix = a.opposite; - a.pxlen = BITS_PER_IP_ADDRESS; - } - else - a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen)); - if (fl & IFF_LOOPBACK) - i.flags |= IF_LOOPBACK | IF_IGNORE; - if (1 -#ifndef CONFIG_ALL_MULTICAST - && (fl & IFF_MULTICAST) -#endif -#ifndef CONFIG_UNNUM_MULTICAST - && !(a.flags & IA_PEER) -#endif - ) - i.flags |= IF_MULTICAST; - - scope = ipa_classify(a.ip); - if (scope < 0) - { - log(L_ERR "%s: Invalid address", i.name); - goto bad; - } - a.scope = scope & IADDR_SCOPE_MASK; - - if (a.pxlen < 32) - { - a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen))); - if (ipa_equal(a.ip, a.prefix) || ipa_equal(a.ip, a.brd)) - { - log(L_ERR "%s: Using network or broadcast address for interface", i.name); - goto bad; - } - if (fl & IFF_BROADCAST) - i.flags |= IF_BROADCAST; - if (a.pxlen < 30) - i.flags |= IF_MULTIACCESS; - if (a.pxlen == 30) - ifa.opposite = ipa_opposite_m2(ifa.ip); - if (a.pxlen == 31) - ifa.opposite = ipa_opposite_m1(ifa.ip); - } - else - a.brd = a.opposite; - a.scope = SCOPE_UNIVERSE; - - if (ioctl(if_scan_sock, SIOCGIFMTU, r) < 0) - { err = "SIOCGIFMTU"; goto faulty; } - i.mtu = r->ifr_mtu; - -#ifdef SIOCGIFINDEX - if (ioctl(if_scan_sock, SIOCGIFINDEX, r) >= 0) - i.index = r->ifr_ifindex; - else if (errno != EINVAL) - DBG("SIOCGIFINDEX failed: %m\n"); - else /* defined, but not supported by the kernel */ -#endif - /* - * The kernel doesn't give us real ifindices, but we still need them - * at least for OSPF unnumbered links. So let's make them up ourselves. - */ - if (pi = if_find_by_name(i.name)) - i.index = pi->index; - else - { - static int if_index_counter = 1; - i.index = if_index_counter++; - } - - pi = NULL; - if (sec) - { - a.flags |= IA_SECONDARY; - pi = if_find_by_index(i.index); - } - if (!pi) - pi = if_update(&i); - a.iface = pi; - ifa_update(&a); - } - if_end_update(); -} - -void -krt_if_scan(struct kif_proto *p) -{ - struct ifconf ic; - static int last_ifbuf_size = 4*sizeof(struct ifreq); - int res; - - for(;;) - { - ic.ifc_buf = alloca(last_ifbuf_size); - ic.ifc_len = last_ifbuf_size; - res = ioctl(if_scan_sock, SIOCGIFCONF, &ic); - if (res < 0 && errno != EFAULT) - die("SIOCCGIFCONF: %m"); - if (res >= 0 && ic.ifc_len <= last_ifbuf_size) - break; - last_ifbuf_size *= 2; - DBG("Increased ifconf buffer size to %d\n", last_ifbuf_size); - } - scan_ifs(ic.ifc_req, ic.ifc_len); -} - -void -krt_if_construct(struct kif_config *c) -{ -} - -void -krt_if_start(struct kif_proto *p) -{ -} - -void -krt_if_shutdown(struct kif_proto *p) -{ -} - -void -krt_if_io_init(void) -{ - if_scan_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); - DBG("Using socket %d for interface and route scanning\n", if_scan_sock); - if (if_scan_sock < 0) - die("Cannot create scanning socket: %m"); -} - diff --git a/sysdep/unix/krt-iface.h b/sysdep/unix/krt-iface.h deleted file mode 100644 index 9e12bcc3..00000000 --- a/sysdep/unix/krt-iface.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * BIRD -- Unix Kernel Interface Syncer - * - * (c) 1998--2000 Martin Mares <mj@ucw.cz> - * - * Can be freely distributed and used under the terms of the GNU GPL. - */ - -#ifndef _BIRD_KRT_IFACE_H_ -#define _BIRD_KRT_IFACE_H_ - -struct krt_if_params { -}; - -struct krt_if_status { -}; - -extern int if_scan_sock; - -static inline int kif_params_same(struct krt_if_params *old UNUSED, struct krt_if_params *new UNUSED) { return 1; } -static inline void kif_copy_params(struct krt_if_params *dest UNUSED, struct krt_if_params *src UNUSED) { } - -#endif diff --git a/sysdep/unix/krt-set.c b/sysdep/unix/krt-set.c deleted file mode 100644 index 23cbe5c5..00000000 --- a/sysdep/unix/krt-set.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * BIRD -- Unix Routing Table Syncing - * - * (c) 1998--2000 Martin Mares <mj@ucw.cz> - * - * Can be freely distributed and used under the terms of the GNU GPL. - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <sys/ioctl.h> -#include <net/route.h> - -#undef LOCAL_DEBUG - -#include "nest/bird.h" -#include "nest/iface.h" -#include "nest/route.h" -#include "nest/protocol.h" -#include "lib/unix.h" -#include "lib/krt.h" -#include "lib/string.h" - -int -krt_capable(rte *e) -{ - rta *a = e->attrs; - -#ifdef CONFIG_AUTO_ROUTES - if (a->source == RTS_DEVICE) - return 0; -#endif - return - a->cast == RTC_UNICAST && - (a->dest == RTD_ROUTER - || a->dest == RTD_DEVICE -#ifdef RTF_REJECT - || a->dest == RTD_UNREACHABLE -#endif - ); -} - -static void -krt_ioctl(int ioc, rte *e, char *name) -{ - net *net = e->net; - struct rtentry re; - rta *a = e->attrs; - - bzero(&re, sizeof(re)); - fill_in_sockaddr((struct sockaddr_in *) &re.rt_dst, net->n.prefix, 0); - fill_in_sockaddr((struct sockaddr_in *) &re.rt_genmask, ipa_mkmask(net->n.pxlen), 0); - re.rt_flags = RTF_UP; - if (net->n.pxlen == 32) - re.rt_flags |= RTF_HOST; - switch (a->dest) - { - case RTD_ROUTER: - fill_in_sockaddr((struct sockaddr_in *) &re.rt_gateway, a->gw, 0); - re.rt_flags |= RTF_GATEWAY; - break; - case RTD_DEVICE: - if (!a->iface) - return; - re.rt_dev = a->iface->name; - break; -#ifdef RTF_REJECT - case RTD_UNREACHABLE: - re.rt_flags |= RTF_REJECT; - break; -#endif - default: - bug("krt set: unknown flags, but not filtered"); - } - - if (ioctl(if_scan_sock, ioc, &re) < 0) - log(L_ERR "%s(%I/%d): %m", name, net->n.prefix, net->n.pxlen); -} - -void -krt_set_notify(struct krt_proto *p, net *net, rte *new, rte *old) -{ - if (old) - { - DBG("krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen); - krt_ioctl(SIOCDELRT, old, "SIOCDELRT"); - } - if (new) - { - DBG("krt_add_route(%I/%d)\n", net->n.prefix, net->n.pxlen); - krt_ioctl(SIOCADDRT, new, "SIOCADDRT"); - } -} - -void -krt_set_start(struct krt_proto *x, int first) -{ - if (if_scan_sock < 0) - bug("krt set: missing socket"); -} - -void -krt_set_construct(struct krt_config *c) -{ -} - -void -krt_set_shutdown(struct krt_proto *x, int last) -{ -} diff --git a/sysdep/unix/krt-set.h b/sysdep/unix/krt-set.h deleted file mode 100644 index 87cffcfc..00000000 --- a/sysdep/unix/krt-set.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * BIRD -- Unix Kernel Route Syncer -- Setting - * - * (c) 1998--2000 Martin Mares <mj@ucw.cz> - * - * Can be freely distributed and used under the terms of the GNU GPL. - */ - -#ifndef _BIRD_KRT_SET_H_ -#define _BIRD_KRT_SET_H_ - -struct krt_set_params { -}; - -struct krt_set_status { -}; - -static inline int krt_set_params_same(struct krt_set_params *o UNUSED, struct krt_set_params *n UNUSED) { return 1; } -static inline void krt_set_copy_params(struct krt_set_params *d UNUSED, struct krt_set_params *s UNUSED) { } - -#endif diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y index c0141f57..469c136d 100644 --- a/sysdep/unix/krt.Y +++ b/sysdep/unix/krt.Y @@ -25,17 +25,7 @@ CF_GRAMMAR CF_ADDTO(proto, kern_proto '}') -kern_proto_start: proto_start KERNEL { -#ifndef CONFIG_MULTIPLE_TABLES - if (cf_krt) - cf_error("Kernel protocol already defined"); -#endif - cf_krt = this_proto = proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), $1); - THIS_KRT->scan_time = 60; - THIS_KRT->learn = THIS_KRT->persist = 0; - krt_scan_construct(THIS_KRT); - krt_set_construct(THIS_KRT); - } +kern_proto_start: proto_start KERNEL { this_proto = krt_init_config($1); } ; CF_ADDTO(kern_proto, kern_proto_start proto_name '{') @@ -62,14 +52,7 @@ kern_item: CF_ADDTO(proto, kif_proto '}') -kif_proto_start: proto_start DEVICE { - if (cf_kif) - cf_error("Kernel device protocol already defined"); - cf_kif = this_proto = proto_config_new(&proto_unix_iface, sizeof(struct kif_config), $1); - THIS_KIF->scan_time = 60; - init_list(&THIS_KIF->primary); - krt_if_construct(THIS_KIF); - } +kif_proto_start: proto_start DEVICE { this_proto = kif_init_config($1); } ; CF_ADDTO(kif_proto, kif_proto_start proto_name '{') diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index de97a092..2bd1bc44 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -23,7 +23,7 @@ * Either with a single routing table and single KRT protocol [traditional UNIX] * or with many routing tables and separate KRT protocols for all of them * or with many routing tables, but every scan including all tables, so we start - * separate KRT protocols which cooperate with each other [Linux 2.2]. + * separate KRT protocols which cooperate with each other [Linux]. * In this case, we keep only a single scan timer. * * We use FIB node flags in the routing table to keep track of route @@ -34,6 +34,15 @@ * When starting up, we cheat by looking if there is another * KRT instance to be initialized later and performing table scan * only once for all the instances. + * + * The code uses OS-dependent parts for kernel updates and scans. These parts are + * in more specific sysdep directories (e.g. sysdep/linux) in functions krt_sys_* + * and kif_sys_* (and some others like krt_replace_rte()) and krt-sys.h header file. + * This is also used for platform specific protocol options and route attributes. + * + * There was also an old code that used traditional UNIX ioctls for these tasks. + * It was unmaintained and later removed. For reference, see sysdep/krt-* files + * in commit 396dfa9042305f62da1f56589c4b98fac57fc2f6 */ /* @@ -66,33 +75,25 @@ krt_io_init(void) { krt_pool = rp_new(&root_pool, "Kernel Syncer"); krt_filter_lp = lp_new(krt_pool, 4080); - krt_if_io_init(); } /* * Interfaces */ -struct proto_config *cf_kif; - +static struct kif_config *kif_cf; static struct kif_proto *kif_proto; static timer *kif_scan_timer; static bird_clock_t kif_last_shot; static void -kif_preconfig(struct protocol *P UNUSED, struct config *c UNUSED) -{ - cf_kif = NULL; -} - -static void kif_scan(timer *t) { struct kif_proto *p = t->data; KRT_TRACE(p, D_EVENTS, "Scanning interfaces"); kif_last_shot = now; - krt_if_scan(p); + kif_do_scan(p); } static void @@ -112,45 +113,6 @@ kif_request_scan(void) tm_start(kif_scan_timer, 1); } -static struct proto * -kif_init(struct proto_config *c) -{ - struct kif_proto *p = proto_new(c, sizeof(struct kif_proto)); - return &p->p; -} - -static int -kif_start(struct proto *P) -{ - struct kif_proto *p = (struct kif_proto *) P; - - kif_proto = p; - krt_if_start(p); - - /* Start periodic interface scanning */ - kif_scan_timer = tm_new(P->pool); - kif_scan_timer->hook = kif_scan; - kif_scan_timer->data = p; - kif_scan_timer->recurrent = KIF_CF->scan_time; - kif_scan(kif_scan_timer); - tm_start(kif_scan_timer, KIF_CF->scan_time); - - return PS_UP; -} - -static int -kif_shutdown(struct proto *P) -{ - struct kif_proto *p = (struct kif_proto *) P; - - tm_stop(kif_scan_timer); - krt_if_shutdown(p); - kif_proto = NULL; - - return PS_DOWN; -} - - static inline int prefer_scope(struct ifa *a, struct ifa *b) { return (a->scope > SCOPE_LINK) && (b->scope <= SCOPE_LINK); } @@ -193,13 +155,53 @@ kif_choose_primary(struct iface *i) } +static struct proto * +kif_init(struct proto_config *c) +{ + struct kif_proto *p = proto_new(c, sizeof(struct kif_proto)); + + kif_sys_init(p); + return &p->p; +} + +static int +kif_start(struct proto *P) +{ + struct kif_proto *p = (struct kif_proto *) P; + + kif_proto = p; + kif_sys_start(p); + + /* Start periodic interface scanning */ + kif_scan_timer = tm_new(P->pool); + kif_scan_timer->hook = kif_scan; + kif_scan_timer->data = p; + kif_scan_timer->recurrent = KIF_CF->scan_time; + kif_scan(kif_scan_timer); + tm_start(kif_scan_timer, KIF_CF->scan_time); + + return PS_UP; +} + +static int +kif_shutdown(struct proto *P) +{ + struct kif_proto *p = (struct kif_proto *) P; + + tm_stop(kif_scan_timer); + kif_sys_shutdown(p); + kif_proto = NULL; + + return PS_DOWN; +} + static int kif_reconfigure(struct proto *p, struct proto_config *new) { struct kif_config *o = (struct kif_config *) p->cf; struct kif_config *n = (struct kif_config *) new; - if (!kif_params_same(&o->iface, &n->iface)) + if (!kif_sys_reconfigure((struct kif_proto *) p, n, o)) return 0; if (o->scan_time != n->scan_time) @@ -224,6 +226,28 @@ kif_reconfigure(struct proto *p, struct proto_config *new) return 1; } + +static void +kif_preconfig(struct protocol *P UNUSED, struct config *c) +{ + kif_cf = NULL; + kif_sys_preconfig(c); +} + +struct proto_config * +kif_init_config(int class) +{ + if (kif_cf) + cf_error("Kernel device protocol already defined"); + + kif_cf = (struct kif_config *) proto_config_new(&proto_unix_iface, sizeof(struct kif_config), class); + kif_cf->scan_time = 60; + init_list(&kif_cf->primary); + + kif_sys_init_config(kif_cf); + return (struct proto_config *) kif_cf; +} + static void kif_copy_config(struct proto_config *dest, struct proto_config *src) { @@ -231,13 +255,13 @@ kif_copy_config(struct proto_config *dest, struct proto_config *src) struct kif_config *s = (struct kif_config *) src; /* Shallow copy of everything (just scan_time currently) */ - proto_copy_rest(dest, src, sizeof(struct krt_config)); + proto_copy_rest(dest, src, sizeof(struct kif_config)); /* Copy primary addr list */ cfg_copy_list(&d->primary, &s->primary, sizeof(struct kif_primary_item)); /* Fix sysdep parts */ - kif_copy_params(&d->iface, &s->iface); + kif_sys_copy_config(d, s); } @@ -551,16 +575,11 @@ krt_flush_routes(struct krt_proto *p) { net *n = (net *) f; rte *e = n->routes; - if (e) + if (e && (n->n.flags & KRF_INSTALLED)) { - rta *a = e->attrs; - if ((n->n.flags & KRF_INSTALLED) && - a->source != RTS_DEVICE && a->source != RTS_INHERIT) - { - /* FIXME: this does not work if gw is changed in export filter */ - krt_set_notify(p, e->net, NULL, e, NULL); - n->n.flags &= ~KRF_INSTALLED; - } + /* FIXME: this does not work if gw is changed in export filter */ + krt_replace_rte(p, e->net, NULL, e, NULL); + n->n.flags &= ~KRF_INSTALLED; } } FIB_WALK_END; @@ -717,7 +736,7 @@ krt_prune(struct krt_proto *p) if (new && (f->flags & KRF_INSTALLED)) { krt_trace_in(p, new, "reinstalling"); - krt_set_notify(p, n, new, NULL, tmpa); + krt_replace_rte(p, n, new, NULL, tmpa); } break; case KRF_SEEN: @@ -726,11 +745,11 @@ krt_prune(struct krt_proto *p) break; case KRF_UPDATE: krt_trace_in(p, new, "updating"); - krt_set_notify(p, n, new, old, tmpa); + krt_replace_rte(p, n, new, old, tmpa); break; case KRF_DELETE: krt_trace_in(p, old, "deleting"); - krt_set_notify(p, n, NULL, old, NULL); + krt_replace_rte(p, n, NULL, old, NULL); break; default: bug("krt_prune: invalid route status"); @@ -766,7 +785,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new) if (new) { krt_trace_in(p, e, "[redirect] deleting"); - krt_set_notify(p, net, NULL, e, NULL); + krt_replace_rte(p, net, NULL, e, NULL); } /* If !new, it is probably echo of our deletion */ break; @@ -800,7 +819,7 @@ krt_scan(timer *t UNUSED) p = SKIP_BACK(struct krt_proto, instance_node, HEAD(krt_instance_list)); if (p->instance_node.next) KRT_TRACE(p, D_EVENTS, "Scanning routing table"); - krt_scan_fire(NULL); + krt_do_scan(NULL); WALK_LIST(q, krt_instance_list) { p = SKIP_BACK(struct krt_proto, instance_node, q); @@ -810,14 +829,45 @@ krt_scan(timer *t UNUSED) #else p = t->data; KRT_TRACE(p, D_EVENTS, "Scanning routing table"); - krt_scan_fire(p); + krt_do_scan(p); krt_prune(p); #endif } + /* * Updates */ + +static struct ea_list * +krt_make_tmp_attrs(rte *rt, struct linpool *pool) +{ + struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr)); + + l->next = NULL; + l->flags = EALF_SORTED; + 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(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 int krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool) { @@ -853,37 +903,37 @@ krt_notify(struct proto *P, struct rtable *table UNUSED, net *net, else net->n.flags &= ~KRF_INSTALLED; if (p->initialized) /* Before first scan we don't touch the routes */ - krt_set_notify(p, net, new, old, eattrs); + krt_replace_rte(p, net, new, old, eattrs); } +static int +krt_rte_same(rte *a, rte *b) +{ + /* src is always KRT_SRC_ALIEN and type is irrelevant */ + return (a->u.krt.proto == b->u.krt.proto) && (a->u.krt.metric == b->u.krt.metric); +} + + /* * Protocol glue */ -struct proto_config *cf_krt; - -static void -krt_preconfig(struct protocol *P UNUSED, struct config *c) -{ - cf_krt = NULL; - krt_scan_preconfig(c); -} +struct krt_config *krt_cf; -static void -krt_postconfig(struct proto_config *C) +static struct proto * +krt_init(struct proto_config *c) { - struct krt_config *c = (struct krt_config *) C; + struct krt_proto *p = proto_new(c, sizeof(struct krt_proto)); -#ifdef CONFIG_ALL_TABLES_AT_ONCE - struct krt_config *first = (struct krt_config *) cf_krt; - if (first->scan_time != c->scan_time) - cf_error("All kernel syncers must use the same table scan interval"); -#endif + 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; + p->p.rte_same = krt_rte_same; - if (C->table->krt_attached) - cf_error("Kernel syncer (%s) already attached to table %s", C->table->krt_attached->name, C->table->name); - C->table->krt_attached = C; - krt_scan_postconfig(c); + krt_sys_init(p); + return &p->p; } static timer * @@ -920,8 +970,7 @@ krt_start(struct proto *P) krt_learn_init(p); #endif - krt_scan_start(p, first); - krt_set_start(p, first); + krt_sys_start(p, first); /* Start periodic routing table scanning */ #ifdef CONFIG_ALL_TABLES_AT_ONCE @@ -955,8 +1004,7 @@ krt_shutdown(struct proto *P) if (p->initialized && !KRT_CF->persist) krt_flush_routes(p); - krt_set_shutdown(p, last); - krt_scan_shutdown(p, last); + krt_sys_shutdown(p, last); #ifdef CONFIG_ALL_TABLES_AT_ONCE if (last) @@ -966,69 +1014,55 @@ krt_shutdown(struct proto *P) return PS_DOWN; } -static struct ea_list * -krt_make_tmp_attrs(rte *rt, struct linpool *pool) +static int +krt_reconfigure(struct proto *p, struct proto_config *new) { - struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr)); - - l->next = NULL; - l->flags = EALF_SORTED; - 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; + struct krt_config *o = (struct krt_config *) p->cf; + struct krt_config *n = (struct krt_config *) new; - 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; + if (!krt_sys_reconfigure((struct krt_proto *) p, n, o)) + return 0; - return l; + /* persist needn't be the same */ + return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes; } static void -krt_store_tmp_attrs(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 int -krt_rte_same(rte *a, rte *b) +krt_preconfig(struct protocol *P UNUSED, struct config *c) { - /* src is always KRT_SRC_ALIEN and type is irrelevant */ - return (a->u.krt.proto == b->u.krt.proto) && (a->u.krt.metric == b->u.krt.metric); + krt_cf = NULL; + krt_sys_preconfig(c); } -static struct proto * -krt_init(struct proto_config *c) +static void +krt_postconfig(struct proto_config *C) { - 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.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; - p->p.rte_same = krt_rte_same; +#ifdef CONFIG_ALL_TABLES_AT_ONCE + if (krt_cf->scan_time != c->scan_time) + cf_error("All kernel syncers must use the same table scan interval"); +#endif - return &p->p; + if (C->table->krt_attached) + cf_error("Kernel syncer (%s) already attached to table %s", C->table->krt_attached->name, C->table->name); + C->table->krt_attached = C; + krt_sys_postconfig(c); } -static int -krt_reconfigure(struct proto *p, struct proto_config *new) +struct proto_config * +krt_init_config(int class) { - struct krt_config *o = (struct krt_config *) p->cf; - struct krt_config *n = (struct krt_config *) new; +#ifndef CONFIG_MULTIPLE_TABLES + if (krt_cf) + cf_error("Kernel protocol already defined"); +#endif + + krt_cf = (struct krt_config *) proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), class); + krt_cf->scan_time = 60; - return o->scan_time == n->scan_time - && o->learn == n->learn /* persist needn't be the same */ - && o->devroutes == n->devroutes - && krt_set_params_same(&o->set, &n->set) - && krt_scan_params_same(&o->scan, &n->scan) - ; + krt_sys_init_config(krt_cf); + return (struct proto_config *) krt_cf; } static void @@ -1041,8 +1075,7 @@ krt_copy_config(struct proto_config *dest, struct proto_config *src) proto_copy_rest(dest, src, sizeof(struct krt_config)); /* Fix sysdep parts */ - krt_set_copy_params(&d->set, &s->set); - krt_scan_copy_params(&d->scan, &s->scan); + krt_sys_copy_config(d, s); } static int diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 19b69e49..d6fbf721 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -15,9 +15,7 @@ struct krt_proto; struct kif_config; struct kif_proto; -#include "lib/krt-scan.h" -#include "lib/krt-set.h" -#include "lib/krt-iface.h" +#include "lib/krt-sys.h" /* Flags stored in net->n.flags, rest are in nest/route.h */ @@ -45,8 +43,7 @@ extern struct protocol proto_unix_kernel; struct krt_config { struct proto_config c; - struct krt_set_params set; - struct krt_scan_params scan; + struct krt_params sys; /* Sysdep params */ int persist; /* Keep routes when we exit */ int scan_time; /* How often we re-scan routes */ int learn; /* Learn routes from other sources */ @@ -55,9 +52,7 @@ struct krt_config { struct krt_proto { struct proto p; - struct krt_set_status set; - struct krt_scan_status scan; - struct krt_if_status iface; + struct krt_status sys; /* Sysdep state */ #ifdef KRT_ALLOW_LEARN struct rtable krt_table; /* Internal table of inherited routes */ #endif @@ -69,7 +64,6 @@ struct krt_proto { int initialized; /* First scan has already been finished */ }; -extern struct proto_config *cf_krt; extern pool *krt_pool; #define KRT_CF ((struct krt_config *)p->p.cf) @@ -79,6 +73,7 @@ extern pool *krt_pool; if (pr->p.debug & fl) \ { log(L_TRACE "%s: " msg, pr->p.name , ## args); } } while(0) +struct proto_config * kif_init_config(int class); void kif_request_scan(void); void krt_got_route(struct krt_proto *p, struct rte *e); void krt_got_route_async(struct krt_proto *p, struct rte *e, int new); @@ -101,46 +96,49 @@ struct kif_primary_item { struct kif_config { struct proto_config c; - struct krt_if_params iface; + struct kif_params sys; /* Sysdep params */ int scan_time; /* How often we re-scan interfaces */ list primary; /* Preferences for primary addresses (struct kif_primary_item) */ }; struct kif_proto { struct proto p; - struct krt_if_status iface; + struct kif_status sys; /* Sysdep state */ }; -extern struct proto_config *cf_kif; - #define KIF_CF ((struct kif_config *)p->p.cf) -/* krt-scan.c */ +struct proto_config * krt_init_config(int class); + + +/* krt sysdep */ + +void krt_sys_init(struct krt_proto *); +void krt_sys_start(struct krt_proto *, int); +void krt_sys_shutdown(struct krt_proto *, int); +int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o); -void krt_scan_preconfig(struct config *); -void krt_scan_postconfig(struct krt_config *); -void krt_scan_construct(struct krt_config *); -void krt_scan_start(struct krt_proto *, int); -void krt_scan_shutdown(struct krt_proto *, int); +void krt_sys_preconfig(struct config *); +void krt_sys_postconfig(struct krt_config *); +void krt_sys_init_config(struct krt_config *); +void krt_sys_copy_config(struct krt_config *, struct krt_config *); -void krt_scan_fire(struct krt_proto *); +int krt_capable(rte *e); +void krt_do_scan(struct krt_proto *); +void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs); -/* krt-set.c */ -void krt_set_construct(struct krt_config *); -void krt_set_start(struct krt_proto *, int); -void krt_set_shutdown(struct krt_proto *, int); +/* kif sysdep */ -int krt_capable(rte *e); -void krt_set_notify(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs); +void kif_sys_init(struct kif_proto *); +void kif_sys_start(struct kif_proto *); +void kif_sys_shutdown(struct kif_proto *); +int kif_sys_reconfigure(struct kif_proto *, struct kif_config *, struct kif_config *); -/* krt-iface.c */ +void kif_sys_init_config(struct kif_config *); +void kif_sys_copy_config(struct kif_config *, struct kif_config *); -void krt_if_construct(struct kif_config *); -void krt_if_start(struct kif_proto *); -void krt_if_shutdown(struct kif_proto *); +void kif_do_scan(struct kif_proto *); -void krt_if_scan(struct kif_proto *); -void krt_if_io_init(void); #endif diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index dfe0b89c..e0563aae 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -151,7 +151,7 @@ read_iproute_table(char *file, char *prefix, int max) #endif // PATH_IPROUTE_DIR -static char *config_name = PATH_CONFIG; +static char *config_name = PATH_CONFIG_FILE; static int cf_read(byte *dest, unsigned int len, int fd) diff --git a/sysdep/unix/timer.h b/sysdep/unix/timer.h index a20df483..a788ae27 100644 --- a/sysdep/unix/timer.h +++ b/sysdep/unix/timer.h @@ -30,6 +30,22 @@ void tm_start(timer *, unsigned after); void tm_stop(timer *); void tm_dump_all(void); +extern bird_clock_t now; /* Relative, monotonic time in seconds */ +extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */ + +static inline bird_clock_t +tm_remains(timer *t) +{ + return t->expires ? t->expires - now : 0; +} + +static inline void +tm_start_max(timer *t, unsigned after) +{ + bird_clock_t rem = tm_remains(t); + tm_start(t, (rem > after) ? rem : after); +} + static inline timer * tm_new_set(pool *p, void (*hook)(struct timer *), void *data, unsigned rand, unsigned rec) { @@ -41,8 +57,6 @@ tm_new_set(pool *p, void (*hook)(struct timer *), void *data, unsigned rand, uns return t; } -extern bird_clock_t now; /* Relative, monotonic time in seconds */ -extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */ struct timeformat { char *fmt1, *fmt2; |