net/i40e: fix IPv6 fragment RSS offload type in flow
[dpdk.git] / doc / guides / sample_app_ug / flow_classify.rst
index 427fded..6c4c04e 100644 (file)
@@ -1,32 +1,5 @@
-..  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.
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2017 Intel Corporation.
 
 Flow Classify Sample Application
 ================================
@@ -51,12 +24,12 @@ The application is located in the ``flow_classify`` sub-directory.
 Running the Application
 -----------------------
 
-To run the example in a ``linuxapp`` environment:
+To run the example in a ``linux`` environment:
 
 .. code-block:: console
 
-    cd ~/dpdk/examples/flow_classify
-    ./build/flow_classify -c 4 -n 4 -- --rule_ipv4="../ipv4_rules_file.txt"
+    ./<build_dir>/examples/dpdk-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`
@@ -91,81 +64,12 @@ 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..
+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),
-        },
-    };
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Creation of ACL table during initialization of application. 8<
+    :end-before: >8 End of creation of ACL table.
 
 The Main Function
 ~~~~~~~~~~~~~~~~~
@@ -177,34 +81,28 @@ 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");
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Initialize the Environment Abstraction Layer (EAL). 8<
+    :end-before: >8 End of initialization of EAL.
+    :dedent: 1
 
 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");
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Parse application arguments (after the EAL ones). 8<
+    :end-before: >8 End of parse application arguments.
+    :dedent: 1
 
 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);
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Creates a new mempool in memory to hold the mbufs. 8<
+    :end-before: >8 End of creation of new mempool in memory.
+    :dedent: 1
 
 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*.
@@ -212,72 +110,35 @@ 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);
-        }
-    }
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Initialize all ports. 8<
+    :end-before: >8 End of initialization of all ports.
+    :dedent: 1
 
 The ``main()`` function creates the ``flow classifier object`` and adds an ``ACL
 table`` to the flow classifier.
 
-.. code-block:: c
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Creation of flow classifier object. 8<
+    :end-before: >8 End of creation of flow classifier object.
 
-    struct flow_classifier {
-        struct rte_flow_classifier *cls;
-    };
-
-    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_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.type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
-
-    ret = rte_flow_classify_table_create(cls_app->cls, &cls_table_params);
-    if (ret) {
-        rte_flow_classifier_free(cls_app->cls);
-        rte_free(cls);
-        rte_exit(EXIT_FAILURE, "Failed to create classifier table\n");
-    }
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Memory allocation. 8<
+    :end-before: >8 End of initialization of table create params.
+    :dedent: 1
 
 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");
-    }
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Read file of IPv4 tuple rules. 8<
+    :end-before: >8 End of reading file of IPv4 5 tuple rules.
+    :dedent: 1
 
 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
@@ -295,85 +156,31 @@ 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;
-    }
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Initializing port using global settings. 8<
+    :end-before: >8 End of initializing a given port.
 
 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 }
-    };
+``rte_eth_dev_configure()`` function.
 
 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);
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Start the Ethernet port. 8<
+    :end-before: >8 End of starting the Ethernet port.
+    :dedent: 1
 
 
 Finally the RX port is set in promiscuous mode:
 
 .. code-block:: c
 
-    rte_eth_promiscuous_enable(port);
+    retval = rte_eth_promiscuous_enable(port);
 
 The Add Rules function
 ~~~~~~~~~~~~~~~~~~~~~~
@@ -382,51 +189,10 @@ 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;
-    }
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Reads file and calls the add_classify_rule function. 8<
+    :end-before: >8 End of add_rules.
 
 
 The Lcore Main function
@@ -438,118 +204,23 @@ 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
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Flow classify data. 8<
+    :end-before: >8 End of flow classify data.
 
-    /* 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,
-                            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]);
-                }
-            }
-        }
-    }
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Classifying the packets. 8<
+    :end-before: >8 End of lcore main.
 
 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]);
-                }
-            }
-        }
+.. literalinclude:: ../../../examples/flow_classify/flow_classify.c
+    :language: c
+    :start-after: Run until the application is quit or killed. 8<
+    :end-before: >8 End of main loop.
+    :dedent: 1
 
 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