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