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

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
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;
+22 −0
Original line number Diff line number Diff line
@@ -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)
+2 −1
Original line number Diff line number Diff line
@@ -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;
+8 −0
Original line number Diff line number Diff line
@@ -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; }

+2 −3
Original line number Diff line number Diff line
@@ -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; }
Loading