1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2018 Joyent, Inc.
14 */
15
16 #ifndef _LIBVARPD_PROVIDER_H
17 #define _LIBVARPD_PROVIDER_H
18
19 /*
20 * varpd provider interface for lookup modules
21 *
22 * This header file defines all the structures and functions that a given lookup
23 * module needs to implement and perform its purpose. At this time, all of these
24 * interfaces are considered private to illumos and therefore are subject to
25 * change. At some point we will move to more broadly stabilize these interfaces
26 * and commit to them. Until such time, expect breakage for out of gate
27 * consumers.
28 *
29 * A plugin is a dynamic shared object that is placed inside of varpd's default
30 * module.
31 *
32 * The shared object must define an initializer, such as with #pragma init. This
33 * function will be run with the module is dlopened by libvarpd. In that init
34 * function, the function must allocate a varpd_plugin_register by calling
35 * libvarpd_plugin_alloc() and specifying VARPD_CURRENT_VERSION. If that
36 * succeeds, then it should proceed to fill out the registration and then call,
37 * libvarpd_plugin_register() with it. Regardless of whether it succeeds or
38 * fails, it should call libvarpd_plugin_free(). In the case of failure, there
39 * is not much that the module should do, other than log some message to the
40 * standard bunyan logger that exists.
41 *
42 * Once libvarpd_plugin_register() returns, the module should assume that any
43 * of the operations it defined in the operation vector may be called and
44 * therefore it is recommended that any other required initialization should be
45 * performed at that time.
46 *
47 * At this time, once a plugin is loaded, it will not be unloaded. Therefore,
48 * there is no corresponding requirement to unregister, though that may come in
49 * a future version.
50 *
51 * -----------------------------
52 * Plugin Types and Destinations
53 * -----------------------------
54 *
55 * There are two different kinds of plugins in this world, there are point to
56 * point plugins and there are dynamic plugins. The key difference is in how
57 * packets are routed through the system. In a point to point plugin, a single
58 * destination is used when the instance is started. In dynamic plugins,
59 * destinations are looked up as they are required and an instance of a plugin
60 * is required to provide that.
61 *
62 * These point to point plugins define a type of OVERLAY_TARGET_POINT and the
63 * dynamic plugins instead define a type of OVERLAY_TARGET_DYNAMIC.
64 *
65 * Encapsulation plugins have multiple types of destinations. They may require
66 * an Ethernet address (OVERLAY_PLUGIN_D_ETHERNET), IP address
67 * (OVERLAY_PLUGIN_D_IP), and a port (OVERLAY_PLUGIN_D_PORT). For example,
68 * consider vxlan, it requires an IP and a port; while a hypothetical nvgre,
69 * would only require an IP.
70 *
71 * A plugin is allowed to describe which of these fields that it supports and
72 * given which encapsulation plugin it is paired with, it can support a varying
73 * degree of properties. For example, consider the example of the direct plugin.
74 * It has a notion of a destination port and a destination IP. If it is paired
75 * with a plugin that only requires an IP, then it wouldn't need to show a
76 * property that's related to a destination port.
77 *
78 * ------------------
79 * Plugin Definitions
80 * ------------------
81 *
82 * A plugin is required to fill in both an operations vector and a series of
83 * additional metadata that it passed in to libvarpd_plugin_register(). The
84 * following lists all of the routines and their purposes. The full signatures
85 * are available in the body of the header file.
86 *
87 * varpd_plugin_create_f
88 *
89 * Create a new instance of a plugin. Each instance refers to a different
90 * overlay device and thus a different overlay identifier. Each instance
91 * has its own property space and is unique. This function gives the chance
92 * for the plugin to create and provide any private data that it will
93 * require.
94 *
95 * In addition, the plugin is given the type of destination that is
96 * required and it is its job to determine whether or not it supports it.
97 *
98 * varpd_plugin_destory_f
99 *
100 * This is the opposite of varpd_plugin_create_f. It is called to allow the
101 * plugin to reclaim any resources with the private argument that it passed
102 * out as part of the destroy function.
103 *
104 * varpd_plugin_start_f
105 *
106 * This routine is called to indicate that an instance should be started.
107 * This is a plugin's chance to verify that it has all of its required
108 * properties set and to take care of any action that needs to be handled
109 * to begin the plugin. After this point it will be legal to have the
110 * varpd_plugin_default_f, varpd_plugin_lookup_f, varpd_plugin_arp_f and
111 * varpd_plugin_dhcp_f endpoints called.
112 *
113 * varpd_plugin_stop_f
114 *
115 * This routine is called to indicate that an instance is stopping, it is
116 * the opposite of varpd_plugin_start_f. This is a chance to clean up
117 * resources that are a side effect of having started the instance.
118 *
119 * varpd_plugin_default_f
120 *
121 * This routine is defined by plugins of type OVERLAY_TARGET_POINT. It is
122 * used to answer the question of where should all traffic for this
123 * instance be destined. Plugins of type OVERLAY_TARGET_DYNAMIC should
124 * leave this entry set to NULL.
125 *
126 * On success, the default routine should return VARPD_LOOKUP_OK. On
127 * failure, it should return the macro VARPD_LOOKUP_DROP.
128 *
129 * varpd_plugin_lookup_f
130 *
131 * This routine must be defined by plugins of type OVERLAY_TARGET_DYNAMIC.
132 * It is used to lookup the destination for a given request. Each request
133 * comes in with its own MAC address this allows a plugin to direct it to
134 * any remote location.
135 *
136 * This is designed as an asynchronous API. Once a lookup is completed it
137 * should call libvarpd_plugin_query_reply() and pass as the second
138 * argument either VARPD_LOOKUP_OK to indicate that it went alright or it
139 * should reply VARPD_LOOKUP_DROP to indicate that the packet should be
140 * dropped.
141 *
142 * In addition, there are several utility routines that can take care of
143 * various kinds of traffic automatically. For example, if an ARP, NDP, or
144 * DHCP packet comes in, there are utilities such as
145 * libvarpd_plugin_proxy_arp(), libvarpd_plugin_proxy_ndp() and
146 * libvarpd_plugin_proxy_dhcp(), which allows the system to do the heavy
147 * lifting of validating the packet once it finds that it matches certain
148 * properties.
149 *
150 * varpd_plugin_arp_f
151 *
152 * This is an optional entry for plugins of type OVERLAY_TARGET_DYNAMIC.
153 * This is called after a plugin calls libvarpd_plugin_proxy_arp() and is
154 * used to ask the plugin to perform an ARP or NDP query. The type of query
155 * is passed in in the third argument, the only valid value for which will
156 * be VARPD_QTYPE_ETHERNET, to indicate we're doing an Ethernet lookup.
157 *
158 * The layer three IP address that is being looked up will be included in
159 * the struct sockaddr. The sockaddr(3SOCKET)'s sa_family will be set to
160 * indicate the type, eg. AF_INET or AF_INET6 and that will indicate the
161 * kind of sockaddr that will be used. For more information see
162 * sockaddr(3SOCKET). The implementation ensures that enough space for the
163 * link layer address will exist.
164 *
165 * This is an asynchronous lookup. Once the answer has been written, a
166 * plugin should call libvarpd_plugin_arp_reply and if it was successful,
167 * VARPD_LOOKUP_OK should be passed in and if it failed, VARPD_LOOKUP_DROP
168 * should be passed in instead.
169 *
170 * varpd_plugin_dhcp_f
171 *
172 * This is an optional entry for plugins of type OVERLAY_TARGET_DYNAMIC.
173 * This is called after a plugin calls the libvarpd_plugin_proxy_dhcp() and
174 * is used to ask the plugin to determine where is the DHCP server that
175 * this packet should actually be sent to. What is happening here is that
176 * rather than broadcast the initial DHCP request, we instead unicast it to
177 * a specified DHCP server that this operation vector indicates.
178 *
179 * The plugin is given a type, the same as the ARP plugin which indicates
180 * the kind of link layer address, the only valid type is
181 * VARPD_QTYPE_ETHERNET, other types should be rejected. Then, like the arp
182 * entry point, the dhcp entry point should determine the link layer
183 * address of the DHCP server and write that out in the appropriate memory
184 * and call libvarpd_plugin_dhcp_reply() when done. Similar to the arp
185 * entry point, it should use VARPD_LOOKUP_OK to indicate that it was
186 * filled in and VARPD_LOOKUP_DROP to indicate that it was not.
187 *
188 * varpd_plugin_nprops_f
189 *
190 * This is used by a plugin to indicate the number of properties that
191 * should exist for this instance. Recall from the section that Plugin
192 * types and Destinations, that the number of entries here may vary. As
193 * such, the plugin should return the number that is appropriate for the
194 * instance.
195 *
196 * This number will be used to obtain information about a property via the
197 * propinfo functions. However, the getprop and setprop interfaces will
198 * always use names to indicate the property it is getting and setting.
199 * This difference is structured this way to deal with property discovery
200 * and to make the getprop and setprop interfaces slightly easier for other
201 * parts of the broader varpd/dladm infrastructure.
202 *
203 * varpd_plugin_propinfo_f
204 *
205 * This interface is used to get information about a property, the property
206 * that information is being requested for is being passed in via the
207 * second argument. Here, callers should set properties such as the name,
208 * the protection, whether or not the property is required, set any default
209 * value, if it exist, and if relevant, set the valid range of values.
210 *
211 * varpd_plugin_getprop_f
212 *
213 * This is used to get the value of a property, if it is set. The passed in
214 * length indicates the length of the buffer that is used for updating
215 * properties. If it is not of sufficient size, the function should return
216 * an error and not update the buffer. Otherwise, it should update the size
217 * pointer with the valid size.
218 *
219 * varpd_plugin_setprop_f
220 *
221 * This is used to set the value of a property. An endpoint should validate
222 * that the property is valid before updating it. In addition, it should
223 * update its state as appropriate.
224 *
225 * varpd_plugin_save_f
226 *
227 * This is used to serialize the state of a given instance of a plugin such
228 * that if varpd crashes, it can be recovered. The plugin should write all
229 * state into the nvlist that it is passed in, it may use any keys and
230 * values that it wants. The only consumer of that nvlist will be the
231 * plugin itself when the restore endpoint is called.
232 *
233 * varpd_plugin_restore_f
234 *
235 * This is called by the server to restore an instance that used to exist,
236 * but was lost due to a crash. This is a combination of calling create and
237 * setting properties. The plugin should restore any private state that it
238 * can find recorded from the nvlist. The only items in the nvlist will be
239 * those that were written out during a previous call to
240 * varpd_plugin_save_f.
241 *
242 *
243 * Once all of these interfaces are implemented, the plugin should define the
244 * following members in the varpd_plugin_register_t.
245 *
246 * vpr_version
247 *
248 * This indicates the version of the plugin. Plugins should set this to the
249 * macro VARPD_CURRENT_VERSION.
250 *
251 * vpr_mode
252 *
253 * This indicates the mode of the plugin. The plugin's mode should be one
254 * of OVERLAY_TARGET_POINT and OVERLAY_TARGET_DYNAMIC. For more discussion
255 * of these types and the differences, see the section on Plugin Types and
256 * Destinations.
257 *
258 * vpr_name
259 *
260 * This is the name of the plugin. This is how users will refer to it in
261 * the context of running dladm(1M) commands. Note, this name must be
262 * unique across the different plugins, as it will cause others with the
263 * same name not to be registered.
264 *
265 * vpr_ops
266 *
267 * This is the operations vector as described above. Importantly, the
268 * member vpo_callbacks must be set to zero, this is being used for future
269 * expansion of the structure.
270 *
271 *
272 * --------------------------------------------------
273 * Downcalls, Upcalls, and Synchronization Guarantees
274 * --------------------------------------------------
275 *
276 * Every instance of a plugin is independent. Calls into a plugin may be made
277 * for different instances in parallel. Any necessary locking is left to the
278 * plugin module. Within an instance, various calls may come in parallel.
279 *
280 * The primary guarantees are that none of the varpd_plugin_save_f,
281 * varpd_plugin_lookup_f, varpd_default_f, varpd_plugin_arp_f, and
282 * varpd_plugin_dhcp_f will be called until after a call to varpd_plugin_start_f
283 * has been called. Similarly, they will not be called after a call to
284 * vardp_plugin_stop_f.
285 *
286 * The functions documented in this header may be called back into from any
287 * context, including from the operation vectors.
288 */
289
290 #include <bunyan.h>
291 #include <libvarpd.h>
292 #include <libnvpair.h>
293 #include <sys/socket.h>
294 #include <sys/overlay_target.h>
295
296 #ifdef __cplusplus
297 extern "C" {
298 #endif
299
300 #define VARPD_VERSION_ONE 1
301 #define VARPD_CURRENT_VERSION VARPD_VERSION_ONE
302
303 typedef struct __varpd_provier_handle varpd_provider_handle_t;
304 typedef struct __varpd_query_handle varpd_query_handle_t;
305 typedef struct __varpd_arp_handle varpd_arp_handle_t;
306 typedef struct __varpd_dhcp_handle varpd_dhcp_handle_t;
307
308 typedef int (*varpd_plugin_create_f)(varpd_provider_handle_t *, void **,
309 overlay_plugin_dest_t);
310 typedef int (*varpd_plugin_start_f)(void *);
311 typedef void (*varpd_plugin_stop_f)(void *);
312 typedef void (*varpd_plugin_destroy_f)(void *);
313
314 #define VARPD_LOOKUP_OK (0)
315 #define VARPD_LOOKUP_DROP (-1)
316 typedef int (*varpd_plugin_default_f)(void *, overlay_target_point_t *);
317 typedef void (*varpd_plugin_lookup_f)(void *, varpd_query_handle_t *,
318 const overlay_targ_lookup_t *, overlay_target_point_t *,
319 overlay_target_route_t *, overlay_target_mac_t *);
320
321 #define VARPD_QTYPE_ETHERNET 0x0
322 typedef void (*varpd_plugin_arp_f)(void *, varpd_arp_handle_t *, int,
323 const struct sockaddr *, uint16_t, uint8_t *);
324 typedef void (*varpd_plugin_dhcp_f)(void *, varpd_dhcp_handle_t *, int,
325 const overlay_targ_lookup_t *, uint8_t *);
326
327 typedef int (*varpd_plugin_nprops_f)(void *, uint_t *);
328 typedef int (*varpd_plugin_propinfo_f)(void *, const uint_t,
329 varpd_prop_handle_t *);
330 typedef int (*varpd_plugin_getprop_f)(void *, const char *, void *, uint32_t *);
331 typedef int (*varpd_plugin_setprop_f)(void *, const char *, const void *,
332 const uint32_t);
333
334 typedef int (*varpd_plugin_save_f)(void *, nvlist_t *);
335 typedef int (*varpd_plugin_restore_f)(nvlist_t *, varpd_provider_handle_t *,
336 overlay_plugin_dest_t, void **);
337
338 typedef struct varpd_plugin_ops {
339 uint_t vpo_callbacks;
340 varpd_plugin_create_f vpo_create;
341 varpd_plugin_start_f vpo_start;
342 varpd_plugin_stop_f vpo_stop;
343 varpd_plugin_destroy_f vpo_destroy;
344 varpd_plugin_default_f vpo_default;
345 varpd_plugin_lookup_f vpo_lookup;
346 varpd_plugin_nprops_f vpo_nprops;
347 varpd_plugin_propinfo_f vpo_propinfo;
348 varpd_plugin_getprop_f vpo_getprop;
349 varpd_plugin_setprop_f vpo_setprop;
350 varpd_plugin_save_f vpo_save;
351 varpd_plugin_restore_f vpo_restore;
352 varpd_plugin_arp_f vpo_arp;
353 varpd_plugin_dhcp_f vpo_dhcp;
354 } varpd_plugin_ops_t;
355
356 typedef struct varpd_plugin_register {
357 uint_t vpr_version;
358 uint_t vpr_mode;
359 const char *vpr_name;
360 const varpd_plugin_ops_t *vpr_ops;
361 } varpd_plugin_register_t;
362
363 extern varpd_plugin_register_t *libvarpd_plugin_alloc(uint_t, int *);
364 extern void libvarpd_plugin_free(varpd_plugin_register_t *);
365 extern int libvarpd_plugin_register(varpd_plugin_register_t *);
366
367 /*
368 * Blowing up and logging
369 */
370 extern void libvarpd_panic(const char *, ...) __NORETURN;
371 extern const bunyan_logger_t *libvarpd_plugin_bunyan(varpd_provider_handle_t *);
372
373 /*
374 * Misc. Information APIs
375 */
376 extern uint64_t libvarpd_plugin_vnetid(varpd_provider_handle_t *);
377 extern uint32_t libvarpd_plugin_dcid(varpd_provider_handle_t *);
378
379 /*
380 * Lookup Replying query and proxying
381 */
382 extern void libvarpd_plugin_query_reply(varpd_query_handle_t *, int);
383
384 extern void libvarpd_plugin_proxy_arp(varpd_provider_handle_t *,
385 varpd_query_handle_t *, const overlay_targ_lookup_t *);
386 extern void libvarpd_plugin_proxy_ndp(varpd_provider_handle_t *,
387 varpd_query_handle_t *, const overlay_targ_lookup_t *);
388 extern void libvarpd_plugin_arp_reply(varpd_arp_handle_t *, int);
389
390 extern void libvarpd_plugin_proxy_dhcp(varpd_provider_handle_t *,
391 varpd_query_handle_t *, const overlay_targ_lookup_t *);
392 extern void libvarpd_plugin_dhcp_reply(varpd_dhcp_handle_t *, int);
393
394
395 /*
396 * Property information callbacks
397 */
398 extern void libvarpd_prop_set_name(varpd_prop_handle_t *, const char *);
399 extern void libvarpd_prop_set_prot(varpd_prop_handle_t *, overlay_prop_prot_t);
400 extern void libvarpd_prop_set_type(varpd_prop_handle_t *, overlay_prop_type_t);
401 extern int libvarpd_prop_set_default(varpd_prop_handle_t *, void *, ssize_t);
402 extern void libvarpd_prop_set_nodefault(varpd_prop_handle_t *);
403 extern void libvarpd_prop_set_range_uint32(varpd_prop_handle_t *, uint32_t,
404 uint32_t);
405 extern void libvarpd_prop_set_range_str(varpd_prop_handle_t *, const char *);
406
407 /*
408 * Various injecting and invalidation routines
409 */
410 extern void libvarpd_inject_varp(varpd_provider_handle_t *, const uint8_t *,
411 const overlay_target_point_t *);
412 extern void libvarpd_inject_arp(varpd_provider_handle_t *, const uint16_t,
413 const uint8_t *, const struct in_addr *, const uint8_t *);
414 extern void libvarpd_fma_degrade(varpd_provider_handle_t *, const char *);
415 extern void libvarpd_fma_restore(varpd_provider_handle_t *);
416 extern void libvarpd_route_flush(varpd_provider_handle_t *, uint8_t *,
417 uint8_t *, uint8_t, uint8_t, uint16_t vlan_id);
418
419 #ifdef __cplusplus
420 }
421 #endif
422
423 #endif /* _LIBVARPD_PROVIDER_H */