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 2015 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
40  * stderr.
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_destroy_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(8) 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  * varpd_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 <libvarpd.h>
291 #include <libnvpair.h>
292 #include <sys/socket.h>
293 #include <sys/overlay_target.h>
294 
295 #ifdef __cplusplus
296 extern "C" {
297 #endif
298 
299 #define	VARPD_VERSION_ONE	1
300 #define	VARPD_CURRENT_VERSION	VARPD_VERSION_ONE
301 
302 typedef struct __varpd_provier_handle varpd_provider_handle_t;
303 typedef struct __varpd_query_handle varpd_query_handle_t;
304 typedef struct __varpd_arp_handle varpd_arp_handle_t;
305 typedef struct __varpd_dhcp_handle varpd_dhcp_handle_t;
306 
307 typedef int (*varpd_plugin_create_f)(varpd_provider_handle_t *, void **,
308     overlay_plugin_dest_t);
309 typedef int (*varpd_plugin_start_f)(void *);
310 typedef void (*varpd_plugin_stop_f)(void *);
311 typedef void (*varpd_plugin_destroy_f)(void *);
312 
313 #define	VARPD_LOOKUP_OK		(0)
314 #define	VARPD_LOOKUP_DROP	(-1)
315 typedef int (*varpd_plugin_default_f)(void *, overlay_target_point_t *);
316 typedef void (*varpd_plugin_lookup_f)(void *, varpd_query_handle_t *,
317     const overlay_targ_lookup_t *, overlay_target_point_t *);
318 
319 #define	VARPD_QTYPE_ETHERNET	0x0
320 typedef void (*varpd_plugin_arp_f)(void *, varpd_arp_handle_t *, int,
321     const struct sockaddr *, uint8_t *);
322 typedef void (*varpd_plugin_dhcp_f)(void *, varpd_dhcp_handle_t *, int,
323     const overlay_targ_lookup_t *, uint8_t *);
324 
325 typedef int (*varpd_plugin_nprops_f)(void *, uint_t *);
326 typedef int (*varpd_plugin_propinfo_f)(void *, const uint_t,
327     varpd_prop_handle_t *);
328 typedef int (*varpd_plugin_getprop_f)(void *, const char *, void *, uint32_t *);
329 typedef int (*varpd_plugin_setprop_f)(void *, const char *, const void *,
330     const uint32_t);
331 
332 typedef int (*varpd_plugin_save_f)(void *, nvlist_t *);
333 typedef int (*varpd_plugin_restore_f)(nvlist_t *, varpd_provider_handle_t *,
334     overlay_plugin_dest_t, void **);
335 
336 typedef struct varpd_plugin_ops {
337 	uint_t			vpo_callbacks;
338 	varpd_plugin_create_f	vpo_create;
339 	varpd_plugin_start_f	vpo_start;
340 	varpd_plugin_stop_f	vpo_stop;
341 	varpd_plugin_destroy_f	vpo_destroy;
342 	varpd_plugin_default_f	vpo_default;
343 	varpd_plugin_lookup_f	vpo_lookup;
344 	varpd_plugin_nprops_f	vpo_nprops;
345 	varpd_plugin_propinfo_f	vpo_propinfo;
346 	varpd_plugin_getprop_f	vpo_getprop;
347 	varpd_plugin_setprop_f	vpo_setprop;
348 	varpd_plugin_save_f	vpo_save;
349 	varpd_plugin_restore_f	vpo_restore;
350 	varpd_plugin_arp_f	vpo_arp;
351 	varpd_plugin_dhcp_f	vpo_dhcp;
352 } varpd_plugin_ops_t;
353 
354 typedef struct varpd_plugin_register {
355 	uint_t		vpr_version;
356 	uint_t		vpr_mode;
357 	const char	*vpr_name;
358 	const varpd_plugin_ops_t *vpr_ops;
359 } varpd_plugin_register_t;
360 
361 extern varpd_plugin_register_t *libvarpd_plugin_alloc(uint_t, int *);
362 extern void libvarpd_plugin_free(varpd_plugin_register_t *);
363 extern int libvarpd_plugin_register(varpd_plugin_register_t *);
364 
365 /*
366  * Blowing up and logging
367  */
368 extern void libvarpd_panic(const char *, ...) __NORETURN;
369 
370 /*
371  * Misc. Information APIs
372  */
373 extern uint64_t libvarpd_plugin_vnetid(varpd_provider_handle_t *);
374 
375 /*
376  * Lookup Replying query and proxying
377  */
378 extern void libvarpd_plugin_query_reply(varpd_query_handle_t *, int);
379 
380 extern void libvarpd_plugin_proxy_arp(varpd_provider_handle_t *,
381     varpd_query_handle_t *, const overlay_targ_lookup_t *);
382 extern void libvarpd_plugin_proxy_ndp(varpd_provider_handle_t *,
383     varpd_query_handle_t *, const overlay_targ_lookup_t *);
384 extern void libvarpd_plugin_arp_reply(varpd_arp_handle_t *, int);
385 
386 extern void libvarpd_plugin_proxy_dhcp(varpd_provider_handle_t *,
387     varpd_query_handle_t *, const overlay_targ_lookup_t *);
388 extern void libvarpd_plugin_dhcp_reply(varpd_dhcp_handle_t *, int);
389 
390 
391 /*
392  * Property information callbacks
393  */
394 extern void libvarpd_prop_set_name(varpd_prop_handle_t *, const char *);
395 extern void libvarpd_prop_set_prot(varpd_prop_handle_t *, overlay_prop_prot_t);
396 extern void libvarpd_prop_set_type(varpd_prop_handle_t *, overlay_prop_type_t);
397 extern int libvarpd_prop_set_default(varpd_prop_handle_t *, void *, ssize_t);
398 extern void libvarpd_prop_set_nodefault(varpd_prop_handle_t *);
399 extern void libvarpd_prop_set_range_uint32(varpd_prop_handle_t *, uint32_t,
400     uint32_t);
401 extern void libvarpd_prop_set_range_str(varpd_prop_handle_t *, const char *);
402 
403 /*
404  * Various injecting and invalidation routines
405  */
406 extern void libvarpd_inject_varp(varpd_provider_handle_t *, const uint8_t *,
407     const overlay_target_point_t *);
408 extern void libvarpd_inject_arp(varpd_provider_handle_t *, const uint16_t,
409     const uint8_t *, const struct in_addr *, const uint8_t *);
410 extern void libvarpd_fma_degrade(varpd_provider_handle_t *, const char *);
411 extern void libvarpd_fma_restore(varpd_provider_handle_t *);
412 
413 #ifdef __cplusplus
414 }
415 #endif
416 
417 #endif /* _LIBVARPD_PROVIDER_H */
418