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 { 40*1e19e02cSEric 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 #define DST_BALANCED 0x10 511da177e4SLinus Torvalds unsigned long expires; 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds unsigned short header_len; /* more space at head required */ 541b5c2299SMasahide NAKAMURA unsigned short nfheader_len; /* more non-fragment space at head required */ 551da177e4SLinus Torvalds unsigned short trailer_len; /* space to reserve at tail */ 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds u32 metrics[RTAX_MAX]; 581da177e4SLinus Torvalds struct dst_entry *path; 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds unsigned long rate_last; /* rate limiting for ICMP */ 611da177e4SLinus Torvalds unsigned long rate_tokens; 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds struct neighbour *neighbour; 641da177e4SLinus Torvalds struct hh_cache *hh; 651da177e4SLinus Torvalds struct xfrm_state *xfrm; 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds int (*input)(struct sk_buff*); 681da177e4SLinus Torvalds int (*output)(struct sk_buff*); 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds #ifdef CONFIG_NET_CLS_ROUTE 711da177e4SLinus Torvalds __u32 tclassid; 721da177e4SLinus Torvalds #endif 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds struct dst_ops *ops; 751da177e4SLinus Torvalds 76*1e19e02cSEric Dumazet unsigned long lastuse; 77*1e19e02cSEric Dumazet atomic_t __refcnt; /* client references */ 78*1e19e02cSEric Dumazet int __use; 79*1e19e02cSEric Dumazet union { 80*1e19e02cSEric Dumazet struct dst_entry *next; 81*1e19e02cSEric Dumazet struct rtable *rt_next; 82*1e19e02cSEric Dumazet struct rt6_info *rt6_next; 83*1e19e02cSEric Dumazet struct dn_route *dn_next; 84*1e19e02cSEric Dumazet }; 851da177e4SLinus Torvalds char info[0]; 861da177e4SLinus Torvalds }; 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds struct dst_ops 901da177e4SLinus Torvalds { 911da177e4SLinus Torvalds unsigned short family; 92d77072ecSAl Viro __be16 protocol; 931da177e4SLinus Torvalds unsigned gc_thresh; 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds int (*gc)(void); 961da177e4SLinus Torvalds struct dst_entry * (*check)(struct dst_entry *, __u32 cookie); 971da177e4SLinus Torvalds void (*destroy)(struct dst_entry *); 981da177e4SLinus Torvalds void (*ifdown)(struct dst_entry *, 991da177e4SLinus Torvalds struct net_device *dev, int how); 1001da177e4SLinus Torvalds struct dst_entry * (*negative_advice)(struct dst_entry *); 1011da177e4SLinus Torvalds void (*link_failure)(struct sk_buff *); 1021da177e4SLinus Torvalds void (*update_pmtu)(struct dst_entry *dst, u32 mtu); 1031da177e4SLinus Torvalds int entry_size; 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds atomic_t entries; 106e18b890bSChristoph Lameter struct kmem_cache *kmem_cachep; 1071da177e4SLinus Torvalds }; 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds #ifdef __KERNEL__ 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds static inline u32 1121da177e4SLinus Torvalds dst_metric(const struct dst_entry *dst, int metric) 1131da177e4SLinus Torvalds { 1141da177e4SLinus Torvalds return dst->metrics[metric-1]; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds static inline u32 dst_mtu(const struct dst_entry *dst) 1181da177e4SLinus Torvalds { 1191da177e4SLinus Torvalds u32 mtu = dst_metric(dst, RTAX_MTU); 1201da177e4SLinus Torvalds /* 1211da177e4SLinus Torvalds * Alexey put it here, so ask him about it :) 1221da177e4SLinus Torvalds */ 1231da177e4SLinus Torvalds barrier(); 1241da177e4SLinus Torvalds return mtu; 1251da177e4SLinus Torvalds } 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds static inline u32 1281da177e4SLinus Torvalds dst_allfrag(const struct dst_entry *dst) 1291da177e4SLinus Torvalds { 1301da177e4SLinus Torvalds int ret = dst_metric(dst, RTAX_FEATURES) & RTAX_FEATURE_ALLFRAG; 1311da177e4SLinus Torvalds /* Yes, _exactly_. This is paranoia. */ 1321da177e4SLinus Torvalds barrier(); 1331da177e4SLinus Torvalds return ret; 1341da177e4SLinus Torvalds } 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds static inline int 1371da177e4SLinus Torvalds dst_metric_locked(struct dst_entry *dst, int metric) 1381da177e4SLinus Torvalds { 1391da177e4SLinus Torvalds return dst_metric(dst, RTAX_LOCK) & (1<<metric); 1401da177e4SLinus Torvalds } 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds static inline void dst_hold(struct dst_entry * dst) 1431da177e4SLinus Torvalds { 1441da177e4SLinus Torvalds atomic_inc(&dst->__refcnt); 1451da177e4SLinus Torvalds } 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds static inline 1481da177e4SLinus Torvalds struct dst_entry * dst_clone(struct dst_entry * dst) 1491da177e4SLinus Torvalds { 1501da177e4SLinus Torvalds if (dst) 1511da177e4SLinus Torvalds atomic_inc(&dst->__refcnt); 1521da177e4SLinus Torvalds return dst; 1531da177e4SLinus Torvalds } 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds static inline 1561da177e4SLinus Torvalds void dst_release(struct dst_entry * dst) 1571da177e4SLinus Torvalds { 1581da177e4SLinus Torvalds if (dst) { 1591da177e4SLinus Torvalds WARN_ON(atomic_read(&dst->__refcnt) < 1); 1601da177e4SLinus Torvalds smp_mb__before_atomic_dec(); 1611da177e4SLinus Torvalds atomic_dec(&dst->__refcnt); 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds } 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds /* Children define the path of the packet through the 1661da177e4SLinus Torvalds * Linux networking. Thus, destinations are stackable. 1671da177e4SLinus Torvalds */ 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds static inline struct dst_entry *dst_pop(struct dst_entry *dst) 1701da177e4SLinus Torvalds { 1711da177e4SLinus Torvalds struct dst_entry *child = dst_clone(dst->child); 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds dst_release(dst); 1741da177e4SLinus Torvalds return child; 1751da177e4SLinus Torvalds } 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds extern void * dst_alloc(struct dst_ops * ops); 1781da177e4SLinus Torvalds extern void __dst_free(struct dst_entry * dst); 1791da177e4SLinus Torvalds extern struct dst_entry *dst_destroy(struct dst_entry * dst); 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds static inline void dst_free(struct dst_entry * dst) 1821da177e4SLinus Torvalds { 1831da177e4SLinus Torvalds if (dst->obsolete > 1) 1841da177e4SLinus Torvalds return; 1851da177e4SLinus Torvalds if (!atomic_read(&dst->__refcnt)) { 1861da177e4SLinus Torvalds dst = dst_destroy(dst); 1871da177e4SLinus Torvalds if (!dst) 1881da177e4SLinus Torvalds return; 1891da177e4SLinus Torvalds } 1901da177e4SLinus Torvalds __dst_free(dst); 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds static inline void dst_rcu_free(struct rcu_head *head) 1941da177e4SLinus Torvalds { 1951da177e4SLinus Torvalds struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); 1961da177e4SLinus Torvalds dst_free(dst); 1971da177e4SLinus Torvalds } 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds static inline void dst_confirm(struct dst_entry *dst) 2001da177e4SLinus Torvalds { 2011da177e4SLinus Torvalds if (dst) 2021da177e4SLinus Torvalds neigh_confirm(dst->neighbour); 2031da177e4SLinus Torvalds } 2041da177e4SLinus Torvalds 2051da177e4SLinus Torvalds static inline void dst_negative_advice(struct dst_entry **dst_p) 2061da177e4SLinus Torvalds { 2071da177e4SLinus Torvalds struct dst_entry * dst = *dst_p; 2081da177e4SLinus Torvalds if (dst && dst->ops->negative_advice) 2091da177e4SLinus Torvalds *dst_p = dst->ops->negative_advice(dst); 2101da177e4SLinus Torvalds } 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds static inline void dst_link_failure(struct sk_buff *skb) 2131da177e4SLinus Torvalds { 2141da177e4SLinus Torvalds struct dst_entry * dst = skb->dst; 2151da177e4SLinus Torvalds if (dst && dst->ops && dst->ops->link_failure) 2161da177e4SLinus Torvalds dst->ops->link_failure(skb); 2171da177e4SLinus Torvalds } 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds static inline void dst_set_expires(struct dst_entry *dst, int timeout) 2201da177e4SLinus Torvalds { 2211da177e4SLinus Torvalds unsigned long expires = jiffies + timeout; 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds if (expires == 0) 2241da177e4SLinus Torvalds expires = 1; 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds if (dst->expires == 0 || time_before(expires, dst->expires)) 2271da177e4SLinus Torvalds dst->expires = expires; 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds /* Output packet to network from transport. */ 2311da177e4SLinus Torvalds static inline int dst_output(struct sk_buff *skb) 2321da177e4SLinus Torvalds { 23316a6677fSPatrick McHardy return skb->dst->output(skb); 2341da177e4SLinus Torvalds } 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds /* Input packet from network to transport. */ 2371da177e4SLinus Torvalds static inline int dst_input(struct sk_buff *skb) 2381da177e4SLinus Torvalds { 2391da177e4SLinus Torvalds int err; 2401da177e4SLinus Torvalds 2411da177e4SLinus Torvalds for (;;) { 2421da177e4SLinus Torvalds err = skb->dst->input(skb); 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds if (likely(err == 0)) 2451da177e4SLinus Torvalds return err; 2461da177e4SLinus Torvalds /* Oh, Jamal... Seems, I will not forgive you this mess. :-) */ 2471da177e4SLinus Torvalds if (unlikely(err != NET_XMIT_BYPASS)) 2481da177e4SLinus Torvalds return err; 2491da177e4SLinus Torvalds } 2501da177e4SLinus Torvalds } 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie) 2531da177e4SLinus Torvalds { 2541da177e4SLinus Torvalds if (dst->obsolete) 2551da177e4SLinus Torvalds dst = dst->ops->check(dst, cookie); 2561da177e4SLinus Torvalds return dst; 2571da177e4SLinus Torvalds } 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds extern void dst_init(void); 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds struct flowi; 2621da177e4SLinus Torvalds #ifndef CONFIG_XFRM 2631da177e4SLinus Torvalds static inline int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, 2641da177e4SLinus Torvalds struct sock *sk, int flags) 2651da177e4SLinus Torvalds { 2661da177e4SLinus Torvalds return 0; 2671da177e4SLinus Torvalds } 2681da177e4SLinus Torvalds #else 2691da177e4SLinus Torvalds extern int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, 2701da177e4SLinus Torvalds struct sock *sk, int flags); 2711da177e4SLinus Torvalds #endif 2721da177e4SLinus Torvalds #endif 2731da177e4SLinus Torvalds 2741da177e4SLinus Torvalds #endif /* _NET_DST_H */ 275