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 
 417 #ifdef __cplusplus
 418 }
 419 #endif
 420 
 421 #endif /* _LIBVARPD_PROVIDER_H */