summaryrefslogtreecommitdiffstats
path: root/sysdep
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep')
-rw-r--r--sysdep/bsd/krt-sock.c5
-rw-r--r--sysdep/config.h2
-rw-r--r--sysdep/linux/krt-scan.c6
-rw-r--r--sysdep/linux/netlink/netlink.Y5
-rw-r--r--sysdep/linux/netlink/netlink.c38
-rw-r--r--sysdep/unix/io.c96
6 files changed, 109 insertions, 43 deletions
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c
index 2e8f1b8..4842a6b 100644
--- a/sysdep/bsd/krt-sock.c
+++ b/sysdep/bsd/krt-sock.c
@@ -339,7 +339,10 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
if (ng && ng->scope)
a.iface = ng->iface;
else
- log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", igate, net->n.prefix, net->n.pxlen);
+ {
+ log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", igate, net->n.prefix, net->n.pxlen);
+ return;
+ }
a.dest = RTD_ROUTER;
a.gw = igate;
diff --git a/sysdep/config.h b/sysdep/config.h
index 54f3674..03399bd 100644
--- a/sysdep/config.h
+++ b/sysdep/config.h
@@ -7,7 +7,7 @@
#define _BIRD_CONFIG_H_
/* BIRD version */
-#define BIRD_VERSION "1.1.0"
+#define BIRD_VERSION "1.1.5"
/* Include parameters determined by configure script */
#include "sysdep/autoconf.h"
diff --git a/sysdep/linux/krt-scan.c b/sysdep/linux/krt-scan.c
index b7fc129..feb128e 100644
--- a/sysdep/linux/krt-scan.c
+++ b/sysdep/linux/krt-scan.c
@@ -103,8 +103,10 @@ krt_parse_entry(byte *ent, struct krt_proto *p)
if (ng && ng->scope)
a.iface = ng->iface;
else
- /* FIXME: Remove this warning? Handle it somehow... */
- log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", gw, net->n.prefix, net->n.pxlen);
+ {
+ log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", gw, net->n.prefix, net->n.pxlen);
+ return;
+ }
a.dest = RTD_ROUTER;
a.gw = gw;
}
diff --git a/sysdep/linux/netlink/netlink.Y b/sysdep/linux/netlink/netlink.Y
index c448d89..c5dcf62 100644
--- a/sysdep/linux/netlink/netlink.Y
+++ b/sysdep/linux/netlink/netlink.Y
@@ -18,13 +18,8 @@ CF_ADDTO(kern_proto, kern_proto nl_item ';')
nl_item:
KERNEL TABLE expr {
-#ifndef IPV6
if ($3 <= 0 || $3 >= NL_NUM_TABLES)
cf_error("Kernel routing table number out of range");
-#else
- if ($3 != 254)
- cf_error("Linux implementation of IPv6 doesn't support multiple routing tables");
-#endif
THIS_KRT->scan.table_id = $3;
}
;
diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c
index 6cfb0ba..f45fe15 100644
--- a/sysdep/linux/netlink/netlink.c
+++ b/sysdep/linux/netlink/netlink.c
@@ -691,18 +691,34 @@ nl_parse_route(struct nlmsghdr *h, int scan)
ra.dest = RTD_ROUTER;
memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
ipa_ntoh(ra.gw);
- ng = neigh_find2(&p->p, &ra.gw, ifa, 0);
- if (ng && ng->scope)
- {
- if (ng->iface != ifa)
- log(L_WARN "KRT: Route with unexpected iface for %I/%d", net->n.prefix, net->n.pxlen);
- ra.iface = ng->iface;
- }
+
+ if (i->rtm_flags & RTNH_F_ONLINK)
+ {
+ /* route with 'onlink' attribute */
+ ra.iface = if_find_by_index(oif);
+ if (ra.iface == NULL)
+ {
+ log(L_WARN "Kernel told us to use unknown interface %u for %I/%d",
+ oif, net->n.prefix, net->n.pxlen);
+ return;
+ }
+ }
else
- {
- log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", ra.gw, net->n.prefix, net->n.pxlen);
- return;
- }
+ {
+ ng = neigh_find2(&p->p, &ra.gw, ifa, 0);
+ if (ng && ng->scope)
+ {
+ if (ng->iface != ifa)
+ log(L_WARN "KRT: Route with unexpected iface for %I/%d", net->n.prefix, net->n.pxlen);
+ ra.iface = ng->iface;
+ }
+ else
+ {
+ log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", ra.gw, net->n.prefix, net->n.pxlen);
+ return;
+ }
+
+ }
}
else
{
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 5cc80dc..3eb2e03 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
*/
@@ -205,10 +210,6 @@ timer *
tm_new(pool *p)
{
timer *t = ralloc(p, &tm_class);
- t->hook = NULL;
- t->data = NULL;
- t->randomize = 0;
- t->expires = 0;
return t;
}
@@ -497,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 *
@@ -545,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;
}
@@ -595,22 +599,9 @@ sk_new(pool *p)
{
sock *s = ralloc(p, &sk_class);
s->pool = p;
- s->data = NULL;
- s->saddr = s->daddr = IPA_NONE;
- s->sport = s->dport = 0;
+ // s->saddr = s->daddr = IPA_NONE;
s->tos = s->ttl = -1;
- s->flags = 0;
- s->iface = NULL;
- s->rbuf = NULL;
- s->rx_hook = NULL;
- s->rbsize = 0;
- s->tbuf = NULL;
- s->tx_hook = NULL;
- s->tbsize = 0;
- s->err_hook = NULL;
s->fd = -1;
- s->rbuf_alloc = s->tbuf_alloc = NULL;
- s->password = NULL;
return s;
}
@@ -1169,6 +1160,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
@@ -1337,6 +1351,9 @@ io_init(void)
srandom((int) now_real);
}
+static int short_loops = 0;
+#define SHORT_LOOP_MAX 10
+
void
io_loop(void)
{
@@ -1415,8 +1432,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)
@@ -1425,13 +1442,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--;
@@ -1454,6 +1475,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;
}
}
}