The branch main has been updated by vmaffione:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=36d6e65722ea515bf2d122d6e69096a5ff620a92

commit 36d6e65722ea515bf2d122d6e69096a5ff620a92
Author:     Vincenzo Maffione <vmaffi...@freebsd.org>
AuthorDate: 2021-04-02 14:39:30 +0000
Commit:     Vincenzo Maffione <vmaffi...@freebsd.org>
CommitDate: 2021-04-02 14:39:30 +0000

    netmap: update unit tests with libnetmap tests
---
 tests/sys/netmap/Makefile        |   1 +
 tests/sys/netmap/ctrl-api-test.c | 321 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 309 insertions(+), 13 deletions(-)

diff --git a/tests/sys/netmap/Makefile b/tests/sys/netmap/Makefile
index 0228271dd668..a7891f583b3b 100644
--- a/tests/sys/netmap/Makefile
+++ b/tests/sys/netmap/Makefile
@@ -10,5 +10,6 @@ PLAIN_TESTS_C+=       ctrl-api-test
 
 CFLAGS+=       -I${SRCTOP}/tests
 LIBADD+=       pthread
+LIBADD+=       netmap
 
 .include <bsd.test.mk>
diff --git a/tests/sys/netmap/ctrl-api-test.c b/tests/sys/netmap/ctrl-api-test.c
index cea78141fbe4..7cd4d6ac6d9b 100644
--- a/tests/sys/netmap/ctrl-api-test.c
+++ b/tests/sys/netmap/ctrl-api-test.c
@@ -46,6 +46,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <libnetmap.h>
 #include <net/if.h>
 #include <net/netmap.h>
 #include <pthread.h>
@@ -57,6 +58,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <signal.h>
+#include <stddef.h>
 
 #ifdef __FreeBSD__
 #include "freebsd_test_suite/macros.h"
@@ -71,6 +73,8 @@ eventfd(int x __unused, int y __unused)
 #include <sys/eventfd.h>
 #endif
 
