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