15 #include <linux/string.h>
16 #include <linux/net.h>
17 #include <linux/socket.h>
18 #include <linux/slab.h>
22 #include <linux/netlink.h>
23 #include <linux/rtnetlink.h>
25 #include <linux/netdevice.h>
29 #include <asm/uaccess.h>
49 #define DZ_HASHMASK(dz) ((dz)->dz_hashmask)
52 #define DZ_MASK(dz) ((dz)->dz_mask)
61 #define dz_key_0(key) ((key).datum = 0)
63 #define for_nexthops(fi) { int nhsel; const struct dn_fib_nh *nh;\
64 for(nhsel = 0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
66 #define endfor_nexthops(fi) }
68 #define DN_MAX_DIVISOR 1024
70 #define DN_S_ACCESSED 2
72 #define DN_FIB_SCAN(f, fp) \
73 for( ; ((f) = *(fp)) != NULL; (fp) = &(f)->fn_next)
75 #define DN_FIB_SCAN_KEY(f, fp, key) \
76 for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next)
78 #define RT_TABLE_MIN 1
79 #define DN_FIB_TABLE_HASHSZ 256
84 static int dn_fib_hash_zombies;
122 static inline void dn_rebuild_zone(
struct dn_zone *dz,
129 for(i = 0; i < old_divisor; i++) {
130 for(f = old_ht[i];
f; f =
next) {
132 for(fp = dn_chain_p(f->
fn_key, dz);
133 *fp && dn_key_leq((*fp)->fn_key, f->
fn_key);
142 static void dn_rehash_zone(
struct dn_zone *dz)
145 int old_divisor, new_divisor;
150 switch (old_divisor) {
160 new_hashmask = 0x3FF;
173 dn_rebuild_zone(dz, old_ht, old_divisor);
207 dz->
dz_mask = dnet_make_mask(z);
209 for(i = z + 1; i <= 16; i++)
249 int attrlen = nhlen -
sizeof(
struct rtnexthop);
252 if (attrlen < 0 || (nhlen -= nhp->
rtnh_len) < 0)
259 if (gw && gw != nh->nh_gw)
268 static inline size_t dn_fib_nlmsg_size(
struct dn_fib_info *fi)
276 payload += nla_total_size((
RTAX_MAX * nla_total_size(4)));
282 size_t nhsize = nla_total_size(
sizeof(
struct rtnexthop));
285 nhsize += nla_total_size(4);
288 payload += nla_total_size(fi->
fib_nhs * nhsize);
301 nlh = nlmsg_put(skb, portid, seq, event,
sizeof(*rtm), flags);
305 rtm = nlmsg_data(nlh);
316 if (nla_put_u32(skb,
RTA_TABLE, tb_id) < 0)
359 nhp->
rtnh_len = skb_tail_pointer(skb) - (
unsigned char *)nhp;
362 nla_nest_end(skb, mp_head);
365 return nlmsg_end(skb, nlh);
368 nlmsg_cancel(skb, nlh);
373 static void dn_rtmsg_fib(
int event,
struct dn_fib_node *f,
int z,
u32 tb_id,
384 err = dn_fib_dump_info(skb, portid, nlh->
nlmsg_seq, event, tb_id,
409 for(i = 0;
f; i++, f = f->
fn_next) {
419 f->fn_scope, &f->fn_key, dz->
dz_order,
444 if (dn_hash_dump_bucket(skb, cb, tb, dz, dz->
dz_hash[h]) < 0) {
468 if (dn_hash_dump_zone(skb, cb, tb, dz) < 0) {
482 struct net *
net = sock_net(skb->
sk);
484 unsigned int e = 0, s_e;
506 2 *
sizeof(cb->
args[0]));
507 if (tb->
dump(tb, skb, cb) < 0)
536 if (!dz && !(dz = dn_new_zone(table, z)))
545 key = dz_key(dst, dz);
556 fp = dn_chain_p(
key, dz);
559 if (dn_key_leq(
key, f->fn_key))
566 dn_key_eq(f->fn_key,
key)) {
578 if (f && dn_key_eq(f->fn_key,
key) &&
599 if (f->fn_type == type &&
618 new_f = kmem_cache_zalloc(dn_hash_kmem,
GFP_KERNEL);
636 *del_fp = f->fn_next;
680 key = dz_key(dst, dz);
683 fp = dn_chain_p(
key, dz);
686 if (dn_key_eq(f->fn_key,
key))
688 if (dn_key_leq(
key, f->fn_key))
702 if (del_fp ==
NULL &&
707 dn_fib_nh_match(r, n, rta, fi) == 0)
717 *del_fp = f->fn_next;
730 if (++dn_fib_hash_zombies > 128)
740 static inline int dn_flush_list(
struct dn_fib_node **fp,
int z,
struct dn_hash *table)
745 while((f = *fp) !=
NULL) {
769 dn_fib_hash_zombies = 0;
793 for(f = dz_chain(k, dz);
f; f = f->
fn_next) {
794 if (!dn_key_eq(k, f->
fn_key)) {
795 if (dn_key_leq(k, f->
fn_key))
806 if (f->
fn_scope < flp->flowidn_scope)
842 hlist_for_each_entry_rcu(t, node, &dn_fib_table_hash[h],
hlist) {
864 t->
insert = dn_fib_table_insert;
865 t->
delete = dn_fib_table_delete;
866 t->
lookup = dn_fib_table_lookup;
867 t->
flush = dn_fib_table_flush;
868 t->
dump = dn_fib_table_dump;
869 hlist_add_head_rcu(&t->
hlist, &dn_fib_table_hash[h]);
893 flushed += tb->
flush(tb);
918 hlist_del(&t->
hlist);