+#define NM_IFNAMSZ 64
+
 static int
 exec_command(int argc, const char *const argv[])
 {
@@ -143,9 +147,9 @@ exec_command(int argc, const char *const argv[])
 #define THRET_FAILURE  ((void *)0)
 
 struct TestContext {
-       char ifname[64];
-       char ifname_ext[128];
-       char bdgname[64];
+       char ifname[NM_IFNAMSZ];
+       char ifname_ext[NM_IFNAMSZ];
+       char bdgname[NM_IFNAMSZ];
        uint32_t nr_tx_slots;   /* slots in tx rings */
        uint32_t nr_rx_slots;   /* slots in rx rings */
        uint16_t nr_tx_rings;   /* number of tx rings */
@@ -166,6 +170,10 @@ struct TestContext {
        void *csb;                    /* CSB entries (atok and ktoa) */
        struct nmreq_option *nr_opt;  /* list of options */
        sem_t *sem;     /* for thread synchronization */
+
+       struct nmctx *nmctx;
+       const char *ifparse;
+       struct nmport_d *nmport;      /* nmport descriptor from libnetmap */
 };
 
 static struct TestContext ctx_;
@@ -177,7 +185,8 @@ nmreq_hdr_init(struct nmreq_header *hdr, const char *ifname)
 {
        memset(hdr, 0, sizeof(*hdr));
        hdr->nr_version = NETMAP_API;
-       strncpy(hdr->nr_name, ifname, sizeof(hdr->nr_name) - 1);
+       assert(strlen(ifname) < NM_IFNAMSZ);
+       strncpy(hdr->nr_name, ifname, sizeof(hdr->nr_name));
 }
 
 /* Single NETMAP_REQ_PORT_INFO_GET. */
@@ -522,16 +531,30 @@ port_register_hwall_rx(struct TestContext *ctx)
        return port_register(ctx);
 }
 
+
+static int
+vale_mkname(char *vpname, struct TestContext *ctx)
+{
+       if (snprintf(vpname, NM_IFNAMSZ, "%s:%s", ctx->bdgname, 
ctx->ifname_ext) >= NM_IFNAMSZ) {
+               fprintf(stderr, "%s:%s too long (max %d chars)\n", 
ctx->bdgname, ctx->ifname_ext,
+                               NM_IFNAMSZ - 1);
+               return -1;
+       }
+       return 0;
+}
+
+
 /* NETMAP_REQ_VALE_ATTACH */
 static int
 vale_attach(struct TestContext *ctx)
 {
        struct nmreq_vale_attach req;
        struct nmreq_header hdr;
-       char vpname[sizeof(ctx->bdgname) + 1 + sizeof(ctx->ifname_ext)];
+       char vpname[NM_IFNAMSZ];
        int ret;
 
-       snprintf(vpname, sizeof(vpname), "%s:%s", ctx->bdgname, 
ctx->ifname_ext);
+       if (vale_mkname(vpname, ctx) < 0)
+               return -1;
 
        printf("Testing NETMAP_REQ_VALE_ATTACH on '%s'\n", vpname);
        nmreq_hdr_init(&hdr, vpname);
@@ -563,10 +586,11 @@ vale_detach(struct TestContext *ctx)
 {
        struct nmreq_header hdr;
        struct nmreq_vale_detach req;
-       char vpname[256];
+       char vpname[NM_IFNAMSZ];
        int ret;
 
-       snprintf(vpname, sizeof(vpname), "%s:%s", ctx->bdgname, 
ctx->ifname_ext);
+       if (vale_mkname(vpname, ctx) < 0)
+               return -1;
 
        printf("Testing NETMAP_REQ_VALE_DETACH on '%s'\n", vpname);
        nmreq_hdr_init(&hdr, vpname);
@@ -818,7 +842,7 @@ pipe_slave(struct TestContext *ctx)
 }
 
 /* Test PORT_INFO_GET and POOLS_INFO_GET on a pipe. This is useful to test the
- * registration request used internall by netmap. */
+ * registration request used internally by netmap. */
 static int
 pipe_port_info_get(struct TestContext *ctx)
 {
@@ -841,10 +865,12 @@ vale_polling_enable(struct TestContext *ctx)
 {
        struct nmreq_vale_polling req;
        struct nmreq_header hdr;
-       char vpname[256];
+       char vpname[NM_IFNAMSZ];
        int ret;
 
-       snprintf(vpname, sizeof(vpname), "%s:%s", ctx->bdgname, 
ctx->ifname_ext);
+       if (vale_mkname(vpname, ctx) < 0)
+               return -1;
+
        printf("Testing NETMAP_REQ_VALE_POLLING_ENABLE on '%s'\n", vpname);
 
        nmreq_hdr_init(&hdr, vpname);
@@ -873,10 +899,12 @@ vale_polling_disable(struct TestContext *ctx)
 {
        struct nmreq_vale_polling req;
        struct nmreq_header hdr;
-       char vpname[256];
+       char vpname[NM_IFNAMSZ];
        int ret;
 
-       snprintf(vpname, sizeof(vpname), "%s:%s", ctx->bdgname, 
ctx->ifname_ext);
+       if (vale_mkname(vpname, ctx) < 0)
+               return -1;
+
        printf("Testing NETMAP_REQ_VALE_POLLING_DISABLE on '%s'\n", vpname);
 
        nmreq_hdr_init(&hdr, vpname);
@@ -1715,6 +1743,271 @@ null_port_sync(struct TestContext *ctx)
        return 0;
 }
 
+struct nmreq_parse_test {
+       const char *ifname;
+       const char *exp_port;
+       const char *exp_suff;
+       int exp_error;
+       uint32_t exp_mode;
+       uint16_t exp_ringid;
+       uint64_t exp_flags;
+};
+
+static struct nmreq_parse_test nmreq_parse_tests[] = {
+       /* port spec is the input. The expected results are as follows:
+        * - port: what should go into hdr.nr_name
+        * - suff: the trailing part of the input after parsing (NULL means 
equal to port spec)
+        * - err: the expected return value, interpreted as follows
+        *       err > 0 => nmreq_header_parse should fail with the given error
+        *       err < 0 => nrmeq_header_parse should succeed, but 
nmreq_register_decode should
+        *                         fail with error |err|
+        *       err = 0 => should succeed
+        * - mode, ringid flags: what should go into the corresponding nr_* 
fields in the
+        *      nmreq_register struct in case of success
+        */
+
+       /*port spec*/                   /*port*/        /*suff*/    /*err*/     
/*mode*/    /*ringid*/ /*flags*/
+       { "netmap:eth0",                "eth0",         "",             0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "netmap:eth0-1",              "eth0",         "",             0,      
NR_REG_ONE_NIC, 1,      0 },
+       { "netmap:eth0-",               "eth0",         "-",            
-EINVAL,0,              0,      0 },
+       { "netmap:eth0/x",              "eth0",         "",             0,      
NR_REG_ALL_NIC, 0,      NR_EXCLUSIVE },
+       { "netmap:eth0/z",              "eth0",         "",             0,      
NR_REG_ALL_NIC, 0,      NR_ZCOPY_MON },
+       { "netmap:eth0/r",              "eth0",         "",             0,      
NR_REG_ALL_NIC, 0,      NR_MONITOR_RX },
+       { "netmap:eth0/t",              "eth0",         "",             0,      
NR_REG_ALL_NIC, 0,      NR_MONITOR_TX },
+       { "netmap:eth0-2/Tx",           "eth0",         "",             0,      
NR_REG_ONE_NIC, 2,      NR_TX_RINGS_ONLY|NR_EXCLUSIVE },
+       { "netmap:eth0*",               "eth0",         "",             0,      
NR_REG_NIC_SW,  0,      0 },
+       { "netmap:eth0^",               "eth0",         "",             0,      
NR_REG_SW,      0,      0 },
+       { "netmap:eth0@2",              "eth0",         "",             0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "netmap:eth0@2/R",            "eth0",         "",             0,      
NR_REG_ALL_NIC, 0,      NR_RX_RINGS_ONLY },
+       { "netmap:eth0@netmap:lo/R",    "eth0",         "@netmap:lo/R", 0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "netmap:eth0/R@xxx",          "eth0",         "@xxx",         0,      
NR_REG_ALL_NIC, 0,      NR_RX_RINGS_ONLY },
+       { "netmap:eth0@2/R@2",          "eth0",         "",             0,      
NR_REG_ALL_NIC, 0,      NR_RX_RINGS_ONLY },
+       { "netmap:eth0@2/R@3",          "eth0",         "@2/R@3",       
-EINVAL,0,              0,      0 },
+       { "netmap:eth0@",               "eth0",         "@",            
-EINVAL,0,              0,      0 },
+       { "netmap:",                    "",             NULL,           EINVAL, 
0,              0,      0 },
+       { "netmap:^",                   "",             NULL,           EINVAL, 
0,              0,      0 },
+       { "netmap:{",                   "",             NULL,           EINVAL, 
0,              0,      0 },
+       { "netmap:vale0:0",             NULL,           NULL,           EINVAL, 
0,              0,      0 },
+       { "eth0",                       NULL,           NULL,           EINVAL, 
0,              0,      0 },
+       { "vale0:0",                    "vale0:0",      "",             0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "vale:0",                     "vale:0",       "",             0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "valeXXX:YYY",                "valeXXX:YYY",  "",             0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "valeXXX:YYY-4",              "valeXXX:YYY",  "",             0,      
NR_REG_ONE_NIC, 4,      0 },
+       { "netmapXXX:eth0",             NULL,           NULL,           EINVAL, 
0,              0,      0 },
+       { "netmap:14",                  "14",           "",             0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "netmap:eth0&",               NULL,           NULL,           EINVAL, 
0,              0,      0 },
+       { "netmap:pipe{0",              "pipe{0",       "",             0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "netmap:pipe{in",             "pipe{in",      "",             0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "netmap:pipe{in-7",           "pipe{in",      "",             0,      
NR_REG_ONE_NIC, 7,      0 },
+       { "vale0:0{0",                  "vale0:0{0",    "",             0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "netmap:pipe{1}2",            NULL,           NULL,           EINVAL, 
0,              0,      0 },
+       { "vale0:0@opt",                "vale0:0",      "@opt",         0,      
NR_REG_ALL_NIC, 0,      0 },
+       { "vale0:0/Tx@opt",             "vale0:0",      "@opt",         0,      
NR_REG_ALL_NIC, 0,      NR_TX_RINGS_ONLY|NR_EXCLUSIVE },
+       { "vale0:0-3@opt",              "vale0:0",      "@opt",         0,      
NR_REG_ONE_NIC, 3,      0 },
+       { "vale0:0@",                   "vale0:0",      "@",            
-EINVAL,0,              0,      0 },
+       { "",                           NULL,           NULL,           EINVAL, 
0,              0,      0 },
+       { NULL,                         NULL,           NULL,           0,      
0,              0,      0 },
+};
+
+static void
+randomize(void *dst, size_t n)
+{
+       size_t i;
+       char *dst_ = dst;
+
+       for (i = 0; i < n; i++)
+               dst_[i] = (char)random();
+}
+
+static int
+nmreq_hdr_parsing(struct TestContext *ctx,
+               struct nmreq_parse_test *t,
+               struct nmreq_header *hdr)
+{
+       const char *save;
+       struct nmreq_header orig_hdr;
+
+       save = ctx->ifparse = t->ifname;
+       orig_hdr = *hdr;
+
+       printf("nmreq_header: \"%s\"\n", ctx->ifparse);
+       if (nmreq_header_decode(&ctx->ifparse, hdr, ctx->nmctx) < 0) {
+               if (t->exp_error > 0) {
+                       if (errno != t->exp_error) {
+                               printf("!!! got errno=%d, want %d\n",
+                                               errno, t->exp_error);
+                               return -1;
+                       }
+                       if (ctx->ifparse != save) {
+                               printf("!!! parse error, but first arg 
changed\n");
+                               return -1;
+                       }
+                       if (memcmp(&orig_hdr, hdr, sizeof(*hdr))) {
+                               printf("!!! parse error, but header changed\n");
+                               return -1;
+                       }
+                       return 0;
+               }
+               printf ("!!! nmreq_header_decode was expected to succeed, but 
it failed with error %d\n", errno);
+               return -1;
+       }
+       if (t->exp_error > 0) {
+               printf("!!! nmreq_header_decode returns 0, but error %d was 
expected\n", t->exp_error);
+               return -1;
+       }
+       if (strcmp(t->exp_port, hdr->nr_name) != 0) {
+               printf("!!! got '%s', want '%s'\n", hdr->nr_name, t->exp_port);
+               return -1;
+       }
+       if (hdr->nr_reqtype != orig_hdr.nr_reqtype ||
+           hdr->nr_options != orig_hdr.nr_options ||
+           hdr->nr_body    != orig_hdr.nr_body) {
+               printf("!!! some fields of the nmreq_header where changed 
unexpectedly\n");
+               return -1;
+       }
+       return 0;
+}
+
+static int
+nmreq_reg_parsing(struct TestContext *ctx,
+               struct nmreq_parse_test *t,
+               struct nmreq_register *reg)
+{
+       const char *save;
+       struct nmreq_register orig_reg;
+
+
+       save = ctx->ifparse;
+       orig_reg = *reg;
+
+       printf("nmreq_register: \"%s\"\n", ctx->ifparse);
+       if (nmreq_register_decode(&ctx->ifparse, reg, ctx->nmctx) < 0) {
+               if (t->exp_error < 0) {
+                       if (errno != -t->exp_error) {
+                               printf("!!! got errno=%d, want %d\n",
+                                               errno, -t->exp_error);
+                               return -1;
+                       }
+                       if (ctx->ifparse != save) {
+                               printf("!!! parse error, but first arg 
changed\n");
+                               return -1;
+                       }
+                       if (memcmp(&orig_reg, reg, sizeof(*reg))) {
+                               printf("!!! parse error, but nmreq_register 
changed\n");
+                               return -1;
+                       }
+                       return 0;
+               }
+               printf ("!!! parse failed but it should have succeeded\n");
+               return -1;
+       }
+       if (t->exp_error < 0) {
+               printf("!!! nmreq_register_decode returns 0, but error %d was 
expected\n", -t->exp_error);
+               return -1;
+       }
+       if (reg->nr_mode != t->exp_mode) {
+               printf("!!! got nr_mode '%d', want '%d'\n", reg->nr_mode, 
t->exp_mode);
+               return -1;
+       }
+       if (reg->nr_ringid != t->exp_ringid) {
+               printf("!!! got nr_ringid '%d', want '%d'\n", reg->nr_ringid, 
t->exp_ringid);
+               return -1;
+       }
+       if (reg->nr_flags != t->exp_flags) {
+               printf("!!! got nm_flags '%llx', want '%llx\n", (unsigned long 
long)reg->nr_flags,
+                               (unsigned long long)t->exp_flags);
+               return -1;
+       }
+       if (reg->nr_offset     != orig_reg.nr_offset     ||
+           reg->nr_memsize    != orig_reg.nr_memsize    ||
+           reg->nr_tx_slots   != orig_reg.nr_tx_slots   ||
+           reg->nr_rx_slots   != orig_reg.nr_rx_slots   ||
+           reg->nr_tx_rings   != orig_reg.nr_tx_rings   ||
+           reg->nr_rx_rings   != orig_reg.nr_rx_rings   ||
+           reg->nr_extra_bufs != orig_reg.nr_extra_bufs)
+       {
+               printf("!!! some fields of the nmreq_register where changed 
unexpectedly\n");
+               return -1;
+       }
+       return 0;
+}
+
+static void
+nmctx_parsing_error(struct nmctx *ctx, const char *msg)
+{
+       (void)ctx;
+       printf("    got message: %s\n", msg);
+}
+
+static int
+nmreq_parsing(struct TestContext *ctx)
+{
+       struct nmreq_parse_test *t;
+       struct nmreq_header hdr;
+       struct nmreq_register reg;
+       struct nmctx test_nmctx, *nmctx;
+       int ret = 0;
+
+       nmctx = nmctx_get();
+       if (nmctx == NULL) {
+               printf("Failed to acquire nmctx: %s", strerror(errno));
+               return -1;
+       }
+       test_nmctx = *nmctx;
+       test_nmctx.error = nmctx_parsing_error;
+       ctx->nmctx = &test_nmctx;
+       for (t = nmreq_parse_tests; t->ifname != NULL; t++) {
+               const char *exp_suff = t->exp_suff != NULL ?
+                       t->exp_suff : t->ifname;
+
+               randomize(&hdr, sizeof(hdr));
+               randomize(&reg, sizeof(reg));
+               reg.nr_mem_id = 0;
+               if (nmreq_hdr_parsing(ctx, t, &hdr) < 0) {
+                       ret = -1;
+               } else if (t->exp_error <= 0 && nmreq_reg_parsing(ctx, t, &reg) 
< 0) {
+                       ret = -1;
+               }
+               if (strcmp(ctx->ifparse, exp_suff) != 0) {
+                       printf("!!! string suffix after parse is '%s', but it 
should be '%s'\n",
+                                       ctx->ifparse, exp_suff);
+                       ret = -1;
+               }
+       }
+       return ret;
+}
+
+static int
+binarycomp(struct TestContext *ctx)
+{
+#define ckroff(f, o) do {\
+       if (offsetof(struct netmap_ring, f) != (o)) {\
+               printf("offset of netmap_ring.%s is %zd, but it should be %d",\
+                               #f, offsetof(struct netmap_ring, f), (o));\
+               return -1;\
+       }\
+} while (0)
+
+       (void)ctx;
+
+       ckroff(buf_ofs, 0);
+       ckroff(num_slots, 8);
+       ckroff(nr_buf_size, 12);
+       ckroff(ringid, 16);
+       ckroff(dir, 18);
+       ckroff(head, 20);
+       ckroff(cur, 24);
+       ckroff(tail, 28);
+       ckroff(flags, 32);
+       ckroff(ts, 40);
+       ckroff(offset_mask, 56);
+       ckroff(buf_align, 64);
+       ckroff(sem, 128);
+       ckroff(slot, 256);
+
+       return 0;
+}
+
 static void
 usage(const char *prog)
 {
@@ -1783,6 +2076,8 @@ static struct mytest tests[] = {
        decltest(legacy_regif_extra_bufs),
        decltest(legacy_regif_extra_bufs_pipe),
        decltest(legacy_regif_extra_bufs_pipe_vale),
+       decltest(nmreq_parsing),
+       decltest(binarycomp),
 };
 
 static void
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to