xref: /freebsd/sys/netipsec/ipsec_offload.h (revision 39598c2a9f5d074b1365e5ba97441fb5b4f8476b)
1 /*-
2  * Copyright (c) 2021,2022 NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #ifndef _NETIPSEC_IPSEC_OFFLOAD_H_
27 #define _NETIPSEC_IPSEC_OFFLOAD_H_
28 
29 #ifdef _KERNEL
30 #include <sys/errno.h>
31 #include <net/if.h>
32 #include <net/if_var.h>
33 #include <netipsec/xform.h>
34 
35 struct secpolicy;
36 struct secasvar;
37 struct inpcb;
38 
39 struct ipsec_accel_out_tag {
40 	struct m_tag tag;
41 	uint16_t drv_spi;
42 };
43 
44 struct ipsec_accel_in_tag {
45 	struct m_tag tag;
46 	struct xform_history xh; /* Must be first to mimic IPSEC_IN_DONE */
47 	uint16_t drv_spi;
48 };
49 
50 #define	IPSEC_ACCEL_DRV_SPI_BYPASS	2
51 #define	IPSEC_ACCEL_DRV_SPI_MIN		3
52 #define	IPSEC_ACCEL_DRV_SPI_MAX		0xffff
53 
54 extern void (*ipsec_accel_sa_newkey_p)(struct secasvar *sav);
55 extern void (*ipsec_accel_sa_install_input_p)(struct secasvar *sav,
56     const union sockaddr_union *dst_address, int sproto, uint32_t spi);
57 extern void (*ipsec_accel_forget_sav_p)(struct secasvar *sav);
58 extern void (*ipsec_accel_spdadd_p)(struct secpolicy *sp, struct inpcb *inp);
59 extern void (*ipsec_accel_spddel_p)(struct secpolicy *sp);
60 extern int (*ipsec_accel_sa_lifetime_op_p)(struct secasvar *sav,
61     struct seclifetime *lft_c, if_t ifp, enum IF_SA_CNT_WHICH op,
62     struct rm_priotracker *sahtree_trackerp);
63 extern void (*ipsec_accel_sync_p)(void);
64 extern bool (*ipsec_accel_is_accel_sav_p)(struct secasvar *sav);
65 extern struct mbuf *(*ipsec_accel_key_setaccelif_p)(struct secasvar *sav);
66 extern void (*ipsec_accel_on_ifdown_p)(struct ifnet *ifp);
67 extern void (*ipsec_accel_drv_sa_lifetime_update_p)(struct secasvar *sav,
68     if_t ifp, u_int drv_spi, uint64_t octets, uint64_t allocs);
69 extern int (*ipsec_accel_drv_sa_lifetime_fetch_p)(struct secasvar *sav,
70     if_t ifp, u_int drv_spi, uint64_t *octets, uint64_t *allocs);
71 extern bool (*ipsec_accel_fill_xh_p)(if_t ifp, uint32_t drv_spi,
72     struct xform_history *xh);
73 
74 #ifdef IPSEC_OFFLOAD
75 /*
76  * Have to use ipsec_accel_sa_install_input_p indirection because
77  * key.c is unconditionally included into the static kernel.
78  */
79 static inline void
ipsec_accel_sa_newkey(struct secasvar * sav)80 ipsec_accel_sa_newkey(struct secasvar *sav)
81 {
82 	void (*p)(struct secasvar *sav);
83 
84 	p = atomic_load_ptr(&ipsec_accel_sa_newkey_p);
85 	if (p != NULL)
86 		p(sav);
87 }
88 
89 static inline void
ipsec_accel_forget_sav(struct secasvar * sav)90 ipsec_accel_forget_sav(struct secasvar *sav)
91 {
92 	void (*p)(struct secasvar *sav);
93 
94 	p = atomic_load_ptr(&ipsec_accel_forget_sav_p);
95 	if (p != NULL)
96 		p(sav);
97 }
98 
99 static inline void
ipsec_accel_spdadd(struct secpolicy * sp,struct inpcb * inp)100 ipsec_accel_spdadd(struct secpolicy *sp, struct inpcb *inp)
101 {
102 	void (*p)(struct secpolicy *sp, struct inpcb *inp);
103 
104 	p = atomic_load_ptr(&ipsec_accel_spdadd_p);
105 	if (p != NULL)
106 		p(sp, inp);
107 }
108 
109 static inline void
ipsec_accel_spddel(struct secpolicy * sp)110 ipsec_accel_spddel(struct secpolicy *sp)
111 {
112 	void (*p)(struct secpolicy *sp);
113 
114 	p = atomic_load_ptr(&ipsec_accel_spddel_p);
115 	if (p != NULL)
116 		p(sp);
117 }
118 
119 static inline int
ipsec_accel_sa_lifetime_op(struct secasvar * sav,struct seclifetime * lft_c,if_t ifp,enum IF_SA_CNT_WHICH op,struct rm_priotracker * sahtree_trackerp)120 ipsec_accel_sa_lifetime_op(struct secasvar *sav,
121     struct seclifetime *lft_c, if_t ifp, enum IF_SA_CNT_WHICH op,
122     struct rm_priotracker *sahtree_trackerp)
123 {
124 	int (*p)(struct secasvar *sav, struct seclifetime *lft_c, if_t ifp,
125 	    enum IF_SA_CNT_WHICH op, struct rm_priotracker *sahtree_trackerp);
126 
127 	p = atomic_load_ptr(&ipsec_accel_sa_lifetime_op_p);
128 	if (p != NULL)
129 		return (p(sav, lft_c, ifp, op, sahtree_trackerp));
130 	return (ENOTSUP);
131 }
132 
133 static inline void
ipsec_accel_sync(void)134 ipsec_accel_sync(void)
135 {
136 	void (*p)(void);
137 
138 	p = atomic_load_ptr(&ipsec_accel_sync_p);
139 	if (p != NULL)
140 		p();
141 }
142 
143 static inline bool
ipsec_accel_is_accel_sav(struct secasvar * sav)144 ipsec_accel_is_accel_sav(struct secasvar *sav)
145 {
146 	bool (*p)(struct secasvar *sav);
147 
148 	p = atomic_load_ptr(&ipsec_accel_is_accel_sav_p);
149 	if (p != NULL)
150 		return (p(sav));
151 	return (false);
152 }
153 
154 static inline struct mbuf *
ipsec_accel_key_setaccelif(struct secasvar * sav)155 ipsec_accel_key_setaccelif(struct secasvar *sav)
156 {
157 	struct mbuf *(*p)(struct secasvar *sav);
158 
159 	p = atomic_load_ptr(&ipsec_accel_key_setaccelif_p);
160 	if (p != NULL)
161 		return (p(sav));
162 	return (NULL);
163 }
164 
165 static inline bool
ipsec_accel_fill_xh(if_t ifp,uint32_t drv_spi,struct xform_history * xh)166 ipsec_accel_fill_xh(if_t ifp, uint32_t drv_spi, struct xform_history *xh)
167 {
168 	bool (*p)(if_t ifp, uint32_t drv_spi, struct xform_history *xh);
169 
170 	p = atomic_load_ptr(&ipsec_accel_fill_xh_p);
171 	if (p != NULL)
172 		return (p(ifp, drv_spi, xh));
173 	return (false);
174 }
175 
176 #else
177 #define	ipsec_accel_sa_newkey(a)
178 #define	ipsec_accel_forget_sav(a)
179 #define	ipsec_accel_spdadd(a, b)
180 #define	ipsec_accel_spddel(a)
181 #define	ipsec_accel_sa_lifetime_op(a, b, c, d, e)
182 #define	ipsec_accel_sync()
183 #define	ipsec_accel_is_accel_sav(a)
184 #define	ipsec_accel_key_setaccelif(a)
185 #define	ipsec_accel_fill_xh(a, b, c)	(false)
186 #endif
187 
188 void ipsec_accel_forget_sav_impl(struct secasvar *sav);
189 void ipsec_accel_spdadd_impl(struct secpolicy *sp, struct inpcb *inp);
190 void ipsec_accel_spddel_impl(struct secpolicy *sp);
191 
192 #ifdef IPSEC_OFFLOAD
193 int ipsec_accel_input(struct mbuf *m, int offset, int proto);
194 bool ipsec_accel_output(struct ifnet *ifp, struct mbuf *m,
195     struct inpcb *inp, struct secpolicy *sp, struct secasvar *sav, int af,
196     int mtu, int *hwassist);
197 void ipsec_accel_forget_sav(struct secasvar *sav);
198 struct xform_history;
199 #else
200 #define	ipsec_accel_input(a, b, c) (ENXIO)
201 #define	ipsec_accel_output(a, b, c, d, e, f, g, h) ({	\
202 	*h = 0;						\
203 	false;						\
204 })
205 #define	ipsec_accel_forget_sav(a)
206 #endif
207 
208 struct ipsec_accel_in_tag *ipsec_accel_input_tag_lookup(const struct mbuf *);
209 void ipsec_accel_on_ifdown(struct ifnet *ifp);
210 void ipsec_accel_drv_sa_lifetime_update(struct secasvar *sav, if_t ifp,
211     u_int drv_spi, uint64_t octets, uint64_t allocs);
212 int ipsec_accel_drv_sa_lifetime_fetch(struct secasvar *sav,
213     if_t ifp, u_int drv_spi, uint64_t *octets, uint64_t *allocs);
214 
215 #endif	/* _KERNEL */
216 
217 #endif	/* _NETIPSEC_IPSEC_OFFLOAD_H_ */
218