diff options
Diffstat (limited to 'include/net/dst.h')
-rw-r--r-- | include/net/dst.h | 213 |
1 files changed, 147 insertions, 66 deletions
diff --git a/include/net/dst.h b/include/net/dst.h index 02386505033d..e12ddfb9eb16 100644 --- a/include/net/dst.h +++ b/include/net/dst.h | |||
@@ -16,13 +16,6 @@ | |||
16 | #include <net/neighbour.h> | 16 | #include <net/neighbour.h> |
17 | #include <asm/processor.h> | 17 | #include <asm/processor.h> |
18 | 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) | 19 | #define DST_GC_MIN (HZ/10) |
27 | #define DST_GC_INC (HZ/2) | 20 | #define DST_GC_INC (HZ/2) |
28 | #define DST_GC_MAX (120*HZ) | 21 | #define DST_GC_MAX (120*HZ) |
@@ -40,23 +33,10 @@ struct dst_entry { | |||
40 | struct rcu_head rcu_head; | 33 | struct rcu_head rcu_head; |
41 | struct dst_entry *child; | 34 | struct dst_entry *child; |
42 | struct net_device *dev; | 35 | struct net_device *dev; |
43 | short error; | 36 | struct dst_ops *ops; |
44 | short obsolete; | 37 | unsigned long _metrics; |
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; | 38 | 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; | 39 | struct dst_entry *path; |
59 | |||
60 | struct neighbour *neighbour; | 40 | struct neighbour *neighbour; |
61 | struct hh_cache *hh; | 41 | struct hh_cache *hh; |
62 | #ifdef CONFIG_XFRM | 42 | #ifdef CONFIG_XFRM |
@@ -67,17 +47,16 @@ struct dst_entry { | |||
67 | int (*input)(struct sk_buff*); | 47 | int (*input)(struct sk_buff*); |
68 | int (*output)(struct sk_buff*); | 48 | int (*output)(struct sk_buff*); |
69 | 49 | ||
70 | struct dst_ops *ops; | 50 | short error; |
71 | 51 | short obsolete; | |
72 | u32 metrics[RTAX_MAX]; | 52 | unsigned short header_len; /* more space at head required */ |
73 | 53 | unsigned short trailer_len; /* space to reserve at tail */ | |
74 | #ifdef CONFIG_NET_CLS_ROUTE | 54 | #ifdef CONFIG_IP_ROUTE_CLASSID |
75 | __u32 tclassid; | 55 | __u32 tclassid; |
76 | #else | 56 | #else |
77 | __u32 __pad2; | 57 | __u32 __pad2; |
78 | #endif | 58 | #endif |
79 | 59 | ||
80 | |||
81 | /* | 60 | /* |
82 | * Align __refcnt to a 64 bytes alignment | 61 | * Align __refcnt to a 64 bytes alignment |
83 | * (L1_CACHE_SIZE would be too much) | 62 | * (L1_CACHE_SIZE would be too much) |
@@ -92,20 +71,115 @@ struct dst_entry { | |||
92 | atomic_t __refcnt; /* client references */ | 71 | atomic_t __refcnt; /* client references */ |
93 | int __use; | 72 | int __use; |
94 | unsigned long lastuse; | 73 | unsigned long lastuse; |
74 | int flags; | ||
75 | #define DST_HOST 0x0001 | ||
76 | #define DST_NOXFRM 0x0002 | ||
77 | #define DST_NOPOLICY 0x0004 | ||
78 | #define DST_NOHASH 0x0008 | ||
79 | #define DST_NOCACHE 0x0010 | ||
80 | #define DST_NOCOUNT 0x0020 | ||
95 | union { | 81 | union { |
96 | struct dst_entry *next; | 82 | struct dst_entry *next; |
97 | struct rtable *rt_next; | 83 | struct rtable __rcu *rt_next; |
98 | struct rt6_info *rt6_next; | 84 | struct rt6_info *rt6_next; |
99 | struct dn_route *dn_next; | 85 | struct dn_route __rcu *dn_next; |
100 | }; | 86 | }; |
101 | }; | 87 | }; |
102 | 88 | ||
103 | #ifdef __KERNEL__ | 89 | extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); |
90 | extern const u32 dst_default_metrics[RTAX_MAX]; | ||
91 | |||
92 | #define DST_METRICS_READ_ONLY 0x1UL | ||
93 | #define __DST_METRICS_PTR(Y) \ | ||
94 | ((u32 *)((Y) & ~DST_METRICS_READ_ONLY)) | ||
95 | #define DST_METRICS_PTR(X) __DST_METRICS_PTR((X)->_metrics) | ||
96 | |||
97 | static inline bool dst_metrics_read_only(const struct dst_entry *dst) | ||
98 | { | ||
99 | return dst->_metrics & DST_METRICS_READ_ONLY; | ||
100 | } | ||
101 | |||
102 | extern void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old); | ||
103 | |||
104 | static inline void dst_destroy_metrics_generic(struct dst_entry *dst) | ||
105 | { | ||
106 | unsigned long val = dst->_metrics; | ||
107 | if (!(val & DST_METRICS_READ_ONLY)) | ||
108 | __dst_destroy_metrics_generic(dst, val); | ||
109 | } | ||
110 | |||
111 | static inline u32 *dst_metrics_write_ptr(struct dst_entry *dst) | ||
112 | { | ||
113 | unsigned long p = dst->_metrics; | ||
114 | |||
115 | BUG_ON(!p); | ||
116 | |||
117 | if (p & DST_METRICS_READ_ONLY) | ||
118 | return dst->ops->cow_metrics(dst, p); | ||
119 | return __DST_METRICS_PTR(p); | ||
120 | } | ||
121 | |||
122 | /* This may only be invoked before the entry has reached global | ||
123 | * visibility. | ||
124 | */ | ||
125 | static inline void dst_init_metrics(struct dst_entry *dst, | ||
126 | const u32 *src_metrics, | ||
127 | bool read_only) | ||
128 | { | ||
129 | dst->_metrics = ((unsigned long) src_metrics) | | ||
130 | (read_only ? DST_METRICS_READ_ONLY : 0); | ||
131 | } | ||
132 | |||
133 | static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src) | ||
134 | { | ||
135 | u32 *dst_metrics = dst_metrics_write_ptr(dest); | ||
136 | |||
137 | if (dst_metrics) { | ||
138 | u32 *src_metrics = DST_METRICS_PTR(src); | ||
139 | |||
140 | memcpy(dst_metrics, src_metrics, RTAX_MAX * sizeof(u32)); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | static inline u32 *dst_metrics_ptr(struct dst_entry *dst) | ||
145 | { | ||
146 | return DST_METRICS_PTR(dst); | ||
147 | } | ||
148 | |||
149 | static inline u32 | ||
150 | dst_metric_raw(const struct dst_entry *dst, const int metric) | ||
151 | { | ||
152 | u32 *p = DST_METRICS_PTR(dst); | ||
153 | |||
154 | return p[metric-1]; | ||
155 | } | ||
156 | |||
157 | static inline u32 | ||
158 | dst_metric(const struct dst_entry *dst, const int metric) | ||
159 | { | ||
160 | WARN_ON_ONCE(metric == RTAX_HOPLIMIT || | ||
161 | metric == RTAX_ADVMSS || | ||
162 | metric == RTAX_MTU); | ||
163 | return dst_metric_raw(dst, metric); | ||
164 | } | ||
104 | 165 | ||
105 | static inline u32 | 166 | static inline u32 |
106 | dst_metric(const struct dst_entry *dst, int metric) | 167 | dst_metric_advmss(const struct dst_entry *dst) |
107 | { | 168 | { |
108 | return dst->metrics[metric-1]; | 169 | u32 advmss = dst_metric_raw(dst, RTAX_ADVMSS); |
170 | |||
171 | if (!advmss) | ||
172 | advmss = dst->ops->default_advmss(dst); | ||
173 | |||
174 | return advmss; | ||
175 | } | ||
176 | |||
177 | static inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val) | ||
178 | { | ||
179 | u32 *p = dst_metrics_write_ptr(dst); | ||
180 | |||
181 | if (p) | ||
182 | p[metric-1] = val; | ||
109 | } | 183 | } |
110 | 184 | ||
111 | static inline u32 | 185 | static inline u32 |
@@ -116,11 +190,11 @@ dst_feature(const struct dst_entry *dst, u32 feature) | |||
116 | 190 | ||
117 | static inline u32 dst_mtu(const struct dst_entry *dst) | 191 | static inline u32 dst_mtu(const struct dst_entry *dst) |
118 | { | 192 | { |
119 | u32 mtu = dst_metric(dst, RTAX_MTU); | 193 | u32 mtu = dst_metric_raw(dst, RTAX_MTU); |
120 | /* | 194 | |
121 | * Alexey put it here, so ask him about it :) | 195 | if (!mtu) |
122 | */ | 196 | mtu = dst->ops->default_mtu(dst); |
123 | barrier(); | 197 | |
124 | return mtu; | 198 | return mtu; |
125 | } | 199 | } |
126 | 200 | ||
@@ -133,20 +207,18 @@ static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metr | |||
133 | static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric, | 207 | static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric, |
134 | unsigned long rtt) | 208 | unsigned long rtt) |
135 | { | 209 | { |
136 | dst->metrics[metric-1] = jiffies_to_msecs(rtt); | 210 | dst_metric_set(dst, metric, jiffies_to_msecs(rtt)); |
137 | } | 211 | } |
138 | 212 | ||
139 | static inline u32 | 213 | static inline u32 |
140 | dst_allfrag(const struct dst_entry *dst) | 214 | dst_allfrag(const struct dst_entry *dst) |
141 | { | 215 | { |
142 | int ret = dst_feature(dst, RTAX_FEATURE_ALLFRAG); | 216 | int ret = dst_feature(dst, RTAX_FEATURE_ALLFRAG); |
143 | /* Yes, _exactly_. This is paranoia. */ | ||
144 | barrier(); | ||
145 | return ret; | 217 | return ret; |
146 | } | 218 | } |
147 | 219 | ||
148 | static inline int | 220 | static inline int |
149 | dst_metric_locked(struct dst_entry *dst, int metric) | 221 | dst_metric_locked(const struct dst_entry *dst, int metric) |
150 | { | 222 | { |
151 | return dst_metric(dst, RTAX_LOCK) & (1<<metric); | 223 | return dst_metric(dst, RTAX_LOCK) & (1<<metric); |
152 | } | 224 | } |
@@ -228,23 +300,37 @@ static inline void skb_dst_force(struct sk_buff *skb) | |||
228 | 300 | ||
229 | 301 | ||
230 | /** | 302 | /** |
303 | * __skb_tunnel_rx - prepare skb for rx reinsert | ||
304 | * @skb: buffer | ||
305 | * @dev: tunnel device | ||
306 | * | ||
307 | * After decapsulation, packet is going to re-enter (netif_rx()) our stack, | ||
308 | * so make some cleanups. (no accounting done) | ||
309 | */ | ||
310 | static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) | ||
311 | { | ||
312 | skb->dev = dev; | ||
313 | skb->rxhash = 0; | ||
314 | skb_set_queue_mapping(skb, 0); | ||
315 | skb_dst_drop(skb); | ||
316 | nf_reset(skb); | ||
317 | } | ||
318 | |||
319 | /** | ||
231 | * skb_tunnel_rx - prepare skb for rx reinsert | 320 | * skb_tunnel_rx - prepare skb for rx reinsert |
232 | * @skb: buffer | 321 | * @skb: buffer |
233 | * @dev: tunnel device | 322 | * @dev: tunnel device |
234 | * | 323 | * |
235 | * After decapsulation, packet is going to re-enter (netif_rx()) our stack, | 324 | * After decapsulation, packet is going to re-enter (netif_rx()) our stack, |
236 | * so make some cleanups, and perform accounting. | 325 | * so make some cleanups, and perform accounting. |
326 | * Note: this accounting is not SMP safe. | ||
237 | */ | 327 | */ |
238 | static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) | 328 | static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) |
239 | { | 329 | { |
240 | skb->dev = dev; | ||
241 | /* TODO : stats should be SMP safe */ | 330 | /* TODO : stats should be SMP safe */ |
242 | dev->stats.rx_packets++; | 331 | dev->stats.rx_packets++; |
243 | dev->stats.rx_bytes += skb->len; | 332 | dev->stats.rx_bytes += skb->len; |
244 | skb->rxhash = 0; | 333 | __skb_tunnel_rx(skb, dev); |
245 | skb_set_queue_mapping(skb, 0); | ||
246 | skb_dst_drop(skb); | ||
247 | nf_reset(skb); | ||
248 | } | 334 | } |
249 | 335 | ||
250 | /* Children define the path of the packet through the | 336 | /* Children define the path of the packet through the |
@@ -253,14 +339,15 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) | |||
253 | 339 | ||
254 | static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) | 340 | static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) |
255 | { | 341 | { |
256 | struct dst_entry *child = skb_dst(skb)->child; | 342 | struct dst_entry *child = dst_clone(skb_dst(skb)->child); |
257 | 343 | ||
258 | skb_dst_drop(skb); | 344 | skb_dst_drop(skb); |
259 | return child; | 345 | return child; |
260 | } | 346 | } |
261 | 347 | ||
262 | extern int dst_discard(struct sk_buff *skb); | 348 | extern int dst_discard(struct sk_buff *skb); |
263 | extern void * dst_alloc(struct dst_ops * ops); | 349 | extern void *dst_alloc(struct dst_ops * ops, struct net_device *dev, |
350 | int initial_ref, int initial_obsolete, int flags); | ||
264 | extern void __dst_free(struct dst_entry * dst); | 351 | extern void __dst_free(struct dst_entry * dst); |
265 | extern struct dst_entry *dst_destroy(struct dst_entry * dst); | 352 | extern struct dst_entry *dst_destroy(struct dst_entry * dst); |
266 | 353 | ||
@@ -329,28 +416,22 @@ extern void dst_init(void); | |||
329 | 416 | ||
330 | /* Flags for xfrm_lookup flags argument. */ | 417 | /* Flags for xfrm_lookup flags argument. */ |
331 | enum { | 418 | enum { |
332 | XFRM_LOOKUP_WAIT = 1 << 0, | 419 | XFRM_LOOKUP_ICMP = 1 << 0, |
333 | XFRM_LOOKUP_ICMP = 1 << 1, | ||
334 | }; | 420 | }; |
335 | 421 | ||
336 | struct flowi; | 422 | struct flowi; |
337 | #ifndef CONFIG_XFRM | 423 | #ifndef CONFIG_XFRM |
338 | static inline int xfrm_lookup(struct net *net, struct dst_entry **dst_p, | 424 | static inline struct dst_entry *xfrm_lookup(struct net *net, |
339 | struct flowi *fl, struct sock *sk, int flags) | 425 | struct dst_entry *dst_orig, |
426 | const struct flowi *fl, struct sock *sk, | ||
427 | int flags) | ||
340 | { | 428 | { |
341 | return 0; | 429 | return dst_orig; |
342 | } | 430 | } |
343 | static inline int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, | ||
344 | struct flowi *fl, struct sock *sk, int flags) | ||
345 | { | ||
346 | return 0; | ||
347 | } | ||
348 | #else | 431 | #else |
349 | extern int xfrm_lookup(struct net *net, struct dst_entry **dst_p, | 432 | extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, |
350 | struct flowi *fl, struct sock *sk, int flags); | 433 | const struct flowi *fl, struct sock *sk, |
351 | extern int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, | 434 | int flags); |
352 | struct flowi *fl, struct sock *sk, int flags); | ||
353 | #endif | ||
354 | #endif | 435 | #endif |
355 | 436 | ||
356 | #endif /* _NET_DST_H */ | 437 | #endif /* _NET_DST_H */ |