1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * INETPEER - A storage for permanent information about peers
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Authors: Andrey V. Savochkin <[email protected]>
61da177e4SLinus Torvalds */
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds #ifndef _NET_INETPEER_H
91da177e4SLinus Torvalds #define _NET_INETPEER_H
101da177e4SLinus Torvalds
111da177e4SLinus Torvalds #include <linux/types.h>
121da177e4SLinus Torvalds #include <linux/init.h>
131da177e4SLinus Torvalds #include <linux/jiffies.h>
141da177e4SLinus Torvalds #include <linux/spinlock.h>
1560659823SDavid S. Miller #include <linux/rtnetlink.h>
16672f007dSDavid S. Miller #include <net/ipv6.h>
1760063497SArun Sharma #include <linux/atomic.h>
181da177e4SLinus Torvalds
19192132b9SDavid Ahern /* IPv4 address key for cache lookups */
20192132b9SDavid Ahern struct ipv4_addr_key {
21192132b9SDavid Ahern __be32 addr;
22192132b9SDavid Ahern int vif;
23192132b9SDavid Ahern };
24192132b9SDavid Ahern
255345c2e1SDavid Ahern #define INETPEER_MAXKEYSZ (sizeof(struct in6_addr) / sizeof(u32))
267a71ed89SDavid S. Miller
277a71ed89SDavid S. Miller struct inetpeer_addr {
285345c2e1SDavid Ahern union {
29192132b9SDavid Ahern struct ipv4_addr_key a4;
305345c2e1SDavid Ahern struct in6_addr a6;
315345c2e1SDavid Ahern u32 key[INETPEER_MAXKEYSZ];
325345c2e1SDavid Ahern };
33582a72daSDavid S. Miller __u16 family;
348790ca17SDavid S. Miller };
35582a72daSDavid S. Miller
36fd2c3ef7SEric Dumazet struct inet_peer {
37b145425fSEric Dumazet struct rb_node rb_node;
388790ca17SDavid S. Miller struct inetpeer_addr daddr;
392b77bddeSEric Dumazet
402b77bddeSEric Dumazet u32 metrics[RTAX_MAX];
412b77bddeSEric Dumazet u32 rate_tokens; /* rate limiting for ICMP */
42c09551c6SLorenzo Bianconi u32 n_redirects;
432b77bddeSEric Dumazet unsigned long rate_last;
44317fe0e6SEric Dumazet /*
451cc9a98bSReshetova, Elena * Once inet_peer is queued for deletion (refcnt == 0), following field
4673f156a6SEric Dumazet * is not available: rid
4760659823SDavid S. Miller * We can share memory with rcu_head to help keep inet_peer small.
48317fe0e6SEric Dumazet */
49317fe0e6SEric Dumazet union {
50317fe0e6SEric Dumazet struct {
5189cee8b1SHerbert Xu atomic_t rid; /* Frag reception counter */
52317fe0e6SEric Dumazet };
53aa1039e7SEric Dumazet struct rcu_head rcu;
541da177e4SLinus Torvalds };
552b77bddeSEric Dumazet
562b77bddeSEric Dumazet /* following fields might be frequently dirtied */
572b77bddeSEric Dumazet __u32 dtime; /* the time of last use of not referenced entries */
581cc9a98bSReshetova, Elena refcount_t refcnt;
59317fe0e6SEric Dumazet };
601da177e4SLinus Torvalds
61c3426b47SDavid S. Miller struct inet_peer_base {
62b145425fSEric Dumazet struct rb_root rb_root;
63c3426b47SDavid S. Miller seqlock_t lock;
64c3426b47SDavid S. Miller int total;
65c3426b47SDavid S. Miller };
66c3426b47SDavid S. Miller
671fd51155SJoe Perches void inet_peer_base_init(struct inet_peer_base *);
68c3426b47SDavid S. Miller
691da177e4SLinus Torvalds void inet_initpeers(void) __init;
701da177e4SLinus Torvalds
71144001bdSDavid S. Miller #define INETPEER_METRICS_NEW (~(u32) 0)
72144001bdSDavid S. Miller
inetpeer_set_addr_v4(struct inetpeer_addr * iaddr,__be32 ip)733abef286SDavid Ahern static inline void inetpeer_set_addr_v4(struct inetpeer_addr *iaddr, __be32 ip)
743abef286SDavid Ahern {
75192132b9SDavid Ahern iaddr->a4.addr = ip;
76887dc9f2SEric Dumazet iaddr->a4.vif = 0;
773abef286SDavid Ahern iaddr->family = AF_INET;
783abef286SDavid Ahern }
793abef286SDavid Ahern
inetpeer_get_addr_v4(struct inetpeer_addr * iaddr)803abef286SDavid Ahern static inline __be32 inetpeer_get_addr_v4(struct inetpeer_addr *iaddr)
813abef286SDavid Ahern {
82192132b9SDavid Ahern return iaddr->a4.addr;
833abef286SDavid Ahern }
843abef286SDavid Ahern
inetpeer_set_addr_v6(struct inetpeer_addr * iaddr,struct in6_addr * in6)853abef286SDavid Ahern static inline void inetpeer_set_addr_v6(struct inetpeer_addr *iaddr,
863abef286SDavid Ahern struct in6_addr *in6)
873abef286SDavid Ahern {
885345c2e1SDavid Ahern iaddr->a6 = *in6;
893abef286SDavid Ahern iaddr->family = AF_INET6;
903abef286SDavid Ahern }
913abef286SDavid Ahern
inetpeer_get_addr_v6(struct inetpeer_addr * iaddr)923abef286SDavid Ahern static inline struct in6_addr *inetpeer_get_addr_v6(struct inetpeer_addr *iaddr)
933abef286SDavid Ahern {
945345c2e1SDavid Ahern return &iaddr->a6;
953abef286SDavid Ahern }
963abef286SDavid Ahern
971da177e4SLinus Torvalds /* can be called with or without local BH being disabled */
98c0efc887SDavid S. Miller struct inet_peer *inet_getpeer(struct inet_peer_base *base,
99*7a596a50SEric Dumazet const struct inetpeer_addr *daddr);
100b534ecf1SDavid S. Miller
inet_getpeer_v4(struct inet_peer_base * base,__be32 v4daddr,int vif)101c0efc887SDavid S. Miller static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base,
10254db0cc2SGao feng __be32 v4daddr,
103661cd8fcSEric Dumazet int vif)
104b534ecf1SDavid S. Miller {
1058790ca17SDavid S. Miller struct inetpeer_addr daddr;
106b534ecf1SDavid S. Miller
107192132b9SDavid Ahern daddr.a4.addr = v4daddr;
108192132b9SDavid Ahern daddr.a4.vif = vif;
109b534ecf1SDavid S. Miller daddr.family = AF_INET;
110*7a596a50SEric Dumazet return inet_getpeer(base, &daddr);
111b534ecf1SDavid S. Miller }
1121da177e4SLinus Torvalds
inet_getpeer_v6(struct inet_peer_base * base,const struct in6_addr * v6daddr)113c0efc887SDavid S. Miller static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base,
114661cd8fcSEric Dumazet const struct in6_addr *v6daddr)
115672f007dSDavid S. Miller {
1168790ca17SDavid S. Miller struct inetpeer_addr daddr;
117672f007dSDavid S. Miller
1185345c2e1SDavid Ahern daddr.a6 = *v6daddr;
119672f007dSDavid S. Miller daddr.family = AF_INET6;
120*7a596a50SEric Dumazet return inet_getpeer(base, &daddr);
121672f007dSDavid S. Miller }
122672f007dSDavid S. Miller
inetpeer_addr_cmp(const struct inetpeer_addr * a,const struct inetpeer_addr * b)123d39d14ffSDavid Ahern static inline int inetpeer_addr_cmp(const struct inetpeer_addr *a,
124d39d14ffSDavid Ahern const struct inetpeer_addr *b)
125d39d14ffSDavid Ahern {
1265345c2e1SDavid Ahern int i, n;
1275345c2e1SDavid Ahern
1285345c2e1SDavid Ahern if (a->family == AF_INET)
1295345c2e1SDavid Ahern n = sizeof(a->a4) / sizeof(u32);
1305345c2e1SDavid Ahern else
1315345c2e1SDavid Ahern n = sizeof(a->a6) / sizeof(u32);
132d39d14ffSDavid Ahern
133d39d14ffSDavid Ahern for (i = 0; i < n; i++) {
1345345c2e1SDavid Ahern if (a->key[i] == b->key[i])
135d39d14ffSDavid Ahern continue;
1365345c2e1SDavid Ahern if (a->key[i] < b->key[i])
137d39d14ffSDavid Ahern return -1;
138d39d14ffSDavid Ahern return 1;
139d39d14ffSDavid Ahern }
140d39d14ffSDavid Ahern
141d39d14ffSDavid Ahern return 0;
142d39d14ffSDavid Ahern }
143d39d14ffSDavid Ahern
1441da177e4SLinus Torvalds /* can be called from BH context or outside */
1451fd51155SJoe Perches void inet_putpeer(struct inet_peer *p);
1461fd51155SJoe Perches bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
1471da177e4SLinus Torvalds
1481fd51155SJoe Perches void inetpeer_invalidate_tree(struct inet_peer_base *);
1495faa5df1SSteffen Klassert
1501da177e4SLinus Torvalds #endif /* _NET_INETPEER_H */
151