diff options
Diffstat (limited to 'include/net/dst.h')
| -rw-r--r-- | include/net/dst.h | 172 |
1 files changed, 109 insertions, 63 deletions
diff --git a/include/net/dst.h b/include/net/dst.h index 344c8dd0287..71c60f42be4 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -12,6 +12,7 @@ #include <linux/netdevice.h> #include <linux/rtnetlink.h> #include <linux/rcupdate.h> +#include <linux/bug.h> #include <linux/jiffies.h> #include <net/neighbour.h> #include <asm/processor.h> @@ -35,28 +36,45 @@ struct dst_entry { struct net_device *dev; struct dst_ops *ops; unsigned long _metrics; - unsigned long expires; + unsigned long expires; struct dst_entry *path; - struct neighbour __rcu *_neighbour; + struct dst_entry *from; #ifdef CONFIG_XFRM struct xfrm_state *xfrm; #else void *__pad1; #endif - int (*input)(struct sk_buff*); - int (*output)(struct sk_buff*); + int (*input)(struct sk_buff *); + int (*output)(struct sock *sk, struct sk_buff *skb); - int flags; + unsigned short flags; #define DST_HOST 0x0001 #define DST_NOXFRM 0x0002 #define DST_NOPOLICY 0x0004 #define DST_NOHASH 0x0008 #define DST_NOCACHE 0x0010 #define DST_NOCOUNT 0x0020 -#define DST_NOPEER 0x0040 +#define DST_FAKE_RTABLE 0x0040 +#define DST_XFRM_TUNNEL 0x0080 +#define DST_XFRM_QUEUE 0x0100 + + unsigned short pending_confirm; short error; + + /* A non-zero value of dst->obsolete forces by-hand validation + * of the route entry. Positive values are set by the generic + * dst layer to indicate that the entry has been forcefully + * destroyed. + * + * Negative values are used by the implementation layer code to + * force invocation of the dst_ops->check() method. + */ short obsolete; +#define DST_OBSOLETE_NONE 0 +#define DST_OBSOLETE_DEAD 2 +#define DST_OBSOLETE_FORCE_CHK -1 +#define DST_OBSOLETE_KILL -2 unsigned short header_len; /* more space at head required */ unsigned short trailer_len; /* space to reserve at tail */ #ifdef CONFIG_IP_ROUTE_CLASSID @@ -87,27 +105,14 @@ struct dst_entry { }; }; -static inline struct neighbour *dst_get_neighbour_noref(struct dst_entry *dst) -{ - return rcu_dereference(dst->_neighbour); -} - -static inline struct neighbour *dst_get_neighbour_noref_raw(struct dst_entry *dst) -{ - return rcu_dereference_raw(dst->_neighbour); -} +u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); +extern const u32 dst_default_metrics[]; -static inline void dst_set_neighbour(struct dst_entry *dst, struct neighbour *neigh) -{ - rcu_assign_pointer(dst->_neighbour, neigh); -} - -extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); -extern const u32 dst_default_metrics[RTAX_MAX]; - -#define DST_METRICS_READ_ONLY 0x1UL +#define DST_METRICS_READ_ONLY 0x1UL +#define DST_METRICS_FORCE_OVERWRITE 0x2UL +#define DST_METRICS_FLAGS 0x3UL #define __DST_METRICS_PTR(Y) \ - ((u32 *)((Y) & ~DST_METRICS_READ_ONLY)) + ((u32 *)((Y) & ~DST_METRICS_FLAGS)) #define DST_METRICS_PTR(X) __DST_METRICS_PTR((X)->_metrics) static inline bool dst_metrics_read_only(const struct dst_entry *dst) @@ -115,7 +120,12 @@ static inline bool dst_metrics_read_only(const struct dst_entry *dst) return dst->_metrics & DST_METRICS_READ_ONLY; } -extern void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old); +static inline void dst_metrics_set_force_overwrite(struct dst_entry *dst) +{ + dst->_metrics |= DST_METRICS_FORCE_OVERWRITE; +} + +void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old); static inline void dst_destroy_metrics_generic(struct dst_entry *dst) { @@ -215,12 +225,6 @@ static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metr return msecs_to_jiffies(dst_metric(dst, metric)); } -static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric, - unsigned long rtt) -{ - dst_metric_set(dst, metric, jiffies_to_msecs(rtt)); -} - static inline u32 dst_allfrag(const struct dst_entry *dst) { @@ -234,7 +238,7 @@ dst_metric_locked(const struct dst_entry *dst, int metric) return dst_metric(dst, RTAX_LOCK) & (1<<metric); } -static inline void dst_hold(struct dst_entry * dst) +static inline void dst_hold(struct dst_entry *dst) { /* * If your kernel compilation stops here, please check @@ -257,15 +261,14 @@ static inline void dst_use_noref(struct dst_entry *dst, unsigned long time) dst->lastuse = time; } -static inline -struct dst_entry * dst_clone(struct dst_entry * dst) +static inline struct dst_entry *dst_clone(struct dst_entry *dst) { if (dst) atomic_inc(&dst->__refcnt); return dst; } -extern void dst_release(struct dst_entry *dst); +void dst_release(struct dst_entry *dst); static inline void refdst_drop(unsigned long refdst) { @@ -314,24 +317,24 @@ static inline void skb_dst_force(struct sk_buff *skb) * __skb_tunnel_rx - prepare skb for rx reinsert * @skb: buffer * @dev: tunnel device + * @net: netns for packet i/o * * After decapsulation, packet is going to re-enter (netif_rx()) our stack, * so make some cleanups. (no accounting done) */ -static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) +static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, + struct net *net) { skb->dev = dev; /* - * Clear rxhash so that we can recalulate the hash for the + * Clear hash so that we can recalulate the hash for the * encapsulated packet, unless we have already determine the hash * over the L4 4-tuple. */ - if (!skb->l4_rxhash) - skb->rxhash = 0; + skb_clear_hash_if_not_l4(skb); skb_set_queue_mapping(skb, 0); - skb_dst_drop(skb); - nf_reset(skb); + skb_scrub_packet(skb, !net_eq(net, dev_net(dev))); } /** @@ -343,12 +346,13 @@ static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) * so make some cleanups, and perform accounting. * Note: this accounting is not SMP safe. */ -static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) +static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, + struct net *net) { /* TODO : stats should be SMP safe */ dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; - __skb_tunnel_rx(skb, dev); + __skb_tunnel_rx(skb, dev, net); } /* Children define the path of the packet through the @@ -363,15 +367,19 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) return child; } -extern int dst_discard(struct sk_buff *skb); -extern void *dst_alloc(struct dst_ops * ops, struct net_device *dev, - int initial_ref, int initial_obsolete, int flags); -extern void __dst_free(struct dst_entry * dst); -extern struct dst_entry *dst_destroy(struct dst_entry * dst); +int dst_discard_sk(struct sock *sk, struct sk_buff *skb); +static inline int dst_discard(struct sk_buff *skb) +{ + return dst_discard_sk(skb->sk, skb); +} +void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref, + int initial_obsolete, unsigned short flags); +void __dst_free(struct dst_entry *dst); +struct dst_entry *dst_destroy(struct dst_entry *dst); -static inline void dst_free(struct dst_entry * dst) +static inline void dst_free(struct dst_entry *dst) { - if (dst->obsolete > 1) + if (dst->obsolete > 0) return; if (!atomic_read(&dst->__refcnt)) { dst = dst_destroy(dst); @@ -389,19 +397,41 @@ static inline void dst_rcu_free(struct rcu_head *head) static inline void dst_confirm(struct dst_entry *dst) { - if (dst) { - struct neighbour *n; + dst->pending_confirm = 1; +} + +static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n, + struct sk_buff *skb) +{ + const struct hh_cache *hh; - rcu_read_lock(); - n = dst_get_neighbour_noref(dst); - neigh_confirm(n); - rcu_read_unlock(); + if (dst->pending_confirm) { + unsigned long now = jiffies; + + dst->pending_confirm = 0; + /* avoid dirtying neighbour */ + if (n->confirmed != now) + n->confirmed = now; } + + hh = &n->hh; + if ((n->nud_state & NUD_CONNECTED) && hh->hh_len) + return neigh_hh_output(hh, skb); + else + return n->output(n, skb); } static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) { - return dst->ops->neigh_lookup(dst, daddr); + struct neighbour *n = dst->ops->neigh_lookup(dst, NULL, daddr); + return IS_ERR(n) ? NULL : n; +} + +static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst, + struct sk_buff *skb) +{ + struct neighbour *n = dst->ops->neigh_lookup(dst, skb, NULL); + return IS_ERR(n) ? NULL : n; } static inline void dst_link_failure(struct sk_buff *skb) @@ -423,9 +453,13 @@ 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) { - return skb_dst(skb)->output(skb); + return dst_output_sk(skb->sk, skb); } /* Input packet from network to transport. */ @@ -441,7 +475,7 @@ static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie) return dst; } -extern void dst_init(void); +void dst_init(void); /* Flags for xfrm_lookup flags argument. */ enum { @@ -457,10 +491,22 @@ static inline struct dst_entry *xfrm_lookup(struct net *net, { return dst_orig; } + +static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) +{ + return NULL; +} + #else -extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, - const struct flowi *fl, struct sock *sk, - int flags); +struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, + const struct flowi *fl, struct sock *sk, + int flags); + +/* skb attached with this dst needs transformation if dst->xfrm is valid */ +static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) +{ + return dst->xfrm; +} #endif #endif /* _NET_DST_H */ |
