summaryrefslogtreecommitdiff
path: root/include/net/dst.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/dst.h')
-rw-r--r--include/net/dst.h56
1 files changed, 43 insertions, 13 deletions
diff --git a/include/net/dst.h b/include/net/dst.h
index 9261d9283..c7329dcd9 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -45,7 +45,7 @@ struct dst_entry {
void *__pad1;
#endif
int (*input)(struct sk_buff *);
- int (*output)(struct sock *sk, struct sk_buff *skb);
+ int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
unsigned short flags;
#define DST_HOST 0x0001
@@ -322,6 +322,39 @@ static inline void skb_dst_force(struct sk_buff *skb)
}
}
+/**
+ * dst_hold_safe - Take a reference on a dst if possible
+ * @dst: pointer to dst entry
+ *
+ * This helper returns false if it could not safely
+ * take a reference on a dst.
+ */
+static inline bool dst_hold_safe(struct dst_entry *dst)
+{
+ if (dst->flags & DST_NOCACHE)
+ return atomic_inc_not_zero(&dst->__refcnt);
+ dst_hold(dst);
+ return true;
+}
+
+/**
+ * skb_dst_force_safe - makes sure skb dst is refcounted
+ * @skb: buffer
+ *
+ * If dst is not yet refcounted and not destroyed, grab a ref on it.
+ */
+static inline void skb_dst_force_safe(struct sk_buff *skb)
+{
+ if (skb_dst_is_noref(skb)) {
+ struct dst_entry *dst = skb_dst(skb);
+
+ if (!dst_hold_safe(dst))
+ dst = NULL;
+
+ skb->_skb_refdst = (unsigned long)dst;
+ }
+}
+
/**
* __skb_tunnel_rx - prepare skb for rx reinsert
@@ -365,10 +398,10 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev,
__skb_tunnel_rx(skb, dev, net);
}
-int dst_discard_sk(struct sock *sk, struct sk_buff *skb);
+int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb);
static inline int dst_discard(struct sk_buff *skb)
{
- return dst_discard_sk(skb->sk, skb);
+ return dst_discard_out(&init_net, skb->sk, skb);
}
void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref,
int initial_obsolete, unsigned short flags);
@@ -454,13 +487,9 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
}
/* Output packet to network from transport. */
-static inline int dst_output_sk(struct sock *sk, struct sk_buff *skb)
-{
- return skb_dst(skb)->output(sk, skb);
-}
-static inline int dst_output(struct sk_buff *skb)
+static inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
- return dst_output_sk(skb->sk, skb);
+ return skb_dst(skb)->output(net, sk, skb);
}
/* Input packet from network to transport. */
@@ -489,7 +518,8 @@ struct flowi;
#ifndef CONFIG_XFRM
static inline struct dst_entry *xfrm_lookup(struct net *net,
struct dst_entry *dst_orig,
- const struct flowi *fl, struct sock *sk,
+ const struct flowi *fl,
+ const struct sock *sk,
int flags)
{
return dst_orig;
@@ -498,7 +528,7 @@ static inline struct dst_entry *xfrm_lookup(struct net *net,
static inline struct dst_entry *xfrm_lookup_route(struct net *net,
struct dst_entry *dst_orig,
const struct flowi *fl,
- struct sock *sk,
+ const struct sock *sk,
int flags)
{
return dst_orig;
@@ -511,11 +541,11 @@ static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
#else
struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
- const struct flowi *fl, struct sock *sk,
+ const struct flowi *fl, const struct sock *sk,
int flags);
struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
- const struct flowi *fl, struct sock *sk,
+ const struct flowi *fl, const struct sock *sk,
int flags);
/* skb attached with this dst needs transformation if dst->xfrm is valid */