From be6e39ebbf7ed107abde6fc1a18e8827ca47a7c1 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Thu, 24 Sep 2009 22:12:11 +0200 Subject: Passive option. --- proto/bgp/bgp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'proto/bgp/bgp.c') diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 0c8ee6da..af5dbfcb 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -120,7 +120,9 @@ bgp_startup(struct bgp_proto *p) { BGP_TRACE(D_EVENTS, "Started"); p->start_state = p->cf->capabilities ? BSS_CONNECT : BSS_CONNECT_NOCAP; - bgp_active(p); + + if (!p->cf->passive) + bgp_active(p); } static void @@ -292,7 +294,8 @@ bgp_decision(void *vp) DBG("BGP: Decision start\n"); if ((p->p.proto_state == PS_START) - && (p->outgoing_conn.state == BS_IDLE)) + && (p->outgoing_conn.state == BS_IDLE) + && (!p->cf->passive)) bgp_active(p); if ((p->p.proto_state == PS_STOP) -- cgit v1.2.3 From ea89da381fc682155e7d08d6ad3d4ac8aa5fe115 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Sun, 11 Oct 2009 18:56:16 +0200 Subject: Workaround for stupid callback scheduler. There is no reak callback scheduler and previous behavior causes bad things during hard congestion (like BGP hold timeouts). Smart callback scheduler is still missing, but main loop was changed such that it first processes all tx callbacks (which are fast enough) (but max 4* per socket) + rx callbacks for CLI, and in the second phase it processes one rx callback per socket up to four sockets (as rx callback can be slow when there are too many protocols, because route redistribution is done synchronously inside rx callback). If there is event callback ready, second phase is skipped in 90% of iterations (to speed up CLI during congestion). --- lib/socket.h | 1 + proto/bgp/bgp.c | 11 ++++++-- sysdep/unix/io.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 7 deletions(-) (limited to 'proto/bgp/bgp.c') diff --git a/lib/socket.h b/lib/socket.h index f1922607..53e89edd 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -51,6 +51,7 @@ void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */ void sk_dump_all(void); int sk_set_ttl(sock *s, int ttl); /* Set TTL for given socket */ int sk_set_md5_auth(sock *s, ip_addr a, char *passwd); /* Add or remove security associations for given passive socket */ +int sk_rx_ready(sock *s); static inline int sk_send_buffer_empty(sock *sk) diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index af5dbfcb..b76b7f97 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -431,8 +431,15 @@ bgp_hold_timeout(timer *t) { struct bgp_conn *conn = t->data; - DBG("BGP: Hold timeout, closing connection\n"); - bgp_error(conn, 4, 0, NULL, 0); + DBG("BGP: Hold timeout\n"); + + /* If there is something in input queue, we are probably congested + and perhaps just not processed BGP packets in time. */ + + if (sk_rx_ready(conn->sk) > 0) + bgp_start_timer(conn->hold_timer, 10); + else + bgp_error(conn, 4, 0, NULL, 0); } static void diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 99d33936..330aea4f 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -30,12 +30,17 @@ #include "lib/unix.h" #include "lib/sysio.h" -/* Maximum number of calls of rx/tx handler for one socket in one +/* Maximum number of calls of tx handler for one socket in one * select iteration. Should be small enough to not monopolize CPU by * one protocol instance. */ #define MAX_STEPS 4 +/* Maximum number of calls of rx handler for all sockets in one select + iteration. RX callbacks are often much more costly so we limit + this to gen small latencies */ +#define MAX_RX_STEPS 4 + /* * Tracked Files */ @@ -493,6 +498,7 @@ tm_format_reltime(char *x, bird_clock_t t) static list sock_list; static struct birdsock *current_sock; +static struct birdsock *stored_sock; static int sock_recalc_fdsets_p; static inline sock * @@ -541,6 +547,8 @@ sk_free(resource *r) close(s->fd); if (s == current_sock) current_sock = sk_next(s); + if (s == stored_sock) + stored_sock = sk_next(s); rem_node(&s->n); sock_recalc_fdsets_p = 1; } @@ -1071,6 +1079,29 @@ sk_maybe_write(sock *s) } } +int +sk_rx_ready(sock *s) +{ + fd_set rd, wr; + struct timeval timo; + int rv; + + FD_ZERO(&rd); + FD_ZERO(&wr); + FD_SET(s->fd, &rd); + + timo.tv_sec = 0; + timo.tv_usec = 0; + + redo: + rv = select(s->fd+1, &rd, &wr, NULL, &timo); + + if ((rv < 0) && (errno == EINTR || errno == EAGAIN)) + goto redo; + + return rv; +} + /** * sk_send - send data to a socket * @s: socket @@ -1239,6 +1270,9 @@ io_init(void) srandom((int) now_real); } +static int short_loops = 0; +#define SHORT_LOOP_MAX 10 + void io_loop(void) { @@ -1317,8 +1351,8 @@ io_loop(void) } /* And finally enter select() to find active sockets */ - hi = select(hi+1, &rd, &wr, NULL, &timo); + if (hi < 0) { if (errno == EINTR || errno == EAGAIN) @@ -1327,13 +1361,17 @@ io_loop(void) } if (hi) { - current_sock = SKIP_BACK(sock, n, HEAD(sock_list)); /* guaranteed to be non-empty */ + /* guaranteed to be non-empty */ + current_sock = SKIP_BACK(sock, n, HEAD(sock_list)); + while (current_sock) { sock *s = current_sock; int e; - int steps = MAX_STEPS; - if (FD_ISSET(s->fd, &rd) && s->rx_hook) + int steps; + + steps = MAX_STEPS; + if ((s->type >= SK_MAGIC) && FD_ISSET(s->fd, &rd) && s->rx_hook) do { steps--; @@ -1356,6 +1394,35 @@ io_loop(void) current_sock = sk_next(s); next: ; } + + short_loops++; + if (events && (short_loops < SHORT_LOOP_MAX)) + continue; + short_loops = 0; + + int count = 0; + current_sock = stored_sock; + if (current_sock == NULL) + current_sock = SKIP_BACK(sock, n, HEAD(sock_list)); + + while (current_sock && count < MAX_RX_STEPS) + { + sock *s = current_sock; + int e; + int steps; + + if ((s->type < SK_MAGIC) && FD_ISSET(s->fd, &rd) && s->rx_hook) + { + count++; + e = sk_read(s); + if (s != current_sock) + goto next2; + } + current_sock = sk_next(s); + next2: ; + } + + stored_sock = current_sock; } } } -- cgit v1.2.3 From 4cdd078453d585ac97a183ea1f3951d85f1b8784 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Mon, 12 Oct 2009 23:31:42 +0200 Subject: Implements protocol-specific router id and updates documentation. --- doc/bird.sgml | 31 ++++++++++++++++++++++++++++++- filter/test.conf | 1 + nest/config.Y | 1 + nest/proto.c | 1 + nest/protocol.h | 8 ++++++++ proto/bgp/bgp.c | 2 +- 6 files changed, 42 insertions(+), 2 deletions(-) (limited to 'proto/bgp/bgp.c') diff --git a/doc/bird.sgml b/doc/bird.sgml index ceff31d8..0c2b8fbe 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -297,6 +297,10 @@ to zero to disable it. An empty is equivalent to router id This option can be used to override global + router id for a given protocol. This option is not yet implemented for OSPF + protocol. Default: uses global router id. + import all | none | filter Specify a filter to be used for filtering routes coming from the protocol to the routing table. option is used, changes in filters does not cause + returns the first ASN (the neighbor ASN) in path returns the last ASN (the source ASN) in path returns the length of path prepend( prepends ASN can be shortened to + if [= * 4 (1+2) a =]. There is also old syntax that uses / .. / instead of [= .. =] and ? instead of *. + add( adds pair delete( deletes pair can be shortened to + if diff --git a/filter/test.conf b/filter/test.conf index f3b79619..7114fd28 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -62,6 +62,7 @@ clist l; print "Should be true: ", p2 ~ / ? 4 3 2 1 /, " ", p2, " ", / ? 4 3 2 1 /; print "Should be true: ", p2 ~ [= * 4 3 * 1 =], " ", p2, " ", [= * 4 3 * 1 =]; print "Should be true: ", p2 ~ [= (3+2) (2*2) 3 2 1 =], " ", p2 ~ mkpath(5, 4); + print "Should be true: ", p2.len = 5, " ", p2.first = 5, " ", p2.last = 1; print "5 = ", p2.len; pm1 = [= 1 2 * 3 4 5 =]; diff --git a/nest/config.Y b/nest/config.Y index a2c44ab7..4721112a 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -140,6 +140,7 @@ proto_item: | IMPORT imexport { this_proto->in_filter = $2; } | EXPORT imexport { this_proto->out_filter = $2; } | TABLE rtable { this_proto->table = $2; } + | ROUTER ID idval { this_proto->router_id = $3; } ; imexport: diff --git a/nest/proto.c b/nest/proto.c index d0792134..7bb1286d 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -313,6 +313,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty && nc->preference == oc->preference && nc->disabled == oc->disabled && nc->table->table == oc->table->table + && proto_get_router_id(nc) == proto_get_router_id(oc) && ((type == RECONFIG_SOFT) || filter_same(nc->in_filter, oc->in_filter)) && ((type == RECONFIG_SOFT) || filter_same(nc->out_filter, oc->out_filter)) && p->proto_state != PS_DOWN) diff --git a/nest/protocol.h b/nest/protocol.h index 0f9d59d8..484df846 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -12,6 +12,7 @@ #include "lib/lists.h" #include "lib/resource.h" #include "lib/timer.h" +#include "conf/conf.h" struct iface; struct ifa; @@ -81,6 +82,7 @@ struct proto_config { struct proto *proto; /* Instance we've created */ char *name; unsigned debug, preference, disabled; /* Generic parameters */ + u32 router_id; /* Protocol specific router ID */ struct rtable_config *table; /* Table we're attached to */ struct filter *in_filter, *out_filter; /* Attached filters */ @@ -192,6 +194,12 @@ struct proto *proto_get_named(struct symbol *, struct protocol *); void proto_xxable(char *, int); void proto_debug(char *, unsigned int); +static inline u32 +proto_get_router_id(struct proto_config *pc) +{ + return pc->router_id ? pc->router_id : pc->global->router_id; +} + extern list active_proto_list; /* diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index b76b7f97..b38c6b13 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -689,7 +689,7 @@ bgp_start_locked(struct object_lock *lock) } DBG("BGP: Got lock\n"); - p->local_id = cf->c.global->router_id; + p->local_id = proto_get_router_id(&cf->c); p->next_hop = cf->multihop ? cf->multihop_via : cf->remote_ip; p->neigh = neigh_find(&p->p, &p->next_hop, NEF_STICKY); -- cgit v1.2.3