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