linux/include/net/dst.h
<<
>>
Prefs
   1/*
   2 * net/dst.h    Protocol independent destination cache definitions.
   3 *
   4 * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
   5 *
   6 */
   7
   8#ifndef _NET_DST_H
   9#define _NET_DST_H
  10
  11#include <net/dst_ops.h>
  12#include <linux/netdevice.h>
  13#include <linux/rtnetlink.h>
  14#include <linux/rcupdate.h>
  15#include <linux/jiffies.h>
  16#include <net/neighbour.h>
  17#include <asm/processor.h>
  18
  19/*
  20 * 0 - no debugging messages
  21 * 1 - rare events and bugs (default)
  22 * 2 - trace mode.
  23 */
  24#define RT_CACHE_DEBUG          0
  25
  26#define DST_GC_MIN      (HZ/10)
  27#define DST_GC_INC      (HZ/2)
  28#define DST_GC_MAX      (120*HZ)
  29
  30/* Each dst_entry has reference count and sits in some parent list(s).
  31 * When it is removed from parent list, it is "freed" (dst_free).
  32 * After this it enters dead state (dst->obsolete > 0) and if its refcnt
  33 * is zero, it can be destroyed immediately, otherwise it is added
  34 * to gc list and garbage collector periodically checks the refcnt.
  35 */
  36
  37struct sk_buff;
  38
  39struct dst_entry {
  40        struct rcu_head         rcu_head;
  41        struct dst_entry        *child;
  42        struct net_device       *dev;
  43        short                   error;
  44        short                   obsolete;
  45        int                     flags;
  46#define DST_HOST                0x0001
  47#define DST_NOXFRM              0x0002
  48#define DST_NOPOLICY            0x0004
  49#define DST_NOHASH              0x0008
  50#define DST_NOCACHE             0x0010
  51        unsigned long           expires;
  52
  53        unsigned short          header_len;     /* more space at head required */
  54        unsigned short          trailer_len;    /* space to reserve at tail */
  55
  56        unsigned int            rate_tokens;
  57        unsigned long           rate_last;      /* rate limiting for ICMP */
  58
  59        struct dst_entry        *path;
  60
  61        struct neighbour        *neighbour;
  62        struct hh_cache         *hh;
  63#ifdef CONFIG_XFRM
  64        struct xfrm_state       *xfrm;
  65#else
  66        void                    *__pad1;
  67#endif
  68        int                     (*input)(struct sk_buff*);
  69        int                     (*output)(struct sk_buff*);
  70
  71        struct  dst_ops         *ops;
  72
  73        u32                     _metrics[RTAX_MAX];
  74
  75#ifdef CONFIG_NET_CLS_ROUTE
  76        __u32                   tclassid;
  77#else
  78        __u32                   __pad2;
  79#endif
  80
  81
  82        /*
  83         * Align __refcnt to a 64 bytes alignment
  84         * (L1_CACHE_SIZE would be too much)
  85         */
  86#ifdef CONFIG_64BIT
  87        long                    __pad_to_align_refcnt[1];
  88#endif
  89        /*
  90         * __refcnt wants to be on a different cache line from
  91         * input/output/ops or performance tanks badly
  92         */
  93        atomic_t                __refcnt;       /* client references    */
  94        int                     __use;
  95        unsigned long           lastuse;
  96        union {
  97                struct dst_entry        *next;
  98                struct rtable __rcu     *rt_next;
  99                struct rt6_info         *rt6_next;
 100                struct dn_route __rcu   *dn_next;
 101        };
 102};
 103
 104#ifdef __KERNEL__
 105
 106static inline u32
 107dst_metric_raw(const struct dst_entry *dst, const int metric)
 108{
 109        return dst->_metrics[metric-1];
 110}
 111
 112static inline u32
 113dst_metric(const struct dst_entry *dst, const int metric)
 114{
 115        WARN_ON_ONCE(metric == RTAX_HOPLIMIT ||
 116                     metric == RTAX_ADVMSS ||
 117                     metric == RTAX_MTU);
 118        return dst_metric_raw(dst, metric);
 119}
 120
 121static inline u32
 122dst_metric_advmss(const struct dst_entry *dst)
 123{
 124        u32 advmss = dst_metric_raw(dst, RTAX_ADVMSS);
 125
 126        if (!advmss)
 127                advmss = dst->ops->default_advmss(dst);
 128
 129        return advmss;
 130}
 131
 132static inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val)
 133{
 134        dst->_metrics[metric-1] = val;
 135}
 136
 137static inline void dst_import_metrics(struct dst_entry *dst, const u32 *src_metrics)
 138{
 139        memcpy(dst->_metrics, src_metrics, RTAX_MAX * sizeof(u32));
 140}
 141
 142static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src)
 143{
 144        dst_import_metrics(dest, src->_metrics);
 145}
 146
 147static inline u32 *dst_metrics_ptr(struct dst_entry *dst)
 148{
 149        return dst->_metrics;
 150}
 151
 152static inline u32
 153dst_feature(const struct dst_entry *dst, u32 feature)
 154{
 155        return dst_metric(dst, RTAX_FEATURES) & feature;
 156}
 157
 158static inline u32 dst_mtu(const struct dst_entry *dst)
 159{
 160        u32 mtu = dst_metric_raw(dst, RTAX_MTU);
 161
 162        if (!mtu)
 163                mtu = dst->ops->default_mtu(dst);
 164
 165        return mtu;
 166}
 167
 168/* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */
 169static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metric)
 170{
 171        return msecs_to_jiffies(dst_metric(dst, metric));
 172}
 173
 174static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric,
 175                                      unsigned long rtt)
 176{
 177        dst_metric_set(dst, metric, jiffies_to_msecs(rtt));
 178}
 179
 180static inline u32
 181dst_allfrag(const struct dst_entry *dst)
 182{
 183        int ret = dst_feature(dst,  RTAX_FEATURE_ALLFRAG);
 184        /* Yes, _exactly_. This is paranoia. */
 185        barrier();
 186        return ret;
 187}
 188
 189static inline int
 190dst_metric_locked(const struct dst_entry *dst, int metric)
 191{
 192        return dst_metric(dst, RTAX_LOCK) & (1<<metric);
 193}
 194
 195static inline void dst_hold(struct dst_entry * dst)
 196{
 197        /*
 198         * If your kernel compilation stops here, please check
 199         * __pad_to_align_refcnt declaration in struct dst_entry
 200         */
 201        BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63);
 202        atomic_inc(&dst->__refcnt);
 203}
 204
 205static inline void dst_use(struct dst_entry *dst, unsigned long time)
 206{
 207        dst_hold(dst);
 208        dst->__use++;
 209        dst->lastuse = time;
 210}
 211
 212static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
 213{
 214        dst->__use++;
 215        dst->lastuse = time;
 216}
 217
 218static inline
 219struct dst_entry * dst_clone(struct dst_entry * dst)
 220{
 221        if (dst)
 222                atomic_inc(&dst->__refcnt);
 223        return dst;
 224}
 225
 226extern void dst_release(struct dst_entry *dst);
 227
 228static inline void refdst_drop(unsigned long refdst)
 229{
 230        if (!(refdst & SKB_DST_NOREF))
 231                dst_release((struct dst_entry *)(refdst & SKB_DST_PTRMASK));
 232}
 233
 234/**
 235 * skb_dst_drop - drops skb dst
 236 * @skb: buffer
 237 *
 238 * Drops dst reference count if a reference was taken.
 239 */
 240static inline void skb_dst_drop(struct sk_buff *skb)
 241{
 242        if (skb->_skb_refdst) {
 243                refdst_drop(skb->_skb_refdst);
 244                skb->_skb_refdst = 0UL;
 245        }
 246}
 247
 248static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb)
 249{
 250        nskb->_skb_refdst = oskb->_skb_refdst;
 251        if (!(nskb->_skb_refdst & SKB_DST_NOREF))
 252                dst_clone(skb_dst(nskb));
 253}
 254
 255/**
 256 * skb_dst_force - makes sure skb dst is refcounted
 257 * @skb: buffer
 258 *
 259 * If dst is not yet refcounted, let's do it
 260 */
 261static inline void skb_dst_force(struct sk_buff *skb)
 262{
 263        if (skb_dst_is_noref(skb)) {
 264                WARN_ON(!rcu_read_lock_held());
 265                skb->_skb_refdst &= ~SKB_DST_NOREF;
 266                dst_clone(skb_dst(skb));
 267        }
 268}
 269
 270
 271/**
 272 *      __skb_tunnel_rx - prepare skb for rx reinsert
 273 *      @skb: buffer
 274 *      @dev: tunnel device
 275 *
 276 *      After decapsulation, packet is going to re-enter (netif_rx()) our stack,
 277 *      so make some cleanups. (no accounting done)
 278 */
 279static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
 280{
 281        skb->dev = dev;
 282        skb->rxhash = 0;
 283        skb_set_queue_mapping(skb, 0);
 284        skb_dst_drop(skb);
 285        nf_reset(skb);
 286}
 287
 288/**
 289 *      skb_tunnel_rx - prepare skb for rx reinsert
 290 *      @skb: buffer
 291 *      @dev: tunnel device
 292 *
 293 *      After decapsulation, packet is going to re-enter (netif_rx()) our stack,
 294 *      so make some cleanups, and perform accounting.
 295 *      Note: this accounting is not SMP safe.
 296 */
 297static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
 298{
 299        /* TODO : stats should be SMP safe */
 300        dev->stats.rx_packets++;
 301        dev->stats.rx_bytes += skb->len;
 302        __skb_tunnel_rx(skb, dev);
 303}
 304
 305/* Children define the path of the packet through the
 306 * Linux networking.  Thus, destinations are stackable.
 307 */
 308
 309static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
 310{
 311        struct dst_entry *child = skb_dst(skb)->child;
 312
 313        skb_dst_drop(skb);
 314        return child;
 315}
 316
 317extern int dst_discard(struct sk_buff *skb);
 318extern void * dst_alloc(struct dst_ops * ops);
 319extern void __dst_free(struct dst_entry * dst);
 320extern struct dst_entry *dst_destroy(struct dst_entry * dst);
 321
 322static inline void dst_free(struct dst_entry * dst)
 323{
 324        if (dst->obsolete > 1)
 325                return;
 326        if (!atomic_read(&dst->__refcnt)) {
 327                dst = dst_destroy(dst);
 328                if (!dst)
 329                        return;
 330        }
 331        __dst_free(dst);
 332}
 333
 334static inline void dst_rcu_free(struct rcu_head *head)
 335{
 336        struct dst_entry *dst = container_of(head, struct dst_entry, rcu_head);
 337        dst_free(dst);
 338}
 339
 340static inline void dst_confirm(struct dst_entry *dst)
 341{
 342        if (dst)
 343                neigh_confirm(dst->neighbour);
 344}
 345
 346static inline void dst_link_failure(struct sk_buff *skb)
 347{
 348        struct dst_entry *dst = skb_dst(skb);
 349        if (dst && dst->ops && dst->ops->link_failure)
 350                dst->ops->link_failure(skb);
 351}
 352
 353static inline void dst_set_expires(struct dst_entry *dst, int timeout)
 354{
 355        unsigned long expires = jiffies + timeout;
 356
 357        if (expires == 0)
 358                expires = 1;
 359
 360        if (dst->expires == 0 || time_before(expires, dst->expires))
 361                dst->expires = expires;
 362}
 363
 364/* Output packet to network from transport.  */
 365static inline int dst_output(struct sk_buff *skb)
 366{
 367        return skb_dst(skb)->output(skb);
 368}
 369
 370/* Input packet from network to transport.  */
 371static inline int dst_input(struct sk_buff *skb)
 372{
 373        return skb_dst(skb)->input(skb);
 374}
 375
 376static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
 377{
 378        if (dst->obsolete)
 379                dst = dst->ops->check(dst, cookie);
 380        return dst;
 381}
 382
 383extern void             dst_init(void);
 384
 385/* Flags for xfrm_lookup flags argument. */
 386enum {
 387        XFRM_LOOKUP_WAIT = 1 << 0,
 388        XFRM_LOOKUP_ICMP = 1 << 1,
 389};
 390
 391struct flowi;
 392#ifndef CONFIG_XFRM
 393static inline int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
 394                              struct flowi *fl, struct sock *sk, int flags)
 395{
 396        return 0;
 397} 
 398static inline int __xfrm_lookup(struct net *net, struct dst_entry **dst_p,
 399                                struct flowi *fl, struct sock *sk, int flags)
 400{
 401        return 0;
 402}
 403#else
 404extern int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
 405                       struct flowi *fl, struct sock *sk, int flags);
 406extern int __xfrm_lookup(struct net *net, struct dst_entry **dst_p,
 407                         struct flowi *fl, struct sock *sk, int flags);
 408#endif
 409#endif
 410
 411#endif /* _NET_DST_H */
 412