linux/include/net/inetpeer.h
<<
>>
Prefs
   1/*
   2 *              INETPEER - A storage for permanent information about peers
   3 *
   4 *  Authors:    Andrey V. Savochkin <saw@msu.ru>
   5 */
   6
   7#ifndef _NET_INETPEER_H
   8#define _NET_INETPEER_H
   9
  10#include <linux/types.h>
  11#include <linux/init.h>
  12#include <linux/jiffies.h>
  13#include <linux/spinlock.h>
  14#include <linux/rtnetlink.h>
  15#include <net/ipv6.h>
  16#include <linux/atomic.h>
  17
  18/* IPv4 address key for cache lookups */
  19struct ipv4_addr_key {
  20        __be32  addr;
  21        int     vif;
  22};
  23
  24#define INETPEER_MAXKEYSZ   (sizeof(struct in6_addr) / sizeof(u32))
  25
  26struct inetpeer_addr {
  27        union {
  28                struct ipv4_addr_key    a4;
  29                struct in6_addr         a6;
  30                u32                     key[INETPEER_MAXKEYSZ];
  31        };
  32        __u16                           family;
  33};
  34
  35struct inet_peer {
  36        /* group together avl_left,avl_right,v4daddr to speedup lookups */
  37        struct inet_peer __rcu  *avl_left, *avl_right;
  38        struct inetpeer_addr    daddr;
  39        __u32                   avl_height;
  40
  41        u32                     metrics[RTAX_MAX];
  42        u32                     rate_tokens;    /* rate limiting for ICMP */
  43        unsigned long           rate_last;
  44        union {
  45                struct list_head        gc_list;
  46                struct rcu_head     gc_rcu;
  47        };
  48        /*
  49         * Once inet_peer is queued for deletion (refcnt == -1), following field
  50         * is not available: rid
  51         * We can share memory with rcu_head to help keep inet_peer small.
  52         */
  53        union {
  54                struct {
  55                        atomic_t                        rid;            /* Frag reception counter */
  56                };
  57                struct rcu_head         rcu;
  58                struct inet_peer        *gc_next;
  59        };
  60
  61        /* following fields might be frequently dirtied */
  62        __u32                   dtime;  /* the time of last use of not referenced entries */
  63        atomic_t                refcnt;
  64};
  65
  66struct inet_peer_base {
  67        struct inet_peer __rcu  *root;
  68        seqlock_t               lock;
  69        int                     total;
  70};
  71
  72void inet_peer_base_init(struct inet_peer_base *);
  73
  74void inet_initpeers(void) __init;
  75
  76#define INETPEER_METRICS_NEW    (~(u32) 0)
  77
  78static inline void inetpeer_set_addr_v4(struct inetpeer_addr *iaddr, __be32 ip)
  79{
  80        iaddr->a4.addr = ip;
  81        iaddr->a4.vif = 0;
  82        iaddr->family = AF_INET;
  83}
  84
  85static inline __be32 inetpeer_get_addr_v4(struct inetpeer_addr *iaddr)
  86{
  87        return iaddr->a4.addr;
  88}
  89
  90static inline void inetpeer_set_addr_v6(struct inetpeer_addr *iaddr,
  91                                        struct in6_addr *in6)
  92{
  93        iaddr->a6 = *in6;
  94        iaddr->family = AF_INET6;
  95}
  96
  97static inline struct in6_addr *inetpeer_get_addr_v6(struct inetpeer_addr *iaddr)
  98{
  99        return &iaddr->a6;
 100}
 101
 102/* can be called with or without local BH being disabled */
 103struct inet_peer *inet_getpeer(struct inet_peer_base *base,
 104                               const struct inetpeer_addr *daddr,
 105                               int create);
 106
 107static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base,
 108                                                __be32 v4daddr,
 109                                                int vif, int create)
 110{
 111        struct inetpeer_addr daddr;
 112
 113        daddr.a4.addr = v4daddr;
 114        daddr.a4.vif = vif;
 115        daddr.family = AF_INET;
 116        return inet_getpeer(base, &daddr, create);
 117}
 118
 119static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base,
 120                                                const struct in6_addr *v6daddr,
 121                                                int create)
 122{
 123        struct inetpeer_addr daddr;
 124
 125        daddr.a6 = *v6daddr;
 126        daddr.family = AF_INET6;
 127        return inet_getpeer(base, &daddr, create);
 128}
 129
 130static inline int inetpeer_addr_cmp(const struct inetpeer_addr *a,
 131                                    const struct inetpeer_addr *b)
 132{
 133        int i, n;
 134
 135        if (a->family == AF_INET)
 136                n = sizeof(a->a4) / sizeof(u32);
 137        else
 138                n = sizeof(a->a6) / sizeof(u32);
 139
 140        for (i = 0; i < n; i++) {
 141                if (a->key[i] == b->key[i])
 142                        continue;
 143                if (a->key[i] < b->key[i])
 144                        return -1;
 145                return 1;
 146        }
 147
 148        return 0;
 149}
 150
 151/* can be called from BH context or outside */
 152void inet_putpeer(struct inet_peer *p);
 153bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
 154
 155void inetpeer_invalidate_tree(struct inet_peer_base *);
 156
 157#endif /* _NET_INETPEER_H */
 158