* [dpdk-dev] [PATCH 1/2] doc: flow classify library prog guide
2017-10-26 9:09 [dpdk-dev] [PATCH 0/2] flow classify documentation Bernard Iremonger
@ 2017-10-26 9:09 ` Bernard Iremonger
2017-11-02 16:58 ` Mcnamara, John
2017-10-26 9:09 ` [dpdk-dev] [PATCH 2/2] doc: flow classify sample app guide Bernard Iremonger
` (2 subsequent siblings)
3 siblings, 1 reply; 13+ messages in thread
From: Bernard Iremonger @ 2017-10-26 9:09 UTC (permalink / raw)
To: dev, john.mcnamara; +Cc: Bernard Iremonger
This file documents the Flow Classification library,
librte_flow_classify.
Updated MAINTAINERS file
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
MAINTAINERS | 1 +
doc/guides/prog_guide/flow_classify_lib.rst | 427 ++++++++++++++++++++++++++++
doc/guides/prog_guide/index.rst | 1 +
3 files changed, 429 insertions(+)
create mode 100644 doc/guides/prog_guide/flow_classify_lib.rst
diff --git a/MAINTAINERS b/MAINTAINERS
index 04bdbae..117d104 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -718,6 +718,7 @@ M: Bernard Iremonger <bernard.iremonger@intel.com>
F: lib/librte_flow_classify/
F: test/test/test_flow_classify*
F: examples/flow_classify/
+F: doc/guides/prog_guide/flow_classify_lib.rst
Distributor
M: Bruce Richardson <bruce.richardson@intel.com>
diff --git a/doc/guides/prog_guide/flow_classify_lib.rst b/doc/guides/prog_guide/flow_classify_lib.rst
new file mode 100644
index 0000000..7fa4be9
--- /dev/null
+++ b/doc/guides/prog_guide/flow_classify_lib.rst
@@ -0,0 +1,427 @@
+.. BSD LICENSE
+ Copyright(c) 2017 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.
+
+Flow Classification Library
+===========================
+
+DPDK provides a Flow Classification library that provides the ability
+to classify an input packet by matching it against a set of Flow rules.
+
+The initial implementation supports counting of IPv4 5-tuple packets which match
+a particular Flow rule only.
+
+Please refer to the
+:doc:`./rte_flow`
+for more information.
+
+The Flow Classification library uses the ``librte_table`` API for managing Flow
+rules and matching packets against the Flow rules.
+The library is table agnostic and can use the following tables:
+``Access Control List``, ``Hash`` and ``Longest Prefix Match(LPM)``.
+The ``Access Control List`` table is used in the initial implementation.
+
+Please refer to the
+:doc:`./packet_framework`
+for more information.on ``librte_table``.
+
+DPDK provides an Access Control List library that provides the ability to
+classify an input packet based on a set of classification rules.
+
+Please refer to the
+:doc:`./packet_classif_access_ctrl`
+library for more information on ``librte_acl``.
+
+There is also a Flow Classify sample application which demonstrates the use of
+the Flow Classification Library API's.
+
+Please refer to the
+:doc:`../sample_app_ug/flow_classify`
+for more information on the ``flow_classify`` sample application.
+
+Overview
+--------
+
+The library has the following API's
+
+.. code-block:: c
+
+ /**
+ * Flow classifier create
+ *
+ * @param params
+ * Parameters for flow classifier creation
+ * @return
+ * Handle to flow classifier instance on success or NULL otherwise
+ */
+ struct rte_flow_classifier *
+ rte_flow_classifier_create(struct rte_flow_classifier_params *params);
+
+ /**
+ * Flow classifier free
+ *
+ * @param cls
+ * Handle to flow classifier instance
+ * @return
+ * 0 on success, error code otherwise
+ */
+ int
+ rte_flow_classifier_free(struct rte_flow_classifier *cls);
+
+ /**
+ * Flow classify table create
+ *
+ * @param cls
+ * Handle to flow classifier instance
+ * @param params
+ * Parameters for flow_classify table creation
+ * @param table_id
+ * Table ID. Valid only within the scope of table IDs of the current
+ * classifier. Only returned after a successful invocation.
+ * @return
+ * 0 on success, error code otherwise
+ */
+ int
+ rte_flow_classify_table_create(struct rte_flow_classifier *cls,
+ struct rte_flow_classify_table_params *params,
+ uint32_t *table_id);
+
+ /**
+ * Add a flow classify rule to the flow_classifer table.
+ *
+ * @param[in] cls
+ * Flow classifier handle
+ * @param[in] table_id
+ * id of table
+ * @param[in] attr
+ * Flow rule attributes
+ * @param[in] pattern
+ * Pattern specification (list terminated by the END pattern item).
+ * @param[in] actions
+ * Associated actions (list terminated by the END pattern item).
+ * @param[out] error
+ * Perform verbose error reporting if not NULL. Structure
+ * initialised in case of error only.
+ * @return
+ * A valid handle in case of success, NULL otherwise.
+ */
+ struct rte_flow_classify_rule *
+ rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
+ uint32_t table_id,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error);
+
+ /**
+ * Delete a flow classify rule from the flow_classifer table.
+ *
+ * @param[in] cls
+ * Flow classifier handle
+ * @param[in] table_id
+ * id of table
+ * @param[in] rule
+ * Flow classify rule
+ * @return
+ * 0 on success, error code otherwise.
+ */
+ int
+ rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
+ uint32_t table_id,
+ struct rte_flow_classify_rule *rule);
+
+ /**
+ * Query flow classifier for given rule.
+ *
+ * @param[in] cls
+ * Flow classifier handle
+ * @param[in] table_id
+ * id of table
+ * @param[in] pkts
+ * Pointer to packets to process
+ * @param[in] nb_pkts
+ * Number of packets to process
+ * @param[in] rule
+ * Flow classify rule
+ * @param[in] stats
+ * Flow classify stats
+ *
+ * @return
+ * 0 on success, error code otherwise.
+ */
+ int
+ rte_flow_classifier_query(struct rte_flow_classifier *cls,
+ uint32_t table_id,
+ struct rte_mbuf **pkts,
+ const uint16_t nb_pkts,
+ struct rte_flow_classify_rule *rule,
+ struct rte_flow_classify_stats *stats);
+
+Classifier creation
+~~~~~~~~~~~~~~~~~~~
+
+The application creates the ``Classifier`` using the
+``rte_flow_classifier_create`` API.
+The ``rte_flow_classify_params`` structure must be initialised by the
+application before calling the API.
+
+.. code-block:: c
+
+ struct rte_flow_classifier_params {
+ /** flow classifier name */
+ const char *name;
+
+ /** CPU socket ID where memory for the flow classifier and its */
+ /** elements (tables) should be allocated */
+ int socket_id;
+
+ /** Table type */
+ enum rte_flow_classify_table_type type;
+ };
+
+The ``Classifier`` has the following internal structures:
+
+.. code-block:: c
+
+ struct rte_table {
+ /* Input parameters */
+ struct rte_table_ops ops;
+ uint32_t entry_size;
+ enum rte_flow_classify_table_type type;
+
+ /* Handle to the low-level table object */
+ void *h_table;
+ };
+
+ #define RTE_FLOW_CLASSIFIER_MAX_NAME_SZ 256
+
+ struct rte_flow_classifier {
+ /* Input parameters */
+ char name[RTE_FLOW_CLASSIFIER_MAX_NAME_SZ];
+ int socket_id;
+ enum rte_flow_classify_table_type type;
+
+ /* Internal tables */
+ struct rte_table tables[RTE_FLOW_CLASSIFY_TABLE_MAX];
+ uint32_t num_tables;
+ uint16_t nb_pkts;
+ struct rte_flow_classify_table_entry
+ *entries[RTE_PORT_IN_BURST_SIZE_MAX];
+ } __rte_cache_aligned;
+
+Adding a table to the Classifier
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The application adds a table to the ``Classifier`` using the
+``rte_flow_classify_table_create`` API.
+The ``rte_flow_classify_table_params`` structure must be initialised by the
+application before calling the API.
+
+.. code-block:: c
+
+ struct rte_flow_classify_table_params {
+ /** Table operations (specific to each table type) */
+ struct rte_table_ops *ops;
+
+ /** Opaque param to be passed to the table create operation */
+ void *arg_create;
+
+ /** Memory size to be reserved per classifier object entry for */
+ /** storing meta data */
+ uint32_t table_metadata_size;
+ };
+
+To create an ACL table the ``rte_table_acl_params`` structure must be
+initialised and assigned to ``arg_create`` in the
+``rte_flow_classify_table_params`` structure.
+
+.. code-block:: c
+
+ struct rte_table_acl_params {
+ /** Name */
+ const char *name;
+
+ /** Maximum number of ACL rules in the table */
+ uint32_t n_rules;
+
+ /** Number of fields in the ACL rule specification */
+ uint32_t n_rule_fields;
+
+ /** Format specification of the fields of the ACL rule */
+ struct rte_acl_field_def field_format[RTE_ACL_MAX_FIELDS];
+ };
+
+The fields for the ACL rule must also be initialised by the application.
+
+An ACL table can be added to the ``Classifier`` for each ACL rule, for example
+another table could be added for the IPv6 5-tuple rule.
+
+Flow Parsing
+~~~~~~~~~~~~
+
+The library currently supports three IPv4 5-tuple flow patterns, for UDP, TCP
+and SCTP.
+
+.. code-block:: c
+
+ /* Pattern for IPv4 5-tuple UDP filter */
+ static enum rte_flow_item_type pattern_ntuple_1[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_END,
+ };
+
+ /* Pattern for IPv4 5-tuple TCP filter */
+ static enum rte_flow_item_type pattern_ntuple_2[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_TCP,
+ RTE_FLOW_ITEM_TYPE_END,
+ };
+
+ /* Pattern for IPv4 5-tuple SCTP filter */
+ static enum rte_flow_item_type pattern_ntuple_3[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_SCTP,
+ RTE_FLOW_ITEM_TYPE_END,
+ };
+
+The internal function ``flow_classify_parse_flow`` parses the
+IPv4 5-tuple pattern, attributes and actions and returns the 5-tuple data in the
+``rte_eth_ntuple_filter`` structure.
+
+.. code-block:: c
+
+ static int
+ flow_classify_parse_flow(
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error)
+
+Adding Flow Rules
+~~~~~~~~~~~~~~~~~
+
+The ``rte_flow_classify_table_entry_add`` API creates an
+``rte_flow_classify`` object which contains the flow_classify id and type, the
+action, a union of add and delete keys and a union of rules.
+It uses the ``flow_classify_parse_flow`` internal function for parsing the
+flow parameters.
+The 5-tuple ACL key data is obtained from the ``rte_eth_ntuple_filter``
+structure populated by the ``classify_parse_ntuple_filter`` function which
+parses the Flow rule.
+
+.. code-block:: c
+
+ struct acl_keys {
+ struct rte_table_acl_rule_add_params key_add; /* add key */
+ struct rte_table_acl_rule_delete_params key_del; /* delete key */
+ };
+
+ struct classify_rules {
+ enum rte_flow_classify_rule_type type;
+ union {
+ struct rte_flow_classify_ipv4_5tuple ipv4_5tuple;
+ } u;
+ };
+
+ struct rte_flow_classify {
+ uint32_t id; /* unique ID of classify object */
+ struct rte_flow_action action; /* action when match found */
+ struct classify_rules rules; /* union of rules */
+ union {
+ struct acl_keys key;
+ } u;
+ int key_found; /* rule key found in table */
+ void *entry; /* pointer to buffer to hold rule meta data */
+ void *entry_ptr; /* handle to the table entry for rule meta data */
+ };
+
+It then calls the ``table[table_id].ops.f_add`` API to add the rule to the ACL
+table.
+
+Deleting Flow Rules
+~~~~~~~~~~~~~~~~~~~
+
+The ``rte_flow_classify_table_entry_delete`` API calls the
+``table[table_id].ops.f_delete`` API to delete a rule from the ACL table.
+
+Packet Matching
+~~~~~~~~~~~~~~~
+
+The ``rte_flow_classifier_query`` API is used to find packets which match a
+given flow Flow rule in the table.
+This API calls the flow_classify_run internal function which calls the
+``table[table_id].ops.f_lookup`` API to see if any packets in a burst match any
+of the Flow rules in the table.
+The meta data for the highest priority rule matched for each packet is returned
+in the entries array in the ``rte_flow_classify`` object.
+The internal function ``action_apply`` implements the ``Count`` action which is
+used to return data which matches a particular Flow rule.
+
+The rte_flow_classifier_query API uses the following structures to return data
+to the application.
+
+.. code-block:: c
+
+ /** IPv4 5-tuple data */
+ struct rte_flow_classify_ipv4_5tuple {
+ uint32_t dst_ip; /**< Destination IP address in big endian. */
+ uint32_t dst_ip_mask; /**< Mask of destination IP address. */
+ uint32_t src_ip; /**< Source IP address in big endian. */
+ uint32_t src_ip_mask; /**< Mask of destination IP address. */
+ uint16_t dst_port; /**< Destination port in big endian. */
+ uint16_t dst_port_mask; /**< Mask of destination port. */
+ uint16_t src_port; /**< Source Port in big endian. */
+ uint16_t src_port_mask; /**< Mask of source port. */
+ uint8_t proto; /**< L4 protocol. */
+ uint8_t proto_mask; /**< Mask of L4 protocol. */
+ };
+
+ /**
+ * Flow stats
+ *
+ * For the count action, stats can be returned by the query API.
+ *
+ * Storage for stats is provided by the application.
+ *
+ *
+ */
+ struct rte_flow_classify_stats {
+ void *stats;
+ };
+
+ struct rte_flow_classify_5tuple_stats {
+ /** count of packets that match IPv4 5tuple pattern */
+ uint64_t counter1;
+ /** IPv4 5tuple data */
+ struct rte_flow_classify_ipv4_5tuple ipv4_5tuple;
+ };
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index 9759264..21d1c3d 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -72,6 +72,7 @@ Programmer's Guide
vhost_lib
metrics_lib
port_hotplug_framework
+ flow_classify_lib
source_org
dev_kit_build_system
dev_kit_root_make_help
--
1.9.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH 1/2] doc: flow classify library prog guide
2017-10-26 9:09 ` [dpdk-dev] [PATCH 1/2] doc: flow classify library prog guide Bernard Iremonger
@ 2017-11-02 16:58 ` Mcnamara, John
2017-11-02 17:29 ` Iremonger, Bernard
0 siblings, 1 reply; 13+ messages in thread
From: Mcnamara, John @ 2017-11-02 16:58 UTC (permalink / raw)
To: Iremonger, Bernard, dev
> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Thursday, October 26, 2017 10:09 AM
> To: dev@dpdk.org; Mcnamara, John <john.mcnamara@intel.com>
> Cc: Iremonger, Bernard <bernard.iremonger@intel.com>
> Subject: [PATCH 1/2] doc: flow classify library prog guide
>
> This file documents the Flow Classification library, librte_flow_classify.
>
> Updated MAINTAINERS file
>
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Hi Bernard,
Thanks for the doc.
There is a doc build warning due to a reference to a file that is in the 2/2
patch:
$ make doc-guides-html -j
sphinx processing guides-html...
/work/dpdk_docs/doc/guides/prog_guide/flow_classify_lib.rst:64:
WARNING: unknown document: ../sample_app_ug/flow_classify
There are also 2 x s/classifer/classifier/ typos in this patch and 1 in 2/2.
John
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH 1/2] doc: flow classify library prog guide
2017-11-02 16:58 ` Mcnamara, John
@ 2017-11-02 17:29 ` Iremonger, Bernard
2017-11-03 9:52 ` Mcnamara, John
0 siblings, 1 reply; 13+ messages in thread
From: Iremonger, Bernard @ 2017-11-02 17:29 UTC (permalink / raw)
To: Mcnamara, John, dev; +Cc: Iremonger, Bernard
Hi John,
<snip>
> > Subject: [PATCH 1/2] doc: flow classify library prog guide
> >
> > This file documents the Flow Classification library, librte_flow_classify.
> >
> > Updated MAINTAINERS file
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
>
> Hi Bernard,
>
> Thanks for the doc.
>
> There is a doc build warning due to a reference to a file that is in the 2/2
> patch:
>
> $ make doc-guides-html -j
> sphinx processing guides-html...
> /work/dpdk_docs/doc/guides/prog_guide/flow_classify_lib.rst:64:
> WARNING: unknown document: ../sample_app_ug/flow_classify
>
Both docs reference each other.
I could squash the patches into one, or add a third patch with the reference.
Which option would you prefer?
>
> There are also 2 x s/classifer/classifier/ typos in this patch and 1 in 2/2.
I will fix typo's
>
> John
>
>
Thanks for the review.
Regards,
Bernard.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH 1/2] doc: flow classify library prog guide
2017-11-02 17:29 ` Iremonger, Bernard
@ 2017-11-03 9:52 ` Mcnamara, John
2017-11-03 15:32 ` Iremonger, Bernard
0 siblings, 1 reply; 13+ messages in thread
From: Mcnamara, John @ 2017-11-03 9:52 UTC (permalink / raw)
To: Iremonger, Bernard, dev
> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Thursday, November 2, 2017 5:29 PM
> To: Mcnamara, John <john.mcnamara@intel.com>; dev@dpdk.org
> Cc: Iremonger, Bernard <bernard.iremonger@intel.com>
> Subject: RE: [PATCH 1/2] doc: flow classify library prog guide
>
> Hi John,
>
> <snip>
>
> > > Subject: [PATCH 1/2] doc: flow classify library prog guide
> > >
> > > This file documents the Flow Classification library,
> librte_flow_classify.
> > >
> > > Updated MAINTAINERS file
> > >
> > > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> >
> > Hi Bernard,
> >
> > Thanks for the doc.
> >
> > There is a doc build warning due to a reference to a file that is in the
> 2/2
> > patch:
> >
> > $ make doc-guides-html -j
> > sphinx processing guides-html...
> > /work/dpdk_docs/doc/guides/prog_guide/flow_classify_lib.rst:64:
> > WARNING: unknown document: ../sample_app_ug/flow_classify
> >
> Both docs reference each other.
> I could squash the patches into one, or add a third patch with the
> reference.
> Which option would you prefer?
Hi Bernard,
I think squashing them into 1 patch would be okay.
John
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH 1/2] doc: flow classify library prog guide
2017-11-03 9:52 ` Mcnamara, John
@ 2017-11-03 15:32 ` Iremonger, Bernard
0 siblings, 0 replies; 13+ messages in thread
From: Iremonger, Bernard @ 2017-11-03 15:32 UTC (permalink / raw)
To: Mcnamara, John, dev; +Cc: Iremonger, Bernard
Hi John,
<snip>
> >
> > > > Subject: [PATCH 1/2] doc: flow classify library prog guide
> > > >
> > > > This file documents the Flow Classification library,
> > librte_flow_classify.
> > > >
> > > > Updated MAINTAINERS file
> > > >
> > > > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> > >
> > > Hi Bernard,
> > >
> > > Thanks for the doc.
> > >
> > > There is a doc build warning due to a reference to a file that is in
> > > the
> > 2/2
> > > patch:
> > >
> > > $ make doc-guides-html -j
> > > sphinx processing guides-html...
> > > /work/dpdk_docs/doc/guides/prog_guide/flow_classify_lib.rst:64:
> > > WARNING: unknown document: ../sample_app_ug/flow_classify
> > >
> > Both docs reference each other.
> > I could squash the patches into one, or add a third patch with the
> > reference.
> > Which option would you prefer?
>
> Hi Bernard,
>
> I think squashing them into 1 patch would be okay.
>
> John
I have sent a v2 patch with both patches squashed into one patch.
Regards,
Bernard.
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH 2/2] doc: flow classify sample app guide
2017-10-26 9:09 [dpdk-dev] [PATCH 0/2] flow classify documentation Bernard Iremonger
2017-10-26 9:09 ` [dpdk-dev] [PATCH 1/2] doc: flow classify library prog guide Bernard Iremonger
@ 2017-10-26 9:09 ` Bernard Iremonger
2017-11-02 17:00 ` Mcnamara, John
2017-11-03 11:13 ` [dpdk-dev] [PATCH v2] flow classify documentation Bernard Iremonger
2017-11-03 11:13 ` [dpdk-dev] [PATCH v2] doc: flow classify guides Bernard Iremonger
3 siblings, 1 reply; 13+ messages in thread
From: Bernard Iremonger @ 2017-10-26 9:09 UTC (permalink / raw)
To: dev, john.mcnamara; +Cc: Bernard Iremonger
This file documents the flow_classify sample application
which is used to demonstate use of the Flow Classify library,
librte_flow_classify.
Updated MAINTAINERS file
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
MAINTAINERS | 1 +
doc/guides/sample_app_ug/flow_classify.rst | 592 +++++++++++++++++++++++++++++
doc/guides/sample_app_ug/index.rst | 1 +
3 files changed, 594 insertions(+)
create mode 100644 doc/guides/sample_app_ug/flow_classify.rst
diff --git a/MAINTAINERS b/MAINTAINERS
index 117d104..63ba5ab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -719,6 +719,7 @@ F: lib/librte_flow_classify/
F: test/test/test_flow_classify*
F: examples/flow_classify/
F: doc/guides/prog_guide/flow_classify_lib.rst
+F: doc/guides/sample_app_ug/flow_classify.rst
Distributor
M: Bruce Richardson <bruce.richardson@intel.com>
diff --git a/doc/guides/sample_app_ug/flow_classify.rst b/doc/guides/sample_app_ug/flow_classify.rst
new file mode 100644
index 0000000..b2f5e4f
--- /dev/null
+++ b/doc/guides/sample_app_ug/flow_classify.rst
@@ -0,0 +1,592 @@
+.. BSD LICENSE
+ Copyright(c) 2017 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.
+
+Flow Classify Sample Application
+================================
+
+The Flow Classify sample application is based on the simple *skeleton* example
+of a forwarding application.
+
+It is intended as a demonstration of the basic components of a DPDK forwarding
+application which uses the Flow Classify library API's.
+
+Please refer to the
+:doc:`../prog_guide/flow_classify_lib`
+for more information.
+
+Compiling the Application
+-------------------------
+
+To compile the application export the path to the DPDK source tree and go to
+the example directory:
+
+.. code-block:: console
+
+ export RTE_SDK=/path/to/rte_sdk
+
+ cd ${RTE_SDK}/examples/flow_classify
+
+Set the target, for example:
+
+.. code-block:: console
+
+ export RTE_TARGET=x86_64-native-linuxapp-gcc
+
+See the *DPDK Getting Started* Guide for possible ``RTE_TARGET`` values.
+
+Build the application as follows:
+
+.. code-block:: console
+
+ make clean
+
+ make
+
+Running the Application
+-----------------------
+
+To run the example in a ``linuxapp`` environment:
+
+.. code-block:: console
+
+ ./build/flow_classify -c 4 -n 4 -- --rule_ipv4="../ipv4_rules_file.txt"
+
+Refer to *DPDK Getting Started Guide* for general information on running
+applications and the Environment Abstraction Layer (EAL) options.
+
+Sample ipv4_rules_file.txt
+--------------------------
+
+.. code-block:: console
+
+ #file format:
+ #src_ip/masklen dst_ip/masklen src_port : mask dst_port : mask proto/mask priority
+ #
+ 2.2.2.3/24 2.2.2.7/24 32 : 0xffff 33 : 0xffff 17/0xff 0
+ 9.9.9.3/24 9.9.9.7/24 32 : 0xffff 33 : 0xffff 17/0xff 1
+ 9.9.9.3/24 9.9.9.7/24 32 : 0xffff 33 : 0xffff 6/0xff 2
+ 9.9.8.3/24 9.9.8.7/24 32 : 0xffff 33 : 0xffff 6/0xff 3
+ 6.7.8.9/24 2.3.4.5/24 32 : 0x0000 33 : 0x0000 132/0xff 4
+
+Explanation
+-----------
+
+The following sections provide an explanation of the main components of the
+code.
+
+All DPDK library functions used in the sample code are prefixed with ``rte_``
+and are explained in detail in the *DPDK API Documentation*.
+
+ACL field definitions for the IPv4 5 tuple rule
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following field definitions are used when creating the ACL table during
+initialisation of the ``Flow Classify`` application..
+
+.. code-block:: c
+
+ enum {
+ PROTO_FIELD_IPV4,
+ SRC_FIELD_IPV4,
+ DST_FIELD_IPV4,
+ SRCP_FIELD_IPV4,
+ DSTP_FIELD_IPV4,
+ NUM_FIELDS_IPV4
+ };
+
+ enum {
+ PROTO_INPUT_IPV4,
+ SRC_INPUT_IPV4,
+ DST_INPUT_IPV4,
+ SRCP_DESTP_INPUT_IPV4
+ };
+
+ static struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
+ /* first input field - always one byte long. */
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = PROTO_FIELD_IPV4,
+ .input_index = PROTO_INPUT_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, next_proto_id),
+ },
+ /* next input field (IPv4 source address) - 4 consecutive bytes. */
+ {
+ /* rte_flow uses a bit mask for IPv4 addresses */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC_FIELD_IPV4,
+ .input_index = SRC_INPUT_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, src_addr),
+ },
+ /* next input field (IPv4 destination address) - 4 consecutive bytes. */
+ {
+ /* rte_flow uses a bit mask for IPv4 addresses */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST_FIELD_IPV4,
+ .input_index = DST_INPUT_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, dst_addr),
+ },
+ /*
+ * Next 2 fields (src & dst ports) form 4 consecutive bytes.
+ * They share the same input index.
+ */
+ {
+ /* rte_flow uses a bit mask for protocol ports */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint16_t),
+ .field_index = SRCP_FIELD_IPV4,
+ .input_index = SRCP_DESTP_INPUT_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr) +
+ offsetof(struct tcp_hdr, src_port),
+ },
+ {
+ /* rte_flow uses a bit mask for protocol ports */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint16_t),
+ .field_index = DSTP_FIELD_IPV4,
+ .input_index = SRCP_DESTP_INPUT_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr) +
+ offsetof(struct tcp_hdr, dst_port),
+ },
+ };
+
+The Main Function
+~~~~~~~~~~~~~~~~~
+
+The ``main()`` function performs the initialization and calls the execution
+threads for each lcore.
+
+The first task is to initialize the Environment Abstraction Layer (EAL).
+The ``argc`` and ``argv`` arguments are provided to the ``rte_eal_init()``
+function. The value returned is the number of parsed arguments:
+
+.. code-block:: c
+
+ int ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
+
+It then parses the flow_classify application arguments
+
+.. code-block:: c
+
+ ret = parse_args(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid flow_classify parameters\n");
+
+The ``main()`` function also allocates a mempool to hold the mbufs
+(Message Buffers) used by the application:
+
+.. code-block:: c
+
+ mbuf_pool = rte_mempool_create("MBUF_POOL",
+ NUM_MBUFS * nb_ports,
+ MBUF_SIZE,
+ MBUF_CACHE_SIZE,
+ sizeof(struct rte_pktmbuf_pool_private),
+ rte_pktmbuf_pool_init, NULL,
+ rte_pktmbuf_init, NULL,
+ rte_socket_id(),
+ 0);
+
+mbufs are the packet buffer structure used by DPDK. They are explained in
+detail in the "Mbuf Library" section of the *DPDK Programmer's Guide*.
+
+The ``main()`` function also initializes all the ports using the user defined
+``port_init()`` function which is explained in the next section:
+
+.. code-block:: c
+
+ for (portid = 0; portid < nb_ports; portid++) {
+ if (port_init(portid, mbuf_pool) != 0) {
+ rte_exit(EXIT_FAILURE,
+ "Cannot init port %" PRIu8 "\n", portid);
+ }
+ }
+
+The ``main()`` function creates the ``flow classifier object`` and adds an ``ACL
+table`` to the flow classifer.
+
+.. code-block:: c
+
+ struct flow_classifier {
+ struct rte_flow_classifier *cls;
+ uint32_t table_id[RTE_FLOW_CLASSIFY_TABLE_MAX];
+ };
+
+ struct flow_classifier_acl {
+ struct flow_classifier cls;
+ } __rte_cache_aligned;
+
+ /* Memory allocation */
+ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct flow_classifier_acl));
+ cls_app = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+ if (cls_app == NULL)
+ rte_exit(EXIT_FAILURE, "Cannot allocate classifier memory\n");
+
+ cls_params.name = "flow_classifier";
+ cls_params.socket_id = socket_id;
+ cls_params.type = RTE_FLOW_CLASSIFY_TABLE_TYPE_ACL;
+
+ cls_app->cls = rte_flow_classifier_create(&cls_params);
+ if (cls_app->cls == NULL) {
+ rte_free(cls_app);
+ rte_exit(EXIT_FAILURE, "Cannot create classifier\n");
+ }
+
+ /* initialise ACL table params */
+ table_acl_params.name = "table_acl_ipv4_5tuple";
+ table_acl_params.n_rule_fields = RTE_DIM(ipv4_defs);
+ table_acl_params.n_rules = FLOW_CLASSIFY_MAX_RULE_NUM;
+ memcpy(table_acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
+
+ /* initialise table create params */
+ cls_table_params.ops = &rte_table_acl_ops,
+ cls_table_params.arg_create = &table_acl_params,
+ cls_table_params.table_metadata_size = 0;
+
+ ret = rte_flow_classify_table_create(cls_app->cls, &cls_table_params,
+ &cls->table_id[0]);
+ if (ret) {
+ rte_flow_classifier_free(cls_app->cls);
+ rte_free(cls);
+ rte_exit(EXIT_FAILURE, "Failed to create classifier table\n");
+ }
+
+It then reads the ipv4_rules_file.txt file and initialises the parameters for
+the ``rte_flow_classify_table_entry_add`` API.
+This API adds a rule to the ACL table.
+
+.. code-block:: c
+
+ if (add_rules(parm_config.rule_ipv4_name)) {
+ rte_flow_classifier_free(cls_app->cls);
+ rte_free(cls_app);
+ rte_exit(EXIT_FAILURE, "Failed to add rules\n");
+ }
+
+Once the initialization is complete, the application is ready to launch a
+function on an lcore. In this example ``lcore_main()`` is called on a single
+lcore.
+
+.. code-block:: c
+
+ lcore_main(cls_app);
+
+The ``lcore_main()`` function is explained below.
+
+The Port Initialization Function
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The main functional part of the port initialization used in the Basic
+Forwarding application is shown below:
+
+.. code-block:: c
+
+ static inline int
+ port_init(uint8_t port, struct rte_mempool *mbuf_pool)
+ {
+ struct rte_eth_conf port_conf = port_conf_default;
+ const uint16_t rx_rings = 1, tx_rings = 1;
+ struct ether_addr addr;
+ int retval;
+ uint16_t q;
+
+ if (port >= rte_eth_dev_count())
+ return -1;
+
+ /* Configure the Ethernet device. */
+ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
+ if (retval != 0)
+ return retval;
+
+ /* Allocate and set up 1 RX queue per Ethernet port. */
+ for (q = 0; q < rx_rings; q++) {
+ retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
+ rte_eth_dev_socket_id(port), NULL, mbuf_pool);
+ if (retval < 0)
+ return retval;
+ }
+
+ /* Allocate and set up 1 TX queue per Ethernet port. */
+ for (q = 0; q < tx_rings; q++) {
+ retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
+ rte_eth_dev_socket_id(port), NULL);
+ if (retval < 0)
+ return retval;
+ }
+
+ /* Start the Ethernet port. */
+ retval = rte_eth_dev_start(port);
+ if (retval < 0)
+ return retval;
+
+ /* Display the port MAC address. */
+ rte_eth_macaddr_get(port, &addr);
+ printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
+ " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
+ port,
+ addr.addr_bytes[0], addr.addr_bytes[1],
+ addr.addr_bytes[2], addr.addr_bytes[3],
+ addr.addr_bytes[4], addr.addr_bytes[5]);
+
+ /* Enable RX in promiscuous mode for the Ethernet device. */
+ rte_eth_promiscuous_enable(port);
+
+ return 0;
+ }
+
+The Ethernet ports are configured with default settings using the
+``rte_eth_dev_configure()`` function and the ``port_conf_default`` struct.
+
+.. code-block:: c
+
+ static const struct rte_eth_conf port_conf_default = {
+ .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
+ };
+
+For this example the ports are set up with 1 RX and 1 TX queue using the
+``rte_eth_rx_queue_setup()`` and ``rte_eth_tx_queue_setup()`` functions.
+
+The Ethernet port is then started:
+
+.. code-block:: c
+
+ retval = rte_eth_dev_start(port);
+
+
+Finally the RX port is set in promiscuous mode:
+
+.. code-block:: c
+
+ rte_eth_promiscuous_enable(port);
+
+The Add Rules function
+~~~~~~~~~~~~~~~~~~~~~~
+
+The ``add_rules`` function reads the ``ipv4_rules_file.txt`` file and calls the
+``add_classify_rule`` function which calls the
+``rte_flow_classify_table_entry_add`` API.
+
+.. code-block:: c
+
+ static int
+ add_rules(const char *rule_path)
+ {
+ FILE *fh;
+ char buff[LINE_MAX];
+ unsigned int i = 0;
+ unsigned int total_num = 0;
+ struct rte_eth_ntuple_filter ntuple_filter;
+
+ fh = fopen(rule_path, "rb");
+ if (fh == NULL)
+ rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__,
+ rule_path);
+
+ fseek(fh, 0, SEEK_SET);
+
+ i = 0;
+ while (fgets(buff, LINE_MAX, fh) != NULL) {
+ i++;
+
+ if (is_bypass_line(buff))
+ continue;
+
+ if (total_num >= FLOW_CLASSIFY_MAX_RULE_NUM - 1) {
+ printf("\nINFO: classify rule capacity %d reached\n",
+ total_num);
+ break;
+ }
+
+ if (parse_ipv4_5tuple_rule(buff, &ntuple_filter) != 0)
+ rte_exit(EXIT_FAILURE,
+ "%s Line %u: parse rules error\n",
+ rule_path, i);
+
+ if (add_classify_rule(&ntuple_filter) != 0)
+ rte_exit(EXIT_FAILURE, "add rule error\n");
+
+ total_num++;
+ }
+
+ fclose(fh);
+ return 0;
+ }
+
+
+The Lcore Main function
+~~~~~~~~~~~~~~~~~~~~~~~
+
+As we saw above the ``main()`` function calls an application function on the
+available lcores.
+The ``lcore_main`` function calls the ``rte_flow_classifier_query`` API.
+For the Basic Forwarding application the ``lcore_main`` function looks like the
+following:
+
+.. code-block:: c
+
+ /* flow classify data */
+ static int num_classify_rules;
+ static struct rte_flow_classify_rule *rules[MAX_NUM_CLASSIFY];
+ static struct rte_flow_classify_ipv4_5tuple_stats ntuple_stats;
+ static struct rte_flow_classify_stats classify_stats = {
+ .stats = (void *)&ntuple_stats
+ };
+
+ static __attribute__((noreturn)) void
+ lcore_main(cls_app)
+ {
+ const uint8_t nb_ports = rte_eth_dev_count();
+ uint8_t port;
+
+ /*
+ * Check that the port is on the same NUMA node as the polling thread
+ * for best performance.
+ */
+ for (port = 0; port < nb_ports; port++)
+ if (rte_eth_dev_socket_id(port) > 0 &&
+ rte_eth_dev_socket_id(port) != (int)rte_socket_id()) {
+ printf("\n\n");
+ printf("WARNING: port %u is on remote NUMA node\n",
+ port);
+ printf("to polling thread.\n");
+ printf("Performance will not be optimal.\n");
+
+ printf("\nCore %u forwarding packets. \n",
+ rte_lcore_id());
+ printf("[Ctrl+C to quit]\n
+ }
+
+ /* Run until the application is quit or killed. */
+ for (;;) {
+ /*
+ * Receive packets on a port and forward them on the paired
+ * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc.
+ */
+ for (port = 0; port < nb_ports; port++) {
+
+ /* Get burst of RX packets, from first port of pair. */
+ struct rte_mbuf *bufs[BURST_SIZE];
+ const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
+ bufs, BURST_SIZE);
+
+ if (unlikely(nb_rx == 0))
+ continue;
+
+ for (i = 0; i < MAX_NUM_CLASSIFY; i++) {
+ if (rules[i]) {
+ ret = rte_flow_classifier_query(
+ cls_app->cls,
+ cls_app->table_id[0],
+ bufs, nb_rx, rules[i],
+ &classify_stats);
+ if (ret)
+ printf(
+ "rule [%d] query failed ret [%d]\n\n",
+ i, ret);
+ else {
+ printf(
+ "rule[%d] count=%"PRIu64"\n",
+ i, ntuple_stats.counter1);
+
+ printf("proto = %d\n",
+ ntuple_stats.ipv4_5tuple.proto);
+ }
+ }
+ }
+
+ /* Send burst of TX packets, to second port of pair. */
+ const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
+ bufs, nb_rx);
+
+ /* Free any unsent packets. */
+ if (unlikely(nb_tx < nb_rx)) {
+ uint16_t buf;
+ for (buf = nb_tx; buf < nb_rx; buf++)
+ rte_pktmbuf_free(bufs[buf]);
+ }
+ }
+ }
+ }
+
+The main work of the application is done within the loop:
+
+.. code-block:: c
+
+ for (;;) {
+ for (port = 0; port < nb_ports; port++) {
+
+ /* Get burst of RX packets, from first port of pair. */
+ struct rte_mbuf *bufs[BURST_SIZE];
+ const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
+ bufs, BURST_SIZE);
+
+ if (unlikely(nb_rx == 0))
+ continue;
+
+ /* Send burst of TX packets, to second port of pair. */
+ const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
+ bufs, nb_rx);
+
+ /* Free any unsent packets. */
+ if (unlikely(nb_tx < nb_rx)) {
+ uint16_t buf;
+ for (buf = nb_tx; buf < nb_rx; buf++)
+ rte_pktmbuf_free(bufs[buf]);
+ }
+ }
+ }
+
+Packets are received in bursts on the RX ports and transmitted in bursts on
+the TX ports. The ports are grouped in pairs with a simple mapping scheme
+using the an XOR on the port number::
+
+ 0 -> 1
+ 1 -> 0
+
+ 2 -> 3
+ 3 -> 2
+
+ etc.
+
+The ``rte_eth_tx_burst()`` function frees the memory buffers of packets that
+are transmitted. If packets fail to transmit, ``(nb_tx < nb_rx)``, then they
+must be freed explicitly using ``rte_pktmbuf_free()``.
+
+The forwarding loop can be interrupted and the application closed using
+``Ctrl-C``.
diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index 0c17ebb..6e66046 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -78,6 +78,7 @@ Sample Applications User Guides
ptpclient
performance_thread
ipsec_secgw
+ flow_classify
**Figures**
--
1.9.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH 2/2] doc: flow classify sample app guide
2017-10-26 9:09 ` [dpdk-dev] [PATCH 2/2] doc: flow classify sample app guide Bernard Iremonger
@ 2017-11-02 17:00 ` Mcnamara, John
2017-11-02 17:32 ` Iremonger, Bernard
0 siblings, 1 reply; 13+ messages in thread
From: Mcnamara, John @ 2017-11-02 17:00 UTC (permalink / raw)
To: Iremonger, Bernard, dev
> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Thursday, October 26, 2017 10:09 AM
> To: dev@dpdk.org; Mcnamara, John <john.mcnamara@intel.com>
> Cc: Iremonger, Bernard <bernard.iremonger@intel.com>
> Subject: [PATCH 2/2] doc: flow classify sample app guide
>
> This file documents the flow_classify sample application which is used to
> demonstate use of the Flow Classify library, librte_flow_classify.
>
> Updated MAINTAINERS file
>
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> +
> +Compiling the Application
> +-------------------------
> +
> +To compile the application export the path to the DPDK source tree and
> +go to the example directory:
> +
There is now a simple section for compilation that you can reference directly
like this:
http://dpdk.org/doc/guides/sample_app_ug/hello_world.html#compiling-the-application
Copy the example from one of the other sample app guides.
John
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH 2/2] doc: flow classify sample app guide
2017-11-02 17:00 ` Mcnamara, John
@ 2017-11-02 17:32 ` Iremonger, Bernard
0 siblings, 0 replies; 13+ messages in thread
From: Iremonger, Bernard @ 2017-11-02 17:32 UTC (permalink / raw)
To: Mcnamara, John, dev; +Cc: Iremonger, Bernard
Hi John,
<snip>
> > Subject: [PATCH 2/2] doc: flow classify sample app guide
> >
> > This file documents the flow_classify sample application which is used
> > to demonstate use of the Flow Classify library, librte_flow_classify.
> >
> > Updated MAINTAINERS file
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
>
> > +
> > +Compiling the Application
> > +-------------------------
> > +
> > +To compile the application export the path to the DPDK source tree
> > +and go to the example directory:
> > +
>
>
> There is now a simple section for compilation that you can reference directly
> like this:
>
> http://dpdk.org/doc/guides/sample_app_ug/hello_world.html#compiling-
> the-application
>
> Copy the example from one of the other sample app guides.
Will do.
>
>
> John
Regards,
Bernard.
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2] flow classify documentation
2017-10-26 9:09 [dpdk-dev] [PATCH 0/2] flow classify documentation Bernard Iremonger
2017-10-26 9:09 ` [dpdk-dev] [PATCH 1/2] doc: flow classify library prog guide Bernard Iremonger
2017-10-26 9:09 ` [dpdk-dev] [PATCH 2/2] doc: flow classify sample app guide Bernard Iremonger
@ 2017-11-03 11:13 ` Bernard Iremonger
2017-11-03 11:13 ` [dpdk-dev] [PATCH v2] doc: flow classify guides Bernard Iremonger
3 siblings, 0 replies; 13+ messages in thread
From: Bernard Iremonger @ 2017-11-03 11:13 UTC (permalink / raw)
To: dev, john.mcnamara; +Cc: Bernard Iremonger
This patch set contains documention files for the
Flow Classify library and the Flow Classify sample
application and updates the MAINTAINERS file.
Changes in v2:
Squashed into 1 patch.
Fixed typos.
Replaced the compiling section in the Flow Classify
sample app guide with a reference to the standard
compiling document.
Added a reference to the Getting Started guide in
the Flow Classify sample app guide.
Bernard Iremonger (1):
doc: flow classify guides
MAINTAINERS | 2 +
doc/guides/prog_guide/flow_classify_lib.rst | 427 +++++++++++++++++++++
doc/guides/prog_guide/index.rst | 1 +
doc/guides/sample_app_ug/flow_classify.rst | 575 ++++++++++++++++++++++++++++
doc/guides/sample_app_ug/index.rst | 1 +
5 files changed, 1006 insertions(+)
create mode 100644 doc/guides/prog_guide/flow_classify_lib.rst
create mode 100644 doc/guides/sample_app_ug/flow_classify.rst
--
1.9.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2] doc: flow classify guides
2017-10-26 9:09 [dpdk-dev] [PATCH 0/2] flow classify documentation Bernard Iremonger
` (2 preceding siblings ...)
2017-11-03 11:13 ` [dpdk-dev] [PATCH v2] flow classify documentation Bernard Iremonger
@ 2017-11-03 11:13 ` Bernard Iremonger
2017-11-03 15:34 ` Mcnamara, John
3 siblings, 1 reply; 13+ messages in thread
From: Bernard Iremonger @ 2017-11-03 11:13 UTC (permalink / raw)
To: dev, john.mcnamara; +Cc: Bernard Iremonger
The Flow Classify Library Programmers Guide documents
librte_flow_classify.
The Flow Classify Sample Application Guide documents the
flow_classify sample application which is used to
demonstate the use of the Flow Classify Library,
librte_flow_classify.
Updated MAINTAINERS file
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
MAINTAINERS | 2 +
doc/guides/prog_guide/flow_classify_lib.rst | 427 +++++++++++++++++++++
doc/guides/prog_guide/index.rst | 1 +
doc/guides/sample_app_ug/flow_classify.rst | 575 ++++++++++++++++++++++++++++
doc/guides/sample_app_ug/index.rst | 1 +
5 files changed, 1006 insertions(+)
create mode 100644 doc/guides/prog_guide/flow_classify_lib.rst
create mode 100644 doc/guides/sample_app_ug/flow_classify.rst
diff --git a/MAINTAINERS b/MAINTAINERS
index 8ab08d2..7d30bda 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -725,6 +725,8 @@ M: Bernard Iremonger <bernard.iremonger@intel.com>
F: lib/librte_flow_classify/
F: test/test/test_flow_classify*
F: examples/flow_classify/
+F: doc/guides/prog_guide/flow_classify_lib.rst
+F: doc/guides/sample_app_ug/flow_classify.rst
Distributor
M: Bruce Richardson <bruce.richardson@intel.com>
diff --git a/doc/guides/prog_guide/flow_classify_lib.rst b/doc/guides/prog_guide/flow_classify_lib.rst
new file mode 100644
index 0000000..820dc72
--- /dev/null
+++ b/doc/guides/prog_guide/flow_classify_lib.rst
@@ -0,0 +1,427 @@
+.. BSD LICENSE
+ Copyright(c) 2017 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.
+
+Flow Classification Library
+===========================
+
+DPDK provides a Flow Classification library that provides the ability
+to classify an input packet by matching it against a set of Flow rules.
+
+The initial implementation supports counting of IPv4 5-tuple packets which match
+a particular Flow rule only.
+
+Please refer to the
+:doc:`./rte_flow`
+for more information.
+
+The Flow Classification library uses the ``librte_table`` API for managing Flow
+rules and matching packets against the Flow rules.
+The library is table agnostic and can use the following tables:
+``Access Control List``, ``Hash`` and ``Longest Prefix Match(LPM)``.
+The ``Access Control List`` table is used in the initial implementation.
+
+Please refer to the
+:doc:`./packet_framework`
+for more information.on ``librte_table``.
+
+DPDK provides an Access Control List library that provides the ability to
+classify an input packet based on a set of classification rules.
+
+Please refer to the
+:doc:`./packet_classif_access_ctrl`
+library for more information on ``librte_acl``.
+
+There is also a Flow Classify sample application which demonstrates the use of
+the Flow Classification Library API's.
+
+Please refer to the
+:doc:`../sample_app_ug/flow_classify`
+for more information on the ``flow_classify`` sample application.
+
+Overview
+--------
+
+The library has the following API's
+
+.. code-block:: c
+
+ /**
+ * Flow classifier create
+ *
+ * @param params
+ * Parameters for flow classifier creation
+ * @return
+ * Handle to flow classifier instance on success or NULL otherwise
+ */
+ struct rte_flow_classifier *
+ rte_flow_classifier_create(struct rte_flow_classifier_params *params);
+
+ /**
+ * Flow classifier free
+ *
+ * @param cls
+ * Handle to flow classifier instance
+ * @return
+ * 0 on success, error code otherwise
+ */
+ int
+ rte_flow_classifier_free(struct rte_flow_classifier *cls);
+
+ /**
+ * Flow classify table create
+ *
+ * @param cls
+ * Handle to flow classifier instance
+ * @param params
+ * Parameters for flow_classify table creation
+ * @param table_id
+ * Table ID. Valid only within the scope of table IDs of the current
+ * classifier. Only returned after a successful invocation.
+ * @return
+ * 0 on success, error code otherwise
+ */
+ int
+ rte_flow_classify_table_create(struct rte_flow_classifier *cls,
+ struct rte_flow_classify_table_params *params,
+ uint32_t *table_id);
+
+ /**
+ * Add a flow classify rule to the flow_classifier table.
+ *
+ * @param[in] cls
+ * Flow classifier handle
+ * @param[in] table_id
+ * id of table
+ * @param[in] attr
+ * Flow rule attributes
+ * @param[in] pattern
+ * Pattern specification (list terminated by the END pattern item).
+ * @param[in] actions
+ * Associated actions (list terminated by the END pattern item).
+ * @param[out] error
+ * Perform verbose error reporting if not NULL. Structure
+ * initialised in case of error only.
+ * @return
+ * A valid handle in case of success, NULL otherwise.
+ */
+ struct rte_flow_classify_rule *
+ rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls,
+ uint32_t table_id,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error);
+
+ /**
+ * Delete a flow classify rule from the flow_classifier table.
+ *
+ * @param[in] cls
+ * Flow classifier handle
+ * @param[in] table_id
+ * id of table
+ * @param[in] rule
+ * Flow classify rule
+ * @return
+ * 0 on success, error code otherwise.
+ */
+ int
+ rte_flow_classify_table_entry_delete(struct rte_flow_classifier *cls,
+ uint32_t table_id,
+ struct rte_flow_classify_rule *rule);
+
+ /**
+ * Query flow classifier for given rule.
+ *
+ * @param[in] cls
+ * Flow classifier handle
+ * @param[in] table_id
+ * id of table
+ * @param[in] pkts
+ * Pointer to packets to process
+ * @param[in] nb_pkts
+ * Number of packets to process
+ * @param[in] rule
+ * Flow classify rule
+ * @param[in] stats
+ * Flow classify stats
+ *
+ * @return
+ * 0 on success, error code otherwise.
+ */
+ int
+ rte_flow_classifier_query(struct rte_flow_classifier *cls,
+ uint32_t table_id,
+ struct rte_mbuf **pkts,
+ const uint16_t nb_pkts,
+ struct rte_flow_classify_rule *rule,
+ struct rte_flow_classify_stats *stats);
+
+Classifier creation
+~~~~~~~~~~~~~~~~~~~
+
+The application creates the ``Classifier`` using the
+``rte_flow_classifier_create`` API.
+The ``rte_flow_classify_params`` structure must be initialised by the
+application before calling the API.
+
+.. code-block:: c
+
+ struct rte_flow_classifier_params {
+ /** flow classifier name */
+ const char *name;
+
+ /** CPU socket ID where memory for the flow classifier and its */
+ /** elements (tables) should be allocated */
+ int socket_id;
+
+ /** Table type */
+ enum rte_flow_classify_table_type type;
+ };
+
+The ``Classifier`` has the following internal structures:
+
+.. code-block:: c
+
+ struct rte_table {
+ /* Input parameters */
+ struct rte_table_ops ops;
+ uint32_t entry_size;
+ enum rte_flow_classify_table_type type;
+
+ /* Handle to the low-level table object */
+ void *h_table;
+ };
+
+ #define RTE_FLOW_CLASSIFIER_MAX_NAME_SZ 256
+
+ struct rte_flow_classifier {
+ /* Input parameters */
+ char name[RTE_FLOW_CLASSIFIER_MAX_NAME_SZ];
+ int socket_id;
+ enum rte_flow_classify_table_type type;
+
+ /* Internal tables */
+ struct rte_table tables[RTE_FLOW_CLASSIFY_TABLE_MAX];
+ uint32_t num_tables;
+ uint16_t nb_pkts;
+ struct rte_flow_classify_table_entry
+ *entries[RTE_PORT_IN_BURST_SIZE_MAX];
+ } __rte_cache_aligned;
+
+Adding a table to the Classifier
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The application adds a table to the ``Classifier`` using the
+``rte_flow_classify_table_create`` API.
+The ``rte_flow_classify_table_params`` structure must be initialised by the
+application before calling the API.
+
+.. code-block:: c
+
+ struct rte_flow_classify_table_params {
+ /** Table operations (specific to each table type) */
+ struct rte_table_ops *ops;
+
+ /** Opaque param to be passed to the table create operation */
+ void *arg_create;
+
+ /** Memory size to be reserved per classifier object entry for */
+ /** storing meta data */
+ uint32_t table_metadata_size;
+ };
+
+To create an ACL table the ``rte_table_acl_params`` structure must be
+initialised and assigned to ``arg_create`` in the
+``rte_flow_classify_table_params`` structure.
+
+.. code-block:: c
+
+ struct rte_table_acl_params {
+ /** Name */
+ const char *name;
+
+ /** Maximum number of ACL rules in the table */
+ uint32_t n_rules;
+
+ /** Number of fields in the ACL rule specification */
+ uint32_t n_rule_fields;
+
+ /** Format specification of the fields of the ACL rule */
+ struct rte_acl_field_def field_format[RTE_ACL_MAX_FIELDS];
+ };
+
+The fields for the ACL rule must also be initialised by the application.
+
+An ACL table can be added to the ``Classifier`` for each ACL rule, for example
+another table could be added for the IPv6 5-tuple rule.
+
+Flow Parsing
+~~~~~~~~~~~~
+
+The library currently supports three IPv4 5-tuple flow patterns, for UDP, TCP
+and SCTP.
+
+.. code-block:: c
+
+ /* Pattern for IPv4 5-tuple UDP filter */
+ static enum rte_flow_item_type pattern_ntuple_1[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_UDP,
+ RTE_FLOW_ITEM_TYPE_END,
+ };
+
+ /* Pattern for IPv4 5-tuple TCP filter */
+ static enum rte_flow_item_type pattern_ntuple_2[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_TCP,
+ RTE_FLOW_ITEM_TYPE_END,
+ };
+
+ /* Pattern for IPv4 5-tuple SCTP filter */
+ static enum rte_flow_item_type pattern_ntuple_3[] = {
+ RTE_FLOW_ITEM_TYPE_ETH,
+ RTE_FLOW_ITEM_TYPE_IPV4,
+ RTE_FLOW_ITEM_TYPE_SCTP,
+ RTE_FLOW_ITEM_TYPE_END,
+ };
+
+The internal function ``flow_classify_parse_flow`` parses the
+IPv4 5-tuple pattern, attributes and actions and returns the 5-tuple data in the
+``rte_eth_ntuple_filter`` structure.
+
+.. code-block:: c
+
+ static int
+ flow_classify_parse_flow(
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_action actions[],
+ struct rte_flow_error *error)
+
+Adding Flow Rules
+~~~~~~~~~~~~~~~~~
+
+The ``rte_flow_classify_table_entry_add`` API creates an
+``rte_flow_classify`` object which contains the flow_classify id and type, the
+action, a union of add and delete keys and a union of rules.
+It uses the ``flow_classify_parse_flow`` internal function for parsing the
+flow parameters.
+The 5-tuple ACL key data is obtained from the ``rte_eth_ntuple_filter``
+structure populated by the ``classify_parse_ntuple_filter`` function which
+parses the Flow rule.
+
+.. code-block:: c
+
+ struct acl_keys {
+ struct rte_table_acl_rule_add_params key_add; /* add key */
+ struct rte_table_acl_rule_delete_params key_del; /* delete key */
+ };
+
+ struct classify_rules {
+ enum rte_flow_classify_rule_type type;
+ union {
+ struct rte_flow_classify_ipv4_5tuple ipv4_5tuple;
+ } u;
+ };
+
+ struct rte_flow_classify {
+ uint32_t id; /* unique ID of classify object */
+ struct rte_flow_action action; /* action when match found */
+ struct classify_rules rules; /* union of rules */
+ union {
+ struct acl_keys key;
+ } u;
+ int key_found; /* rule key found in table */
+ void *entry; /* pointer to buffer to hold rule meta data */
+ void *entry_ptr; /* handle to the table entry for rule meta data */
+ };
+
+It then calls the ``table[table_id].ops.f_add`` API to add the rule to the ACL
+table.
+
+Deleting Flow Rules
+~~~~~~~~~~~~~~~~~~~
+
+The ``rte_flow_classify_table_entry_delete`` API calls the
+``table[table_id].ops.f_delete`` API to delete a rule from the ACL table.
+
+Packet Matching
+~~~~~~~~~~~~~~~
+
+The ``rte_flow_classifier_query`` API is used to find packets which match a
+given flow Flow rule in the table.
+This API calls the flow_classify_run internal function which calls the
+``table[table_id].ops.f_lookup`` API to see if any packets in a burst match any
+of the Flow rules in the table.
+The meta data for the highest priority rule matched for each packet is returned
+in the entries array in the ``rte_flow_classify`` object.
+The internal function ``action_apply`` implements the ``Count`` action which is
+used to return data which matches a particular Flow rule.
+
+The rte_flow_classifier_query API uses the following structures to return data
+to the application.
+
+.. code-block:: c
+
+ /** IPv4 5-tuple data */
+ struct rte_flow_classify_ipv4_5tuple {
+ uint32_t dst_ip; /**< Destination IP address in big endian. */
+ uint32_t dst_ip_mask; /**< Mask of destination IP address. */
+ uint32_t src_ip; /**< Source IP address in big endian. */
+ uint32_t src_ip_mask; /**< Mask of destination IP address. */
+ uint16_t dst_port; /**< Destination port in big endian. */
+ uint16_t dst_port_mask; /**< Mask of destination port. */
+ uint16_t src_port; /**< Source Port in big endian. */
+ uint16_t src_port_mask; /**< Mask of source port. */
+ uint8_t proto; /**< L4 protocol. */
+ uint8_t proto_mask; /**< Mask of L4 protocol. */
+ };
+
+ /**
+ * Flow stats
+ *
+ * For the count action, stats can be returned by the query API.
+ *
+ * Storage for stats is provided by the application.
+ *
+ *
+ */
+ struct rte_flow_classify_stats {
+ void *stats;
+ };
+
+ struct rte_flow_classify_5tuple_stats {
+ /** count of packets that match IPv4 5tuple pattern */
+ uint64_t counter1;
+ /** IPv4 5tuple data */
+ struct rte_flow_classify_ipv4_5tuple ipv4_5tuple;
+ };
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index 9759264..21d1c3d 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -72,6 +72,7 @@ Programmer's Guide
vhost_lib
metrics_lib
port_hotplug_framework
+ flow_classify_lib
source_org
dev_kit_build_system
dev_kit_root_make_help
diff --git a/doc/guides/sample_app_ug/flow_classify.rst b/doc/guides/sample_app_ug/flow_classify.rst
new file mode 100644
index 0000000..bc12b87
--- /dev/null
+++ b/doc/guides/sample_app_ug/flow_classify.rst
@@ -0,0 +1,575 @@
+.. BSD LICENSE
+ Copyright(c) 2017 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.
+
+Flow Classify Sample Application
+================================
+
+The Flow Classify sample application is based on the simple *skeleton* example
+of a forwarding application.
+
+It is intended as a demonstration of the basic components of a DPDK forwarding
+application which uses the Flow Classify library API's.
+
+Please refer to the
+:doc:`../prog_guide/flow_classify_lib`
+for more information.
+
+Compiling the Application
+-------------------------
+
+To compile the sample application see :doc:`compiling`.
+
+The application is located in the ``flow_classify`` sub-directory.
+
+Running the Application
+-----------------------
+
+To run the example in a ``linuxapp`` environment:
+
+.. code-block:: console
+
+ cd ~/dpdk/examples/flow_classify
+ ./build/flow_classify -c 4 -n 4 -- --rule_ipv4="../ipv4_rules_file.txt"
+
+Please refer to the *DPDK Getting Started Guide*, section
+:doc:`../linux_gsg/build_sample_apps`
+for general information on running applications and the Environment Abstraction
+Layer (EAL) options.
+
+
+Sample ipv4_rules_file.txt
+--------------------------
+
+.. code-block:: console
+
+ #file format:
+ #src_ip/masklen dst_ip/masklen src_port : mask dst_port : mask proto/mask priority
+ #
+ 2.2.2.3/24 2.2.2.7/24 32 : 0xffff 33 : 0xffff 17/0xff 0
+ 9.9.9.3/24 9.9.9.7/24 32 : 0xffff 33 : 0xffff 17/0xff 1
+ 9.9.9.3/24 9.9.9.7/24 32 : 0xffff 33 : 0xffff 6/0xff 2
+ 9.9.8.3/24 9.9.8.7/24 32 : 0xffff 33 : 0xffff 6/0xff 3
+ 6.7.8.9/24 2.3.4.5/24 32 : 0x0000 33 : 0x0000 132/0xff 4
+
+Explanation
+-----------
+
+The following sections provide an explanation of the main components of the
+code.
+
+All DPDK library functions used in the sample code are prefixed with ``rte_``
+and are explained in detail in the *DPDK API Documentation*.
+
+ACL field definitions for the IPv4 5 tuple rule
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following field definitions are used when creating the ACL table during
+initialisation of the ``Flow Classify`` application..
+
+.. code-block:: c
+
+ enum {
+ PROTO_FIELD_IPV4,
+ SRC_FIELD_IPV4,
+ DST_FIELD_IPV4,
+ SRCP_FIELD_IPV4,
+ DSTP_FIELD_IPV4,
+ NUM_FIELDS_IPV4
+ };
+
+ enum {
+ PROTO_INPUT_IPV4,
+ SRC_INPUT_IPV4,
+ DST_INPUT_IPV4,
+ SRCP_DESTP_INPUT_IPV4
+ };
+
+ static struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
+ /* first input field - always one byte long. */
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = PROTO_FIELD_IPV4,
+ .input_index = PROTO_INPUT_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, next_proto_id),
+ },
+ /* next input field (IPv4 source address) - 4 consecutive bytes. */
+ {
+ /* rte_flow uses a bit mask for IPv4 addresses */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC_FIELD_IPV4,
+ .input_index = SRC_INPUT_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, src_addr),
+ },
+ /* next input field (IPv4 destination address) - 4 consecutive bytes. */
+ {
+ /* rte_flow uses a bit mask for IPv4 addresses */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST_FIELD_IPV4,
+ .input_index = DST_INPUT_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ offsetof(struct ipv4_hdr, dst_addr),
+ },
+ /*
+ * Next 2 fields (src & dst ports) form 4 consecutive bytes.
+ * They share the same input index.
+ */
+ {
+ /* rte_flow uses a bit mask for protocol ports */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint16_t),
+ .field_index = SRCP_FIELD_IPV4,
+ .input_index = SRCP_DESTP_INPUT_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr) +
+ offsetof(struct tcp_hdr, src_port),
+ },
+ {
+ /* rte_flow uses a bit mask for protocol ports */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint16_t),
+ .field_index = DSTP_FIELD_IPV4,
+ .input_index = SRCP_DESTP_INPUT_IPV4,
+ .offset = sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr) +
+ offsetof(struct tcp_hdr, dst_port),
+ },
+ };
+
+The Main Function
+~~~~~~~~~~~~~~~~~
+
+The ``main()`` function performs the initialization and calls the execution
+threads for each lcore.
+
+The first task is to initialize the Environment Abstraction Layer (EAL).
+The ``argc`` and ``argv`` arguments are provided to the ``rte_eal_init()``
+function. The value returned is the number of parsed arguments:
+
+.. code-block:: c
+
+ int ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
+
+It then parses the flow_classify application arguments
+
+.. code-block:: c
+
+ ret = parse_args(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid flow_classify parameters\n");
+
+The ``main()`` function also allocates a mempool to hold the mbufs
+(Message Buffers) used by the application:
+
+.. code-block:: c
+
+ mbuf_pool = rte_mempool_create("MBUF_POOL",
+ NUM_MBUFS * nb_ports,
+ MBUF_SIZE,
+ MBUF_CACHE_SIZE,
+ sizeof(struct rte_pktmbuf_pool_private),
+ rte_pktmbuf_pool_init, NULL,
+ rte_pktmbuf_init, NULL,
+ rte_socket_id(),
+ 0);
+
+mbufs are the packet buffer structure used by DPDK. They are explained in
+detail in the "Mbuf Library" section of the *DPDK Programmer's Guide*.
+
+The ``main()`` function also initializes all the ports using the user defined
+``port_init()`` function which is explained in the next section:
+
+.. code-block:: c
+
+ for (portid = 0; portid < nb_ports; portid++) {
+ if (port_init(portid, mbuf_pool) != 0) {
+ rte_exit(EXIT_FAILURE,
+ "Cannot init port %" PRIu8 "\n", portid);
+ }
+ }
+
+The ``main()`` function creates the ``flow classifier object`` and adds an ``ACL
+table`` to the flow classifier.
+
+.. code-block:: c
+
+ struct flow_classifier {
+ struct rte_flow_classifier *cls;
+ uint32_t table_id[RTE_FLOW_CLASSIFY_TABLE_MAX];
+ };
+
+ struct flow_classifier_acl {
+ struct flow_classifier cls;
+ } __rte_cache_aligned;
+
+ /* Memory allocation */
+ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct flow_classifier_acl));
+ cls_app = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+ if (cls_app == NULL)
+ rte_exit(EXIT_FAILURE, "Cannot allocate classifier memory\n");
+
+ cls_params.name = "flow_classifier";
+ cls_params.socket_id = socket_id;
+ cls_params.type = RTE_FLOW_CLASSIFY_TABLE_TYPE_ACL;
+
+ cls_app->cls = rte_flow_classifier_create(&cls_params);
+ if (cls_app->cls == NULL) {
+ rte_free(cls_app);
+ rte_exit(EXIT_FAILURE, "Cannot create classifier\n");
+ }
+
+ /* initialise ACL table params */
+ table_acl_params.name = "table_acl_ipv4_5tuple";
+ table_acl_params.n_rule_fields = RTE_DIM(ipv4_defs);
+ table_acl_params.n_rules = FLOW_CLASSIFY_MAX_RULE_NUM;
+ memcpy(table_acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
+
+ /* initialise table create params */
+ cls_table_params.ops = &rte_table_acl_ops,
+ cls_table_params.arg_create = &table_acl_params,
+ cls_table_params.table_metadata_size = 0;
+
+ ret = rte_flow_classify_table_create(cls_app->cls, &cls_table_params,
+ &cls->table_id[0]);
+ if (ret) {
+ rte_flow_classifier_free(cls_app->cls);
+ rte_free(cls);
+ rte_exit(EXIT_FAILURE, "Failed to create classifier table\n");
+ }
+
+It then reads the ipv4_rules_file.txt file and initialises the parameters for
+the ``rte_flow_classify_table_entry_add`` API.
+This API adds a rule to the ACL table.
+
+.. code-block:: c
+
+ if (add_rules(parm_config.rule_ipv4_name)) {
+ rte_flow_classifier_free(cls_app->cls);
+ rte_free(cls_app);
+ rte_exit(EXIT_FAILURE, "Failed to add rules\n");
+ }
+
+Once the initialization is complete, the application is ready to launch a
+function on an lcore. In this example ``lcore_main()`` is called on a single
+lcore.
+
+.. code-block:: c
+
+ lcore_main(cls_app);
+
+The ``lcore_main()`` function is explained below.
+
+The Port Initialization Function
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The main functional part of the port initialization used in the Basic
+Forwarding application is shown below:
+
+.. code-block:: c
+
+ static inline int
+ port_init(uint8_t port, struct rte_mempool *mbuf_pool)
+ {
+ struct rte_eth_conf port_conf = port_conf_default;
+ const uint16_t rx_rings = 1, tx_rings = 1;
+ struct ether_addr addr;
+ int retval;
+ uint16_t q;
+
+ if (port >= rte_eth_dev_count())
+ return -1;
+
+ /* Configure the Ethernet device. */
+ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
+ if (retval != 0)
+ return retval;
+
+ /* Allocate and set up 1 RX queue per Ethernet port. */
+ for (q = 0; q < rx_rings; q++) {
+ retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
+ rte_eth_dev_socket_id(port), NULL, mbuf_pool);
+ if (retval < 0)
+ return retval;
+ }
+
+ /* Allocate and set up 1 TX queue per Ethernet port. */
+ for (q = 0; q < tx_rings; q++) {
+ retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
+ rte_eth_dev_socket_id(port), NULL);
+ if (retval < 0)
+ return retval;
+ }
+
+ /* Start the Ethernet port. */
+ retval = rte_eth_dev_start(port);
+ if (retval < 0)
+ return retval;
+
+ /* Display the port MAC address. */
+ rte_eth_macaddr_get(port, &addr);
+ printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
+ " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
+ port,
+ addr.addr_bytes[0], addr.addr_bytes[1],
+ addr.addr_bytes[2], addr.addr_bytes[3],
+ addr.addr_bytes[4], addr.addr_bytes[5]);
+
+ /* Enable RX in promiscuous mode for the Ethernet device. */
+ rte_eth_promiscuous_enable(port);
+
+ return 0;
+ }
+
+The Ethernet ports are configured with default settings using the
+``rte_eth_dev_configure()`` function and the ``port_conf_default`` struct.
+
+.. code-block:: c
+
+ static const struct rte_eth_conf port_conf_default = {
+ .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
+ };
+
+For this example the ports are set up with 1 RX and 1 TX queue using the
+``rte_eth_rx_queue_setup()`` and ``rte_eth_tx_queue_setup()`` functions.
+
+The Ethernet port is then started:
+
+.. code-block:: c
+
+ retval = rte_eth_dev_start(port);
+
+
+Finally the RX port is set in promiscuous mode:
+
+.. code-block:: c
+
+ rte_eth_promiscuous_enable(port);
+
+The Add Rules function
+~~~~~~~~~~~~~~~~~~~~~~
+
+The ``add_rules`` function reads the ``ipv4_rules_file.txt`` file and calls the
+``add_classify_rule`` function which calls the
+``rte_flow_classify_table_entry_add`` API.
+
+.. code-block:: c
+
+ static int
+ add_rules(const char *rule_path)
+ {
+ FILE *fh;
+ char buff[LINE_MAX];
+ unsigned int i = 0;
+ unsigned int total_num = 0;
+ struct rte_eth_ntuple_filter ntuple_filter;
+
+ fh = fopen(rule_path, "rb");
+ if (fh == NULL)
+ rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__,
+ rule_path);
+
+ fseek(fh, 0, SEEK_SET);
+
+ i = 0;
+ while (fgets(buff, LINE_MAX, fh) != NULL) {
+ i++;
+
+ if (is_bypass_line(buff))
+ continue;
+
+ if (total_num >= FLOW_CLASSIFY_MAX_RULE_NUM - 1) {
+ printf("\nINFO: classify rule capacity %d reached\n",
+ total_num);
+ break;
+ }
+
+ if (parse_ipv4_5tuple_rule(buff, &ntuple_filter) != 0)
+ rte_exit(EXIT_FAILURE,
+ "%s Line %u: parse rules error\n",
+ rule_path, i);
+
+ if (add_classify_rule(&ntuple_filter) != 0)
+ rte_exit(EXIT_FAILURE, "add rule error\n");
+
+ total_num++;
+ }
+
+ fclose(fh);
+ return 0;
+ }
+
+
+The Lcore Main function
+~~~~~~~~~~~~~~~~~~~~~~~
+
+As we saw above the ``main()`` function calls an application function on the
+available lcores.
+The ``lcore_main`` function calls the ``rte_flow_classifier_query`` API.
+For the Basic Forwarding application the ``lcore_main`` function looks like the
+following:
+
+.. code-block:: c
+
+ /* flow classify data */
+ static int num_classify_rules;
+ static struct rte_flow_classify_rule *rules[MAX_NUM_CLASSIFY];
+ static struct rte_flow_classify_ipv4_5tuple_stats ntuple_stats;
+ static struct rte_flow_classify_stats classify_stats = {
+ .stats = (void *)&ntuple_stats
+ };
+
+ static __attribute__((noreturn)) void
+ lcore_main(cls_app)
+ {
+ const uint8_t nb_ports = rte_eth_dev_count();
+ uint8_t port;
+
+ /*
+ * Check that the port is on the same NUMA node as the polling thread
+ * for best performance.
+ */
+ for (port = 0; port < nb_ports; port++)
+ if (rte_eth_dev_socket_id(port) > 0 &&
+ rte_eth_dev_socket_id(port) != (int)rte_socket_id()) {
+ printf("\n\n");
+ printf("WARNING: port %u is on remote NUMA node\n",
+ port);
+ printf("to polling thread.\n");
+ printf("Performance will not be optimal.\n");
+
+ printf("\nCore %u forwarding packets. \n",
+ rte_lcore_id());
+ printf("[Ctrl+C to quit]\n
+ }
+
+ /* Run until the application is quit or killed. */
+ for (;;) {
+ /*
+ * Receive packets on a port and forward them on the paired
+ * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc.
+ */
+ for (port = 0; port < nb_ports; port++) {
+
+ /* Get burst of RX packets, from first port of pair. */
+ struct rte_mbuf *bufs[BURST_SIZE];
+ const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
+ bufs, BURST_SIZE);
+
+ if (unlikely(nb_rx == 0))
+ continue;
+
+ for (i = 0; i < MAX_NUM_CLASSIFY; i++) {
+ if (rules[i]) {
+ ret = rte_flow_classifier_query(
+ cls_app->cls,
+ cls_app->table_id[0],
+ bufs, nb_rx, rules[i],
+ &classify_stats);
+ if (ret)
+ printf(
+ "rule [%d] query failed ret [%d]\n\n",
+ i, ret);
+ else {
+ printf(
+ "rule[%d] count=%"PRIu64"\n",
+ i, ntuple_stats.counter1);
+
+ printf("proto = %d\n",
+ ntuple_stats.ipv4_5tuple.proto);
+ }
+ }
+ }
+
+ /* Send burst of TX packets, to second port of pair. */
+ const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
+ bufs, nb_rx);
+
+ /* Free any unsent packets. */
+ if (unlikely(nb_tx < nb_rx)) {
+ uint16_t buf;
+ for (buf = nb_tx; buf < nb_rx; buf++)
+ rte_pktmbuf_free(bufs[buf]);
+ }
+ }
+ }
+ }
+
+The main work of the application is done within the loop:
+
+.. code-block:: c
+
+ for (;;) {
+ for (port = 0; port < nb_ports; port++) {
+
+ /* Get burst of RX packets, from first port of pair. */
+ struct rte_mbuf *bufs[BURST_SIZE];
+ const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
+ bufs, BURST_SIZE);
+
+ if (unlikely(nb_rx == 0))
+ continue;
+
+ /* Send burst of TX packets, to second port of pair. */
+ const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
+ bufs, nb_rx);
+
+ /* Free any unsent packets. */
+ if (unlikely(nb_tx < nb_rx)) {
+ uint16_t buf;
+ for (buf = nb_tx; buf < nb_rx; buf++)
+ rte_pktmbuf_free(bufs[buf]);
+ }
+ }
+ }
+
+Packets are received in bursts on the RX ports and transmitted in bursts on
+the TX ports. The ports are grouped in pairs with a simple mapping scheme
+using the an XOR on the port number::
+
+ 0 -> 1
+ 1 -> 0
+
+ 2 -> 3
+ 3 -> 2
+
+ etc.
+
+The ``rte_eth_tx_burst()`` function frees the memory buffers of packets that
+are transmitted. If packets fail to transmit, ``(nb_tx < nb_rx)``, then they
+must be freed explicitly using ``rte_pktmbuf_free()``.
+
+The forwarding loop can be interrupted and the application closed using
+``Ctrl-C``.
diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index 1e18d88..b62046a 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -79,6 +79,7 @@ Sample Applications User Guides
ptpclient
performance_thread
ipsec_secgw
+ flow_classify
**Figures**
--
1.9.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH v2] doc: flow classify guides
2017-11-03 11:13 ` [dpdk-dev] [PATCH v2] doc: flow classify guides Bernard Iremonger
@ 2017-11-03 15:34 ` Mcnamara, John
2017-11-07 22:00 ` Thomas Monjalon
0 siblings, 1 reply; 13+ messages in thread
From: Mcnamara, John @ 2017-11-03 15:34 UTC (permalink / raw)
To: Iremonger, Bernard, dev
> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Friday, November 3, 2017 11:14 AM
> To: dev@dpdk.org; Mcnamara, John <john.mcnamara@intel.com>
> Cc: Iremonger, Bernard <bernard.iremonger@intel.com>
> Subject: [PATCH v2] doc: flow classify guides
>
> The Flow Classify Library Programmers Guide documents
> librte_flow_classify.
>
> The Flow Classify Sample Application Guide documents the flow_classify
> sample application which is used to demonstate the use of the Flow
> Classify Library, librte_flow_classify.
>
> Updated MAINTAINERS file
>
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: John McNamara <john.mcnamara@intel.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH v2] doc: flow classify guides
2017-11-03 15:34 ` Mcnamara, John
@ 2017-11-07 22:00 ` Thomas Monjalon
0 siblings, 0 replies; 13+ messages in thread
From: Thomas Monjalon @ 2017-11-07 22:00 UTC (permalink / raw)
To: Iremonger, Bernard; +Cc: dev, Mcnamara, John
> > The Flow Classify Library Programmers Guide documents
> > librte_flow_classify.
> >
> > The Flow Classify Sample Application Guide documents the flow_classify
> > sample application which is used to demonstate the use of the Flow
> > Classify Library, librte_flow_classify.
> >
> > Updated MAINTAINERS file
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
>
> Acked-by: John McNamara <john.mcnamara@intel.com>
Applied, thanks
^ permalink raw reply [flat|nested] 13+ messages in thread