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 struct rb_node rb_node; 37 struct inetpeer_addr daddr; 38 39 u32 metrics[RTAX_MAX]; 40 u32 rate_tokens; /* rate limiting for ICMP */ 41 unsigned long rate_last; 42 /* 43 * Once inet_peer is queued for deletion (refcnt == 0), following field 44 * is not available: rid 45 * We can share memory with rcu_head to help keep inet_peer small. 46 */ 47 union { 48 struct { 49 atomic_t rid; /* Frag reception counter */ 50 }; 51 struct rcu_head rcu; 52 }; 53 54 /* following fields might be frequently dirtied */ 55 __u32 dtime; /* the time of last use of not referenced entries */ 56 refcount_t refcnt; 57 }; 58 59 struct inet_peer_base { 60 struct rb_root rb_root; 61 seqlock_t lock; 62 int total; 63 }; 64 65 void inet_peer_base_init(struct inet_peer_base *); 66 67 void inet_initpeers(void) __init; 68 69 #define INETPEER_METRICS_NEW (~(u32) 0) 70 71 static inline void inetpeer_set_addr_v4(struct inetpeer_addr *iaddr, __be32 ip) 72 { 73 iaddr->a4.addr = ip; 74 iaddr->a4.vif = 0; 75 iaddr->family = AF_INET; 76 } 77 78 static inline __be32 inetpeer_get_addr_v4(struct inetpeer_addr *iaddr) 79 { 80 return iaddr->a4.addr; 81 } 82 83 static inline void inetpeer_set_addr_v6(struct inetpeer_addr *iaddr, 84 struct in6_addr *in6) 85 { 86 iaddr->a6 = *in6; 87 iaddr->family = AF_INET6; 88 } 89 90 static inline struct in6_addr *inetpeer_get_addr_v6(struct inetpeer_addr *iaddr) 91 { 92 return &iaddr->a6; 93 } 94 95 /* can be called with or without local BH being disabled */ 96 struct inet_peer *inet_getpeer(struct inet_peer_base *base, 97 const struct inetpeer_addr *daddr, 98 int create); 99 100 static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base, 101 __be32 v4daddr, 102 int vif, int create) 103 { 104 struct inetpeer_addr daddr; 105 106 daddr.a4.addr = v4daddr; 107 daddr.a4.vif = vif; 108 daddr.family = AF_INET; 109 return inet_getpeer(base, &daddr, create); 110 } 111 112 static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base, 113 const struct in6_addr *v6daddr, 114 int create) 115 { 116 struct inetpeer_addr daddr; 117 118 daddr.a6 = *v6daddr; 119 daddr.family = AF_INET6; 120 return inet_getpeer(base, &daddr, create); 121 } 122 123 static inline int inetpeer_addr_cmp(const struct inetpeer_addr *a, 124 const struct inetpeer_addr *b) 125 { 126 int i, n; 127 128 if (a->family == AF_INET) 129 n = sizeof(a->a4) / sizeof(u32); 130 else 131 n = sizeof(a->a6) / sizeof(u32); 132 133 for (i = 0; i < n; i++) { 134 if (a->key[i] == b->key[i]) 135 continue; 136 if (a->key[i] < b->key[i]) 137 return -1; 138 return 1; 139 } 140 141 return 0; 142 } 143 144 /* can be called from BH context or outside */ 145 void inet_putpeer(struct inet_peer *p); 146 bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); 147 148 void inetpeer_invalidate_tree(struct inet_peer_base *); 149 150 #endif /* _NET_INETPEER_H */ 151