^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * DECnet An implementation of the DECnet protocol suite for the LINUX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * operating system. DECnet is implemented using the BSD Socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * interface as the means of communication with the user level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * DECnet Routing Forwarding Information Base (Routing Tables)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Author: Steve Whitehouse <SteveW@ACM.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Mostly copied from the IPv4 routing code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/sockios.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/route.h> /* RTF_xxx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <net/neighbour.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <net/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <net/tcp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <net/dst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <net/flow.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <net/fib_rules.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <net/dn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <net/dn_route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <net/dn_fib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <net/dn_neigh.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <net/dn_dev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct dn_zone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct dn_zone *dz_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct dn_fib_node **dz_hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int dz_nent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int dz_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u32 dz_hashmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define DZ_HASHMASK(dz) ((dz)->dz_hashmask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int dz_order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) __le16 dz_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define DZ_MASK(dz) ((dz)->dz_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct dn_hash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct dn_zone *dh_zones[17];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct dn_zone *dh_zone_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define dz_key_0(key) ((key).datum = 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define for_nexthops(fi) { int nhsel; const struct dn_fib_nh *nh;\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) for(nhsel = 0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define endfor_nexthops(fi) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define DN_MAX_DIVISOR 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define DN_S_ZOMBIE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define DN_S_ACCESSED 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define DN_FIB_SCAN(f, fp) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) for( ; ((f) = *(fp)) != NULL; (fp) = &(f)->fn_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define DN_FIB_SCAN_KEY(f, fp, key) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define RT_TABLE_MIN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define DN_FIB_TABLE_HASHSZ 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static struct hlist_head dn_fib_table_hash[DN_FIB_TABLE_HASHSZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static DEFINE_RWLOCK(dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static struct kmem_cache *dn_hash_kmem __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int dn_fib_hash_zombies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static inline dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u16 h = le16_to_cpu(key.datum)>>(16 - dz->dz_order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) h ^= (h >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) h ^= (h >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) h &= DZ_HASHMASK(dz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return *(dn_fib_idx_t *)&h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static inline dn_fib_key_t dz_key(__le16 dst, struct dn_zone *dz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dn_fib_key_t k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) k.datum = dst & DZ_MASK(dz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static inline struct dn_fib_node **dn_chain_p(dn_fib_key_t key, struct dn_zone *dz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return &dz->dz_hash[dn_hash(key, dz).datum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static inline struct dn_fib_node *dz_chain(dn_fib_key_t key, struct dn_zone *dz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return dz->dz_hash[dn_hash(key, dz).datum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static inline int dn_key_eq(dn_fib_key_t a, dn_fib_key_t b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return a.datum == b.datum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static inline int dn_key_leq(dn_fib_key_t a, dn_fib_key_t b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return a.datum <= b.datum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static inline void dn_rebuild_zone(struct dn_zone *dz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct dn_fib_node **old_ht,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int old_divisor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct dn_fib_node *f, **fp, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) for(i = 0; i < old_divisor; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for(f = old_ht[i]; f; f = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) next = f->fn_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) for(fp = dn_chain_p(f->fn_key, dz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *fp && dn_key_leq((*fp)->fn_key, f->fn_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) fp = &(*fp)->fn_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* NOTHING */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) f->fn_next = *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *fp = f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void dn_rehash_zone(struct dn_zone *dz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct dn_fib_node **ht, **old_ht;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int old_divisor, new_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u32 new_hashmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) old_divisor = dz->dz_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) switch (old_divisor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) new_divisor = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) new_hashmask = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) printk(KERN_DEBUG "DECnet: dn_rehash_zone: BUG! %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) old_divisor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case 256:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) new_divisor = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) new_hashmask = 0x3FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ht = kcalloc(new_divisor, sizeof(struct dn_fib_node*), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (ht == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) write_lock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) old_ht = dz->dz_hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) dz->dz_hash = ht;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) dz->dz_hashmask = new_hashmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) dz->dz_divisor = new_divisor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) dn_rebuild_zone(dz, old_ht, old_divisor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) write_unlock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) kfree(old_ht);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static void dn_free_node(struct dn_fib_node *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dn_fib_release_info(DN_FIB_INFO(f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) kmem_cache_free(dn_hash_kmem, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static struct dn_zone *dn_new_zone(struct dn_hash *table, int z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct dn_zone *dz = kzalloc(sizeof(struct dn_zone), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (!dz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (z) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) dz->dz_divisor = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) dz->dz_hashmask = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) dz->dz_divisor = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) dz->dz_hashmask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) dz->dz_hash = kcalloc(dz->dz_divisor, sizeof(struct dn_fib_node *), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!dz->dz_hash) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) kfree(dz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) dz->dz_order = z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) dz->dz_mask = dnet_make_mask(z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) for(i = z + 1; i <= 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (table->dh_zones[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) write_lock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (i>16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) dz->dz_next = table->dh_zone_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) table->dh_zone_list = dz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) dz->dz_next = table->dh_zones[i]->dz_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) table->dh_zones[i]->dz_next = dz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) table->dh_zones[z] = dz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) write_unlock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return dz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct nlattr *attrs[], struct dn_fib_info *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct rtnexthop *nhp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int nhlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (attrs[RTA_PRIORITY] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) nla_get_u32(attrs[RTA_PRIORITY]) != fi->fib_priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (attrs[RTA_OIF] || attrs[RTA_GATEWAY]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if ((!attrs[RTA_OIF] || nla_get_u32(attrs[RTA_OIF]) == fi->fib_nh->nh_oif) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) (!attrs[RTA_GATEWAY] || nla_get_le16(attrs[RTA_GATEWAY]) != fi->fib_nh->nh_gw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (!attrs[RTA_MULTIPATH])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) nhp = nla_data(attrs[RTA_MULTIPATH]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) nhlen = nla_len(attrs[RTA_MULTIPATH]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) for_nexthops(fi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int attrlen = nhlen - sizeof(struct rtnexthop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) __le16 gw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (attrlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct nlattr *gw_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) gw = gw_attr ? nla_get_le16(gw_attr) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (gw && gw != nh->nh_gw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) nhp = RTNH_NEXT(nhp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) } endfor_nexthops(fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static inline size_t dn_fib_nlmsg_size(struct dn_fib_info *fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) + nla_total_size(4) /* RTA_TABLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) + nla_total_size(2) /* RTA_DST */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) + nla_total_size(4) /* RTA_PRIORITY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) + nla_total_size(TCP_CA_NAME_MAX); /* RTAX_CC_ALGO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* space for nested metrics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (fi->fib_nhs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* Also handles the special case fib_nhs == 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /* each nexthop is packed in an attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) size_t nhsize = nla_total_size(sizeof(struct rtnexthop));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* may contain a gateway attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) nhsize += nla_total_size(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* all nexthops are packed in a nested attribute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) payload += nla_total_size(fi->fib_nhs * nhsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static int dn_fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u32 tb_id, u8 type, u8 scope, void *dst, int dst_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct dn_fib_info *fi, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) struct rtmsg *rtm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct nlmsghdr *nlh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) nlh = nlmsg_put(skb, portid, seq, event, sizeof(*rtm), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (!nlh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) rtm = nlmsg_data(nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) rtm->rtm_family = AF_DECnet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) rtm->rtm_dst_len = dst_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) rtm->rtm_src_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) rtm->rtm_tos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) rtm->rtm_table = tb_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) rtm->rtm_flags = fi->fib_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) rtm->rtm_scope = scope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) rtm->rtm_type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) rtm->rtm_protocol = fi->fib_protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (nla_put_u32(skb, RTA_TABLE, tb_id) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (rtm->rtm_dst_len &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) nla_put(skb, RTA_DST, 2, dst) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (fi->fib_priority &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (fi->fib_nhs == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (fi->fib_nh->nh_gw &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) nla_put_le16(skb, RTA_GATEWAY, fi->fib_nh->nh_gw) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (fi->fib_nh->nh_oif &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) nla_put_u32(skb, RTA_OIF, fi->fib_nh->nh_oif) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (fi->fib_nhs > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct rtnexthop *nhp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct nlattr *mp_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) mp_head = nla_nest_start_noflag(skb, RTA_MULTIPATH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (!mp_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) for_nexthops(fi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (!(nhp = nla_reserve_nohdr(skb, sizeof(*nhp))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) nhp->rtnh_flags = nh->nh_flags & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) nhp->rtnh_hops = nh->nh_weight - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) nhp->rtnh_ifindex = nh->nh_oif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (nh->nh_gw &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) nla_put_le16(skb, RTA_GATEWAY, nh->nh_gw) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) nhp->rtnh_len = skb_tail_pointer(skb) - (unsigned char *)nhp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) } endfor_nexthops(fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) nla_nest_end(skb, mp_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) nlmsg_end(skb, nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) errout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) nlmsg_cancel(skb, nlh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct nlmsghdr *nlh, struct netlink_skb_parms *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) u32 portid = req ? req->portid : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f)), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) err = dn_fib_dump_info(skb, portid, nlh->nlmsg_seq, event, tb_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) f->fn_type, f->fn_scope, &f->fn_key, z,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) DN_FIB_INFO(f), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* -EMSGSIZE implies BUG in dn_fib_nlmsg_size() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) WARN_ON(err == -EMSGSIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) goto errout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) rtnl_notify(skb, &init_net, portid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) errout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_ROUTE, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct dn_fib_table *tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct dn_zone *dz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct dn_fib_node *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) int i, s_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) s_i = cb->args[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) for(i = 0; f; i++, f = f->fn_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (i < s_i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (f->fn_state & DN_S_ZOMBIE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (dn_fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) cb->nlh->nlmsg_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) RTM_NEWROUTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) tb->n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) (f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) f->fn_scope, &f->fn_key, dz->dz_order,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) f->fn_info, NLM_F_MULTI) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) cb->args[4] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) cb->args[4] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static __inline__ int dn_hash_dump_zone(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct netlink_callback *cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct dn_fib_table *tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct dn_zone *dz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) int h, s_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) s_h = cb->args[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) for(h = 0; h < dz->dz_divisor; h++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (h < s_h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (h > s_h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) memset(&cb->args[4], 0, sizeof(cb->args) - 4*sizeof(cb->args[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (dz->dz_hash == NULL || dz->dz_hash[h] == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (dn_hash_dump_bucket(skb, cb, tb, dz, dz->dz_hash[h]) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) cb->args[3] = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) cb->args[3] = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static int dn_fib_table_dump(struct dn_fib_table *tb, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) int m, s_m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) struct dn_zone *dz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct dn_hash *table = (struct dn_hash *)tb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) s_m = cb->args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) read_lock(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) for(dz = table->dh_zone_list, m = 0; dz; dz = dz->dz_next, m++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (m < s_m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (m > s_m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (dn_hash_dump_zone(skb, cb, tb, dz) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) cb->args[2] = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) read_unlock(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) read_unlock(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) cb->args[2] = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) unsigned int h, s_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) unsigned int e = 0, s_e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct dn_fib_table *tb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int dumped = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (!net_eq(net, &init_net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ((struct rtmsg *)nlmsg_data(cb->nlh))->rtm_flags&RTM_F_CLONED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return dn_cache_dump(skb, cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) s_h = cb->args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) s_e = cb->args[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) for (h = s_h; h < DN_FIB_TABLE_HASHSZ; h++, s_h = 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) e = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) hlist_for_each_entry(tb, &dn_fib_table_hash[h], hlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (e < s_e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (dumped)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) memset(&cb->args[2], 0, sizeof(cb->args) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 2 * sizeof(cb->args[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (tb->dump(tb, skb, cb) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) dumped = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) e++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) cb->args[1] = e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) cb->args[0] = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct nlattr *attrs[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct nlmsghdr *n, struct netlink_skb_parms *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct dn_hash *table = (struct dn_hash *)tb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct dn_fib_node *new_f, *f, **fp, **del_fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct dn_zone *dz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct dn_fib_info *fi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int z = r->rtm_dst_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) int type = r->rtm_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) dn_fib_key_t key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (z > 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) dz = table->dh_zones[z];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (!dz && !(dz = dn_new_zone(table, z)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) dz_key_0(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (attrs[RTA_DST]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) __le16 dst = nla_get_le16(attrs[RTA_DST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (dst & ~DZ_MASK(dz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) key = dz_key(dst, dz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if ((fi = dn_fib_create_info(r, attrs, n, &err)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (dz->dz_nent > (dz->dz_divisor << 2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) dz->dz_divisor > DN_MAX_DIVISOR &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) (z==16 || (1<<z) > dz->dz_divisor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) dn_rehash_zone(dz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) fp = dn_chain_p(key, dz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) DN_FIB_SCAN(f, fp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (dn_key_leq(key, f->fn_key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) del_fp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (f && (f->fn_state & DN_S_ZOMBIE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) dn_key_eq(f->fn_key, key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) del_fp = fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) fp = &f->fn_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) f = *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) goto create;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) DN_FIB_SCAN_KEY(f, fp, key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (fi->fib_priority <= DN_FIB_INFO(f)->fib_priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (f && dn_key_eq(f->fn_key, key) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) fi->fib_priority == DN_FIB_INFO(f)->fib_priority) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) struct dn_fib_node **ins_fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) err = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (n->nlmsg_flags & NLM_F_EXCL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (n->nlmsg_flags & NLM_F_REPLACE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) del_fp = fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) fp = &f->fn_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) f = *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) goto replace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) ins_fp = fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) err = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) DN_FIB_SCAN_KEY(f, fp, key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (fi->fib_priority != DN_FIB_INFO(f)->fib_priority)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (f->fn_type == type &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) f->fn_scope == r->rtm_scope &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) DN_FIB_INFO(f) == fi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (!(n->nlmsg_flags & NLM_F_APPEND)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) fp = ins_fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) f = *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) create:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (!(n->nlmsg_flags & NLM_F_CREATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) replace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) new_f = kmem_cache_zalloc(dn_hash_kmem, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (new_f == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) new_f->fn_key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) new_f->fn_type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) new_f->fn_scope = r->rtm_scope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) DN_FIB_INFO(new_f) = fi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) new_f->fn_next = f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) write_lock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) *fp = new_f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) write_unlock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) dz->dz_nent++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (del_fp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) f = *del_fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) write_lock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) *del_fp = f->fn_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) write_unlock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (!(f->fn_state & DN_S_ZOMBIE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) dn_rtmsg_fib(RTM_DELROUTE, f, z, tb->n, n, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (f->fn_state & DN_S_ACCESSED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) dn_rt_cache_flush(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) dn_free_node(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) dz->dz_nent--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) dn_rt_cache_flush(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) dn_rtmsg_fib(RTM_NEWROUTE, new_f, z, tb->n, n, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) dn_fib_release_info(fi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct nlattr *attrs[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct nlmsghdr *n, struct netlink_skb_parms *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct dn_hash *table = (struct dn_hash*)tb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct dn_fib_node **fp, **del_fp, *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) int z = r->rtm_dst_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct dn_zone *dz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) dn_fib_key_t key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) int matched;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (z > 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if ((dz = table->dh_zones[z]) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) dz_key_0(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (attrs[RTA_DST]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) __le16 dst = nla_get_le16(attrs[RTA_DST]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (dst & ~DZ_MASK(dz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) key = dz_key(dst, dz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) fp = dn_chain_p(key, dz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) DN_FIB_SCAN(f, fp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (dn_key_eq(f->fn_key, key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (dn_key_leq(key, f->fn_key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) matched = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) del_fp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) DN_FIB_SCAN_KEY(f, fp, key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct dn_fib_info *fi = DN_FIB_INFO(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (f->fn_state & DN_S_ZOMBIE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) matched++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (del_fp == NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) (!r->rtm_type || f->fn_type == r->rtm_type) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) (r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) (!r->rtm_protocol ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) fi->fib_protocol == r->rtm_protocol) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) dn_fib_nh_match(r, n, attrs, fi) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) del_fp = fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (del_fp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) f = *del_fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) dn_rtmsg_fib(RTM_DELROUTE, f, z, tb->n, n, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (matched != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) write_lock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) *del_fp = f->fn_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) write_unlock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (f->fn_state & DN_S_ACCESSED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) dn_rt_cache_flush(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) dn_free_node(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) dz->dz_nent--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) f->fn_state |= DN_S_ZOMBIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (f->fn_state & DN_S_ACCESSED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) f->fn_state &= ~DN_S_ACCESSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) dn_rt_cache_flush(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (++dn_fib_hash_zombies > 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) dn_fib_flush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static inline int dn_flush_list(struct dn_fib_node **fp, int z, struct dn_hash *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) int found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct dn_fib_node *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) while((f = *fp) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) struct dn_fib_info *fi = DN_FIB_INFO(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (fi && ((f->fn_state & DN_S_ZOMBIE) || (fi->fib_flags & RTNH_F_DEAD))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) write_lock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) *fp = f->fn_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) write_unlock_bh(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) dn_free_node(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) found++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) fp = &f->fn_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) static int dn_fib_table_flush(struct dn_fib_table *tb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) struct dn_hash *table = (struct dn_hash *)tb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) struct dn_zone *dz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) int found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) dn_fib_hash_zombies = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) for(dz = table->dh_zone_list; dz; dz = dz->dz_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) int tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) for(i = dz->dz_divisor-1; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) tmp += dn_flush_list(&dz->dz_hash[i], dz->dz_order, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) dz->dz_nent -= tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) found += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct flowidn *flp, struct dn_fib_res *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) struct dn_zone *dz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) struct dn_hash *t = (struct dn_hash *)tb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) read_lock(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) for(dz = t->dh_zone_list; dz; dz = dz->dz_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct dn_fib_node *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) dn_fib_key_t k = dz_key(flp->daddr, dz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) for(f = dz_chain(k, dz); f; f = f->fn_next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!dn_key_eq(k, f->fn_key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (dn_key_leq(k, f->fn_key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) f->fn_state |= DN_S_ACCESSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (f->fn_state&DN_S_ZOMBIE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (f->fn_scope < flp->flowidn_scope)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) err = dn_fib_semantic_match(f->fn_type, DN_FIB_INFO(f), flp, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (err == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) res->type = f->fn_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) res->scope = f->fn_scope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) res->prefixlen = dz->dz_order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) err = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) read_unlock(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) struct dn_fib_table *dn_fib_get_table(u32 n, int create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) struct dn_fib_table *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) unsigned int h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (n < RT_TABLE_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (n > RT_TABLE_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) h = n & (DN_FIB_TABLE_HASHSZ - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) hlist_for_each_entry_rcu(t, &dn_fib_table_hash[h], hlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (t->n == n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (!create)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (in_interrupt()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) net_dbg_ratelimited("DECnet: BUG! Attempt to create routing table from interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) t = kzalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (t == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) t->n = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) t->insert = dn_fib_table_insert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) t->delete = dn_fib_table_delete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) t->lookup = dn_fib_table_lookup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) t->flush = dn_fib_table_flush;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) t->dump = dn_fib_table_dump;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) struct dn_fib_table *dn_fib_empty_table(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (dn_fib_get_table(id, 0) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return dn_fib_get_table(id, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) void dn_fib_flush(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) int flushed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct dn_fib_table *tb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) unsigned int h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) hlist_for_each_entry(tb, &dn_fib_table_hash[h], hlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) flushed += tb->flush(tb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (flushed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) dn_rt_cache_flush(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) void __init dn_fib_table_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) dn_hash_kmem = kmem_cache_create("dn_fib_info_cache",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) sizeof(struct dn_fib_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) 0, SLAB_HWCACHE_ALIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) void __exit dn_fib_table_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct dn_fib_table *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct hlist_node *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) unsigned int h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) write_lock(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) hlist_for_each_entry_safe(t, next, &dn_fib_table_hash[h],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) hlist) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) hlist_del(&t->hlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) kfree(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) write_unlock(&dn_fib_tables_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }