1
2#ifndef __NET_LWTUNNEL_H
3#define __NET_LWTUNNEL_H 1
4
5#include <linux/lwtunnel.h>
6#include <linux/netdevice.h>
7#include <linux/skbuff.h>
8#include <linux/types.h>
9#include <net/route.h>
10
11#include <linux/rh_kabi.h>
12
13#define LWTUNNEL_HASH_BITS 7
14#define LWTUNNEL_HASH_SIZE (1 << LWTUNNEL_HASH_BITS)
15
16
17#define LWTUNNEL_STATE_OUTPUT_REDIRECT BIT(0)
18#define LWTUNNEL_STATE_INPUT_REDIRECT BIT(1)
19#define LWTUNNEL_STATE_XMIT_REDIRECT BIT(2)
20
21enum {
22 LWTUNNEL_XMIT_DONE,
23 LWTUNNEL_XMIT_CONTINUE,
24};
25
26
27struct lwtunnel_state {
28 __u16 type;
29 __u16 flags;
30 __u16 headroom;
31 atomic_t refcnt;
32 int (*orig_output)(struct net *net, struct sock *sk, struct sk_buff *skb);
33 int (*orig_input)(struct sk_buff *);
34 struct rcu_head rcu;
35
36 RH_KABI_RESERVE(1)
37 RH_KABI_RESERVE(2)
38 RH_KABI_RESERVE(3)
39 RH_KABI_RESERVE(4)
40 __u8 data[0];
41};
42
43struct lwtunnel_encap_ops {
44 int (*build_state)(struct nlattr *encap,
45 unsigned int family, const void *cfg,
46 struct lwtunnel_state **ts,
47 struct netlink_ext_ack *extack);
48 void (*destroy_state)(struct lwtunnel_state *lws);
49 int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
50 int (*input)(struct sk_buff *skb);
51 int (*fill_encap)(struct sk_buff *skb,
52 struct lwtunnel_state *lwtstate);
53 int (*get_encap_size)(struct lwtunnel_state *lwtstate);
54 int (*cmp_encap)(struct lwtunnel_state *a, struct lwtunnel_state *b);
55 int (*xmit)(struct sk_buff *skb);
56
57 struct module *owner;
58};
59
60#ifdef CONFIG_LWTUNNEL
61void lwtstate_free(struct lwtunnel_state *lws);
62
63static inline struct lwtunnel_state *
64lwtstate_get(struct lwtunnel_state *lws)
65{
66 if (lws)
67 atomic_inc(&lws->refcnt);
68
69 return lws;
70}
71
72static inline void lwtstate_put(struct lwtunnel_state *lws)
73{
74 if (!lws)
75 return;
76
77 if (atomic_dec_and_test(&lws->refcnt))
78 lwtstate_free(lws);
79}
80
81static inline bool lwtunnel_output_redirect(struct lwtunnel_state *lwtstate)
82{
83 if (lwtstate && (lwtstate->flags & LWTUNNEL_STATE_OUTPUT_REDIRECT))
84 return true;
85
86 return false;
87}
88
89static inline bool lwtunnel_input_redirect(struct lwtunnel_state *lwtstate)
90{
91 if (lwtstate && (lwtstate->flags & LWTUNNEL_STATE_INPUT_REDIRECT))
92 return true;
93
94 return false;
95}
96
97static inline bool lwtunnel_xmit_redirect(struct lwtunnel_state *lwtstate)
98{
99 if (lwtstate && (lwtstate->flags & LWTUNNEL_STATE_XMIT_REDIRECT))
100 return true;
101
102 return false;
103}
104
105static inline unsigned int lwtunnel_headroom(struct lwtunnel_state *lwtstate,
106 unsigned int mtu)
107{
108 if ((lwtunnel_xmit_redirect(lwtstate) ||
109 lwtunnel_output_redirect(lwtstate)) && lwtstate->headroom < mtu)
110 return lwtstate->headroom;
111
112 return 0;
113}
114
115int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *op,
116 unsigned int num);
117int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
118 unsigned int num);
119int lwtunnel_valid_encap_type(u16 encap_type,
120 struct netlink_ext_ack *extack);
121int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len,
122 struct netlink_ext_ack *extack);
123int lwtunnel_build_state(u16 encap_type,
124 struct nlattr *encap,
125 unsigned int family, const void *cfg,
126 struct lwtunnel_state **lws,
127 struct netlink_ext_ack *extack);
128int lwtunnel_fill_encap(struct sk_buff *skb,
129 struct lwtunnel_state *lwtstate);
130int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate);
131struct lwtunnel_state *lwtunnel_state_alloc(int hdr_len);
132int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b);
133int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb);
134int lwtunnel_input(struct sk_buff *skb);
135int lwtunnel_xmit(struct sk_buff *skb);
136int bpf_lwt_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len,
137 bool ingress);
138
139static inline void lwtunnel_set_redirect(struct dst_entry *dst)
140{
141 if (lwtunnel_output_redirect(dst->lwtstate)) {
142 dst->lwtstate->orig_output = dst->output;
143 dst->output = lwtunnel_output;
144 }
145 if (lwtunnel_input_redirect(dst->lwtstate)) {
146 dst->lwtstate->orig_input = dst->input;
147 dst->input = lwtunnel_input;
148 }
149}
150#else
151
152static inline void lwtstate_free(struct lwtunnel_state *lws)
153{
154}
155
156static inline struct lwtunnel_state *
157lwtstate_get(struct lwtunnel_state *lws)
158{
159 return lws;
160}
161
162static inline void lwtstate_put(struct lwtunnel_state *lws)
163{
164}
165
166static inline bool lwtunnel_output_redirect(struct lwtunnel_state *lwtstate)
167{
168 return false;
169}
170
171static inline bool lwtunnel_input_redirect(struct lwtunnel_state *lwtstate)
172{
173 return false;
174}
175
176static inline bool lwtunnel_xmit_redirect(struct lwtunnel_state *lwtstate)
177{
178 return false;
179}
180
181static inline void lwtunnel_set_redirect(struct dst_entry *dst)
182{
183}
184
185static inline unsigned int lwtunnel_headroom(struct lwtunnel_state *lwtstate,
186 unsigned int mtu)
187{
188 return 0;
189}
190
191static inline int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *op,
192 unsigned int num)
193{
194 return -EOPNOTSUPP;
195
196}
197
198static inline int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
199 unsigned int num)
200{
201 return -EOPNOTSUPP;
202}
203
204static inline int lwtunnel_valid_encap_type(u16 encap_type,
205 struct netlink_ext_ack *extack)
206{
207 NL_SET_ERR_MSG(extack, "CONFIG_LWTUNNEL is not enabled in this kernel");
208 return -EOPNOTSUPP;
209}
210static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len,
211 struct netlink_ext_ack *extack)
212{
213
214
215
216 return 0;
217}
218
219static inline int lwtunnel_build_state(u16 encap_type,
220 struct nlattr *encap,
221 unsigned int family, const void *cfg,
222 struct lwtunnel_state **lws,
223 struct netlink_ext_ack *extack)
224{
225 return -EOPNOTSUPP;
226}
227
228static inline int lwtunnel_fill_encap(struct sk_buff *skb,
229 struct lwtunnel_state *lwtstate)
230{
231 return 0;
232}
233
234static inline int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate)
235{
236 return 0;
237}
238
239static inline struct lwtunnel_state *lwtunnel_state_alloc(int hdr_len)
240{
241 return NULL;
242}
243
244static inline int lwtunnel_cmp_encap(struct lwtunnel_state *a,
245 struct lwtunnel_state *b)
246{
247 return 0;
248}
249
250static inline int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb)
251{
252 return -EOPNOTSUPP;
253}
254
255static inline int lwtunnel_input(struct sk_buff *skb)
256{
257 return -EOPNOTSUPP;
258}
259
260static inline int lwtunnel_xmit(struct sk_buff *skb)
261{
262 return -EOPNOTSUPP;
263}
264
265#endif
266
267#define MODULE_ALIAS_RTNL_LWT(encap_type) MODULE_ALIAS("rtnl-lwt-" __stringify(encap_type))
268
269#endif
270