diff options
Diffstat (limited to 'proto/bfd')
-rw-r--r-- | proto/bfd/Makefile | 9 | ||||
-rw-r--r-- | proto/bfd/bfd.c | 67 | ||||
-rw-r--r-- | proto/bfd/bfd.h | 14 | ||||
-rw-r--r-- | proto/bfd/io.c | 283 | ||||
-rw-r--r-- | proto/bfd/io.h | 67 | ||||
-rw-r--r-- | proto/bfd/packets.c | 13 |
6 files changed, 75 insertions, 378 deletions
diff --git a/proto/bfd/Makefile b/proto/bfd/Makefile index c28cedec..402122fc 100644 --- a/proto/bfd/Makefile +++ b/proto/bfd/Makefile @@ -1,5 +1,6 @@ -source=bfd.c packets.c io.c -root-rel=../../ -dir-name=proto/bfd +src := bfd.c io.c packets.c +obj := $(src-o-files) +$(all-daemon) +$(cf-local) -include ../../Rules +tests_objs := $(tests_objs) $(src-o-files)
\ No newline at end of file diff --git a/proto/bfd/bfd.c b/proto/bfd/bfd.c index 79135fae..67ec2270 100644 --- a/proto/bfd/bfd.c +++ b/proto/bfd/bfd.c @@ -64,16 +64,15 @@ * ready, the protocol just creates a BFD request like any other protocol. * * The protocol uses a new generic event loop (structure &birdloop) from |io.c|, - * which supports sockets, timers and events like the main loop. Timers - * (structure &timer2) are new microsecond based timers, while sockets and - * events are the same. A birdloop is associated with a thread (field @thread) - * in which event hooks are executed. Most functions for setting event sources - * (like sk_start() or tm2_start()) must be called from the context of that - * thread. Birdloop allows to temporarily acquire the context of that thread for - * the main thread by calling birdloop_enter() and then birdloop_leave(), which - * also ensures mutual exclusion with all event hooks. Note that resources - * associated with a birdloop (like timers) should be attached to the - * independent resource pool, detached from the main resource tree. + * which supports sockets, timers and events like the main loop. A birdloop is + * associated with a thread (field @thread) in which event hooks are executed. + * Most functions for setting event sources (like sk_start() or tm_start()) must + * be called from the context of that thread. Birdloop allows to temporarily + * acquire the context of that thread for the main thread by calling + * birdloop_enter() and then birdloop_leave(), which also ensures mutual + * exclusion with all event hooks. Note that resources associated with a + * birdloop (like timers) should be attached to the independent resource pool, + * detached from the main resource tree. * * There are two kinds of interaction between the BFD core (running in the BFD * thread) and the rest of BFD (running in the main thread). The first kind are @@ -112,7 +111,7 @@ #define HASH_IP_KEY(n) n->addr #define HASH_IP_NEXT(n) n->next_ip #define HASH_IP_EQ(a,b) ipa_equal(a,b) -#define HASH_IP_FN(k) ipa_hash32(k) +#define HASH_IP_FN(k) ipa_hash(k) static list bfd_proto_list; static list bfd_wait_list; @@ -145,6 +144,7 @@ bfd_session_update_state(struct bfd_session *s, uint state, uint diag) bfd_lock_sessions(p); s->loc_state = state; s->loc_diag = diag; + s->last_state_change = current_time(); notify = !NODE_VALID(&s->n); if (notify) @@ -176,7 +176,7 @@ bfd_session_update_tx_interval(struct bfd_session *s) return; /* Set timer relative to last tx_timer event */ - tm2_set(s->tx_timer, s->last_tx + tx_int_l); + tm_set(s->tx_timer, s->last_tx + tx_int_l); } static void @@ -190,7 +190,7 @@ bfd_session_update_detection_time(struct bfd_session *s, int kick) if (!s->last_rx) return; - tm2_set(s->hold_timer, s->last_rx + timeout); + tm_set(s->hold_timer, s->last_rx + timeout); } static void @@ -211,16 +211,16 @@ bfd_session_control_tx_timer(struct bfd_session *s, int reset) goto stop; /* So TX timer should run */ - if (reset || !tm2_active(s->tx_timer)) + if (reset || !tm_active(s->tx_timer)) { s->last_tx = 0; - tm2_start(s->tx_timer, 0); + tm_start(s->tx_timer, 0); } return; stop: - tm2_stop(s->tx_timer); + tm_stop(s->tx_timer); s->last_tx = 0; } @@ -379,7 +379,7 @@ bfd_find_session_by_addr(struct bfd_proto *p, ip_addr addr) } static void -bfd_tx_timer_hook(timer2 *t) +bfd_tx_timer_hook(timer *t) { struct bfd_session *s = t->data; @@ -388,7 +388,7 @@ bfd_tx_timer_hook(timer2 *t) } static void -bfd_hold_timer_hook(timer2 *t) +bfd_hold_timer_hook(timer *t) { bfd_session_timeout(t->data); } @@ -432,13 +432,13 @@ bfd_add_session(struct bfd_proto *p, ip_addr addr, ip_addr local, struct iface * s->passive = ifa->cf->passive; s->tx_csn = random_u32(); - s->tx_timer = tm2_new_init(p->tpool, bfd_tx_timer_hook, s, 0, 0); - s->hold_timer = tm2_new_init(p->tpool, bfd_hold_timer_hook, s, 0, 0); + s->tx_timer = tm_new_init(p->tpool, bfd_tx_timer_hook, s, 0, 0); + s->hold_timer = tm_new_init(p->tpool, bfd_hold_timer_hook, s, 0, 0); bfd_session_update_tx_interval(s); bfd_session_control_tx_timer(s, 1); init_list(&s->request_list); - s->last_state_change = now; + s->last_state_change = current_time(); TRACE(D_EVENTS, "Session to %I added", s->addr); @@ -879,9 +879,6 @@ bfd_notify_hook(sock *sk, uint len UNUSED) diag = s->loc_diag; bfd_unlock_sessions(p); - /* FIXME: convert to btime and move to bfd_session_update_state() */ - s->last_state_change = now; - s->notify_running = 1; WALK_LIST_DELSAFE(n, nn, s->request_list) bfd_request_notify(SKIP_BACK(struct bfd_request, n, n), state, diag); @@ -954,7 +951,7 @@ bfd_init_all(void) static struct proto * bfd_init(struct proto_config *c) { - struct proto *p = proto_new(c, sizeof(struct bfd_proto)); + struct proto *p = proto_new(c); p->neigh_notify = bfd_neigh_notify; @@ -983,8 +980,10 @@ bfd_start(struct proto *P) add_tail(&bfd_proto_list, &p->bfd_node); birdloop_enter(p->loop); - p->rx_1 = bfd_open_rx_sk(p, 0); - p->rx_m = bfd_open_rx_sk(p, 1); + p->rx4_1 = bfd_open_rx_sk(p, 0, SK_IPV4); + p->rx4_m = bfd_open_rx_sk(p, 1, SK_IPV4); + p->rx6_1 = bfd_open_rx_sk(p, 0, SK_IPV6); + p->rx6_m = bfd_open_rx_sk(p, 1, SK_IPV6); birdloop_leave(p->loop); bfd_take_requests(p); @@ -1078,7 +1077,7 @@ bfd_show_sessions(struct proto *P) byte tbuf[TM_DATETIME_BUFFER_SIZE]; struct bfd_proto *p = (struct bfd_proto *) P; uint state, diag UNUSED; - u32 tx_int, timeout; + btime tx_int, timeout; const char *ifname; if (p->p.proto_state != PS_UP) @@ -1099,15 +1098,14 @@ bfd_show_sessions(struct proto *P) state = s->loc_state; diag = s->loc_diag; ifname = (s->ifa && s->ifa->iface) ? s->ifa->iface->name : "---"; - tx_int = s->last_tx ? (MAX(s->des_min_tx_int, s->rem_min_rx_int) TO_MS) : 0; - timeout = (MAX(s->req_min_rx_int, s->rem_min_tx_int) TO_MS) * s->rem_detect_mult; + tx_int = s->last_tx ? MAX(s->des_min_tx_int, s->rem_min_rx_int) : 0; + timeout = (btime) MAX(s->req_min_rx_int, s->rem_min_tx_int) * s->rem_detect_mult; state = (state < 4) ? state : 0; - tm_format_datetime(tbuf, &config->tf_proto, s->last_state_change); + tm_format_time(tbuf, &config->tf_proto, s->last_state_change); - cli_msg(-1020, "%-25I %-10s %-10s %-10s %3u.%03u %3u.%03u", - s->addr, ifname, bfd_state_names[state], tbuf, - tx_int / 1000, tx_int % 1000, timeout / 1000, timeout % 1000); + cli_msg(-1020, "%-25I %-10s %-10s %-10s %7t %7t", + s->addr, ifname, bfd_state_names[state], tbuf, tx_int, timeout); } HASH_WALK_END; @@ -1118,6 +1116,7 @@ bfd_show_sessions(struct proto *P) struct protocol proto_bfd = { .name = "BFD", .template = "bfd%d", + .proto_size = sizeof(struct bfd_proto), .config_size = sizeof(struct bfd_config), .init = bfd_init, .start = bfd_start, diff --git a/proto/bfd/bfd.h b/proto/bfd/bfd.h index 46e09879..bc4fe969 100644 --- a/proto/bfd/bfd.h +++ b/proto/bfd/bfd.h @@ -87,8 +87,10 @@ struct bfd_proto sock *notify_ws; list notify_list; - sock *rx_1; - sock *rx_m; + sock *rx4_1; + sock *rx6_1; + sock *rx4_m; + sock *rx6_m; list iface_list; }; @@ -138,11 +140,11 @@ struct bfd_session btime last_tx; /* Time of last sent periodic control packet */ btime last_rx; /* Time of last received valid control packet */ - timer2 *tx_timer; /* Periodic control packet timer */ - timer2 *hold_timer; /* Timer for session down detection time */ + timer *tx_timer; /* Periodic control packet timer */ + timer *hold_timer; /* Timer for session down detection time */ list request_list; /* List of client requests (struct bfd_request) */ - bird_clock_t last_state_change; /* Time of last state change */ + btime last_state_change; /* Time of last state change */ u8 notify_running; /* 1 if notify hooks are running */ u8 rx_csn_known; /* Received crypto sequence number is known */ @@ -201,7 +203,7 @@ void bfd_show_sessions(struct proto *P); /* packets.c */ void bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final); -sock * bfd_open_rx_sk(struct bfd_proto *p, int multihop); +sock * bfd_open_rx_sk(struct bfd_proto *p, int multihop, int inet_version); sock * bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa); diff --git a/proto/bfd/io.c b/proto/bfd/io.c index 8f4f5007..1cd9365a 100644 --- a/proto/bfd/io.c +++ b/proto/bfd/io.c @@ -18,10 +18,10 @@ #include "proto/bfd/io.h" #include "lib/buffer.h" -#include "lib/heap.h" #include "lib/lists.h" #include "lib/resource.h" #include "lib/event.h" +#include "lib/timer.h" #include "lib/socket.h" @@ -31,16 +31,12 @@ struct birdloop pthread_t thread; pthread_mutex_t mutex; - btime last_time; - btime real_time; - u8 use_monotonic_clock; - u8 stop_called; u8 poll_active; u8 wakeup_masked; int wakeup_fds[2]; - BUFFER(timer2 *) timers; + struct timeloop time; list event_list; list sock_list; uint sock_num; @@ -57,6 +53,7 @@ struct birdloop */ static pthread_key_t current_loop_key; +extern pthread_key_t current_time_key; static inline struct birdloop * birdloop_current(void) @@ -68,6 +65,7 @@ static inline void birdloop_set_current(struct birdloop *loop) { pthread_setspecific(current_loop_key, loop); + pthread_setspecific(current_time_key, loop ? &loop->time : &main_timeloop); } static inline void @@ -78,98 +76,6 @@ birdloop_init_current(void) /* - * Time clock - */ - -static void times_update_alt(struct birdloop *loop); - -static void -times_init(struct birdloop *loop) -{ - struct timespec ts; - int rv; - - rv = clock_gettime(CLOCK_MONOTONIC, &ts); - if (rv < 0) - { - log(L_WARN "Monotonic clock is missing"); - - loop->use_monotonic_clock = 0; - loop->last_time = 0; - loop->real_time = 0; - times_update_alt(loop); - return; - } - - if ((ts.tv_sec < 0) || (((s64) ts.tv_sec) > ((s64) 1 << 40))) - log(L_WARN "Monotonic clock is crazy"); - - loop->use_monotonic_clock = 1; - loop->last_time = ((s64) ts.tv_sec S) + (ts.tv_nsec / 1000); - loop->real_time = 0; -} - -static void -times_update_pri(struct birdloop *loop) -{ - struct timespec ts; - int rv; - - rv = clock_gettime(CLOCK_MONOTONIC, &ts); - if (rv < 0) - die("clock_gettime: %m"); - - btime new_time = ((s64) ts.tv_sec S) + (ts.tv_nsec / 1000); - - if (new_time < loop->last_time) - log(L_ERR "Monotonic clock is broken"); - - loop->last_time = new_time; - loop->real_time = 0; -} - -static void -times_update_alt(struct birdloop *loop) -{ - struct timeval tv; - int rv; - - rv = gettimeofday(&tv, NULL); - if (rv < 0) - die("gettimeofday: %m"); - - btime new_time = ((s64) tv.tv_sec S) + tv.tv_usec; - btime delta = new_time - loop->real_time; - - if ((delta < 0) || (delta > (60 S))) - { - if (loop->real_time) - log(L_WARN "Time jump, delta %d us", (int) delta); - - delta = 100 MS; - } - - loop->last_time += delta; - loop->real_time = new_time; -} - -static void -times_update(struct birdloop *loop) -{ - if (loop->use_monotonic_clock) - times_update_pri(loop); - else - times_update_alt(loop); -} - -btime -current_time(void) -{ - return birdloop_current()->last_time; -} - - -/* * Wakeup code for birdloop */ @@ -238,7 +144,7 @@ wakeup_drain(struct birdloop *loop) } static inline void -wakeup_do_kick(struct birdloop *loop) +wakeup_do_kick(struct birdloop *loop) { pipe_kick(loop->wakeup_fds[1]); } @@ -252,6 +158,16 @@ wakeup_kick(struct birdloop *loop) loop->wakeup_masked = 2; } +/* For notifications from outside */ +void +wakeup_kick_current(void) +{ + struct birdloop *loop = birdloop_current(); + + if (loop && loop->poll_active) + wakeup_kick(loop); +} + /* * Events @@ -272,7 +188,7 @@ events_init(struct birdloop *loop) static void events_fire(struct birdloop *loop) { - times_update(loop); + times_update(&loop->time); ev_run_list(&loop->event_list); } @@ -292,154 +208,6 @@ ev2_schedule(event *e) /* - * Timers - */ - -#define TIMER_LESS(a,b) ((a)->expires < (b)->expires) -#define TIMER_SWAP(heap,a,b,t) (t = heap[a], heap[a] = heap[b], heap[b] = t, \ - heap[a]->index = (a), heap[b]->index = (b)) - -static inline uint timers_count(struct birdloop *loop) -{ return loop->timers.used - 1; } - -static inline timer2 *timers_first(struct birdloop *loop) -{ return (loop->timers.used > 1) ? loop->timers.data[1] : NULL; } - - -static void -tm2_free(resource *r) -{ - timer2 *t = (timer2 *) r; - - tm2_stop(t); -} - -static void -tm2_dump(resource *r) -{ - timer2 *t = (timer2 *) r; - - debug("(code %p, data %p, ", t->hook, t->data); - if (t->randomize) - debug("rand %d, ", t->randomize); - if (t->recurrent) - debug("recur %d, ", t->recurrent); - if (t->expires) - debug("expires in %d ms)\n", (t->expires - current_time()) TO_MS); - else - debug("inactive)\n"); -} - - -static struct resclass tm2_class = { - "Timer", - sizeof(timer2), - tm2_free, - tm2_dump, - NULL, - NULL -}; - -timer2 * -tm2_new(pool *p) -{ - timer2 *t = ralloc(p, &tm2_class); - t->index = -1; - return t; -} - -void -tm2_set(timer2 *t, btime when) -{ - struct birdloop *loop = birdloop_current(); - uint tc = timers_count(loop); - - if (!t->expires) - { - t->index = ++tc; - t->expires = when; - BUFFER_PUSH(loop->timers) = t; - HEAP_INSERT(loop->timers.data, tc, timer2 *, TIMER_LESS, TIMER_SWAP); - } - else if (t->expires < when) - { - t->expires = when; - HEAP_INCREASE(loop->timers.data, tc, timer2 *, TIMER_LESS, TIMER_SWAP, t->index); - } - else if (t->expires > when) - { - t->expires = when; - HEAP_DECREASE(loop->timers.data, tc, timer2 *, TIMER_LESS, TIMER_SWAP, t->index); - } - - if (loop->poll_active && (t->index == 1)) - wakeup_kick(loop); -} - -void -tm2_start(timer2 *t, btime after) -{ - tm2_set(t, current_time() + MAX(after, 0)); -} - -void -tm2_stop(timer2 *t) -{ - if (!t->expires) - return; - - struct birdloop *loop = birdloop_current(); - uint tc = timers_count(loop); - - HEAP_DELETE(loop->timers.data, tc, timer2 *, TIMER_LESS, TIMER_SWAP, t->index); - BUFFER_POP(loop->timers); - - t->index = -1; - t->expires = 0; -} - -static void -timers_init(struct birdloop *loop) -{ - BUFFER_INIT(loop->timers, loop->pool, 4); - BUFFER_PUSH(loop->timers) = NULL; -} - -static void -timers_fire(struct birdloop *loop) -{ - btime base_time; - timer2 *t; - - times_update(loop); - base_time = loop->last_time; - - while (t = timers_first(loop)) - { - if (t->expires > base_time) - return; - - if (t->recurrent) - { - btime when = t->expires + t->recurrent; - - if (when <= loop->last_time) - when = loop->last_time + t->recurrent; - - if (t->randomize) - when += random() % (t->randomize + 1); - - tm2_set(t, when); - } - else - tm2_stop(t); - - t->hook(t); - } -} - - -/* * Sockets */ @@ -530,7 +298,7 @@ sockets_prepare(struct birdloop *loop) struct pollfd *pfd = loop->poll_fd.data; sock **psk = loop->poll_sk.data; - int i = 0; + uint i = 0; node *n; WALK_LIST(n, loop->sock_list) @@ -586,7 +354,7 @@ sockets_fire(struct birdloop *loop) sock **psk = loop->poll_sk.data; int poll_num = loop->poll_fd.used - 1; - times_update(loop); + times_update(&loop->time); /* Last fd is internal wakeup fd */ if (pfd[poll_num].revents & POLLIN) @@ -634,11 +402,10 @@ birdloop_new(void) loop->pool = p; pthread_mutex_init(&loop->mutex, NULL); - times_init(loop); wakeup_init(loop); events_init(loop); - timers_init(loop); + timers_init(&loop->time, p); sockets_init(loop); return loop; @@ -710,7 +477,7 @@ static void * birdloop_main(void *arg) { struct birdloop *loop = arg; - timer2 *t; + timer *t; int rv, timeout; birdloop_set_current(loop); @@ -719,13 +486,13 @@ birdloop_main(void *arg) while (1) { events_fire(loop); - timers_fire(loop); + timers_fire(&loop->time); - times_update(loop); + times_update(&loop->time); if (events_waiting(loop)) timeout = 0; - else if (t = timers_first(loop)) - timeout = (tm2_remains(t) TO_MS) + 1; + else if (t = timers_first(&loop->time)) + timeout = (tm_remains(t) TO_MS) + 1; else timeout = -1; @@ -756,7 +523,7 @@ birdloop_main(void *arg) if (rv) sockets_fire(loop); - timers_fire(loop); + timers_fire(&loop->time); } loop->stop_called = 0; diff --git a/proto/bfd/io.h b/proto/bfd/io.h index 641ee054..ec706e9a 100644 --- a/proto/bfd/io.h +++ b/proto/bfd/io.h @@ -11,80 +11,15 @@ #include "lib/lists.h" #include "lib/resource.h" #include "lib/event.h" +#include "lib/timer.h" #include "lib/socket.h" -// #include "lib/timer.h" -typedef struct timer2 -{ - resource r; - void (*hook)(struct timer2 *); - void *data; - - btime expires; /* 0=inactive */ - uint randomize; /* Amount of randomization */ - uint recurrent; /* Timer recurrence */ - - int index; -} timer2; - - -btime current_time(void); - void ev2_schedule(event *e); - -timer2 *tm2_new(pool *p); -void tm2_set(timer2 *t, btime when); -void tm2_start(timer2 *t, btime after); -void tm2_stop(timer2 *t); - -static inline int -tm2_active(timer2 *t) -{ - return t->expires != 0; -} - -static inline btime -tm2_remains(timer2 *t) -{ - btime now = current_time(); - return (t->expires > now) ? (t->expires - now) : 0; -} - -static inline timer2 * -tm2_new_init(pool *p, void (*hook)(struct timer2 *), void *data, uint rec, uint rand) -{ - timer2 *t = tm2_new(p); - t->hook = hook; - t->data = data; - t->recurrent = rec; - t->randomize = rand; - return t; -} - -static inline void -tm2_set_max(timer2 *t, btime when) -{ - if (when > t->expires) - tm2_set(t, when); -} - -/* -static inline void -tm2_start_max(timer2 *t, btime after) -{ - btime rem = tm2_remains(t); - tm2_start(t, MAX_(rem, after)); -} -*/ - - void sk_start(sock *s); void sk_stop(sock *s); - - struct birdloop *birdloop_new(void); void birdloop_start(struct birdloop *loop); void birdloop_stop(struct birdloop *loop); diff --git a/proto/bfd/packets.c b/proto/bfd/packets.c index 129db72f..b76efda6 100644 --- a/proto/bfd/packets.c +++ b/proto/bfd/packets.c @@ -248,7 +248,7 @@ bfd_check_authentication(struct bfd_proto *p, struct bfd_session *s, struct bfd_ /* BFD CSNs are in 32-bit circular number space */ u32 csn = ntohl(auth->csn); if (s->rx_csn_known && - (((csn - s->rx_csn) > (3 * s->detect_mult)) || + (((csn - s->rx_csn) > (3 * (uint) s->detect_mult)) || (meticulous && (csn == s->rx_csn)))) { /* We want to report both new and old CSN */ @@ -405,10 +405,11 @@ bfd_err_hook(sock *sk, int err) } sock * -bfd_open_rx_sk(struct bfd_proto *p, int multihop) +bfd_open_rx_sk(struct bfd_proto *p, int multihop, int af) { sock *sk = sk_new(p->tpool); sk->type = SK_UDP; + sk->subtype = af; sk->sport = !multihop ? BFD_CONTROL_PORT : BFD_MULTI_CTL_PORT; sk->data = p; @@ -421,10 +422,6 @@ bfd_open_rx_sk(struct bfd_proto *p, int multihop) sk->priority = sk_priority_control; sk->flags = SKF_THREAD | SKF_LADDR_RX | (!multihop ? SKF_TTL_RX : 0); -#ifdef IPV6 - sk->flags |= SKF_V6ONLY; -#endif - if (sk_open(sk) < 0) goto err; @@ -456,10 +453,6 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa) sk->ttl = ifa ? 255 : -1; sk->flags = SKF_THREAD | SKF_BIND | SKF_HIGH_PORT; -#ifdef IPV6 - sk->flags |= SKF_V6ONLY; -#endif - if (sk_open(sk) < 0) goto err; |