]>
Commit | Line | Data |
---|---|---|
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 | iaddr->a4.addr = ip; | |
76 | iaddr->a4.vif = 0; | |
77 | iaddr->family = AF_INET; | |
78 | } | |
79 | ||
80 | static inline __be32 inetpeer_get_addr_v4(struct inetpeer_addr *iaddr) | |
81 | { | |
82 | 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 | iaddr->a6 = *in6; | |
89 | iaddr->family = AF_INET6; | |
90 | } | |
91 | ||
92 | static inline struct in6_addr *inetpeer_get_addr_v6(struct inetpeer_addr *iaddr) | |
93 | { | |
94 | 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 | daddr.a4.addr = v4daddr; | |
109 | daddr.a4.vif = vif; | |
110 | daddr.family = AF_INET; | |
111 | 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 | static inline int inetpeer_addr_cmp(const struct inetpeer_addr *a, | |
126 | const struct inetpeer_addr *b) | |
127 | { | |
128 | int i, n; | |
129 | ||
130 | if (a->family == AF_INET) | |
131 | n = sizeof(a->a4) / sizeof(u32); | |
132 | else | |
133 | n = sizeof(a->a6) / sizeof(u32); | |
134 | ||
135 | for (i = 0; i < n; i++) { | |
136 | if (a->key[i] == b->key[i]) | |
137 | continue; | |
138 | 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 */ |