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
35struct secpolicy;
36struct secasvar;
37struct inpcb;
38
39struct ipsec_accel_out_tag {
40 struct m_tag tag;
41 uint16_t drv_spi;
42};
43
44struct 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
54extern void (*ipsec_accel_sa_newkey_p)(struct secasvar *sav);
55extern void (*ipsec_accel_sa_install_input_p)(struct secasvar *sav,
56 const union sockaddr_union *dst_address, int sproto, uint32_t spi);
57extern void (*ipsec_accel_forget_sav_p)(struct secasvar *sav);
58extern void (*ipsec_accel_spdadd_p)(struct secpolicy *sp, struct inpcb *inp);
59extern void (*ipsec_accel_spddel_p)(struct secpolicy *sp);
60extern 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);
63extern void (*ipsec_accel_sync_p)(void);
64extern bool (*ipsec_accel_is_accel_sav_p)(struct secasvar *sav);
65extern struct mbuf *(*ipsec_accel_key_setaccelif_p)(struct secasvar *sav);
66extern void (*ipsec_accel_on_ifdown_p)(struct ifnet *ifp);
67extern 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);
69extern 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);
71extern 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 */
79static inline void
80ipsec_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
89static inline void
90ipsec_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
99static inline void
100ipsec_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
109static inline void
110ipsec_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
119static inline int
120ipsec_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
133static inline void
134ipsec_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
143static inline bool
144ipsec_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
154static inline struct mbuf *
155ipsec_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
165static inline bool
166ipsec_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
188void ipsec_accel_forget_sav_impl(struct secasvar *sav);
189void ipsec_accel_spdadd_impl(struct secpolicy *sp, struct inpcb *inp);
190void ipsec_accel_spddel_impl(struct secpolicy *sp);
191
192#ifdef IPSEC_OFFLOAD
193int ipsec_accel_input(struct mbuf *m, int offset, int proto);
194bool 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);
197void ipsec_accel_forget_sav(struct secasvar *sav);
198struct 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
208struct ipsec_accel_in_tag *ipsec_accel_input_tag_lookup(const struct mbuf *);
209void ipsec_accel_on_ifdown(struct ifnet *ifp);
210void ipsec_accel_drv_sa_lifetime_update(struct secasvar *sav, if_t ifp,
211 u_int drv_spi, uint64_t octets, uint64_t allocs);
212int 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_ */