Commit 91d466ec authored by Ondřej Zajíček's avatar Ondřej Zajíček
Browse files

Minor changes in multiprotocol core support.

The patch from Alexander V. Chernikov.
parent adaa289c
......@@ -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;
......
......@@ -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
......@@ -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;
......
......@@ -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;
......
......@@ -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 ipa_hash(*((ip_addr *)a)) >> f->hash_shift;
}
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
......
......@@ -855,10 +855,18 @@ rt_event(void *ptr)
rt_prune(tab);
}
/**
* rt_addrsize - returns (host format) size of address of given type
* @addr_type: address type
*
* Returns sizeof() appropriate structure or sizeof(ip_addr) if
* address type is unknown
*
*/
int
rt_addrsize(int rtype)
rt_addrsize(int addr_type)
{
switch (rtype)
switch (addr_type)
{
#ifdef MPLS_VPN
case RT_VPNV4:
......@@ -884,9 +892,27 @@ rt_addrsize(int rtype)
void
rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
{
fib_hash_func f;
bzero(t, sizeof(*t));
t->rtype = cf ? cf->rtype : RT_IP;
fib2_init(&t->fib, p, sizeof(net), t->rtype, rt_addrsize(t->rtype), 0, rte_init, NULL);
t->addr_type = cf ? cf->addr_type : RT_IP;
/* Select hashing function depending on table type */
switch (t->addr_type)
{
case RT_IP:
f = ip_hash;
break;
case RT_VPN:
f = vpn_hash;
break;
default:
f = ip_hash;
break;
}
fib2_init(&t->fib, p, sizeof(net), t->addr_type, rt_addrsize(t->addr_type), 0, rte_init, f);
t->name = name;
t->config = cf;
init_list(&t->hooks);
......@@ -1132,13 +1158,13 @@ rt_next_hop_update(rtable *tab)
struct rtable_config *
rt_new_table(struct symbol *s, int rtype)
rt_new_table(struct symbol *s, int addr_type)
{
struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
cf_define_symbol(s, SYM_TABLE, c);
c->name = s->name;
c->rtype = rtype;
c->addr_type = addr_type;
add_tail(&new_config->tables, &c->n);
c->gc_max_ops = 1000;
c->gc_min_time = 5;
......@@ -1662,7 +1688,7 @@ rt_find_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep)
void
rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_addr *ll)
{
if (tab->rtype != RT_IP)
if (tab->addr_type != RT_IP)
return;
rta_apply_hostentry(a, rt_find_hostentry(tab, *gw, *ll, dep));
......@@ -1690,7 +1716,7 @@ rt_format_via(rte *e, byte *via)
}
static void
rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
rt_show_rte(struct cli *c, byte *prefix, rte *e, struct rt_show_data *d, ea_list *tmpa)
{
byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+8];
byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
......@@ -1717,7 +1743,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
a->proto->proto->get_route_info(e, info, tmpa);
else
bsprintf(info, " (%d)", e->pref);
cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", ia, via, a->proto->name,
cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", prefix, via, a->proto->name,
tm, from, primary ? " *" : "", info);
for (nh = a->nexthops; nh; nh = nh->next)
cli_printf(c, -1007, "\tvia %I on %s weight %d", nh->gw, nh->iface->name, nh->weight + 1);
......@@ -1730,7 +1756,9 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{
rte *e, *ee;
int ok;
byte prefix[MAX_ADDRESS_P_LENGTH];
fn_print(prefix, sizeof(prefix), &n->n);
if (n->routes)
d->net_counter++;
for(e=n->routes; e; e=e->next)
......@@ -1766,7 +1794,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{
d->show_counter++;
if (d->stats < 2)
rt_show_rte(c, fn_print(&n->n), e, d, tmpa);
rt_show_rte(c, prefix, e, d, tmpa);
prefix[0] = '\0';
}
if (e != ee)
{
......
Supports Markdown
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