1 /* 2 * INETPEER - A storage for permanent information about peers 3 * 4 * Authors: Andrey V. Savochkin <saw@msu.ru> 5 */ 6 7 #ifndef _NET_INETPEER_H 8 #define _NET_INETPEER_H 9 10 #include <linux/types.h> 11 #include <linux/init.h> 12 #include <linux/jiffies.h> 13 #include <linux/spinlock.h> 14 #include <linux/rtnetlink.h> 15 #include <net/ipv6.h> 16 #include <linux/atomic.h> 17 18 /* IPv4 address key for cache lookups */ 19 struct ipv4_addr_key { 20 __be32 addr; 21 int vif; 22 }; 23 24 #define INETPEER_MAXKEYSZ (sizeof(struct in6_addr) / sizeof(u32)) 25 26 struct inetpeer_addr { 27 union { 28 struct ipv4_addr_key a4; 29 struct in6_addr a6; 30 u32 key[INETPEER_MAXKEYSZ]; 31 }; 32 __u16 family; 33 }; 34 35 struct inet_peer { 36 /* group together avl_left,avl_right,v4daddr to speedup lookups */ 37 struct inet_peer __rcu *avl_left, *avl_right; 38 struct inetpeer_addr daddr; 39 __u32 avl_height; 40 41 u32 metrics[RTAX_MAX]; 42 u32 rate_tokens; /* rate limiting for ICMP */ 43 unsigned long rate_last; 44 union { 45 struct list_head gc_list; 46 struct rcu_head gc_rcu; 47 }; 48 /* 49 * Once inet_peer is queued for deletion (refcnt == -1), following field 50 * is not available: rid 51 * We can share memory with rcu_head to help keep inet_peer small. 52 */ 53 union { 54 struct { 55 atomic_t rid; /* Frag reception counter */ 56 }; 57 struct rcu_head rcu; 58 struct inet_peer *gc_next; 59 }; 60 61 /* following fields might be frequently dirtied */ 62 __u32 dtime; /* the time of last use of not referenced entries */ 63 atomic_t refcnt; 64 }; 65 66 struct inet_peer_base { 67 struct inet_peer __rcu *root; 68 seqlock_t lock; 69 int total; 70 }; 71 72 void inet_peer_base_init(struct inet_peer_base *); 73 74 void inet_initpeers(void) __init; 75 76 #define INETPEER_METRICS_NEW (~(u32) 0) 77 78 static inline void inetpeer_set_addr_v4(struct inetpeer_addr *iaddr, __be32 ip) 79 { 80 iaddr->a4.addr = ip; 81 iaddr->a4.vif = 0; 82 iaddr->family = AF_INET; 83 } 84 85 static inline __be32 inetpeer_get_addr_v4(struct inetpeer_addr *iaddr) 86 { 87 return iaddr->a4.addr; 88 } 89 90 static inline void inetpeer_set_addr_v6(struct inetpeer_addr *iaddr, 91 struct in6_addr *in6) 92 { 93 iaddr->a6 = *in6; 94 iaddr->family = AF_INET6; 95 } 96 97 static inline struct in6_addr *inetpeer_get_addr_v6(struct inetpeer_addr *iaddr) 98 { 99 return &iaddr->a6; 100 } 101 102 /* can be called with or without local BH being disabled */ 103 struct inet_peer *inet_getpeer(struct inet_peer_base *base, 104 const struct inetpeer_addr *daddr, 105 int create); 106 107 static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base, 108 __be32 v4daddr, 109 int vif, int create) 110 { 111 struct inetpeer_addr daddr; 112 113 daddr.a4.addr = v4daddr; 114 daddr.a4.vif = vif; 115 daddr.family = AF_INET; 116 return inet_getpeer(base, &daddr, create); 117 } 118 119 static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base, 120 const struct in6_addr *v6daddr, 121 int create) 122 { 123 struct inetpeer_addr daddr; 124 125 daddr.a6 = *v6daddr; 126 daddr.family = AF_INET6; 127 return inet_getpeer(base, &daddr, create); 128 } 129 130 static inline int inetpeer_addr_cmp(const struct inetpeer_addr *a, 131 const struct inetpeer_addr *b) 132 { 133 int i, n; 134 135 if (a->family == AF_INET) 136 n = sizeof(a->a4) / sizeof(u32); 137 else 138 n = sizeof(a->a6) / sizeof(u32); 139 140 for (i = 0; i < n; i++) { 141 if (a->key[i] == b->key[i]) 142 continue; 143 if (a->key[i] < b->key[i]) 144 return -1; 145 return 1; 146 } 147 148 return 0; 149 } 150 151 /* can be called from BH context or outside */ 152 void inet_putpeer(struct inet_peer *p); 153 bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); 154 155 void inetpeer_invalidate_tree(struct inet_peer_base *); 156 157 #endif /* _NET_INETPEER_H */ 158