diff options
author | David S. Miller <davem@davemloft.net> | 2012-07-02 05:21:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-05 04:03:06 -0400 |
commit | 5110effee8fde2edfacac9cd12a9960ab2dc39ea (patch) | |
tree | f74fff97af20ffdf805fedc56f0c8f88bbef2df7 /include/net/dst.h | |
parent | 60d354ebebd9d0f760cb6c3b9f53a7ade0f8cd0e (diff) |
net: Do delayed neigh confirmation.
When a dst_confirm() happens, mark the confirmation as pending in the
dst. Then on the next packet out, when we have the neigh in-hand, do
the update.
This removes the dependency in dst_confirm() of dst's having an
attached neigh.
While we're here, remove the explicit 'dst' NULL check, all except 2
or 3 call sites ensure it's not NULL. So just fix those cases up.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/dst.h')
-rw-r--r-- | include/net/dst.h | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/include/net/dst.h b/include/net/dst.h index f0bf3b8d5911..84e7a3ff968d 100644 --- a/include/net/dst.h +++ b/include/net/dst.h | |||
@@ -51,7 +51,7 @@ struct dst_entry { | |||
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,6 +62,8 @@ 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; |
66 | short obsolete; | 68 | short obsolete; |
67 | unsigned short header_len; /* more space at head required */ | 69 | unsigned short header_len; /* more space at head required */ |
@@ -371,7 +373,8 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) | |||
371 | 373 | ||
372 | extern int dst_discard(struct sk_buff *skb); | 374 | extern int dst_discard(struct sk_buff *skb); |
373 | extern void *dst_alloc(struct dst_ops *ops, struct net_device *dev, | 375 | extern void *dst_alloc(struct dst_ops *ops, struct net_device *dev, |
374 | int initial_ref, int initial_obsolete, int flags); | 376 | int initial_ref, int initial_obsolete, |
377 | unsigned short flags); | ||
375 | extern void __dst_free(struct dst_entry *dst); | 378 | extern void __dst_free(struct dst_entry *dst); |
376 | extern struct dst_entry *dst_destroy(struct dst_entry *dst); | 379 | extern struct dst_entry *dst_destroy(struct dst_entry *dst); |
377 | 380 | ||
@@ -395,14 +398,24 @@ static inline void dst_rcu_free(struct rcu_head *head) | |||
395 | 398 | ||
396 | static inline void dst_confirm(struct dst_entry *dst) | 399 | static inline void dst_confirm(struct dst_entry *dst) |
397 | { | 400 | { |
398 | if (dst) { | 401 | dst->pending_confirm = 1; |
399 | struct neighbour *n; | 402 | } |
400 | 403 | ||
401 | rcu_read_lock(); | 404 | static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n, |
402 | n = dst_get_neighbour_noref(dst); | 405 | struct sk_buff *skb) |
403 | neigh_confirm(n); | 406 | { |
404 | rcu_read_unlock(); | 407 | struct hh_cache *hh; |
408 | |||
409 | if (unlikely(dst->pending_confirm)) { | ||
410 | n->confirmed = jiffies; | ||
411 | dst->pending_confirm = 0; | ||
405 | } | 412 | } |
413 | |||
414 | hh = &n->hh; | ||
415 | if ((n->nud_state & NUD_CONNECTED) && hh->hh_len) | ||
416 | return neigh_hh_output(hh, skb); | ||
417 | else | ||
418 | return n->output(n, skb); | ||
406 | } | 419 | } |
407 | 420 | ||
408 | static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) | 421 | static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) |