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 551da177e4SLinus Torvalds u32 metrics[RTAX_MAX]; 561da177e4SLinus Torvalds struct dst_entry *path; 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds unsigned long rate_last; /* rate limiting for ICMP */ 591da177e4SLinus Torvalds unsigned long rate_tokens; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds struct neighbour *neighbour; 621da177e4SLinus Torvalds struct hh_cache *hh; 631da177e4SLinus Torvalds struct xfrm_state *xfrm; 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds int (*input)(struct sk_buff*); 661da177e4SLinus Torvalds int (*output)(struct sk_buff*); 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds #ifdef CONFIG_NET_CLS_ROUTE 691da177e4SLinus Torvalds __u32 tclassid; 701da177e4SLinus Torvalds #endif 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds struct dst_ops *ops; 731da177e4SLinus Torvalds 741e19e02cSEric Dumazet unsigned long lastuse; 751e19e02cSEric Dumazet atomic_t __refcnt; /* client references */ 761e19e02cSEric Dumazet int __use; 771e19e02cSEric Dumazet union { 781e19e02cSEric Dumazet struct dst_entry *next; 791e19e02cSEric Dumazet struct rtable *rt_next; 801e19e02cSEric Dumazet struct rt6_info *rt6_next; 811e19e02cSEric Dumazet struct dn_route *dn_next; 821e19e02cSEric Dumazet }; 831da177e4SLinus Torvalds char info[0]; 841da177e4SLinus Torvalds }; 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds struct dst_ops 881da177e4SLinus Torvalds { 891da177e4SLinus Torvalds unsigned short family; 90d77072ecSAl Viro __be16 protocol; 911da177e4SLinus Torvalds unsigned gc_thresh; 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds int (*gc)(void); 941da177e4SLinus Torvalds struct dst_entry * (*check)(struct dst_entry *, __u32 cookie); 951da177e4SLinus Torvalds void (*destroy)(struct dst_entry *); 961da177e4SLinus Torvalds void (*ifdown)(struct dst_entry *, 971da177e4SLinus Torvalds struct net_device *dev, int how); 981da177e4SLinus Torvalds struct dst_entry * (*negative_advice)(struct dst_entry *); 991da177e4SLinus Torvalds void (*link_failure)(struct sk_buff *); 1001da177e4SLinus Torvalds void (*update_pmtu)(struct dst_entry *dst, u32 mtu); 101862b82c6SHerbert Xu int (*local_out)(struct sk_buff *skb); 1021da177e4SLinus Torvalds int entry_size; 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds atomic_t entries; 105e18b890bSChristoph Lameter struct kmem_cache *kmem_cachep; 1061da177e4SLinus Torvalds }; 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds #ifdef __KERNEL__ 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds static inline u32 1111da177e4SLinus Torvalds dst_metric(const struct dst_entry *dst, int metric) 1121da177e4SLinus Torvalds { 1131da177e4SLinus Torvalds return dst->metrics[metric-1]; 1141da177e4SLinus Torvalds } 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds static inline u32 dst_mtu(const struct dst_entry *dst) 1171da177e4SLinus Torvalds { 1181da177e4SLinus Torvalds u32 mtu = dst_metric(dst, RTAX_MTU); 1191da177e4SLinus Torvalds /* 1201da177e4SLinus Torvalds * Alexey put it here, so ask him about it :) 1211da177e4SLinus Torvalds */ 1221da177e4SLinus Torvalds barrier(); 1231da177e4SLinus Torvalds return mtu; 1241da177e4SLinus Torvalds } 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds static inline u32 1271da177e4SLinus Torvalds dst_allfrag(const struct dst_entry *dst) 1281da177e4SLinus Torvalds { 1291da177e4SLinus Torvalds int ret = dst_metric(dst, RTAX_FEATURES) & RTAX_FEATURE_ALLFRAG; 1301da177e4SLinus Torvalds /* Yes, _exactly_. This is paranoia. */ 1311da177e4SLinus Torvalds barrier(); 1321da177e4SLinus Torvalds return ret; 1331da177e4SLinus Torvalds } 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds static inline int 1361da177e4SLinus Torvalds dst_metric_locked(struct dst_entry *dst, int metric) 1371da177e4SLinus Torvalds { 1381da177e4SLinus Torvalds return dst_metric(dst, RTAX_LOCK) & (1<<metric); 1391da177e4SLinus Torvalds } 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds static inline void dst_hold(struct dst_entry * dst) 1421da177e4SLinus Torvalds { 1431da177e4SLinus Torvalds atomic_inc(&dst->__refcnt); 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds 14603f49f34SPavel Emelyanov static inline void dst_use(struct dst_entry *dst, unsigned long time) 14703f49f34SPavel Emelyanov { 14803f49f34SPavel Emelyanov dst_hold(dst); 14903f49f34SPavel Emelyanov dst->__use++; 15003f49f34SPavel Emelyanov dst->lastuse = time; 15103f49f34SPavel Emelyanov } 15203f49f34SPavel Emelyanov 1531da177e4SLinus Torvalds static inline 1541da177e4SLinus Torvalds struct dst_entry * dst_clone(struct dst_entry * dst) 1551da177e4SLinus Torvalds { 1561da177e4SLinus Torvalds if (dst) 1571da177e4SLinus Torvalds atomic_inc(&dst->__refcnt); 1581da177e4SLinus Torvalds return dst; 1591da177e4SLinus Torvalds } 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds static inline 1621da177e4SLinus Torvalds void dst_release(struct dst_entry * dst) 1631da177e4SLinus Torvalds { 1641da177e4SLinus Torvalds if (dst) { 1651da177e4SLinus Torvalds WARN_ON(atomic_read(&dst->__refcnt) < 1); 1661da177e4SLinus Torvalds smp_mb__before_atomic_dec(); 1671da177e4SLinus Torvalds atomic_dec(&dst->__refcnt); 1681da177e4SLinus Torvalds } 1691da177e4SLinus Torvalds } 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds /* Children define the path of the packet through the 1721da177e4SLinus Torvalds * Linux networking. Thus, destinations are stackable. 1731da177e4SLinus Torvalds */ 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds static inline struct dst_entry *dst_pop(struct dst_entry *dst) 1761da177e4SLinus Torvalds { 1771da177e4SLinus Torvalds struct dst_entry *child = dst_clone(dst->child); 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds dst_release(dst); 1801da177e4SLinus Torvalds return child; 1811da177e4SLinus Torvalds } 1821da177e4SLinus Torvalds 183352e512cSHerbert Xu extern int dst_discard(struct sk_buff *skb); 1841da177e4SLinus Torvalds extern void * dst_alloc(struct dst_ops * ops); 1851da177e4SLinus Torvalds extern void __dst_free(struct dst_entry * dst); 1861da177e4SLinus Torvalds extern struct dst_entry *dst_destroy(struct dst_entry * dst); 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds static inline void dst_free(struct dst_entry * dst) 1891da177e4SLinus Torvalds { 1901da177e4SLinus Torvalds if (dst->obsolete > 1) 1911da177e4SLinus Torvalds return; 1921da177e4SLinus Torvalds if (!atomic_read(&dst->__refcnt)) { 1931da177e4SLinus Torvalds dst = dst_destroy(dst); 1941da177e4SLinus Torvalds if (!dst) 1951da177e4SLinus Torvalds return; 1961da177e4SLinus Torvalds } 1971da177e4SLinus Torvalds __dst_free(dst); 1981da177e4SLinus Torvalds } 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds static inline void dst_rcu_free(struct rcu_head *head) 2011da177e4SLinus Torvalds { 2021da177e4SLinus Torvalds struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head); 2031da177e4SLinus Torvalds dst_free(dst); 2041da177e4SLinus Torvalds } 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds static inline void dst_confirm(struct dst_entry *dst) 2071da177e4SLinus Torvalds { 2081da177e4SLinus Torvalds if (dst) 2091da177e4SLinus Torvalds neigh_confirm(dst->neighbour); 2101da177e4SLinus Torvalds } 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds static inline void dst_negative_advice(struct dst_entry **dst_p) 2131da177e4SLinus Torvalds { 2141da177e4SLinus Torvalds struct dst_entry * dst = *dst_p; 2151da177e4SLinus Torvalds if (dst && dst->ops->negative_advice) 2161da177e4SLinus Torvalds *dst_p = dst->ops->negative_advice(dst); 2171da177e4SLinus Torvalds } 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds static inline void dst_link_failure(struct sk_buff *skb) 2201da177e4SLinus Torvalds { 2211da177e4SLinus Torvalds struct dst_entry * dst = skb->dst; 2221da177e4SLinus Torvalds if (dst && dst->ops && dst->ops->link_failure) 2231da177e4SLinus Torvalds dst->ops->link_failure(skb); 2241da177e4SLinus Torvalds } 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds static inline void dst_set_expires(struct dst_entry *dst, int timeout) 2271da177e4SLinus Torvalds { 2281da177e4SLinus Torvalds unsigned long expires = jiffies + timeout; 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds if (expires == 0) 2311da177e4SLinus Torvalds expires = 1; 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds if (dst->expires == 0 || time_before(expires, dst->expires)) 2341da177e4SLinus Torvalds dst->expires = expires; 2351da177e4SLinus Torvalds } 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds /* Output packet to network from transport. */ 2381da177e4SLinus Torvalds static inline int dst_output(struct sk_buff *skb) 2391da177e4SLinus Torvalds { 24016a6677fSPatrick McHardy return skb->dst->output(skb); 2411da177e4SLinus Torvalds } 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds /* Input packet from network to transport. */ 2441da177e4SLinus Torvalds static inline int dst_input(struct sk_buff *skb) 2451da177e4SLinus Torvalds { 2461da177e4SLinus Torvalds int err; 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds for (;;) { 2491da177e4SLinus Torvalds err = skb->dst->input(skb); 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds if (likely(err == 0)) 2521da177e4SLinus Torvalds return err; 2531da177e4SLinus Torvalds /* Oh, Jamal... Seems, I will not forgive you this mess. :-) */ 2541da177e4SLinus Torvalds if (unlikely(err != NET_XMIT_BYPASS)) 2551da177e4SLinus Torvalds return err; 2561da177e4SLinus Torvalds } 2571da177e4SLinus Torvalds } 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie) 2601da177e4SLinus Torvalds { 2611da177e4SLinus Torvalds if (dst->obsolete) 2621da177e4SLinus Torvalds dst = dst->ops->check(dst, cookie); 2631da177e4SLinus Torvalds return dst; 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds extern void dst_init(void); 2671da177e4SLinus Torvalds 268*815f4e57SHerbert Xu /* Flags for xfrm_lookup flags argument. */ 269*815f4e57SHerbert Xu enum { 270*815f4e57SHerbert Xu XFRM_LOOKUP_WAIT = 1 << 0, 271*815f4e57SHerbert Xu }; 272*815f4e57SHerbert Xu 2731da177e4SLinus Torvalds struct flowi; 2741da177e4SLinus Torvalds #ifndef CONFIG_XFRM 2751da177e4SLinus Torvalds static inline int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, 2761da177e4SLinus Torvalds struct sock *sk, int flags) 2771da177e4SLinus Torvalds { 2781da177e4SLinus Torvalds return 0; 2791da177e4SLinus Torvalds } 28014e50e57SDavid S. Miller static inline int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, 28114e50e57SDavid S. Miller struct sock *sk, int flags) 28214e50e57SDavid S. Miller { 28314e50e57SDavid S. Miller return 0; 28414e50e57SDavid S. Miller } 2851da177e4SLinus Torvalds #else 2861da177e4SLinus Torvalds extern int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, 2871da177e4SLinus Torvalds struct sock *sk, int flags); 28814e50e57SDavid S. Miller extern int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, 28914e50e57SDavid S. Miller struct sock *sk, int flags); 2901da177e4SLinus Torvalds #endif 2911da177e4SLinus Torvalds #endif 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds #endif /* _NET_DST_H */ 294