Commit ee3256fe authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Multiprotocol core support.

The patch from Alexander V. Chernikov.
parent 35c875f0
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ AC_ARG_ENABLE(debug,[ --enable-debug enable internal debugging routine
AC_ARG_ENABLE(memcheck,[  --enable-memcheck       check memory allocations when debugging (default: enabled)],,enable_memcheck=yes)
AC_ARG_ENABLE(client,[  --enable-client         enable building of BIRD client (default: enabled)],,enable_client=yes)
AC_ARG_ENABLE(ipv6,[  --enable-ipv6           enable building of IPv6 version (default: disabled)],,enable_ipv6=no)
AC_ARG_ENABLE(mpls,[  --enable-mpls           enable building MPLS version (default: disabled)],,enable_mpls=no)
AC_ARG_WITH(sysconfig,[  --with-sysconfig=FILE   use specified BIRD system configuration file])
AC_ARG_WITH(protocols,[  --with-protocols=LIST   include specified routing protocols (default: all)],,[with_protocols="all"])
AC_ARG_WITH(sysinclude,[  --with-sysinclude=PATH  search for system includes on specified place])
@@ -50,6 +51,12 @@ else
	all_protocols=bgp,ospf,pipe,rip,static
fi

if test "$enable_mpls" = yes ; then
	AC_DEFINE(MPLS)
	AC_DEFINE(MPLS_VPN)
#	all_protocols="$all_protocols",ldp
fi

if test "$with_protocols" = all ; then
	with_protocols="$all_protocols"
fi
+1 −1
Original line number Diff line number Diff line
@@ -804,7 +804,7 @@ interpret(struct f_inst *what)
      case T_STRING:	/* Warning: this is a special case for proto attribute */
	res.val.s = rta->proto->name;
	break;
      case T_PREFIX:	/* Warning: this works only for prefix of network */
      case T_PREFIX:	/* Warning: this works only for RT_IP prefix of network */
	{
	  res.val.px.ip = (*f_rte)->net->n.prefix;
	  res.val.px.len = (*f_rte)->net->n.pxlen;
+2 −0
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@ ipv6.h
ipv4.c
ipv4.h
#endif
addrs.c
addrs.h
lists.c
lists.h
md5.c

lib/addrs.c

0 → 100644
+293 −0
Original line number Diff line number Diff line
/*
 *	BIRD Library -- Address Manipulation Functions
 *
 *	(c) 2011 Alexander V. Chernikov <melifaro@ipfw.ru>
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "nest/bird.h"
#include "nest/route.h"
#include "lib/ip.h"
#include "lib/string.h"
#include "lib/addrs.h"

#define PBUFS	4
#define PSIZE	50

/**
 * fn_print - prints a FIB node
 * @n: pointer to fib_node structure
 *
 * This function prints fib node address to static buffer and
 * returns it to the caller. Up to PBUFS(4) different buffers are
 * available.
 */
char *
fn_print(struct fib_node *n)
{
  char *x;
  int res;

  switch (n->addr_type)
  {
    case RT_IPV4:
    case RT_IPV6:
    case RT_VPNV4:
    case RT_VPNV6:
      x = addr_print(n->addr_type, FPREFIX(n), &res);
      bsnprintf(x + res, 5, "/%d", n->pxlen);
      break;

    default:
      x = addr_print(n->addr_type, FPREFIX(n), &res);
  }

  return x;
}

/**
 * addr_print - prints address of given type into static buffer
 * @rtype: address type
 * @addr: pointer to address data
 * @len: pointer to save printed address length to. Can be NULL
 *
 * This function prints address int human-readable format to static buffer
 * and returns it to the caller. Up to PBUFS(4) different buffers are
 * available.
 */
char *
addr_print(int rtype, void *addr, int *len)
{
  static int cntr;
  static char buf[PBUFS][PSIZE];
  char *x;
  int res = 0;
  ip4_addr v4;
  ip6_addr v6;
#ifdef MPLS_VPN
  vpn4_addr *pv4;
  vpn6_addr *pv6;
#endif

  x = buf[cntr++ % PBUFS];

  /* 
   * XXX: converting address to network format and 
   * printing it after that is rather complex.
   * However, printing IPv6 address without inet_ntop
   * is not so easy, too
   */
  switch (rtype)
  {
    case RT_IPV4:
      put_addr(&v4, rtype, addr);
      inet_ntop(AF_INET, &v4, x, PSIZE);
      break;

    case RT_IPV6:
      put_addr(&v6, rtype, addr);
      inet_ntop(AF_INET6, &v6, x, PSIZE);
      break;
#ifdef MPLS_VPN
    case RT_VPNV4:
      pv4 = (vpn4_addr *)addr;
      res = addr_print_rd(pv4->rd, x, PSIZE);
      *(x + res++) = ' ';
      put_addr(&v4, RT_IPV4, &pv4->addr);
      inet_ntop(AF_INET, &v4, x + res, PSIZE - res);
      break;

    case RT_VPNV6:
      pv6 = (vpn6_addr *)addr;
      res = addr_print_rd(pv6->rd, x, PSIZE);
      *(x + res++) = ' ';
      put_addr(&v6, RT_IPV6, &pv6->addr);
      inet_ntop(AF_INET6, &v6, x + res, PSIZE - res);
      break;
#endif

    default:
      res = bsnprintf(x, PSIZE, "RT:%d", rtype);
  }

  if (len)
    *len = strlen(x);

  return x;
}

#ifdef MPLS_VPN
/**
 * addr_print_rd - prints route distinguisher into supplied buffer
 * @rd: route distinguisher (host format)
 * @addr: pointer to destination buffer
 * @len: buffer length
 *
 * This function prints RD in human-readable format
 */
int
addr_print_rd(u64 rd, char *buf, int buflen)
{
  int res = 0;
  u32 v4;

  switch (rd >> 48)
  {
    case 0:
      /* 2-byte asn id : 4-byte vpn id */
      res = snprintf(buf, buflen, "%d:%u", (int)((rd >> 32) & 0xFFFF), (u32)(rd & 0xFFFFFFFF));
      break;
    case 1:
      /* 4-byte IPv4 id : 2-byte vpn id */
      v4 = (u32)(rd >> 16);
      res = snprintf(buf, buflen, "%s:%d", addr_print(RT_IPV4, &v4, NULL), (int)(rd >> 48));
      break;
    case 2:
      /* 4-byte asn id : 2-byte vpn id */
      v4 = (u32)(rd >> 16);
      res = snprintf(buf, buflen, "%u:%d", v4, (int)(rd >> 48));
      break;
  }

  return res;
}

#endif

#ifdef MPLS_VPN
void inline
get_vpn4(void *addrdata, vpn4_addr *addr)
{
  addr->rd = ((u64)get_u32(addrdata) << 32) + get_u32(addrdata + 4);
  addr->addr = get_u32(addrdata + 8);
}

void inline
get_vpn6(void *addrdata, vpn6_addr *addr)
{
  int i;
  u32 *old, *new;

  addr->rd = ((u64)get_u32(addrdata) << 32) + get_u32(addrdata + 4);
  old = addrdata + 8;
  new = (u32 *)&addr->addr;
  for (i = 0; i < 4; i++, old++, new++)
    *new = get_u32(old);
}

void inline
put_vpn4(void *addrdata, vpn4_addr *addr)
{
  u32 *v4;
  /* Put RD */
  put_u32(addrdata, (u32)(addr->rd >> 32));
  put_u32(addrdata + 4, (u32)(addr->rd & 0xFFFFFFFF));
  /* Put IPv4 addr */
  v4 = (u32 *)&addr->addr;
  put_u32(addrdata + 8, *v4);
}

void inline
put_vpn6(void *addrdata, vpn6_addr *addr)
{
  int i;
  u32 *old, *new;
  /* Put RD */
  put_u32(addrdata, (u32)(addr->rd >> 32));
  put_u32(addrdata + 4, (u32)(addr->rd & 0xFFFFFFFF));
  /* Put IPv6 addr */
  new = addrdata + 8;
  old = (u32 *)&addr->addr;
  for (i = 0; i < 4; i++, old++, new++)
    put_u32(new, *old);
}
#endif

/**
 * get_addr - converts address to host presentation
 * @addrdata: pointer to network (source) data buffer
 * @rt_family: address family
 * @datanew: pointer to host data buffer
 *
 * Convert address in @rt_family family from network 
 * to host format. @addrdata can be unaligned.
 */
void
get_addr(void *addrdata, int rt_family, void *datanew)
{
  int i;
  u32 *old, *new;

  switch (rt_family)
  {
    case RT_IPV4:
      new = datanew;
      *new = get_u32(addrdata);
      break;

    case RT_IPV6:
      old = addrdata;
      new = datanew;
      for (i = 0; i < 4; i++, old++, new++)
      	*new = get_u32(old);
      break;
#ifdef MPLS_VPN
    case RT_VPNV4:
      get_vpn4(addrdata, (vpn4_addr *)datanew);
      break;

    case RT_VPNV6:
      get_vpn6(addrdata, (vpn6_addr *)datanew);
      break;
#endif
  }
}

/**
 * put_addr - converts address to network presentation
 * @datanew: pointer to network data buffer
 * @rt_family: address family
 * @addrdata: pointer to host data buffer
 *
 * Convert address in @rt_family family from host
 * to network format. @datanew can be unaligned.
 */
void
put_addr(void *datanew, int rt_family, void *addrdata)
{
  int i;
  uint32_t *old, *new;
  switch (rt_family)
  {
    case RT_IPV4:
      old = (uint32_t *)addrdata;
      put_u32(datanew, *old);
      break;

    case RT_IPV6:
      old = addrdata;
      new = datanew;
      for (i = 0; i < 4; i++, old++, new++)
      	put_u32(new, *old);
      break;
#ifdef MPLS_VPN
    case RT_VPNV4:
      put_vpn4(datanew, (vpn4_addr *)addrdata);
      break;

    case RT_VPNV6:
      put_vpn6(datanew, (vpn6_addr *)addrdata);
      break;
#endif
  }
}

lib/addrs.h

0 → 100644
+78 −0
Original line number Diff line number Diff line
/*
 *	BIRD Internet Routing Daemon -- The Internet Protocol
 *
 *	(c) 2011 Alexander V. Chernikov <melifaro@ipfw.ru>
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#ifndef _BIRD_ADDRS_H_
#define _BIRD_ADDRS_H_

/* Build ip4_addr and ip6_addr on top of existing types to support existing macro */
#ifdef DEBUGGING

#ifndef IPV6
typedef struct ipv6_addr {
  u32 addr[4];
} ip6_addr;
typedef ip_addr ip4_addr;
#else
typedef struct ipv4_addr {
  u32 addr;
} ip4_addr;
typedef ip_addr ip6_addr;
#endif

#else	/* ! DEBUGGING */

typedef uint64_t u64;

#ifndef IPV6
typedef struct ipv6_addr {
  u32 addr[4];
} ip6_addr;
typedef ip_addr ip4_addr;
#else
typedef u32 ip4_addr;
typedef ip_addr ip6_addr;
#endif

#endif	/* DEBUGGING */

#ifdef MPLS_VPN
typedef struct vpn4_addr {
	u64		rd;
	ip4_addr	addr;
} vpn4_addr;

typedef struct vpn6_addr {
	u64		rd;
	ip6_addr	addr;
} vpn6_addr;

#ifndef IPV6
typedef vpn4_addr vpn_addr;
#else
typedef vpn6_addr vpn_addr;
#endif

#endif

struct fib_node;

#ifdef MPLS_VPN
int addr_print_rd(u64 rd, char *buf, int buflen);
void get_vpn4(void *addrdata, vpn4_addr *newv4);
void get_vpn6(void *addrdata, vpn6_addr *newv6);
void put_vpn4(void *addrdata, vpn4_addr *addr);
void put_vpn6(void *addrdata, vpn6_addr *addr);
#endif
void get_addr(void *addrdata, int rt_family, void *datanew);
void put_addr(void *datanew, int rt_family, void *addrdata);

char *addr_print(int rtype, void *addr, int *len);
char *fn_print(struct fib_node *f);	/* Prints human-readable fib_node prefix */

#endif
Loading