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
34 struct secpolicy;
35 struct secasvar;
36 struct inpcb;
37
38 struct ipsec_accel_out_tag {
39 struct m_tag tag;
40 uint16_t drv_spi;
41 };
42
43 struct ipsec_accel_in_tag {
44 struct m_tag tag;
45 uint16_t drv_spi;
46 };
47
48 #define IPSEC_ACCEL_DRV_SPI_BYPASS 2
49 #define IPSEC_ACCEL_DRV_SPI_MIN 3
50 #define IPSEC_ACCEL_DRV_SPI_MAX 0xffff
51
52 extern void (*ipsec_accel_sa_newkey_p)(struct secasvar *sav);
53 extern void (*ipsec_accel_sa_install_input_p)(struct secasvar *sav,
54 const union sockaddr_union *dst_address, int sproto, uint32_t spi);
55 extern void (*ipsec_accel_forget_sav_p)(struct secasvar *sav);
56 extern void (*ipsec_accel_spdadd_p)(struct secpolicy *sp, struct inpcb *inp);
57 extern void (*ipsec_accel_spddel_p)(struct secpolicy *sp);
58 extern int (*ipsec_accel_sa_lifetime_op_p)(struct secasvar *sav,
59 struct seclifetime *lft_c, if_t ifp, enum IF_SA_CNT_WHICH op,
60 struct rm_priotracker *sahtree_trackerp);
61 extern void (*ipsec_accel_sync_p)(void);
62 extern bool (*ipsec_accel_is_accel_sav_p)(struct secasvar *sav);
63 extern struct mbuf *(*ipsec_accel_key_setaccelif_p)(struct secasvar *sav);
64 extern void (*ipsec_accel_on_ifdown_p)(struct ifnet *ifp);
65 extern void (*ipsec_accel_drv_sa_lifetime_update_p)(struct secasvar *sav,
66 if_t ifp, u_int drv_spi, uint64_t octets, uint64_t allocs);
67 extern int (*ipsec_accel_drv_sa_lifetime_fetch_p)(struct secasvar *sav,
68 if_t ifp, u_int drv_spi, uint64_t *octets, uint64_t *allocs);
69
70 #ifdef IPSEC_OFFLOAD
71 /*
72 * Have to use ipsec_accel_sa_install_input_p indirection because
73 * key.c is unconditionally included into the static kernel.
74 */
75 static inline void
ipsec_accel_sa_newkey(struct secasvar * sav)76 ipsec_accel_sa_newkey(struct secasvar *sav)
77 {
78 void (*p)(struct secasvar *sav);
79
80 p = atomic_load_ptr(&ipsec_accel_sa_newkey_p);
81 if (p != NULL)
82 p(sav);
83 }
84
85 static inline void
ipsec_accel_forget_sav(struct secasvar * sav)86 ipsec_accel_forget_sav(struct secasvar *sav)
87 {
88 void (*p)(struct secasvar *sav);
89
90 p = atomic_load_ptr(&ipsec_accel_forget_sav_p);
91 if (p != NULL)
92 p(sav);
93 }
94
95 static inline void
ipsec_accel_spdadd(struct secpolicy * sp,struct inpcb * inp)96 ipsec_accel_spdadd(struct secpolicy *sp, struct inpcb *inp)
97 {
98 void (*p)(struct secpolicy *sp, struct inpcb *inp);
99
100 p = atomic_load_ptr(&ipsec_accel_spdadd_p);
101 if (p != NULL)
102 p(sp, inp);
103 }
104
105 static inline void
ipsec_accel_spddel(struct secpolicy * sp)106 ipsec_accel_spddel(struct secpolicy *sp)
107 {
108 void (*p)(struct secpolicy *sp);
109
110 p = atomic_load_ptr(&ipsec_accel_spddel_p);
111 if (p != NULL)
112 p(sp);
113 }
114
115 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)116 ipsec_accel_sa_lifetime_op(struct secasvar *sav,
117 struct seclifetime *lft_c, if_t ifp, enum IF_SA_CNT_WHICH op,
118 struct rm_priotracker *sahtree_trackerp)
119 {
120 int (*p)(struct secasvar *sav, struct seclifetime *lft_c, if_t ifp,
121 enum IF_SA_CNT_WHICH op, struct rm_priotracker *sahtree_trackerp);
122
123 p = atomic_load_ptr(&ipsec_accel_sa_lifetime_op_p);
124 if (p != NULL)
125 return (p(sav, lft_c, ifp, op, sahtree_trackerp));
126 return (ENOTSUP);
127 }
128
129 static inline void
ipsec_accel_sync(void)130 ipsec_accel_sync(void)
131 {
132 void (*p)(void);
133
134 p = atomic_load_ptr(&ipsec_accel_sync_p);
135 if (p != NULL)
136 p();
137 }
138
139 static inline bool
ipsec_accel_is_accel_sav(struct secasvar * sav)140 ipsec_accel_is_accel_sav(struct secasvar *sav)
141 {
142 bool (*p)(struct secasvar *sav);
143
144 p = atomic_load_ptr(&ipsec_accel_is_accel_sav_p);
145 if (p != NULL)
146 return (p(sav));
147 return (false);
148 }
149
150 static inline struct mbuf *
ipsec_accel_key_setaccelif(struct secasvar * sav)151 ipsec_accel_key_setaccelif(struct secasvar *sav)
152 {
153 struct mbuf *(*p)(struct secasvar *sav);
154
155 p = atomic_load_ptr(&ipsec_accel_key_setaccelif_p);
156 if (p != NULL)
157 return (p(sav));
158 return (NULL);
159 }
160
161
162 #else
163 #define ipsec_accel_sa_newkey(a)
164 #define ipsec_accel_forget_sav(a)
165 #define ipsec_accel_spdadd(a, b)
166 #define ipsec_accel_spddel(a)
167 #define ipsec_accel_sa_lifetime_op(a, b, c, d, e)
168 #define ipsec_accel_sync()
169 #define ipsec_accel_is_accel_sav(a)
170 #define ipsec_accel_key_setaccelif(a)
171 #endif
172
173 void ipsec_accel_forget_sav_impl(struct secasvar *sav);
174 void ipsec_accel_spdadd_impl(struct secpolicy *sp, struct inpcb *inp);
175 void ipsec_accel_spddel_impl(struct secpolicy *sp);
176
177 #ifdef IPSEC_OFFLOAD
178 int ipsec_accel_input(struct mbuf *m, int offset, int proto);
179 bool ipsec_accel_output(struct ifnet *ifp, struct mbuf *m,
180 struct inpcb *inp, struct secpolicy *sp, struct secasvar *sav, int af,
181 int mtu, int *hwassist);
182 void ipsec_accel_forget_sav(struct secasvar *sav);
183 #else
184 #define ipsec_accel_input(a, b, c) (ENXIO)
185 #define ipsec_accel_output(a, b, c, d, e, f, g, h) ({ \
186 *h = 0; \
187 false; \
188 })
189 #define ipsec_accel_forget_sav(a)
190 #endif
191
192 struct ipsec_accel_in_tag *ipsec_accel_input_tag_lookup(const struct mbuf *);
193 void ipsec_accel_on_ifdown(struct ifnet *ifp);
194 void ipsec_accel_drv_sa_lifetime_update(struct secasvar *sav, if_t ifp,
195 u_int drv_spi, uint64_t octets, uint64_t allocs);
196 int ipsec_accel_drv_sa_lifetime_fetch(struct secasvar *sav,
197 if_t ifp, u_int drv_spi, uint64_t *octets, uint64_t *allocs);
198
199 #endif /* _KERNEL */
200
201 #endif /* _NETIPSEC_IPSEC_OFFLOAD_H_ */
202