DPDK patches and discussions
 help / color / mirror / Atom feed
From: Andrzej Ostruszka <aostruszka@marvell.com>
To: <dev@dpdk.org>, Thomas Monjalon <thomas@monjalon.net>
Subject: [dpdk-dev] [PATCH 3/4] if_proxy: add simple functionality test
Date: Fri, 6 Mar 2020 17:41:03 +0100	[thread overview]
Message-ID: <20200306164104.15528-4-aostruszka@marvell.com> (raw)
In-Reply-To: <20200306164104.15528-1-aostruszka@marvell.com>

This commit adds simple test of the library notifications.

Signed-off-by: Andrzej Ostruszka <aostruszka@marvell.com>
---
 MAINTAINERS              |   1 +
 app/test/Makefile        |   5 +
 app/test/meson.build     |   4 +
 app/test/test_if_proxy.c | 706 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 716 insertions(+)
 create mode 100644 app/test/test_if_proxy.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 3854d7661..a92cb7356 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1472,6 +1472,7 @@ F: doc/guides/prog_guide/bpf_lib.rst
 IF Proxy - EXPERIMENTAL
 M: Andrzej Ostruszka <aostruszka@marvell.com>
 F: lib/librte_if_proxy/
+F: app/test/test_if_proxy.c
 F: doc/guides/prog_guide/if_proxy_lib.rst
 
 Test Applications
diff --git a/app/test/Makefile b/app/test/Makefile
index 1f080d162..dc287f94b 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -231,6 +231,11 @@ SRCS-$(CONFIG_RTE_LIBRTE_BPF) += test_bpf.c
 
 SRCS-$(CONFIG_RTE_LIBRTE_RCU) += test_rcu_qsbr.c test_rcu_qsbr_perf.c
 
+ifeq ($(CONFIG_RTE_LIBRTE_IF_PROXY),y)
+SRCS-y += test_if_proxy.c
+LDLIBS += -lrte_if_proxy
+endif
+
 SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec.c
 SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec_sad.c
 ifeq ($(CONFIG_RTE_LIBRTE_IPSEC),y)
diff --git a/app/test/meson.build b/app/test/meson.build
index 0a2ce710f..870c3a8bb 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -352,6 +352,10 @@ endif
 if dpdk_conf.has('RTE_LIBRTE_PDUMP')
 	test_deps += 'pdump'
 endif
+if dpdk_conf.has('RTE_LIBRTE_IF_PROXY')
+	test_deps += 'if_proxy'
+	test_sources += 'test_if_proxy.c'
+endif
 
 cflags = machine_args
 if cc.has_argument('-Wno-format-truncation')
