/*-* SPDX-License-Identifier: BSD-2-Clause-FreeBSD** Copyright (C) 2018 Universita` di Pisa* All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions* are met:** 1. Redistributions of source code must retain the above copyright* notice, this list of conditions and the following disclaimer.* 2. Redistributions in binary form must reproduce the above copyright* notice, this list of conditions and the following disclaimer in the* documentation and/or other materials provided with the distribution.** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF* SUCH DAMAGE.*/#ifndef LIBNETMAP_H_#define LIBNETMAP_H_/* if thread-safety is not needed, define LIBNETMAP_NOTHREADSAFE before including* this file.*//* NOTE: we include net/netmap_user.h without defining NETMAP_WITH_LIBS, which* is deprecated. If you still need it, please define NETMAP_WITH_LIBS and* include net/netmap_user.h before including this file.*/#include <net/netmap_user.h>struct nmctx;struct nmport_d;struct nmem_d;/** A port open specification (portspec for brevity) has the following syntax* (square brackets delimit optional parts):** subsystem:vpname[mode][options]** The "subsystem" is denoted by a prefix, possibly followed by an identifier.* There can be several kinds of subsystems, each one selected by a unique* prefix. Currently defined subsystems are:** netmap (no id allowed)* the standard subsystem** vale (followed by a possibly empty id)* the vpname is connected to a VALE switch identified by* the id (an empty id selects the default switch)** The "vpname" has the following syntax:** identifier or* identifier1{identifier2 or* identifier1}identifier2** Identifiers are sequences of alphanumeric characters. The part that begins* with either '{' or '}', when present, denotes a netmap pipe opened in the* same memory region as the subsystem:indentifier1 port.** The "mode" can be one of the following:** ^ bind all host (sw) ring pairs* ^NN bind individual host ring pair* * bind host and NIC ring pairs* -NN bind individual NIC ring pair* @NN open the port in the NN memory region* a suffix starting with / and the following flags,* in any order:* x exclusive access* z zero copy monitor (both tx and rx)* t monitor tx side (copy monitor)* r monitor rx side (copy monitor)* R bind only RX ring(s)* T bind only TX ring(s)** The "options" start at the first '@' character not followed by a number.* Each option starts with '@' and has the following syntax:** option (flag option)* option=value (single key option)* option:key1=value1,key2=value2,... (multi-key option)** For multi-key options, the keys can be assigned in any order, but they* cannot be assigned more than once. It is not necessary to assign all the* option keys: unmentioned keys will receive default values. Some multi-key* options define a default key and also accept the single-key syntax, by* assigning the value to this key.** NOTE: Options may be silently ignored if the port is already open by some* other process.** The currently available options are (default keys, when defined, are marked* with '*'):** share (single-key)* open the port in the same memory region used by the* given port name (the port name must be given in* subsystem:vpname form)** conf (multi-key)* specify the rings/slots numbers (effective only on* ports that are created by the open operation itself,* and ignored otherwise).** The keys are:** *rings number of tx and rx rings* tx-rings number of tx rings* rx-rings number of rx rings* host-rings number of tx and rx host rings* host-tx-rings number of host tx rings* host-rx-rings number of host rx rings* slots number of slots in each tx and rx* ring* tx-slots number of slots in each tx ring* rx-slots number of slots in each rx ring** (more specific keys override the less specific ones)* All keys default to zero if not assigned, and the* corresponding value will be chosen by netmap.** extmem (multi-key)* open the port in the memory region obtained by* mmap()ing the given file.** The keys are:** *file the file to mmap* if-num number of pre-allocated netmap_if's* if-size size of each netmap_if* ring-num number of pre-allocated netmap_ring's* ring-size size of each netmap_ring* buf-num number of pre-allocated buffers* buf-size size of each buffer** file must be assigned. The other keys default to zero,* causing netmap to take the corresponding values from* the priv_{if,ring,buf}_{num,size} sysctls.** offset (multi-key)* reserve (part of) the ptr fields as an offset field* and write an initial offset into them.** The keys are:** bits number of bits of ptr to use* *initial initial offset value** initial must be assigned. If bits is omitted, it* defaults to the entire ptr field. The max offset is set* at the same value as the initial offset. Note that the* actual values may be increased by the kernel.** This option is disabled by default (see* nmport_enable_option() below)*//* nmport manipulation *//* struct nmport_d - describes a netmap port */struct nmport_d {/* see net/netmap.h for the definition of these fields */struct nmreq_header hdr;struct nmreq_register reg;/* all the fields below should be considered read-only *//* if the same context is used throughout the program, d1->mem ==* d2->mem iff d1 and d2 are using the memory region (i.e., zero* copy is possible between the two ports)*/struct nmem_d *mem;/* the nmctx used when this nmport_d was created */struct nmctx *ctx;int register_done; /* nmport_register() has been called */int mmap_done; /* nmport_mmap() has been called *//* pointer to the extmem option contained in the hdr options, if any */struct nmreq_opt_extmem *extmem;/* the fields below are compatible with nm_open() */int fd; /* "/dev/netmap", -1 if not open */struct netmap_if *nifp; /* pointer to the netmap_if */uint16_t first_tx_ring;uint16_t last_tx_ring;uint16_t first_rx_ring;uint16_t last_rx_ring;uint16_t cur_tx_ring; /* used by nmport_inject */uint16_t cur_rx_ring;/* LIFO list of cleanup functions (used internally) */struct nmport_cleanup_d *clist;};/* nmport_open - opens a port from a portspec* @portspec the port opening specification** If successful, the function returns a new nmport_d describing a netmap* port, opened according to the port specification, ready to be used for rx* and/or tx.** The rings available for tx are in the [first_tx_ring, last_tx_ring]* interval, and similarly for rx. One or both intervals may be empty.** When done using it, the nmport_d descriptor must be closed using* nmport_close().** In case of error, NULL is returned, errno is set to some error, and an* error message is sent through the error() method of the current context.*/struct nmport_d * nmport_open(const char *portspec);/* nport_close - close a netmap port* @d the port we want to close** Undoes the actions performed by the nmport_open that created d, then* frees the descriptor.*/void nmport_close(struct nmport_d *d);/* nmport_inject - sends a packet* @d the port through which we want to send* @buf base address of the packet* @size its size in bytes** Sends a packet using the cur_tx_ring and updates the index* to use all available tx rings in turn. Note: the packet is copied.** Returns 0 on success an -1 on error.*/int nmport_inject(struct nmport_d *d, const void *buf, size_t size);/** the functions below can be used to split the functionality of* nmport_open when special features (e.g., extra buffers) are needed** The relation among the functions is as follows:** |nmport_new* |nmport_prepare = |* | |nmport_parse* nmport_open =|* | |nmport_register* |nmport_open_desc =|* |nmport_mmap**//* nmport_new - create a new nmport_d** Creates a new nmport_d using the malloc() method of the current default* context. Returns NULL on error, setting errno to an error value.*/struct nmport_d *nmport_new(void);/* nmport_parse - fills the nmport_d netmap-register request* @d the nmport to be filled* @portspec the port opening specification** This function parses the portspec and initizalizes the @d->hdr and @d->reg* fields. It may need to allocate a list of options. If an extmem option is* found, it may also mmap() the corresponding file.** It returns 0 on success. On failure it returns -1, sets errno to an error* value and sends an error message to the error() method of the context used* when @d was created. Moreover, *@d is left unchanged.*/int nmport_parse(struct nmport_d *d, const char *portspec);/* nmport_register - registers the port with netmap* @d the nmport to be registered** This function obtains a netmap file descriptor and registers the port with* netmap. The @d->hdr and @d->reg data structures must have been previously* initialized (via nmport_parse() or otherwise).** It returns 0 on success. On failure it returns -1, sets errno to an error* value and sends an error message to the error() method of the context used* when @d was created. Moreover, *@d is left unchanged.*/int nmport_register(struct nmport_d *);/* nmport_mmap - maps the port resources into the process memory* @d the nmport to be mapped** The port must have been previously been registered using nmport_register.** Note that if extmem is used (either via an option or by calling an* nmport_extmem_* function before nmport_register()), no new mmap() is issued.** It returns 0 on success. On failure it returns -1, sets errno to an error* value and sends an error message to the error() method of the context used* when @d was created. Moreover, *@d is left unchanged.*/int nmport_mmap(struct nmport_d *);/* the following functions undo the actions of nmport_new(), nmport_parse(),* nmport_register() and nmport_mmap(), respectively.*/void nmport_delete(struct nmport_d *);void nmport_undo_parse(struct nmport_d *);void nmport_undo_register(struct nmport_d *);void nmport_undo_mmap(struct nmport_d *);/* nmport_prepare - create a port descriptor, but do not open it* @portspec the port opening specification** This functions creates a new nmport_d and initializes it according to* @portspec. It is equivalent to nmport_new() followed by nmport_parse().** It returns 0 on success. On failure it returns -1, sets errno to an error* value and sends an error message to the error() method of the context used* when @d was created. Moreover, *@d is left unchanged.*/struct nmport_d *nmport_prepare(const char *portspec);/* nmport_open_desc - open an initialized port descriptor* @d the descriptor we want to open** Registers the port with netmap and maps the rings and buffers into the* process memory. It is equivalent to nmport_register() followed by* nmport_mmap().** It returns 0 on success. On failure it returns -1, sets errno to an error* value and sends an error message to the error() method of the context used* when @d was created. Moreover, *@d is left unchanged.*/int nmport_open_desc(struct nmport_d *d);/* the following functions undo the actions of nmport_prepare()* and nmport_open_desc(), respectively.*/void nmport_undo_prepare(struct nmport_d *);void nmport_undo_open_desc(struct nmport_d *);/* nmport_clone - copy an nmport_d* @d the nmport_d we want to copy** Copying an nmport_d by hand should be avoided, since adjustments are needed* and some part of the state cannot be easily duplicated. This function* creates a copy of @d in a safe way. The returned nmport_d contains* nmreq_header and nmreq_register structures equivalent to those contained in* @d, except for the option list, which is ignored. The returned nmport_d is* already nmport_prepare()d, but it must still be nmport_open_desc()ed. The* new nmport_d uses the same nmctx as @d.** If extmem was used for @d, then @d cannot be nmport_clone()d until it has* been nmport_register()ed.** In case of error, the function returns NULL, sets errno to an error value* and sends an error message to the nmctx error() method.*/struct nmport_d *nmport_clone(struct nmport_d *);/* nmport_extmem - use extmem for this port* @d the port we want to use the extmem for* @base the base address of the extmem region* @size the size in bytes of the extmem region** the memory that contains the netmap ifs, rings and buffers is usually* allocated by netmap and later mmap()ed by the applications. It is sometimes* useful to reverse this process, by having the applications allocate some* memory (through mmap() or otherwise) and then let netmap use it. The extmem* option can be used to implement this latter strategy. The option can be* passed through the portspec using the '@extmem:...' syntax, or* programmatically by calling nmport_extmem() or nmport_extmem_from_file()* between nmport_parse() and nmport_register() (or between nmport_prepare()* and nmport_open_desc()).** It returns 0 on success. On failure it returns -1, sets errno to an error* value and sends an error message to the error() method of the context used* when @d was created. Moreover, *@d is left unchanged.*/int nmport_extmem(struct nmport_d *d, void *base, size_t size);/* nmport_extmem_from_file - use the extmem obtained by mapping a file* @d the port we want to use the extmem for* @fname path of the file we want to map** This works like nmport_extmem, but the extmem memory is obtained by* mmap()ping @fname. nmport_close() will also automatically munmap() the file.** It returns 0 on success. On failure it returns -1, sets errno to an error* value and sends an error message to the error() method of the context used* when @d was created. Moreover, *@d is left unchanged.*/int nmport_extmem_from_file(struct nmport_d *d, const char *fname);/* nmport_extmem_getinfo - opbtai a pointer to the extmem configuration* @d the port we want to obtain the pointer from** Returns a pointer to the nmreq_pools_info structure containing the* configuration of the extmem attached to port @d, or NULL if no extmem* is attached. This can be used to set the desired configuration before* registering the port, or to read the actual configuration after* registration.*/struct nmreq_pools_info* nmport_extmem_getinfo(struct nmport_d *d);/* nmport_offset - use offsets for this port* @initial the initial offset for all the slots* @maxoff the maximum offset* @bits the number of bits of slot->ptr to use for the offsets* @mingap the minimum gap between offsets (in shared buffers)** With this option the lower @bits bits of the ptr field in the netmap_slot* can be used to specify an offset into the buffer. All offsets will be set* to the @initial value by netmap.** The offset field can be read and updated using the bitmask found in* ring->offset_mask after a successful register. netmap_user.h contains* some helper macros (NETMAP_ROFFSET, NETMAP_WOFFSET and NETMAP_BUF_OFFSET).** For RX rings, the user writes the offset o in an empty slot before passing* it to netmap; then, netmap will write the incoming packet at an offset o' >=* o in the buffer. o' may be larger than o because of, e.g., alignment* constrains. If o' > o netmap will also update the offset field in the slot.* Note that large offsets may cause the port to split the packet over several* slots, setting the NS_MOREFRAG flag accordingly.** For TX rings, the user may prepare the packet to send at an offset o into* the buffer and write o in the offset field. Netmap will send the packets* starting o bytes in the buffer. Note that the address of the packet must* comply with any alignment constraints that the port may have, or the result* will be undefined. The user may read the alignment constraint in the new* ring->buf_align field. It is also possible that empty slots already come* with a non-zero offset o specified in the offset field. In this case, the* user will have to write the packet at an offset o' >= o.** The user must also declare the @maxoff offset that she is going to use. Any* offset larger than this will be truncated.** The user may also declare a @mingap (ignored if zero) if she plans to use* offsets to share the same buffer among several slots. Netmap will guarantee* that it will never write more than @mingap bytes for each slot, irrespective* of the buffer length.*/int nmport_offset(struct nmport_d *d, uint64_t initial, uint64_t maxoff,uint64_t bits, uint64_t mingap);/* enable/disable options** These functions can be used to disable options that the application cannot* or doesn't want to handle, or to enable options that require special support* from the application and are, therefore, disabled by default. Disabled* options will cause an error if encountered during option parsing.** If the option is unknown, nmport_disable_option is a NOP, while* nmport_enable_option returns -1 and sets errno to EOPNOTSUPP.** These functions are not threadsafe and are meant to be used at the beginning* of the program.*/void nmport_disable_option(const char *opt);int nmport_enable_option(const char *opt);/* nmreq manipulation** nmreq_header_init - initialize an nmreq_header* @hdr the nmreq_header to initialize* @reqtype the kind of netmap request* @body the body of the request** Initialize the nr_version, nr_reqtype and nr_body fields of *@hdr.* The other fields are set to zero.*/void nmreq_header_init(struct nmreq_header *hdr, uint16_t reqtype, void *body);/** These functions allow for finer grained parsing of portspecs. They are used* internally by nmport_parse().*//* nmreq_header_decode - initialize an nmreq_header* @ppspec: (in/out) pointer to a pointer to the portspec* @hdr: pointer to the nmreq_header to be initialized* @ctx: pointer to the nmctx to use (for errors)** This function fills the @hdr the nr_name field with the port name extracted* from *@pifname. The other fields of *@hdr are unchanged. The @pifname is* updated to point at the first char past the port name.** Returns 0 on success. In case of error, -1 is returned with errno set to* EINVAL, @pifname is unchanged, *@hdr is also unchanged, and an error message* is sent through @ctx->error().*/int nmreq_header_decode(const char **ppspec, struct nmreq_header *hdr,struct nmctx *ctx);/* nmreq_regiter_decode - initialize an nmreq_register* @pmode: (in/out) pointer to a pointer to an opening mode* @reg: pointer to the nmreq_register to be initialized* @ctx: pointer to the nmctx to use (for errors)** This function fills the nr_mode, nr_ringid, nr_flags and nr_mem_id fields of* the structure pointed by @reg, according to the opening mode specified by* *@pmode. The other fields of *@reg are unchanged. The @pmode is updated to* point at the first char past the opening mode.** If a '@' is encountered followed by something which is not a number, parsing* stops (without error) and @pmode is left pointing at the '@' char. The* nr_mode, nr_ringid and nr_flags fields are still updated, but nr_mem_id is* not touched and the interpretation of the '@' field is left to the caller.** Returns 0 on success. In case of error, -1 is returned with errno set to* EINVAL, @pmode is unchanged, *@reg is also unchanged, and an error message* is sent through @ctx->error().*/int nmreq_register_decode(const char **pmode, struct nmreq_register *reg,struct nmctx *ctx);/* nmreq_options_decode - parse the "options" part of the portspec* @opt: pointer to the option list* @parsers: list of option parsers* @token: token to pass to each parser* @ctx: pointer to the nmctx to use (for errors and malloc/free)** This function parses each option in @opt. Each option is matched (based on* the "option" prefix) to a corresponding parser in @parsers. The function* checks that the syntax is appropriate for the parser and it assigns all the* keys mentioned in the option. It then passes control to the parser, to* interpret the keys values.** Returns 0 on success. In case of error, -1 is returned, errno is set to an* error value and a message is sent to @ctx->error(). The effects of partially* interpreted options may not be undone.*/struct nmreq_opt_parser;int nmreq_options_decode(const char *opt, struct nmreq_opt_parser *parsers,void *token, struct nmctx *ctx);struct nmreq_parse_ctx;/* type of the option-parsers callbacks */typedef int (*nmreq_opt_parser_cb)(struct nmreq_parse_ctx *);#define NMREQ_OPT_MAXKEYS 16 /* max nr of recognized keys per option *//* struct nmreq_opt_key - describes an option key */struct nmreq_opt_key {const char *key; /* the key name */int id; /* its position in the parse context */unsigned int flags;#define NMREQ_OPTK_ALLOWEMPTY (1U << 0) /* =value may be omitted */#define NMREQ_OPTK_MUSTSET (1U << 1) /* the key is mandatory */#define NMREQ_OPTK_DEFAULT (1U << 2) /* this is the default key */};/* struct nmreq_opt_parser - describes an option parser */struct nmreq_opt_parser {const char *prefix; /* matches one option prefix */nmreq_opt_parser_cb parse; /* the parse callback */int default_key; /* which option is the default if theparser is multi-key (-1 if none) */int nr_keys;unsigned int flags;#define NMREQ_OPTF_DISABLED (1U << 0)#define NMREQ_OPTF_ALLOWEMPTY (1U << 1) /* =value can be omitted */struct nmreq_opt_parser *next; /* list of options *//* recognized keys */struct nmreq_opt_key keys[NMREQ_OPT_MAXKEYS];} __attribute__((aligned(16)));/* struct nmreq_parse_ctx - the parse context received by the parse callback */struct nmreq_parse_ctx {struct nmctx *ctx; /* the nmctx for errors and malloc/free */void *token; /* the token passed to nmreq_options_parse *//* the value (i.e., the part after the = sign) of each recognized key* is assigned to the corresponding entry in this array, based on the* key id. Unassigned keys are left at NULL.*/const char *keys[NMREQ_OPT_MAXKEYS];};/* nmreq_get_mem_id - get the mem_id of the given port* @portname pointer to a pointer to the portname* @ctx pointer to the nmctx to use (for errors)** *@portname must point to a substem:vpname porname, possibly followed by* something else.** If successful, returns the mem_id of *@portname and moves @portname past the* subsystem:vpname part of the input. In case of error it returns -1, sets* errno to an error value and sends an error message to ctx->error().*/int32_t nmreq_get_mem_id(const char **portname, struct nmctx *ctx);/* option list manipulation */void nmreq_push_option(struct nmreq_header *, struct nmreq_option *);void nmreq_remove_option(struct nmreq_header *, struct nmreq_option *);struct nmreq_option *nmreq_find_option(struct nmreq_header *, uint32_t);void nmreq_free_options(struct nmreq_header *);const char* nmreq_option_name(uint32_t);#define nmreq_foreach_option(h_, o_) \for ((o_) = (struct nmreq_option *)((uintptr_t)((h_)->nr_options));\(o_) != NULL;\(o_) = (struct nmreq_option *)((uintptr_t)((o_)->nro_next)))/* nmctx manipulation *//* the nmctx serves a few purposes:** - maintain a list of all memory regions open by the program, so that two* ports that are using the same region (as identified by the mem_id) will* point to the same nmem_d instance.** - allow the user to specify how to lock accesses to the above list, if* needed (lock() callback)** - allow the user to specify how error messages should be delivered (error()* callback)** - select the verbosity of the library (verbose field); if verbose==0, no* errors are sent to the error() callback** - allow the user to override the malloc/free functions used by the library* (malloc() and free() callbacks)**/typedef void (*nmctx_error_cb)(struct nmctx *, const char *);typedef void *(*nmctx_malloc_cb)(struct nmctx *,size_t);typedef void (*nmctx_free_cb)(struct nmctx *,void *);typedef void (*nmctx_lock_cb)(struct nmctx *, int);struct nmctx {int verbose;nmctx_error_cb error;nmctx_malloc_cb malloc;nmctx_free_cb free;nmctx_lock_cb lock;struct nmem_d *mem_descs;};/* nmctx_get - obtain a pointer to the current default context */struct nmctx *nmctx_get(void);/* nmctx_set_default - change the default context* @ctx pointer to the new context** Returns a pointer to the previous default context.*/struct nmctx *nmctx_set_default(struct nmctx *ctx);/* internal functions and data structures *//* struct nmem_d - describes a memory region currently used */struct nmem_d {uint16_t mem_id; /* the region netmap identifier */int refcount; /* how many nmport_d's point here */void *mem; /* memory region base address */size_t size; /* memory region size */int is_extmem; /* was it obtained via extmem? *//* pointers for the circular list implementation.* The list head is the mem_descs filed in the nmctx*/struct nmem_d *next;struct nmem_d *prev;};/* a trick to force the inclusion of libpthread only if requested. If* LIBNETMAP_NOTHREADSAFE is defined, no pthread symbol is imported.** There is no need to actually call this function: the ((used)) attribute is* sufficient to include it in the image.*/static __attribute__((used)) void libnetmap_init(void){#ifndef LIBNETMAP_NOTHREADSAFEextern int nmctx_threadsafe;/* dummy assignment to link-in the nmctx-pthread.o object. The proper* inizialization is performed only once in the library constructor* defined there.*/nmctx_threadsafe = 1;#endif /* LIBNETMAP_NOTHREADSAFE */}/* nmctx_set_threadsafe - install a threadsafe default context** called by the constructor in nmctx-pthread.o to initialize a lock and install* the lock() callback in the default context.*/void nmctx_set_threadsafe(void);/* nmctx_ferror - format and send an error message */void nmctx_ferror(struct nmctx *, const char *, ...);/* nmctx_malloc - allocate memory */void *nmctx_malloc(struct nmctx *, size_t);/* nmctx_free - free memory allocated via nmctx_malloc */void nmctx_free(struct nmctx *, void *);/* nmctx_lock - lock the list of nmem_d */void nmctx_lock(struct nmctx *);/* nmctx_unlock - unlock the list of nmem_d */void nmctx_unlock(struct nmctx *);#endif /* LIBNETMAP_H_ */
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。