Branch data 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 : : static inline void inetpeer_set_addr_v4(struct inetpeer_addr *iaddr, __be32 ip) 74 : : { 75 : 1 : iaddr->a4.addr = ip; 76 : 1 : iaddr->a4.vif = 0; 77 : 1 : iaddr->family = AF_INET; 78 : : } 79 : : 80 : : static inline __be32 inetpeer_get_addr_v4(struct inetpeer_addr *iaddr) 81 : : { 82 : 0 : return iaddr->a4.addr; 83 : : } 84 : : 85 : : 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 : : 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 : : static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base, 103 : : __be32 v4daddr, 104 : : int vif, int create) 105 : : { 106 : : struct inetpeer_addr daddr; 107 : : 108 : 2 : daddr.a4.addr = v4daddr; 109 : 2 : daddr.a4.vif = vif; 110 : 2 : daddr.family = AF_INET; 111 : 2 : return inet_getpeer(base, &daddr, create); 112 : : } 113 : : 114 : 0 : 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 : 0 : daddr.a6 = *v6daddr; 121 : 0 : daddr.family = AF_INET6; 122 : 0 : return inet_getpeer(base, &daddr, create); 123 : : } 124 : : 125 : : static inline int inetpeer_addr_cmp(const struct inetpeer_addr *a, 126 : : const struct inetpeer_addr *b) 127 : : { 128 : : int i, n; 129 : : 130 : 3 : if (a->family == AF_INET) 131 : : n = sizeof(a->a4) / sizeof(u32); 132 : : else 133 : : n = sizeof(a->a6) / sizeof(u32); 134 : : 135 : 3 : for (i = 0; i < n; i++) { 136 : 3 : if (a->key[i] == b->key[i]) 137 : 3 : continue; 138 : 0 : if (a->key[i] < b->key[i]) 139 : : 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 */