aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/dst.h
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-07-02 05:21:03 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-05 04:03:06 -0400
commit5110effee8fde2edfacac9cd12a9960ab2dc39ea (patch)
treef74fff97af20ffdf805fedc56f0c8f88bbef2df7 /include/net/dst.h
parent60d354ebebd9d0f760cb6c3b9f53a7ade0f8cd0e (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.h29
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
372extern int dst_discard(struct sk_buff *skb); 374extern int dst_discard(struct sk_buff *skb);
373extern void *dst_alloc(struct dst_ops *ops, struct net_device *dev, 375extern 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);
375extern void __dst_free(struct dst_entry *dst); 378extern void __dst_free(struct dst_entry *dst);
376extern struct dst_entry *dst_destroy(struct dst_entry *dst); 379extern 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
396static inline void dst_confirm(struct dst_entry *dst) 399static 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(); 404static 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
408static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) 421static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)