diff options
-rw-r--r-- | filter/config.Y | 13 | ||||
-rw-r--r-- | lib/birdlib.h | 9 | ||||
-rw-r--r-- | lib/settle.h | 2 | ||||
-rw-r--r-- | nest/rt-table.c | 4 | ||||
-rw-r--r-- | sysdep/bsd/krt-sock.c | 111 | ||||
-rw-r--r-- | sysdep/linux/netlink.Y | 21 | ||||
-rw-r--r-- | sysdep/unix/domain.c | 6 | ||||
-rw-r--r-- | sysdep/unix/krt.c | 34 |
8 files changed, 114 insertions, 86 deletions
diff --git a/filter/config.Y b/filter/config.Y index d20e4a04..7f152659 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -338,7 +338,6 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, %type <xp> cmds_int cmd_prep %type <x> term cmd cmd_var cmds cmds_scoped constant constructor print_list var var_init var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail %type <fsa> static_attr -%type <fab> attr_bit %type <f> filter where_filter %type <fl> filter_body function_body %type <flv> lvalue @@ -846,10 +845,6 @@ term: | constructor { $$ = $1; } | static_attr { $$ = f_new_inst(FI_RTA_GET, $1); } - | attr_bit { - struct f_inst *c = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = (1U << $1.bit)}); - $$ = f_new_inst(FI_EQ, c, f_new_inst(FI_BITAND, f_new_inst(FI_EA_GET, $1.class), c)); - } | term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4, $1); } | term '.' TYPE { $$ = f_new_inst(FI_TYPE, $1); } @@ -979,14 +974,6 @@ cmd: cf_error("Attribute %s is read-only", $3->attribute->name); $$ = f_new_inst(FI_EA_UNSET, $3->attribute); } - | attr_bit '=' term ';' { - $$ = f_new_inst(FI_CONDITION, $3, - f_generate_complex_default(FI_BITOR, $1.class, - f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = (1U << $1.bit)}), 0), - f_generate_complex_default(FI_BITAND, $1.class, - f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = ~(1U << $1.bit)}), 0) - ); - } | break_command print_list ';' { struct f_inst *breaker = f_new_inst(FI_DIE, $1); if ($2) { diff --git a/lib/birdlib.h b/lib/birdlib.h index d743ecdf..5ecd19ca 100644 --- a/lib/birdlib.h +++ b/lib/birdlib.h @@ -9,13 +9,22 @@ #ifndef _BIRD_BIRDLIB_H_ #define _BIRD_BIRDLIB_H_ +#include <stddef.h> + #include "sysdep/config.h" #include "lib/alloca.h" /* Ugly structure offset handling macros */ #define SAME_TYPE(a, b) ({ int _ = ((a) != (b)); !_; }) +#define TYPE_CAST(from, to, what) ( SAME_TYPE(((from) NULL), (what)), ((to) (what))) + +#ifdef offsetof +#define OFFSETOF offsetof +#else #define OFFSETOF(s, i) ((size_t) &((s *)0)->i) +#endif + #define SKIP_BACK(s, i, p) ({ s *_ptr = ((s *)((char *)p - OFFSETOF(s, i))); SAME_TYPE(&_ptr->i, p); _ptr; }) #define BIRD_ALIGN(s, a) (((s)+a-1)&~(a-1)) #define CPU_STRUCT_ALIGN (MAX_(_Alignof(void*), _Alignof(u64))) diff --git a/lib/settle.h b/lib/settle.h index d274599d..e721f21f 100644 --- a/lib/settle.h +++ b/lib/settle.h @@ -32,7 +32,7 @@ struct settle { STATIC_ASSERT(OFFSETOF(struct settle, hook) == OFFSETOF(struct settle, tm) + OFFSETOF(timer, hook)); -#define SETTLE_INIT(_cfp, _hook, _data) (struct settle) { .tm = { .data = (_data), }, .hook = (_hook), .cf = ({ASSERT_DIE((_cfp)->min <= (_cfp)->max); *(_cfp); }), } +#define SETTLE_INIT(_cfp, _hook, _data) (struct settle) { .tm = { .data = (_data), .hook = TYPE_CAST(void (*)(struct settle *), void (*)(struct timer *), (_hook)), }, .cf = ({ASSERT_DIE((_cfp)->min <= (_cfp)->max); *(_cfp); }), } static inline void settle_init(struct settle *s, struct settle_config *cf, void (*hook)(struct settle *), void *data) diff --git a/nest/rt-table.c b/nest/rt-table.c index e712796b..48f5587b 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -3352,8 +3352,8 @@ ea_set_hostentry(ea_list **to, rtable *dep, rtable *src, ip_addr gw, ip_addr ll, struct { struct adata ad; struct hostentry *he; - u32 labels[lnum]; - } *head = (void *) tmp_alloc_adata(sizeof *head - sizeof(struct adata)); + u32 labels[0]; + } *head = (void *) tmp_alloc_adata(sizeof *head + sizeof(u32) * lnum - sizeof(struct adata)); RT_LOCKED(src, tab) head->he = rt_get_hostentry(tab, gw, ll, dep); diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 1c1bd50c..0706f546 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -148,15 +148,18 @@ static struct krt_proto *krt_table_map[KRT_MAX_TABLES][2]; int krt_capable(rte *e) { - rta *a = e->attrs; + ea_list *eattrs = e->attrs; + eattr *nhea = ea_find(eattrs, &ea_gen_nexthop); + struct nexthop_adata *nh = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL; + int dest = nhea_dest(nhea); return - ((a->dest == RTD_UNICAST && !a->nh.next) /* No multipath support */ + ((dest == RTD_UNICAST && !NEXTHOP_ONE(nh)) /* No multipath support */ #ifdef RTF_REJECT - || a->dest == RTD_UNREACHABLE + || dest == RTD_UNREACHABLE #endif #ifdef RTF_BLACKHOLE - || a->dest == RTD_BLACKHOLE + || dest == RTD_BLACKHOLE #endif ); } @@ -197,18 +200,22 @@ sockaddr_fill_dl(struct sockaddr_dl *sa, struct iface *ifa) } static int -krt_send_route(struct krt_proto *p, int cmd, rte *e) +krt_send_route(struct krt_proto *p, int cmd, const rte *e) { - net *net = e->net; - rta *a = e->attrs; + const net_addr *net = e->net; + ea_list *eattrs = e->attrs; + eattr *nhea = ea_find(eattrs, &ea_gen_nexthop); + struct nexthop_adata *nh = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL; + int dest = nhea_dest(nhea); + static int msg_seq; - struct iface *j, *i = a->nh.iface; + struct iface *j, *i = (dest == RTD_UNICAST) ? nh->nh.iface : NULL; int l; struct ks_msg msg; char *body = (char *)msg.buf; sockaddr gate, mask, dst; - DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw); + DBG("krt-sock: send %N via %I\n", net, nh->nh.gw); bzero(&msg,sizeof (struct rt_msghdr)); msg.rtm.rtm_version = RTM_VERSION; @@ -218,7 +225,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1; /* XXXX */ - if (net_pxlen(net->n.addr) == net_max_prefix_length[net->n.addr->type]) + if (net_pxlen(e->net) == net_max_prefix_length[net->type]) msg.rtm.rtm_flags |= RTF_HOST; else msg.rtm.rtm_addrs |= RTA_NETMASK; @@ -228,11 +235,11 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) #endif #ifdef RTF_REJECT - if(a->dest == RTD_UNREACHABLE) + if(dest == RTD_UNREACHABLE) msg.rtm.rtm_flags |= RTF_REJECT; #endif #ifdef RTF_BLACKHOLE - if(a->dest == RTD_BLACKHOLE) + if(dest == RTD_BLACKHOLE) msg.rtm.rtm_flags |= RTF_BLACKHOLE; #endif @@ -260,7 +267,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) int af = AF_UNSPEC; - switch (net->n.addr->type) { + switch (net->type) { case NET_IP4: af = AF_INET; break; @@ -268,19 +275,19 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) af = AF_INET6; break; default: - log(L_ERR "KRT: Not sending route %N to kernel", net->n.addr); + log(L_ERR "KRT: Not sending route %N to kernel", net); return -1; } - sockaddr_fill(&dst, af, net_prefix(net->n.addr), NULL, 0); - sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0); + sockaddr_fill(&dst, af, net_prefix(net), NULL, 0); + sockaddr_fill(&mask, af, net_pxmask(net), NULL, 0); - switch (a->dest) + switch (dest) { case RTD_UNICAST: - if (ipa_nonzero(a->nh.gw)) + if (ipa_nonzero(nh->nh.gw)) { - ip_addr gw = a->nh.gw; + ip_addr gw = nh->nh.gw; /* Embed interface ID to link-local address */ if (ipa_is_link_local(gw)) @@ -292,6 +299,8 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) break; } + /* Fall through */ + #ifdef RTF_REJECT case RTD_UNREACHABLE: #endif @@ -303,7 +312,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) #if __OpenBSD__ /* Keeping temporarily old code for OpenBSD */ - struct ifa *addr = (net->n.addr->type == NET_IP4) ? i->addr4 : (i->addr6 ?: i->llv6); + struct ifa *addr = (net->type == NET_IP4) ? i->addr4 : (i->addr6 ?: i->llv6); if (!addr) { @@ -339,7 +348,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) msg.rtm.rtm_msglen = l; if ((l = write(p->sys.sk->fd, (char *)&msg, l)) < 0) { - log(L_ERR "KRT: Error sending route %N to kernel: %m", net->n.addr); + log(L_ERR "KRT: Error sending route %N to kernel: %m", net); return -1; } @@ -347,7 +356,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) } void -krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old) +krt_replace_rte(struct krt_proto *p, const net_addr *n UNUSED, rte *new, const rte *old) { int err = 0; @@ -398,7 +407,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) /* p is NULL iff KRT_SHARED_SOCKET and !scan */ int ipv6; - net *net; sockaddr dst, gate, mask; ip_addr idst, igate, imask; net_addr ndst; @@ -514,74 +522,82 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) src = KRT_SRC_ALIEN; else src = KRT_SRC_KERNEL; + + union { + struct { + struct adata ad; + struct nexthop nh; + u32 labels[MPLS_MAX_LABEL_STACK]; + }; + struct nexthop_adata nhad; + } nhad = {}; - net = net_get(p->p.main_channel->table, &ndst); - - rta a = { - }; + ea_list *eattrs = NULL; - ea_set_attr_u32(&a->eattrs, &ea_gen_source, 0, RTS_INHERIT); + ea_set_attr_u32(&eattrs, &ea_gen_source, 0, RTS_INHERIT); /* reject/blackhole routes have also set RTF_GATEWAY, we wil check them first. */ #ifdef RTF_REJECT if(flags & RTF_REJECT) { - a.dest = RTD_UNREACHABLE; + nhad.nhad = NEXTHOP_DEST_LITERAL(RTD_UNREACHABLE); goto done; } #endif #ifdef RTF_BLACKHOLE if(flags & RTF_BLACKHOLE) { - a.dest = RTD_BLACKHOLE; + nhad.nhad = NEXTHOP_DEST_LITERAL(RTD_BLACKHOLE); goto done; } #endif - a.nh.iface = if_find_by_index(msg->rtm.rtm_index); - if (!a.nh.iface) + nhad.nh.iface = if_find_by_index(msg->rtm.rtm_index); + if (!nhad.nh.iface) { log(L_ERR "KRT: Received route %N with unknown ifindex %u", - net->n.addr, msg->rtm.rtm_index); + &ndst, msg->rtm.rtm_index); return; } - a.dest = RTD_UNICAST; if (flags & RTF_GATEWAY) { - a.nh.gw = igate; + nhad.nh.gw = igate; /* Clean up embedded interface ID returned in link-local address */ - if (ipa_is_link_local(a.nh.gw)) - _I0(a.nh.gw) = 0xfe800000; + if (ipa_is_link_local(nhad.nh.gw)) + _I0(nhad.nh.gw) = 0xfe800000; /* The BSD kernel does not support an onlink flag. We heuristically set the onlink flag, if the iface has only host addresses. */ - if (krt_assume_onlink(a.nh.iface, ipv6)) - a.nh.flags |= RNF_ONLINK; + if (krt_assume_onlink(nhad.nh.iface, ipv6)) + nhad.nh.flags |= RNF_ONLINK; neighbor *nbr; - nbr = neigh_find(&p->p, a.nh.gw, a.nh.iface, - (a.nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0); + nbr = neigh_find(&p->p, nhad.nh.gw, nhad.nh.iface, + (nhad.nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0); if (!nbr || (nbr->scope == SCOPE_HOST)) { /* Ignore routes with next-hop 127.0.0.1, host routes with such next-hop appear on OpenBSD for address aliases. */ - if (ipa_classify(a.nh.gw) == (IADDR_HOST | SCOPE_HOST)) + if (ipa_classify(nhad.nh.gw) == (IADDR_HOST | SCOPE_HOST)) return; log(L_ERR "KRT: Received route %N with strange next-hop %I", - net->n.addr, a.nh.gw); + &ndst, nhad.nh.gw); return; } } - done:; - rte e0 = { .attrs = &a, .net = net, }; + nhad.ad.length = (void *) NEXTHOP_NEXT(&nhad.nh) - (void *) nhad.ad.data; + + done: + ea_set_attr(&eattrs, EA_LITERAL_DIRECT_ADATA(&ea_gen_nexthop, 0, &nhad.ad)); + rte e0 = { .attrs = eattrs, .net = &ndst, }; - ea_set_attr(e0.attrs->eattrs, - EA_LITERAL_EMBEDDED(EA_KRT_SOURCE, T_INT, 0, src2)); + ea_set_attr(&e0.attrs, + EA_LITERAL_EMBEDDED(&ea_krt_source, 0, src2)); if (scan) krt_got_route(p, &e0, src); @@ -822,6 +838,7 @@ krt_read_msg(struct proto *p, struct ks_msg *msg, int scan) { case RTM_GET: if(!scan) return; + /* Fall through */ case RTM_ADD: case RTM_DELETE: case RTM_CHANGE: diff --git a/sysdep/linux/netlink.Y b/sysdep/linux/netlink.Y index 7ba8c7c9..9b07e9bb 100644 --- a/sysdep/linux/netlink.Y +++ b/sysdep/linux/netlink.Y @@ -15,6 +15,8 @@ CF_KEYWORDS(KERNEL, TABLE, METRIC, NETLINK, RX, BUFFER, KRT_LOCK_SSTRESH, KRT_LOCK_CWND, KRT_LOCK_ADVMSS, KRT_LOCK_REORDERING, KRT_LOCK_HOPLIMIT, KRT_LOCK_RTO_MIN, KRT_FEATURE_ECN, KRT_FEATURE_ALLFRAG) +%type <fab> attr_bit + CF_GRAMMAR kern_proto: kern_proto kern_sys_item ';' ; @@ -42,6 +44,25 @@ attr_bit: KRT_LOCK_RTO_MIN { $$ = f_new_dynamic_attr_bit(13, "krt_lock"); } ; attr_bit: KRT_FEATURE_ECN { $$ = f_new_dynamic_attr_bit(0, "krt_features"); } ; attr_bit: KRT_FEATURE_ALLFRAG { $$ = f_new_dynamic_attr_bit(3, "krt_features"); } ; +/* Getting attribute bits (moved here to not confuse Bison on *BSD) */ +term: + attr_bit { + struct f_inst *c = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = (1U << $1.bit)}); + $$ = f_new_inst(FI_EQ, c, f_new_inst(FI_BITAND, f_new_inst(FI_EA_GET, $1.class), c)); + } + ; + +/* Setting attribute bits (moved here to not confuse Bison on *BSD) */ +cmd: + attr_bit '=' term ';' { + $$ = f_new_inst(FI_CONDITION, $3, + f_generate_complex_default(FI_BITOR, $1.class, + f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = (1U << $1.bit)}), 0), + f_generate_complex_default(FI_BITAND, $1.class, + f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = ~(1U << $1.bit)}), 0) + ); + } + ; CF_CODE diff --git a/sysdep/unix/domain.c b/sysdep/unix/domain.c index 1cba540b..f4ee595d 100644 --- a/sysdep/unix/domain.c +++ b/sysdep/unix/domain.c @@ -83,11 +83,15 @@ uint dg_order(struct domain_generic *dg) void do_lock(struct domain_generic *dg, struct domain_generic **lsp) { + struct lock_order stack_copy; + memcpy(&stack_copy, &locking_stack, sizeof(stack_copy)); + struct domain_generic **lll = last_locked; + if ((char *) lsp - (char *) &locking_stack != dg->order) bug("Trying to lock on bad position: order=%u, lsp=%p, base=%p", dg->order, lsp, &locking_stack); if (lsp <= last_locked) - bug("Trying to lock in a bad order"); + bug("Trying to lock in a bad order: %p %p", &stack_copy, lll); if (*lsp) bug("Inconsistent locking stack state on lock"); diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 3b6c91cc..b3681c9c 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -290,18 +290,6 @@ krt_metric(rte *a) return ea ? ea->u.data : 0; } -static inline int -krt_same_key(rte *a, rte *b) -{ - return (krt_metric(a) == krt_metric(b)); -} - -static inline int -krt_uptodate(rte *a, rte *b) -{ - return (a->attrs == b->attrs); -} - static void krt_learn_alien_attr(struct channel *c, rte *e) { @@ -444,10 +432,13 @@ krt_got_route(struct krt_proto *p, rte *e, s8 src) switch (src) { case KRT_SRC_KERNEL: - goto ignore; + krt_trace_in(p, e, "ignored"); + return; case KRT_SRC_REDIRECT: - goto delete; + krt_trace_in(p, e, "deleting"); + krt_replace_rte(p, e->net, NULL, e); + return; case KRT_SRC_ALIEN: if (KRT_CF->learn) @@ -457,6 +448,7 @@ krt_got_route(struct krt_proto *p, rte *e, s8 src) return; } #endif + /* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */ RT_LOCKED(p->p.main_channel->table, tab) @@ -719,7 +711,11 @@ static int krt_preexport(struct channel *C, rte *e) { if (e->src->owner == &C->proto->sources) +#ifdef CONFIG_SINGLE_ROUTE + return 1; +#else return -1; +#endif if (!krt_capable(e)) return -1; @@ -737,14 +733,8 @@ krt_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net, return; #ifdef CONFIG_SINGLE_ROUTE - /* - * Implicit withdraw - when the imported kernel route becomes the best one, - * we know that the previous one exported to the kernel was already removed, - * but if we processed the update as usual, we would send withdraw to the - * kernel, which would remove the new imported route instead. - */ - rte *best = net->routes; - if (!new && best && (best->attrs->src->proto == P)) + /* Got the same route as we imported. Keep it, do nothing. */ + if (new && new->src->owner == &P->sources) return; #endif |