1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * Based on include/net/ip6_fib.h
4 *
5 * Linux NewIP INET implementation
6 * Authors:
7 * Pedro Roque <roque@di.fc.ul.pt>
8 */
9 #ifndef _NET_NEWIP_FIB_H
10 #define _NET_NEWIP_FIB_H
11
12 #include <net/netlink.h>
13 #include <net/inetpeer.h>
14 #include <net/dst.h>
15 #include <linux/ipv6_route.h>
16 #include <linux/rtnetlink.h>
17 #include <linux/spinlock.h>
18 #include <linux/socket.h>
19 #include <linux/in.h>
20 #include <linux/kernel.h>
21
22 #include <linux/newip_route.h>
23 #include "nip.h"
24 #include "flow_nip.h"
25
26 #define NIN_ROUTE_HSIZE_SHIFT 4
27 #define NIN_ROUTE_HSIZE (1 << NIN_ROUTE_HSIZE_SHIFT)
28
29 struct nip_fib_config {
30 u32 fc_table;
31 u32 fc_metric;
32 int fc_ifindex;
33 u32 fc_flags;
34 u32 fc_protocol;
35 u32 fc_type; /* only 8 bits are used */
36
37 struct nip_addr fc_dst;
38 struct nip_addr fc_src;
39 struct nip_addr fc_gateway;
40
41 struct nl_info fc_nlinfo;
42 unsigned long fc_expires;
43 };
44
45 struct nip_fib_node {
46 struct hlist_node fib_hlist;
47 struct nip_rt_info *nip_route_info;
48 struct rcu_head rcu;
49 };
50
51 struct nip_fib_table;
52
53 struct nip_rt_info {
54 struct dst_entry dst;
55 struct dst_entry *from;
56 struct nip_fib_table *rt_table;
57 struct nip_fib_node __rcu *rt_node;
58 struct ninet_dev *rt_idev;
59 struct nip_rt_info *__percpu *rt_pcpu;
60
61 atomic_t rt_ref;
62
63 uint32_t rt_flags;
64 struct nip_addr gateway;
65 struct nip_addr rt_dst;
66 struct nip_addr rt_src;
67
68 u32 rt_metric;
69 u32 rt_pmtu;
70 u8 rt_protocol;
71 };
72
nip_dst_idev(struct dst_entry * dst)73 static inline struct ninet_dev *nip_dst_idev(struct dst_entry *dst)
74 {
75 return ((struct nip_rt_info *)dst)->rt_idev;
76 }
77
78 struct nip_fib_table {
79 u32 nip_tb_id;
80 spinlock_t nip_tb_lock;
81 struct hlist_head nip_tb_head[NIN_ROUTE_HSIZE];
82 unsigned int flags;
83 };
84
85 #define NIP_RT_TABLE_MAIN RT_TABLE_MAIN
86 #define NIP_RT_TABLE_LOCAL RT_TABLE_LOCAL
87
88 typedef struct nip_rt_info *(*nip_pol_lookup_t) (struct net *,
89 struct nip_fib_table *,
90 struct flow_nip *, int);
91
92 struct nip_fib_table *nip_fib_get_table(struct net *net, u32 id);
93
94 struct dst_entry *nip_fib_rule_lookup(struct net *net, struct flow_nip *fln,
95 int flags, int *tbl_type, nip_pol_lookup_t lookup);
96
97 #define NIP_RT_EXPIRES_FLAGS 12
nip_rt_set_expires(struct nip_rt_info * rt,unsigned long expires)98 static inline void nip_rt_set_expires(struct nip_rt_info *rt,
99 unsigned long expires)
100 {
101 rt->dst.expires = expires;
102
103 rt->rt_flags |= NIP_RT_EXPIRES_FLAGS;
104 }
105
nip_rt_clean_expires(struct nip_rt_info * rt)106 static inline void nip_rt_clean_expires(struct nip_rt_info *rt)
107 {
108 rt->rt_flags &= ~NIP_RT_EXPIRES_FLAGS;
109 rt->dst.expires = 0;
110 }
111
nip_rt_put(struct nip_rt_info * rt)112 static inline void nip_rt_put(struct nip_rt_info *rt)
113 {
114 BUILD_BUG_ON(offsetof(struct nip_rt_info, dst) != 0);
115 dst_release(&rt->dst);
116 }
117
118 void nip_rt_free_pcpu(struct nip_rt_info *non_pcpu_rt);
119
nip_rt_hold(struct nip_rt_info * rt)120 static inline void nip_rt_hold(struct nip_rt_info *rt)
121 {
122 atomic_inc(&rt->rt_ref);
123 }
124
nip_rt_release(struct nip_rt_info * rt)125 static inline void nip_rt_release(struct nip_rt_info *rt)
126 {
127 if (atomic_dec_and_test(&rt->rt_ref)) {
128 nip_rt_free_pcpu(rt);
129 dst_dev_put(&rt->dst);
130
131 dst_release(&rt->dst);
132 }
133 }
134
135 int nip_fib_init(void);
136
137 void nip_fib_gc_cleanup(void);
138
139 struct nip_fib_node *nip_fib_locate(struct hlist_head *nip_tb_head,
140 const struct nip_addr *daddr);
141
142 void nip_fib_clean_all(struct net *net,
143 int (*func)(struct nip_rt_info *, void *arg), void *arg);
144
145 int nip_fib_add(struct nip_fib_table *table, struct nip_rt_info *rt);
146
147 int nip_fib_del(struct nip_rt_info *rt_info, struct nl_info *info);
148
149 int nip_set_route_netlink(struct net *net, struct nip_rtmsg *rtmsg);
150
151 int nip_del_route_netlink(struct net *net, struct nip_rtmsg *rtmsg);
152
153 #endif /* _NET_NEWIP_FIB_H */
154