Commit d14f8c3c authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka

Netlink: MPLS routes in kernel

Anyway, Bird is now capable to insert both MPLS routes and MPLS encap
routes into kernel.

It was (among others) needed to define platform-specific AF_MPLS to 28
as this constant has been assigned in the linux kernel.

No support for BSD now, it may be added in the future.
parent f2010f9c
......@@ -270,7 +270,7 @@ net_or_ipa:
label_stack_start: NUM
{
$$ = cfg_allocz(sizeof(u32) * (NEXTHOP_MAX_LABEL_STACK+1));
$$ = cfg_allocz(sizeof(u32) * (MPLS_MAX_LABEL_STACK+1));
$$[0] = 1;
$$[1] = $1;
};
......@@ -278,7 +278,7 @@ label_stack_start: NUM
label_stack:
label_stack_start
| label_stack '/' NUM {
if ($1[0] >= NEXTHOP_MAX_LABEL_STACK)
if ($1[0] >= MPLS_MAX_LABEL_STACK)
cf_error("Too many labels in stack.");
$1[++$1[0]] = $3;
$$ = $1;
......
......@@ -325,6 +325,28 @@ static inline ip6_addr ip6_hton(ip6_addr a)
static inline ip6_addr ip6_ntoh(ip6_addr a)
{ return _MI6(ntohl(_I0(a)), ntohl(_I1(a)), ntohl(_I2(a)), ntohl(_I3(a))); }
#define MPLS_MAX_LABEL_STACK 8
static inline int
mpls_get(const char *buf, int buflen, u32 *stack)
{
for (int i=0; (i<MPLS_MAX_LABEL_STACK) && (i*4+3 < buflen); i++)
{
u32 s = get_u32(buf + i*4);
stack[i] = s >> 12;
if (s & 0x100)
return i+1;
}
return -1;
}
static inline int
mpls_put(char *buf, int len, u32 *stack)
{
for (int i=0; i<len; i++)
put_u32(buf + i*4, stack[i] << 12 | (i+1 == len ? 0x100 : 0));
return len*4;
}
/*
* Unaligned data access (in network order)
......
......@@ -225,7 +225,8 @@ net_classify(const net_addr *N)
case NET_FLOW6:
return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6.prefix);
/* classify probably not needed for NET_MPLS */
case NET_MPLS:
return IADDR_HOST | SCOPE_UNIVERSE;
}
return IADDR_INVALID;
......
......@@ -259,6 +259,14 @@ static inline ip_addr net_prefix(const net_addr *a)
}
}
static inline u32 net_mpls(const net_addr *a)
{
if (a->type == NET_MPLS)
return ((net_addr_mpls *) a)->label;
bug("Can't call net_mpls on non-mpls net_addr");
}
static inline uint net4_pxlen(const net_addr *a)
{ return a->pxlen; }
......
......@@ -512,8 +512,7 @@ uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */
ea_list *ea_append(ea_list *to, ea_list *what);
void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
#define NEXTHOP_MAX_LABEL_STACK 8
#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK)
#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
static inline size_t nexthop_size(const struct nexthop *nh)
{ return sizeof(struct nexthop) + sizeof(u32)*nh->labels; }
......@@ -528,7 +527,7 @@ int nexthop_is_sorted(struct nexthop *x);
void rta_init(void);
static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a->nh.labels; }
#define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK)
#define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */
static inline int rta_is_cached(rta *r) { return r->aflags & RTAF_CACHED; }
static inline rta *rta_clone(rta *r) { r->uc++; return r; }
......
......@@ -1279,12 +1279,12 @@ rta_init(void)
rta_slab_[0] = sl_new(rta_pool, sizeof(rta));
rta_slab_[1] = sl_new(rta_pool, sizeof(rta) + sizeof(u32));
rta_slab_[2] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*2);
rta_slab_[3] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK);
rta_slab_[3] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK);
nexthop_slab_[0] = sl_new(rta_pool, sizeof(struct nexthop));
nexthop_slab_[1] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32));
nexthop_slab_[2] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*2);
nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK);
nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK);
rta_alloc_hash();
rte_src_init();
......
......@@ -2487,7 +2487,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
tm, from, primary ? (sync_error ? " !" : " *") : "", info);
for (nh = &(a->nh); nh; nh = nh->next)
{
char ls[NEXTHOP_MAX_LABEL_STACK*8 + 5]; char *lsp = ls;
char ls[MPLS_MAX_LABEL_STACK*8 + 5]; char *lsp = ls;
if (nh->labels)
{
lsp += bsprintf(lsp, " mpls %d", nh->label[0]);
......
......@@ -21,6 +21,10 @@
#define CONFIG_INCLUDE_SYSPRIV_H "sysdep/linux/syspriv.h"
#ifndef AF_MPLS
#define AF_MPLS 28
#endif
/*
Link: sysdep/linux
Link: sysdep/unix
......
This diff is collapsed.
......@@ -1153,7 +1153,8 @@ krt_start(struct proto *P)
{
case NET_IP4: p->af = AF_INET; break;
case NET_IP6: p->af = AF_INET6; break;
default: ASSERT(0);
case NET_MPLS: p->af = AF_MPLS; break;
default: log(L_ERR "KRT: Tried to start with strange net type: %d", p->p.net_type); return PS_START; break;
}
add_tail(&krt_proto_list, &p->krt_node);
......@@ -1264,7 +1265,7 @@ struct protocol proto_unix_kernel = {
.template = "kernel%d",
.attr_class = EAP_KRT,
.preference = DEF_PREF_INHERITED,
.channel_mask = NB_IP,
.channel_mask = NB_IP | NB_MPLS,
.proto_size = sizeof(struct krt_proto),
.config_size = sizeof(struct krt_config),
.preconfig = krt_preconfig,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment