Commit 91d466ec authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Minor changes in multiprotocol core support.

The patch from Alexander V. Chernikov.
parent adaa289c
Loading
Loading
Loading
Loading
+29 −48
Original line number Diff line number Diff line
@@ -20,56 +20,44 @@
#include "lib/string.h"
#include "lib/addrs.h"

#define PBUFS	4
#define PSIZE	50

/**
 * fn_print - prints a FIB node
 * @buf: data buffer
 * @buflen: data buffer size
 * @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.
 * This function prints fib node address to supplied buffer.
 */
char *
fn_print(struct fib_node *n)
void
fn_print(char *buf, int buflen, 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);
      addr_print(buf, buflen, n->addr_type, FPREFIX(n));
      bsnprintf(buf + strlen(buf), 5, "/%d", n->pxlen);
      break;

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

  return x;
}

/**
 * addr_print - prints address of given type into static buffer
 * addr_print - prints address of given type into supplied buffer
 * @buf: data buffer
 * @buflen: data buffer size
 * @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.
 * This function prints address into human-readable format.
 */
char *
addr_print(int rtype, void *addr, int *len)
void
addr_print(char *buf, int buflen, int rtype, void *addr)
{
  static int cntr;
  static char buf[PBUFS][PSIZE];
  char *x;
  int res = 0;
  ip4_addr v4;
  ip6_addr v6;
@@ -78,8 +66,6 @@ addr_print(int rtype, void *addr, int *len)
  vpn6_addr *pv6;
#endif

  x = buf[cntr++ % PBUFS];

  /* 
   * XXX: converting address to network format and 
   * printing it after that is rather complex.
@@ -90,52 +76,47 @@ addr_print(int rtype, void *addr, int *len)
  {
    case RT_IPV4:
      put_addr(&v4, rtype, addr);
      inet_ntop(AF_INET, &v4, x, PSIZE);
      inet_ntop(AF_INET, &v4, buf, buflen);
      break;

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

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

    default:
      res = bsnprintf(x, PSIZE, "RT:%d", rtype);
      res = bsnprintf(buf, buflen, "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
 * @rd: route distinguisher (host format)
 *
 * This function prints RD in human-readable format
 * This function prints RD in human-readable format.
 */
int
addr_print_rd(u64 rd, char *buf, int buflen)
addr_print_rd(char *buf, int buflen, u64 rd)
{
  int res = 0;
  u32 key, val;
@@ -212,7 +193,7 @@ put_vpn6(void *addrdata, vpn6_addr *addr)
#endif

/**
 * get_addr - converts address to host presentation
 * get_addr - converts address to host representation
 * @addrdata: pointer to network (source) data buffer
 * @rt_family: address family
 * @datanew: pointer to host data buffer
@@ -264,11 +245,11 @@ void
put_addr(void *datanew, int rt_family, void *addrdata)
{
  int i;
  uint32_t *old, *new;
  u32 *old, *new;
  switch (rt_family)
  {
    case RT_IPV4:
      old = (uint32_t *)addrdata;
      old = addrdata;
      put_u32(datanew, *old);
      break;

+6 −3
Original line number Diff line number Diff line
@@ -57,10 +57,13 @@ typedef vpn6_addr vpn_addr;

#endif

/* Buffer must be sufficient to hold RD(15+6+1) + IPv6 address(39) + prefix(4) = 22+39+4=67 */
#define MAX_ADDRESS_P_LENGTH	70

struct fib_node;

#ifdef MPLS_VPN
int addr_print_rd(u64 rd, char *buf, int buflen);
int addr_print_rd(char *buf, int buflen, u64 rd);
void get_vpn4(void *addrdata, vpn4_addr *newv4);
void get_vpn6(void *addrdata, vpn6_addr *newv6);
void put_vpn4(void *addrdata, vpn4_addr *addr);
@@ -69,8 +72,8 @@ void put_vpn6(void *addrdata, vpn6_addr *addr);
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 */
void addr_print(char *buf, int buflen, int rtype, void *addr);
void fn_print(char *buf, int buflen, struct fib_node *n);

#endif
+2 −2
Original line number Diff line number Diff line
@@ -137,7 +137,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
	u32 x;
	char *str, *start;
	const char *s;
	char ipbuf[STD_ADDRESS_P_LENGTH+1];
	char ipbuf[MAX_ADDRESS_P_LENGTH];

	int flags;		/* flags to number() */

@@ -281,7 +281,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)

		/* Generic address - pointer to fib_node */
		case 'F':
			bsprintf(ipbuf, "%s", fn_print(va_arg(args, struct fib_node *)));
			fn_print(ipbuf, sizeof(ipbuf), va_arg(args, struct fib_node *));
			s = ipbuf;
			goto str;

+12 −7
Original line number Diff line number Diff line
@@ -50,8 +50,9 @@ struct fib_iterator { /* See lib/slists.h for an explanation */
  unsigned int hash;
};

struct fib;
typedef void (*fib_init_func)(struct fib_node *);
typedef int (*fib_hash_func)(void *);
typedef u32 (*fib_hash_func)(struct fib *, void *);

struct fib {
  pool *fib_pool;			/* Pool holding all our data */
@@ -61,8 +62,8 @@ struct fib {
  unsigned int hash_order;		/* Binary logarithm of hash_size */
  unsigned int hash_shift;		/* 16 - hash_log */
  unsigned int addr_type;		/* Type of adresses stored in fib (IPv46, VPNv46, MPLS, etc..)*/
  unsigned int addr_size;		/* size of address specified in entry */
  unsigned int addr_off;		/* value of data offset to be set in fib_node */
  unsigned int addr_size;		/* Size of address data */
  unsigned int addr_off;		/* Address data offset from the structure beginning */
  unsigned int entries;			/* Number of entries */
  unsigned int entries_min, entries_max;/* Entry count limits (else start rehashing) */
  fib_init_func init;			/* Constructor */
@@ -78,11 +79,15 @@ void *fib_route(struct fib *, ip_addr *, int); /* Longest-match routing lookup *
void fib_delete(struct fib *, void *);	/* Remove fib entry */
void fib_free(struct fib *);		/* Destroy the fib */
void fib_check(struct fib *);		/* Consistency check for debugging */
u32 ip_hash(struct fib *f, void *a);	/* Hashing function for RT_IP fib types */
u32 vpn_hash(struct fib *f, void *a);	/* Hashing function for RT_VPN fib types */

void fit_init(struct fib_iterator *, struct fib *); /* Internal functions, don't call */
struct fib_node *fit_get(struct fib *, struct fib_iterator *);
void fit_put(struct fib_iterator *, struct fib_node *);

#define fib_hash(f, a)	(f)->hash_f(f, a)

#define FPREFIX(n)	((void *)(((char *)(n)) + (n)->addr_off))
#define FPREFIX_IP(n)	((ip_addr *)FPREFIX(n))
#define FPREFIX_VPN(n)	((vpn_addr *)FPREFIX(n))
@@ -129,7 +134,7 @@ void fit_put(struct fib_iterator *, struct fib_node *);
struct rtable_config {
  node n;
  char *name;
  int rtype;				/* Type of the table (IPv46, VPNv46, MPLS, etc..)*/
  int addr_type;			/* Type of address data stored in table (IPv46, VPNv46, etc..) */
  struct rtable *table;
  struct proto_config *krt_attached;	/* Kernel syncer attached to this table */
  int gc_max_ops;			/* Maximum number of operations before GC is run */
@@ -140,7 +145,7 @@ typedef struct rtable {
  node n;				/* Node in list of all tables */
  struct fib fib;
  char *name;				/* Name of this table */
  int rtype;				/* Type of the table (IPv46, VPNv46, MPLS, etc..)*/
  int addr_type;			/* Type of address data stored in table (IPv46, VPNv46, etc..) */
  list hooks;				/* List of announcement hooks */
  int pipe_busy;			/* Pipe loop detection */
  int use_count;			/* Number of protocols using this table */
@@ -282,8 +287,8 @@ void rt_dump_all(void);
int rt_feed_baby(struct proto *p);
void rt_feed_baby_abort(struct proto *p);
void rt_prune_all(void);
struct rtable_config *rt_new_table(struct symbol *s, int rtype);
int rt_addrsize(int rtype);
struct rtable_config *rt_new_table(struct symbol *s, int addr_type);
int rt_addrsize(int addr_type);

struct rt_show_data {
  ip_addr prefix;
+11 −17
Original line number Diff line number Diff line
@@ -72,23 +72,17 @@ fib_ht_free(struct fib_node **h)
  mb_free(h);
}

static inline unsigned
fib_hash(struct fib *f, void *a)
u32
ip_hash(struct fib *f, void *a)
{
  u32 *v, x;
  int i;

  if (f->hash_f)
    return f->hash_f(a);

  if (f->addr_type == RT_IP)
  return ipa_hash(*((ip_addr *)a)) >> f->hash_shift;
}

  x = 0;
  for (i = 0, v = (u32 *)a; i < f->addr_size / 4; i++, v++)
    x = x ^ *v;

  return ((x ^ (x >> 16) ^ (x >> 8)) & 0xffff) >> f->hash_shift;
u32
vpn_hash(struct fib *f, void *a)
{
  /* Ignore RD in our calculations for now */
  return ipa_hash(((vpn_addr *)a)->addr) >> f->hash_shift;
}

static void
@@ -111,7 +105,7 @@ fib_dummy_init(struct fib_node *dummy UNUSED)
void
fib_init(struct fib *f, pool *p, unsigned node_size, unsigned hash_order, fib_init_func init)
{
  fib2_init(f, p, node_size, RT_IP, sizeof(ip_addr), hash_order, init, NULL);
  fib2_init(f, p, node_size, RT_IP, sizeof(ip_addr), hash_order, init, ip_hash);
}

/**
@@ -125,7 +119,7 @@ fib_init(struct fib *f, pool *p, unsigned node_size, unsigned hash_order, fib_in
 * @hash_order: initial hash order (a binary logarithm of hash table size), 0 to use default order
 * (recommended)
 * @init: pointer a function to be called to initialize a newly created node
 * @hash_p: optional pointer a function to be called to hash node
 * @hash_p: mandatory pointer a function to be called to hash node
 *
 * This function initializes a newly allocated FIB and prepares it for use. Note node_size
 * cannot exceed 255 bytes for address types not fitting into ip_addr
Loading