xref: /openbmc/linux/include/net/dst.h (revision 52479b623d3d41df84c499325b6a8c7915413032)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * net/dst.h	Protocol independent destination cache definitions.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  */
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds #ifndef _NET_DST_H
91da177e4SLinus Torvalds #define _NET_DST_H
101da177e4SLinus Torvalds 
1114c85021SArnaldo Carvalho de Melo #include <linux/netdevice.h>
121da177e4SLinus Torvalds #include <linux/rtnetlink.h>
131da177e4SLinus Torvalds #include <linux/rcupdate.h>
141da177e4SLinus Torvalds #include <linux/jiffies.h>
151da177e4SLinus Torvalds #include <net/neighbour.h>
161da177e4SLinus Torvalds #include <asm/processor.h>
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds /*
191da177e4SLinus Torvalds  * 0 - no debugging messages
201da177e4SLinus Torvalds  * 1 - rare events and bugs (default)
211da177e4SLinus Torvalds  * 2 - trace mode.
221da177e4SLinus Torvalds  */
231da177e4SLinus Torvalds #define RT_CACHE_DEBUG		0
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds #define DST_GC_MIN	(HZ/10)
261da177e4SLinus Torvalds #define DST_GC_INC	(HZ/2)
271da177e4SLinus Torvalds #define DST_GC_MAX	(120*HZ)
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds /* Each dst_entry has reference count and sits in some parent list(s).
301da177e4SLinus Torvalds  * When it is removed from parent list, it is "freed" (dst_free).
311da177e4SLinus Torvalds  * After this it enters dead state (dst->obsolete > 0) and if its refcnt
321da177e4SLinus Torvalds  * is zero, it can be destroyed immediately, otherwise it is added
331da177e4SLinus Torvalds  * to gc list and garbage collector periodically checks the refcnt.
341da177e4SLinus Torvalds  */
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds struct sk_buff;
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds struct dst_entry
391da177e4SLinus Torvalds {
401e19e02cSEric Dumazet 	struct rcu_head		rcu_head;
411da177e4SLinus Torvalds 	struct dst_entry	*child;
421da177e4SLinus Torvalds 	struct net_device       *dev;
43c4d54110SHerbert Xu 	short			error;
44c4d54110SHerbert Xu 	short			obsolete;
451da177e4SLinus Torvalds 	int			flags;
461da177e4SLinus Torvalds #define DST_HOST		1
471da177e4SLinus Torvalds #define DST_NOXFRM		2
481da177e4SLinus Torvalds #define DST_NOPOLICY		4
491da177e4SLinus Torvalds #define DST_NOHASH		8
501da177e4SLinus Torvalds 	unsigned long		expires;
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds 	unsigned short		header_len;	/* more space at head required */
531da177e4SLinus Torvalds 	unsigned short		trailer_len;	/* space to reserve at tail */
541da177e4SLinus Torvalds 
5569a73829SEric Dumazet 	unsigned int		rate_tokens;
56f1dd9c37SZhang Yanmin 	unsigned long		rate_last;	/* rate limiting for ICMP */
5769a73829SEric Dumazet 
58f1dd9c37SZhang Yanmin 	struct dst_entry	*path;
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds 	struct neighbour	*neighbour;
611da177e4SLinus Torvalds 	struct hh_cache		*hh;
62def8b4faSAlexey Dobriyan #ifdef CONFIG_XFRM
631da177e4SLinus Torvalds 	struct xfrm_state	*xfrm;
645635c10dSEric Dumazet #else
655635c10dSEric Dumazet 	void			*__pad1;
66def8b4faSAlexey Dobriyan #endif
671da177e4SLinus Torvalds 	int			(*input)(struct sk_buff*);
681da177e4SLinus Torvalds 	int			(*output)(struct sk_buff*);
691da177e4SLinus Torvalds 
701da177e4SLinus Torvalds 	struct  dst_ops	        *ops;
711da177e4SLinus Torvalds 
72f1dd9c37SZhang Yanmin 	u32			metrics[RTAX_MAX];
73f1dd9c37SZhang Yanmin 
74f1dd9c37SZhang Yanmin #ifdef CONFIG_NET_CLS_ROUTE
75f1dd9c37SZhang Yanmin 	__u32			tclassid;
765635c10dSEric Dumazet #else
775635c10dSEric Dumazet 	__u32			__pad2;
78f1dd9c37SZhang Yanmin #endif
79f1dd9c37SZhang Yanmin 
805635c10dSEric Dumazet 
815635c10dSEric Dumazet 	/*
825635c10dSEric Dumazet 	 * Align __refcnt to a 64 bytes alignment
835635c10dSEric Dumazet 	 * (L1_CACHE_SIZE would be too much)
845635c10dSEric Dumazet 	 */
855635c10dSEric Dumazet #ifdef CONFIG_64BIT
865635c10dSEric Dumazet 	long			__pad_to_align_refcnt[2];
875635c10dSEric Dumazet #else
885635c10dSEric Dumazet 	long			__pad_to_align_refcnt[1];
895635c10dSEric Dumazet #endif
90f1dd9c37SZhang Yanmin 	/*
91f1dd9c37SZhang Yanmin 	 * __refcnt wants to be on a different cache line from
92f1dd9c37SZhang Yanmin 	 * input/output/ops or performance tanks badly
93f1dd9c37SZhang Yanmin 	 */
941e19e02cSEric Dumazet 	atomic_t		__refcnt;	/* client references	*/
951e19e02cSEric Dumazet 	int			__use;
96f1dd9c37SZhang Yanmin 	unsigned long		lastuse;
971e19e02cSEric Dumazet 	union {
981e19e02cSEric Dumazet 		struct dst_entry *next;
991e19e02cSEric Dumazet 		struct rtable    *rt_next;
1001e19e02cSEric Dumazet 		struct rt6_info   *rt6_next;
1011e19e02cSEric Dumazet 		struct dn_route  *dn_next;
1021e19e02cSEric Dumazet 	};
1031da177e4SLinus Torvalds };
1041da177e4SLinus Torvalds 
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds struct dst_ops
1071da177e4SLinus Torvalds {
1081da177e4SLinus Torvalds 	unsigned short		family;
109d77072ecSAl Viro 	__be16			protocol;
1101da177e4SLinus Torvalds 	unsigned		gc_thresh;
1111da177e4SLinus Torvalds 
112569d3645SDaniel Lezcano 	int			(*gc)(struct dst_ops *ops);
1131da177e4SLinus Torvalds 	struct dst_entry *	(*check)(struct dst_entry *, __u32 cookie);
1141da177e4SLinus Torvalds 	void			(*destroy)(struct dst_entry *);
1151da177e4SLinus Torvalds 	void			(*ifdown)(struct dst_entry *,
1161da177e4SLinus Torvalds 					  struct net_device *dev, int how);
1171da177e4SLinus Torvalds 	struct dst_entry *	(*negative_advice)(struct dst_entry *);
1181da177e4SLinus Torvalds 	void			(*link_failure)(struct sk_buff *);
1191da177e4SLinus Torvalds 	void			(*update_pmtu)(struct dst_entry *dst, u32 mtu);
120862b82c6SHerbert Xu 	int			(*local_out)(struct sk_buff *skb);
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds 	atomic_t		entries;
123e18b890bSChristoph Lameter 	struct kmem_cache 		*kmem_cachep;
124d4fa26ffSDaniel Lezcano 	struct net              *dst_net;
1251da177e4SLinus Torvalds };
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds #ifdef __KERNEL__
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds static inline u32
1301da177e4SLinus Torvalds dst_metric(const struct dst_entry *dst, int metric)
1311da177e4SLinus Torvalds {
1321da177e4SLinus Torvalds 	return dst->metrics[metric-1];
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds static inline u32 dst_mtu(const struct dst_entry *dst)
1361da177e4SLinus Torvalds {
1371da177e4SLinus Torvalds 	u32 mtu = dst_metric(dst, RTAX_MTU);
1381da177e4SLinus Torvalds 	/*
1391da177e4SLinus Torvalds 	 * Alexey put it here, so ask him about it :)
1401da177e4SLinus Torvalds 	 */
1411da177e4SLinus Torvalds 	barrier();
1421da177e4SLinus Torvalds 	return mtu;
1431da177e4SLinus Torvalds }
1441da177e4SLinus Torvalds 
145c1e20f7cSStephen Hemminger /* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */
146c1e20f7cSStephen Hemminger static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metric)
147c1e20f7cSStephen Hemminger {
148c1e20f7cSStephen Hemminger 	return msecs_to_jiffies(dst_metric(dst, metric));
149c1e20f7cSStephen Hemminger }
150c1e20f7cSStephen Hemminger 
151c1e20f7cSStephen Hemminger static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric,
152c1e20f7cSStephen Hemminger 				      unsigned long rtt)
153c1e20f7cSStephen Hemminger {
154c1e20f7cSStephen Hemminger 	dst->metrics[metric-1] = jiffies_to_msecs(rtt);
155c1e20f7cSStephen Hemminger }
156c1e20f7cSStephen Hemminger 
1571da177e4SLinus Torvalds static inline u32
1581da177e4SLinus Torvalds dst_allfrag(const struct dst_entry *dst)
1591da177e4SLinus Torvalds {
1601da177e4SLinus Torvalds 	int ret = dst_metric(dst, RTAX_FEATURES) & RTAX_FEATURE_ALLFRAG;
1611da177e4SLinus Torvalds 	/* Yes, _exactly_. This is paranoia. */
1621da177e4SLinus Torvalds 	barrier();
1631da177e4SLinus Torvalds 	return ret;
1641da177e4SLinus Torvalds }
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds static inline int
1671da177e4SLinus Torvalds dst_metric_locked(struct dst_entry *dst, int metric)
1681da177e4SLinus Torvalds {
1691da177e4SLinus Torvalds 	return dst_metric(dst, RTAX_LOCK) & (1<<metric);
1701da177e4SLinus Torvalds }
1711da177e4SLinus Torvalds 
1721da177e4SLinus Torvalds static inline void dst_hold(struct dst_entry * dst)
1731da177e4SLinus Torvalds {
1745635c10dSEric Dumazet 	/*
1755635c10dSEric Dumazet 	 * If your kernel compilation stops here, please check
1765635c10dSEric Dumazet 	 * __pad_to_align_refcnt declaration in struct dst_entry
1775635c10dSEric Dumazet 	 */
1785635c10dSEric Dumazet 	BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63);
1791da177e4SLinus Torvalds 	atomic_inc(&dst->__refcnt);
1801da177e4SLinus Torvalds }
1811da177e4SLinus Torvalds 
18203f49f34SPavel Emelyanov static inline void dst_use(struct dst_entry *dst, unsigned long time)
18303f49f34SPavel Emelyanov {
18403f49f34SPavel Emelyanov 	dst_hold(dst);
18503f49f34SPavel Emelyanov 	dst->__use++;
18603f49f34SPavel Emelyanov 	dst->lastuse = time;
18703f49f34SPavel Emelyanov }
18803f49f34SPavel Emelyanov 
1891da177e4SLinus Torvalds static inline
1901da177e4SLinus Torvalds struct dst_entry * dst_clone(struct dst_entry * dst)
1911da177e4SLinus Torvalds {
1921da177e4SLinus Torvalds 	if (dst)
1931da177e4SLinus Torvalds 		atomic_inc(&dst->__refcnt);
1941da177e4SLinus Torvalds 	return dst;
1951da177e4SLinus Torvalds }
1961da177e4SLinus Torvalds 
1978d330868SIlpo Järvinen extern void dst_release(struct dst_entry *dst);
1981da177e4SLinus Torvalds 
1991da177e4SLinus Torvalds /* Children define the path of the packet through the
2001da177e4SLinus Torvalds  * Linux networking.  Thus, destinations are stackable.
2011da177e4SLinus Torvalds  */
2021da177e4SLinus Torvalds 
2031da177e4SLinus Torvalds static inline struct dst_entry *dst_pop(struct dst_entry *dst)
2041da177e4SLinus Torvalds {
2051da177e4SLinus Torvalds 	struct dst_entry *child = dst_clone(dst->child);
2061da177e4SLinus Torvalds 
2071da177e4SLinus Torvalds 	dst_release(dst);
2081da177e4SLinus Torvalds 	return child;
2091da177e4SLinus Torvalds }
2101da177e4SLinus Torvalds 
211352e512cSHerbert Xu extern int dst_discard(struct sk_buff *skb);
2121da177e4SLinus Torvalds extern void * dst_alloc(struct dst_ops * ops);
2131da177e4SLinus Torvalds extern void __dst_free(struct dst_entry * dst);
2141da177e4SLinus Torvalds extern struct dst_entry *dst_destroy(struct dst_entry * dst);
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds static inline void dst_free(struct dst_entry * dst)
2171da177e4SLinus Torvalds {
2181da177e4SLinus Torvalds 	if (dst->obsolete > 1)
2191da177e4SLinus Torvalds 		return;
2201da177e4SLinus Torvalds 	if (!atomic_read(&dst->__refcnt)) {
2211da177e4SLinus Torvalds 		dst = dst_destroy(dst);
2221da177e4SLinus Torvalds 		if (!dst)
2231da177e4SLinus Torvalds 			return;
2241da177e4SLinus Torvalds 	}
2251da177e4SLinus Torvalds 	__dst_free(dst);
2261da177e4SLinus Torvalds }
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds static inline void dst_rcu_free(struct rcu_head *head)
2291da177e4SLinus Torvalds {
2301da177e4SLinus Torvalds 	struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head);
2311da177e4SLinus Torvalds 	dst_free(dst);
2321da177e4SLinus Torvalds }
2331da177e4SLinus Torvalds 
2341da177e4SLinus Torvalds static inline void dst_confirm(struct dst_entry *dst)
2351da177e4SLinus Torvalds {
2361da177e4SLinus Torvalds 	if (dst)
2371da177e4SLinus Torvalds 		neigh_confirm(dst->neighbour);
2381da177e4SLinus Torvalds }
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds static inline void dst_negative_advice(struct dst_entry **dst_p)
2411da177e4SLinus Torvalds {
2421da177e4SLinus Torvalds 	struct dst_entry * dst = *dst_p;
2431da177e4SLinus Torvalds 	if (dst && dst->ops->negative_advice)
2441da177e4SLinus Torvalds 		*dst_p = dst->ops->negative_advice(dst);
2451da177e4SLinus Torvalds }
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds static inline void dst_link_failure(struct sk_buff *skb)
2481da177e4SLinus Torvalds {
2491da177e4SLinus Torvalds 	struct dst_entry * dst = skb->dst;
2501da177e4SLinus Torvalds 	if (dst && dst->ops && dst->ops->link_failure)
2511da177e4SLinus Torvalds 		dst->ops->link_failure(skb);
2521da177e4SLinus Torvalds }
2531da177e4SLinus Torvalds 
2541da177e4SLinus Torvalds static inline void dst_set_expires(struct dst_entry *dst, int timeout)
2551da177e4SLinus Torvalds {
2561da177e4SLinus Torvalds 	unsigned long expires = jiffies + timeout;
2571da177e4SLinus Torvalds 
2581da177e4SLinus Torvalds 	if (expires == 0)
2591da177e4SLinus Torvalds 		expires = 1;
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds 	if (dst->expires == 0 || time_before(expires, dst->expires))
2621da177e4SLinus Torvalds 		dst->expires = expires;
2631da177e4SLinus Torvalds }
2641da177e4SLinus Torvalds 
2651da177e4SLinus Torvalds /* Output packet to network from transport.  */
2661da177e4SLinus Torvalds static inline int dst_output(struct sk_buff *skb)
2671da177e4SLinus Torvalds {
26816a6677fSPatrick McHardy 	return skb->dst->output(skb);
2691da177e4SLinus Torvalds }
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds /* Input packet from network to transport.  */
2721da177e4SLinus Torvalds static inline int dst_input(struct sk_buff *skb)
2731da177e4SLinus Torvalds {
274cc6533e9SDavid S. Miller 	return skb->dst->input(skb);
2751da177e4SLinus Torvalds }
2761da177e4SLinus Torvalds 
2771da177e4SLinus Torvalds static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
2781da177e4SLinus Torvalds {
2791da177e4SLinus Torvalds 	if (dst->obsolete)
2801da177e4SLinus Torvalds 		dst = dst->ops->check(dst, cookie);
2811da177e4SLinus Torvalds 	return dst;
2821da177e4SLinus Torvalds }
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds extern void		dst_init(void);
2851da177e4SLinus Torvalds 
286815f4e57SHerbert Xu /* Flags for xfrm_lookup flags argument. */
287815f4e57SHerbert Xu enum {
288815f4e57SHerbert Xu 	XFRM_LOOKUP_WAIT = 1 << 0,
2898b7817f3SHerbert Xu 	XFRM_LOOKUP_ICMP = 1 << 1,
290815f4e57SHerbert Xu };
291815f4e57SHerbert Xu 
2921da177e4SLinus Torvalds struct flowi;
2931da177e4SLinus Torvalds #ifndef CONFIG_XFRM
294*52479b62SAlexey Dobriyan static inline int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
295*52479b62SAlexey Dobriyan 			      struct flowi *fl, struct sock *sk, int flags)
2961da177e4SLinus Torvalds {
2971da177e4SLinus Torvalds 	return 0;
2981da177e4SLinus Torvalds }
299*52479b62SAlexey Dobriyan static inline int __xfrm_lookup(struct net *net, struct dst_entry **dst_p,
300*52479b62SAlexey Dobriyan 				struct flowi *fl, struct sock *sk, int flags)
30114e50e57SDavid S. Miller {
30214e50e57SDavid S. Miller 	return 0;
30314e50e57SDavid S. Miller }
3041da177e4SLinus Torvalds #else
305*52479b62SAlexey Dobriyan extern int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
306*52479b62SAlexey Dobriyan 		       struct flowi *fl, struct sock *sk, int flags);
307*52479b62SAlexey Dobriyan extern int __xfrm_lookup(struct net *net, struct dst_entry **dst_p,
308*52479b62SAlexey Dobriyan 			 struct flowi *fl, struct sock *sk, int flags);
3091da177e4SLinus Torvalds #endif
3101da177e4SLinus Torvalds #endif
3111da177e4SLinus Torvalds 
3121da177e4SLinus Torvalds #endif /* _NET_DST_H */
313