diff --git a/app/test/test_if_proxy.c b/app/test/test_if_proxy.c
new file mode 100644
index 000000000..acd496126
--- /dev/null
+++ b/app/test/test_if_proxy.c
@@ -0,0 +1,706 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#include "test.h"
+
+#include <rte_ethdev.h>
+#include <rte_if_proxy.h>
+#include <rte_cycles.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <time.h>
+
+/* There are two types of event notifications - one using callbacks and one
+ * using event queues (rings).  We'll test them both and this "bool" will govern
+ * the type of API to use.
+ */
+static int use_callbacks = 1;
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+static struct rte_ring *ev_queue;
+
+enum net_event_mask {
+	INITIALIZED	= 1U << RTE_IFPX_CFG_DONE,
+	LINK_CHANGED	= 1U << RTE_IFPX_LINK_CHANGE,
+	MAC_CHANGED	= 1U << RTE_IFPX_MAC_CHANGE,
+	MTU_CHANGED	= 1U << RTE_IFPX_MTU_CHANGE,
+	ADDR_ADD	= 1U << RTE_IFPX_ADDR_ADD,
+	ADDR_DEL	= 1U << RTE_IFPX_ADDR_DEL,
+	ROUTE_ADD	= 1U << RTE_IFPX_ROUTE_ADD,
+	ROUTE_DEL	= 1U << RTE_IFPX_ROUTE_DEL,
+	ADDR6_ADD	= 1U << RTE_IFPX_ADDR6_ADD,
+	ADDR6_DEL	= 1U << RTE_IFPX_ADDR6_DEL,
+	ROUTE6_ADD	= 1U << RTE_IFPX_ROUTE6_ADD,
+	ROUTE6_DEL	= 1U << RTE_IFPX_ROUTE6_DEL,
+	NEIGH_ADD	= 1U << RTE_IFPX_NEIGH_ADD,
+	NEIGH_DEL	= 1U << RTE_IFPX_NEIGH_DEL,
+	NEIGH6_ADD	= 1U << RTE_IFPX_NEIGH6_ADD,
+	NEIGH6_DEL	= 1U << RTE_IFPX_NEIGH6_DEL,
+};
+
+static unsigned int state;
+
+static struct {
+	struct rte_ether_addr mac_addr;
+	uint16_t port_id, mtu;
+	struct in_addr ipv4, route4;
+	struct in6_addr ipv6, route6;
+	uint16_t depth4, depth6;
+	int is_up;
+} net_cfg;
+
+static
+int unlock_notify(unsigned int op)
+{
+	/* the mutex is expected to be locked on entry */
+	RTE_VERIFY(pthread_mutex_trylock(&mutex) == EBUSY);
+	state |= op;
+
+	pthread_mutex_unlock(&mutex);
+	return pthread_cond_signal(&cond);
+}
+
+static
+void handle_event(struct rte_ifpx_event *ev);
+
+static
+int wait_for(unsigned int op_mask, unsigned int sec)
+{
+	int ec;
+
+	if (use_callbacks) {
+		struct timespec time;
+
+		ec = pthread_mutex_trylock(&mutex);
+		/* the mutex is expected to be locked on entry */
+		RTE_VERIFY(ec == EBUSY);
+
+		ec = 0;
+		clock_gettime(CLOCK_REALTIME, &time);
+		time.tv_sec += sec;
+
+		while ((state & op_mask) != op_mask && ec == 0)
+			ec = pthread_cond_timedwait(&cond, &mutex, &time);
+	} else {
+		uint64_t deadline;
+		struct rte_ifpx_event *ev;
+
+		ec = 0;
+		deadline = rte_get_timer_cycles() + sec * rte_get_timer_hz();
+
+		while ((state & op_mask) != op_mask) {
+			if (rte_get_timer_cycles() >= deadline) {
+				ec = ETIMEDOUT;
+				break;
+			}
+			if (rte_ring_dequeue(ev_queue, (void**)&ev) == 0)
+				handle_event(ev);
+		}
+	}
+
+	return ec;
+}
+
+static
+int expect(unsigned int op_mask, const char *fmt, ...)
+#if __GNUC__
+	__attribute__((format(printf, 2, 3)));
+#endif
+
+static
+int expect(unsigned int op_mask, const char *fmt, ...)
+{
+	char cmd[128];
+	va_list args;
+	int ret;
+
+	state &= ~op_mask;
+	va_start(args, fmt);
+	vsnprintf(cmd, sizeof(cmd), fmt, args);
+	va_end(args);
+	ret = system(cmd);
+	if (ret == 0)
+		/* IPv6 address notifications seem to need that long delay. */
+		return wait_for(op_mask, 2);
+	return ret;
+}
+
+static
+int mac_change(const struct rte_ifpx_mac_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (memcmp(ev->mac.addr_bytes, net_cfg.mac_addr.addr_bytes,
+		   RTE_ETHER_ADDR_LEN) == 0) {
+		unlock_notify(MAC_CHANGED);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int mtu_change(const struct rte_ifpx_mtu_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (ev->mtu == net_cfg.mtu) {
+		unlock_notify(MTU_CHANGED);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int link_change(const struct rte_ifpx_link_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (ev->is_up == net_cfg.is_up) {
+		/* Special case for testing of callbacks modification from
+		 * inside of callback: we catch putting link down (the last
+		 * operation in test) and remove callbacks registered.
+		 */
+		if (!ev->is_up) {
+			rte_ifpx_callbacks_unregister();
+		}
+		unlock_notify(LINK_CHANGED);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int addr_add(const struct rte_ifpx_addr_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (ev->ip == net_cfg.ipv4.s_addr) {
+		unlock_notify(ADDR_ADD);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int addr_del(const struct rte_ifpx_addr_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (ev->ip == net_cfg.ipv4.s_addr) {
+		unlock_notify(ADDR_DEL);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int addr6_add(const struct rte_ifpx_addr6_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (memcmp(ev->ip, net_cfg.ipv6.s6_addr, 16) == 0) {
+		unlock_notify(ADDR6_ADD);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int addr6_del(const struct rte_ifpx_addr6_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (memcmp(ev->ip, net_cfg.ipv6.s6_addr, 16) == 0) {
+		unlock_notify(ADDR6_DEL);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int route_add(const struct rte_ifpx_route_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (net_cfg.depth4 == ev->depth && net_cfg.route4.s_addr == ev->ip) {
+		unlock_notify(ROUTE_ADD);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int route_del(const struct rte_ifpx_route_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (net_cfg.depth4 == ev->depth && net_cfg.route4.s_addr == ev->ip) {
+		unlock_notify(ROUTE_DEL);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int route6_add(const struct rte_ifpx_route6_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (net_cfg.depth6 == ev->depth &&
+	    /* don't check for trailing zeros */
+	    memcmp(ev->ip, net_cfg.route6.s6_addr, ev->depth/8) == 0) {
+		unlock_notify(ROUTE6_ADD);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int route6_del(const struct rte_ifpx_route6_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (net_cfg.depth6 == ev->depth &&
+	    /* don't check for trailing zeros */
+	    memcmp(ev->ip, net_cfg.route6.s6_addr, ev->depth/8) == 0) {
+		unlock_notify(ROUTE6_DEL);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int neigh_add(const struct rte_ifpx_neigh_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (net_cfg.ipv4.s_addr == ev->ip &&
+	    memcmp(ev->mac.addr_bytes, net_cfg.mac_addr.addr_bytes,
+	           RTE_ETHER_ADDR_LEN) == 0) {
+		unlock_notify(NEIGH_ADD);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int neigh_del(const struct rte_ifpx_neigh_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (net_cfg.ipv4.s_addr == ev->ip) {
+		unlock_notify(NEIGH_DEL);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int neigh6_add(const struct rte_ifpx_neigh6_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (memcmp(ev->ip, net_cfg.ipv6.s6_addr, 16) == 0 &&
+	    memcmp(ev->mac.addr_bytes, net_cfg.mac_addr.addr_bytes,
+	           RTE_ETHER_ADDR_LEN) == 0) {
+		unlock_notify(NEIGH6_ADD);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int neigh6_del(const struct rte_ifpx_neigh6_change *ev)
+{
+	pthread_mutex_lock(&mutex);
+	RTE_VERIFY(ev->port_id == net_cfg.port_id);
+	if (memcmp(ev->ip, net_cfg.ipv6.s6_addr, 16) == 0) {
+		unlock_notify(NEIGH6_DEL);
+		return 1;
+	}
+	pthread_mutex_unlock(&mutex);
+	return 0;
+}
+
+static
+int cfg_done(void)
+{
+	pthread_mutex_lock(&mutex);
+	unlock_notify(INITIALIZED);
+	return 1;
+}
+
+static
+void handle_event(struct rte_ifpx_event *ev)
+{
+	if (ev->type != RTE_IFPX_CFG_DONE)
+		RTE_VERIFY(ev->data.port_id == net_cfg.port_id);
+
+	/* If params do not match what we expect just free the event. */
+	switch (ev->type) {
+	case RTE_IFPX_MAC_CHANGE:
+		if (memcmp(ev->mac_change.mac.addr_bytes,
+			   net_cfg.mac_addr.addr_bytes,
+		           RTE_ETHER_ADDR_LEN) != 0)
+			goto exit;
+		break;
+	case RTE_IFPX_MTU_CHANGE:
+		if (ev->mtu_change.mtu != net_cfg.mtu)
+			goto exit;
+		break;
+	case RTE_IFPX_LINK_CHANGE:
+		if (ev->link_change.is_up != net_cfg.is_up)
+			goto exit;
+		break;
+	case RTE_IFPX_ADDR_ADD:
+		if (ev->addr_change.ip != net_cfg.ipv4.s_addr)
+			goto exit;
+		break;
+	case RTE_IFPX_ADDR_DEL:
+		if (ev->addr_change.ip != net_cfg.ipv4.s_addr)
+			goto exit;
+		break;
+	case RTE_IFPX_ADDR6_ADD:
+		if (memcmp(ev->addr6_change.ip, net_cfg.ipv6.s6_addr,
+			   16) != 0)
+			goto exit;
+		break;
+	case RTE_IFPX_ADDR6_DEL:
+		if (memcmp(ev->addr6_change.ip, net_cfg.ipv6.s6_addr,
+			   16) != 0)
+			goto exit;
+		break;
+	case RTE_IFPX_ROUTE_ADD:
+		if (net_cfg.depth4 != ev->route_change.depth ||
+		    net_cfg.route4.s_addr != ev->route_change.ip)
+			goto exit;
+		break;
+	case RTE_IFPX_ROUTE_DEL:
+		if (net_cfg.depth4 != ev->route_change.depth ||
+		    net_cfg.route4.s_addr != ev->route_change.ip)
+			goto exit;
+		break;
+	case RTE_IFPX_ROUTE6_ADD:
+		if (net_cfg.depth6 != ev->route6_change.depth ||
+		    /* don't check for trailing zeros */
+		    memcmp(ev->route6_change.ip, net_cfg.route6.s6_addr,
+			   ev->route6_change.depth/8) != 0)
+			goto exit;
+		break;
+	case RTE_IFPX_ROUTE6_DEL:
+		if (net_cfg.depth6 != ev->route6_change.depth ||
+		    /* don't check for trailing zeros */
+		    memcmp(ev->route6_change.ip, net_cfg.route6.s6_addr,
+			   ev->route6_change.depth/8) != 0)
+			goto exit;
+		break;
+	case RTE_IFPX_NEIGH_ADD:
+		if (net_cfg.ipv4.s_addr != ev->neigh_change.ip ||
+		    memcmp(ev->neigh_change.mac.addr_bytes,
+			   net_cfg.mac_addr.addr_bytes, RTE_ETHER_ADDR_LEN) != 0)
+			goto exit;
+		break;
+	case RTE_IFPX_NEIGH_DEL:
+		if (net_cfg.ipv4.s_addr != ev->neigh_change.ip)
+			goto exit;
+		break;
+	case RTE_IFPX_NEIGH6_ADD:
+		if (memcmp(ev->neigh6_change.ip,
+			   net_cfg.ipv6.s6_addr, 16) != 0 ||
+		    memcmp(ev->neigh6_change.mac.addr_bytes,
+			   net_cfg.mac_addr.addr_bytes, RTE_ETHER_ADDR_LEN) != 0)
+			goto exit;
+		break;
+	case RTE_IFPX_NEIGH6_DEL:
+		if (memcmp(ev->neigh6_change.ip, net_cfg.ipv6.s6_addr, 16) != 0)
+			goto exit;
+		break;
+	case RTE_IFPX_CFG_DONE:
+		break;
+	default:
+		RTE_VERIFY(0 && "Unhandled event type");
+	}
+
+	state |= 1U << ev->type;
+exit:
+	free(ev);
+}
+
+static
+struct rte_ifpx_callbacks cbs = {
+	.mac_change = mac_change,
+	.mtu_change = mtu_change,
+	.link_change = link_change,
+	.addr_add = addr_add,
+	.addr_del = addr_del,
+	.addr6_add = addr6_add,
+	.addr6_del = addr6_del,
+	.route_add = route_add,
+	.route_del = route_del,
+	.route6_add = route6_add,
+	.route6_del = route6_del,
+	.neigh_add = neigh_add,
+	.neigh_del = neigh_del,
+	.neigh6_add = neigh6_add,
+	.neigh6_del = neigh6_del,
+	/* lib specific callback */
+	.cfg_done = cfg_done,
+};
+
+static
+int test_notifications(const struct rte_ifpx_info *pinfo)
+{
+	char mac_buf[RTE_ETHER_ADDR_FMT_SIZE];
+	int ec;
+
+	/* Test link up notification. */
+	net_cfg.is_up = 1;
+	ec = expect(LINK_CHANGED, "ip link set dev %s up", pinfo->if_name);
+	if (ec != 0) {
+		printf("Failed to notify about link going up\n");
+		return ec;
+	}
+
+	/* Test for MAC changes notification. */
+	rte_eth_random_addr(net_cfg.mac_addr.addr_bytes);
+	rte_ether_format_addr(mac_buf, sizeof(mac_buf), &net_cfg.mac_addr);
+	ec = expect(MAC_CHANGED, "ip link set dev %s address %s",
+		    pinfo->if_name, mac_buf);
+	if (ec != 0) {
+		printf("Missing/wrong notification about mac change\n");
+		return ec;
+	}
+
+	/* Test for MTU changes notification. */
+	net_cfg.mtu = pinfo->mtu + 100;
+	ec = expect(MTU_CHANGED, "ip link set dev %s mtu %d",
+		    pinfo->if_name, net_cfg.mtu);
+	if (ec != 0) {
+		printf("Missing/wrong notification about mtu change\n");
+		return ec;
+	}
+
+	/* Test for adding of IPv4 address - using address from TEST-2 pool.
+	 * This test is specific to linux netlink behaviour - after adding
+	 * address we get both notification about address being added and new
+	 * route.  So I check both.
+	 */
+	net_cfg.ipv4.s_addr = RTE_IPV4(198, 51, 100, 14);
+	net_cfg.route4.s_addr = net_cfg.ipv4.s_addr;
+	net_cfg.depth4 = 32;
+	ec = expect(ADDR_ADD | ROUTE_ADD, "ip addr add 198.51.100.14 dev %s",
+		    pinfo->if_name);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv4 address add\n");
+		return ec;
+	}
+
+	/* Test for IPv4 address removal.  See comment above for 'addr add'. */
+	ec = expect(ADDR_DEL | ROUTE_DEL, "ip addr del 198.51.100.14/32 dev %s",
+		    pinfo->if_name);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv4 address del\n");
+		return ec;
+	}
+
+	/* Test for adding IPv4 route. */
+	net_cfg.route4.s_addr = RTE_IPV4(198, 51, 100, 0);
+	net_cfg.depth4 = 24;
+	ec = expect(ROUTE_ADD, "ip route add 198.51.100.0/24 dev %s",
+		    pinfo->if_name);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv4 route add\n");
+		return ec;
+	}
+
+	/* Test for IPv4 route removal. */
+	ec = expect(ROUTE_DEL, "ip route del 198.51.100.0/24 dev %s",
+		    pinfo->if_name);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv4 route del\n");
+		return ec;
+	}
+
+	/* Test for neighbour addresses notifications. */
+	rte_eth_random_addr(net_cfg.mac_addr.addr_bytes);
+	rte_ether_format_addr(mac_buf, sizeof(mac_buf), &net_cfg.mac_addr);
+
+	ec = expect(NEIGH_ADD,
+		    "ip neigh add 198.51.100.14 dev %s lladdr %s nud noarp",
+		    pinfo->if_name, mac_buf);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv4 neighbour add\n");
+		return ec;
+	}
+
+	ec = expect(NEIGH_DEL, "ip neigh del 198.51.100.14 dev %s",
+		    pinfo->if_name);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv4 neighbour del\n");
+		return ec;
+	}
+
+	/* Now the same for IPv6 - with address from "documentation pool". */
+	inet_pton(AF_INET6, "2001:db8::dead:beef", net_cfg.ipv6.s6_addr);
+	/* This is specific to linux netlink behaviour - after adding address
+	 * we get both notification about address being added and new route.
+	 * So I wait for both.
+	 */
+	memcpy(net_cfg.route6.s6_addr, net_cfg.ipv6.s6_addr, 16);
+	net_cfg.depth6 = 128;
+	ec = expect(ADDR6_ADD | ROUTE6_ADD,
+		    "ip addr add 2001:db8::dead:beef dev %s",
+		    pinfo->if_name);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv6 address add\n");
+		return ec;
+	}
+
+	/* See comment above for 'addr6 add'. */
+	ec = expect(ADDR6_DEL | ROUTE6_DEL,
+		    "ip addr del 2001:db8::dead:beef/128 dev %s",
+		    pinfo->if_name);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv6 address del\n");
+		return ec;
+	}
+
+	net_cfg.depth6 = 96;
+	ec = expect(ROUTE6_ADD, "ip route add 2001:db8::dead:0/96 dev %s",
+		    pinfo->if_name);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv6 route add\n");
+		return ec;
+	}
+
+	ec = expect(ROUTE6_DEL, "ip route del 2001:db8::dead:0/96 dev %s",
+		    pinfo->if_name);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv6 route del\n");
+		return ec;
+	}
+
+	ec = expect(NEIGH6_ADD,
+		    "ip neigh add 2001:db8::dead:beef dev %s lladdr %s nud noarp",
+		    pinfo->if_name, mac_buf);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv6 neighbour add\n");
+		return ec;
+	}
+
+	ec = expect(NEIGH6_DEL, "ip neigh del 2001:db8::dead:beef dev %s",
+		    pinfo->if_name);
+	if (ec != 0) {
+		printf("Missing/wrong notifications about IPv6 neighbour del\n");
+		return ec;
+	}
+
+	/* Finally put link down and test for notification. */
+	net_cfg.is_up = 0;
+	ec = expect(LINK_CHANGED, "ip link set dev %s down", pinfo->if_name);
+	if (ec != 0) {
+		printf("Failed to notify about link going down\n");
+		return ec;
+	}
+
+	return 0;
+}
+
+static
+int test_if_proxy(void)
+{
+	int ec;
+	const struct rte_ifpx_info *pinfo;
+	uint16_t proxy_id;
+
+	state = 0;
+	memset(&net_cfg, 0, sizeof(net_cfg));
+
+	if (rte_eth_dev_count_avail() == 0) {
+		printf("Run this test with at least one port configured\n");
+		return 1;
+	}
+	/* User the first port available. */
+	RTE_ETH_FOREACH_DEV(net_cfg.port_id)
+		break;
+	proxy_id = rte_ifpx_proxy_create(RTE_IFPX_DEFAULT);
+	RTE_VERIFY(proxy_id != RTE_MAX_ETHPORTS);
+	rte_ifpx_port_bind(net_cfg.port_id, proxy_id);
+	rte_ifpx_callbacks_register(&cbs);
+	rte_ifpx_listen();
+
+	/* Let's start with callback based API. */
+	use_callbacks = 1;
+	pthread_mutex_lock(&mutex);
+	ec = wait_for(INITIALIZED, 2);
+	if (ec != 0) {
+		printf("Failed to obtain network configuration\n");
+		goto exit;
+	}
+	pinfo = rte_ifpx_info_get(net_cfg.port_id);
+	RTE_VERIFY(pinfo);
+
+	/* Make sure the link is down. */
+	net_cfg.is_up = 0;
+	ec = expect(LINK_CHANGED, "ip link set dev %s down", pinfo->if_name);
+	RTE_VERIFY(ec == ETIMEDOUT || ec == 0);
+
+	ec = test_notifications(pinfo);
+	if (ec != 0) {
+		printf("Failed test with callback based API\n");
+		goto exit;
+	}
+	/* Switch to event queue based API and repeat tests. */
+	use_callbacks = 0;
+	ev_queue = rte_ring_create("IFPX-events", 16, SOCKET_ID_ANY,
+				   RING_F_SP_ENQ | RING_F_SC_DEQ);
+	ec = rte_ifpx_queue_add(ev_queue);
+	if (ec != 0) {
+		printf("Failed to add a notification queue\n");
+		goto exit;
+	}
+	ec = test_notifications(pinfo);
+	if (ec != 0) {
+		printf("Failed test with event queue based API\n");
+		goto exit;
+	}
+
+exit:
+	pthread_mutex_unlock(&mutex);
+	/* Proxy ports are not owned by the lib.  Internal references to them
+	 * are cleared on close, but the ports are not destroyed so we need to
+	 * do that explicitly.
+	 */
+	rte_ifpx_proxy_destroy(proxy_id);
+	rte_ifpx_close();
+	/* Queue is removed from the lib by rte_ifpx_close() - here we just
+	 * free it.
+	 */
+	rte_ring_free(ev_queue);
+	ev_queue = NULL;
+
+	return ec;
+}
+
+REGISTER_TEST_COMMAND(if_proxy_autotest, test_if_proxy)
-- 
2.17.1


  parent reply	other threads:[~2020-03-06 16:41 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-06 16:41 [dpdk-dev] [PATCH 0/4] Introduce IF proxy library Andrzej Ostruszka
2020-03-06 16:41 ` [dpdk-dev] [PATCH 1/4] lib: introduce IF Proxy library Andrzej Ostruszka
2020-03-31 12:36   ` Harman Kalra
2020-03-31 15:37     ` Andrzej Ostruszka [C]
2020-04-01  5:29   ` Varghese, Vipin
2020-04-01 20:08     ` Andrzej Ostruszka [C]
2020-04-08  3:04       ` Varghese, Vipin
2020-04-08 18:13         ` Andrzej Ostruszka [C]
2020-03-06 16:41 ` [dpdk-dev] [PATCH 2/4] if_proxy: add library documentation Andrzej Ostruszka
2020-03-06 16:41 ` Andrzej Ostruszka [this message]
2020-03-06 16:41 ` [dpdk-dev] [PATCH 4/4] if_proxy: add example application Andrzej Ostruszka
2020-03-06 17:17 ` [dpdk-dev] [PATCH 0/4] Introduce IF proxy library Andrzej Ostruszka
2020-03-10 11:10 ` [dpdk-dev] [PATCH v2 " Andrzej Ostruszka
2020-03-10 11:10   ` [dpdk-dev] [PATCH v2 1/4] lib: introduce IF Proxy library Andrzej Ostruszka
2020-07-02  0:34     ` Stephen Hemminger
2020-07-07 20:13       ` Andrzej Ostruszka [C]
2020-07-08 16:07         ` Morten Brørup
2020-07-09  8:43           ` Andrzej Ostruszka [C]
2020-07-22  0:40             ` Thomas Monjalon
2020-07-22  8:45               ` Jerin Jacob
2020-07-22  8:56                 ` Thomas Monjalon
2020-07-22  9:09                   ` Jerin Jacob
2020-07-22  9:27                     ` Thomas Monjalon
2020-07-22  9:54                       ` Jerin Jacob
2020-07-23 14:09                         ` [dpdk-dev] [EXT] " Andrzej Ostruszka [C]
2020-03-10 11:10   ` [dpdk-dev] [PATCH v2 2/4] if_proxy: add library documentation Andrzej Ostruszka
2020-03-10 11:10   ` [dpdk-dev] [PATCH v2 3/4] if_proxy: add simple functionality test Andrzej Ostruszka
2020-03-10 11:10   ` [dpdk-dev] [PATCH v2 4/4] if_proxy: add example application Andrzej Ostruszka
2020-03-25  8:08   ` [dpdk-dev] [PATCH v2 0/4] Introduce IF proxy library David Marchand
2020-03-25 11:11     ` Morten Brørup
2020-03-26 17:42       ` Andrzej Ostruszka
2020-04-02 13:48         ` Andrzej Ostruszka [C]
2020-04-03 17:19           ` Thomas Monjalon
2020-04-03 19:09             ` Jerin Jacob
2020-04-03 21:18               ` Morten Brørup
2020-04-03 21:57                 ` Thomas Monjalon
2020-04-04 10:18                   ` Jerin Jacob
2020-04-10 10:41                     ` Morten Brørup
2020-04-04 18:30             ` Andrzej Ostruszka [C]
2020-04-04 19:58               ` Thomas Monjalon
2020-04-10 10:03                 ` Morten Brørup
2020-04-10 12:28                   ` Jerin Jacob
2020-03-26 12:41     ` Andrzej Ostruszka
2020-03-30 19:23       ` Andrzej Ostruszka
2020-04-03 21:42   ` Thomas Monjalon
2020-04-04 18:07     ` Andrzej Ostruszka [C]
2020-04-04 19:51       ` Thomas Monjalon
2020-04-16 16:11 ` [dpdk-dev] [PATCH " Stephen Hemminger
2020-04-16 16:49   ` Jerin Jacob
2020-04-16 17:04     ` Stephen Hemminger
2020-04-16 17:26       ` Andrzej Ostruszka [C]
2020-04-16 17:27       ` Jerin Jacob
2020-04-16 17:12     ` Andrzej Ostruszka [C]
2020-04-16 17:19       ` Stephen Hemminger
2020-05-04  8:53 ` [dpdk-dev] [PATCH v3 " Andrzej Ostruszka
2020-05-04  8:53   ` [dpdk-dev] [PATCH v3 1/4] lib: introduce IF Proxy library Andrzej Ostruszka
2020-05-04  8:53   ` [dpdk-dev] [PATCH v3 2/4] if_proxy: add library documentation Andrzej Ostruszka
2020-05-04  8:53   ` [dpdk-dev] [PATCH v3 3/4] if_proxy: add simple functionality test Andrzej Ostruszka
2020-05-04  8:53   ` [dpdk-dev] [PATCH v3 4/4] if_proxy: add example application Andrzej Ostruszka
2020-06-22  9:21 ` [dpdk-dev] [PATCH v4 0/4] Introduce IF proxy library Andrzej Ostruszka
2020-06-22  9:21   ` [dpdk-dev] [PATCH v4 1/4] lib: introduce IF Proxy library Andrzej Ostruszka
2020-06-22  9:21   ` [dpdk-dev] [PATCH v4 2/4] if_proxy: add library documentation Andrzej Ostruszka
2020-06-22  9:21   ` [dpdk-dev] [PATCH v4 3/4] if_proxy: add simple functionality test Andrzej Ostruszka
2020-06-22  9:21   ` [dpdk-dev] [PATCH v4 4/4] if_proxy: add example application Andrzej Ostruszka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200306164104.15528-4-aostruszka@marvell.com \
    --to=aostruszka@marvell.com \
    --cc=dev@dpdk.org \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).