Line data Source code
1 : /*
2 : * net/dst.h Protocol independent destination cache definitions.
3 : *
4 : * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
5 : *
6 : */
7 :
8 : #ifndef _NET_DST_H
9 : #define _NET_DST_H
10 :
11 : #include <net/dst_ops.h>
12 : #include <linux/netdevice.h>
13 : #include <linux/rtnetlink.h>
14 : #include <linux/rcupdate.h>
15 : #include <linux/jiffies.h>
16 : #include <net/neighbour.h>
17 : #include <asm/processor.h>
18 :
19 : /*
20 : * 0 - no debugging messages
21 : * 1 - rare events and bugs (default)
22 : * 2 - trace mode.
23 : */
24 : #define RT_CACHE_DEBUG 0
25 :
26 : #define DST_GC_MIN (HZ/10)
27 : #define DST_GC_INC (HZ/2)
28 : #define DST_GC_MAX (120*HZ)
29 :
30 : /* Each dst_entry has reference count and sits in some parent list(s).
31 : * When it is removed from parent list, it is "freed" (dst_free).
32 : * After this it enters dead state (dst->obsolete > 0) and if its refcnt
33 : * is zero, it can be destroyed immediately, otherwise it is added
34 : * to gc list and garbage collector periodically checks the refcnt.
35 : */
36 :
37 : struct sk_buff;
38 :
39 : struct dst_entry {
40 : struct rcu_head rcu_head;
41 : struct dst_entry *child;
42 : struct net_device *dev;
43 : short error;
44 : short obsolete;
45 : int flags;
46 : #define DST_HOST 1
47 : #define DST_NOXFRM 2
48 : #define DST_NOPOLICY 4
49 : #define DST_NOHASH 8
50 : unsigned long expires;
51 :
52 : unsigned short header_len; /* more space at head required */
53 : unsigned short trailer_len; /* space to reserve at tail */
54 :
55 : unsigned int rate_tokens;
56 : unsigned long rate_last; /* rate limiting for ICMP */
57 :
58 : struct dst_entry *path;
59 :
60 : struct neighbour *neighbour;
61 : struct hh_cache *hh;
62 : #ifdef CONFIG_XFRM
63 : struct xfrm_state *xfrm;
64 : #else
65 : void *__pad1;
66 : #endif
67 : int (*input)(struct sk_buff*);
68 : int (*output)(struct sk_buff*);
69 :
70 : struct dst_ops *ops;
71 :
72 : u32 metrics[RTAX_MAX];
73 :
74 : #ifdef CONFIG_NET_CLS_ROUTE
75 : __u32 tclassid;
76 : #else
77 : __u32 __pad2;
78 : #endif
79 :
80 :
81 : /*
82 : * Align __refcnt to a 64 bytes alignment
83 : * (L1_CACHE_SIZE would be too much)
84 : */
85 : #ifdef CONFIG_64BIT
86 : long __pad_to_align_refcnt[2];
87 : #else
88 : long __pad_to_align_refcnt[1];
89 : #endif
90 : /*
91 : * __refcnt wants to be on a different cache line from
92 : * input/output/ops or performance tanks badly
93 : */
94 : atomic_t __refcnt; /* client references */
95 : int __use;
96 : unsigned long lastuse;
97 : union {
98 : struct dst_entry *next;
99 : struct rtable *rt_next;
100 : struct rt6_info *rt6_next;
101 : struct dn_route *dn_next;
102 : };
103 : };
104 :
105 : #ifdef __KERNEL__
106 :
107 : static inline u32
108 : dst_metric(const struct dst_entry *dst, int metric)
109 : {
110 : return dst->metrics[metric-1];
111 : }
112 :
113 : static inline u32
114 : dst_feature(const struct dst_entry *dst, u32 feature)
115 : {
116 : return dst_metric(dst, RTAX_FEATURES) & feature;
117 : }
118 :
119 : static inline u32 dst_mtu(const struct dst_entry *dst)
120 : {
121 : u32 mtu = dst_metric(dst, RTAX_MTU);
122 : /*
123 : * Alexey put it here, so ask him about it :)
124 : */
125 : barrier();
126 : return mtu;
127 : }
128 :
129 : /* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */
130 : static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metric)
131 : {
132 : return msecs_to_jiffies(dst_metric(dst, metric));
133 : }
134 :
135 : static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric,
136 : unsigned long rtt)
137 : {
138 : dst->metrics[metric-1] = jiffies_to_msecs(rtt);
139 : }
140 :
141 : static inline u32
142 : dst_allfrag(const struct dst_entry *dst)
143 : {
144 : int ret = dst_feature(dst, RTAX_FEATURE_ALLFRAG);
145 : /* Yes, _exactly_. This is paranoia. */
146 : barrier();
147 : return ret;
148 : }
149 :
150 : static inline int
151 : dst_metric_locked(struct dst_entry *dst, int metric)
152 : {
153 : return dst_metric(dst, RTAX_LOCK) & (1<<metric);
154 : }
155 :
156 : static inline void dst_hold(struct dst_entry * dst)
157 : {
158 : /*
159 : * If your kernel compilation stops here, please check
160 : * __pad_to_align_refcnt declaration in struct dst_entry
161 : */
162 : BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63);
163 : atomic_inc(&dst->__refcnt);
164 : }
165 :
166 : static inline void dst_use(struct dst_entry *dst, unsigned long time)
167 : {
168 : dst_hold(dst);
169 : dst->__use++;
170 : dst->lastuse = time;
171 : }
172 :
173 : static inline
174 : struct dst_entry * dst_clone(struct dst_entry * dst)
175 : {
176 : if (dst)
177 : atomic_inc(&dst->__refcnt);
178 : return dst;
179 : }
180 :
181 : extern void dst_release(struct dst_entry *dst);
182 : static inline void skb_dst_drop(struct sk_buff *skb)
183 : {
184 0 : if (skb->_skb_dst)
185 0 : dst_release(skb_dst(skb));
186 0 : skb->_skb_dst = 0UL;
187 0 : }
188 :
189 : /* Children define the path of the packet through the
190 : * Linux networking. Thus, destinations are stackable.
191 : */
192 :
193 : static inline struct dst_entry *dst_pop(struct dst_entry *dst)
194 : {
195 : struct dst_entry *child = dst_clone(dst->child);
196 :
197 : dst_release(dst);
198 : return child;
199 : }
200 :
201 : extern int dst_discard(struct sk_buff *skb);
202 : extern void * dst_alloc(struct dst_ops * ops);
203 : extern void __dst_free(struct dst_entry * dst);
204 : extern struct dst_entry *dst_destroy(struct dst_entry * dst);
205 :
206 : static inline void dst_free(struct dst_entry * dst)
207 : {
208 : if (dst->obsolete > 1)
209 : return;
210 : if (!atomic_read(&dst->__refcnt)) {
211 : dst = dst_destroy(dst);
212 : if (!dst)
213 : return;
214 : }
215 : __dst_free(dst);
216 : }
217 :
218 : static inline void dst_rcu_free(struct rcu_head *head)
219 : {
220 : struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head);
221 : dst_free(dst);
222 : }
223 :
224 : static inline void dst_confirm(struct dst_entry *dst)
225 : {
226 : if (dst)
227 : neigh_confirm(dst->neighbour);
228 : }
229 :
230 : static inline void dst_negative_advice(struct dst_entry **dst_p,
231 : struct sock *sk)
232 : {
233 : struct dst_entry * dst = *dst_p;
234 : if (dst && dst->ops->negative_advice) {
235 : *dst_p = dst->ops->negative_advice(dst);
236 :
237 : if (dst != *dst_p) {
238 : extern void sk_reset_txq(struct sock *sk);
239 :
240 : sk_reset_txq(sk);
241 : }
242 : }
243 : }
244 :
245 : static inline void dst_link_failure(struct sk_buff *skb)
246 : {
247 : struct dst_entry *dst = skb_dst(skb);
248 : if (dst && dst->ops && dst->ops->link_failure)
249 : dst->ops->link_failure(skb);
250 : }
251 :
252 : static inline void dst_set_expires(struct dst_entry *dst, int timeout)
253 : {
254 : unsigned long expires = jiffies + timeout;
255 :
256 : if (expires == 0)
257 : expires = 1;
258 :
259 : if (dst->expires == 0 || time_before(expires, dst->expires))
260 : dst->expires = expires;
261 : }
262 :
263 : /* Output packet to network from transport. */
264 : static inline int dst_output(struct sk_buff *skb)
265 : {
266 : return skb_dst(skb)->output(skb);
267 : }
268 :
269 : /* Input packet from network to transport. */
270 : static inline int dst_input(struct sk_buff *skb)
271 : {
272 : return skb_dst(skb)->input(skb);
273 : }
274 :
275 : static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
276 : {
277 : if (dst->obsolete)
278 : dst = dst->ops->check(dst, cookie);
279 : return dst;
280 : }
281 :
282 : extern void dst_init(void);
283 :
284 : /* Flags for xfrm_lookup flags argument. */
285 : enum {
286 : XFRM_LOOKUP_WAIT = 1 << 0,
287 : XFRM_LOOKUP_ICMP = 1 << 1,
288 : };
289 :
290 : struct flowi;
291 : #ifndef CONFIG_XFRM
292 : static inline int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
293 : struct flowi *fl, struct sock *sk, int flags)
294 : {
295 : return 0;
296 : }
297 : static inline int __xfrm_lookup(struct net *net, struct dst_entry **dst_p,
298 : struct flowi *fl, struct sock *sk, int flags)
299 : {
300 : return 0;
301 : }
302 : #else
303 : extern int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
304 : struct flowi *fl, struct sock *sk, int flags);
305 : extern int __xfrm_lookup(struct net *net, struct dst_entry **dst_p,
306 : struct flowi *fl, struct sock *sk, int flags);
307 : #endif
308 : #endif
309 :
310 : #endif /* _NET_DST_H */
|