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