1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * net/dst.h Protocol independent destination cache definitions. 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds */ 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds #ifndef _NET_DST_H 101da177e4SLinus Torvalds #define _NET_DST_H 111da177e4SLinus Torvalds 1286393e52SAlexey Dobriyan #include <net/dst_ops.h> 1314c85021SArnaldo Carvalho de Melo #include <linux/netdevice.h> 141da177e4SLinus Torvalds #include <linux/rtnetlink.h> 151da177e4SLinus Torvalds #include <linux/rcupdate.h> 16187f1882SPaul Gortmaker #include <linux/bug.h> 171da177e4SLinus Torvalds #include <linux/jiffies.h> 189620fef2SEric Dumazet #include <linux/refcount.h> 191da177e4SLinus Torvalds #include <net/neighbour.h> 201da177e4SLinus Torvalds #include <asm/processor.h> 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #define DST_GC_MIN (HZ/10) 231da177e4SLinus Torvalds #define DST_GC_INC (HZ/2) 241da177e4SLinus Torvalds #define DST_GC_MAX (120*HZ) 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds /* Each dst_entry has reference count and sits in some parent list(s). 271da177e4SLinus Torvalds * When it is removed from parent list, it is "freed" (dst_free). 281da177e4SLinus Torvalds * After this it enters dead state (dst->obsolete > 0) and if its refcnt 291da177e4SLinus Torvalds * is zero, it can be destroyed immediately, otherwise it is added 301da177e4SLinus Torvalds * to gc list and garbage collector periodically checks the refcnt. 311da177e4SLinus Torvalds */ 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds struct sk_buff; 341da177e4SLinus Torvalds 35fd2c3ef7SEric Dumazet struct dst_entry { 3666727145SAlexey Dobriyan struct net_device *dev; 3762fa8a84SDavid S. Miller struct dst_ops *ops; 3862fa8a84SDavid S. Miller unsigned long _metrics; 391da177e4SLinus Torvalds unsigned long expires; 40def8b4faSAlexey Dobriyan #ifdef CONFIG_XFRM 411da177e4SLinus Torvalds struct xfrm_state *xfrm; 425635c10dSEric Dumazet #else 435635c10dSEric Dumazet void *__pad1; 44def8b4faSAlexey Dobriyan #endif 451da177e4SLinus Torvalds int (*input)(struct sk_buff *); 46ede2059dSEric W. Biederman int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb); 471da177e4SLinus Torvalds 485110effeSDavid S. Miller unsigned short flags; 49f6b72b62SDavid S. Miller #define DST_HOST 0x0001 50f6b72b62SDavid S. Miller #define DST_NOXFRM 0x0002 51f6b72b62SDavid S. Miller #define DST_NOPOLICY 0x0004 521eb04e7cSWei Wang #define DST_NOCOUNT 0x0008 531eb04e7cSWei Wang #define DST_FAKE_RTABLE 0x0010 541eb04e7cSWei Wang #define DST_XFRM_TUNNEL 0x0020 551eb04e7cSWei Wang #define DST_XFRM_QUEUE 0x0040 561eb04e7cSWei Wang #define DST_METADATA 0x0080 57f6b72b62SDavid S. Miller 58f5b0a874SDavid S. Miller /* A non-zero value of dst->obsolete forces by-hand validation 59f5b0a874SDavid S. Miller * of the route entry. Positive values are set by the generic 60f5b0a874SDavid S. Miller * dst layer to indicate that the entry has been forcefully 61f5b0a874SDavid S. Miller * destroyed. 62f5b0a874SDavid S. Miller * 63f5b0a874SDavid S. Miller * Negative values are used by the implementation layer code to 64f5b0a874SDavid S. Miller * force invocation of the dst_ops->check() method. 65f5b0a874SDavid S. Miller */ 6662fa8a84SDavid S. Miller short obsolete; 67f5b0a874SDavid S. Miller #define DST_OBSOLETE_NONE 0 68f5b0a874SDavid S. Miller #define DST_OBSOLETE_DEAD 2 69f5b0a874SDavid S. Miller #define DST_OBSOLETE_FORCE_CHK -1 70ceb33206SDavid S. Miller #define DST_OBSOLETE_KILL -2 7162fa8a84SDavid S. Miller unsigned short header_len; /* more space at head required */ 7262fa8a84SDavid S. Miller unsigned short trailer_len; /* space to reserve at tail */ 7351ce8bd4SJulian Anastasov 74f1dd9c37SZhang Yanmin /* 75f1dd9c37SZhang Yanmin * __refcnt wants to be on a different cache line from 76f1dd9c37SZhang Yanmin * input/output/ops or performance tanks badly 77f1dd9c37SZhang Yanmin */ 78*8b207e73SDavid Miller #ifdef CONFIG_64BIT 79*8b207e73SDavid Miller atomic_t __refcnt; /* 64-bit offset 64 */ 80*8b207e73SDavid Miller #endif 811e19e02cSEric Dumazet int __use; 82f1dd9c37SZhang Yanmin unsigned long lastuse; 83751a587aSJiri Benc struct lwtunnel_state *lwtstate; 84*8b207e73SDavid Miller struct rcu_head rcu_head; 85*8b207e73SDavid Miller short error; 86*8b207e73SDavid Miller short __pad; 87*8b207e73SDavid Miller __u32 tclassid; 88*8b207e73SDavid Miller #ifndef CONFIG_64BIT 89*8b207e73SDavid Miller atomic_t __refcnt; /* 32-bit offset 64 */ 90*8b207e73SDavid Miller #endif 91*8b207e73SDavid Miller 921e19e02cSEric Dumazet union { 931e19e02cSEric Dumazet struct dst_entry *next; 941e19e02cSEric Dumazet }; 951da177e4SLinus Torvalds }; 961da177e4SLinus Torvalds 973fb07dafSEric Dumazet struct dst_metrics { 983fb07dafSEric Dumazet u32 metrics[RTAX_MAX]; 999620fef2SEric Dumazet refcount_t refcnt; 1003fb07dafSEric Dumazet }; 1013fb07dafSEric Dumazet extern const struct dst_metrics dst_default_metrics; 1023fb07dafSEric Dumazet 103a4023dd0SJoe Perches u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); 10462fa8a84SDavid S. Miller 10562fa8a84SDavid S. Miller #define DST_METRICS_READ_ONLY 0x1UL 1063fb07dafSEric Dumazet #define DST_METRICS_REFCOUNTED 0x2UL 107e5fd387aSMichal Kubeček #define DST_METRICS_FLAGS 0x3UL 10862fa8a84SDavid S. Miller #define __DST_METRICS_PTR(Y) \ 109e5fd387aSMichal Kubeček ((u32 *)((Y) & ~DST_METRICS_FLAGS)) 11062fa8a84SDavid S. Miller #define DST_METRICS_PTR(X) __DST_METRICS_PTR((X)->_metrics) 11162fa8a84SDavid S. Miller 11262fa8a84SDavid S. Miller static inline bool dst_metrics_read_only(const struct dst_entry *dst) 11362fa8a84SDavid S. Miller { 11462fa8a84SDavid S. Miller return dst->_metrics & DST_METRICS_READ_ONLY; 11562fa8a84SDavid S. Miller } 11662fa8a84SDavid S. Miller 117a4023dd0SJoe Perches void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old); 11862fa8a84SDavid S. Miller 11962fa8a84SDavid S. Miller static inline void dst_destroy_metrics_generic(struct dst_entry *dst) 12062fa8a84SDavid S. Miller { 12162fa8a84SDavid S. Miller unsigned long val = dst->_metrics; 12262fa8a84SDavid S. Miller if (!(val & DST_METRICS_READ_ONLY)) 12362fa8a84SDavid S. Miller __dst_destroy_metrics_generic(dst, val); 12462fa8a84SDavid S. Miller } 12562fa8a84SDavid S. Miller 12662fa8a84SDavid S. Miller static inline u32 *dst_metrics_write_ptr(struct dst_entry *dst) 12762fa8a84SDavid S. Miller { 12862fa8a84SDavid S. Miller unsigned long p = dst->_metrics; 12962fa8a84SDavid S. Miller 1301f37070dSStephen Hemminger BUG_ON(!p); 1311f37070dSStephen Hemminger 13262fa8a84SDavid S. Miller if (p & DST_METRICS_READ_ONLY) 13362fa8a84SDavid S. Miller return dst->ops->cow_metrics(dst, p); 13462fa8a84SDavid S. Miller return __DST_METRICS_PTR(p); 13562fa8a84SDavid S. Miller } 13662fa8a84SDavid S. Miller 13762fa8a84SDavid S. Miller /* This may only be invoked before the entry has reached global 13862fa8a84SDavid S. Miller * visibility. 13962fa8a84SDavid S. Miller */ 14062fa8a84SDavid S. Miller static inline void dst_init_metrics(struct dst_entry *dst, 14162fa8a84SDavid S. Miller const u32 *src_metrics, 14262fa8a84SDavid S. Miller bool read_only) 14362fa8a84SDavid S. Miller { 14462fa8a84SDavid S. Miller dst->_metrics = ((unsigned long) src_metrics) | 14562fa8a84SDavid S. Miller (read_only ? DST_METRICS_READ_ONLY : 0); 14662fa8a84SDavid S. Miller } 14762fa8a84SDavid S. Miller 14862fa8a84SDavid S. Miller static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src) 14962fa8a84SDavid S. Miller { 15062fa8a84SDavid S. Miller u32 *dst_metrics = dst_metrics_write_ptr(dest); 15162fa8a84SDavid S. Miller 15262fa8a84SDavid S. Miller if (dst_metrics) { 15362fa8a84SDavid S. Miller u32 *src_metrics = DST_METRICS_PTR(src); 15462fa8a84SDavid S. Miller 15562fa8a84SDavid S. Miller memcpy(dst_metrics, src_metrics, RTAX_MAX * sizeof(u32)); 15662fa8a84SDavid S. Miller } 15762fa8a84SDavid S. Miller } 15862fa8a84SDavid S. Miller 15962fa8a84SDavid S. Miller static inline u32 *dst_metrics_ptr(struct dst_entry *dst) 16062fa8a84SDavid S. Miller { 16162fa8a84SDavid S. Miller return DST_METRICS_PTR(dst); 16262fa8a84SDavid S. Miller } 16362fa8a84SDavid S. Miller 1641da177e4SLinus Torvalds static inline u32 1655170ae82SDavid S. Miller dst_metric_raw(const struct dst_entry *dst, const int metric) 1661da177e4SLinus Torvalds { 16762fa8a84SDavid S. Miller u32 *p = DST_METRICS_PTR(dst); 16862fa8a84SDavid S. Miller 16962fa8a84SDavid S. Miller return p[metric-1]; 170defb3519SDavid S. Miller } 171defb3519SDavid S. Miller 1725170ae82SDavid S. Miller static inline u32 1735170ae82SDavid S. Miller dst_metric(const struct dst_entry *dst, const int metric) 1745170ae82SDavid S. Miller { 1750dbaee3bSDavid S. Miller WARN_ON_ONCE(metric == RTAX_HOPLIMIT || 176d33e4553SDavid S. Miller metric == RTAX_ADVMSS || 177d33e4553SDavid S. Miller metric == RTAX_MTU); 1785170ae82SDavid S. Miller return dst_metric_raw(dst, metric); 1795170ae82SDavid S. Miller } 1805170ae82SDavid S. Miller 1810dbaee3bSDavid S. Miller static inline u32 1820dbaee3bSDavid S. Miller dst_metric_advmss(const struct dst_entry *dst) 1830dbaee3bSDavid S. Miller { 1840dbaee3bSDavid S. Miller u32 advmss = dst_metric_raw(dst, RTAX_ADVMSS); 1850dbaee3bSDavid S. Miller 1860dbaee3bSDavid S. Miller if (!advmss) 1870dbaee3bSDavid S. Miller advmss = dst->ops->default_advmss(dst); 1880dbaee3bSDavid S. Miller 1890dbaee3bSDavid S. Miller return advmss; 1900dbaee3bSDavid S. Miller } 1910dbaee3bSDavid S. Miller 192defb3519SDavid S. Miller static inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val) 193defb3519SDavid S. Miller { 19462fa8a84SDavid S. Miller u32 *p = dst_metrics_write_ptr(dst); 195defb3519SDavid S. Miller 19662fa8a84SDavid S. Miller if (p) 19762fa8a84SDavid S. Miller p[metric-1] = val; 1981da177e4SLinus Torvalds } 1991da177e4SLinus Torvalds 200c3a8d947SDaniel Borkmann /* Kernel-internal feature bits that are unallocated in user space. */ 201c3a8d947SDaniel Borkmann #define DST_FEATURE_ECN_CA (1 << 31) 202c3a8d947SDaniel Borkmann 203c3a8d947SDaniel Borkmann #define DST_FEATURE_MASK (DST_FEATURE_ECN_CA) 204c3a8d947SDaniel Borkmann #define DST_FEATURE_ECN_MASK (DST_FEATURE_ECN_CA | RTAX_FEATURE_ECN) 205c3a8d947SDaniel Borkmann 2060c3adfb8SGilad Ben-Yossef static inline u32 2070c3adfb8SGilad Ben-Yossef dst_feature(const struct dst_entry *dst, u32 feature) 2080c3adfb8SGilad Ben-Yossef { 209bb5b7c11SDavid S. Miller return dst_metric(dst, RTAX_FEATURES) & feature; 2100c3adfb8SGilad Ben-Yossef } 2110c3adfb8SGilad Ben-Yossef 2121da177e4SLinus Torvalds static inline u32 dst_mtu(const struct dst_entry *dst) 2131da177e4SLinus Torvalds { 214618f9bc7SSteffen Klassert return dst->ops->mtu(dst); 2151da177e4SLinus Torvalds } 2161da177e4SLinus Torvalds 217c1e20f7cSStephen Hemminger /* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */ 218c1e20f7cSStephen Hemminger static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metric) 219c1e20f7cSStephen Hemminger { 220c1e20f7cSStephen Hemminger return msecs_to_jiffies(dst_metric(dst, metric)); 221c1e20f7cSStephen Hemminger } 222c1e20f7cSStephen Hemminger 2231da177e4SLinus Torvalds static inline u32 2241da177e4SLinus Torvalds dst_allfrag(const struct dst_entry *dst) 2251da177e4SLinus Torvalds { 2260c3adfb8SGilad Ben-Yossef int ret = dst_feature(dst, RTAX_FEATURE_ALLFRAG); 2271da177e4SLinus Torvalds return ret; 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds static inline int 231d33e4553SDavid S. Miller dst_metric_locked(const struct dst_entry *dst, int metric) 2321da177e4SLinus Torvalds { 2331da177e4SLinus Torvalds return dst_metric(dst, RTAX_LOCK) & (1<<metric); 2341da177e4SLinus Torvalds } 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds static inline void dst_hold(struct dst_entry *dst) 2371da177e4SLinus Torvalds { 2385635c10dSEric Dumazet /* 2395635c10dSEric Dumazet * If your kernel compilation stops here, please check 240*8b207e73SDavid Miller * the placement of __refcnt in struct dst_entry 2415635c10dSEric Dumazet */ 2425635c10dSEric Dumazet BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63); 24344ebe791SWei Wang WARN_ON(atomic_inc_not_zero(&dst->__refcnt) == 0); 2441da177e4SLinus Torvalds } 2451da177e4SLinus Torvalds 2460da4af00SWei Wang static inline void dst_use_noref(struct dst_entry *dst, unsigned long time) 24703f49f34SPavel Emelyanov { 24832d18ab1SPaolo Abeni if (unlikely(time != dst->lastuse)) { 24903f49f34SPavel Emelyanov dst->__use++; 25003f49f34SPavel Emelyanov dst->lastuse = time; 25103f49f34SPavel Emelyanov } 2520da4af00SWei Wang } 25303f49f34SPavel Emelyanov 2540da4af00SWei Wang static inline void dst_hold_and_use(struct dst_entry *dst, unsigned long time) 2557fee226aSEric Dumazet { 2560da4af00SWei Wang dst_hold(dst); 2570da4af00SWei Wang dst_use_noref(dst, time); 2587fee226aSEric Dumazet } 2597fee226aSEric Dumazet 2607f95e188SEldad Zack static inline struct dst_entry *dst_clone(struct dst_entry *dst) 2611da177e4SLinus Torvalds { 2621da177e4SLinus Torvalds if (dst) 263222d7dbdSEric Dumazet dst_hold(dst); 2641da177e4SLinus Torvalds return dst; 2651da177e4SLinus Torvalds } 2661da177e4SLinus Torvalds 267a4023dd0SJoe Perches void dst_release(struct dst_entry *dst); 2687fee226aSEric Dumazet 2695f56f409SWei Wang void dst_release_immediate(struct dst_entry *dst); 2705f56f409SWei Wang 2717fee226aSEric Dumazet static inline void refdst_drop(unsigned long refdst) 2727fee226aSEric Dumazet { 2737fee226aSEric Dumazet if (!(refdst & SKB_DST_NOREF)) 2747fee226aSEric Dumazet dst_release((struct dst_entry *)(refdst & SKB_DST_PTRMASK)); 2757fee226aSEric Dumazet } 2767fee226aSEric Dumazet 2777fee226aSEric Dumazet /** 2787fee226aSEric Dumazet * skb_dst_drop - drops skb dst 2797fee226aSEric Dumazet * @skb: buffer 2807fee226aSEric Dumazet * 2817fee226aSEric Dumazet * Drops dst reference count if a reference was taken. 2827fee226aSEric Dumazet */ 283adf30907SEric Dumazet static inline void skb_dst_drop(struct sk_buff *skb) 284adf30907SEric Dumazet { 2857fee226aSEric Dumazet if (skb->_skb_refdst) { 2867fee226aSEric Dumazet refdst_drop(skb->_skb_refdst); 2877fee226aSEric Dumazet skb->_skb_refdst = 0UL; 2887fee226aSEric Dumazet } 2897fee226aSEric Dumazet } 2907fee226aSEric Dumazet 291e79e2595SJoe Stringer static inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst) 2927fee226aSEric Dumazet { 293e79e2595SJoe Stringer nskb->_skb_refdst = refdst; 2947fee226aSEric Dumazet if (!(nskb->_skb_refdst & SKB_DST_NOREF)) 2957fee226aSEric Dumazet dst_clone(skb_dst(nskb)); 2967fee226aSEric Dumazet } 2977fee226aSEric Dumazet 298e79e2595SJoe Stringer static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb) 299e79e2595SJoe Stringer { 300e79e2595SJoe Stringer __skb_dst_copy(nskb, oskb->_skb_refdst); 301e79e2595SJoe Stringer } 302e79e2595SJoe Stringer 3037fee226aSEric Dumazet /** 3045037e9efSEric Dumazet * dst_hold_safe - Take a reference on a dst if possible 3055037e9efSEric Dumazet * @dst: pointer to dst entry 3065037e9efSEric Dumazet * 3075037e9efSEric Dumazet * This helper returns false if it could not safely 3085037e9efSEric Dumazet * take a reference on a dst. 3095037e9efSEric Dumazet */ 3105037e9efSEric Dumazet static inline bool dst_hold_safe(struct dst_entry *dst) 3115037e9efSEric Dumazet { 3125037e9efSEric Dumazet return atomic_inc_not_zero(&dst->__refcnt); 3135037e9efSEric Dumazet } 3145037e9efSEric Dumazet 3155037e9efSEric Dumazet /** 316222d7dbdSEric Dumazet * skb_dst_force - makes sure skb dst is refcounted 3175037e9efSEric Dumazet * @skb: buffer 3185037e9efSEric Dumazet * 3195037e9efSEric Dumazet * If dst is not yet refcounted and not destroyed, grab a ref on it. 3205037e9efSEric Dumazet */ 321222d7dbdSEric Dumazet static inline void skb_dst_force(struct sk_buff *skb) 3225037e9efSEric Dumazet { 3235037e9efSEric Dumazet if (skb_dst_is_noref(skb)) { 3245037e9efSEric Dumazet struct dst_entry *dst = skb_dst(skb); 3255037e9efSEric Dumazet 326222d7dbdSEric Dumazet WARN_ON(!rcu_read_lock_held()); 3275037e9efSEric Dumazet if (!dst_hold_safe(dst)) 3285037e9efSEric Dumazet dst = NULL; 3295037e9efSEric Dumazet 3305037e9efSEric Dumazet skb->_skb_refdst = (unsigned long)dst; 3315037e9efSEric Dumazet } 3325037e9efSEric Dumazet } 3335037e9efSEric Dumazet 334d19d56ddSEric Dumazet 335d19d56ddSEric Dumazet /** 336290b895eSEric Dumazet * __skb_tunnel_rx - prepare skb for rx reinsert 337290b895eSEric Dumazet * @skb: buffer 338290b895eSEric Dumazet * @dev: tunnel device 339ea23192eSNicolas Dichtel * @net: netns for packet i/o 340290b895eSEric Dumazet * 341290b895eSEric Dumazet * After decapsulation, packet is going to re-enter (netif_rx()) our stack, 342290b895eSEric Dumazet * so make some cleanups. (no accounting done) 343290b895eSEric Dumazet */ 344ea23192eSNicolas Dichtel static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, 345ea23192eSNicolas Dichtel struct net *net) 346290b895eSEric Dumazet { 347290b895eSEric Dumazet skb->dev = dev; 348bdeab991STom Herbert 349bdeab991STom Herbert /* 3507539fadcSTom Herbert * Clear hash so that we can recalulate the hash for the 351bdeab991STom Herbert * encapsulated packet, unless we have already determine the hash 352bdeab991STom Herbert * over the L4 4-tuple. 353bdeab991STom Herbert */ 3547539fadcSTom Herbert skb_clear_hash_if_not_l4(skb); 355290b895eSEric Dumazet skb_set_queue_mapping(skb, 0); 356ea23192eSNicolas Dichtel skb_scrub_packet(skb, !net_eq(net, dev_net(dev))); 357290b895eSEric Dumazet } 358290b895eSEric Dumazet 359290b895eSEric Dumazet /** 360d19d56ddSEric Dumazet * skb_tunnel_rx - prepare skb for rx reinsert 361d19d56ddSEric Dumazet * @skb: buffer 362d19d56ddSEric Dumazet * @dev: tunnel device 363d19d56ddSEric Dumazet * 364d19d56ddSEric Dumazet * After decapsulation, packet is going to re-enter (netif_rx()) our stack, 365d19d56ddSEric Dumazet * so make some cleanups, and perform accounting. 366290b895eSEric Dumazet * Note: this accounting is not SMP safe. 367d19d56ddSEric Dumazet */ 368ea23192eSNicolas Dichtel static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, 369ea23192eSNicolas Dichtel struct net *net) 370d19d56ddSEric Dumazet { 371d19d56ddSEric Dumazet /* TODO : stats should be SMP safe */ 372d19d56ddSEric Dumazet dev->stats.rx_packets++; 373d19d56ddSEric Dumazet dev->stats.rx_bytes += skb->len; 374ea23192eSNicolas Dichtel __skb_tunnel_rx(skb, dev, net); 375d19d56ddSEric Dumazet } 376d19d56ddSEric Dumazet 377808c1b69SDaniel Borkmann static inline u32 dst_tclassid(const struct sk_buff *skb) 378808c1b69SDaniel Borkmann { 379808c1b69SDaniel Borkmann #ifdef CONFIG_IP_ROUTE_CLASSID 380808c1b69SDaniel Borkmann const struct dst_entry *dst; 381808c1b69SDaniel Borkmann 382808c1b69SDaniel Borkmann dst = skb_dst(skb); 383808c1b69SDaniel Borkmann if (dst) 384808c1b69SDaniel Borkmann return dst->tclassid; 385808c1b69SDaniel Borkmann #endif 386808c1b69SDaniel Borkmann return 0; 387808c1b69SDaniel Borkmann } 388808c1b69SDaniel Borkmann 389ede2059dSEric W. Biederman int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb); 390aad88724SEric Dumazet static inline int dst_discard(struct sk_buff *skb) 391aad88724SEric Dumazet { 392ede2059dSEric W. Biederman return dst_discard_out(&init_net, skb->sk, skb); 393aad88724SEric Dumazet } 394a4023dd0SJoe Perches void *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref, 395a4023dd0SJoe Perches int initial_obsolete, unsigned short flags); 396f38a9eb1SThomas Graf void dst_init(struct dst_entry *dst, struct dst_ops *ops, 397f38a9eb1SThomas Graf struct net_device *dev, int initial_ref, int initial_obsolete, 398f38a9eb1SThomas Graf unsigned short flags); 399a4023dd0SJoe Perches struct dst_entry *dst_destroy(struct dst_entry *dst); 4004a6ce2b6SWei Wang void dst_dev_put(struct dst_entry *dst); 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds static inline void dst_confirm(struct dst_entry *dst) 4031da177e4SLinus Torvalds { 40469cce1d1SDavid S. Miller } 4055110effeSDavid S. Miller 406d3aaeb38SDavid S. Miller static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) 407d3aaeb38SDavid S. Miller { 408aaa0c23cSZhouyi Zhou struct neighbour *n = dst->ops->neigh_lookup(dst, NULL, daddr); 409aaa0c23cSZhouyi Zhou return IS_ERR(n) ? NULL : n; 410f894cbf8SDavid S. Miller } 411f894cbf8SDavid S. Miller 412f894cbf8SDavid S. Miller static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst, 413f894cbf8SDavid S. Miller struct sk_buff *skb) 414f894cbf8SDavid S. Miller { 415aaa0c23cSZhouyi Zhou struct neighbour *n = dst->ops->neigh_lookup(dst, skb, NULL); 416aaa0c23cSZhouyi Zhou return IS_ERR(n) ? NULL : n; 417d3aaeb38SDavid S. Miller } 418d3aaeb38SDavid S. Miller 41963fca65dSJulian Anastasov static inline void dst_confirm_neigh(const struct dst_entry *dst, 42063fca65dSJulian Anastasov const void *daddr) 42163fca65dSJulian Anastasov { 42263fca65dSJulian Anastasov if (dst->ops->confirm_neigh) 42363fca65dSJulian Anastasov dst->ops->confirm_neigh(dst, daddr); 42463fca65dSJulian Anastasov } 42563fca65dSJulian Anastasov 4261da177e4SLinus Torvalds static inline void dst_link_failure(struct sk_buff *skb) 4271da177e4SLinus Torvalds { 428adf30907SEric Dumazet struct dst_entry *dst = skb_dst(skb); 4291da177e4SLinus Torvalds if (dst && dst->ops && dst->ops->link_failure) 4301da177e4SLinus Torvalds dst->ops->link_failure(skb); 4311da177e4SLinus Torvalds } 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds static inline void dst_set_expires(struct dst_entry *dst, int timeout) 4341da177e4SLinus Torvalds { 4351da177e4SLinus Torvalds unsigned long expires = jiffies + timeout; 4361da177e4SLinus Torvalds 4371da177e4SLinus Torvalds if (expires == 0) 4381da177e4SLinus Torvalds expires = 1; 4391da177e4SLinus Torvalds 4401da177e4SLinus Torvalds if (dst->expires == 0 || time_before(expires, dst->expires)) 4411da177e4SLinus Torvalds dst->expires = expires; 4421da177e4SLinus Torvalds } 4431da177e4SLinus Torvalds 4441da177e4SLinus Torvalds /* Output packet to network from transport. */ 44513206b6bSEric W. Biederman static inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb) 446aad88724SEric Dumazet { 447ede2059dSEric W. Biederman return skb_dst(skb)->output(net, sk, skb); 448aad88724SEric Dumazet } 4491da177e4SLinus Torvalds 4501da177e4SLinus Torvalds /* Input packet from network to transport. */ 4511da177e4SLinus Torvalds static inline int dst_input(struct sk_buff *skb) 4521da177e4SLinus Torvalds { 453adf30907SEric Dumazet return skb_dst(skb)->input(skb); 4541da177e4SLinus Torvalds } 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie) 4571da177e4SLinus Torvalds { 4581da177e4SLinus Torvalds if (dst->obsolete) 4591da177e4SLinus Torvalds dst = dst->ops->check(dst, cookie); 4601da177e4SLinus Torvalds return dst; 4611da177e4SLinus Torvalds } 4621da177e4SLinus Torvalds 463815f4e57SHerbert Xu /* Flags for xfrm_lookup flags argument. */ 464815f4e57SHerbert Xu enum { 46580c0bc9eSDavid S. Miller XFRM_LOOKUP_ICMP = 1 << 0, 466b8c203b2SSteffen Klassert XFRM_LOOKUP_QUEUE = 1 << 1, 467ac37e251Shuaibin Wang XFRM_LOOKUP_KEEP_DST_REF = 1 << 2, 468815f4e57SHerbert Xu }; 469815f4e57SHerbert Xu 4701da177e4SLinus Torvalds struct flowi; 4711da177e4SLinus Torvalds #ifndef CONFIG_XFRM 472452edd59SDavid S. Miller static inline struct dst_entry *xfrm_lookup(struct net *net, 473452edd59SDavid S. Miller struct dst_entry *dst_orig, 4746f9c9615SEric Dumazet const struct flowi *fl, 4756f9c9615SEric Dumazet const struct sock *sk, 476dee9f4bcSDavid S. Miller int flags) 4771da177e4SLinus Torvalds { 478452edd59SDavid S. Miller return dst_orig; 4791da177e4SLinus Torvalds } 480e87b3998SVlad Yasevich 481f92ee619SSteffen Klassert static inline struct dst_entry *xfrm_lookup_route(struct net *net, 482f92ee619SSteffen Klassert struct dst_entry *dst_orig, 483f92ee619SSteffen Klassert const struct flowi *fl, 4846f9c9615SEric Dumazet const struct sock *sk, 485f92ee619SSteffen Klassert int flags) 486f92ee619SSteffen Klassert { 487f92ee619SSteffen Klassert return dst_orig; 488f92ee619SSteffen Klassert } 489f92ee619SSteffen Klassert 490e87b3998SVlad Yasevich static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) 491e87b3998SVlad Yasevich { 492e87b3998SVlad Yasevich return NULL; 493e87b3998SVlad Yasevich } 494e87b3998SVlad Yasevich 4951da177e4SLinus Torvalds #else 496a4023dd0SJoe Perches struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, 4976f9c9615SEric Dumazet const struct flowi *fl, const struct sock *sk, 498452edd59SDavid S. Miller int flags); 499e87b3998SVlad Yasevich 500f92ee619SSteffen Klassert struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, 5016f9c9615SEric Dumazet const struct flowi *fl, const struct sock *sk, 502f92ee619SSteffen Klassert int flags); 503f92ee619SSteffen Klassert 504e87b3998SVlad Yasevich /* skb attached with this dst needs transformation if dst->xfrm is valid */ 505e87b3998SVlad Yasevich static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) 506e87b3998SVlad Yasevich { 507e87b3998SVlad Yasevich return dst->xfrm; 508e87b3998SVlad Yasevich } 5091da177e4SLinus Torvalds #endif 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds #endif /* _NET_DST_H */ 512