[dpdk-dev] dpdk/vpp and cross-version migration for vhost
Hi Michael, On 10/13/2016 07:50 PM, Michael S. Tsirkin wrote: > Hi! > So it looks like we face a problem with cross-version > migration when using vhost. It's not new but became more > acute with the advent of vhost user. > > For users to be able to migrate between different versions > of the hypervisor the interface exposed to guests > by hypervisor must stay unchanged. > > The problem is that a qemu device is connected > to a backend in another process, so the interface > exposed to guests depends on the capabilities of that > process. > > Specifically, for vhost user interface based on virtio, this includes > the "host features" bitmap that defines the interface, as well as more > host values such as the max ring size. Adding new features/changing > values to this interface is required to make progress, but on the other > hand we need ability to get the old host features to be compatible. > > To solve this problem within qemu, qemu has a versioning system based on > a machine type concept which fundamentally is a version string, by > specifying that string one can get hardware compatible with a previous > qemu version. QEMU also reports the latest version and list of versions > supported so libvirt records the version at VM creation and then is > careful to use this machine version whenever it migrates a VM. > > One might wonder how is this solved with a kernel vhost backend. The > answer is that it mostly isn't - instead an assumption is made, that > qemu versions are deployed together with the kernel - this is generally > true for downstreams. Thus whenever qemu gains a new feature, it is > already supported by the kernel as well. However, if one attempts > migration with a new qemu from a system with a new to old kernel, one > would get a failure. > > In the world where we have multiple userspace backends, with some of > these supplied by ISVs, this seems non-realistic. > > IMO we need to support vhost backend versioning, ideally > in a way that will also work for vhost kernel backends. > > So I'd like to get some input from both backend and management > developers on what a good solution would look like. > > If we want to emulate the qemu solution, this involves adding the > concept of interface versions to dpdk. For example, dpdk could supply a > file (or utility printing?) with list of versions: latest and versions > supported. libvirt could read that and So if I understand correctly, it would be generated at build time? One problem I see is that the DPDK's vhost-user lib API provides a way to disable features: " rte_vhost_feature_disable/rte_vhost_feature_enable(feature_mask) This function disables/enables some features. For example, it can be used to disable mergeable buffers and TSO features, which both are enabled by default. " I think we should not have this capability on host side, it should be guest's decision to use or not some features, and if it has to be done on host, QEMU already provides a way to disable features (moreover per-device, which is not the case with rte_vhost_feature_disable). IMHO, we should consider deprecating this API in v17.02. That said, the API is here, and it would break migration if the version file advertises some features the vSwitch has disabled at runtime. > - store latest version at vm creation > - pass it around with the vm > - pass it to qemu > From here, qemu could pass this over the vhost-user channel, > thus making sure it's initialized with the correct > compatible interface. Using vhost-user protocol features I guess? > As version here is an opaque string for libvirt and qemu, > anything can be used - but I suggest either a list > of values defining the interface, e.g. > any_layout=on,max_ring=256 > or a version including the name and vendor of the backend, > e.g. "org.dpdk.v4.5.6". I think the first option provides more flexibility. For example, we could imagine migrating from a process using DPDK's vhost-user lib, to another process using its own implementation (VPP has its own implementation currently if I'm not mistaken). Maybe this scenario does not make sense, but in this case, exposing values directly would avoid the need for synchronization between vhost-user implementations. > > Note that typically the list of supported versions can only be > extended, not shrunk. Also, if the host/guest interface > does not change, don't change the current version as > this just creates work for everyone. > > Thoughts? Would this work well for management? dpdk? vpp? One thing I'm not clear is how it will work for the MTU feature, if the process it is migrated to exposes a larger MTU that the guest doesn't support (if it has sized receive buffers to pre-migration MTU for example). Thanks, Maxime
[dpdk-dev] [PATCH 7/7] examples/eventdev_pipeline: adding example
This patch adds a sample app to the examples/ directory, which can be used as a reference application and for general testing. The application requires two ethdev ports and expects traffic to be flowing. The application must be run with the --vdev flags as follows to indicate to EAL that a virtual eventdev device called "evdev_sw0" is available to be used: ./build/eventdev_pipeline --vdev evdev_sw0 The general flow of the traffic is as follows: Rx core -> Atomic Queue => 4 worker cores => TX core A scheduler core is required to do the packet scheduling, making this configuration require 7 cores (Rx, Tx, Scheduler, and 4 workers). Finally a master core brings the core count to 8 for this configuration. The application can be configured for various numbers of flows and worker cores. Run the application with -h for details. Signed-off-by: Gage Eads Signed-off-by: Bruce Richardson Signed-off-by: Harry van Haaren --- examples/eventdev_pipeline/Makefile | 49 +++ examples/eventdev_pipeline/main.c | 718 2 files changed, 767 insertions(+) create mode 100644 examples/eventdev_pipeline/Makefile create mode 100644 examples/eventdev_pipeline/main.c diff --git a/examples/eventdev_pipeline/Makefile b/examples/eventdev_pipeline/Makefile new file mode 100644 index 000..bab8916 --- /dev/null +++ b/examples/eventdev_pipeline/Makefile @@ -0,0 +1,49 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +ifeq ($(RTE_SDK),) +$(error "Please define RTE_SDK environment variable") +endif + +# Default target, can be overriden by command line or environment +RTE_TARGET ?= x86_64-native-linuxapp-gcc + +include $(RTE_SDK)/mk/rte.vars.mk + +# binary name +APP = eventdev_pipeline + +# all source are stored in SRCS-y +SRCS-y := main.c + +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) + +include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/examples/eventdev_pipeline/main.c b/examples/eventdev_pipeline/main.c new file mode 100644 index 000..6a8052c --- /dev/null +++ b/examples/eventdev_pipeline/main.c @@ -0,0 +1,718 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +
[dpdk-dev] [PATCH 6/7] test/eventdev: unit func makefiles
Enable the functional and unit tests in the makefile. To run the unit tests, apply these patches, and run the test app with the following arguments and choose the unit or functional test to run: ./test --vdev evdev_sw0 RTE>> eventdev_func_autotest RTE>> eventdev_unit_autotest Signed-off-by: Gage Eads Signed-off-by: David Hunt Signed-off-by: Harry van Haaren --- app/test/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/test/Makefile b/app/test/Makefile index 5be023a..6d43cb7 100644 --- a/app/test/Makefile +++ b/app/test/Makefile @@ -197,6 +197,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev_blockcipher.c SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev_perf.c SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev.c +SRCS-$(CONFIG_RTE_LIBRTE_EVENTDEV) += test_eventdev_unit.c +SRCS-$(CONFIG_RTE_LIBRTE_EVENTDEV) += test_eventdev_func.c + SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) += test_kvargs.c CFLAGS += -O3 -- 2.7.4
[dpdk-dev] [PATCH 5/7] test/eventdev: unit and functional tests
This commit adds basic unit and functional tests for the eventdev API. The test code is added in this commit, but not yet enabled until the next commit. Signed-off-by: Gage Eads Signed-off-by: David Hunt Signed-off-by: Harry van Haaren --- app/test/test_eventdev_func.c | 1268 + app/test/test_eventdev_unit.c | 557 ++ 2 files changed, 1825 insertions(+) create mode 100644 app/test/test_eventdev_func.c create mode 100644 app/test/test_eventdev_unit.c diff --git a/app/test/test_eventdev_func.c b/app/test/test_eventdev_func.c new file mode 100644 index 000..d7fe481 --- /dev/null +++ b/app/test/test_eventdev_func.c @@ -0,0 +1,1268 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "test.h" + +#define MAX_PORTS 16 +#define MAX_QIDS 16 +#define NUM_PACKETS (1<<18) + +struct test { + struct rte_mempool *mbuf_pool; + int ev; + int port[MAX_PORTS]; + int qid[MAX_QIDS]; + int nb_qids; +}; + +static inline struct rte_mbuf * +rte_gen_arp(int portid, struct rte_mempool *mp) +{ + /* + * len = 14 + 46 + * ARP, Request who-has 10.0.0.1 tell 10.0.0.2, length 46 + */ + static const uint8_t arp_request[] = { + /*0x:*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xa8, + 0x6b, 0xfd, 0x02, 0x29, 0x08, 0x06, 0x00, 0x01, + /*0x0010:*/ 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xec, 0xa8, + 0x6b, 0xfd, 0x02, 0x29, 0x0a, 0x00, 0x00, 0x01, + /*0x0020:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*0x0030:*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + struct rte_mbuf *m; + int pkt_len = sizeof(arp_request) - 1; + + m = rte_pktmbuf_alloc(mp); + if (!m) + return 0; + + memcpy((void *)((uint64_t)m->buf_addr + m->data_off), + arp_request, pkt_len); + rte_pktmbuf_pkt_len(m) = pkt_len; + rte_pktmbuf_data_len(m) = pkt_len; + + RTE_SET_USED(portid); + /* +* Ignore MAC address for super-simple testing +* struct ether_addr mac_addr; +* rte_eth_macaddr_get(portid, &mac_addr); +* memcpy((void *)((uint64_t)m->buf_addr + m->data_off + 6), +* &mac_addr, 6); +*/ + + return m; +} + +/* initialization and config */ +static inline int +init(struct test *t, int nb_queues, int nb_ports) +{ + struct rte_event_dev_config config = { + .nb_event_queues = nb_queues, + .nb_event_ports = nb_ports, + }; + int ret, nevdevs = rte_event_dev_count(); + + void *temp = t->mbuf_pool; /* save and restore mbuf pool */ + + memset(t, 0, sizeof(*t)); + t->mbuf_pool = temp; + + if (nevdevs < 1) { + printf("%d: No Eventdev Devices Found\n", __LINE__); + return -1; + } + + const char *eventdev_name = "evdev_sw0"; + + t->ev = rte_event_dev_get_dev_id(eventde
[dpdk-dev] [PATCH 4/7] event/sw: makefiles and config
This commit modifies the existing Makefiles to have the sw_evdev instance compiled. At this point in the patchset, the infrastructure and sw_evdev pmd is compiled, which means that it can be instantiated and used successfully. Signed-off-by: Gage Eads Signed-off-by: Bruce Richardson Signed-off-by: Harry van Haaren --- config/common_base | 6 ++ drivers/event/Makefile | 2 ++ mk/rte.app.mk | 4 3 files changed, 12 insertions(+) diff --git a/config/common_base b/config/common_base index a0a07f6..862178a 100644 --- a/config/common_base +++ b/config/common_base @@ -417,6 +417,12 @@ CONFIG_RTE_LIBRTE_EVENTDEV=y CONFIG_RTE_LIBRTE_EVENTDEV_DEBUG=n # +# Compile a pure sw event device instance +# +CONFIG_RTE_LIBRTE_PMD_EVDEV_SW=y +CONFIG_RTE_LIBRTE_PMD_EVDEV_SW_DEBUG=n + +# # Compile librte_ring # CONFIG_RTE_LIBRTE_RING=y diff --git a/drivers/event/Makefile b/drivers/event/Makefile index 93f90eb..b9c37d7 100644 --- a/drivers/event/Makefile +++ b/drivers/event/Makefile @@ -31,4 +31,6 @@ include $(RTE_SDK)/mk/rte.vars.mk +DIRS-$(CONFIG_RTE_LIBRTE_PMD_EVDEV_SW) += sw + include $(RTE_SDK)/mk/rte.subdir.mk diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 716725a..2fce863 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -148,6 +148,10 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_ZUC) += -lrte_pmd_zuc _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_ZUC) += -L$(LIBSSO_ZUC_PATH)/build -lsso_zuc endif # CONFIG_RTE_LIBRTE_CRYPTODEV +ifeq ($(CONFIG_RTE_LIBRTE_EVENTDEV),y) +_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_EVDEV_SW)+= -lrte_pmd_evdev_sw +endif # CONFIG_RTE_LIBRTE_EVENTDEV + endif # !CONFIG_RTE_BUILD_SHARED_LIBS _LDLIBS-y += --no-whole-archive -- 2.7.4
[dpdk-dev] [PATCH 3/7] event/sw: software eventdev implementation
This commit adds a software implementation of the eventdev API. The implementation here is intended to enable the community to use the eventdev API, and test if the API serves the purpose that it is designed to. It should be noted this is an RFC implementation, and hence there should be no performance expectations. Note that the code added here is based on a prototype implementation, and hence some cleanup is expected to be necessary. The main components of the implementation is three files: - sw_evdev.c Creation, configuration, etc - sw_evdev_worker.c Worker cores' enqueue (etc) functions - sw_evdev_scheduler.cCore pkt scheduling implementation This commit only adds the implementation, no existing DPDK files are modified. Signed-off-by: Gage Eads Signed-off-by: Bruce Richardson Signed-off-by: Harry van Haaren --- drivers/event/sw/Makefile | 59 +++ drivers/event/sw/event_ring.h | 142 ++ drivers/event/sw/iq_ring.h| 160 +++ drivers/event/sw/rte_pmd_evdev_sw_version.map | 3 + drivers/event/sw/sw_evdev.c | 619 drivers/event/sw/sw_evdev.h | 234 + drivers/event/sw/sw_evdev_scheduler.c | 660 ++ drivers/event/sw/sw_evdev_worker.c| 218 + 8 files changed, 2095 insertions(+) create mode 100644 drivers/event/sw/Makefile create mode 100644 drivers/event/sw/event_ring.h create mode 100644 drivers/event/sw/iq_ring.h create mode 100644 drivers/event/sw/rte_pmd_evdev_sw_version.map create mode 100644 drivers/event/sw/sw_evdev.c create mode 100644 drivers/event/sw/sw_evdev.h create mode 100644 drivers/event/sw/sw_evdev_scheduler.c create mode 100644 drivers/event/sw/sw_evdev_worker.c diff --git a/drivers/event/sw/Makefile b/drivers/event/sw/Makefile new file mode 100644 index 000..7fc4371 --- /dev/null +++ b/drivers/event/sw/Makefile @@ -0,0 +1,59 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +include $(RTE_SDK)/mk/rte.vars.mk + + +# library name +LIB = librte_pmd_evdev_sw.a + +# build flags +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) + +# library version +LIBABIVER := 1 + +# versioning export map +EXPORT_MAP := rte_pmd_evdev_sw_version.map + +# library source files +SRCS-$(CONFIG_RTE_LIBRTE_PMD_EVDEV_SW) += sw_evdev.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_EVDEV_SW) += sw_evdev_worker.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_EVDEV_SW) += sw_evdev_scheduler.c + +# export include files +SYMLINK-y-include += + +# library dependencies +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_EVDEV_SW) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_EVDEV_SW) += lib/librte_eventdev + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/drivers/event/sw/event_ring.h b/drivers/event/sw/event_ring.h new file mode 100644 index 000..531fb68 --- /dev/null +++ b/drivers/event/sw/event_ring.h @@ -0,0 +1,142 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must repr
[dpdk-dev] [PATCH 2/7] eventdev: makefiles
Makefiles that compile the previously committed eventdev header and infrastructure files. This commit changes the Makefiles and config/base to add the config options of building the eventdev. Signed-off-by: Gage Eads Signed-off-by: Bruce Richardson Signed-off-by: Harry van Haaren --- config/common_base | 6 drivers/Makefile | 1 + drivers/event/Makefile | 34 lib/Makefile | 1 + lib/librte_eal/common/include/rte_vdev.h | 1 + lib/librte_eventdev/Makefile | 54 mk/rte.app.mk| 1 + 7 files changed, 98 insertions(+) create mode 100644 drivers/event/Makefile create mode 100644 lib/librte_eventdev/Makefile diff --git a/config/common_base b/config/common_base index 4bff83a..a0a07f6 100644 --- a/config/common_base +++ b/config/common_base @@ -411,6 +411,12 @@ CONFIG_RTE_LIBRTE_PMD_ZUC_DEBUG=n CONFIG_RTE_LIBRTE_PMD_NULL_CRYPTO=y # +# Compile event device library +# +CONFIG_RTE_LIBRTE_EVENTDEV=y +CONFIG_RTE_LIBRTE_EVENTDEV_DEBUG=n + +# # Compile librte_ring # CONFIG_RTE_LIBRTE_RING=y diff --git a/drivers/Makefile b/drivers/Makefile index 81c03a8..40b8347 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -33,5 +33,6 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += net DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += crypto +DIRS-$(CONFIG_RTE_LIBRTE_EVENTDEV) += event include $(RTE_SDK)/mk/rte.subdir.mk diff --git a/drivers/event/Makefile b/drivers/event/Makefile new file mode 100644 index 000..93f90eb --- /dev/null +++ b/drivers/event/Makefile @@ -0,0 +1,34 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +include $(RTE_SDK)/mk/rte.vars.mk + +include $(RTE_SDK)/mk/rte.subdir.mk diff --git a/lib/Makefile b/lib/Makefile index 990f23a..75b9868 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump +DIRS-$(CONFIG_RTE_LIBRTE_EVENTDEV) += librte_eventdev ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_eal/common/include/rte_vdev.h b/lib/librte_eal/common/include/rte_vdev.h index 784e837..22c1e19 100644 --- a/lib/librte_eal/common/include/rte_vdev.h +++ b/lib/librte_eal/common/include/rte_vdev.h @@ -38,6 +38,7 @@ extern "C" { #endif #include +#include #include /** Double linked list of virtual device drivers. */ diff --git a/lib/librte_eventdev/Makefile b/lib/librte_eventdev/Makefile new file mode 100644 index 000..5e2c467 --- /dev/null +++ b/lib/librte_eventdev/Makefile @@ -0,0 +1,54 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the f
[dpdk-dev] [PATCH 1/7] eventdev: header and implementation
This commit adds the eventdev API header, and the library infrastructure necessary to work with an eventdev instance. The header is mostly the same as discussed on the mailing list, in particular see the libeventdev RFC thread[1]. A second thread[2] gathered input from the community, which resulted in various modifications to the header. Since then, some modifications have been made that were discovered during the implementation of the software implementation of an eventdev. These changes are present in this header as suggestions, and feedback on these changes is welcomed. Some of the main items are: - A statistics API, similar to rte_ethdev_stats_get() - A dump API, similar to rte_ring_dump() - Return value of rte_eventdev_enqueue() changed for dequeue consistency - rte_event has implementation/operation field as discussed[3] - Add enqueue types using operation[4] This commit does not change any existing DPDK code - only adds the eventdev header and infrastructure. Signed-off-by: Gage Eads Signed-off-by: Bruce Richardson Signed-off-by: Harry van Haaren [1] http://dpdk.org/ml/archives/dev/2016-August/045181.html [2] http://dpdk.org/ml/archives/dev/2016-October/048196.html [3] http://dpdk.org/ml/archives/dev/2016-October/049459.html [4] http://dpdk.org/ml/archives/dev/2016-October/049641.html --- lib/librte_eventdev/rte_eventdev.c | 466 ++ lib/librte_eventdev/rte_eventdev.h | 1272 ++ lib/librte_eventdev/rte_eventdev_ops.h | 177 lib/librte_eventdev/rte_eventdev_pmd.h | 69 ++ lib/librte_eventdev/rte_eventdev_version.map | 33 + 5 files changed, 2017 insertions(+) create mode 100644 lib/librte_eventdev/rte_eventdev.c create mode 100644 lib/librte_eventdev/rte_eventdev.h create mode 100644 lib/librte_eventdev/rte_eventdev_ops.h create mode 100644 lib/librte_eventdev/rte_eventdev_pmd.h create mode 100644 lib/librte_eventdev/rte_eventdev_version.map diff --git a/lib/librte_eventdev/rte_eventdev.c b/lib/librte_eventdev/rte_eventdev.c new file mode 100644 index 000..aace5ca --- /dev/null +++ b/lib/librte_eventdev/rte_eventdev.c @@ -0,0 +1,466 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. + */ + +#include + +#include +#include +#include +#include "rte_eventdev.h" +#include "rte_eventdev_pmd.h" +#include "rte_eventdev_ops.h" + +#define RTE_MAX_EVENT_DEVS 32 +struct rte_event_dev *event_devs[RTE_MAX_EVENT_DEVS]; +static int rte_num_event_dev_pmds; + +TAILQ_HEAD(rte_eventdev_list, rte_event_dev); + +static struct rte_tailq_elem rte_eventdev_tailq = { + .name = "EVENT_DEVS", +}; +EAL_REGISTER_TAILQ(rte_eventdev_tailq) + +#ifdef RTE_LIBRTE_EVENTDEV_DEBUG +#define RTE_PMD_DEBUG_TRACE(...) \ + rte_pmd_debug_trace(__func__, __VA_ARGS__) +#else +#define RTE_PMD_DEBUG_TRACE(...) +#endif + + +int +rte_event_dev_register(struct rte_event_dev *new_dev) +{ + uint8_t index = rte_num_event_dev_pmds; + struct rte_eventdev_list *list; + + list = RTE_TAILQ_CAST(rte_eventdev_tailq.head, rte_eventdev_list); + + /* The primary process is responsible for adding the eventdevs to the +* tailQ, and the secondary processes simply look up the eventdev in +* the list and add it to their local array for fast access. +*/ + if
[dpdk-dev] [RFC PATCH 0/7] RFC: EventDev Software PMD
This series of RFC patches implements the libeventdev API and a software eventdev PMD. The implementation here is intended to enable the community to use the eventdev API, specifically to test if the API serves the purpose that it is designed to. It should be noted this is an RFC implementation, and hence there should be no performance expectations. An RFC for the eventdev was sent in August[1] by Jerin Jacob of Cavium, which introduced the core concepts of the eventdev to the community. Since then there has been extensive discussion[2] on the mailing list, which had led to various modifications to the initial proposed API. The API as presented in the first patch contains a number of changes that have not yet been discussed. These changes were noticed during the implementation of the software eventdev PMD, and were added to the API to enable completion of the PMD. These modifications include a statistics API and a dump API. For more details, please refer to the commit message of the patch itself. The functionality provided by each of the patches is as follows: 1: Add eventdev API and library infrastructure 2: Enable compilation of library 3: Add software eventdev PMD 4: Enable compilation of PMD 5: Add test code 6: Enable test code compilation 7: Sample application demonstrating basic usage This breakdown of the patchset hopefully enables the community to experiment with the eventdev API, and allows us all to gain first-hand experience in using the eventdev API. Note also that this patchset has not passed checkpatch testing just yet - will fix for v2 :) As next steps I see value in discussing the proposed changes included in this version of the header file, while welcoming feedback from the community on the API in general too. Signed-off-by: Harry van Haaren [1] http://dpdk.org/ml/archives/dev/2016-August/045181.html [2] http://dpdk.org/ml/archives/dev/2016-October/thread.html#48196 Harry van Haaren (7): eventdev: header and implementation eventdev: makefiles event/sw: software eventdev implementation event/sw: makefiles and config test/eventdev: unit and functional tests test/eventdev: unit func makefiles examples/eventdev_pipeline: adding example app/test/Makefile |3 + app/test/test_eventdev_func.c | 1272 app/test/test_eventdev_unit.c | 557 +++ config/common_base| 12 + drivers/Makefile |1 + drivers/event/Makefile| 36 + drivers/event/sw/Makefile | 59 ++ drivers/event/sw/event_ring.h | 142 +++ drivers/event/sw/iq_ring.h| 160 +++ drivers/event/sw/rte_pmd_evdev_sw_version.map |3 + drivers/event/sw/sw_evdev.c | 619 drivers/event/sw/sw_evdev.h | 234 + drivers/event/sw/sw_evdev_scheduler.c | 660 + drivers/event/sw/sw_evdev_worker.c| 218 + examples/eventdev_pipeline/Makefile | 49 + examples/eventdev_pipeline/main.c | 717 ++ lib/Makefile |1 + lib/librte_eal/common/include/rte_vdev.h |1 + lib/librte_eventdev/Makefile | 54 ++ lib/librte_eventdev/rte_eventdev.c| 466 + lib/librte_eventdev/rte_eventdev.h| 1289 + lib/librte_eventdev/rte_eventdev_ops.h| 177 lib/librte_eventdev/rte_eventdev_pmd.h| 69 ++ lib/librte_eventdev/rte_eventdev_version.map | 33 + mk/rte.app.mk |5 + 25 files changed, 6837 insertions(+) create mode 100644 app/test/test_eventdev_func.c create mode 100644 app/test/test_eventdev_unit.c create mode 100644 drivers/event/Makefile create mode 100644 drivers/event/sw/Makefile create mode 100644 drivers/event/sw/event_ring.h create mode 100644 drivers/event/sw/iq_ring.h create mode 100644 drivers/event/sw/rte_pmd_evdev_sw_version.map create mode 100644 drivers/event/sw/sw_evdev.c create mode 100644 drivers/event/sw/sw_evdev.h create mode 100644 drivers/event/sw/sw_evdev_scheduler.c create mode 100644 drivers/event/sw/sw_evdev_worker.c create mode 100644 examples/eventdev_pipeline/Makefile create mode 100644 examples/eventdev_pipeline/main.c create mode 100644 lib/librte_eventdev/Makefile create mode 100644 lib/librte_eventdev/rte_eventdev.c create mode 100644 lib/librte_eventdev/rte_eventdev.h create mode 100644 lib/librte_eventdev/rte_eventdev_ops.h create mode 100644 lib/librte_eventdev/rte_eventdev_pmd.h create mode 100644 lib/librte_eventdev/rte_eventdev_version.map -- 2.7.4
[dpdk-dev] [PATCH 22/22] app/testpmd: add queue actions to flow command
- QUEUE: assign packets to a given queue index. - DUP: duplicate packets to a given queue index. - RSS: spread packets among several queues. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 152 +++ 1 file changed, 152 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index e166045..70e2b76 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -157,8 +157,15 @@ enum index { ACTION_MARK, ACTION_MARK_ID, ACTION_FLAG, + ACTION_QUEUE, + ACTION_QUEUE_INDEX, ACTION_DROP, ACTION_COUNT, + ACTION_DUP, + ACTION_DUP_INDEX, + ACTION_RSS, + ACTION_RSS_QUEUES, + ACTION_RSS_QUEUE, ACTION_PF, ACTION_VF, ACTION_VF_ORIGINAL, @@ -172,6 +179,14 @@ enum index { #define ITEM_RAW_SIZE \ (offsetof(struct rte_flow_item_raw, pattern) + ITEM_RAW_PATTERN_SIZE) +/** Number of queue[] entries in struct rte_flow_action_rss. */ +#define ACTION_RSS_NUM 32 + +/** Storage size for struct rte_flow_action_rss including queues. */ +#define ACTION_RSS_SIZE \ + (offsetof(struct rte_flow_action_rss, queue) + \ +sizeof(*((struct rte_flow_action_rss *)0)->queue) * ACTION_RSS_NUM) + /** Maximum number of subsequent tokens and arguments on the stack. */ #define CTX_STACK_SIZE 16 @@ -489,8 +504,11 @@ static const enum index next_action[] = { ACTION_PASSTHRU, ACTION_MARK, ACTION_FLAG, + ACTION_QUEUE, ACTION_DROP, ACTION_COUNT, + ACTION_DUP, + ACTION_RSS, ACTION_PF, ACTION_VF, 0, @@ -502,6 +520,24 @@ static const enum index action_mark[] = { 0, }; +static const enum index action_queue[] = { + ACTION_QUEUE_INDEX, + ACTION_NEXT, + 0, +}; + +static const enum index action_dup[] = { + ACTION_DUP_INDEX, + ACTION_NEXT, + 0, +}; + +static const enum index action_rss[] = { + ACTION_RSS_QUEUES, + ACTION_NEXT, + 0, +}; + static const enum index action_vf[] = { ACTION_VF_ORIGINAL, ACTION_VF_ID, @@ -519,6 +555,9 @@ static int parse_vc_spec(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); static int parse_vc_conf(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_vc_action_rss_queue(struct context *, const struct token *, +const char *, unsigned int, void *, +unsigned int); static int parse_destroy(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -568,6 +607,8 @@ static int comp_port(struct context *, const struct token *, unsigned int, char *, unsigned int); static int comp_rule_id(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_vc_action_rss_queue(struct context *, const struct token *, + unsigned int, char *, unsigned int); /** Token definitions. */ static const struct token token_list[] = { @@ -1169,6 +1210,21 @@ static const struct token token_list[] = { .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), .call = parse_vc, }, + [ACTION_QUEUE] = { + .name = "queue", + .help = "assign packets to a given queue index", + .priv = PRIV_ACTION(QUEUE, + sizeof(struct rte_flow_action_queue)), + .next = NEXT(action_queue), + .call = parse_vc, + }, + [ACTION_QUEUE_INDEX] = { + .name = "index", + .help = "queue index to use", + .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)), + .call = parse_vc_conf, + }, [ACTION_DROP] = { .name = "drop", .help = "drop packets (note: passthru has priority)", @@ -1183,6 +1239,39 @@ static const struct token token_list[] = { .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), .call = parse_vc, }, + [ACTION_DUP] = { + .name = "dup", + .help = "duplicate packets to a given queue index", + .priv = PRIV_ACTION(DUP, sizeof(struct rte_flow_action_dup)), + .next = NEXT(action_dup), + .call = parse_vc, + }, + [ACTION_DUP_INDEX] = { + .name = "index", + .help = "queue index to duplicate packets to", + .next = NEXT(action_dup, NEXT_ENTRY(UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_dup, index)), +
[dpdk-dev] [PATCH 21/22] app/testpmd: add various actions to flow command
- MARK: attach 32 bit value to packets. - FLAG: flag packets. - DROP: drop packets. - COUNT: enable counters for a rule. - PF: redirect packets to physical device function. - VF: redirect packets to virtual device function. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 121 +++ 1 file changed, 121 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 892f300..e166045 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -154,6 +154,15 @@ enum index { ACTION_END, ACTION_VOID, ACTION_PASSTHRU, + ACTION_MARK, + ACTION_MARK_ID, + ACTION_FLAG, + ACTION_DROP, + ACTION_COUNT, + ACTION_PF, + ACTION_VF, + ACTION_VF_ORIGINAL, + ACTION_VF_ID, }; /** Size of pattern[] field in struct rte_flow_item_raw. */ @@ -478,6 +487,25 @@ static const enum index next_action[] = { ACTION_END, ACTION_VOID, ACTION_PASSTHRU, + ACTION_MARK, + ACTION_FLAG, + ACTION_DROP, + ACTION_COUNT, + ACTION_PF, + ACTION_VF, + 0, +}; + +static const enum index action_mark[] = { + ACTION_MARK_ID, + ACTION_NEXT, + 0, +}; + +static const enum index action_vf[] = { + ACTION_VF_ORIGINAL, + ACTION_VF_ID, + ACTION_NEXT, 0, }; @@ -489,6 +517,8 @@ static int parse_vc(struct context *, const struct token *, void *, unsigned int); static int parse_vc_spec(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_vc_conf(struct context *, const struct token *, +const char *, unsigned int, void *, unsigned int); static int parse_destroy(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -1118,6 +1148,70 @@ static const struct token token_list[] = { .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), .call = parse_vc, }, + [ACTION_MARK] = { + .name = "mark", + .help = "attach 32 bit value to packets", + .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)), + .next = NEXT(action_mark), + .call = parse_vc, + }, + [ACTION_MARK_ID] = { + .name = "id", + .help = "32 bit value to return with packets", + .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)), + .call = parse_vc_conf, + }, + [ACTION_FLAG] = { + .name = "flag", + .help = "flag packets", + .priv = PRIV_ACTION(FLAG, 0), + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), + .call = parse_vc, + }, + [ACTION_DROP] = { + .name = "drop", + .help = "drop packets (note: passthru has priority)", + .priv = PRIV_ACTION(DROP, 0), + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), + .call = parse_vc, + }, + [ACTION_COUNT] = { + .name = "count", + .help = "enable counters for this rule", + .priv = PRIV_ACTION(COUNT, 0), + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), + .call = parse_vc, + }, + [ACTION_PF] = { + .name = "pf", + .help = "redirect packets to physical device function", + .priv = PRIV_ACTION(PF, 0), + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), + .call = parse_vc, + }, + [ACTION_VF] = { + .name = "vf", + .help = "redirect packets to virtual device function", + .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)), + .next = NEXT(action_vf), + .call = parse_vc, + }, + [ACTION_VF_ORIGINAL] = { + .name = "original", + .help = "use original VF ID if possible", + .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)), + .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf, + original)), + .call = parse_vc_conf, + }, + [ACTION_VF_ID] = { + .name = "id", + .help = "VF ID to redirect packets to", + .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)), + .call = parse_vc_conf, + }, }; /** Remove and return last entry from argument stack. */ @@ -1441,6 +1535,33 @@ parse_vc_spec(struct context *ctx, const struct token *token, return len; } +/** Parse action configuration field. */ +static int +parse_vc_conf(struct conte
[dpdk-dev] [PATCH 20/22] app/testpmd: add L4 items to flow command
Add the ability to match a few properties of common L4[.5] protocol headers: - ICMP: type and code. - UDP: source and destination ports. - TCP: source and destination ports. - SCTP: source and destination ports. - VXLAN: network identifier. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 163 +++ 1 file changed, 163 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 75096df..892f300 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -133,6 +133,20 @@ enum index { ITEM_IPV6, ITEM_IPV6_SRC, ITEM_IPV6_DST, + ITEM_ICMP, + ITEM_ICMP_TYPE, + ITEM_ICMP_CODE, + ITEM_UDP, + ITEM_UDP_SRC, + ITEM_UDP_DST, + ITEM_TCP, + ITEM_TCP_SRC, + ITEM_TCP_DST, + ITEM_SCTP, + ITEM_SCTP_SRC, + ITEM_SCTP_DST, + ITEM_VXLAN, + ITEM_VXLAN_VNI, /* Validate/create actions. */ ACTIONS, @@ -360,6 +374,11 @@ static const enum index next_item[] = { ITEM_VLAN, ITEM_IPV4, ITEM_IPV6, + ITEM_ICMP, + ITEM_UDP, + ITEM_TCP, + ITEM_SCTP, + ITEM_VXLAN, 0, }; @@ -421,6 +440,40 @@ static const enum index item_ipv6[] = { 0, }; +static const enum index item_icmp[] = { + ITEM_ICMP_TYPE, + ITEM_ICMP_CODE, + ITEM_NEXT, + 0, +}; + +static const enum index item_udp[] = { + ITEM_UDP_SRC, + ITEM_UDP_DST, + ITEM_NEXT, + 0, +}; + +static const enum index item_tcp[] = { + ITEM_TCP_SRC, + ITEM_TCP_DST, + ITEM_NEXT, + 0, +}; + +static const enum index item_sctp[] = { + ITEM_SCTP_SRC, + ITEM_SCTP_DST, + ITEM_NEXT, + 0, +}; + +static const enum index item_vxlan[] = { + ITEM_VXLAN_VNI, + ITEM_NEXT, + 0, +}; + static const enum index next_action[] = { ACTION_END, ACTION_VOID, @@ -936,6 +989,103 @@ static const struct token token_list[] = { .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, hdr.dst_addr)), }, + [ITEM_ICMP] = { + .name = "icmp", + .help = "match ICMP header", + .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)), + .next = NEXT(item_icmp), + .call = parse_vc, + }, + [ITEM_ICMP_TYPE] = { + .name = "type", + .help = "ICMP packet type", + .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, +hdr.icmp_type)), + }, + [ITEM_ICMP_CODE] = { + .name = "code", + .help = "ICMP packet code", + .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, +hdr.icmp_code)), + }, + [ITEM_UDP] = { + .name = "udp", + .help = "match UDP header", + .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)), + .next = NEXT(item_udp), + .call = parse_vc, + }, + [ITEM_UDP_SRC] = { + .name = "src", + .help = "UDP source port", + .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp, +hdr.src_port)), + }, + [ITEM_UDP_DST] = { + .name = "dst", + .help = "UDP destination port", + .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp, +hdr.dst_port)), + }, + [ITEM_TCP] = { + .name = "tcp", + .help = "match TCP header", + .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)), + .next = NEXT(item_tcp), + .call = parse_vc, + }, + [ITEM_TCP_SRC] = { + .name = "src", + .help = "TCP source port", + .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, +hdr.src_port)), + }, + [ITEM_TCP_DST] = { + .name = "dst", + .help = "TCP destination port", + .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, +hdr.dst_port)), + }, + [ITEM_SCTP] = { + .name = "sctp", + .help = "match
[dpdk-dev] [PATCH 19/22] app/testpmd: add items ipv4/ipv6 to flow command
Add the ability to match basic fields from IPv4 and IPv6 headers (source and destination addresses only). Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 177 +++ 1 file changed, 177 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index f2bd405..75096df 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,8 @@ enum index { BOOLEAN, STRING, MAC_ADDR, + IPV4_ADDR, + IPV6_ADDR, RULE_ID, PORT_ID, GROUP_ID, @@ -124,6 +127,12 @@ enum index { ITEM_VLAN, ITEM_VLAN_TPID, ITEM_VLAN_TCI, + ITEM_IPV4, + ITEM_IPV4_SRC, + ITEM_IPV4_DST, + ITEM_IPV6, + ITEM_IPV6_SRC, + ITEM_IPV6_DST, /* Validate/create actions. */ ACTIONS, @@ -349,6 +358,8 @@ static const enum index next_item[] = { ITEM_RAW, ITEM_ETH, ITEM_VLAN, + ITEM_IPV4, + ITEM_IPV6, 0, }; @@ -396,6 +407,20 @@ static const enum index item_vlan[] = { 0, }; +static const enum index item_ipv4[] = { + ITEM_IPV4_SRC, + ITEM_IPV4_DST, + ITEM_NEXT, + 0, +}; + +static const enum index item_ipv6[] = { + ITEM_IPV6_SRC, + ITEM_IPV6_DST, + ITEM_NEXT, + 0, +}; + static const enum index next_action[] = { ACTION_END, ACTION_VOID, @@ -441,6 +466,12 @@ static int parse_string(struct context *, const struct token *, static int parse_mac_addr(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_ipv4_addr(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_ipv6_addr(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_port(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -511,6 +542,20 @@ static const struct token token_list[] = { .call = parse_mac_addr, .comp = comp_none, }, + [IPV4_ADDR] = { + .name = "{IPv4 address}", + .type = "IPV4 ADDRESS", + .help = "standard IPv4 address notation", + .call = parse_ipv4_addr, + .comp = comp_none, + }, + [IPV6_ADDR] = { + .name = "{IPv6 address}", + .type = "IPV6 ADDRESS", + .help = "standard IPv6 address notation", + .call = parse_ipv6_addr, + .comp = comp_none, + }, [RULE_ID] = { .name = "{rule id}", .type = "RULE ID", @@ -849,6 +894,48 @@ static const struct token token_list[] = { .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)), }, + [ITEM_IPV4] = { + .name = "ipv4", + .help = "match IPv4 header", + .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)), + .next = NEXT(item_ipv4), + .call = parse_vc, + }, + [ITEM_IPV4_SRC] = { + .name = "src", + .help = "source address", + .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, +hdr.src_addr)), + }, + [ITEM_IPV4_DST] = { + .name = "dst", + .help = "destination address", + .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, +hdr.dst_addr)), + }, + [ITEM_IPV6] = { + .name = "ipv6", + .help = "match IPv6 header", + .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)), + .next = NEXT(item_ipv6), + .call = parse_vc, + }, + [ITEM_IPV6_SRC] = { + .name = "src", + .help = "source address", + .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, +hdr.src_addr)), + }, + [ITEM_IPV6_DST] = { + .name = "dst", + .help = "destination address", + .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param), + .args = ARGS(ARGS_ENTRY_HTON
[dpdk-dev] [PATCH 18/22] app/testpmd: add items eth/vlan to flow command
These pattern items match basic Ethernet headers (source, destination and type) and related 802.1Q/ad VLAN headers. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 126 +++ 1 file changed, 126 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 6f2f26c..f2bd405 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "testpmd.h" @@ -59,6 +60,7 @@ enum index { PREFIX, BOOLEAN, STRING, + MAC_ADDR, RULE_ID, PORT_ID, GROUP_ID, @@ -115,6 +117,13 @@ enum index { ITEM_RAW_OFFSET, ITEM_RAW_LIMIT, ITEM_RAW_PATTERN, + ITEM_ETH, + ITEM_ETH_DST, + ITEM_ETH_SRC, + ITEM_ETH_TYPE, + ITEM_VLAN, + ITEM_VLAN_TPID, + ITEM_VLAN_TCI, /* Validate/create actions. */ ACTIONS, @@ -239,6 +248,14 @@ struct token { .size = (sz), \ }) +/** Same as ARGS_ENTRY() using network byte ordering. */ +#define ARGS_ENTRY_HTON(s, f) \ + (&(const struct arg){ \ + .hton = 1, \ + .offset = offsetof(s, f), \ + .size = sizeof(((s *)0)->f), \ + }) + /** Parser output buffer layout expected by cmd_flow_parsed(). */ struct buffer { enum index command; /**< Flow command. */ @@ -330,6 +347,8 @@ static const enum index next_item[] = { ITEM_VF, ITEM_PORT, ITEM_RAW, + ITEM_ETH, + ITEM_VLAN, 0, }; @@ -362,6 +381,21 @@ static const enum index item_raw[] = { 0, }; +static const enum index item_eth[] = { + ITEM_ETH_DST, + ITEM_ETH_SRC, + ITEM_ETH_TYPE, + ITEM_NEXT, + 0, +}; + +static const enum index item_vlan[] = { + ITEM_VLAN_TPID, + ITEM_VLAN_TCI, + ITEM_NEXT, + 0, +}; + static const enum index next_action[] = { ACTION_END, ACTION_VOID, @@ -404,6 +438,9 @@ static int parse_boolean(struct context *, const struct token *, static int parse_string(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_mac_addr(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_port(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -467,6 +504,13 @@ static const struct token token_list[] = { .call = parse_string, .comp = comp_none, }, + [MAC_ADDR] = { + .name = "{MAC address}", + .type = "MAC-48", + .help = "standard MAC address notation", + .call = parse_mac_addr, + .comp = comp_none, + }, [RULE_ID] = { .name = "{rule id}", .type = "RULE ID", @@ -761,6 +805,50 @@ static const struct token token_list[] = { pattern, ITEM_RAW_PATTERN_SIZE)), }, + [ITEM_ETH] = { + .name = "eth", + .help = "match Ethernet header", + .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)), + .next = NEXT(item_eth), + .call = parse_vc, + }, + [ITEM_ETH_DST] = { + .name = "dst", + .help = "destination MAC", + .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param), + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_eth, dst)), + }, + [ITEM_ETH_SRC] = { + .name = "src", + .help = "source MAC", + .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param), + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_eth, src)), + }, + [ITEM_ETH_TYPE] = { + .name = "type", + .help = "EtherType", + .next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)), + }, + [ITEM_VLAN] = { + .name = "vlan", + .help = "match 802.1Q/ad VLAN tag", + .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)), + .next = NEXT(item_vlan), + .call = parse_vc, + }, + [ITEM_VLAN_TPID] = { + .name = "tpid", + .help = "tag protocol identifier", + .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tpid)), + }, + [ITEM_VLAN_TCI] = { + .name = "tci", + .help = "tag control
[dpdk-dev] [PATCH 17/22] app/testpmd: add item raw to flow command
Matches arbitrary byte strings with properties: - relative: look for pattern after the previous item. - search: search pattern from offset (see also limit). - offset: absolute or relative offset for pattern. - limit: search area limit for start of pattern. - length: pattern length. - pattern: byte string to look for. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 206 +++ 1 file changed, 206 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index c61e31e..6f2f26c 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -57,6 +57,8 @@ enum index { INTEGER, UNSIGNED, PREFIX, + BOOLEAN, + STRING, RULE_ID, PORT_ID, GROUP_ID, @@ -107,6 +109,12 @@ enum index { ITEM_VF_ID, ITEM_PORT, ITEM_PORT_INDEX, + ITEM_RAW, + ITEM_RAW_RELATIVE, + ITEM_RAW_SEARCH, + ITEM_RAW_OFFSET, + ITEM_RAW_LIMIT, + ITEM_RAW_PATTERN, /* Validate/create actions. */ ACTIONS, @@ -116,6 +124,13 @@ enum index { ACTION_PASSTHRU, }; +/** Size of pattern[] field in struct rte_flow_item_raw. */ +#define ITEM_RAW_PATTERN_SIZE 36 + +/** Storage size for struct rte_flow_item_raw including pattern. */ +#define ITEM_RAW_SIZE \ + (offsetof(struct rte_flow_item_raw, pattern) + ITEM_RAW_PATTERN_SIZE) + /** Maximum number of subsequent tokens and arguments on the stack. */ #define CTX_STACK_SIZE 16 @@ -217,6 +232,13 @@ struct token { .size = sizeof(*((s *)0)->f), \ }) +/** Static initializer for ARGS() with arbitrary size. */ +#define ARGS_ENTRY_USZ(s, f, sz) \ + (&(const struct arg){ \ + .offset = offsetof(s, f), \ + .size = (sz), \ + }) + /** Parser output buffer layout expected by cmd_flow_parsed(). */ struct buffer { enum index command; /**< Flow command. */ @@ -307,6 +329,7 @@ static const enum index next_item[] = { ITEM_PF, ITEM_VF, ITEM_PORT, + ITEM_RAW, 0, }; @@ -329,6 +352,16 @@ static const enum index item_port[] = { 0, }; +static const enum index item_raw[] = { + ITEM_RAW_RELATIVE, + ITEM_RAW_SEARCH, + ITEM_RAW_OFFSET, + ITEM_RAW_LIMIT, + ITEM_RAW_PATTERN, + ITEM_NEXT, + 0, +}; + static const enum index next_action[] = { ACTION_END, ACTION_VOID, @@ -365,11 +398,19 @@ static int parse_int(struct context *, const struct token *, static int parse_prefix(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_boolean(struct context *, const struct token *, +const char *, unsigned int, +void *, unsigned int); +static int parse_string(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_port(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); static int comp_none(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_boolean(struct context *, const struct token *, + unsigned int, char *, unsigned int); static int comp_action(struct context *, const struct token *, unsigned int, char *, unsigned int); static int comp_port(struct context *, const struct token *, @@ -412,6 +453,20 @@ static const struct token token_list[] = { .call = parse_prefix, .comp = comp_none, }, + [BOOLEAN] = { + .name = "{boolean}", + .type = "BOOLEAN", + .help = "any boolean value", + .call = parse_boolean, + .comp = comp_boolean, + }, + [STRING] = { + .name = "{string}", + .type = "STRING", + .help = "fixed string", + .call = parse_string, + .comp = comp_none, + }, [RULE_ID] = { .name = "{rule id}", .type = "RULE ID", @@ -662,6 +717,50 @@ static const struct token token_list[] = { .next = NEXT(item_port, NEXT_ENTRY(UNSIGNED), item_param), .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port, index)), }, + [ITEM_RAW] = { + .name = "raw", + .help = "match an arbitrary byte string", + .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE), + .next = NEXT(item_raw), + .call = parse_vc, + }, + [ITEM_RAW_RELATIVE] = { + .name = "relative", + .help = "look for pattern after the previous item", + .next = NEXT(item_r
[dpdk-dev] [PATCH 16/22] app/testpmd: add various items to flow command
- PF: match packets addressed to the physical function. - VF: match packets addressed to a virtual function ID. - PORT: device-specific physical port index to use. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 53 1 file changed, 53 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 5816be4..c61e31e 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -102,6 +102,11 @@ enum index { ITEM_ANY, ITEM_ANY_MIN, ITEM_ANY_MAX, + ITEM_PF, + ITEM_VF, + ITEM_VF_ID, + ITEM_PORT, + ITEM_PORT_INDEX, /* Validate/create actions. */ ACTIONS, @@ -299,6 +304,9 @@ static const enum index next_item[] = { ITEM_VOID, ITEM_INVERT, ITEM_ANY, + ITEM_PF, + ITEM_VF, + ITEM_PORT, 0, }; @@ -309,6 +317,18 @@ static const enum index item_any[] = { 0, }; +static const enum index item_vf[] = { + ITEM_VF_ID, + ITEM_NEXT, + 0, +}; + +static const enum index item_port[] = { + ITEM_PORT_INDEX, + ITEM_NEXT, + 0, +}; + static const enum index next_action[] = { ACTION_END, ACTION_VOID, @@ -609,6 +629,39 @@ static const struct token token_list[] = { .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param), .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, max)), }, + [ITEM_PF] = { + .name = "pf", + .help = "match packets addressed to the physical function", + .priv = PRIV_ITEM(PF, 0), + .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), + .call = parse_vc, + }, + [ITEM_VF] = { + .name = "vf", + .help = "match packets addressed to a virtual function ID", + .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)), + .next = NEXT(item_vf), + .call = parse_vc, + }, + [ITEM_VF_ID] = { + .name = "id", + .help = "destination VF ID", + .next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)), + }, + [ITEM_PORT] = { + .name = "port", + .help = "device-specific physical port index to use", + .priv = PRIV_ITEM(PORT, sizeof(struct rte_flow_item_port)), + .next = NEXT(item_port), + .call = parse_vc, + }, + [ITEM_PORT_INDEX] = { + .name = "index", + .help = "physical port index", + .next = NEXT(item_port, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port, index)), + }, /* Validate/create actions. */ [ACTIONS] = { .name = "actions", -- 2.1.4
[dpdk-dev] [PATCH 15/22] app/testpmd: add item any to flow command
This pattern item matches any protocol in place of the current layer and has two properties: - min: minimum number of layers covered (0 or more). - max: maximum number of layers covered (0 means infinity). Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 30 ++ 1 file changed, 30 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 81930e1..5816be4 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -99,6 +99,9 @@ enum index { ITEM_END, ITEM_VOID, ITEM_INVERT, + ITEM_ANY, + ITEM_ANY_MIN, + ITEM_ANY_MAX, /* Validate/create actions. */ ACTIONS, @@ -295,6 +298,14 @@ static const enum index next_item[] = { ITEM_END, ITEM_VOID, ITEM_INVERT, + ITEM_ANY, + 0, +}; + +static const enum index item_any[] = { + ITEM_ANY_MIN, + ITEM_ANY_MAX, + ITEM_NEXT, 0, }; @@ -579,6 +590,25 @@ static const struct token token_list[] = { .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), .call = parse_vc, }, + [ITEM_ANY] = { + .name = "any", + .help = "match any protocol for the current layer", + .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)), + .next = NEXT(item_any), + .call = parse_vc, + }, + [ITEM_ANY_MIN] = { + .name = "min", + .help = "minimum number of layers covered", + .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, min)), + }, + [ITEM_ANY_MAX] = { + .name = "max", + .help = "maximum number of layers covered, 0 for infinity", + .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param), + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, max)), + }, /* Validate/create actions. */ [ACTIONS] = { .name = "actions", -- 2.1.4
[dpdk-dev] [PATCH 14/22] app/testpmd: add rte_flow bit-field support
Several rte_flow structures expose bit-fields that cannot be set in a generic fashion at byte level. Add bit-mask support to handle them. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 59 1 file changed, 59 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 89307cb..81930e1 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -136,6 +136,7 @@ struct arg { uint32_t sign:1; /**< Value is signed. */ uint32_t offset; /**< Relative offset from ctx->object. */ uint32_t size; /**< Field size. */ + const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */ }; /** Parser token definition. */ @@ -195,6 +196,13 @@ struct token { .size = sizeof(((s *)0)->f), \ }) +/** Static initializer for ARGS() to target a bit-field. */ +#define ARGS_ENTRY_BF(s, f) \ + (&(const struct arg){ \ + .size = sizeof(s), \ + .mask = (const void *)&(const s){ .f = -1 }, \ + }) + /** Static initializer for ARGS() to target a pointer. */ #define ARGS_ENTRY_PTR(s, f) \ (&(const struct arg){ \ @@ -622,6 +630,34 @@ push_args(struct context *ctx, const struct arg *arg) return 0; } +/** Spread value into buffer according to bit-mask. */ +static size_t +arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg) +{ + uint32_t i; + size_t len = 0; + + /* Endian conversion is not supported on bit-fields. */ + if (!arg->mask || arg->hton) + return 0; + for (i = 0; i != arg->size; ++i) { + unsigned int shift = 0; + uint8_t *buf = (uint8_t *)dst + i; + + for (shift = 0; arg->mask[i] >> shift; ++shift) { + if (!(arg->mask[i] & (1 << shift))) + continue; + ++len; + if (!dst) + continue; + *buf &= ~(1 << shift); + *buf |= (val & 1) << shift; + val >>= 1; + } + } + return len; +} + /** * Parse a prefix length and generate a bit-mask. * @@ -648,6 +684,23 @@ parse_prefix(struct context *ctx, const struct token *token, u = strtoumax(str, &end, 0); if (errno || (size_t)(end - str) != len) goto error; + if (arg->mask) { + uintmax_t v = 0; + + extra = arg_entry_bf_fill(NULL, 0, arg); + if (u > extra) + goto error; + if (!ctx->object) + return len; + extra -= u; + while (u--) + (v <<= 1, v |= 1); + v <<= extra; + if (!arg_entry_bf_fill(ctx->object, v, arg) || + !arg_entry_bf_fill(ctx->objmask, -1, arg)) + goto error; + return len; + } bytes = u / 8; extra = u % 8; size = arg->size; @@ -1071,6 +1124,12 @@ parse_int(struct context *ctx, const struct token *token, goto error; if (!ctx->object) return len; + if (arg->mask) { + if (!arg_entry_bf_fill(ctx->object, u, arg) || + !arg_entry_bf_fill(ctx->objmask, -1, arg)) + goto error; + return len; + } buf = (uint8_t *)ctx->object + arg->offset; size = arg->size; objmask: -- 2.1.4
[dpdk-dev] [PATCH 13/22] app/testpmd: add rte_flow item spec prefix length
Generating bit-masks from prefix lengths is often more convenient than providing them entirely (e.g. to define IPv4 and IPv6 subnets). This commit adds the "prefix" operator that assigns generated bit-masks to any pattern item specification field. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 80 1 file changed, 80 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 790b4b8..89307cb 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -56,6 +56,7 @@ enum index { /* Common tokens. */ INTEGER, UNSIGNED, + PREFIX, RULE_ID, PORT_ID, GROUP_ID, @@ -93,6 +94,7 @@ enum index { ITEM_PARAM_SPEC, ITEM_PARAM_LAST, ITEM_PARAM_MASK, + ITEM_PARAM_PREFIX, ITEM_NEXT, ITEM_END, ITEM_VOID, @@ -277,6 +279,7 @@ static const enum index item_param[] = { ITEM_PARAM_SPEC, ITEM_PARAM_LAST, ITEM_PARAM_MASK, + ITEM_PARAM_PREFIX, 0, }; @@ -320,6 +323,9 @@ static int parse_list(struct context *, const struct token *, static int parse_int(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_prefix(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_port(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -360,6 +366,13 @@ static const struct token token_list[] = { .call = parse_int, .comp = comp_none, }, + [PREFIX] = { + .name = "{prefix}", + .type = "PREFIX", + .help = "prefix length for bit-mask", + .call = parse_prefix, + .comp = comp_none, + }, [RULE_ID] = { .name = "{rule id}", .type = "RULE ID", @@ -527,6 +540,11 @@ static const struct token token_list[] = { .help = "specify bit-mask with relevant bits set to one", .call = parse_vc_spec, }, + [ITEM_PARAM_PREFIX] = { + .name = "prefix", + .help = "generate bit-mask from a prefix length", + .call = parse_vc_spec, + }, [ITEM_NEXT] = { .name = "/", .help = "specify next pattern item", @@ -604,6 +622,62 @@ push_args(struct context *ctx, const struct arg *arg) return 0; } +/** + * Parse a prefix length and generate a bit-mask. + * + * Last argument (ctx->args) is retrieved to determine mask size, storage + * location and whether the result must use network byte ordering. + */ +static int +parse_prefix(struct context *ctx, const struct token *token, +const char *str, unsigned int len, +void *buf, unsigned int size) +{ + const struct arg *arg = pop_args(ctx); + static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff"; + char *end; + uintmax_t u; + unsigned int bytes; + unsigned int extra; + + (void)token; + /* Argument is expected. */ + if (!arg) + return -1; + errno = 0; + u = strtoumax(str, &end, 0); + if (errno || (size_t)(end - str) != len) + goto error; + bytes = u / 8; + extra = u % 8; + size = arg->size; + if (bytes > size || bytes + !!extra > size) + goto error; + if (!ctx->object) + return len; + buf = (uint8_t *)ctx->object + arg->offset; +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + if (!arg->hton) { + memset((uint8_t *)buf + size - bytes, 0xff, bytes); + memset(buf, 0x00, size - bytes); + if (extra) + ((uint8_t *)buf)[size - bytes - 1] = conv[extra]; + } else +#endif + { + memset(buf, 0xff, bytes); + memset((uint8_t *)buf + bytes, 0x00, size - bytes); + if (extra) + ((uint8_t *)buf)[bytes] = conv[extra]; + } + if (ctx->objmask) + memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); + return len; +error: + push_args(ctx, arg); + return -1; +} + /** Default parsing function for token name matching. */ static int parse_default(struct context *ctx, const struct token *token, @@ -775,6 +849,12 @@ parse_vc_spec(struct context *ctx, const struct token *token, case ITEM_PARAM_LAST: index = 1; break; + case ITEM_PARAM_PREFIX: + /* Modify next token to expect a prefix. */ + if (ctx->next_num < 2) + return -1; + ctx->next[ctx->next_
[dpdk-dev] [PATCH 12/22] app/testpmd: add rte_flow item spec handler
Add parser code to fully set individual fields of pattern item specification structures, using the following operators: - fix: sets field and applies full bit-mask for perfect matching. - spec: sets field without modifying its bit-mask. - last: sets upper value of the spec => last range. - mask: sets bit-mask affecting both spec and last from arbitrary value. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 110 +++ 1 file changed, 110 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index e70e8e2..790b4b8 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -89,6 +89,10 @@ enum index { /* Validate/create pattern. */ PATTERN, + ITEM_PARAM_FIX, + ITEM_PARAM_SPEC, + ITEM_PARAM_LAST, + ITEM_PARAM_MASK, ITEM_NEXT, ITEM_END, ITEM_VOID, @@ -121,6 +125,7 @@ struct context { uint16_t port; /**< Current port ID (for completions). */ uint32_t objdata; /**< Object-specific data. */ void *object; /**< Address of current object for relative offsets. */ + void *objmask; /**< Object a full mask must be written to. */ }; /** Token argument. */ @@ -267,6 +272,14 @@ static const enum index next_list_attr[] = { 0, }; +static const enum index item_param[] = { + ITEM_PARAM_FIX, + ITEM_PARAM_SPEC, + ITEM_PARAM_LAST, + ITEM_PARAM_MASK, + 0, +}; + static const enum index next_item[] = { ITEM_END, ITEM_VOID, @@ -287,6 +300,8 @@ static int parse_init(struct context *, const struct token *, static int parse_vc(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_vc_spec(struct context *, const struct token *, +const char *, unsigned int, void *, unsigned int); static int parse_destroy(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -492,6 +507,26 @@ static const struct token token_list[] = { .next = NEXT(next_item), .call = parse_vc, }, + [ITEM_PARAM_FIX] = { + .name = "fix", + .help = "match value perfectly (with full bit-mask)", + .call = parse_vc_spec, + }, + [ITEM_PARAM_SPEC] = { + .name = "spec", + .help = "match value according to configured bit-mask", + .call = parse_vc_spec, + }, + [ITEM_PARAM_LAST] = { + .name = "last", + .help = "specify upper bound to establish a range", + .call = parse_vc_spec, + }, + [ITEM_PARAM_MASK] = { + .name = "mask", + .help = "specify bit-mask with relevant bits set to one", + .call = parse_vc_spec, + }, [ITEM_NEXT] = { .name = "/", .help = "specify next pattern item", @@ -605,6 +640,7 @@ parse_init(struct context *ctx, const struct token *token, memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); ctx->objdata = 0; ctx->object = out; + ctx->objmask = NULL; return len; } @@ -632,11 +668,13 @@ parse_vc(struct context *ctx, const struct token *token, out->command = ctx->curr; ctx->objdata = 0; ctx->object = out; + ctx->objmask = NULL; out->args.vc.data = (uint8_t *)out + size; return len; } ctx->objdata = 0; ctx->object = &out->args.vc.attr; + ctx->objmask = NULL; switch (ctx->curr) { case GROUP: case PRIORITY: @@ -652,6 +690,7 @@ parse_vc(struct context *ctx, const struct token *token, (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), sizeof(double)); ctx->object = out->args.vc.pattern; + ctx->objmask = NULL; return len; case ACTIONS: out->args.vc.actions = @@ -660,6 +699,7 @@ parse_vc(struct context *ctx, const struct token *token, out->args.vc.pattern_n), sizeof(double)); ctx->object = out->args.vc.actions; + ctx->objmask = NULL; return len; default: if (!token->priv) @@ -682,6 +722,7 @@ parse_vc(struct context *ctx, const struct token *token, }; ++out->args.vc.pattern_n; ctx->object = item; + ctx->objmask = NULL; } else { const struct parse_action_priv *priv = token->priv; struct rte_flow_action *action = @@ -698,6 +739,7 @@ par
[dpdk-dev] [PATCH 11/22] app/testpmd: add flow query command
Syntax: flow query {port_id} {rule_id} {action} Query a specific action of an existing flow rule. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline.c | 3 + app/test-pmd/cmdline_flow.c | 121 ++- 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 851cc16..edd1ee3 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -831,6 +831,9 @@ static void cmd_help_long_parsed(void *parsed_result, "flow flush {port_id}\n" "Destroy all flow rules.\n\n" + "flow query {port_id} {rule_id} {action}\n" + "Query an existing flow rule.\n\n" + "flow list {port_id} [group {group_id}] [...]\n" "List existing flow rules sorted by priority," " filtered by group identifiers.\n\n" diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 1874849..e70e8e2 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -69,11 +69,15 @@ enum index { CREATE, DESTROY, FLUSH, + QUERY, LIST, /* Destroy arguments. */ DESTROY_RULE, + /* Query arguments. */ + QUERY_ACTION, + /* List arguments. */ LIST_GROUP, @@ -208,6 +212,10 @@ struct buffer { uint32_t rule_n; } destroy; /**< Destroy arguments. */ struct { + uint32_t rule; + enum rte_flow_action_type action; + } query; /**< Query arguments. */ + struct { uint32_t *group; uint32_t group_n; } list; /**< List arguments. */ @@ -285,6 +293,12 @@ static int parse_destroy(struct context *, const struct token *, static int parse_flush(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_query(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_action(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_list(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -296,6 +310,8 @@ static int parse_port(struct context *, const struct token *, void *, unsigned int); static int comp_none(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_action(struct context *, const struct token *, + unsigned int, char *, unsigned int); static int comp_port(struct context *, const struct token *, unsigned int, char *, unsigned int); static int comp_rule_id(struct context *, const struct token *, @@ -367,7 +383,8 @@ static const struct token token_list[] = { CREATE, DESTROY, FLUSH, - LIST)), + LIST, + QUERY)), .call = parse_init, }, /* Sub-level commands. */ @@ -399,6 +416,17 @@ static const struct token token_list[] = { .args = ARGS(ARGS_ENTRY(struct buffer, port)), .call = parse_flush, }, + [QUERY] = { + .name = "query", + .help = "query an existing flow rule", + .next = NEXT(NEXT_ENTRY(QUERY_ACTION), +NEXT_ENTRY(RULE_ID), +NEXT_ENTRY(PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action), +ARGS_ENTRY(struct buffer, args.query.rule), +ARGS_ENTRY(struct buffer, port)), + .call = parse_query, + }, [LIST] = { .name = "list", .help = "list existing flow rules", @@ -414,6 +442,14 @@ static const struct token token_list[] = { .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)), .call = parse_destroy, }, + /* Query arguments. */ + [QUERY_ACTION] = { + .name = "{action}", + .type = "ACTION", + .help = "action to query, must be part of the rule", + .call = parse_action, + .comp = comp_action, + }, /* List arguments. */ [LIST_GROUP] = { .name = "group", @@ -730,6 +766,67 @@ parse_flush(struct context *ctx, const struct token *token, return
[dpdk-dev] [PATCH 10/22] app/testpmd: add flow validate/create commands
Syntax: flow (validate|create) {port_id} [group {group_id}] [priority {level}] [ingress] [egress] pattern {item} [/ {item} [...]] / end actions {action} [/ {action} [...]] / end Either check the validity of a flow rule or create it. Any number of pattern items and actions can be provided in any order. Completion is available for convenience. This commit only adds support for the most basic item and action types, namely: - END: terminates pattern items and actions lists. - VOID: item/action filler, no operation. - INVERT: inverted pattern matching, process packets that do not match. - PASSTHRU: action that leaves packets up for additional processing by subsequent flow rules. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline.c | 14 ++ app/test-pmd/cmdline_flow.c | 314 ++- 2 files changed, 327 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 20a64b6..851cc16 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -811,6 +811,20 @@ static void cmd_help_long_parsed(void *parsed_result, " (select|add)\n" "Set the input set for FDir.\n\n" + "flow validate {port_id}" + " [group {group_id}] [priority {level}]" + " [ingress] [egress]" + " pattern {item} [/ {item} [...]] / end" + " actions {action} [/ {action} [...]] / end\n" + "Check whether a flow rule can be created.\n\n" + + "flow create {port_id}" + " [group {group_id}] [priority {level}]" + " [ingress] [egress]" + " pattern {item} [{item} [...]] end" + " actions {action} [{action} [...]] end\n" + "Create a flow rule.\n\n" + "flow destroy {port_id} rule {rule_id} [...]\n" "Destroy specific flow rules.\n\n" diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 5a8980c..1874849 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -59,11 +59,14 @@ enum index { RULE_ID, PORT_ID, GROUP_ID, + PRIORITY_LEVEL, /* Top-level command. */ FLOW, /* Sub-level commands. */ + VALIDATE, + CREATE, DESTROY, FLUSH, LIST, @@ -73,6 +76,26 @@ enum index { /* List arguments. */ LIST_GROUP, + + /* Validate/create arguments. */ + GROUP, + PRIORITY, + INGRESS, + EGRESS, + + /* Validate/create pattern. */ + PATTERN, + ITEM_NEXT, + ITEM_END, + ITEM_VOID, + ITEM_INVERT, + + /* Validate/create actions. */ + ACTIONS, + ACTION_NEXT, + ACTION_END, + ACTION_VOID, + ACTION_PASSTHRU, }; /** Maximum number of subsequent tokens and arguments on the stack. */ @@ -92,6 +115,7 @@ struct context { uint32_t eol:1; /**< EOL has been detected. */ uint32_t last:1; /**< No more arguments. */ uint16_t port; /**< Current port ID (for completions). */ + uint32_t objdata; /**< Object-specific data. */ void *object; /**< Address of current object for relative offsets. */ }; @@ -109,6 +133,8 @@ struct token { const char *type; /** Help displayed during completion (defaults to token name). */ const char *help; + /** Private data used by parser functions. */ + const void *priv; /** * Lists of subsequent tokens to push on the stack. Each call to the * parser consumes the last entry of that stack. @@ -170,6 +196,14 @@ struct buffer { uint16_t port; /**< Affected port ID. */ union { struct { + struct rte_flow_attr attr; + struct rte_flow_item *pattern; + struct rte_flow_action *actions; + uint32_t pattern_n; + uint32_t actions_n; + uint8_t *data; + } vc; /**< Validate/create arguments. */ + struct { uint32_t *rule; uint32_t rule_n; } destroy; /**< Destroy arguments. */ @@ -180,6 +214,39 @@ struct buffer { } args; /**< Command arguments. */ }; +/** Private data for pattern items. */ +struct parse_item_priv { + enum rte_flow_item_type type; /**< Item type. */ + uint32_t size; /**< Size of item specification structure. */ +}; + +#define PRIV_ITEM(t, s) \ + (&(const struct parse_item_priv){ \ + .type = RTE_FLOW_ITEM_TYPE_ ## t, \ + .size = s, \ + }) + +/** Private data for actions. */ +struct parse_action_priv { + enum rte_flow_action_type type; /*
[dpdk-dev] [PATCH 09/22] app/testpmd: add flow destroy command
Syntax: flow destroy {port_id} rule {rule_id} [...] Destroy a given set of flow rules associated with a port. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline.c | 3 ++ app/test-pmd/cmdline_flow.c | 106 ++- 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 9f124fc..20a64b6 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -811,6 +811,9 @@ static void cmd_help_long_parsed(void *parsed_result, " (select|add)\n" "Set the input set for FDir.\n\n" + "flow destroy {port_id} rule {rule_id} [...]\n" + "Destroy specific flow rules.\n\n" + "flow flush {port_id}\n" "Destroy all flow rules.\n\n" diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 414bacc..5a8980c 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -56,6 +56,7 @@ enum index { /* Common tokens. */ INTEGER, UNSIGNED, + RULE_ID, PORT_ID, GROUP_ID, @@ -63,9 +64,13 @@ enum index { FLOW, /* Sub-level commands. */ + DESTROY, FLUSH, LIST, + /* Destroy arguments. */ + DESTROY_RULE, + /* List arguments. */ LIST_GROUP, }; @@ -165,12 +170,22 @@ struct buffer { uint16_t port; /**< Affected port ID. */ union { struct { + uint32_t *rule; + uint32_t rule_n; + } destroy; /**< Destroy arguments. */ + struct { uint32_t *group; uint32_t group_n; } list; /**< List arguments. */ } args; /**< Command arguments. */ }; +static const enum index next_destroy_attr[] = { + DESTROY_RULE, + END, + 0, +}; + static const enum index next_list_attr[] = { LIST_GROUP, END, @@ -180,6 +195,9 @@ static const enum index next_list_attr[] = { static int parse_init(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_destroy(struct context *, const struct token *, +const char *, unsigned int, +void *, unsigned int); static int parse_flush(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -196,6 +214,8 @@ static int comp_none(struct context *, const struct token *, unsigned int, char *, unsigned int); static int comp_port(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_rule_id(struct context *, const struct token *, + unsigned int, char *, unsigned int); /** Token definitions. */ static const struct token token_list[] = { @@ -225,6 +245,13 @@ static const struct token token_list[] = { .call = parse_int, .comp = comp_none, }, + [RULE_ID] = { + .name = "{rule id}", + .type = "RULE ID", + .help = "rule identifier", + .call = parse_int, + .comp = comp_rule_id, + }, [PORT_ID] = { .name = "{port_id}", .type = "PORT ID", @@ -245,11 +272,19 @@ static const struct token token_list[] = { .type = "{command} {port_id} [{arg} [...]]", .help = "manage ingress/egress flow rules", .next = NEXT(NEXT_ENTRY -(FLUSH, +(DESTROY, + FLUSH, LIST)), .call = parse_init, }, /* Sub-level commands. */ + [DESTROY] = { + .name = "destroy", + .help = "destroy specific flow rules", + .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_destroy, + }, [FLUSH] = { .name = "flush", .help = "destroy all flow rules", @@ -264,6 +299,14 @@ static const struct token token_list[] = { .args = ARGS(ARGS_ENTRY(struct buffer, port)), .call = parse_list, }, + /* Destroy arguments. */ + [DESTROY_RULE] = { + .name = "rule", + .help = "specify a rule identifier", + .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)), + .call = parse_destroy, + }, /* List arguments. */ [LIST_GROUP] = {
[dpdk-dev] [PATCH 08/22] app/testpmd: add flow flush command
Syntax: flow flush {port_id} Destroy all flow rules on a port. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline.c | 3 +++ app/test-pmd/cmdline_flow.c | 43 +++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 09357c0..9f124fc 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -811,6 +811,9 @@ static void cmd_help_long_parsed(void *parsed_result, " (select|add)\n" "Set the input set for FDir.\n\n" + "flow flush {port_id}\n" + "Destroy all flow rules.\n\n" + "flow list {port_id} [group {group_id}] [...]\n" "List existing flow rules sorted by priority," " filtered by group identifiers.\n\n" diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 727fe78..414bacc 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -63,6 +63,7 @@ enum index { FLOW, /* Sub-level commands. */ + FLUSH, LIST, /* List arguments. */ @@ -179,6 +180,9 @@ static const enum index next_list_attr[] = { static int parse_init(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_flush(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_list(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -240,10 +244,19 @@ static const struct token token_list[] = { .name = "flow", .type = "{command} {port_id} [{arg} [...]]", .help = "manage ingress/egress flow rules", - .next = NEXT(NEXT_ENTRY(LIST)), + .next = NEXT(NEXT_ENTRY +(FLUSH, + LIST)), .call = parse_init, }, /* Sub-level commands. */ + [FLUSH] = { + .name = "flush", + .help = "destroy all flow rules", + .next = NEXT(NEXT_ENTRY(PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_flush, + }, [LIST] = { .name = "list", .help = "list existing flow rules", @@ -316,6 +329,31 @@ parse_init(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for flush command. */ +static int +parse_flush(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command) { + if (ctx->curr != FLUSH) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->object = out; + } + return len; +} + /** Parse tokens for list command. */ static int parse_list(struct context *ctx, const struct token *token, @@ -698,6 +736,9 @@ static void cmd_flow_parsed(const struct buffer *in) { switch (in->command) { + case FLUSH: + port_flow_flush(in->port); + break; case LIST: port_flow_list(in->port, in->args.list.group_n, in->args.list.group); -- 2.1.4
[dpdk-dev] [PATCH 07/22] app/testpmd: add flow list command
Syntax: flow list {port_id} [group {group_id}] [...] List configured flow rules on a port. Output can optionally be limited to a given set of group identifiers. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline.c | 4 ++ app/test-pmd/cmdline_flow.c | 141 +++ 2 files changed, 145 insertions(+) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index b7d10b3..09357c0 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -810,6 +810,10 @@ static void cmd_help_long_parsed(void *parsed_result, "sctp-src-port|sctp-dst-port|sctp-veri-tag|none)" " (select|add)\n" "Set the input set for FDir.\n\n" + + "flow list {port_id} [group {group_id}] [...]\n" + "List existing flow rules sorted by priority," + " filtered by group identifiers.\n\n" ); } } diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 7078f80..727fe78 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -56,9 +56,17 @@ enum index { /* Common tokens. */ INTEGER, UNSIGNED, + PORT_ID, + GROUP_ID, /* Top-level command. */ FLOW, + + /* Sub-level commands. */ + LIST, + + /* List arguments. */ + LIST_GROUP, }; /** Maximum number of subsequent tokens and arguments on the stack. */ @@ -77,6 +85,7 @@ struct context { uint32_t reparse:1; /**< Start over from the beginning. */ uint32_t eol:1; /**< EOL has been detected. */ uint32_t last:1; /**< No more arguments. */ + uint16_t port; /**< Current port ID (for completions). */ void *object; /**< Address of current object for relative offsets. */ }; @@ -153,16 +162,36 @@ struct token { struct buffer { enum index command; /**< Flow command. */ uint16_t port; /**< Affected port ID. */ + union { + struct { + uint32_t *group; + uint32_t group_n; + } list; /**< List arguments. */ + } args; /**< Command arguments. */ +}; + +static const enum index next_list_attr[] = { + LIST_GROUP, + END, + 0, }; static int parse_init(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_list(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_int(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_port(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int comp_none(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_port(struct context *, const struct token *, +unsigned int, char *, unsigned int); /** Token definitions. */ static const struct token token_list[] = { @@ -192,13 +221,44 @@ static const struct token token_list[] = { .call = parse_int, .comp = comp_none, }, + [PORT_ID] = { + .name = "{port_id}", + .type = "PORT ID", + .help = "port identifier", + .call = parse_port, + .comp = comp_port, + }, + [GROUP_ID] = { + .name = "{group_id}", + .type = "GROUP ID", + .help = "group identifier", + .call = parse_int, + .comp = comp_none, + }, /* Top-level command. */ [FLOW] = { .name = "flow", .type = "{command} {port_id} [{arg} [...]]", .help = "manage ingress/egress flow rules", + .next = NEXT(NEXT_ENTRY(LIST)), .call = parse_init, }, + /* Sub-level commands. */ + [LIST] = { + .name = "list", + .help = "list existing flow rules", + .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_list, + }, + /* List arguments. */ + [LIST_GROUP] = { + .name = "group", + .help = "specify a group", + .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)), + .call = parse_list, + }, }; /** Remove and return last entry from argument stack. */ @@ -256,6 +316,39 @@ parse_init(struct context *ctx, const struct token *token, return len; } +/** Parse tok
[dpdk-dev] [PATCH 06/22] app/testpmd: add rte_flow integer support
Parse all integer types and handle conversion to network byte order in a single function. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline_flow.c | 148 +++ 1 file changed, 148 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 7dbda84..7078f80 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -34,11 +34,14 @@ #include #include #include +#include +#include #include #include #include #include +#include #include #include @@ -50,6 +53,10 @@ enum index { ZERO = 0, END, + /* Common tokens. */ + INTEGER, + UNSIGNED, + /* Top-level command. */ FLOW, }; @@ -61,12 +68,24 @@ enum index { struct context { /** Stack of subsequent token lists to process. */ const enum index *next[CTX_STACK_SIZE]; + /** Arguments for stacked tokens. */ + const void *args[CTX_STACK_SIZE]; enum index curr; /**< Current token index. */ enum index prev; /**< Index of the last token seen. */ int next_num; /**< Number of entries in next[]. */ + int args_num; /**< Number of entries in args[]. */ uint32_t reparse:1; /**< Start over from the beginning. */ uint32_t eol:1; /**< EOL has been detected. */ uint32_t last:1; /**< No more arguments. */ + void *object; /**< Address of current object for relative offsets. */ +}; + +/** Token argument. */ +struct arg { + uint32_t hton:1; /**< Use network byte ordering. */ + uint32_t sign:1; /**< Value is signed. */ + uint32_t offset; /**< Relative offset from ctx->object. */ + uint32_t size; /**< Field size. */ }; /** Parser token definition. */ @@ -80,6 +99,8 @@ struct token { * parser consumes the last entry of that stack. */ const enum index *const *next; + /** Arguments stack for subsequent tokens that need them. */ + const struct arg *const *args; /** * Token-processing callback, returns -1 in case of error, the * length of the matched string otherwise. If NULL, attempts to @@ -112,6 +133,22 @@ struct token { /** Static initializer for a NEXT() entry. */ #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, 0, } +/** Static initializer for the args field. */ +#define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, } + +/** Static initializer for ARGS() to target a field. */ +#define ARGS_ENTRY(s, f) \ + (&(const struct arg){ \ + .offset = offsetof(s, f), \ + .size = sizeof(((s *)0)->f), \ + }) + +/** Static initializer for ARGS() to target a pointer. */ +#define ARGS_ENTRY_PTR(s, f) \ + (&(const struct arg){ \ + .size = sizeof(*((s *)0)->f), \ + }) + /** Parser output buffer layout expected by cmd_flow_parsed(). */ struct buffer { enum index command; /**< Flow command. */ @@ -121,6 +158,11 @@ struct buffer { static int parse_init(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_int(struct context *, const struct token *, +const char *, unsigned int, +void *, unsigned int); +static int comp_none(struct context *, const struct token *, +unsigned int, char *, unsigned int); /** Token definitions. */ static const struct token token_list[] = { @@ -135,6 +177,21 @@ static const struct token token_list[] = { .type = "RETURN", .help = "command may end here", }, + /* Common tokens. */ + [INTEGER] = { + .name = "{int}", + .type = "INTEGER", + .help = "integer value", + .call = parse_int, + .comp = comp_none, + }, + [UNSIGNED] = { + .name = "{unsigned}", + .type = "UNSIGNED", + .help = "unsigned integer value", + .call = parse_int, + .comp = comp_none, + }, /* Top-level command. */ [FLOW] = { .name = "flow", @@ -144,6 +201,23 @@ static const struct token token_list[] = { }, }; +/** Remove and return last entry from argument stack. */ +static const struct arg * +pop_args(struct context *ctx) +{ + return ctx->args_num ? ctx->args[--ctx->args_num] : NULL; +} + +/** Add entry on top of the argument stack. */ +static int +push_args(struct context *ctx, const struct arg *arg) +{ + if (ctx->args_num == CTX_STACK_SIZE) + return -1; + ctx->args[ctx->args_num++] = arg; + return 0; +} + /** Default parsing function for token name matching. */ static int parse_default(struct context *ctx, const struct token *token, @@ -178,9 +252,74 @@ parse_init(struct context *ctx, const struct token *token, /* Initializ
[dpdk-dev] [PATCH 05/22] app/testpmd: add flow command
Managing generic flow API functions from command line requires the use of dynamic tokens for convenience as flow rules are not fixed and cannot be defined statically. This commit adds specific flexible parser code and object for a new "flow" command in separate file. Signed-off-by: Adrien Mazarguil --- app/test-pmd/Makefile | 1 + app/test-pmd/cmdline.c | 4 + app/test-pmd/cmdline_flow.c | 439 +++ 3 files changed, 444 insertions(+) diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile index 891b85a..5988c3e 100644 --- a/app/test-pmd/Makefile +++ b/app/test-pmd/Makefile @@ -47,6 +47,7 @@ CFLAGS += $(WERROR_FLAGS) SRCS-y := testpmd.c SRCS-y += parameters.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c +SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_flow.c SRCS-y += config.c SRCS-y += iofwd.c SRCS-y += macfwd.c diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index c5b015c..b7d10b3 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -9520,6 +9520,9 @@ cmdline_parse_inst_t cmd_set_flow_director_flex_payload = { }, }; +/* Generic flow interface command. */ +extern cmdline_parse_inst_t cmd_flow; + /* *** Classification Filters Control *** */ /* *** Get symmetric hash enable per port *** */ struct cmd_get_sym_hash_ena_per_port_result { @@ -11557,6 +11560,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_input_set, (cmdline_parse_inst_t *)&cmd_set_fdir_input_set, + (cmdline_parse_inst_t *)&cmd_flow, (cmdline_parse_inst_t *)&cmd_mcast_addr, (cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all, (cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific, diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c new file mode 100644 index 000..7dbda84 --- /dev/null +++ b/app/test-pmd/cmdline_flow.c @@ -0,0 +1,439 @@ +/*- + * BSD LICENSE + * + * Copyright 2016 6WIND S.A. + * Copyright 2016 Mellanox. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "testpmd.h" + +/** Parser token indices. */ +enum index { + /* Special tokens. */ + ZERO = 0, + END, + + /* Top-level command. */ + FLOW, +}; + +/** Maximum number of subsequent tokens and arguments on the stack. */ +#define CTX_STACK_SIZE 16 + +/** Parser context. */ +struct context { + /** Stack of subsequent token lists to process. */ + const enum index *next[CTX_STACK_SIZE]; + enum index curr; /**< Current token index. */ + enum index prev; /**< Index of the last token seen. */ + int next_num; /**< Number of entries in next[]. */ + uint32_t reparse:1; /**< Start over from the beginning. */ + uint32_t eol:1; /**< EOL has been detected. */ + uint32_t last:1; /**< No more arguments. */ +}; + +/** Parser token definition. */ +struct token { + /** Type displayed during completion (defaults to "TOKEN"). */ + const char *type; + /** Help displayed during completion (defaults to token name). */ + const char *help; + /** +* Lists of subsequent tokens to push on the stack. Each call to the +* parser consumes the last entry of that stack. +*/ + c
[dpdk-dev] [PATCH 04/22] app/testpmd: implement basic support for rte_flow
Add basic management functions for the generic flow API (validate, create, destroy, flush, query and list). Flow rule objects and properties are arranged in lists associated with each port. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline.c | 1 + app/test-pmd/config.c | 484 app/test-pmd/csumonly.c| 1 + app/test-pmd/flowgen.c | 1 + app/test-pmd/icmpecho.c| 1 + app/test-pmd/ieee1588fwd.c | 1 + app/test-pmd/iofwd.c | 1 + app/test-pmd/macfwd.c | 1 + app/test-pmd/macswap.c | 1 + app/test-pmd/parameters.c | 1 + app/test-pmd/rxonly.c | 1 + app/test-pmd/testpmd.c | 6 + app/test-pmd/testpmd.h | 27 +++ app/test-pmd/txonly.c | 1 + 14 files changed, 528 insertions(+) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 63b55dc..c5b015c 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -75,6 +75,7 @@ #include #include #include +#include #include #include diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 36c47ab..c9dc872 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -92,6 +92,8 @@ #include #include #include +#include +#include #include "testpmd.h" @@ -750,6 +752,488 @@ port_mtu_set(portid_t port_id, uint16_t mtu) printf("Set MTU failed. diag=%d\n", diag); } +/* Generic flow management functions. */ + +/** Generate flow_item[] entry. */ +#define MK_FLOW_ITEM(t, s) \ + [RTE_FLOW_ITEM_TYPE_ ## t] = { \ + .name = # t, \ + .size = s, \ + } + +/** Information about known flow pattern items. */ +static const struct { + const char *name; + size_t size; +} flow_item[] = { + MK_FLOW_ITEM(END, 0), + MK_FLOW_ITEM(VOID, 0), + MK_FLOW_ITEM(INVERT, 0), + MK_FLOW_ITEM(ANY, sizeof(struct rte_flow_item_any)), + MK_FLOW_ITEM(PF, 0), + MK_FLOW_ITEM(VF, sizeof(struct rte_flow_item_vf)), + MK_FLOW_ITEM(PORT, sizeof(struct rte_flow_item_port)), + MK_FLOW_ITEM(RAW, sizeof(struct rte_flow_item_raw)), /* +pattern[] */ + MK_FLOW_ITEM(ETH, sizeof(struct rte_flow_item_eth)), + MK_FLOW_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)), + MK_FLOW_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)), + MK_FLOW_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)), + MK_FLOW_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)), + MK_FLOW_ITEM(UDP, sizeof(struct rte_flow_item_udp)), + MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)), + MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)), + MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)), +}; + +/** Compute storage space needed by item specification. */ +static void +flow_item_spec_size(const struct rte_flow_item *item, + size_t *size, size_t *pad) +{ + if (!item->spec) + goto empty; + switch (item->type) { + union { + const struct rte_flow_item_raw *raw; + } spec; + + case RTE_FLOW_ITEM_TYPE_RAW: + spec.raw = item->spec; + *size = offsetof(struct rte_flow_item_raw, pattern) + + spec.raw->length * sizeof(*spec.raw->pattern); + break; + default: +empty: + *size = 0; + break; + } + *pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size; +} + +/** Generate flow_action[] entry. */ +#define MK_FLOW_ACTION(t, s) \ + [RTE_FLOW_ACTION_TYPE_ ## t] = { \ + .name = # t, \ + .size = s, \ + } + +/** Information about known flow actions. */ +static const struct { + const char *name; + size_t size; +} flow_action[] = { + MK_FLOW_ACTION(END, 0), + MK_FLOW_ACTION(VOID, 0), + MK_FLOW_ACTION(PASSTHRU, 0), + MK_FLOW_ACTION(MARK, sizeof(struct rte_flow_action_mark)), + MK_FLOW_ACTION(FLAG, 0), + MK_FLOW_ACTION(QUEUE, sizeof(struct rte_flow_action_queue)), + MK_FLOW_ACTION(DROP, 0), + MK_FLOW_ACTION(COUNT, 0), + MK_FLOW_ACTION(DUP, sizeof(struct rte_flow_action_dup)), + MK_FLOW_ACTION(RSS, sizeof(struct rte_flow_action_rss)), /* +queue[] */ + MK_FLOW_ACTION(PF, 0), + MK_FLOW_ACTION(VF, sizeof(struct rte_flow_action_vf)), +}; + +/** Compute storage space needed by action configuration. */ +static void +flow_action_conf_size(const struct rte_flow_action *action, + size_t *size, size_t *pad) +{ + if (!action->conf) + goto empty; + switch (action->type) { + union { + const struct rte_flow_action_rss *rss; + } conf; + + case RTE_FLOW_ACTION_TYPE_RSS: + conf.rss = action->conf; + *size = offsetof(struct rte_flow_action_rss, queue) + + conf.rss->queues * sizeof(*conf.rss->queue
[dpdk-dev] [PATCH 03/22] cmdline: add alignment constraint
This prevents sigbus errors on architectures that cannot handle unexpected unaligned accesses to the output buffer. Signed-off-by: Adrien Mazarguil --- lib/librte_cmdline/cmdline_parse.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/librte_cmdline/cmdline_parse.c b/lib/librte_cmdline/cmdline_parse.c index 14f5553..763c286 100644 --- a/lib/librte_cmdline/cmdline_parse.c +++ b/lib/librte_cmdline/cmdline_parse.c @@ -255,7 +255,10 @@ cmdline_parse(struct cmdline *cl, const char * buf) unsigned int inst_num=0; cmdline_parse_inst_t *inst; const char *curbuf; - char result_buf[CMDLINE_PARSE_RESULT_BUFSIZE]; + union { + char buf[CMDLINE_PARSE_RESULT_BUFSIZE]; + long double align; /* strong alignment constraint for buf */ + } result; cmdline_parse_token_hdr_t *dyn_tokens[CMDLINE_PARSE_DYNAMIC_TOKENS]; void (*f)(void *, struct cmdline *, void *) = NULL; void *data = NULL; @@ -318,7 +321,7 @@ cmdline_parse(struct cmdline *cl, const char * buf) debug_printf("INST %d\n", inst_num); /* fully parsed */ - tok = match_inst(inst, buf, 0, result_buf, sizeof(result_buf), + tok = match_inst(inst, buf, 0, result.buf, sizeof(result.buf), &dyn_tokens); if (tok > 0) /* we matched at least one token */ @@ -353,7 +356,7 @@ cmdline_parse(struct cmdline *cl, const char * buf) /* call func */ if (f) { - f(result_buf, cl, data); + f(result.buf, cl, data); } /* no match */ -- 2.1.4
[dpdk-dev] [PATCH 02/22] cmdline: add support for dynamic tokens
Considering tokens must be hard-coded in a list part of the instruction structure, context-dependent tokens cannot be expressed. This commit adds support for building dynamic token lists through a user-provided function, which is called when the static token list is empty (a single NULL entry). Because no structures are modified (existing fields are reused), this commit has no impact on the current ABI. Signed-off-by: Adrien Mazarguil --- lib/librte_cmdline/cmdline_parse.c | 60 + lib/librte_cmdline/cmdline_parse.h | 21 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/lib/librte_cmdline/cmdline_parse.c b/lib/librte_cmdline/cmdline_parse.c index b496067..14f5553 100644 --- a/lib/librte_cmdline/cmdline_parse.c +++ b/lib/librte_cmdline/cmdline_parse.c @@ -146,7 +146,9 @@ nb_common_chars(const char * s1, const char * s2) */ static int match_inst(cmdline_parse_inst_t *inst, const char *buf, - unsigned int nb_match_token, void *resbuf, unsigned resbuf_size) + unsigned int nb_match_token, void *resbuf, unsigned resbuf_size, + cmdline_parse_token_hdr_t + *(*dyn_tokens)[CMDLINE_PARSE_DYNAMIC_TOKENS]) { unsigned int token_num=0; cmdline_parse_token_hdr_t * token_p; @@ -155,6 +157,11 @@ match_inst(cmdline_parse_inst_t *inst, const char *buf, struct cmdline_token_hdr token_hdr; token_p = inst->tokens[token_num]; + if (!token_p && dyn_tokens && inst->f) { + if (!(*dyn_tokens)[0]) + inst->f(&(*dyn_tokens)[0], NULL, dyn_tokens); + token_p = (*dyn_tokens)[0]; + } if (token_p) memcpy(&token_hdr, token_p, sizeof(token_hdr)); @@ -196,7 +203,17 @@ match_inst(cmdline_parse_inst_t *inst, const char *buf, buf += n; token_num ++; - token_p = inst->tokens[token_num]; + if (!inst->tokens[0]) { + if (token_num < (CMDLINE_PARSE_DYNAMIC_TOKENS - 1)) { + if (!(*dyn_tokens)[token_num]) + inst->f(&(*dyn_tokens)[token_num], + NULL, + dyn_tokens); + token_p = (*dyn_tokens)[token_num]; + } else + token_p = NULL; + } else + token_p = inst->tokens[token_num]; if (token_p) memcpy(&token_hdr, token_p, sizeof(token_hdr)); } @@ -239,6 +256,7 @@ cmdline_parse(struct cmdline *cl, const char * buf) cmdline_parse_inst_t *inst; const char *curbuf; char result_buf[CMDLINE_PARSE_RESULT_BUFSIZE]; + cmdline_parse_token_hdr_t *dyn_tokens[CMDLINE_PARSE_DYNAMIC_TOKENS]; void (*f)(void *, struct cmdline *, void *) = NULL; void *data = NULL; int comment = 0; @@ -255,6 +273,7 @@ cmdline_parse(struct cmdline *cl, const char * buf) return CMDLINE_PARSE_BAD_ARGS; ctx = cl->ctx; + memset(&dyn_tokens, 0, sizeof(dyn_tokens)); /* * - look if the buffer contains at least one line @@ -299,7 +318,8 @@ cmdline_parse(struct cmdline *cl, const char * buf) debug_printf("INST %d\n", inst_num); /* fully parsed */ - tok = match_inst(inst, buf, 0, result_buf, sizeof(result_buf)); + tok = match_inst(inst, buf, 0, result_buf, sizeof(result_buf), +&dyn_tokens); if (tok > 0) /* we matched at least one token */ err = CMDLINE_PARSE_BAD_ARGS; @@ -355,6 +375,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, cmdline_parse_token_hdr_t *token_p; struct cmdline_token_hdr token_hdr; char tmpbuf[CMDLINE_BUFFER_SIZE], comp_buf[CMDLINE_BUFFER_SIZE]; + cmdline_parse_token_hdr_t *dyn_tokens[CMDLINE_PARSE_DYNAMIC_TOKENS]; unsigned int partial_tok_len; int comp_len = -1; int tmp_len = -1; @@ -374,6 +395,7 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, debug_printf("%s called\n", __func__); memset(&token_hdr, 0, sizeof(token_hdr)); + memset(&dyn_tokens, 0, sizeof(dyn_tokens)); /* count the number of complete token to parse */ for (i=0 ; buf[i] ; i++) { @@ -396,11 +418,24 @@ cmdline_complete(struct cmdline *cl, const char *buf, int *state, inst = ctx[inst_num]; while (inst) { /* parse the first tokens of the inst */ - if (nb_token && match_inst(inst, buf, nb_token, NULL, 0)) + if (nb_token && + match_inst(inst, buf, nb_token, NULL, 0, + &dy
[dpdk-dev] [PATCH 01/22] ethdev: introduce generic flow API
This new API supersedes all the legacy filter types described in rte_eth_ctrl.h. It is slightly higher level and as a result relies more on PMDs to process and validate flow rules. Benefits: - A unified API is easier to program for, applications do not have to be written for a specific filter type which may or may not be supported by the underlying device. - The behavior of a flow rule is the same regardless of the underlying device, applications do not need to be aware of hardware quirks. - Extensible by design, API/ABI breakage should rarely occur if at all. - Documentation is self-standing, no need to look up elsewhere. Existing filter types will be deprecated and removed in the near future. Signed-off-by: Adrien Mazarguil --- MAINTAINERS| 4 + lib/librte_ether/Makefile | 3 + lib/librte_ether/rte_eth_ctrl.h| 1 + lib/librte_ether/rte_ether_version.map | 10 + lib/librte_ether/rte_flow.c| 159 + lib/librte_ether/rte_flow.h| 947 lib/librte_ether/rte_flow_driver.h | 177 ++ 7 files changed, 1301 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d6bb8f8..3b46630 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -243,6 +243,10 @@ M: Thomas Monjalon F: lib/librte_ether/ F: scripts/test-null.sh +Generic flow API +M: Adrien Mazarguil +F: lib/librte_ether/rte_flow* + Crypto API M: Declan Doherty F: lib/librte_cryptodev/ diff --git a/lib/librte_ether/Makefile b/lib/librte_ether/Makefile index efe1e5f..9335361 100644 --- a/lib/librte_ether/Makefile +++ b/lib/librte_ether/Makefile @@ -44,6 +44,7 @@ EXPORT_MAP := rte_ether_version.map LIBABIVER := 5 SRCS-y += rte_ethdev.c +SRCS-y += rte_flow.c # # Export include files @@ -51,6 +52,8 @@ SRCS-y += rte_ethdev.c SYMLINK-y-include += rte_ethdev.h SYMLINK-y-include += rte_eth_ctrl.h SYMLINK-y-include += rte_dev_info.h +SYMLINK-y-include += rte_flow.h +SYMLINK-y-include += rte_flow_driver.h # this lib depends upon: DEPDIRS-y += lib/librte_net lib/librte_eal lib/librte_mempool lib/librte_ring lib/librte_mbuf diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h index fe80eb0..8386904 100644 --- a/lib/librte_ether/rte_eth_ctrl.h +++ b/lib/librte_ether/rte_eth_ctrl.h @@ -99,6 +99,7 @@ enum rte_filter_type { RTE_ETH_FILTER_FDIR, RTE_ETH_FILTER_HASH, RTE_ETH_FILTER_L2_TUNNEL, + RTE_ETH_FILTER_GENERIC, RTE_ETH_FILTER_MAX }; diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map index 72be66d..b5d2547 100644 --- a/lib/librte_ether/rte_ether_version.map +++ b/lib/librte_ether/rte_ether_version.map @@ -147,3 +147,13 @@ DPDK_16.11 { rte_eth_dev_pci_remove; } DPDK_16.07; + +DPDK_17.02 { + global: + + rte_flow_validate; + rte_flow_create; + rte_flow_destroy; + rte_flow_query; + +} DPDK_16.11; diff --git a/lib/librte_ether/rte_flow.c b/lib/librte_ether/rte_flow.c new file mode 100644 index 000..064963d --- /dev/null +++ b/lib/librte_ether/rte_flow.c @@ -0,0 +1,159 @@ +/*- + * BSD LICENSE + * + * Copyright 2016 6WIND S.A. + * Copyright 2016 Mellanox. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER 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. + */ + +#include + +#include +#include +#include "rte_ethdev.h" +#include "rte_flow_driver.h" +#include "rte_flow.h" + +/* Get generic flow operations structure fr
[dpdk-dev] [PATCH 00/22] Generic flow API (rte_flow)
As previously discussed in RFC v1 [1], RFC v2 [2], with changes described in [3] (also pasted below), here is the first non-draft series for this new API. Its capabilities are so generic that its name had to be vague, it may be called "Generic flow API", "Generic flow interface" (possibly shortened as "GFI") to refer to the name of the new filter type, or "rte_flow" from the prefix used for its public symbols. I personally favor the latter. While it is currently meant to supersede existing filter types in order for all PMDs to expose a common filtering/classification interface, it may eventually evolve to cover the following ideas as well: - Rx/Tx offloads configuration through automatic offloads for specific packets, e.g. performing checksum on TCP packets could be expressed with an egress rule with a TCP pattern and a kind of checksum action. - RSS configuration (already defined actually). Could be global or per rule depending on hardware capabilities. - Switching configuration for devices with many physical ports; rules doing both ingress and egress could even be used to completely bypass software if supported by hardware. [1] http://dpdk.org/ml/archives/dev/2016-July/043365.html [2] http://dpdk.org/ml/archives/dev/2016-August/045383.html [3] http://dpdk.org/ml/archives/dev/2016-November/050044.html Changes since RFC v2: - New separate VLAN pattern item (previously part of the ETH definition), found to be much more convenient. - Removed useless "any" field from VF pattern item, the same effect can be achieved by not providing a specification structure. - Replaced bit-fields from the VXLAN pattern item to avoid endianness conversion issues on 24-bit fields. - Updated struct rte_flow_item with a new "last" field to create inclusive ranges. They are defined as the interval between (spec & mask) and (last & mask). All three parameters are optional. - Renamed ID action MARK. - Renamed "queue" fields in actions QUEUE and DUP to "index". - "rss_conf" field in RSS action is now const. - VF action now uses a 32 bit ID like its pattern item counterpart. - Removed redundant struct rte_flow_pattern, API functions now expect struct rte_flow_item lists terminated by END items. - Replaced struct rte_flow_actions for the same reason, with struct rte_flow_action lists terminated by END actions. - Error types (enum rte_flow_error_type) have been updated and the cause pointer in struct rte_flow_error is now const. - Function prototypes (rte_flow_create, rte_flow_validate) have also been updated for clarity. Additions: - Public wrapper functions rte_flow_{validate|create|destroy|flush|query} are now implemented in rte_flow.c, with their symbols exported and versioned. Related filter type RTE_ETH_FILTER_GENERIC has been added. - A separate header (rte_flow_driver.h) has been added for driver-side functionality, in particular struct rte_flow_ops which contains PMD callbacks returned by RTE_ETH_FILTER_GENERIC query. - testpmd now exposes most of this API through the new "flow" command. What remains to be done: - Using endian-aware integer types (rte_beX_t) where necessary for clarity. - API documentation (based on RFC). - testpmd flow command documentation (although context-aware command completion should already help quite a bit in this regard). - A few pattern item / action properties cannot be configured yet (e.g. rss_conf parameter for RSS action) and a few completions (e.g. possible queue IDs) should be added. Adrien Mazarguil (22): ethdev: introduce generic flow API cmdline: add support for dynamic tokens cmdline: add alignment constraint app/testpmd: implement basic support for rte_flow app/testpmd: add flow command app/testpmd: add rte_flow integer support app/testpmd: add flow list command app/testpmd: add flow flush command app/testpmd: add flow destroy command app/testpmd: add flow validate/create commands app/testpmd: add flow query command app/testpmd: add rte_flow item spec handler app/testpmd: add rte_flow item spec prefix length app/testpmd: add rte_flow bit-field support app/testpmd: add item any to flow command app/testpmd: add various items to flow command app/testpmd: add item raw to flow command app/testpmd: add items eth/vlan to flow command app/testpmd: add items ipv4/ipv6 to flow command app/testpmd: add L4 items to flow command app/testpmd: add various actions to flow command app/testpmd: add queue actions to flow command MAINTAINERS|4 + app/test-pmd/Makefile |1 + app/test-pmd/cmdline.c | 32 + app/test-pmd/cmdline_flow.c| 2581 +++ app/test-pmd/config.c | 484 + app/test-pmd/csumonly.c|1 + app/test-pmd/flowgen.c |1 + app/test-pmd/icmpecho.c|1 + app/test-pmd/ieee1588fwd.c |1
[dpdk-dev] [PATCH] eal: define generic vector types
Add common vector type definitions to all CPU architectures. Signed-off-by: Nelio Laranjeiro --- lib/librte_eal/common/Makefile | 1 + lib/librte_eal/common/include/arch/arm/rte_vect.h | 1 + .../common/include/arch/ppc_64/rte_vect.h | 1 + lib/librte_eal/common/include/arch/tile/rte_vect.h | 38 + lib/librte_eal/common/include/arch/x86/rte_vect.h | 7 +- lib/librte_eal/common/include/generic/rte_vect.h | 185 + 6 files changed, 230 insertions(+), 3 deletions(-) create mode 100644 lib/librte_eal/common/include/arch/tile/rte_vect.h create mode 100644 lib/librte_eal/common/include/generic/rte_vect.h diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile index dfd64aa..8af06b1 100644 --- a/lib/librte_eal/common/Makefile +++ b/lib/librte_eal/common/Makefile @@ -48,6 +48,7 @@ endif GENERIC_INC := rte_atomic.h rte_byteorder.h rte_cycles.h rte_prefetch.h GENERIC_INC += rte_spinlock.h rte_memcpy.h rte_cpuflags.h rte_rwlock.h +GENERIC_INC += rte_vect.h # defined in mk/arch/$(RTE_ARCH)/rte.vars.mk ARCH_DIR ?= $(RTE_ARCH) ARCH_INC := $(notdir $(wildcard $(RTE_SDK)/lib/librte_eal/common/include/arch/$(ARCH_DIR)/*.h)) diff --git a/lib/librte_eal/common/include/arch/arm/rte_vect.h b/lib/librte_eal/common/include/arch/arm/rte_vect.h index b86c2cf..4107c99 100644 --- a/lib/librte_eal/common/include/arch/arm/rte_vect.h +++ b/lib/librte_eal/common/include/arch/arm/rte_vect.h @@ -34,6 +34,7 @@ #define _RTE_VECT_ARM_H_ #include +#include "generic/rte_vect.h" #include "arm_neon.h" #ifdef __cplusplus diff --git a/lib/librte_eal/common/include/arch/ppc_64/rte_vect.h b/lib/librte_eal/common/include/arch/ppc_64/rte_vect.h index 05209e5..99586e5 100644 --- a/lib/librte_eal/common/include/arch/ppc_64/rte_vect.h +++ b/lib/librte_eal/common/include/arch/ppc_64/rte_vect.h @@ -34,6 +34,7 @@ #define _RTE_VECT_PPC_64_H_ #include +#include "generic/rte_vect.h" #ifdef __cplusplus extern "C" { diff --git a/lib/librte_eal/common/include/arch/tile/rte_vect.h b/lib/librte_eal/common/include/arch/tile/rte_vect.h new file mode 100644 index 000..f1e1709 --- /dev/null +++ b/lib/librte_eal/common/include/arch/tile/rte_vect.h @@ -0,0 +1,38 @@ +/*- + * BSD LICENSE + * + * Copyright 2016 6WIND S.A. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_VECT_TILE_H_ +#define _RTE_VECT_TILE_H_ + +#include "generic/rte_vect.h" + +#endif /* _RTE_VECT_TILE_H_ */ diff --git a/lib/librte_eal/common/include/arch/x86/rte_vect.h b/lib/librte_eal/common/include/arch/x86/rte_vect.h index 77f2e25..1b4b85d 100644 --- a/lib/librte_eal/common/include/arch/x86/rte_vect.h +++ b/lib/librte_eal/common/include/arch/x86/rte_vect.h @@ -31,8 +31,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _RTE_VECT_H_ -#define _RTE_VECT_H_ +#ifndef _RTE_VECT_X86_H_ +#define _RTE_VECT_X86_H_ /** * @file @@ -41,6 +41,7 @@ */ #include +#include "generic/rte_vect.h" #if (defined(__ICC) || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) @@ -133,4 +134,4 @@ __extension__ ({ \ } #endif -#endif /* _RTE_VECT_H_ */ +#endif /* _RTE_VECT_X86_H_ */ diff --git a/lib/librte_eal/common/include/generic/rte_vect.h b/lib/librte_eal/common/include/generic/rte_vect.h new file mode 100644 index 000..d7b9cd9 --- /dev/null +++ b/lib/librte_eal/common/include/generic/rte_vect.h @@ -0,0 +1,
[dpdk-dev] [PATCH v2] eal/linuxapp: fix return value check of mknod()
Thanks to David, I will submit v3 patch to indicate correct Fixes. > -Original Message- > From: David Marchand [mailto:david.marchand at 6wind.com] > Sent: Wednesday, November 16, 2016 7:24 PM > To: Dai, Wei > Cc: dev at dpdk.org; Burakov, Anatoly > Subject: Re: [PATCH v2] eal/linuxapp: fix return value check of mknod() > > Hello Wei, > > On Wed, Nov 16, 2016 at 3:40 AM, Wei Dai wrote: > > In function pci_mknod_uio_dev() in lib/librte_eal/eal/eal_pci_uio.c, > > The return value of mknod() is ret, not f got by fopen(). > > So the value of ret should be checked for mknod(). > > > > Fixes: 67c536bdad93 ("pci: move uio mapping in a dedicated file") > > The commit you are pointing is just moving the code. > I would incriminate f7f97c16048e ("pci: add option --create-uio-dev to run > without hotplug") > > The rest looks good to me. > > > -- > David Marchand
[dpdk-dev] [PATCH v2] eal/linuxapp: fix return value check of mknod()
Thanks to Yigit Ferruh and Wenzhuo for your guide. Several months ago, I download checkpatch.pl and put it in /root/bin/. In /root/.bash_profile in my server, there is line :export DPDK_CHECKPATCH_PATH=/root/bin/checkpatch.pl Before I send this patch, I have run checkpath.sh to check it and it show no error. ./scripts/checkpatch.sh -v v2-0001-eal-*.patch By search ' != 0', there are many lines in many modules of DPDK. So I think ' !=0' is OK. > -Original Message- > From: Yigit, Ferruh > Sent: Wednesday, November 16, 2016 7:04 PM > To: Lu, Wenzhuo ; Dai, Wei ; > dev at dpdk.org; Burakov, Anatoly ; > david.marchand at 6wind.com > Subject: Re: [dpdk-dev] [PATCH v2] eal/linuxapp: fix return value check of > mknod() > > Hi Wenzhuo, > > On 11/16/2016 3:28 AM, Lu, Wenzhuo wrote: > > Hi Wei, > > > >> -Original Message- > >> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Wei Dai > >> Sent: Wednesday, November 16, 2016 10:41 AM > >> To: dev at dpdk.org; Burakov, Anatoly; david.marchand at 6wind.com; Dai, > >> Wei > >> Subject: [dpdk-dev] [PATCH v2] eal/linuxapp: fix return value check > >> of mknod() > >> > >> In function pci_mknod_uio_dev() in lib/librte_eal/eal/eal_pci_uio.c, > >> The return value of mknod() is ret, not f got by fopen(). > >> So the value of ret should be checked for mknod(). > >> > >> Fixes: 67c536bdad93 ("pci: move uio mapping in a dedicated file") > >> > >> Signed-off-by: Wei Dai > >> --- > >> fix my local git setting and send same patch again to make merging > >> easier > >> > >> lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 2 +- > >> 1 file changed, 1 insertion(+), 1 deletion(-) > >> > >> diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > >> b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > >> index 1786b75..3e4ffb5 100644 > >> --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > >> +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > >> @@ -133,7 +133,7 @@ pci_mknod_uio_dev(const char *sysfs_uio_path, > >> unsigned uio_num) > >>snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num); > >>dev = makedev(major, minor); > >>ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev); > >> - if (f == NULL) { > >> + if (ret != 0) { > > I think checkpatch will suggest to just use if (ret) > > Your are right, default checkpatch.pl complains about this usage (with > --strict > option), but: > > - According DPDK coding style this usage is preferred (although I personally > prefer kernel one..) > > http://dpdk.org/doc/guides/contributing/coding_style.html#null-pointers > > " > if (p == NULL) /* Good, compare pointer to NULL */ > > if (!p) /* Bad, using ! on pointer */ > " > > - This warning disabled in dpdk scripts/checkpatches.sh by "--ignore > COMPARISON_TO_NULL", so it shouldn't complain. > >
[dpdk-dev] [PATCH v2] eal/linuxapp: fix return value check of mknod()
Hello Wei, On Wed, Nov 16, 2016 at 3:40 AM, Wei Dai wrote: > In function pci_mknod_uio_dev() in lib/librte_eal/eal/eal_pci_uio.c, > The return value of mknod() is ret, not f got by fopen(). > So the value of ret should be checked for mknod(). > > Fixes: 67c536bdad93 ("pci: move uio mapping in a dedicated file") The commit you are pointing is just moving the code. I would incriminate f7f97c16048e ("pci: add option --create-uio-dev to run without hotplug") The rest looks good to me. -- David Marchand
[dpdk-dev] [PATCH] cryptodev: fix crash on null dereference
> -Original Message- > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Jerin Jacob > Sent: Tuesday, November 15, 2016 7:12 PM > To: dev at dpdk.org > Cc: Doherty, Declan ; Jerin Jacob > > Subject: [dpdk-dev] [PATCH] cryptodev: fix crash on null dereference > > crypodev->data->name will be null when > rte_cryptodev_get_dev_id() invoked without a valid crypto device instance. > > Signed-off-by: Jerin Jacob > --- > lib/librte_cryptodev/rte_cryptodev.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > -- > 2.5.5 Acked-by: Arek Kusztal
[dpdk-dev] [PATCH v2] eal/linuxapp: fix return value check of mknod()
Hi Wenzhuo, On 11/16/2016 3:28 AM, Lu, Wenzhuo wrote: > Hi Wei, > >> -Original Message- >> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Wei Dai >> Sent: Wednesday, November 16, 2016 10:41 AM >> To: dev at dpdk.org; Burakov, Anatoly; david.marchand at 6wind.com; Dai, Wei >> Subject: [dpdk-dev] [PATCH v2] eal/linuxapp: fix return value check of >> mknod() >> >> In function pci_mknod_uio_dev() in lib/librte_eal/eal/eal_pci_uio.c, The >> return >> value of mknod() is ret, not f got by fopen(). >> So the value of ret should be checked for mknod(). >> >> Fixes: 67c536bdad93 ("pci: move uio mapping in a dedicated file") >> >> Signed-off-by: Wei Dai >> --- >> fix my local git setting and send same patch again to make merging easier >> >> lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c >> b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c >> index 1786b75..3e4ffb5 100644 >> --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c >> +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c >> @@ -133,7 +133,7 @@ pci_mknod_uio_dev(const char *sysfs_uio_path, >> unsigned uio_num) >> snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num); >> dev = makedev(major, minor); >> ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev); >> -if (f == NULL) { >> +if (ret != 0) { > I think checkpatch will suggest to just use if (ret) Your are right, default checkpatch.pl complains about this usage (with --strict option), but: - According DPDK coding style this usage is preferred (although I personally prefer kernel one..) http://dpdk.org/doc/guides/contributing/coding_style.html#null-pointers " if (p == NULL) /* Good, compare pointer to NULL */ if (!p) /* Bad, using ! on pointer */ " - This warning disabled in dpdk scripts/checkpatches.sh by "--ignore COMPARISON_TO_NULL", so it shouldn't complain.
[dpdk-dev] [PATCH v2] eal/linuxapp: fix return value check of mknod()
In function pci_mknod_uio_dev() in lib/librte_eal/eal/eal_pci_uio.c, The return value of mknod() is ret, not f got by fopen(). So the value of ret should be checked for mknod(). Fixes: 67c536bdad93 ("pci: move uio mapping in a dedicated file") Signed-off-by: Wei Dai --- fix my local git setting and send same patch again to make merging easier lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c index 1786b75..3e4ffb5 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c @@ -133,7 +133,7 @@ pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num) snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num); dev = makedev(major, minor); ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev); - if (f == NULL) { + if (ret != 0) { RTE_LOG(ERR, EAL, "%s(): mknod() failed %s\n", __func__, strerror(errno)); return -1; -- 2.5.5
[dpdk-dev] Clarification for eth_driver changes
On Monday 14 November 2016 11:08 PM, Ferruh Yigit wrote: [...] > What I was thinking is: > > rte_device/driver are not abstract classes. > > rte_bus device/driver is an abstract class and any bus inherited from > this class. > rte_func device/driver is and abstract class and eth/crypto inherited > from this class. > > eal layer only deal with rte_bus > pmd's only deal with functional device/driver > > but still, it is required to know device <-> driver, and functional <-> > bus, relations. rte_dev/rte_driver are to provide this links. > > But yes this add extra layer and with second thought I am not sure if it > is really possible to separate bus and functionality, this was just an > idea .. [...] I understand your point. It would really nice if we can achieve that level pluggable-ness where drivers would be able to choose a 'profile' - where 'profiles' are like net/crypto etc. In your text, profile==functionality. Maybe once the basic model is in place, we can revisit this idea. - Shreyansh
[dpdk-dev] [PATCH] eal/linuxapp: fix return value check of mknod()
From: Wei Dai In function pci_mknod_uio_dev() in lib/librte_eal/eal/eal_pci_uio.c, The return value of mknod() is ret, not f got by fopen(). So the value of ret should be checked for mknod(). Fixes: 67c536bdad93 ("pci: move uio mapping in a dedicated file") Signed-off-by: Wei Dai --- lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c index 1786b75..3e4ffb5 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c @@ -133,7 +133,7 @@ pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num) snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num); dev = makedev(major, minor); ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev); - if (f == NULL) { + if (ret != 0) { RTE_LOG(ERR, EAL, "%s(): mknod() failed %s\n", __func__, strerror(errno)); return -1; -- 2.5.5
[dpdk-dev] [PATCH v2] eal/linuxapp: fix return value check of mknod()
Hi Wei, > -Original Message- > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Wei Dai > Sent: Wednesday, November 16, 2016 10:41 AM > To: dev at dpdk.org; Burakov, Anatoly; david.marchand at 6wind.com; Dai, Wei > Subject: [dpdk-dev] [PATCH v2] eal/linuxapp: fix return value check of mknod() > > In function pci_mknod_uio_dev() in lib/librte_eal/eal/eal_pci_uio.c, The > return > value of mknod() is ret, not f got by fopen(). > So the value of ret should be checked for mknod(). > > Fixes: 67c536bdad93 ("pci: move uio mapping in a dedicated file") > > Signed-off-by: Wei Dai > --- > fix my local git setting and send same patch again to make merging easier > > lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > index 1786b75..3e4ffb5 100644 > --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > @@ -133,7 +133,7 @@ pci_mknod_uio_dev(const char *sysfs_uio_path, > unsigned uio_num) > snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num); > dev = makedev(major, minor); > ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev); > - if (f == NULL) { > + if (ret != 0) { I think checkpatch will suggest to just use if (ret)
[dpdk-dev] [PATCH] cryptodev: fix crash on null dereference
crypodev->data->name will be null when rte_cryptodev_get_dev_id() invoked without a valid crypto device instance. Signed-off-by: Jerin Jacob --- lib/librte_cryptodev/rte_cryptodev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c index 127e8d0..54e95d5 100644 --- a/lib/librte_cryptodev/rte_cryptodev.c +++ b/lib/librte_cryptodev/rte_cryptodev.c @@ -225,13 +225,14 @@ rte_cryptodev_create_vdev(const char *name, const char *args) } int -rte_cryptodev_get_dev_id(const char *name) { +rte_cryptodev_get_dev_id(const char *name) +{ unsigned i; if (name == NULL) return -1; - for (i = 0; i < rte_cryptodev_globals->max_devs; i++) + for (i = 0; i < rte_cryptodev_globals->nb_devs; i++) if ((strcmp(rte_cryptodev_globals->devs[i].data->name, name) == 0) && (rte_cryptodev_globals->devs[i].attached == -- 2.5.5