/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright (c) 2015 Joyent, Inc. */ #ifndef _SYS_OVERLAY_PLUGIN_H #define _SYS_OVERLAY_PLUGIN_H /* * overlay plugin interface for encapsulation/decapsulation modules * * This header file defines how encapsulation and decapsulation plugins * interact within the broader system. At this time, these interfaces are * considered private to illumos and therefore are subject to change. As we gain * more experience with a few of the different encapsulation formats, say nvgre * or geneve, then we can move to make this a more-stable interface. * * A plugin is a general kernel module that uses the miscellaneous mod-linkage. * * In it's _init(9E) routine, it must register itself with the overlay * subsystem. To do this, it allocates an overlay_plugin_register_t via * overlay_plugin_alloc(), that it then * fills out with various required * information and then attempts to register with the system via a call to * overlay_plugin_register(). If that succeeds, it should then call * mod_install(9F). If the mod_install(9F) fails, then it should call * overlay_plugin_unregister(). Regardless of success or failure, it should call * overlay_plugin_free() to ensure that any memory that may be associated with * the registration is freed. * * When the module's _fini(9E) is called, overlay_plugin_unregister() should be * called first. It may return an error, such as EBUSY. In such cases, it should * be returned as the return status of _fini(9E). This is quite necessary, it * ensures that if the module is in use it doesn't get unloaded out from under * us the broader subsystem while it's still in use. A driver can use that to * know that there are no current instances of its private data. * * ------------------ * Plugin Definitions * ------------------ * * A plugin is required to fill in both an operations vector and a series of * information to the callback routine. Here are the routines and their * purposes. The full signatures are available below. * * overlay_plugin_init_t * * This interface is used to create a new instance of a plugin. An instance * of a plugin will be created for each overlay device that is created. For * example, if a device is created with VXLAN ID 23 and ID 42, then there * will be two different calls to this function. * * This function gives the plugin a chance to create a private data * structure that will be returned on subsequent calls to the system. * * overlay_plugin_fini_t * * This is the opposite of overlay_plugin_init_t. It will be called when it * is safe to remove any private data that is associated with this instance * of the plugin. * * overlay_plugin_propinfo_t * * This is called with the name of a property that is registered when the * plugin is created. This function will be called with the name of the * property that information is being requested about. The plugin is * responsible for filling out information such as setting the name, the * type of property it is, the protection of the property (can a user * update it?), whether the property is required, an optional default value * for the property, and an optional set of values or ranges that are * allowed. * * overlay_plugin_getprop_t * * Return the value of the named property from the current instance of the * plugin. * * overlay_plugin_setprop_t * * Set the value of the named property to the specified value for the * current instance of the plugin. Note, that it is the plugin's * responsibility to ensure that the value of the property is valid and to * update state as appropriate. * * overlay_plugin_socket_t * * Every overlay device has a corresponding socket that it uses to send and * receive traffic. This routine is used to get the parameters that should * be used to define such a socket. The actual socket may be multiplexed * with other uses of it. * * overlay_plugin_sockopt_t * * Allow a plugin to set any necessary socket options that it needs on the * kernel socket that is being used by a mux. This will only be called once * for a given mux, if additional devices are added to a mux, it will not * be called additional times. * * overlay_plugin_encap_t * * In this routine you're given a message block and information about the * packet, such as the identifier and are asked to fill out a message block * that represents the encapsulation header and optionally manipulate the * input message if required. * * overlay_plugin_decap_t * * In this routine, you're given the encapsulated message block. The * requirement is to decapsulate it and determine what is the correct * overlay identifier for this network and to fill in the header size so * the broader system knows how much of this data should be considered * consumed. * * ovpo_callbacks * * This should be set to zero, it's reserved for future use. * * Once these properties are defined, the module should define the following * members in the overlay_plugin_register_t. * * ovep_version * * Should be set to the value of the macro OVEP_VERSION. * * ovep_name * * Should be set to a character string that has the name of the module. * Generally this should match the name of the kernel module; however, this * is the name that users will use to refer to this module when creating * devices. * * overlay_plugin_ops_t * * Should be set to the functions as described above. * * ovep_props * * This is an array of character strings that holds the names of the * properties of the encapsulation plugin. * * * ovep_id_size * * This is the size in bytes of the valid range for the identifier. The * valid identifier range is considered a ovep_id_size byte unsigned * integer, [ 0, 1 << (ovep_id_size * 8) ). * * ovep_flags * * A series of flags that indicate optional features that are supported. * Valid flags include: * * OVEP_F_VLAN_TAG * * The encapsulation format allows for the encapsulated * packet to maintain a VLAN tag. * * ovep_dest * * Describes the kind of destination that the overlay plugin supports for * sending traffic. For example, vxlan uses UDP, therefore it requires both * an IP address and a port; however, nvgre uses the gre header and * therefore only requires an IP address. The following flags may be * combined: * * OVERLAY_PLUGIN_D_ETHERNET * * Indicates that to send a packet to its destination, we * require a link-layer ethernet address. * * OVERLAY_PLUGIN_D_IP * * Indicates that to send a packet to its destination, we * require an IP address. Note, all IP addresses are * transmitted as IPv6 addresses and for an IPv4 * destination, using an IPv4-mapped IPv6 address is the * expected way to transmit that. * * OVERLAY_PLUGIN_D_PORT * * Indicates that to send a packet to its destination, a * port is required, this usually indicates that the * protocol uses something like TCP or UDP. * * * ------------------------------------------------- * Downcalls, Upcalls, and Synchronization Guarantees * ------------------------------------------------- * * Every instance of a given module is independent. The kernel only guarantees * that it will probably perform downcalls into different instances in parallel * at some point. No locking is provided by the framework for synchronization * across instances. If a module finds itself needing that, it will be up to it * to provide it. * * In a given instance, the kernel may call into entry points in parallel. If * the instance has private data, it should likely synchronize it. The one * guarantee that we do make, is that calls to getprop and setprop will be done * synchronized by a caller holding the MAC perimeter. * * While servicing a downcall from the general overlay device framework, a * kernel module should not make any upcalls, excepting those functions that are * defined in this header file, eg. the property related callbacks. Importantly, * it cannot make any assumptions about what locks may or may not be held by the * broader system. The only thing that it is safe for it to use are its own * locks. * * ---------------- * Downcall Context * ---------------- * * For all of the downcalls, excepting the overlay_plugin_encap_t and * overlay_plugin_decap_t, the calls will be made either in kernel or user * context, the module should not assume either way. * * overlay_plugin_encap_t and overlay_plugin_decap_t may be called in user, * kernel or interrupt context; however, it is guaranteed that the interrupt * will be below LOCK_LEVEL, and therefore it is safe to grab locks. */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define OVEP_VERSION 0x1 typedef enum overlay_plugin_flags { OVEP_F_VLAN_TAG = 0x01 /* Supports VLAN Tags */ } overlay_plugin_flags_t; /* * The ID space could easily be more than a 64-bit number, even * though today it's either a 24-64 bit value. How should we future * proof ourselves here? */ typedef struct ovep_encap_info { uint64_t ovdi_id; size_t ovdi_hdr_size; } ovep_encap_info_t; typedef struct __overlay_prop_handle *overlay_prop_handle_t; typedef struct __overlay_handle *overlay_handle_t; /* * Plugins are guaranteed that calls to setprop are serialized. However, any * number of other calls can be going on in parallel otherwise. */ typedef int (*overlay_plugin_encap_t)(void *, mblk_t *, ovep_encap_info_t *, mblk_t **); typedef int (*overlay_plugin_decap_t)(void *, mblk_t *, ovep_encap_info_t *); typedef int (*overlay_plugin_init_t)(overlay_handle_t, void **); typedef void (*overlay_plugin_fini_t)(void *); typedef int (*overlay_plugin_socket_t)(void *, int *, int *, int *, struct sockaddr *, socklen_t *); typedef int (*overlay_plugin_sockopt_t)(ksocket_t); typedef int (*overlay_plugin_getprop_t)(void *, const char *, void *, uint32_t *); typedef int (*overlay_plugin_setprop_t)(void *, const char *, const void *, uint32_t); typedef int (*overlay_plugin_propinfo_t)(const char *, overlay_prop_handle_t); typedef struct overlay_plugin_ops { uint_t ovpo_callbacks; overlay_plugin_init_t ovpo_init; overlay_plugin_fini_t ovpo_fini; overlay_plugin_encap_t ovpo_encap; overlay_plugin_decap_t ovpo_decap; overlay_plugin_socket_t ovpo_socket; overlay_plugin_sockopt_t ovpo_sockopt; overlay_plugin_getprop_t ovpo_getprop; overlay_plugin_setprop_t ovpo_setprop; overlay_plugin_propinfo_t ovpo_propinfo; } overlay_plugin_ops_t; typedef struct overlay_plugin_register { uint_t ovep_version; const char *ovep_name; const overlay_plugin_ops_t *ovep_ops; const char **ovep_props; uint_t ovep_id_size; uint_t ovep_flags; uint_t ovep_dest; } overlay_plugin_register_t; /* * Functions that interact with registration */ extern overlay_plugin_register_t *overlay_plugin_alloc(uint_t); extern void overlay_plugin_free(overlay_plugin_register_t *); extern int overlay_plugin_register(overlay_plugin_register_t *); extern int overlay_plugin_unregister(const char *); /* * Property information callbacks */ extern void overlay_prop_set_name(overlay_prop_handle_t, const char *); extern void overlay_prop_set_prot(overlay_prop_handle_t, overlay_prop_prot_t); extern void overlay_prop_set_type(overlay_prop_handle_t, overlay_prop_type_t); extern int overlay_prop_set_default(overlay_prop_handle_t, void *, ssize_t); extern void overlay_prop_set_nodefault(overlay_prop_handle_t); extern void overlay_prop_set_range_uint32(overlay_prop_handle_t, uint32_t, uint32_t); extern void overlay_prop_set_range_str(overlay_prop_handle_t, const char *); #ifdef __cplusplus } #endif #endif /* _SYS_OVERLAY_PLUGIN_H */