Index: stable/12/lib/Makefile =================================================================== --- stable/12/lib/Makefile (revision 366012) +++ stable/12/lib/Makefile (revision 366013) @@ -1,228 +1,229 @@ # @(#)Makefile 8.1 (Berkeley) 6/4/93 # $FreeBSD$ .include # The SUBDIR_BOOTSTRAP list is a small set of libraries which are used by many # of the other libraries. These are built first with a .WAIT between them # and the main list to avoid needing a SUBDIR_DEPEND line on every library # naming just these few items. SUBDIR_BOOTSTRAP= \ csu \ .WAIT \ libc \ libc_nonshared \ libcompiler_rt \ ${_libclang_rt} \ ${_libcplusplus} \ ${_libcxxrt} \ libelf \ libssp \ libssp_nonshared \ msun # The main list; please keep these sorted alphabetically. SUBDIR= ${SUBDIR_BOOTSTRAP} \ .WAIT \ geom \ libalias \ libarchive \ libauditd \ libbegemot \ libblocksruntime \ libbsdstat \ libbsm \ libbz2 \ libcalendar \ libcam \ libcapsicum \ libcasper \ libcompat \ libcrypt \ libdevctl \ libdevinfo \ libdevstat \ ${_libdl} \ libdwarf \ libedit \ libelftc \ libevent \ libexecinfo \ libexpat \ libfetch \ libfigpar \ libgeom \ libifconfig \ libipsec \ libjail \ libkiconv \ libkvm \ liblua \ liblzma \ libmemstat \ libmd \ libmt \ lib80211 \ libnetbsd \ + libnetmap \ libnv \ libopenbsd \ libopie \ libpam \ libpathconv \ libpcap \ libpjdlog \ ${_libproc} \ libprocstat \ libregex \ librpcsvc \ librss \ librt \ ${_librtld_db} \ libsbuf \ libsmb \ libsqlite3 \ libstdbuf \ libstdthreads \ libsysdecode \ libtacplus \ libthread_db \ libucl \ libufs \ libugidfw \ libulog \ libutil \ ${_libvgl} \ libwrap \ libxo \ liby \ libz \ libzstd \ ncurses # Inter-library dependencies. When the makefile for a library contains LDADD # libraries, those libraries should be listed as build order dependencies here. SUBDIR_DEPEND_geom= libufs SUBDIR_DEPEND_libarchive= libz libbz2 libexpat liblzma libmd SUBDIR_DEPEND_libauditdm= libbsm SUBDIR_DEPEND_libbsnmp= ${_libnetgraph} SUBDIR_DEPEND_libc++:= libcxxrt # libssp_nonshared doesn't need to be linked into libc on every arch, but it is # small enough to build that this bit of serialization is likely insignificant. SUBDIR_DEPEND_libc= libcompiler_rt libssp_nonshared SUBDIR_DEPEND_libcam= libsbuf SUBDIR_DEPEND_libcasper= libnv SUBDIR_DEPEND_libdevstat= libkvm SUBDIR_DEPEND_libdpv= libfigpar ncurses libutil SUBDIR_DEPEND_libedit= ncurses SUBDIR_DEPEND_libgeom= libexpat libsbuf SUBDIR_DEPEND_librpcsec_gss= libgssapi SUBDIR_DEPEND_libmagic= libz SUBDIR_DEPEND_libmemstat= libkvm SUBDIR_DEPEND_libopie= libmd SUBDIR_DEPEND_libpam= libcrypt libopie ${_libradius} librpcsvc libtacplus libutil ${_libypclnt} ${_libcom_err} SUBDIR_DEPEND_libpjdlog= libutil SUBDIR_DEPEND_libprocstat= libkvm libutil SUBDIR_DEPEND_libradius= libmd SUBDIR_DEPEND_libsmb= libkiconv SUBDIR_DEPEND_libtacplus= libmd SUBDIR_DEPEND_libulog= libmd SUBDIR_DEPEND_libunbound= ${_libldns} SUBDIR_DEPEND_liblzma= ${_libthr} .if ${MK_OFED} != "no" SUBDIR_DEPEND_libpcap= ofed .endif # NB: keep these sorted by MK_* knobs SUBDIR.${MK_ATM}+= libngatm SUBDIR.${MK_BEARSSL}+= libbearssl libsecureboot SUBDIR.${MK_BLACKLIST}+=libblacklist SUBDIR.${MK_BLUETOOTH}+=libbluetooth libsdp SUBDIR.${MK_BSNMP}+= libbsnmp .if !defined(COMPAT_32BIT) && !defined(COMPAT_SOFTFP) SUBDIR.${MK_CLANG}+= clang .endif SUBDIR.${MK_CUSE}+= libcuse SUBDIR.${MK_CXX}+= libdevdctl SUBDIR.${MK_TOOLCHAIN}+=libpe SUBDIR.${MK_DIALOG}+= libdpv SUBDIR.${MK_FILE}+= libmagic SUBDIR.${MK_GPIO}+= libgpio SUBDIR.${MK_GSSAPI}+= libgssapi librpcsec_gss SUBDIR.${MK_ICONV}+= libiconv_modules SUBDIR.${MK_KERBEROS_SUPPORT}+= libcom_err SUBDIR.${MK_LDNS}+= libldns # The libraries under libclang_rt can only be built by clang, and only make # sense to build when clang is enabled at all. Furthermore, they can only be # built for certain architectures. .if ${MK_CLANG} != "no" && ${COMPILER_TYPE} == "clang" && \ (${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \ ${MACHINE_CPUARCH} == "arm" || ${MACHINE_CPUARCH} == "i386" || \ ${MACHINE_CPUARCH} == "powerpc") _libclang_rt= libclang_rt .endif .if ${MK_LIBCPLUSPLUS} != "no" _libcxxrt= libcxxrt _libcplusplus= libc++ _libcplusplus+= libc++experimental .endif SUBDIR.${MK_EFI}+= libefivar SUBDIR.${MK_GOOGLETEST}+= googletest SUBDIR.${MK_LIBTHR}+= libthr SUBDIR.${MK_LLVM_LIBUNWIND}+= libgcc_eh SUBDIR.${MK_LLVM_LIBUNWIND}+= libgcc_s SUBDIR.${MK_NAND}+= libnandfs SUBDIR.${MK_NETGRAPH}+= libnetgraph SUBDIR.${MK_NIS}+= libypclnt .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" _libvgl= libvgl .endif .if ${MACHINE_CPUARCH} == "aarch64" SUBDIR.${MK_PMC}+= libopencsd .endif .if ${MACHINE_CPUARCH} == "amd64" SUBDIR.${MK_PMC}+= libipt SUBDIR.${MK_BHYVE}+= libvmmapi .endif .if ${MACHINE_CPUARCH} != "sparc64" _libproc= libproc _librtld_db= librtld_db .endif .if defined(LINKER_FEATURES) && ${LINKER_FEATURES:Mfilter} _libdl= libdl .endif .if ${MACHINE_ARCH} != "powerpc" SUBDIR.${MK_OPENMP}+= libomp .endif SUBDIR.${MK_OPENSSL}+= libmp SUBDIR.${MK_PMC}+= libpmc libpmcstat SUBDIR.${MK_RADIUS_SUPPORT}+= libradius SUBDIR.${MK_SENDMAIL}+= libmilter libsm libsmdb libsmutil SUBDIR.${MK_TELNET}+= libtelnet SUBDIR.${MK_TESTS_SUPPORT}+= atf SUBDIR.${MK_TESTS}+= tests SUBDIR.${MK_UNBOUND}+= libunbound SUBDIR.${MK_USB}+= libusbhid libusb SUBDIR.${MK_OFED}+= ofed SUBDIR.${MK_VERIEXEC}+= libveriexec SUBDIR.${MK_ZFS}+= libbe .if !make(install) SUBDIR_PARALLEL= .endif .include Index: stable/12/lib/libnetmap/nmctx-pthreads.c =================================================================== --- stable/12/lib/libnetmap/nmctx-pthreads.c (nonexistent) +++ stable/12/lib/libnetmap/nmctx-pthreads.c (revision 366013) @@ -0,0 +1,77 @@ +/*- + * 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libnetmap.h" + +struct nmctx_pthread { + struct nmctx up; + pthread_mutex_t mutex; +}; + +static struct nmctx_pthread nmctx_pthreadsafe; + +static void +nmctx_pthread_lock(struct nmctx *ctx, int lock) +{ + struct nmctx_pthread *ctxp = + (struct nmctx_pthread *)ctx; + if (lock) { + pthread_mutex_lock(&ctxp->mutex); + } else { + pthread_mutex_unlock(&ctxp->mutex); + } +} + +void __attribute__ ((constructor)) +nmctx_set_threadsafe(void) +{ + struct nmctx *old; + + pthread_mutex_init(&nmctx_pthreadsafe.mutex, NULL); + old = nmctx_set_default(&nmctx_pthreadsafe.up); + nmctx_pthreadsafe.up = *old; + nmctx_pthreadsafe.up.lock = nmctx_pthread_lock; +} + +int nmctx_threadsafe; Property changes on: stable/12/lib/libnetmap/nmctx-pthreads.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12/lib/libnetmap/nmctx.c =================================================================== --- stable/12/lib/libnetmap/nmctx.c (nonexistent) +++ stable/12/lib/libnetmap/nmctx.c (revision 366013) @@ -0,0 +1,141 @@ +/*- + * 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define LIBNETMAP_NOTHREADSAFE +#include "libnetmap.h" + +static void +nmctx_default_error(struct nmctx *ctx, const char *errmsg) +{ + fprintf(stderr, "%s\n", errmsg); +} + +static void * +nmctx_default_malloc(struct nmctx *ctx, size_t sz) +{ + (void)ctx; + return malloc(sz); +} + +static void +nmctx_default_free(struct nmctx *ctx, void *p) +{ + (void)ctx; + free(p); +} + +static struct nmctx nmctx_global = { + .verbose = 1, + .error = nmctx_default_error, + .malloc = nmctx_default_malloc, + .free = nmctx_default_free, + .lock = NULL, +}; + +static struct nmctx *nmctx_default = &nmctx_global; + +struct nmctx * +nmctx_get(void) +{ + return nmctx_default; +} + +struct nmctx * +nmctx_set_default(struct nmctx *ctx) +{ + struct nmctx *old = nmctx_default; + nmctx_default = ctx; + return old; +} + +#define MAXERRMSG 1000 +void +nmctx_ferror(struct nmctx *ctx, const char *fmt, ...) +{ + char errmsg[MAXERRMSG]; + va_list ap; + int rv; + + if (!ctx->verbose) + return; + + va_start(ap, fmt); + rv = vsnprintf(errmsg, MAXERRMSG, fmt, ap); + va_end(ap); + + if (rv > 0) { + if (rv < MAXERRMSG) { + ctx->error(ctx, errmsg); + } else { + ctx->error(ctx, "error message too long"); + } + } else { + ctx->error(ctx, "internal error"); + } +} + +void * +nmctx_malloc(struct nmctx *ctx, size_t sz) +{ + return ctx->malloc(ctx, sz); +} + +void +nmctx_free(struct nmctx *ctx, void *p) +{ + ctx->free(ctx, p); +} + +void +nmctx_lock(struct nmctx *ctx) +{ + if (ctx->lock != NULL) + ctx->lock(ctx, 1); +} + +void +nmctx_unlock(struct nmctx *ctx) +{ + if (ctx->lock != NULL) + ctx->lock(ctx, 0); +} Property changes on: stable/12/lib/libnetmap/nmctx.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12/lib/libnetmap/nmport.c =================================================================== --- stable/12/lib/libnetmap/nmport.c (nonexistent) +++ stable/12/lib/libnetmap/nmport.c (revision 366013) @@ -0,0 +1,840 @@ +/*- + * 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define LIBNETMAP_NOTHREADSAFE +#include "libnetmap.h" + +struct nmport_cleanup_d { + struct nmport_cleanup_d *next; + void (*cleanup)(struct nmport_cleanup_d *, struct nmport_d *); +}; + +static void +nmport_push_cleanup(struct nmport_d *d, struct nmport_cleanup_d *c) +{ + c->next = d->clist; + d->clist = c; +} + +static void +nmport_pop_cleanup(struct nmport_d *d) +{ + struct nmport_cleanup_d *top; + + top = d->clist; + d->clist = d->clist->next; + (*top->cleanup)(top, d); + nmctx_free(d->ctx, top); +} + +void nmport_do_cleanup(struct nmport_d *d) +{ + while (d->clist != NULL) { + nmport_pop_cleanup(d); + } +} + +static struct nmport_d * +nmport_new_with_ctx(struct nmctx *ctx) +{ + struct nmport_d *d; + + /* allocate a descriptor */ + d = nmctx_malloc(ctx, sizeof(*d)); + if (d == NULL) { + nmctx_ferror(ctx, "cannot allocate nmport descriptor"); + goto out; + } + memset(d, 0, sizeof(*d)); + + nmreq_header_init(&d->hdr, NETMAP_REQ_REGISTER, &d->reg); + + d->ctx = ctx; + d->fd = -1; + +out: + return d; +} + +struct nmport_d * +nmport_new(void) +{ + struct nmctx *ctx = nmctx_get(); + return nmport_new_with_ctx(ctx); +} + + +void +nmport_delete(struct nmport_d *d) +{ + nmctx_free(d->ctx, d); +} + +void +nmport_extmem_cleanup(struct nmport_cleanup_d *c, struct nmport_d *d) +{ + (void)c; + + if (d->extmem == NULL) + return; + + nmreq_remove_option(&d->hdr, &d->extmem->nro_opt); + nmctx_free(d->ctx, d->extmem); + d->extmem = NULL; +} + + +int +nmport_extmem(struct nmport_d *d, void *base, size_t size) +{ + struct nmctx *ctx = d->ctx; + struct nmport_cleanup_d *clnup = NULL; + + if (d->register_done) { + nmctx_ferror(ctx, "%s: cannot set extmem of an already registered port", d->hdr.nr_name); + errno = EINVAL; + return -1; + } + + if (d->extmem != NULL) { + nmctx_ferror(ctx, "%s: extmem already in use", d->hdr.nr_name); + errno = EINVAL; + return -1; + } + + clnup = (struct nmport_cleanup_d *)nmctx_malloc(ctx, sizeof(*clnup)); + if (clnup == NULL) { + nmctx_ferror(ctx, "failed to allocate cleanup descriptor"); + errno = ENOMEM; + return -1; + } + + d->extmem = nmctx_malloc(ctx, sizeof(*d->extmem)); + if (d->extmem == NULL) { + nmctx_ferror(ctx, "%s: cannot allocate extmem option", d->hdr.nr_name); + nmctx_free(ctx, clnup); + errno = ENOMEM; + return -1; + } + memset(d->extmem, 0, sizeof(*d->extmem)); + d->extmem->nro_usrptr = (uintptr_t)base; + d->extmem->nro_opt.nro_reqtype = NETMAP_REQ_OPT_EXTMEM; + d->extmem->nro_info.nr_memsize = size; + nmreq_push_option(&d->hdr, &d->extmem->nro_opt); + + clnup->cleanup = nmport_extmem_cleanup; + nmport_push_cleanup(d, clnup); + + return 0; +} + +struct nmport_extmem_from_file_cleanup_d { + struct nmport_cleanup_d up; + void *p; + size_t size; +}; + +void nmport_extmem_from_file_cleanup(struct nmport_cleanup_d *c, + struct nmport_d *d) +{ + struct nmport_extmem_from_file_cleanup_d *cc = + (struct nmport_extmem_from_file_cleanup_d *)c; + + munmap(cc->p, cc->size); +} + +int +nmport_extmem_from_file(struct nmport_d *d, const char *fname) +{ + struct nmctx *ctx = d->ctx; + int fd = -1; + off_t mapsize; + void *p; + struct nmport_extmem_from_file_cleanup_d *clnup = NULL; + + clnup = nmctx_malloc(ctx, sizeof(*clnup)); + if (clnup == NULL) { + nmctx_ferror(ctx, "cannot allocate cleanup descriptor"); + errno = ENOMEM; + goto fail; + } + + fd = open(fname, O_RDWR); + if (fd < 0) { + nmctx_ferror(ctx, "cannot open '%s': %s", fname, strerror(errno)); + goto fail; + } + mapsize = lseek(fd, 0, SEEK_END); + if (mapsize < 0) { + nmctx_ferror(ctx, "failed to obtain filesize of '%s': %s", fname, strerror(errno)); + goto fail; + } + p = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (p == MAP_FAILED) { + nmctx_ferror(ctx, "cannot mmap '%s': %s", fname, strerror(errno)); + goto fail; + } + close(fd); + + clnup->p = p; + clnup->size = mapsize; + clnup->up.cleanup = nmport_extmem_from_file_cleanup; + nmport_push_cleanup(d, &clnup->up); + + if (nmport_extmem(d, p, mapsize) < 0) + goto fail; + + return 0; + +fail: + if (fd >= 0) + close(fd); + if (clnup != NULL) { + if (clnup->p != MAP_FAILED) + nmport_pop_cleanup(d); + else + nmctx_free(ctx, clnup); + } + return -1; +} + +struct nmreq_pools_info* +nmport_extmem_getinfo(struct nmport_d *d) +{ + if (d->extmem == NULL) + return NULL; + return &d->extmem->nro_info; +} + +/* head of the list of options */ +static struct nmreq_opt_parser *nmport_opt_parsers; + +#define NPOPT_PARSER(o) nmport_opt_##o##_parser +#define NPOPT_DESC(o) nmport_opt_##o##_desc +#define NPOPT_NRKEYS(o) (NPOPT_DESC(o).nr_keys) +#define NPOPT_DECL(o, f) \ +static int NPOPT_PARSER(o)(struct nmreq_parse_ctx *); \ +static struct nmreq_opt_parser NPOPT_DESC(o) = { \ + .prefix = #o, \ + .parse = NPOPT_PARSER(o), \ + .flags = (f), \ + .default_key = -1, \ + .nr_keys = 0, \ + .next = NULL, \ +}; \ +static void __attribute__((constructor)) \ +nmport_opt_##o##_ctor(void) \ +{ \ + NPOPT_DESC(o).next = nmport_opt_parsers; \ + nmport_opt_parsers = &NPOPT_DESC(o); \ +} +struct nmport_key_desc { + struct nmreq_opt_parser *option; + const char *key; + unsigned int flags; + int id; +}; +static void +nmport_opt_key_ctor(struct nmport_key_desc *k) +{ + struct nmreq_opt_parser *o = k->option; + struct nmreq_opt_key *ok; + + k->id = o->nr_keys; + ok = &o->keys[k->id]; + ok->key = k->key; + ok->id = k->id; + ok->flags = k->flags; + o->nr_keys++; + if (ok->flags & NMREQ_OPTK_DEFAULT) + o->default_key = ok->id; +} +#define NPKEY_DESC(o, k) nmport_opt_##o##_key_##k##_desc +#define NPKEY_ID(o, k) (NPKEY_DESC(o, k).id) +#define NPKEY_DECL(o, k, f) \ +static struct nmport_key_desc NPKEY_DESC(o, k) = { \ + .option = &NPOPT_DESC(o), \ + .key = #k, \ + .flags = (f), \ + .id = -1, \ +}; \ +static void __attribute__((constructor)) \ +nmport_opt_##o##_key_##k##_ctor(void) \ +{ \ + nmport_opt_key_ctor(&NPKEY_DESC(o, k)); \ +} +#define nmport_key(p, o, k) ((p)->keys[NPKEY_ID(o, k)]) +#define nmport_defkey(p, o) ((p)->keys[NPOPT_DESC(o).default_key]) + +NPOPT_DECL(share, 0) + NPKEY_DECL(share, port, NMREQ_OPTK_DEFAULT|NMREQ_OPTK_MUSTSET) +NPOPT_DECL(extmem, 0) + NPKEY_DECL(extmem, file, NMREQ_OPTK_DEFAULT|NMREQ_OPTK_MUSTSET) + NPKEY_DECL(extmem, if_num, 0) + NPKEY_DECL(extmem, if_size, 0) + NPKEY_DECL(extmem, ring_num, 0) + NPKEY_DECL(extmem, ring_size, 0) + NPKEY_DECL(extmem, buf_num, 0) + NPKEY_DECL(extmem, buf_size, 0) +NPOPT_DECL(conf, 0) + NPKEY_DECL(conf, rings, 0) + NPKEY_DECL(conf, host_rings, 0) + NPKEY_DECL(conf, slots, 0) + NPKEY_DECL(conf, tx_rings, 0) + NPKEY_DECL(conf, rx_rings, 0) + NPKEY_DECL(conf, host_tx_rings, 0) + NPKEY_DECL(conf, host_rx_rings, 0) + NPKEY_DECL(conf, tx_slots, 0) + NPKEY_DECL(conf, rx_slots, 0) + + +static int +NPOPT_PARSER(share)(struct nmreq_parse_ctx *p) +{ + struct nmctx *ctx = p->ctx; + struct nmport_d *d = p->token; + int32_t mem_id; + const char *v = nmport_defkey(p, share); + + mem_id = nmreq_get_mem_id(&v, ctx); + if (mem_id < 0) + return -1; + if (d->reg.nr_mem_id && d->reg.nr_mem_id != mem_id) { + nmctx_ferror(ctx, "cannot set mem_id to %"PRId32", already set to %"PRIu16"", + mem_id, d->reg.nr_mem_id); + errno = EINVAL; + return -1; + } + d->reg.nr_mem_id = mem_id; + return 0; +} + +static int +NPOPT_PARSER(extmem)(struct nmreq_parse_ctx *p) +{ + struct nmport_d *d; + struct nmreq_pools_info *pi; + int i; + + d = p->token; + + if (nmport_extmem_from_file(d, nmport_key(p, extmem, file)) < 0) + return -1; + + pi = &d->extmem->nro_info; + + for (i = 0; i < NPOPT_NRKEYS(extmem); i++) { + const char *k = p->keys[i]; + uint32_t v; + + if (k == NULL) + continue; + + v = atoi(k); + if (i == NPKEY_ID(extmem, if_num)) { + pi->nr_if_pool_objtotal = v; + } else if (i == NPKEY_ID(extmem, if_size)) { + pi->nr_if_pool_objsize = v; + } else if (i == NPKEY_ID(extmem, ring_num)) { + pi->nr_ring_pool_objtotal = v; + } else if (i == NPKEY_ID(extmem, ring_size)) { + pi->nr_ring_pool_objsize = v; + } else if (i == NPKEY_ID(extmem, buf_num)) { + pi->nr_buf_pool_objtotal = v; + } else if (i == NPKEY_ID(extmem, buf_size)) { + pi->nr_buf_pool_objsize = v; + } + } + return 0; +} + +static int +NPOPT_PARSER(conf)(struct nmreq_parse_ctx *p) +{ + struct nmport_d *d; + + d = p->token; + + if (nmport_key(p, conf, rings) != NULL) { + uint16_t nr_rings = atoi(nmport_key(p, conf, rings)); + d->reg.nr_tx_rings = nr_rings; + d->reg.nr_rx_rings = nr_rings; + } + if (nmport_key(p, conf, host_rings) != NULL) { + uint16_t nr_rings = atoi(nmport_key(p, conf, host_rings)); + d->reg.nr_host_tx_rings = nr_rings; + d->reg.nr_host_rx_rings = nr_rings; + } + if (nmport_key(p, conf, slots) != NULL) { + uint32_t nr_slots = atoi(nmport_key(p, conf, slots)); + d->reg.nr_tx_slots = nr_slots; + d->reg.nr_rx_slots = nr_slots; + } + if (nmport_key(p, conf, tx_rings) != NULL) { + d->reg.nr_tx_rings = atoi(nmport_key(p, conf, tx_rings)); + } + if (nmport_key(p, conf, rx_rings) != NULL) { + d->reg.nr_rx_rings = atoi(nmport_key(p, conf, rx_rings)); + } + if (nmport_key(p, conf, host_tx_rings) != NULL) { + d->reg.nr_host_tx_rings = atoi(nmport_key(p, conf, host_tx_rings)); + } + if (nmport_key(p, conf, host_rx_rings) != NULL) { + d->reg.nr_host_rx_rings = atoi(nmport_key(p, conf, host_rx_rings)); + } + if (nmport_key(p, conf, tx_slots) != NULL) { + d->reg.nr_tx_slots = atoi(nmport_key(p, conf, tx_slots)); + } + if (nmport_key(p, conf, rx_slots) != NULL) { + d->reg.nr_rx_slots = atoi(nmport_key(p, conf, rx_slots)); + } + return 0; +} + +void +nmport_disable_option(const char *opt) +{ + struct nmreq_opt_parser *p; + + for (p = nmport_opt_parsers; p != NULL; p = p->next) { + if (!strcmp(p->prefix, opt)) { + p->flags |= NMREQ_OPTF_DISABLED; + } + } +} + +int +nmport_enable_option(const char *opt) +{ + struct nmreq_opt_parser *p; + + for (p = nmport_opt_parsers; p != NULL; p = p->next) { + if (!strcmp(p->prefix, opt)) { + p->flags &= ~NMREQ_OPTF_DISABLED; + return 0; + } + } + errno = EOPNOTSUPP; + return -1; +} + + +int +nmport_parse(struct nmport_d *d, const char *ifname) +{ + const char *scan = ifname; + + if (nmreq_header_decode(&scan, &d->hdr, d->ctx) < 0) { + goto err; + } + + /* parse the register request */ + if (nmreq_register_decode(&scan, &d->reg, d->ctx) < 0) { + goto err; + } + + /* parse the options, if any */ + if (nmreq_options_decode(scan, nmport_opt_parsers, d, d->ctx) < 0) { + goto err; + } + return 0; + +err: + nmport_undo_parse(d); + return -1; +} + +void +nmport_undo_parse(struct nmport_d *d) +{ + nmport_do_cleanup(d); + memset(&d->reg, 0, sizeof(d->reg)); + memset(&d->hdr, 0, sizeof(d->hdr)); +} + +struct nmport_d * +nmport_prepare(const char *ifname) +{ + struct nmport_d *d; + + /* allocate a descriptor */ + d = nmport_new(); + if (d == NULL) + goto err; + + /* parse the header */ + if (nmport_parse(d, ifname) < 0) + goto err; + + return d; + +err: + nmport_undo_prepare(d); + return NULL; +} + +void +nmport_undo_prepare(struct nmport_d *d) +{ + if (d == NULL) + return; + nmport_undo_parse(d); + nmport_delete(d); +} + +int +nmport_register(struct nmport_d *d) +{ + struct nmctx *ctx = d->ctx; + + if (d->register_done) { + errno = EINVAL; + nmctx_ferror(ctx, "%s: already registered", d->hdr.nr_name); + return -1; + } + + d->fd = open("/dev/netmap", O_RDWR); + if (d->fd < 0) { + nmctx_ferror(ctx, "/dev/netmap: %s", strerror(errno)); + goto err; + } + + if (ioctl(d->fd, NIOCCTRL, &d->hdr) < 0) { + struct nmreq_option *o; + int option_errors = 0; + + nmreq_foreach_option(&d->hdr, o) { + if (o->nro_status) { + nmctx_ferror(ctx, "%s: option %s: %s", + d->hdr.nr_name, + nmreq_option_name(o->nro_reqtype), + strerror(o->nro_status)); + option_errors++; + } + + } + if (!option_errors) + nmctx_ferror(ctx, "%s: %s", d->hdr.nr_name, strerror(errno)); + goto err; + } + + d->register_done = 1; + + return 0; + +err: + nmport_undo_register(d); + return -1; +} + +void +nmport_undo_register(struct nmport_d *d) +{ + if (d->fd >= 0) + close(d->fd); + d->fd = -1; + d->register_done = 0; +} + +/* lookup the mem_id in the mem-list: do a new mmap() if + * not found, reuse existing otherwise + */ +int +nmport_mmap(struct nmport_d *d) +{ + struct nmctx *ctx = d->ctx; + struct nmem_d *m = NULL; + u_int num_tx, num_rx; + int i; + + if (d->mmap_done) { + errno = EINVAL; + nmctx_ferror(ctx, "%s: already mapped", d->hdr.nr_name); + return -1; + } + + if (!d->register_done) { + errno = EINVAL; + nmctx_ferror(ctx, "cannot map unregistered port"); + return -1; + } + + nmctx_lock(ctx); + + for (m = ctx->mem_descs; m != NULL; m = m->next) + if (m->mem_id == d->reg.nr_mem_id) + break; + + if (m == NULL) { + m = nmctx_malloc(ctx, sizeof(*m)); + if (m == NULL) { + nmctx_ferror(ctx, "cannot allocate memory descriptor"); + goto err; + } + memset(m, 0, sizeof(*m)); + if (d->extmem != NULL) { + m->mem = (void *)d->extmem->nro_usrptr; + m->size = d->extmem->nro_info.nr_memsize; + m->is_extmem = 1; + } else { + m->mem = mmap(NULL, d->reg.nr_memsize, PROT_READ|PROT_WRITE, + MAP_SHARED, d->fd, 0); + if (m->mem == MAP_FAILED) { + nmctx_ferror(ctx, "mmap: %s", strerror(errno)); + goto err; + } + m->size = d->reg.nr_memsize; + } + m->mem_id = d->reg.nr_mem_id; + m->next = ctx->mem_descs; + if (ctx->mem_descs != NULL) + ctx->mem_descs->prev = m; + ctx->mem_descs = m; + } + m->refcount++; + + nmctx_unlock(ctx); + + d->mem = m; + + d->nifp = NETMAP_IF(m->mem, d->reg.nr_offset); + + num_tx = d->reg.nr_tx_rings + d->nifp->ni_host_tx_rings; + for (i = 0; i < num_tx && !d->nifp->ring_ofs[i]; i++) + ; + d->first_tx_ring = i; + for ( ; i < num_tx && d->nifp->ring_ofs[i]; i++) + ; + d->last_tx_ring = i - 1; + + num_rx = d->reg.nr_rx_rings + d->nifp->ni_host_rx_rings; + for (i = 0; i < num_rx && !d->nifp->ring_ofs[i + num_tx]; i++) + ; + d->first_rx_ring = i; + for ( ; i < num_rx && d->nifp->ring_ofs[i + num_tx]; i++) + ; + d->last_rx_ring = i - 1; + + d->mmap_done = 1; + + return 0; + +err: + nmctx_unlock(ctx); + nmport_undo_mmap(d); + return -1; +} + +void +nmport_undo_mmap(struct nmport_d *d) +{ + struct nmem_d *m; + struct nmctx *ctx = d->ctx; + + m = d->mem; + if (m == NULL) + return; + nmctx_lock(ctx); + m->refcount--; + if (m->refcount <= 0) { + if (!m->is_extmem && m->mem != MAP_FAILED) + munmap(m->mem, m->size); + /* extract from the list and free */ + if (m->next != NULL) + m->next->prev = m->prev; + if (m->prev != NULL) + m->prev->next = m->next; + else + ctx->mem_descs = m->next; + nmctx_free(ctx, m); + d->mem = NULL; + } + nmctx_unlock(ctx); + d->mmap_done = 0; + d->mem = NULL; + d->nifp = NULL; + d->first_tx_ring = 0; + d->last_tx_ring = 0; + d->first_rx_ring = 0; + d->last_rx_ring = 0; + d->cur_tx_ring = 0; + d->cur_rx_ring = 0; +} + +int +nmport_open_desc(struct nmport_d *d) +{ + if (nmport_register(d) < 0) + goto err; + + if (nmport_mmap(d) < 0) + goto err; + + return 0; +err: + nmport_undo_open_desc(d); + return -1; +} + +void +nmport_undo_open_desc(struct nmport_d *d) +{ + nmport_undo_mmap(d); + nmport_undo_register(d); +} + + +struct nmport_d * +nmport_open(const char *ifname) +{ + struct nmport_d *d; + + /* prepare the descriptor */ + d = nmport_prepare(ifname); + if (d == NULL) + goto err; + + /* open netmap and register */ + if (nmport_open_desc(d) < 0) + goto err; + + return d; + +err: + nmport_close(d); + return NULL; +} + +void +nmport_close(struct nmport_d *d) +{ + if (d == NULL) + return; + nmport_undo_open_desc(d); + nmport_undo_prepare(d); +} + +struct nmport_d * +nmport_clone(struct nmport_d *d) +{ + struct nmport_d *c; + struct nmctx *ctx; + + ctx = d->ctx; + + if (d->extmem != NULL && !d->register_done) { + errno = EINVAL; + nmctx_ferror(ctx, "cannot clone unregistered port that is using extmem"); + return NULL; + } + + c = nmport_new_with_ctx(ctx); + if (c == NULL) + return NULL; + /* copy the output of parse */ + c->hdr = d->hdr; + /* redirect the pointer to the body */ + c->hdr.nr_body = (uintptr_t)&c->reg; + /* options are not cloned */ + c->hdr.nr_options = 0; + c->reg = d->reg; /* this also copies the mem_id */ + /* put the new port in an un-registered, unmapped state */ + c->fd = -1; + c->nifp = NULL; + c->register_done = 0; + c->mem = NULL; + c->extmem = NULL; + c->mmap_done = 0; + c->first_tx_ring = 0; + c->last_tx_ring = 0; + c->first_rx_ring = 0; + c->last_rx_ring = 0; + c->cur_tx_ring = 0; + c->cur_rx_ring = 0; + + return c; +} + +int +nmport_inject(struct nmport_d *d, const void *buf, size_t size) +{ + u_int c, n = d->last_tx_ring - d->first_tx_ring + 1, + ri = d->cur_tx_ring; + + for (c = 0; c < n ; c++, ri++) { + /* compute current ring to use */ + struct netmap_ring *ring; + uint32_t i, j, idx; + size_t rem; + + if (ri > d->last_tx_ring) + ri = d->first_tx_ring; + ring = NETMAP_TXRING(d->nifp, ri); + rem = size; + j = ring->cur; + while (rem > ring->nr_buf_size && j != ring->tail) { + rem -= ring->nr_buf_size; + j = nm_ring_next(ring, j); + } + if (j == ring->tail && rem > 0) + continue; + i = ring->cur; + while (i != j) { + idx = ring->slot[i].buf_idx; + ring->slot[i].len = ring->nr_buf_size; + ring->slot[i].flags = NS_MOREFRAG; + nm_pkt_copy(buf, NETMAP_BUF(ring, idx), ring->nr_buf_size); + i = nm_ring_next(ring, i); + buf = (char *)buf + ring->nr_buf_size; + } + idx = ring->slot[i].buf_idx; + ring->slot[i].len = rem; + ring->slot[i].flags = 0; + nm_pkt_copy(buf, NETMAP_BUF(ring, idx), rem); + ring->head = ring->cur = nm_ring_next(ring, i); + d->cur_tx_ring = ri; + return size; + } + return 0; /* fail */ +} Property changes on: stable/12/lib/libnetmap/nmport.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12/lib/libnetmap/nmreq.c =================================================================== --- stable/12/lib/libnetmap/nmreq.c (nonexistent) +++ stable/12/lib/libnetmap/nmreq.c (revision 366013) @@ -0,0 +1,714 @@ +/*- + * 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define NMREQ_DEBUG +#ifdef NMREQ_DEBUG +#define NETMAP_WITH_LIBS +#define ED(...) D(__VA_ARGS__) +#else +#define ED(...) +/* an identifier is a possibly empty sequence of alphanum characters and + * underscores + */ +static int +nm_is_identifier(const char *s, const char *e) +{ + for (; s != e; s++) { + if (!isalnum(*s) && *s != '_') { + return 0; + } + } + + return 1; +} +#endif /* NMREQ_DEBUG */ + +#include +#define LIBNETMAP_NOTHREADSAFE +#include "libnetmap.h" + +void +nmreq_push_option(struct nmreq_header *h, struct nmreq_option *o) +{ + o->nro_next = h->nr_options; + h->nr_options = (uintptr_t)o; +} + +struct nmreq_prefix { + const char *prefix; /* the constant part of the prefix */ + size_t len; /* its strlen() */ + uint32_t flags; +#define NR_P_ID (1U << 0) /* whether an identifier is needed */ +#define NR_P_SKIP (1U << 1) /* whether the scope must be passed to netmap */ +#define NR_P_EMPTYID (1U << 2) /* whether an empty identifier is allowed */ +}; + +#define declprefix(prefix, flags) { (prefix), (sizeof(prefix) - 1), (flags) } + +static struct nmreq_prefix nmreq_prefixes[] = { + declprefix("netmap", NR_P_SKIP), + declprefix(NM_BDG_NAME, NR_P_ID|NR_P_EMPTYID), + { NULL } /* terminate the list */ +}; + +void +nmreq_header_init(struct nmreq_header *h, uint16_t reqtype, void *body) +{ + memset(h, 0, sizeof(*h)); + h->nr_version = NETMAP_API; + h->nr_reqtype = reqtype; + h->nr_body = (uintptr_t)body; +} + +int +nmreq_header_decode(const char **pifname, struct nmreq_header *h, struct nmctx *ctx) +{ + const char *scan = NULL; + const char *vpname = NULL; + const char *pipesep = NULL; + u_int namelen; + const char *ifname = *pifname; + struct nmreq_prefix *p; + + scan = ifname; + for (p = nmreq_prefixes; p->prefix != NULL; p++) { + if (!strncmp(scan, p->prefix, p->len)) + break; + } + if (p->prefix == NULL) { + nmctx_ferror(ctx, "%s: invalid request, prefix unknown or missing", *pifname); + goto fail; + } + scan += p->len; + + vpname = index(scan, ':'); + if (vpname == NULL) { + nmctx_ferror(ctx, "%s: missing ':'", ifname); + goto fail; + } + if (vpname != scan) { + /* there is an identifier, can we accept it? */ + if (!(p->flags & NR_P_ID)) { + nmctx_ferror(ctx, "%s: no identifier allowed between '%s' and ':'", *pifname, p->prefix); + goto fail; + } + + if (!nm_is_identifier(scan, vpname)) { + nmctx_ferror(ctx, "%s: invalid identifier '%.*s'", *pifname, vpname - scan, scan); + goto fail; + } + } else { + if ((p->flags & NR_P_ID) && !(p->flags & NR_P_EMPTYID)) { + nmctx_ferror(ctx, "%s: identifier is missing between '%s' and ':'", *pifname, p->prefix); + goto fail; + } + } + ++vpname; /* skip the colon */ + if (p->flags & NR_P_SKIP) + ifname = vpname; + scan = vpname; + + /* scan for a separator */ + for (; *scan && !index("-*^/@", *scan); scan++) + ; + + /* search for possible pipe indicators */ + for (pipesep = vpname; pipesep != scan && !index("{}", *pipesep); pipesep++) + ; + + if (!nm_is_identifier(vpname, pipesep)) { + nmctx_ferror(ctx, "%s: invalid port name '%.*s'", *pifname, + pipesep - vpname, vpname); + goto fail; + } + if (pipesep != scan) { + pipesep++; + if (*pipesep == '\0') { + nmctx_ferror(ctx, "%s: invalid empty pipe name", *pifname); + goto fail; + } + if (!nm_is_identifier(pipesep, scan)) { + nmctx_ferror(ctx, "%s: invalid pipe name '%.*s'", *pifname, scan - pipesep, pipesep); + goto fail; + } + } + + namelen = scan - ifname; + if (namelen >= sizeof(h->nr_name)) { + nmctx_ferror(ctx, "name '%.*s' too long", namelen, ifname); + goto fail; + } + if (namelen == 0) { + nmctx_ferror(ctx, "%s: invalid empty port name", *pifname); + goto fail; + } + + /* fill the header */ + memcpy(h->nr_name, ifname, namelen); + h->nr_name[namelen] = '\0'; + ED("name %s", h->nr_name); + + *pifname = scan; + + return 0; +fail: + errno = EINVAL; + return -1; +} + + +/* + * 0 not recognized + * -1 error + * >= 0 mem_id + */ +int32_t +nmreq_get_mem_id(const char **pifname, struct nmctx *ctx) +{ + int fd = -1; + struct nmreq_header gh; + struct nmreq_port_info_get gb; + const char *ifname; + + errno = 0; + ifname = *pifname; + + if (ifname == NULL) + goto fail; + + /* try to look for a netmap port with this name */ + fd = open("/dev/netmap", O_RDWR); + if (fd < 0) { + nmctx_ferror(ctx, "cannot open /dev/netmap: %s", strerror(errno)); + goto fail; + } + nmreq_header_init(&gh, NETMAP_REQ_PORT_INFO_GET, &gb); + if (nmreq_header_decode(&ifname, &gh, ctx) < 0) { + goto fail; + } + memset(&gb, 0, sizeof(gb)); + if (ioctl(fd, NIOCCTRL, &gh) < 0) { + nmctx_ferror(ctx, "cannot get info for '%s': %s", *pifname, strerror(errno)); + goto fail; + } + *pifname = ifname; + close(fd); + return gb.nr_mem_id; + +fail: + if (fd >= 0) + close(fd); + if (!errno) + errno = EINVAL; + return -1; +} + + +int +nmreq_register_decode(const char **pifname, struct nmreq_register *r, struct nmctx *ctx) +{ + enum { P_START, P_RNGSFXOK, P_GETNUM, P_FLAGS, P_FLAGSOK, P_MEMID, P_ONESW } p_state; + long num; + const char *scan = *pifname; + uint32_t nr_mode; + uint16_t nr_mem_id; + uint16_t nr_ringid; + uint64_t nr_flags; + + /* fill the request */ + + p_state = P_START; + /* defaults */ + nr_mode = NR_REG_ALL_NIC; /* default for no suffix */ + nr_mem_id = r->nr_mem_id; /* if non-zero, further updates are disabled */ + nr_ringid = 0; + nr_flags = 0; + while (*scan) { + switch (p_state) { + case P_START: + switch (*scan) { + case '^': /* only SW ring */ + nr_mode = NR_REG_SW; + p_state = P_ONESW; + break; + case '*': /* NIC and SW */ + nr_mode = NR_REG_NIC_SW; + p_state = P_RNGSFXOK; + break; + case '-': /* one NIC ring pair */ + nr_mode = NR_REG_ONE_NIC; + p_state = P_GETNUM; + break; + case '/': /* start of flags */ + p_state = P_FLAGS; + break; + case '@': /* start of memid */ + p_state = P_MEMID; + break; + default: + nmctx_ferror(ctx, "unknown modifier: '%c'", *scan); + goto fail; + } + scan++; + break; + case P_RNGSFXOK: + switch (*scan) { + case '/': + p_state = P_FLAGS; + break; + case '@': + p_state = P_MEMID; + break; + default: + nmctx_ferror(ctx, "unexpected character: '%c'", *scan); + goto fail; + } + scan++; + break; + case P_GETNUM: + if (!isdigit(*scan)) { + nmctx_ferror(ctx, "got '%s' while expecting a number", scan); + goto fail; + } + num = strtol(scan, (char **)&scan, 10); + if (num < 0 || num >= NETMAP_RING_MASK) { + nmctx_ferror(ctx, "'%ld' out of range [0, %d)", + num, NETMAP_RING_MASK); + goto fail; + } + nr_ringid = num & NETMAP_RING_MASK; + p_state = P_RNGSFXOK; + break; + case P_FLAGS: + case P_FLAGSOK: + switch (*scan) { + case '@': + p_state = P_MEMID; + scan++; + continue; + case 'x': + nr_flags |= NR_EXCLUSIVE; + break; + case 'z': + nr_flags |= NR_ZCOPY_MON; + break; + case 't': + nr_flags |= NR_MONITOR_TX; + break; + case 'r': + nr_flags |= NR_MONITOR_RX; + break; + case 'R': + nr_flags |= NR_RX_RINGS_ONLY; + break; + case 'T': + nr_flags |= NR_TX_RINGS_ONLY; + break; + default: + nmctx_ferror(ctx, "unrecognized flag: '%c'", *scan); + goto fail; + } + scan++; + p_state = P_FLAGSOK; + break; + case P_MEMID: + if (!isdigit(*scan)) { + scan--; /* escape to options */ + goto out; + } + num = strtol(scan, (char **)&scan, 10); + if (num <= 0) { + nmctx_ferror(ctx, "invalid mem_id: '%ld'", num); + goto fail; + } + if (nr_mem_id && nr_mem_id != num) { + nmctx_ferror(ctx, "invalid setting of mem_id to %ld (already set to %"PRIu16")", num, nr_mem_id); + goto fail; + } + nr_mem_id = num; + p_state = P_RNGSFXOK; + break; + case P_ONESW: + if (!isdigit(*scan)) { + p_state = P_RNGSFXOK; + } else { + nr_mode = NR_REG_ONE_SW; + p_state = P_GETNUM; + } + break; + } + } + if (p_state == P_MEMID && !*scan) { + nmctx_ferror(ctx, "invalid empty mem_id"); + goto fail; + } + if (p_state != P_START && p_state != P_RNGSFXOK && + p_state != P_FLAGSOK && p_state != P_MEMID && p_state != P_ONESW) { + nmctx_ferror(ctx, "unexpected end of request"); + goto fail; + } +out: + ED("flags: %s %s %s %s %s %s", + (nr_flags & NR_EXCLUSIVE) ? "EXCLUSIVE" : "", + (nr_flags & NR_ZCOPY_MON) ? "ZCOPY_MON" : "", + (nr_flags & NR_MONITOR_TX) ? "MONITOR_TX" : "", + (nr_flags & NR_MONITOR_RX) ? "MONITOR_RX" : "", + (nr_flags & NR_RX_RINGS_ONLY) ? "RX_RINGS_ONLY" : "", + (nr_flags & NR_TX_RINGS_ONLY) ? "TX_RINGS_ONLY" : ""); + r->nr_mode = nr_mode; + r->nr_ringid = nr_ringid; + r->nr_flags = nr_flags; + r->nr_mem_id = nr_mem_id; + *pifname = scan; + return 0; + +fail: + if (!errno) + errno = EINVAL; + return -1; +} + + +static int +nmreq_option_parsekeys(const char *prefix, char *body, struct nmreq_opt_parser *p, + struct nmreq_parse_ctx *pctx) +{ + char *scan; + char delim1; + struct nmreq_opt_key *k; + + scan = body; + delim1 = *scan; + while (delim1 != '\0') { + char *key, *value; + char delim; + size_t vlen; + + key = scan; + for ( scan++; *scan != '\0' && *scan != '=' && *scan != ','; scan++) { + if (*scan == '-') + *scan = '_'; + } + delim = *scan; + *scan = '\0'; + scan++; + for (k = p->keys; (k - p->keys) < NMREQ_OPT_MAXKEYS && k->key != NULL; + k++) { + if (!strcmp(k->key, key)) + goto found; + + } + nmctx_ferror(pctx->ctx, "unknown key: '%s'", key); + errno = EINVAL; + return -1; + found: + if (pctx->keys[k->id] != NULL) { + nmctx_ferror(pctx->ctx, "option '%s': duplicate key '%s', already set to '%s'", + prefix, key, pctx->keys[k->id]); + errno = EINVAL; + return -1; + } + value = scan; + for ( ; *scan != '\0' && *scan != ','; scan++) + ; + delim1 = *scan; + *scan = '\0'; + vlen = scan - value; + scan++; + if (delim == '=') { + pctx->keys[k->id] = (vlen ? value : NULL); + } else { + if (!(k->flags & NMREQ_OPTK_ALLOWEMPTY)) { + nmctx_ferror(pctx->ctx, "option '%s': missing '=value' for key '%s'", + prefix, key); + errno = EINVAL; + return -1; + } + pctx->keys[k->id] = key; + } + } + /* now check that all no-default keys have been assigned */ + for (k = p->keys; (k - p->keys) < NMREQ_OPT_MAXKEYS && k->key != NULL; k++) { + if ((k->flags & NMREQ_OPTK_MUSTSET) && pctx->keys[k->id] == NULL) { + nmctx_ferror(pctx->ctx, "option '%s': mandatory key '%s' not assigned", + prefix, k->key); + errno = EINVAL; + return -1; + } + } + return 0; +} + + +static int +nmreq_option_decode1(char *opt, struct nmreq_opt_parser *parsers, + void *token, struct nmctx *ctx) +{ + struct nmreq_opt_parser *p; + const char *prefix; + char *scan; + char delim; + struct nmreq_parse_ctx pctx; + int i; + + prefix = opt; + /* find the delimiter */ + for (scan = opt; *scan != '\0' && *scan != ':' && *scan != '='; scan++) + ; + delim = *scan; + *scan = '\0'; + scan++; + /* find the prefix */ + for (p = parsers; p != NULL; p = p->next) { + if (!strcmp(prefix, p->prefix)) + break; + } + if (p == NULL) { + nmctx_ferror(ctx, "unknown option: '%s'", prefix); + errno = EINVAL; + return -1; + } + if (p->flags & NMREQ_OPTF_DISABLED) { + nmctx_ferror(ctx, "option '%s' is not supported", prefix); + errno = EOPNOTSUPP; + return -1; + } + /* prepare the parse context */ + pctx.ctx = ctx; + pctx.token = token; + for (i = 0; i < NMREQ_OPT_MAXKEYS; i++) + pctx.keys[i] = NULL; + switch (delim) { + case '\0': + /* no body */ + if (!(p->flags & NMREQ_OPTF_ALLOWEMPTY)) { + nmctx_ferror(ctx, "syntax error: missing body after '%s'", + prefix); + errno = EINVAL; + return -1; + } + break; + case '=': /* the body goes to the default option key, if any */ + if (p->default_key < 0 || p->default_key >= NMREQ_OPT_MAXKEYS) { + nmctx_ferror(ctx, "syntax error: '=' not valid after '%s'", + prefix); + errno = EINVAL; + return -1; + } + if (*scan == '\0') { + nmctx_ferror(ctx, "missing value for option '%s'", prefix); + errno = EINVAL; + return -1; + } + pctx.keys[p->default_key] = scan; + break; + case ':': /* parse 'key=value' strings */ + if (nmreq_option_parsekeys(prefix, scan, p, &pctx) < 0) + return -1; + break; + } + return p->parse(&pctx); +} + +int +nmreq_options_decode(const char *opt, struct nmreq_opt_parser parsers[], + void *token, struct nmctx *ctx) +{ + const char *scan, *opt1; + char *w; + size_t len; + int ret; + + if (*opt == '\0') + return 0; /* empty list, OK */ + + if (*opt != '@') { + nmctx_ferror(ctx, "option list does not start with '@'"); + errno = EINVAL; + return -1; + } + + scan = opt; + do { + scan++; /* skip the plus */ + opt1 = scan; /* start of option */ + /* find the end of the option */ + for ( ; *scan != '\0' && *scan != '@'; scan++) + ; + len = scan - opt1; + if (len == 0) { + nmctx_ferror(ctx, "invalid empty option"); + errno = EINVAL; + return -1; + } + w = nmctx_malloc(ctx, len + 1); + if (w == NULL) { + nmctx_ferror(ctx, "out of memory"); + errno = ENOMEM; + return -1; + } + memcpy(w, opt1, len); + w[len] = '\0'; + ret = nmreq_option_decode1(w, parsers, token, ctx); + nmctx_free(ctx, w); + if (ret < 0) + return -1; + } while (*scan != '\0'); + + return 0; +} + +struct nmreq_option * +nmreq_find_option(struct nmreq_header *h, uint32_t t) +{ + struct nmreq_option *o; + + for (o = (struct nmreq_option *)h->nr_options; o != NULL; + o = (struct nmreq_option *)o->nro_next) { + if (o->nro_reqtype == t) + break; + } + return o; +} + +void +nmreq_remove_option(struct nmreq_header *h, struct nmreq_option *o) +{ + struct nmreq_option **nmo; + + for (nmo = (struct nmreq_option **)&h->nr_options; *nmo != NULL; + nmo = (struct nmreq_option **)&(*nmo)->nro_next) { + if (*nmo == o) { + *((uint64_t *)(*nmo)) = o->nro_next; + o->nro_next = (uint64_t)(uintptr_t)NULL; + break; + } + } +} + +void +nmreq_free_options(struct nmreq_header *h) +{ + struct nmreq_option *o, *next; + + for (o = (struct nmreq_option *)h->nr_options; o != NULL; o = next) { + next = (struct nmreq_option *)o->nro_next; + free(o); + } +} + +const char* +nmreq_option_name(uint32_t nro_reqtype) +{ + switch (nro_reqtype) { + case NETMAP_REQ_OPT_EXTMEM: + return "extmem"; + case NETMAP_REQ_OPT_SYNC_KLOOP_EVENTFDS: + return "sync-kloop-eventfds"; + case NETMAP_REQ_OPT_CSB: + return "csb"; + case NETMAP_REQ_OPT_SYNC_KLOOP_MODE: + return "sync-kloop-mode"; + default: + return "unknown"; + } +} + +#if 0 +#include +static void +nmreq_dump(struct nmport_d *d) +{ + printf("header:\n"); + printf(" nr_version: %"PRIu16"\n", d->hdr.nr_version); + printf(" nr_reqtype: %"PRIu16"\n", d->hdr.nr_reqtype); + printf(" nr_reserved: %"PRIu32"\n", d->hdr.nr_reserved); + printf(" nr_name: %s\n", d->hdr.nr_name); + printf(" nr_options: %lx\n", (unsigned long)d->hdr.nr_options); + printf(" nr_body: %lx\n", (unsigned long)d->hdr.nr_body); + printf("\n"); + printf("register (%p):\n", (void *)d->hdr.nr_body); + printf(" nr_mem_id: %"PRIu16"\n", d->reg.nr_mem_id); + printf(" nr_ringid: %"PRIu16"\n", d->reg.nr_ringid); + printf(" nr_mode: %lx\n", (unsigned long)d->reg.nr_mode); + printf(" nr_flags: %lx\n", (unsigned long)d->reg.nr_flags); + printf("\n"); + if (d->hdr.nr_options) { + struct nmreq_opt_extmem *e = (struct nmreq_opt_extmem *)d->hdr.nr_options; + printf("opt_extmem (%p):\n", e); + printf(" nro_opt.nro_next: %lx\n", (unsigned long)e->nro_opt.nro_next); + printf(" nro_opt.nro_reqtype: %"PRIu32"\n", e->nro_opt.nro_reqtype); + printf(" nro_usrptr: %lx\n", (unsigned long)e->nro_usrptr); + printf(" nro_info.nr_memsize %"PRIu64"\n", e->nro_info.nr_memsize); + } + printf("\n"); + printf("mem (%p):\n", d->mem); + printf(" refcount: %d\n", d->mem->refcount); + printf(" mem: %p\n", d->mem->mem); + printf(" size: %zu\n", d->mem->size); + printf("\n"); + printf("rings:\n"); + printf(" tx: [%d, %d]\n", d->first_tx_ring, d->last_tx_ring); + printf(" rx: [%d, %d]\n", d->first_rx_ring, d->last_rx_ring); +} +int +main(int argc, char *argv[]) +{ + struct nmport_d *d; + + if (argc < 2) { + fprintf(stderr, "usage: %s netmap-expr\n", argv[0]); + return 1; + } + + d = nmport_open(argv[1]); + if (d != NULL) { + nmreq_dump(d); + nmport_close(d); + } + + return 0; +} +#endif Property changes on: stable/12/lib/libnetmap/nmreq.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12/lib/libnetmap/Makefile =================================================================== --- stable/12/lib/libnetmap/Makefile (nonexistent) +++ stable/12/lib/libnetmap/Makefile (revision 366013) @@ -0,0 +1,16 @@ +# +# $FreeBSD$ +# + +.include + +PACKAGE= lib${LIB} +LIB= netmap +SRCS= nmctx.c nmport.c \ + nmctx-pthreads.c nmreq.c +INCS= libnetmap.h +#MAN= libnetmap.3 +CFLAGS+= -I${SRCTOP}/sys/net -I${.CURDIR} +WARNS?= 2 + +.include Property changes on: stable/12/lib/libnetmap/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12/lib/libnetmap/libnetmap.h =================================================================== --- stable/12/lib/libnetmap/libnetmap.h (nonexistent) +++ stable/12/lib/libnetmap/libnetmap.h (revision 366013) @@ -0,0 +1,660 @@ +/*- + * 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. + * $FreeBSD$ + */ + +#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 + +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. + * + */ + + +/* 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); + + +/* 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 the + parser 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 *)((h_)->nr_options);\ + (o_) != NULL;\ + (o_) = (struct nmreq_option *)((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_NOTHREADSAFE + extern 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_ */ Property changes on: stable/12/lib/libnetmap/libnetmap.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/12/share/mk/bsd.libnames.mk =================================================================== --- stable/12/share/mk/bsd.libnames.mk (revision 366012) +++ stable/12/share/mk/bsd.libnames.mk (revision 366013) @@ -1,216 +1,217 @@ # $FreeBSD$ # The include file define library names. # Other include files (e.g. bsd.prog.mk, bsd.lib.mk) include this # file where necessary. .if !target(____) .error bsd.libnames.mk cannot be included directly. .endif LIBDESTDIR= ${SYSROOT:U${DESTDIR}} .sinclude # Src directory locations are also defined in src.libnames.mk. LIBCRT0?= ${LIBDESTDIR}${LIBDIR_BASE}/crt0.o LIB80211?= ${LIBDESTDIR}${LIBDIR_BASE}/lib80211.a LIBALIAS?= ${LIBDESTDIR}${LIBDIR_BASE}/libalias.a LIBARCHIVE?= ${LIBDESTDIR}${LIBDIR_BASE}/libarchive.a LIBASN1?= ${LIBDESTDIR}${LIBDIR_BASE}/libasn1.a LIBATM?= ${LIBDESTDIR}${LIBDIR_BASE}/libatm.a LIBAUDITD?= ${LIBDESTDIR}${LIBDIR_BASE}/libauditd.a LIBAVL?= ${LIBDESTDIR}${LIBDIR_BASE}/libavl.a LIBBE?= ${LIBDESTDIR}${LIBDIR_BASE}/libbe.a LIBBEGEMOT?= ${LIBDESTDIR}${LIBDIR_BASE}/libbegemot.a LIBBLACKLIST?= ${LIBDESTDIR}${LIBDIR_BASE}/libblacklist.a LIBBLUETOOTH?= ${LIBDESTDIR}${LIBDIR_BASE}/libbluetooth.a LIBBSDXML?= ${LIBDESTDIR}${LIBDIR_BASE}/libbsdxml.a LIBBSM?= ${LIBDESTDIR}${LIBDIR_BASE}/libbsm.a LIBBSNMP?= ${LIBDESTDIR}${LIBDIR_BASE}/libbsnmp.a LIBBZ2?= ${LIBDESTDIR}${LIBDIR_BASE}/libbz2.a LIBC?= ${LIBDESTDIR}${LIBDIR_BASE}/libc.a LIBCALENDAR?= ${LIBDESTDIR}${LIBDIR_BASE}/libcalendar.a LIBCAM?= ${LIBDESTDIR}${LIBDIR_BASE}/libcam.a LIBCOMPAT?= ${LIBDESTDIR}${LIBDIR_BASE}/libcompat.a LIBCOMPILER_RT?=${LIBDESTDIR}${LIBDIR_BASE}/libcompiler_rt.a LIBCOM_ERR?= ${LIBDESTDIR}${LIBDIR_BASE}/libcom_err.a LIBCPLUSPLUS?= ${LIBDESTDIR}${LIBDIR_BASE}/libc++.a LIBCRYPT?= ${LIBDESTDIR}${LIBDIR_BASE}/libcrypt.a LIBCRYPTO?= ${LIBDESTDIR}${LIBDIR_BASE}/libcrypto.a LIBCTF?= ${LIBDESTDIR}${LIBDIR_BASE}/libctf.a LIBCURSES?= ${LIBDESTDIR}${LIBDIR_BASE}/libcurses.a LIBCUSE?= ${LIBDESTDIR}${LIBDIR_BASE}/libcuse.a LIBCXGB4?= ${LIBDESTDIR}${LIBDIR_BASE}/libcxgb4.a LIBCXXRT?= ${LIBDESTDIR}${LIBDIR_BASE}/libcxxrt.a LIBC_PIC?= ${LIBDESTDIR}${LIBDIR_BASE}/libc_pic.a LIBDEVCTL?= ${LIBDESTDIR}${LIBDIR_BASE}/libdevctl.a LIBDEVDCTL?= ${LIBDESTDIR}${LIBDIR_BASE}/libdevdctl.a LIBDEVINFO?= ${LIBDESTDIR}${LIBDIR_BASE}/libdevinfo.a LIBDEVSTAT?= ${LIBDESTDIR}${LIBDIR_BASE}/libdevstat.a LIBDIALOG?= ${LIBDESTDIR}${LIBDIR_BASE}/libdialog.a LIBDL?= ${LIBDESTDIR}${LIBDIR_BASE}/libdl.a LIBDNS?= ${LIBDESTDIR}${LIBDIR_BASE}/libdns.a LIBDPV?= ${LIBDESTDIR}${LIBDIR_BASE}/libdpv.a LIBDTRACE?= ${LIBDESTDIR}${LIBDIR_BASE}/libdtrace.a LIBDWARF?= ${LIBDESTDIR}${LIBDIR_BASE}/libdwarf.a LIBEDIT?= ${LIBDESTDIR}${LIBDIR_BASE}/libedit.a LIBEFIVAR?= ${LIBDESTDIR}${LIBDIR_BASE}/libefivar.a LIBELF?= ${LIBDESTDIR}${LIBDIR_BASE}/libelf.a LIBEXECINFO?= ${LIBDESTDIR}${LIBDIR_BASE}/libexecinfo.a LIBFETCH?= ${LIBDESTDIR}${LIBDIR_BASE}/libfetch.a LIBFIGPAR?= ${LIBDESTDIR}${LIBDIR_BASE}/libfigpar.a LIBFL?= "don't use LIBFL, use LIBL" LIBFORM?= ${LIBDESTDIR}${LIBDIR_BASE}/libform.a LIBG2C?= ${LIBDESTDIR}${LIBDIR_BASE}/libg2c.a LIBGEOM?= ${LIBDESTDIR}${LIBDIR_BASE}/libgeom.a LIBGNUREGEX?= ${LIBDESTDIR}${LIBDIR_BASE}/libgnuregex.a LIBGPIO?= ${LIBDESTDIR}${LIBDIR_BASE}/libgpio.a LIBGSSAPI?= ${LIBDESTDIR}${LIBDIR_BASE}/libgssapi.a LIBGSSAPI_KRB5?= ${LIBDESTDIR}${LIBDIR_BASE}/libgssapi_krb5.a LIBHDB?= ${LIBDESTDIR}${LIBDIR_BASE}/libhdb.a LIBHEIMBASE?= ${LIBDESTDIR}${LIBDIR_BASE}/libheimbase.a LIBHEIMNTLM?= ${LIBDESTDIR}${LIBDIR_BASE}/libheimntlm.a LIBHEIMSQLITE?= ${LIBDESTDIR}${LIBDIR_BASE}/libheimsqlite.a LIBHX509?= ${LIBDESTDIR}${LIBDIR_BASE}/libhx509.a LIBIBCM?= ${LIBDESTDIR}${LIBDIR_BASE}/libibcm.a LIBIBMAD?= ${LIBDESTDIR}${LIBDIR_BASE}/libibmad.a LIBIBNETDISC?= ${LIBDESTDIR}${LIBDIR_BASE}/libibnetdisc.a LIBIBUMAD?= ${LIBDESTDIR}${LIBDIR_BASE}/libibumad.a LIBIBVERBS?= ${LIBDESTDIR}${LIBDIR_BASE}/libibverbs.a LIBIFCONFIG?= ${LIBDESTDIR}${LIBDIR_BASE}/libifconfig.a LIBIPSEC?= ${LIBDESTDIR}${LIBDIR_BASE}/libipsec.a LIBIPT?= ${LIBDESTDIR}${LIBDIR_BASE}/libipt.a LIBJAIL?= ${LIBDESTDIR}${LIBDIR_BASE}/libjail.a LIBKADM5CLNT?= ${LIBDESTDIR}${LIBDIR_BASE}/libkadm5clnt.a LIBKADM5SRV?= ${LIBDESTDIR}${LIBDIR_BASE}/libkadm5srv.a LIBKAFS5?= ${LIBDESTDIR}${LIBDIR_BASE}/libkafs5.a LIBKDC?= ${LIBDESTDIR}${LIBDIR_BASE}/libkdc.a LIBKEYCAP?= ${LIBDESTDIR}${LIBDIR_BASE}/libkeycap.a LIBKICONV?= ${LIBDESTDIR}${LIBDIR_BASE}/libkiconv.a LIBKRB5?= ${LIBDESTDIR}${LIBDIR_BASE}/libkrb5.a LIBKVM?= ${LIBDESTDIR}${LIBDIR_BASE}/libkvm.a LIBL?= ${LIBDESTDIR}${LIBDIR_BASE}/libl.a LIBLN?= "don't use LIBLN, use LIBL" LIBLZMA?= ${LIBDESTDIR}${LIBDIR_BASE}/liblzma.a LIBM?= ${LIBDESTDIR}${LIBDIR_BASE}/libm.a LIBMAGIC?= ${LIBDESTDIR}${LIBDIR_BASE}/libmagic.a LIBMD?= ${LIBDESTDIR}${LIBDIR_BASE}/libmd.a LIBMEMSTAT?= ${LIBDESTDIR}${LIBDIR_BASE}/libmemstat.a LIBMENU?= ${LIBDESTDIR}${LIBDIR_BASE}/libmenu.a LIBMILTER?= ${LIBDESTDIR}${LIBDIR_BASE}/libmilter.a LIBMLX4?= ${LIBDESTDIR}${LIBDIR_BASE}/libmlx4.a LIBMLX5?= ${LIBDESTDIR}${LIBDIR_BASE}/libmlx5.a LIBMP?= ${LIBDESTDIR}${LIBDIR_BASE}/libmp.a LIBMT?= ${LIBDESTDIR}${LIBDIR_BASE}/libmt.a LIBNANDFS?= ${LIBDESTDIR}${LIBDIR_BASE}/libnandfs.a LIBNCURSES?= ${LIBDESTDIR}${LIBDIR_BASE}/libncurses.a LIBNCURSESW?= ${LIBDESTDIR}${LIBDIR_BASE}/libncursesw.a LIBNETGRAPH?= ${LIBDESTDIR}${LIBDIR_BASE}/libnetgraph.a +LIBNETMAP?= ${LIBDESTDIR}${LIBDIR_BASE}/libnetmap.a LIBNGATM?= ${LIBDESTDIR}${LIBDIR_BASE}/libngatm.a LIBNV?= ${LIBDESTDIR}${LIBDIR_BASE}/libnv.a LIBNVPAIR?= ${LIBDESTDIR}${LIBDIR_BASE}/libnvpair.a LIBOPENCSD?= ${LIBDESTDIR}${LIBDIR_BASE}/libopencsd.a LIBOPENSM?= ${LIBDESTDIR}${LIBDIR_BASE}/libopensm.a LIBOPIE?= ${LIBDESTDIR}${LIBDIR_BASE}/libopie.a LIBOSMCOMP?= ${LIBDESTDIR}${LIBDIR_BASE}/libosmcomp.a LIBOSMVENDOR?= ${LIBDESTDIR}${LIBDIR_BASE}/libosmvendor.a LIBPAM?= ${LIBDESTDIR}${LIBDIR_BASE}/libpam.a LIBPANEL?= ${LIBDESTDIR}${LIBDIR_BASE}/libpanel.a LIBPANELW?= ${LIBDESTDIR}${LIBDIR_BASE}/libpanelw.a LIBPCAP?= ${LIBDESTDIR}${LIBDIR_BASE}/libpcap.a LIBPJDLOG?= ${LIBDESTDIR}${LIBDIR_BASE}/libpjdlog.a LIBPMC?= ${LIBDESTDIR}${LIBDIR_BASE}/libpmc.a LIBPROC?= ${LIBDESTDIR}${LIBDIR_BASE}/libproc.a LIBPROCSTAT?= ${LIBDESTDIR}${LIBDIR_BASE}/libprocstat.a LIBPTHREAD?= ${LIBDESTDIR}${LIBDIR_BASE}/libpthread.a LIBRADIUS?= ${LIBDESTDIR}${LIBDIR_BASE}/libradius.a LIBRDMACM?= ${LIBDESTDIR}${LIBDIR_BASE}/librdmacm.a LIBREGEX?= ${LIBDESTDIR}${LIBDIR_BASE}/libregex.a LIBROKEN?= ${LIBDESTDIR}${LIBDIR_BASE}/libroken.a LIBRPCSEC_GSS?= ${LIBDESTDIR}${LIBDIR_BASE}/librpcsec_gss.a LIBRPCSVC?= ${LIBDESTDIR}${LIBDIR_BASE}/librpcsvc.a LIBRT?= ${LIBDESTDIR}${LIBDIR_BASE}/librt.a LIBRTLD_DB?= ${LIBDESTDIR}${LIBDIR_BASE}/librtld_db.a LIBSBUF?= ${LIBDESTDIR}${LIBDIR_BASE}/libsbuf.a LIBSDP?= ${LIBDESTDIR}${LIBDIR_BASE}/libsdp.a LIBSMB?= ${LIBDESTDIR}${LIBDIR_BASE}/libsmb.a LIBSSL?= ${LIBDESTDIR}${LIBDIR_BASE}/libssl.a LIBSSP_NONSHARED?= ${LIBDESTDIR}${LIBDIR_BASE}/libssp_nonshared.a LIBSTDCPLUSPLUS?= ${LIBDESTDIR}${LIBDIR_BASE}/libstdc++.a LIBSTDTHREADS?= ${LIBDESTDIR}${LIBDIR_BASE}/libstdthreads.a LIBSYSDECODE?= ${LIBDESTDIR}${LIBDIR_BASE}/libsysdecode.a LIBTACPLUS?= ${LIBDESTDIR}${LIBDIR_BASE}/libtacplus.a LIBTERMCAP?= ${LIBDESTDIR}${LIBDIR_BASE}/libtermcap.a LIBTERMCAPW?= ${LIBDESTDIR}${LIBDIR_BASE}/libtermcapw.a LIBTERMLIB?= "don't use LIBTERMLIB, use LIBTERMCAP" LIBTINFO?= "don't use LIBTINFO, use LIBNCURSES" LIBUFS?= ${LIBDESTDIR}${LIBDIR_BASE}/libufs.a LIBUGIDFW?= ${LIBDESTDIR}${LIBDIR_BASE}/libugidfw.a LIBULOG?= ${LIBDESTDIR}${LIBDIR_BASE}/libulog.a LIBUMEM?= ${LIBDESTDIR}${LIBDIR_BASE}/libumem.a LIBUSB?= ${LIBDESTDIR}${LIBDIR_BASE}/libusb.a LIBUSBHID?= ${LIBDESTDIR}${LIBDIR_BASE}/libusbhid.a LIBUTIL?= ${LIBDESTDIR}${LIBDIR_BASE}/libutil.a LIBUUTIL?= ${LIBDESTDIR}${LIBDIR_BASE}/libuutil.a LIBVGL?= ${LIBDESTDIR}${LIBDIR_BASE}/libvgl.a LIBVMMAPI?= ${LIBDESTDIR}${LIBDIR_BASE}/libvmmapi.a LIBWIND?= ${LIBDESTDIR}${LIBDIR_BASE}/libwind.a LIBWRAP?= ${LIBDESTDIR}${LIBDIR_BASE}/libwrap.a LIBXO?= ${LIBDESTDIR}${LIBDIR_BASE}/libxo.a LIBXPG4?= ${LIBDESTDIR}${LIBDIR_BASE}/libxpg4.a LIBY?= ${LIBDESTDIR}${LIBDIR_BASE}/liby.a LIBYPCLNT?= ${LIBDESTDIR}${LIBDIR_BASE}/libypclnt.a LIBZ?= ${LIBDESTDIR}${LIBDIR_BASE}/libz.a LIBZFS?= ${LIBDESTDIR}${LIBDIR_BASE}/libzfs.a LIBZFS_CORE?= ${LIBDESTDIR}${LIBDIR_BASE}/libzfs_core.a LIBZPOOL?= ${LIBDESTDIR}${LIBDIR_BASE}/libzpool.a # enforce the 2 -lpthread and -lc to always be the last in that exact order .if defined(LDADD) .if ${LDADD:M-lpthread} LDADD:= ${LDADD:N-lpthread} -lpthread .endif .if ${LDADD:M-lc} LDADD:= ${LDADD:N-lc} -lc .endif .endif # Only do this for src builds. .if defined(SRCTOP) .if defined(_LIBRARIES) && defined(LIB) && \ ${_LIBRARIES:M${LIB}} != "" .if !defined(LIB${LIB:tu}) .error ${.CURDIR}: Missing value for LIB${LIB:tu} in ${_this:T}. Likely should be: LIB${LIB:tu}?= $${LIBDESTDIR}$${LIBDIR_BASE}/lib${LIB}.a .endif .endif # Derive LIB*SRCDIR from LIB*DIR .for lib in ${_LIBRARIES} LIB${lib:tu}SRCDIR?= ${SRCTOP}/${LIB${lib:tu}DIR:S,^${OBJTOP}/,,} .endfor .else # Out of tree builds # There are LIBADD defined in an out-of-tree build. Are they *all* # in-tree libraries? If so convert them to LDADD to support # partial checkouts. .if !empty(LIBADD) _convert_libadd= 1 .for l in ${LIBADD} .if empty(LIB${l:tu}) _convert_libadd= 0 .endif .endfor .if ${_convert_libadd} == 1 .warning Converting out-of-tree build LIBADDs into LDADD. This is not fully supported. .for l in ${LIBADD} LDADD+= -l${l} .endfor .endif .endif .endif # defined(SRCTOP) Index: stable/12/share/mk/src.libnames.mk =================================================================== --- stable/12/share/mk/src.libnames.mk (revision 366012) +++ stable/12/share/mk/src.libnames.mk (revision 366013) @@ -1,659 +1,661 @@ # $FreeBSD$ # # The include file define library names suitable # for INTERNALLIB and PRIVATELIB definition .if !target(____) .error src.libnames.mk cannot be included directly. .endif .if !target(____) ____: .include _PRIVATELIBS= \ atf_c \ atf_cxx \ bsdstat \ devdctl \ event \ gmock \ gtest \ gmock_main \ gtest_main \ heimipcc \ heimipcs \ ifconfig \ ldns \ sqlite3 \ ssh \ ucl \ unbound \ zstd _INTERNALLIBS= \ amu \ bsnmptools \ c_nossp_pic \ cron \ elftc \ fifolog \ ipf \ lpr \ lua \ netbsd \ ntp \ ntpevent \ openbsd \ opts \ parse \ pe \ pmcstat \ sl \ sm \ smdb \ smutil \ telnet \ vers _LIBRARIES= \ ${_PRIVATELIBS} \ ${_INTERNALLIBS} \ ${LOCAL_LIBRARIES} \ 80211 \ alias \ archive \ asn1 \ auditd \ avl \ be \ begemot \ bluetooth \ bsdxml \ bsm \ bsnmp \ bz2 \ c \ c_pic \ calendar \ cam \ casper \ cap_dns \ cap_grp \ cap_pwd \ cap_random \ cap_sysctl \ cap_syslog \ com_err \ compiler_rt \ crypt \ crypto \ ctf \ cuse \ cxxrt \ devctl \ devdctl \ devinfo \ devstat \ dialog \ dl \ dpv \ dtrace \ dwarf \ edit \ efivar \ elf \ execinfo \ fetch \ figpar \ geom \ gnuregex \ gpio \ gssapi \ gssapi_krb5 \ hdb \ heimbase \ heimntlm \ heimsqlite \ hx509 \ ipsec \ ipt \ jail \ kadm5clnt \ kadm5srv \ kafs5 \ kdc \ kiconv \ krb5 \ kvm \ l \ lzma \ m \ magic \ md \ memstat \ mp \ mt \ nandfs \ ncurses \ ncursesw \ netgraph \ + netmap \ ngatm \ nv \ nvpair \ opencsd \ opie \ pam \ panel \ panelw \ pcap \ pcsclite \ pjdlog \ pmc \ proc \ procstat \ pthread \ radius \ regex \ roken \ rpcsec_gss \ rpcsvc \ rt \ rtld_db \ sbuf \ sdp \ sm \ smb \ ssl \ ssp_nonshared \ stdthreads \ supcplusplus \ sysdecode \ tacplus \ termcap \ termcapw \ ufs \ ugidfw \ ulog \ umem \ usb \ usbhid \ util \ uutil \ vmmapi \ wind \ wrap \ xo \ y \ ypclnt \ z \ zfs_core \ zfs \ zpool \ .if ${MK_BLACKLIST} != "no" _LIBRARIES+= \ blacklist \ .endif .if ${MK_OFED} != "no" _LIBRARIES+= \ cxgb4 \ ibcm \ ibmad \ ibnetdisc \ ibumad \ ibverbs \ mlx4 \ mlx5 \ rdmacm \ osmcomp \ opensm \ osmvendor .endif .if ${MK_BEARSSL} == "yes" _LIBRARIES+= \ bearssl \ secureboot \ LIBBEARSSL?= ${LIBBEARSSLDIR}/libbearssl.a LIBSECUREBOOT?= ${LIBSECUREBOOTDIR}/libsecureboot.a .endif .if ${MK_VERIEXEC} == "yes" _LIBRARIES+= veriexec LIBVERIEXEC?= ${LIBVERIEXECDIR}/libveriexec.a .endif # Each library's LIBADD needs to be duplicated here for static linkage of # 2nd+ order consumers. Auto-generating this would be better. _DP_80211= sbuf bsdxml _DP_archive= z bz2 lzma bsdxml _DP_zstd= pthread .if ${MK_BLACKLIST} != "no" _DP_blacklist+= pthread .endif _DP_crypto= pthread .if ${MK_OPENSSL} != "no" _DP_archive+= crypto .else _DP_archive+= md .endif _DP_sqlite3= pthread _DP_ssl= crypto _DP_ssh= crypto crypt z .if ${MK_LDNS} != "no" _DP_ssh+= ldns .endif _DP_edit= ncursesw .if ${MK_OPENSSL} != "no" _DP_bsnmp= crypto .endif _DP_geom= bsdxml sbuf _DP_cam= sbuf _DP_kvm= elf _DP_casper= nv _DP_cap_dns= nv _DP_cap_grp= nv _DP_cap_pwd= nv _DP_cap_random= nv _DP_cap_sysctl= nv _DP_cap_syslog= nv .if ${MK_OFED} != "no" _DP_pcap= ibverbs mlx5 .endif _DP_pjdlog= util _DP_opie= md _DP_usb= pthread _DP_unbound= ssl crypto pthread _DP_rt= pthread .if ${MK_OPENSSL} == "no" _DP_radius= md .else _DP_radius= crypto .endif _DP_rtld_db= elf procstat _DP_procstat= kvm util elf .if ${MK_CXX} == "yes" .if ${MK_LIBCPLUSPLUS} != "no" _DP_proc= cxxrt .else _DP_proc= supcplusplus .endif .endif .if ${MK_CDDL} != "no" _DP_proc+= ctf .endif _DP_proc+= elf procstat rtld_db util _DP_mp= crypto _DP_memstat= kvm _DP_magic= z _DP_mt= sbuf bsdxml _DP_ldns= ssl crypto _DP_lua= m .if ${MK_OPENSSL} != "no" _DP_fetch= ssl crypto .else _DP_fetch= md .endif _DP_execinfo= elf _DP_dwarf= elf _DP_dpv= dialog figpar util ncursesw _DP_dialog= ncursesw m _DP_cuse= pthread _DP_atf_cxx= atf_c _DP_gtest= pthread _DP_gmock= gtest _DP_gmock_main= gmock _DP_gtest_main= gtest _DP_devstat= kvm _DP_pam= radius tacplus opie md util .if ${MK_KERBEROS} != "no" _DP_pam+= krb5 .endif .if ${MK_OPENSSH} != "no" _DP_pam+= ssh .endif .if ${MK_NIS} != "no" _DP_pam+= ypclnt .endif _DP_roken= crypt _DP_kadm5clnt= com_err krb5 roken _DP_kadm5srv= com_err hdb krb5 roken _DP_heimntlm= crypto com_err krb5 roken _DP_hx509= asn1 com_err crypto roken wind _DP_hdb= asn1 com_err krb5 roken sqlite3 _DP_asn1= com_err roken _DP_kdc= roken hdb hx509 krb5 heimntlm asn1 crypto _DP_wind= com_err roken _DP_heimbase= pthread _DP_heimipcc= heimbase roken pthread _DP_heimipcs= heimbase roken pthread _DP_kafs5= asn1 krb5 roken _DP_krb5+= asn1 com_err crypt crypto hx509 roken wind heimbase heimipcc _DP_gssapi_krb5+= gssapi krb5 crypto roken asn1 com_err _DP_lzma= md pthread _DP_ucl= m _DP_vmmapi= util _DP_opencsd= cxxrt _DP_ctf= z _DP_dtrace= ctf elf proc pthread rtld_db _DP_xo= util # The libc dependencies are not strictly needed but are defined to make the # assert happy. _DP_c= compiler_rt .if ${MK_SSP} != "no" _DP_c+= ssp_nonshared .endif _DP_stdthreads= pthread _DP_tacplus= md _DP_panel= ncurses _DP_panelw= ncursesw _DP_rpcsec_gss= gssapi _DP_smb= kiconv _DP_ulog= md _DP_fifolog= z _DP_ipf= kvm _DP_zfs= md pthread umem util uutil m nvpair avl bsdxml geom nvpair z \ zfs_core _DP_zfs_core= nvpair _DP_zpool= md pthread z nvpair avl umem _DP_be= zfs nvpair +_DP_netmap= # OFED support .if ${MK_OFED} != "no" _DP_cxgb4= ibverbs pthread _DP_ibcm= ibverbs _DP_ibmad= ibumad _DP_ibnetdisc= osmcomp ibmad ibumad _DP_ibumad= _DP_ibverbs= _DP_mlx4= ibverbs pthread _DP_mlx5= ibverbs pthread _DP_rdmacm= ibverbs _DP_osmcomp= pthread _DP_opensm= pthread _DP_osmvendor= ibumad pthread .endif # Define special cases LDADD_supcplusplus= -lsupc++ LIBATF_C= ${LIBDESTDIR}${LIBDIR_BASE}/libprivateatf-c.a LIBATF_CXX= ${LIBDESTDIR}${LIBDIR_BASE}/libprivateatf-c++.a LDADD_atf_c= -lprivateatf-c LDADD_atf_cxx= -lprivateatf-c++ LIBGMOCK= ${LIBDESTDIR}${LIBDIR_BASE}/libprivategmock.a LIBGMOCK_MAIN= ${LIBDESTDIR}${LIBDIR_BASE}/libprivategmock_main.a LIBGTEST= ${LIBDESTDIR}${LIBDIR_BASE}/libprivategtest.a LIBGTEST_MAIN= ${LIBDESTDIR}${LIBDIR_BASE}/libprivategtest_main.a LDADD_gmock= -lprivategmock LDADD_gtest= -lprivategtest LDADD_gmock_main= -lprivategmock_main LDADD_gtest_main= -lprivategtest_main .for _l in ${_PRIVATELIBS} LIB${_l:tu}?= ${LIBDESTDIR}${LIBDIR_BASE}/libprivate${_l}.a .endfor .if ${MK_PIE} != "no" PIE_SUFFIX= _pie .endif .for _l in ${_LIBRARIES} .if ${_INTERNALLIBS:M${_l}} || !defined(SYSROOT) LDADD_${_l}_L+= -L${LIB${_l:tu}DIR} .endif DPADD_${_l}?= ${LIB${_l:tu}} .if ${_PRIVATELIBS:M${_l}} LDADD_${_l}?= -lprivate${_l} .elif ${_INTERNALLIBS:M${_l}} LDADD_${_l}?= ${LDADD_${_l}_L} -l${_l:S/${PIE_SUFFIX}//}${PIE_SUFFIX} .else LDADD_${_l}?= ${LDADD_${_l}_L} -l${_l} .endif # Add in all dependencies for static linkage. .if defined(_DP_${_l}) && (${_INTERNALLIBS:M${_l}} || \ (defined(NO_SHARED) && ${NO_SHARED:tl} != "no")) .for _d in ${_DP_${_l}} DPADD_${_l}+= ${DPADD_${_d}} LDADD_${_l}+= ${LDADD_${_d}} .endfor .endif .endfor # These are special cases where the library is broken and anything that uses # it needs to add more dependencies. Broken usually means that it has a # cyclic dependency and cannot link its own dependencies. This is bad, please # fix the library instead. # Unless the library itself is broken then the proper place to define # dependencies is _DP_* above. # libatf-c++ exposes libatf-c abi hence we need to explicit link to atf_c for # atf_cxx DPADD_atf_cxx+= ${DPADD_atf_c} LDADD_atf_cxx+= ${LDADD_atf_c} DPADD_gmock+= ${DPADD_gtest} LDADD_gmock+= ${LDADD_gtest} DPADD_gmock_main+= ${DPADD_gmock} LDADD_gmock_main+= ${LDADD_gmock} DPADD_gtest_main+= ${DPADD_gtest} LDADD_gtest_main+= ${LDADD_gtest} # Detect LDADD/DPADD that should be LIBADD, before modifying LDADD here. _BADLDADD= .for _l in ${LDADD:M-l*:N-l*/*:C,^-l,,} .if ${_LIBRARIES:M${_l}} && !${_PRIVATELIBS:M${_l}} _BADLDADD+= ${_l} .endif .endfor .if !empty(_BADLDADD) .error ${.CURDIR}: These libraries should be LIBADD+=foo rather than DPADD/LDADD+=-lfoo: ${_BADLDADD} .endif .for _l in ${LIBADD} DPADD+= ${DPADD_${_l}} LDADD+= ${LDADD_${_l}} .endfor # INTERNALLIB definitions. LIBELFTCDIR= ${OBJTOP}/lib/libelftc LIBELFTC?= ${LIBELFTCDIR}/libelftc${PIE_SUFFIX}.a LIBLUADIR= ${OBJTOP}/lib/liblua LIBLUA?= ${LIBLUADIR}/liblua${PIE_SUFFIX}.a LIBPEDIR= ${OBJTOP}/lib/libpe LIBPE?= ${LIBPEDIR}/libpe${PIE_SUFFIX}.a LIBOPENBSDDIR= ${OBJTOP}/lib/libopenbsd LIBOPENBSD?= ${LIBOPENBSDDIR}/libopenbsd${PIE_SUFFIX}.a LIBSMDIR= ${OBJTOP}/lib/libsm LIBSM?= ${LIBSMDIR}/libsm${PIE_SUFFIX}.a LIBSMDBDIR= ${OBJTOP}/lib/libsmdb LIBSMDB?= ${LIBSMDBDIR}/libsmdb${PIE_SUFFIX}.a LIBSMUTILDIR= ${OBJTOP}/lib/libsmutil LIBSMUTIL?= ${LIBSMUTILDIR}/libsmutil${PIE_SUFFIX}.a LIBNETBSDDIR?= ${OBJTOP}/lib/libnetbsd LIBNETBSD?= ${LIBNETBSDDIR}/libnetbsd${PIE_SUFFIX}.a LIBVERSDIR?= ${OBJTOP}/kerberos5/lib/libvers LIBVERS?= ${LIBVERSDIR}/libvers${PIE_SUFFIX}.a LIBSLDIR= ${OBJTOP}/kerberos5/lib/libsl LIBSL?= ${LIBSLDIR}/libsl${PIE_SUFFIX}.a LIBIPFDIR= ${OBJTOP}/sbin/ipf/libipf LIBIPF?= ${LIBIPFDIR}/libipf${PIE_SUFFIX}.a LIBTELNETDIR= ${OBJTOP}/lib/libtelnet LIBTELNET?= ${LIBTELNETDIR}/libtelnet${PIE_SUFFIX}.a LIBCRONDIR= ${OBJTOP}/usr.sbin/cron/lib LIBCRON?= ${LIBCRONDIR}/libcron${PIE_SUFFIX}.a LIBNTPDIR= ${OBJTOP}/usr.sbin/ntp/libntp LIBNTP?= ${LIBNTPDIR}/libntp${PIE_SUFFIX}.a LIBNTPEVENTDIR= ${OBJTOP}/usr.sbin/ntp/libntpevent LIBNTPEVENT?= ${LIBNTPEVENTDIR}/libntpevent${PIE_SUFFIX}.a LIBOPTSDIR= ${OBJTOP}/usr.sbin/ntp/libopts LIBOPTS?= ${LIBOPTSDIR}/libopts${PIE_SUFFIX}.a LIBPARSEDIR= ${OBJTOP}/usr.sbin/ntp/libparse LIBPARSE?= ${LIBPARSEDIR}/libparse${PIE_SUFFIX}.a LIBLPRDIR= ${OBJTOP}/usr.sbin/lpr/common_source LIBLPR?= ${LIBLPRDIR}/liblpr${PIE_SUFFIX}.a LIBFIFOLOGDIR= ${OBJTOP}/usr.sbin/fifolog/lib LIBFIFOLOG?= ${LIBFIFOLOGDIR}/libfifolog${PIE_SUFFIX}.a LIBBSNMPTOOLSDIR= ${OBJTOP}/usr.sbin/bsnmpd/tools/libbsnmptools LIBBSNMPTOOLS?= ${LIBBSNMPTOOLSDIR}/libbsnmptools${PIE_SUFFIX}.a LIBAMUDIR= ${OBJTOP}/usr.sbin/amd/libamu LIBAMU?= ${LIBAMUDIR}/libamu${PIE_SUFFIX}.a LIBBE?= ${LIBBEDIR}/libbe${PIE_SUFFIX}.a LIBPMCSTATDIR= ${OBJTOP}/lib/libpmcstat LIBPMCSTAT?= ${LIBPMCSTATDIR}/libpmcstat${PIE_SUFFIX}.a LIBC_NOSSP_PICDIR= ${OBJTOP}/lib/libc LIBC_NOSSP_PIC?= ${LIBC_NOSSP_PICDIR}/libc_nossp_pic.a # Define a directory for each library. This is useful for adding -L in when # not using a --sysroot or for meta mode bootstrapping when there is no # Makefile.depend. These are sorted by directory. LIBAVLDIR= ${OBJTOP}/cddl/lib/libavl LIBCTFDIR= ${OBJTOP}/cddl/lib/libctf LIBDTRACEDIR= ${OBJTOP}/cddl/lib/libdtrace LIBNVPAIRDIR= ${OBJTOP}/cddl/lib/libnvpair LIBUMEMDIR= ${OBJTOP}/cddl/lib/libumem LIBUUTILDIR= ${OBJTOP}/cddl/lib/libuutil LIBZFSDIR= ${OBJTOP}/cddl/lib/libzfs LIBZFS_COREDIR= ${OBJTOP}/cddl/lib/libzfs_core LIBZPOOLDIR= ${OBJTOP}/cddl/lib/libzpool # OFED support LIBCXGB4DIR= ${OBJTOP}/lib/ofed/libcxgb4 LIBIBCMDIR= ${OBJTOP}/lib/ofed/libibcm LIBIBMADDIR= ${OBJTOP}/lib/ofed/libibmad LIBIBNETDISCDIR=${OBJTOP}/lib/ofed/libibnetdisc LIBIBUMADDIR= ${OBJTOP}/lib/ofed/libibumad LIBIBVERBSDIR= ${OBJTOP}/lib/ofed/libibverbs LIBMLX4DIR= ${OBJTOP}/lib/ofed/libmlx4 LIBMLX5DIR= ${OBJTOP}/lib/ofed/libmlx5 LIBRDMACMDIR= ${OBJTOP}/lib/ofed/librdmacm LIBOSMCOMPDIR= ${OBJTOP}/lib/ofed/complib LIBOPENSMDIR= ${OBJTOP}/lib/ofed/libopensm LIBOSMVENDORDIR=${OBJTOP}/lib/ofed/libvendor LIBDIALOGDIR= ${OBJTOP}/gnu/lib/libdialog LIBGCOVDIR= ${OBJTOP}/gnu/lib/libgcov LIBGOMPDIR= ${OBJTOP}/gnu/lib/libgomp LIBGNUREGEXDIR= ${OBJTOP}/gnu/lib/libregex LIBSSPDIR= ${OBJTOP}/lib/libssp LIBSSP_NONSHAREDDIR= ${OBJTOP}/lib/libssp_nonshared LIBSUPCPLUSPLUSDIR= ${OBJTOP}/gnu/lib/libsupc++ LIBASN1DIR= ${OBJTOP}/kerberos5/lib/libasn1 LIBGSSAPI_KRB5DIR= ${OBJTOP}/kerberos5/lib/libgssapi_krb5 LIBGSSAPI_NTLMDIR= ${OBJTOP}/kerberos5/lib/libgssapi_ntlm LIBGSSAPI_SPNEGODIR= ${OBJTOP}/kerberos5/lib/libgssapi_spnego LIBHDBDIR= ${OBJTOP}/kerberos5/lib/libhdb LIBHEIMBASEDIR= ${OBJTOP}/kerberos5/lib/libheimbase LIBHEIMIPCCDIR= ${OBJTOP}/kerberos5/lib/libheimipcc LIBHEIMIPCSDIR= ${OBJTOP}/kerberos5/lib/libheimipcs LIBHEIMNTLMDIR= ${OBJTOP}/kerberos5/lib/libheimntlm LIBHX509DIR= ${OBJTOP}/kerberos5/lib/libhx509 LIBKADM5CLNTDIR= ${OBJTOP}/kerberos5/lib/libkadm5clnt LIBKADM5SRVDIR= ${OBJTOP}/kerberos5/lib/libkadm5srv LIBKAFS5DIR= ${OBJTOP}/kerberos5/lib/libkafs5 LIBKDCDIR= ${OBJTOP}/kerberos5/lib/libkdc LIBKRB5DIR= ${OBJTOP}/kerberos5/lib/libkrb5 LIBROKENDIR= ${OBJTOP}/kerberos5/lib/libroken LIBWINDDIR= ${OBJTOP}/kerberos5/lib/libwind LIBATF_CDIR= ${OBJTOP}/lib/atf/libatf-c LIBATF_CXXDIR= ${OBJTOP}/lib/atf/libatf-c++ LIBGMOCKDIR= ${OBJTOP}/lib/googletest/gmock LIBGMOCK_MAINDIR= ${OBJTOP}/lib/googletest/gmock_main LIBGTESTDIR= ${OBJTOP}/lib/googletest/gtest LIBGTEST_MAINDIR= ${OBJTOP}/lib/googletest/gtest_main LIBALIASDIR= ${OBJTOP}/lib/libalias/libalias LIBBLACKLISTDIR= ${OBJTOP}/lib/libblacklist LIBBLOCKSRUNTIMEDIR= ${OBJTOP}/lib/libblocksruntime LIBBSNMPDIR= ${OBJTOP}/lib/libbsnmp/libbsnmp LIBCASPERDIR= ${OBJTOP}/lib/libcasper/libcasper LIBCAP_DNSDIR= ${OBJTOP}/lib/libcasper/services/cap_dns LIBCAP_GRPDIR= ${OBJTOP}/lib/libcasper/services/cap_grp LIBCAP_PWDDIR= ${OBJTOP}/lib/libcasper/services/cap_pwd LIBCAP_RANDOMDIR= ${OBJTOP}/lib/libcasper/services/cap_random LIBCAP_SYSCTLDIR= ${OBJTOP}/lib/libcasper/services/cap_sysctl LIBCAP_SYSLOGDIR= ${OBJTOP}/lib/libcasper/services/cap_syslog LIBBSDXMLDIR= ${OBJTOP}/lib/libexpat LIBKVMDIR= ${OBJTOP}/lib/libkvm LIBPTHREADDIR= ${OBJTOP}/lib/libthr LIBMDIR= ${OBJTOP}/lib/msun LIBFORMDIR= ${OBJTOP}/lib/ncurses/form LIBFORMLIBWDIR= ${OBJTOP}/lib/ncurses/formw LIBMENUDIR= ${OBJTOP}/lib/ncurses/menu LIBMENULIBWDIR= ${OBJTOP}/lib/ncurses/menuw LIBNCURSESDIR= ${OBJTOP}/lib/ncurses/ncurses LIBNCURSESWDIR= ${OBJTOP}/lib/ncurses/ncursesw LIBPANELDIR= ${OBJTOP}/lib/ncurses/panel LIBPANELWDIR= ${OBJTOP}/lib/ncurses/panelw LIBCRYPTODIR= ${OBJTOP}/secure/lib/libcrypto LIBSSHDIR= ${OBJTOP}/secure/lib/libssh LIBSSLDIR= ${OBJTOP}/secure/lib/libssl LIBTEKENDIR= ${OBJTOP}/sys/teken/libteken LIBEGACYDIR= ${OBJTOP}/tools/build LIBLNDIR= ${OBJTOP}/usr.bin/lex/lib LIBTERMCAPDIR= ${LIBNCURSESDIR} LIBTERMCAPWDIR= ${LIBNCURSESWDIR} # Default other library directories to lib/libNAME. .for lib in ${_LIBRARIES} LIB${lib:tu}DIR?= ${OBJTOP}/lib/lib${lib} .endfor # Validate that listed LIBADD are valid. .for _l in ${LIBADD} .if empty(_LIBRARIES:M${_l}) _BADLIBADD+= ${_l} .endif .endfor .if !empty(_BADLIBADD) .error ${.CURDIR}: Invalid LIBADD used which may need to be added to ${_this:T}: ${_BADLIBADD} .endif # Sanity check that libraries are defined here properly when building them. .if defined(LIB) && ${_LIBRARIES:M${LIB}} != "" .if !empty(LIBADD) && \ (!defined(_DP_${LIB}) || ${LIBADD:O:u} != ${_DP_${LIB}:O:u}) .error ${.CURDIR}: Missing or incorrect _DP_${LIB} entry in ${_this:T}. Should match LIBADD for ${LIB} ('${LIBADD}' vs '${_DP_${LIB}}') .endif # Note that OBJTOP is not yet defined here but for the purpose of the check # it is fine as it resolves to the SRC directory. .if !defined(LIB${LIB:tu}DIR) || !exists(${SRCTOP}/${LIB${LIB:tu}DIR:S,^${OBJTOP}/,,}) .error ${.CURDIR}: Missing or incorrect value for LIB${LIB:tu}DIR in ${_this:T}: ${LIB${LIB:tu}DIR:S,^${OBJTOP}/,,} .endif .if ${_INTERNALLIBS:M${LIB}} != "" && !defined(LIB${LIB:tu}) .error ${.CURDIR}: Missing value for LIB${LIB:tu} in ${_this:T}. Likely should be: LIB${LIB:tu}?= $${LIB${LIB:tu}DIR}/lib${LIB}.a .endif .endif .endif # !target(____) Index: stable/12 =================================================================== --- stable/12 (revision 366012) +++ stable/12 (revision 366013) Property changes on: stable/12 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r364936,365023