diff options
Diffstat (limited to 'include/net/dst.h')
-rw-r--r-- | include/net/dst.h | 92 |
1 files changed, 51 insertions, 41 deletions
diff --git a/include/net/dst.h b/include/net/dst.h index 8197eadca819..baf597890064 100644 --- a/include/net/dst.h +++ b/include/net/dst.h | |||
@@ -42,16 +42,16 @@ struct dst_entry { | |||
42 | struct dst_entry *from; | 42 | struct dst_entry *from; |
43 | }; | 43 | }; |
44 | struct dst_entry *path; | 44 | struct dst_entry *path; |
45 | struct neighbour __rcu *_neighbour; | 45 | void *__pad0; |
46 | #ifdef CONFIG_XFRM | 46 | #ifdef CONFIG_XFRM |
47 | struct xfrm_state *xfrm; | 47 | struct xfrm_state *xfrm; |
48 | #else | 48 | #else |
49 | void *__pad1; | 49 | void *__pad1; |
50 | #endif | 50 | #endif |
51 | int (*input)(struct sk_buff*); | 51 | int (*input)(struct sk_buff *); |
52 | int (*output)(struct sk_buff*); | 52 | int (*output)(struct sk_buff *); |
53 | 53 | ||
54 | int flags; | 54 | unsigned short flags; |
55 | #define DST_HOST 0x0001 | 55 | #define DST_HOST 0x0001 |
56 | #define DST_NOXFRM 0x0002 | 56 | #define DST_NOXFRM 0x0002 |
57 | #define DST_NOPOLICY 0x0004 | 57 | #define DST_NOPOLICY 0x0004 |
@@ -62,8 +62,23 @@ struct dst_entry { | |||
62 | #define DST_FAKE_RTABLE 0x0080 | 62 | #define DST_FAKE_RTABLE 0x0080 |
63 | #define DST_XFRM_TUNNEL 0x0100 | 63 | #define DST_XFRM_TUNNEL 0x0100 |
64 | 64 | ||
65 | unsigned short pending_confirm; | ||
66 | |||
65 | short error; | 67 | short error; |
68 | |||
69 | /* A non-zero value of dst->obsolete forces by-hand validation | ||
70 | * of the route entry. Positive values are set by the generic | ||
71 | * dst layer to indicate that the entry has been forcefully | ||
72 | * destroyed. | ||
73 | * | ||
74 | * Negative values are used by the implementation layer code to | ||
75 | * force invocation of the dst_ops->check() method. | ||
76 | */ | ||
66 | short obsolete; | 77 | short obsolete; |
78 | #define DST_OBSOLETE_NONE 0 | ||
79 | #define DST_OBSOLETE_DEAD 2 | ||
80 | #define DST_OBSOLETE_FORCE_CHK -1 | ||
81 | #define DST_OBSOLETE_KILL -2 | ||
67 | unsigned short header_len; /* more space at head required */ | 82 | unsigned short header_len; /* more space at head required */ |
68 | unsigned short trailer_len; /* space to reserve at tail */ | 83 | unsigned short trailer_len; /* space to reserve at tail */ |
69 | #ifdef CONFIG_IP_ROUTE_CLASSID | 84 | #ifdef CONFIG_IP_ROUTE_CLASSID |
@@ -94,21 +109,6 @@ struct dst_entry { | |||
94 | }; | 109 | }; |
95 | }; | 110 | }; |
96 | 111 | ||
97 | static inline struct neighbour *dst_get_neighbour_noref(struct dst_entry *dst) | ||
98 | { | ||
99 | return rcu_dereference(dst->_neighbour); | ||
100 | } | ||
101 | |||
102 | static inline struct neighbour *dst_get_neighbour_noref_raw(struct dst_entry *dst) | ||
103 | { | ||
104 | return rcu_dereference_raw(dst->_neighbour); | ||
105 | } | ||
106 | |||
107 | static inline void dst_set_neighbour(struct dst_entry *dst, struct neighbour *neigh) | ||
108 | { | ||
109 | rcu_assign_pointer(dst->_neighbour, neigh); | ||
110 | } | ||
111 | |||
112 | extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); | 112 | extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); |
113 | extern const u32 dst_default_metrics[RTAX_MAX]; | 113 | extern const u32 dst_default_metrics[RTAX_MAX]; |
114 | 114 | ||
@@ -222,12 +222,6 @@ static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metr | |||
222 | return msecs_to_jiffies(dst_metric(dst, metric)); | 222 | return msecs_to_jiffies(dst_metric(dst, metric)); |
223 | } | 223 | } |
224 | 224 | ||
225 | static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric, | ||
226 | unsigned long rtt) | ||
227 | { | ||
228 | dst_metric_set(dst, metric, jiffies_to_msecs(rtt)); | ||
229 | } | ||
230 | |||
231 | static inline u32 | 225 | static inline u32 |
232 | dst_allfrag(const struct dst_entry *dst) | 226 | dst_allfrag(const struct dst_entry *dst) |
233 | { | 227 | { |
@@ -241,7 +235,7 @@ dst_metric_locked(const struct dst_entry *dst, int metric) | |||
241 | return dst_metric(dst, RTAX_LOCK) & (1<<metric); | 235 | return dst_metric(dst, RTAX_LOCK) & (1<<metric); |
242 | } | 236 | } |
243 | 237 | ||
244 | static inline void dst_hold(struct dst_entry * dst) | 238 | static inline void dst_hold(struct dst_entry *dst) |
245 | { | 239 | { |
246 | /* | 240 | /* |
247 | * If your kernel compilation stops here, please check | 241 | * If your kernel compilation stops here, please check |
@@ -264,8 +258,7 @@ static inline void dst_use_noref(struct dst_entry *dst, unsigned long time) | |||
264 | dst->lastuse = time; | 258 | dst->lastuse = time; |
265 | } | 259 | } |
266 | 260 | ||
267 | static inline | 261 | static inline struct dst_entry *dst_clone(struct dst_entry *dst) |
268 | struct dst_entry * dst_clone(struct dst_entry * dst) | ||
269 | { | 262 | { |
270 | if (dst) | 263 | if (dst) |
271 | atomic_inc(&dst->__refcnt); | 264 | atomic_inc(&dst->__refcnt); |
@@ -371,14 +364,15 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) | |||
371 | } | 364 | } |
372 | 365 | ||
373 | extern int dst_discard(struct sk_buff *skb); | 366 | extern int dst_discard(struct sk_buff *skb); |
374 | extern void *dst_alloc(struct dst_ops * ops, struct net_device *dev, | 367 | extern void *dst_alloc(struct dst_ops *ops, struct net_device *dev, |
375 | int initial_ref, int initial_obsolete, int flags); | 368 | int initial_ref, int initial_obsolete, |
376 | extern void __dst_free(struct dst_entry * dst); | 369 | unsigned short flags); |
377 | extern struct dst_entry *dst_destroy(struct dst_entry * dst); | 370 | extern void __dst_free(struct dst_entry *dst); |
371 | extern struct dst_entry *dst_destroy(struct dst_entry *dst); | ||
378 | 372 | ||
379 | static inline void dst_free(struct dst_entry * dst) | 373 | static inline void dst_free(struct dst_entry *dst) |
380 | { | 374 | { |
381 | if (dst->obsolete > 1) | 375 | if (dst->obsolete > 0) |
382 | return; | 376 | return; |
383 | if (!atomic_read(&dst->__refcnt)) { | 377 | if (!atomic_read(&dst->__refcnt)) { |
384 | dst = dst_destroy(dst); | 378 | dst = dst_destroy(dst); |
@@ -396,19 +390,35 @@ static inline void dst_rcu_free(struct rcu_head *head) | |||
396 | 390 | ||
397 | static inline void dst_confirm(struct dst_entry *dst) | 391 | static inline void dst_confirm(struct dst_entry *dst) |
398 | { | 392 | { |
399 | if (dst) { | 393 | dst->pending_confirm = 1; |
400 | struct neighbour *n; | 394 | } |
401 | 395 | ||
402 | rcu_read_lock(); | 396 | static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n, |
403 | n = dst_get_neighbour_noref(dst); | 397 | struct sk_buff *skb) |
404 | neigh_confirm(n); | 398 | { |
405 | rcu_read_unlock(); | 399 | struct hh_cache *hh; |
400 | |||
401 | if (unlikely(dst->pending_confirm)) { | ||
402 | n->confirmed = jiffies; | ||
403 | dst->pending_confirm = 0; | ||
406 | } | 404 | } |
405 | |||
406 | hh = &n->hh; | ||
407 | if ((n->nud_state & NUD_CONNECTED) && hh->hh_len) | ||
408 | return neigh_hh_output(hh, skb); | ||
409 | else | ||
410 | return n->output(n, skb); | ||
407 | } | 411 | } |
408 | 412 | ||
409 | static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) | 413 | static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) |
410 | { | 414 | { |
411 | return dst->ops->neigh_lookup(dst, daddr); | 415 | return dst->ops->neigh_lookup(dst, NULL, daddr); |
416 | } | ||
417 | |||
418 | static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst, | ||
419 | struct sk_buff *skb) | ||
420 | { | ||
421 | return dst->ops->neigh_lookup(dst, skb, NULL); | ||
412 | } | 422 | } |
413 | 423 | ||
414 | static inline void dst_link_failure(struct sk_buff *skb) | 424 | static inline void dst_link_failure(struct sk_buff *skb) |