root/usr/src/uts/common/sys/overlay_plugin.h
/*
 * 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 <sys/stream.h>
#include <sys/mac_provider.h>
#include <sys/ksocket.h>
#include <sys/overlay_common.h>

#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 */