[PATCH 1/2] Add IP6_SADR support to Bird Core
Ondrej Zajicek
santiago at crfreenet.org
Mon Feb 5 15:08:51 CET 2018
On Sat, Feb 03, 2018 at 09:40:56PM +0100, Toke Høiland-Jørgensen wrote:
> This adds support for source-specific IPv6 routes to Bird core. This is
> based on Dean Luga's original patch, with the review comments addressed.
> Sadr support is added to network address parsing in confbase.Y and to
> the kernel protocol on Linux.
First, some general comments:
Put sadr_ip6 variant consistently above mpls variant. There are several
places where it is in reverse.
If you do not object, i would much prefer *_ip6_sadr than *_sadr_ip6
(also in uppercase variants). It will also be consistent with user
visible channel and table keywords for this type.
> -%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
> +%type <net> net_ip4_ net_ip6_ net_sadr_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
> %type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_mpls_
net_sadr_ip6_ should be in <net_ptr> instead of <net>, as net_addr_sadr_ip6
is longer than net_addr, so must be passed as pointer. That fixes the
"Integer expression expected" issue.
> %type <mls> label_stack_start label_stack
>
> @@ -96,7 +96,7 @@ CF_DECLS
> %left '!'
> %nonassoc '.'
>
> -CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS)
> +CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM)
>
> CF_GRAMMAR
>
> @@ -206,6 +206,22 @@ net_ip6_: IP6 '/' NUM
> n->prefix, n->pxlen, ip6_and(n->prefix, ip6_mkmask(n->pxlen)), n->pxlen);
> };
>
> +net_sadr_ip6_: IP6 '/' NUM FROM IP6 '/' NUM
> +{
> + if ($3 > IP6_MAX_PREFIX_LENGTH)
> + cf_error("Invalid prefix length %u", $3);
> +
> + if ($7 > IP6_MAX_PREFIX_LENGTH)
> + cf_error("Invalid prefix length %u", $7);
> +
> + net_fill_sadr_ip6(&($$), $1, $3, $5, $7);
> +
> + net_addr_sadr_ip6 *n = (void *) &($$);
W.r.t. the change from <net> to <net_ptr> it should be:
$$ = cfg_alloc(sizeof(net_addr_sadr_ip6));
net_fill_sadr_ip6($$, $1, $3, $5, $7);
net_addr_sadr_ip6 *n = (void *) $$;
> -net_ip_: net_ip4_ | net_ip6_ ;
> +net_ip_: net_ip4_ | net_ip6_ | net_sadr_ip6_;
Here net_sadr_ip6_ should be separate
> net_vpn_: net_vpn4_ | net_vpn6_ ;
> net_roa_: net_roa4_ | net_roa6_ ;
>
> diff --git a/lib/net.c b/lib/net.c
> index 9335b78f..a2dad51d 100644
> --- a/lib/net.c
> +++ b/lib/net.c
> @@ -14,6 +14,7 @@ const char * const net_label[] = {
> [NET_ROA6] = "roa6",
> [NET_FLOW4] = "flow4",
> [NET_FLOW6] = "flow6",
> + [NET_SADR_IP6] = "sadr6",
"ipv4 sadr" to be consistent with table keywords?
> +typedef struct net_addr_sadr_ip6 {
> + u8 type;
> + u8 dst_pxlen;
> + u16 length;
> + ip6_addr dst_prefix;
> + u32 src_pxlen; // if u8, NET_ADDR_SADR_IP6 would leave non-zero padding
Perhaps we should use s32 so it is promoted to same type as u8?
> +int
> +net_compare_sadr_ip6(const net_addr_sadr_ip6 *a, const net_addr_sadr_ip6 *b)
> +{
> + int dst_cmp = ip6_compare(a->dst_prefix, b->dst_prefix) ?: uint_cmp(a->dst_pxlen, b->dst_pxlen);
> + if (dst_cmp)
> + return dst_cmp;
> + else
> + return ip6_compare(a->src_prefix, b->src_prefix) ?: uint_cmp(a->src_pxlen, b->src_pxlen);
> +}
Seems too complicated. Perhaps just:
{
return
ip6_compare(a->dst_prefix, b->dst_prefix) ?: uint_cmp(a->dst_pxlen, b->dst_pxlen) ?:
ip6_compare(a->src_prefix, b->src_prefix) ?: uint_cmp(a->src_pxlen, b->src_pxlen);
}
> +static inline void *
> +net_route_sadr_ip6(rtable *t, net_addr_sadr_ip6 *n)
IMHO proper way how to implement this is like net_roa_check_ip6() is
done. As nets are hashed by dst, you can use fib_get_chain() to get hash
chain, walk through it and find the best matching src from nodes with the
exact dst of the current iteration, and decrease dst_pxlen in further
iterations if no match.
Also note that in order to net_route is used in 'show route for', you
should add net_sadr_ip6_ to r_args_for grammar in nest/config.Y
> --- a/sysdep/unix/krt.c
> +++ b/sysdep/unix/krt.c
> @@ -1103,7 +1103,9 @@ 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_IP6:
> + case NET_SADR_IP6:
> + p->af = AF_INET6; break;
> #ifdef AF_MPLS
> case NET_MPLS: p->af = AF_MPLS; break;
> #endif
> @@ -1219,9 +1221,9 @@ struct protocol proto_unix_kernel = {
> .attr_class = EAP_KRT,
> .preference = DEF_PREF_INHERITED,
> #ifdef HAVE_MPLS_KERNEL
> - .channel_mask = NB_IP | NB_MPLS,
> + .channel_mask = NB_IP | NB_SADR_IP6 | NB_MPLS,
> #else
> - .channel_mask = NB_IP,
> + .channel_mask = NB_IP | NB_SADR_IP6,
> #endif
SADR is not supported in BSD, channel_mask should reflect mask. There
should be define for CONFIG_SADR_IP6_KERNEL in sysdef/cf/linux.h, and
then in sysdep/unix/krt.c:
#ifdef CONFIG_SADR_IP6_KERNEL
#define MAYBE_SADR_IP6 NB_SADR_IP
#else
#define MAYBE_SADR_IP6 0
#endif
#ifdef HAVE_MPLS_KERNEL
#define MAYBE_MPLS NB_MPLS
#else
#define MAYBE_MPLS 0
#endif
struct protocol proto_unix_kernel = {
...
.channel_mask = NB_IP | MAYBE_SADR_IP6 | MAYBE_MPLS
...
};
--
Elen sila lumenn' omentielvo
Ondrej 'Santiago' Zajicek (email: santiago at crfreenet.org)
OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net)
"To err is human -- to blame it on a computer is even more so."
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <http://trubka.network.cz/pipermail/bird-users/attachments/20180205/b48ac7a8/attachment.sig>
More information about the Bird-users
mailing list