18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * net/dst.h Protocol independent destination cache definitions. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef _NET_DST_H 108c2ecf20Sopenharmony_ci#define _NET_DST_H 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <net/dst_ops.h> 138c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 148c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h> 158c2ecf20Sopenharmony_ci#include <linux/rcupdate.h> 168c2ecf20Sopenharmony_ci#include <linux/bug.h> 178c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 188c2ecf20Sopenharmony_ci#include <linux/refcount.h> 198c2ecf20Sopenharmony_ci#include <net/neighbour.h> 208c2ecf20Sopenharmony_ci#include <asm/processor.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistruct sk_buff; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct dst_entry { 258c2ecf20Sopenharmony_ci struct net_device *dev; 268c2ecf20Sopenharmony_ci struct dst_ops *ops; 278c2ecf20Sopenharmony_ci unsigned long _metrics; 288c2ecf20Sopenharmony_ci unsigned long expires; 298c2ecf20Sopenharmony_ci#ifdef CONFIG_XFRM 308c2ecf20Sopenharmony_ci struct xfrm_state *xfrm; 318c2ecf20Sopenharmony_ci#else 328c2ecf20Sopenharmony_ci void *__pad1; 338c2ecf20Sopenharmony_ci#endif 348c2ecf20Sopenharmony_ci int (*input)(struct sk_buff *); 358c2ecf20Sopenharmony_ci int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci unsigned short flags; 388c2ecf20Sopenharmony_ci#define DST_NOXFRM 0x0002 398c2ecf20Sopenharmony_ci#define DST_NOPOLICY 0x0004 408c2ecf20Sopenharmony_ci#define DST_NOCOUNT 0x0008 418c2ecf20Sopenharmony_ci#define DST_FAKE_RTABLE 0x0010 428c2ecf20Sopenharmony_ci#define DST_XFRM_TUNNEL 0x0020 438c2ecf20Sopenharmony_ci#define DST_XFRM_QUEUE 0x0040 448c2ecf20Sopenharmony_ci#define DST_METADATA 0x0080 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci /* A non-zero value of dst->obsolete forces by-hand validation 478c2ecf20Sopenharmony_ci * of the route entry. Positive values are set by the generic 488c2ecf20Sopenharmony_ci * dst layer to indicate that the entry has been forcefully 498c2ecf20Sopenharmony_ci * destroyed. 508c2ecf20Sopenharmony_ci * 518c2ecf20Sopenharmony_ci * Negative values are used by the implementation layer code to 528c2ecf20Sopenharmony_ci * force invocation of the dst_ops->check() method. 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_ci short obsolete; 558c2ecf20Sopenharmony_ci#define DST_OBSOLETE_NONE 0 568c2ecf20Sopenharmony_ci#define DST_OBSOLETE_DEAD 2 578c2ecf20Sopenharmony_ci#define DST_OBSOLETE_FORCE_CHK -1 588c2ecf20Sopenharmony_ci#define DST_OBSOLETE_KILL -2 598c2ecf20Sopenharmony_ci unsigned short header_len; /* more space at head required */ 608c2ecf20Sopenharmony_ci unsigned short trailer_len; /* space to reserve at tail */ 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci /* 638c2ecf20Sopenharmony_ci * __refcnt wants to be on a different cache line from 648c2ecf20Sopenharmony_ci * input/output/ops or performance tanks badly 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 678c2ecf20Sopenharmony_ci atomic_t __refcnt; /* 64-bit offset 64 */ 688c2ecf20Sopenharmony_ci#endif 698c2ecf20Sopenharmony_ci int __use; 708c2ecf20Sopenharmony_ci unsigned long lastuse; 718c2ecf20Sopenharmony_ci struct lwtunnel_state *lwtstate; 728c2ecf20Sopenharmony_ci struct rcu_head rcu_head; 738c2ecf20Sopenharmony_ci short error; 748c2ecf20Sopenharmony_ci short __pad; 758c2ecf20Sopenharmony_ci __u32 tclassid; 768c2ecf20Sopenharmony_ci#ifndef CONFIG_64BIT 778c2ecf20Sopenharmony_ci atomic_t __refcnt; /* 32-bit offset 64 */ 788c2ecf20Sopenharmony_ci#endif 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistruct dst_metrics { 828c2ecf20Sopenharmony_ci u32 metrics[RTAX_MAX]; 838c2ecf20Sopenharmony_ci refcount_t refcnt; 848c2ecf20Sopenharmony_ci} __aligned(4); /* Low pointer bits contain DST_METRICS_FLAGS */ 858c2ecf20Sopenharmony_ciextern const struct dst_metrics dst_default_metrics; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ciu32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#define DST_METRICS_READ_ONLY 0x1UL 908c2ecf20Sopenharmony_ci#define DST_METRICS_REFCOUNTED 0x2UL 918c2ecf20Sopenharmony_ci#define DST_METRICS_FLAGS 0x3UL 928c2ecf20Sopenharmony_ci#define __DST_METRICS_PTR(Y) \ 938c2ecf20Sopenharmony_ci ((u32 *)((Y) & ~DST_METRICS_FLAGS)) 948c2ecf20Sopenharmony_ci#define DST_METRICS_PTR(X) __DST_METRICS_PTR((X)->_metrics) 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic inline bool dst_metrics_read_only(const struct dst_entry *dst) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci return dst->_metrics & DST_METRICS_READ_ONLY; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_civoid __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic inline void dst_destroy_metrics_generic(struct dst_entry *dst) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci unsigned long val = dst->_metrics; 1068c2ecf20Sopenharmony_ci if (!(val & DST_METRICS_READ_ONLY)) 1078c2ecf20Sopenharmony_ci __dst_destroy_metrics_generic(dst, val); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic inline u32 *dst_metrics_write_ptr(struct dst_entry *dst) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci unsigned long p = dst->_metrics; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci BUG_ON(!p); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (p & DST_METRICS_READ_ONLY) 1178c2ecf20Sopenharmony_ci return dst->ops->cow_metrics(dst, p); 1188c2ecf20Sopenharmony_ci return __DST_METRICS_PTR(p); 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/* This may only be invoked before the entry has reached global 1228c2ecf20Sopenharmony_ci * visibility. 1238c2ecf20Sopenharmony_ci */ 1248c2ecf20Sopenharmony_cistatic inline void dst_init_metrics(struct dst_entry *dst, 1258c2ecf20Sopenharmony_ci const u32 *src_metrics, 1268c2ecf20Sopenharmony_ci bool read_only) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci dst->_metrics = ((unsigned long) src_metrics) | 1298c2ecf20Sopenharmony_ci (read_only ? DST_METRICS_READ_ONLY : 0); 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci u32 *dst_metrics = dst_metrics_write_ptr(dest); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (dst_metrics) { 1378c2ecf20Sopenharmony_ci u32 *src_metrics = DST_METRICS_PTR(src); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci memcpy(dst_metrics, src_metrics, RTAX_MAX * sizeof(u32)); 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic inline u32 *dst_metrics_ptr(struct dst_entry *dst) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci return DST_METRICS_PTR(dst); 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic inline u32 1498c2ecf20Sopenharmony_cidst_metric_raw(const struct dst_entry *dst, const int metric) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci u32 *p = DST_METRICS_PTR(dst); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci return p[metric-1]; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic inline u32 1578c2ecf20Sopenharmony_cidst_metric(const struct dst_entry *dst, const int metric) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci WARN_ON_ONCE(metric == RTAX_HOPLIMIT || 1608c2ecf20Sopenharmony_ci metric == RTAX_ADVMSS || 1618c2ecf20Sopenharmony_ci metric == RTAX_MTU); 1628c2ecf20Sopenharmony_ci return dst_metric_raw(dst, metric); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic inline u32 1668c2ecf20Sopenharmony_cidst_metric_advmss(const struct dst_entry *dst) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci u32 advmss = dst_metric_raw(dst, RTAX_ADVMSS); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if (!advmss) 1718c2ecf20Sopenharmony_ci advmss = dst->ops->default_advmss(dst); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci return advmss; 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci u32 *p = dst_metrics_write_ptr(dst); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci if (p) 1818c2ecf20Sopenharmony_ci p[metric-1] = val; 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci/* Kernel-internal feature bits that are unallocated in user space. */ 1858c2ecf20Sopenharmony_ci#define DST_FEATURE_ECN_CA (1U << 31) 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci#define DST_FEATURE_MASK (DST_FEATURE_ECN_CA) 1888c2ecf20Sopenharmony_ci#define DST_FEATURE_ECN_MASK (DST_FEATURE_ECN_CA | RTAX_FEATURE_ECN) 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic inline u32 1918c2ecf20Sopenharmony_cidst_feature(const struct dst_entry *dst, u32 feature) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci return dst_metric(dst, RTAX_FEATURES) & feature; 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistatic inline u32 dst_mtu(const struct dst_entry *dst) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci return dst->ops->mtu(dst); 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci/* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */ 2028c2ecf20Sopenharmony_cistatic inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metric) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci return msecs_to_jiffies(dst_metric(dst, metric)); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic inline u32 2088c2ecf20Sopenharmony_cidst_allfrag(const struct dst_entry *dst) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci int ret = dst_feature(dst, RTAX_FEATURE_ALLFRAG); 2118c2ecf20Sopenharmony_ci return ret; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic inline int 2158c2ecf20Sopenharmony_cidst_metric_locked(const struct dst_entry *dst, int metric) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci return dst_metric(dst, RTAX_LOCK) & (1 << metric); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic inline void dst_hold(struct dst_entry *dst) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci /* 2238c2ecf20Sopenharmony_ci * If your kernel compilation stops here, please check 2248c2ecf20Sopenharmony_ci * the placement of __refcnt in struct dst_entry 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63); 2278c2ecf20Sopenharmony_ci WARN_ON(atomic_inc_not_zero(&dst->__refcnt) == 0); 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic inline void dst_use_noref(struct dst_entry *dst, unsigned long time) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci if (unlikely(time != dst->lastuse)) { 2338c2ecf20Sopenharmony_ci dst->__use++; 2348c2ecf20Sopenharmony_ci dst->lastuse = time; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic inline struct dst_entry *dst_clone(struct dst_entry *dst) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci if (dst) 2418c2ecf20Sopenharmony_ci dst_hold(dst); 2428c2ecf20Sopenharmony_ci return dst; 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_civoid dst_release(struct dst_entry *dst); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_civoid dst_release_immediate(struct dst_entry *dst); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic inline void refdst_drop(unsigned long refdst) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci if (!(refdst & SKB_DST_NOREF)) 2528c2ecf20Sopenharmony_ci dst_release((struct dst_entry *)(refdst & SKB_DST_PTRMASK)); 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci/** 2568c2ecf20Sopenharmony_ci * skb_dst_drop - drops skb dst 2578c2ecf20Sopenharmony_ci * @skb: buffer 2588c2ecf20Sopenharmony_ci * 2598c2ecf20Sopenharmony_ci * Drops dst reference count if a reference was taken. 2608c2ecf20Sopenharmony_ci */ 2618c2ecf20Sopenharmony_cistatic inline void skb_dst_drop(struct sk_buff *skb) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci if (skb->_skb_refdst) { 2648c2ecf20Sopenharmony_ci refdst_drop(skb->_skb_refdst); 2658c2ecf20Sopenharmony_ci skb->_skb_refdst = 0UL; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cistatic inline void __skb_dst_copy(struct sk_buff *nskb, unsigned long refdst) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci nskb->_skb_refdst = refdst; 2728c2ecf20Sopenharmony_ci if (!(nskb->_skb_refdst & SKB_DST_NOREF)) 2738c2ecf20Sopenharmony_ci dst_clone(skb_dst(nskb)); 2748c2ecf20Sopenharmony_ci} 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistatic inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci __skb_dst_copy(nskb, oskb->_skb_refdst); 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci/** 2828c2ecf20Sopenharmony_ci * dst_hold_safe - Take a reference on a dst if possible 2838c2ecf20Sopenharmony_ci * @dst: pointer to dst entry 2848c2ecf20Sopenharmony_ci * 2858c2ecf20Sopenharmony_ci * This helper returns false if it could not safely 2868c2ecf20Sopenharmony_ci * take a reference on a dst. 2878c2ecf20Sopenharmony_ci */ 2888c2ecf20Sopenharmony_cistatic inline bool dst_hold_safe(struct dst_entry *dst) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci return atomic_inc_not_zero(&dst->__refcnt); 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/** 2948c2ecf20Sopenharmony_ci * skb_dst_force - makes sure skb dst is refcounted 2958c2ecf20Sopenharmony_ci * @skb: buffer 2968c2ecf20Sopenharmony_ci * 2978c2ecf20Sopenharmony_ci * If dst is not yet refcounted and not destroyed, grab a ref on it. 2988c2ecf20Sopenharmony_ci * Returns true if dst is refcounted. 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_cistatic inline bool skb_dst_force(struct sk_buff *skb) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci if (skb_dst_is_noref(skb)) { 3038c2ecf20Sopenharmony_ci struct dst_entry *dst = skb_dst(skb); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci WARN_ON(!rcu_read_lock_held()); 3068c2ecf20Sopenharmony_ci if (!dst_hold_safe(dst)) 3078c2ecf20Sopenharmony_ci dst = NULL; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci skb->_skb_refdst = (unsigned long)dst; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci return skb->_skb_refdst != 0UL; 3138c2ecf20Sopenharmony_ci} 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci/** 3178c2ecf20Sopenharmony_ci * __skb_tunnel_rx - prepare skb for rx reinsert 3188c2ecf20Sopenharmony_ci * @skb: buffer 3198c2ecf20Sopenharmony_ci * @dev: tunnel device 3208c2ecf20Sopenharmony_ci * @net: netns for packet i/o 3218c2ecf20Sopenharmony_ci * 3228c2ecf20Sopenharmony_ci * After decapsulation, packet is going to re-enter (netif_rx()) our stack, 3238c2ecf20Sopenharmony_ci * so make some cleanups. (no accounting done) 3248c2ecf20Sopenharmony_ci */ 3258c2ecf20Sopenharmony_cistatic inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, 3268c2ecf20Sopenharmony_ci struct net *net) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci skb->dev = dev; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* 3318c2ecf20Sopenharmony_ci * Clear hash so that we can recalulate the hash for the 3328c2ecf20Sopenharmony_ci * encapsulated packet, unless we have already determine the hash 3338c2ecf20Sopenharmony_ci * over the L4 4-tuple. 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_ci skb_clear_hash_if_not_l4(skb); 3368c2ecf20Sopenharmony_ci skb_set_queue_mapping(skb, 0); 3378c2ecf20Sopenharmony_ci skb_scrub_packet(skb, !net_eq(net, dev_net(dev))); 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci/** 3418c2ecf20Sopenharmony_ci * skb_tunnel_rx - prepare skb for rx reinsert 3428c2ecf20Sopenharmony_ci * @skb: buffer 3438c2ecf20Sopenharmony_ci * @dev: tunnel device 3448c2ecf20Sopenharmony_ci * @net: netns for packet i/o 3458c2ecf20Sopenharmony_ci * 3468c2ecf20Sopenharmony_ci * After decapsulation, packet is going to re-enter (netif_rx()) our stack, 3478c2ecf20Sopenharmony_ci * so make some cleanups, and perform accounting. 3488c2ecf20Sopenharmony_ci * Note: this accounting is not SMP safe. 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_cistatic inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, 3518c2ecf20Sopenharmony_ci struct net *net) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci DEV_STATS_INC(dev, rx_packets); 3548c2ecf20Sopenharmony_ci DEV_STATS_ADD(dev, rx_bytes, skb->len); 3558c2ecf20Sopenharmony_ci __skb_tunnel_rx(skb, dev, net); 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic inline u32 dst_tclassid(const struct sk_buff *skb) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci#ifdef CONFIG_IP_ROUTE_CLASSID 3618c2ecf20Sopenharmony_ci const struct dst_entry *dst; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci dst = skb_dst(skb); 3648c2ecf20Sopenharmony_ci if (dst) 3658c2ecf20Sopenharmony_ci return dst->tclassid; 3668c2ecf20Sopenharmony_ci#endif 3678c2ecf20Sopenharmony_ci return 0; 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ciint dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb); 3718c2ecf20Sopenharmony_cistatic inline int dst_discard(struct sk_buff *skb) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci return dst_discard_out(&init_net, skb->sk, skb); 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_civoid *dst_alloc(struct dst_ops *ops, struct net_device *dev, int initial_ref, 3768c2ecf20Sopenharmony_ci int initial_obsolete, unsigned short flags); 3778c2ecf20Sopenharmony_civoid dst_init(struct dst_entry *dst, struct dst_ops *ops, 3788c2ecf20Sopenharmony_ci struct net_device *dev, int initial_ref, int initial_obsolete, 3798c2ecf20Sopenharmony_ci unsigned short flags); 3808c2ecf20Sopenharmony_cistruct dst_entry *dst_destroy(struct dst_entry *dst); 3818c2ecf20Sopenharmony_civoid dst_dev_put(struct dst_entry *dst); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic inline void dst_confirm(struct dst_entry *dst) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci struct neighbour *n = dst->ops->neigh_lookup(dst, NULL, daddr); 3908c2ecf20Sopenharmony_ci return IS_ERR(n) ? NULL : n; 3918c2ecf20Sopenharmony_ci} 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_cistatic inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst, 3948c2ecf20Sopenharmony_ci struct sk_buff *skb) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci struct neighbour *n = NULL; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* The packets from tunnel devices (eg bareudp) may have only 3998c2ecf20Sopenharmony_ci * metadata in the dst pointer of skb. Hence a pointer check of 4008c2ecf20Sopenharmony_ci * neigh_lookup is needed. 4018c2ecf20Sopenharmony_ci */ 4028c2ecf20Sopenharmony_ci if (dst->ops->neigh_lookup) 4038c2ecf20Sopenharmony_ci n = dst->ops->neigh_lookup(dst, skb, NULL); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci return IS_ERR(n) ? NULL : n; 4068c2ecf20Sopenharmony_ci} 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_cistatic inline void dst_confirm_neigh(const struct dst_entry *dst, 4098c2ecf20Sopenharmony_ci const void *daddr) 4108c2ecf20Sopenharmony_ci{ 4118c2ecf20Sopenharmony_ci if (dst->ops->confirm_neigh) 4128c2ecf20Sopenharmony_ci dst->ops->confirm_neigh(dst, daddr); 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic inline void dst_link_failure(struct sk_buff *skb) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci struct dst_entry *dst = skb_dst(skb); 4188c2ecf20Sopenharmony_ci if (dst && dst->ops && dst->ops->link_failure) 4198c2ecf20Sopenharmony_ci dst->ops->link_failure(skb); 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cistatic inline void dst_set_expires(struct dst_entry *dst, int timeout) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci unsigned long expires = jiffies + timeout; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci if (expires == 0) 4278c2ecf20Sopenharmony_ci expires = 1; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci if (dst->expires == 0 || time_before(expires, dst->expires)) 4308c2ecf20Sopenharmony_ci dst->expires = expires; 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci/* Output packet to network from transport. */ 4348c2ecf20Sopenharmony_cistatic inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci return skb_dst(skb)->output(net, sk, skb); 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci/* Input packet from network to transport. */ 4408c2ecf20Sopenharmony_cistatic inline int dst_input(struct sk_buff *skb) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci return skb_dst(skb)->input(skb); 4438c2ecf20Sopenharmony_ci} 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_cistatic inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie) 4468c2ecf20Sopenharmony_ci{ 4478c2ecf20Sopenharmony_ci if (dst->obsolete) 4488c2ecf20Sopenharmony_ci dst = dst->ops->check(dst, cookie); 4498c2ecf20Sopenharmony_ci return dst; 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci/* Flags for xfrm_lookup flags argument. */ 4538c2ecf20Sopenharmony_cienum { 4548c2ecf20Sopenharmony_ci XFRM_LOOKUP_ICMP = 1 << 0, 4558c2ecf20Sopenharmony_ci XFRM_LOOKUP_QUEUE = 1 << 1, 4568c2ecf20Sopenharmony_ci XFRM_LOOKUP_KEEP_DST_REF = 1 << 2, 4578c2ecf20Sopenharmony_ci}; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_cistruct flowi; 4608c2ecf20Sopenharmony_ci#ifndef CONFIG_XFRM 4618c2ecf20Sopenharmony_cistatic inline struct dst_entry *xfrm_lookup(struct net *net, 4628c2ecf20Sopenharmony_ci struct dst_entry *dst_orig, 4638c2ecf20Sopenharmony_ci const struct flowi *fl, 4648c2ecf20Sopenharmony_ci const struct sock *sk, 4658c2ecf20Sopenharmony_ci int flags) 4668c2ecf20Sopenharmony_ci{ 4678c2ecf20Sopenharmony_ci return dst_orig; 4688c2ecf20Sopenharmony_ci} 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_cistatic inline struct dst_entry * 4718c2ecf20Sopenharmony_cixfrm_lookup_with_ifid(struct net *net, struct dst_entry *dst_orig, 4728c2ecf20Sopenharmony_ci const struct flowi *fl, const struct sock *sk, 4738c2ecf20Sopenharmony_ci int flags, u32 if_id) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci return dst_orig; 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic inline struct dst_entry *xfrm_lookup_route(struct net *net, 4798c2ecf20Sopenharmony_ci struct dst_entry *dst_orig, 4808c2ecf20Sopenharmony_ci const struct flowi *fl, 4818c2ecf20Sopenharmony_ci const struct sock *sk, 4828c2ecf20Sopenharmony_ci int flags) 4838c2ecf20Sopenharmony_ci{ 4848c2ecf20Sopenharmony_ci return dst_orig; 4858c2ecf20Sopenharmony_ci} 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_cistatic inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci return NULL; 4908c2ecf20Sopenharmony_ci} 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci#else 4938c2ecf20Sopenharmony_cistruct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, 4948c2ecf20Sopenharmony_ci const struct flowi *fl, const struct sock *sk, 4958c2ecf20Sopenharmony_ci int flags); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cistruct dst_entry *xfrm_lookup_with_ifid(struct net *net, 4988c2ecf20Sopenharmony_ci struct dst_entry *dst_orig, 4998c2ecf20Sopenharmony_ci const struct flowi *fl, 5008c2ecf20Sopenharmony_ci const struct sock *sk, int flags, 5018c2ecf20Sopenharmony_ci u32 if_id); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_cistruct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, 5048c2ecf20Sopenharmony_ci const struct flowi *fl, const struct sock *sk, 5058c2ecf20Sopenharmony_ci int flags); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci/* skb attached with this dst needs transformation if dst->xfrm is valid */ 5088c2ecf20Sopenharmony_cistatic inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) 5098c2ecf20Sopenharmony_ci{ 5108c2ecf20Sopenharmony_ci return dst->xfrm; 5118c2ecf20Sopenharmony_ci} 5128c2ecf20Sopenharmony_ci#endif 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_cistatic inline void skb_dst_update_pmtu(struct sk_buff *skb, u32 mtu) 5158c2ecf20Sopenharmony_ci{ 5168c2ecf20Sopenharmony_ci struct dst_entry *dst = skb_dst(skb); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci if (dst && dst->ops->update_pmtu) 5198c2ecf20Sopenharmony_ci dst->ops->update_pmtu(dst, NULL, skb, mtu, true); 5208c2ecf20Sopenharmony_ci} 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci/* update dst pmtu but not do neighbor confirm */ 5238c2ecf20Sopenharmony_cistatic inline void skb_dst_update_pmtu_no_confirm(struct sk_buff *skb, u32 mtu) 5248c2ecf20Sopenharmony_ci{ 5258c2ecf20Sopenharmony_ci struct dst_entry *dst = skb_dst(skb); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci if (dst && dst->ops->update_pmtu) 5288c2ecf20Sopenharmony_ci dst->ops->update_pmtu(dst, NULL, skb, mtu, false); 5298c2ecf20Sopenharmony_ci} 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_cistruct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie); 5328c2ecf20Sopenharmony_civoid dst_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk, 5338c2ecf20Sopenharmony_ci struct sk_buff *skb, u32 mtu, bool confirm_neigh); 5348c2ecf20Sopenharmony_civoid dst_blackhole_redirect(struct dst_entry *dst, struct sock *sk, 5358c2ecf20Sopenharmony_ci struct sk_buff *skb); 5368c2ecf20Sopenharmony_ciu32 *dst_blackhole_cow_metrics(struct dst_entry *dst, unsigned long old); 5378c2ecf20Sopenharmony_cistruct neighbour *dst_blackhole_neigh_lookup(const struct dst_entry *dst, 5388c2ecf20Sopenharmony_ci struct sk_buff *skb, 5398c2ecf20Sopenharmony_ci const void *daddr); 5408c2ecf20Sopenharmony_ciunsigned int dst_blackhole_mtu(const struct dst_entry *dst); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci#endif /* _NET_DST_H */ 543