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