diff options
Diffstat (limited to 'sysdep')
-rw-r--r-- | sysdep/cf/linux.h | 1 | ||||
-rw-r--r-- | sysdep/linux/netlink.c | 43 | ||||
-rw-r--r-- | sysdep/unix/io.c | 9 | ||||
-rw-r--r-- | sysdep/unix/krt.Y | 13 | ||||
-rw-r--r-- | sysdep/unix/krt.c | 46 | ||||
-rw-r--r-- | sysdep/unix/krt.h | 2 |
6 files changed, 77 insertions, 37 deletions
diff --git a/sysdep/cf/linux.h b/sysdep/cf/linux.h index 3a3a15da..047d3764 100644 --- a/sysdep/cf/linux.h +++ b/sysdep/cf/linux.h @@ -10,6 +10,7 @@ #define CONFIG_SELF_CONSCIOUS #define CONFIG_MULTIPLE_TABLES #define CONFIG_ALL_TABLES_AT_ONCE +#define CONFIG_IP6_SADR_KERNEL #define CONFIG_MC_PROPER_SRC #define CONFIG_UNIX_DONTROUTE diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 4cb51519..84591eb2 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -374,6 +374,7 @@ static struct nl_want_attrs rtm_attr_want4[BIRD_RTA_MAX] = { static struct nl_want_attrs rtm_attr_want6[BIRD_RTA_MAX] = { [RTA_DST] = { 1, 1, sizeof(ip6_addr) }, + [RTA_SRC] = { 1, 1, sizeof(ip6_addr) }, [RTA_IIF] = { 1, 1, sizeof(u32) }, [RTA_OIF] = { 1, 1, sizeof(u32) }, [RTA_GATEWAY] = { 1, 1, sizeof(ip6_addr) }, @@ -1221,8 +1222,18 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d } else #endif + { nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(net->n.addr)); + /* Add source address for IPv6 SADR routes */ + if (net->n.addr->type == NET_IP6_SADR) + { + net_addr_ip6_sadr *a = (void *) &net->n.addr; + nl_add_attr_ip6(&r->h, rsize, RTA_SRC, a->src_prefix); + r->r.rtm_src_len = a->src_pxlen; + } + } + /* * Strange behavior for RTM_DELROUTE: * 1) rtm_family is ignored in IPv6, works for IPv4 @@ -1447,12 +1458,12 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) struct rtattr *a[BIRD_RTA_MAX]; int new = h->nlmsg_type == RTM_NEWROUTE; - net_addr dst; + net_addr dst, src = {}; u32 oif = ~0; u32 table_id; u32 priority = 0; u32 def_scope = RT_SCOPE_UNIVERSE; - int src; + int krt_src; if (!(i = nl_checkin(h, sizeof(*i)))) return; @@ -1477,6 +1488,11 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) net_fill_ip6(&dst, rta_get_ip6(a[RTA_DST]), i->rtm_dst_len); else net_fill_ip6(&dst, IP6_NONE, 0); + + if (a[RTA_SRC]) + net_fill_ip6(&src, rta_get_ip6(a[RTA_SRC]), i->rtm_src_len); + else + net_fill_ip6(&src, IP6_NONE, 0); break; #ifdef HAVE_MPLS_KERNEL @@ -1511,6 +1527,9 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) if (!p) SKIP("unknown table %d\n", table); + if (a[RTA_SRC] && (p->p.net_type != NET_IP6_SADR)) + SKIP("src prefix for non-SADR channel\n"); + if (a[RTA_IIF]) SKIP("IIF set\n"); @@ -1533,25 +1552,33 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) SKIP("proto unspec\n"); case RTPROT_REDIRECT: - src = KRT_SRC_REDIRECT; + krt_src = KRT_SRC_REDIRECT; break; case RTPROT_KERNEL: - src = KRT_SRC_KERNEL; + krt_src = KRT_SRC_KERNEL; return; case RTPROT_BIRD: if (!s->scan) SKIP("echo\n"); - src = KRT_SRC_BIRD; + krt_src = KRT_SRC_BIRD; break; case RTPROT_BOOT: default: - src = KRT_SRC_ALIEN; + krt_src = KRT_SRC_ALIEN; } - net *net = net_get(p->p.main_channel->table, &dst); + net_addr *n = &dst; + if (p->p.net_type == NET_IP6_SADR) + { + n = alloca(sizeof(net_addr_ip6_sadr)); + net_fill_ip6_sadr(n, net6_prefix(&dst), net6_pxlen(&dst), + net6_prefix(&src), net6_pxlen(&src)); + } + + net *net = net_get(p->p.main_channel->table, n); if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type)) nl_announce_route(s); @@ -1755,7 +1782,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) s->attrs = ra; s->proto = p; s->new = new; - s->krt_src = src; + s->krt_src = krt_src; s->krt_type = i->rtm_type; s->krt_proto = i->rtm_protocol; s->krt_metric = priority; diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index cd2558b2..012deaf0 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -958,10 +958,6 @@ sk_setup(sock *s) #endif } - if (s->priority >= 0) - if (sk_set_priority(s, s->priority) < 0) - return -1; - if (sk_is_ipv4(s)) { if (s->flags & SKF_LADDR_RX) @@ -1012,6 +1008,11 @@ sk_setup(sock *s) return -1; } + /* Must be after sk_set_tos4() as setting ToS on Linux also mangles priority */ + if (s->priority >= 0) + if (sk_set_priority(s, s->priority) < 0) + return -1; + return 0; } diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y index 1cb28389..9aac8668 100644 --- a/sysdep/unix/krt.Y +++ b/sysdep/unix/krt.Y @@ -17,16 +17,6 @@ CF_DEFINES #define KIF_IFACE ((struct kif_iface_config *) this_ipatt) static void -krt_set_merge_paths(struct channel_config *cc, uint merge, uint limit) -{ - if ((limit <= 0) || (limit > 255)) - cf_error("Merge paths limit must be in range 1-255"); - - cc->ra_mode = merge ? RA_MERGED : RA_OPTIMAL; - cc->merge_limit = limit; -} - -static void kif_set_preferred(ip_addr ip) { if (ipa_is_ip4(ip)) @@ -78,10 +68,9 @@ kern_item: cf_error("Learning of kernel routes not supported on this platform"); #endif } - | DEVICE ROUTES bool { THIS_KRT->devroutes = $3; } | GRACEFUL RESTART bool { THIS_KRT->graceful_restart = $3; } | MERGE PATHS bool kern_mp_limit { - krt_set_merge_paths(this_channel, $3, $4); + THIS_KRT->merge_paths = $3 ? $4 : 0; #ifndef KRT_ALLOW_MERGE_PATHS if ($3) cf_error("Path merging not supported on this platform"); diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 29d2d01e..b4fb1967 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -506,7 +506,13 @@ static void krt_learn_init(struct krt_proto *p) { if (KRT_CF->learn) - rt_setup(p->p.pool, &p->krt_table, "Inherited", NULL); + { + struct rtable_config *cf = mb_allocz(p->p.pool, sizeof(struct rtable_config)); + cf->name = "Inherited"; + cf->addr_type = p->p.net_type; + + rt_setup(p->p.pool, &p->krt_table, cf); + } } static void @@ -578,7 +584,7 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa) if (filter == FILTER_ACCEPT) goto accept; - if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR) > F_ACCEPT) + if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR | FF_SILENT) > F_ACCEPT) goto reject; @@ -1059,11 +1065,18 @@ krt_postconfig(struct proto_config *CF) cf_error("All kernel syncers must use the same table scan interval"); #endif - struct rtable_config *tab = proto_cf_main_channel(CF)->table; + struct channel_config *cc = proto_cf_main_channel(CF); + struct rtable_config *tab = cc->table; if (tab->krt_attached) cf_error("Kernel syncer (%s) already attached to table %s", tab->krt_attached->name, tab->name); tab->krt_attached = CF; + if (cf->merge_paths) + { + cc->ra_mode = RA_MERGED; + cc->merge_limit = cf->merge_paths; + } + krt_sys_postconfig(cf); } @@ -1095,10 +1108,11 @@ krt_start(struct proto *P) switch (p->p.net_type) { - case NET_IP4: p->af = AF_INET; break; - case NET_IP6: p->af = AF_INET6; break; + case NET_IP4: p->af = AF_INET; break; + case NET_IP6: p->af = AF_INET6; break; + case NET_IP6_SADR: p->af = AF_INET6; break; #ifdef AF_MPLS - case NET_MPLS: p->af = AF_MPLS; break; + case NET_MPLS: p->af = AF_MPLS; break; #endif default: log(L_ERR "KRT: Tried to start with strange net type: %d", p->p.net_type); return PS_START; break; } @@ -1159,7 +1173,7 @@ krt_reconfigure(struct proto *p, struct proto_config *CF) return 0; /* persist, graceful restart need not be the same */ - return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes; + return o->scan_time == n->scan_time && o->learn == n->learn; } struct proto_config * @@ -1206,16 +1220,24 @@ krt_get_attr(eattr *a, byte *buf, int buflen) } +#ifdef CONFIG_IP6_SADR_KERNEL +#define MAYBE_IP6_SADR NB_IP6_SADR +#else +#define MAYBE_IP6_SADR 0 +#endif + +#ifdef HAVE_MPLS_KERNEL +#define MAYBE_MPLS NB_MPLS +#else +#define MAYBE_MPLS 0 +#endif + struct protocol proto_unix_kernel = { .name = "Kernel", .template = "kernel%d", .attr_class = EAP_KRT, .preference = DEF_PREF_INHERITED, -#ifdef HAVE_MPLS_KERNEL - .channel_mask = NB_IP | NB_MPLS, -#else - .channel_mask = NB_IP, -#endif + .channel_mask = NB_IP | MAYBE_IP6_SADR | MAYBE_MPLS, .proto_size = sizeof(struct krt_proto), .config_size = sizeof(struct krt_config), .preconfig = krt_preconfig, diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 3bfccfc2..b627882d 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -49,8 +49,8 @@ struct krt_config { btime scan_time; /* How often we re-scan routes */ int persist; /* Keep routes when we exit */ int learn; /* Learn routes from other sources */ - int devroutes; /* XXX: remove */ int graceful_restart; /* Regard graceful restart recovery */ + int merge_paths; /* Exported routes are merged for ECMP */ }; struct krt_proto { |