New upstream version 18.02
[deb_dpdk.git] / doc / guides / sample_app_ug / flow_filtering.rst
1 ..  BSD LICENSE
2     Copyright(c) 2017 Mellanox Corporation. All rights reserved.
3     All rights reserved.
4
5     Redistribution and use in source and binary forms, with or without
6     modification, are permitted provided that the following conditions
7     are met:
8
9     * Redistributions of source code must retain the above copyright
10     notice, this list of conditions and the following disclaimer.
11     * Redistributions in binary form must reproduce the above copyright
12     notice, this list of conditions and the following disclaimer in
13     the documentation and/or other materials provided with the
14     distribution.
15     * Neither the name of Mellanox Corporation nor the names of its
16     contributors may be used to endorse or promote products derived
17     from this software without specific prior written permission.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31
32 Basic RTE Flow Filtering Sample Application
33 ===========================================
34
35 The Basic RTE flow filtering sample application is a simple example of a
36 creating a RTE flow rule.
37
38 It is intended as a demonstration of the basic components RTE flow rules.
39
40
41 Compiling the Application
42 -------------------------
43
44 To compile the application export the path to the DPDK source tree and go to
45 the example directory:
46
47 .. code-block:: console
48
49     export RTE_SDK=/path/to/rte_sdk
50
51     cd ${RTE_SDK}/examples/flow_filtering
52
53 Set the target, for example:
54
55 .. code-block:: console
56
57     export RTE_TARGET=x86_64-native-linuxapp-gcc
58
59 See the *DPDK Getting Started* Guide for possible ``RTE_TARGET`` values.
60
61 Build the application as follows:
62
63 .. code-block:: console
64
65     make
66
67
68 Running the Application
69 -----------------------
70
71 To run the example in a ``linuxapp`` environment:
72
73 .. code-block:: console
74
75     ./build/flow -l 1 -n 1
76
77 Refer to *DPDK Getting Started Guide* for general information on running
78 applications and the Environment Abstraction Layer (EAL) options.
79
80
81 Explanation
82 -----------
83
84 The example is build from 2 main files,
85 ``main.c`` which holds the example logic and ``flow_blocks.c`` that holds the
86 implementation for building the flow rule.
87
88 The following sections provide an explanation of the main components of the
89 code.
90
91 All DPDK library functions used in the sample code are prefixed with ``rte_``
92 and are explained in detail in the *DPDK API Documentation*.
93
94
95 The Main Function
96 ~~~~~~~~~~~~~~~~~
97
98 The ``main()`` function located in ``main.c`` file performs the initialization
99 and runs the main loop function.
100
101 The first task is to initialize the Environment Abstraction Layer (EAL).  The
102 ``argc`` and ``argv`` arguments are provided to the ``rte_eal_init()``
103 function. The value returned is the number of parsed arguments:
104
105 .. code-block:: c
106
107     int ret = rte_eal_init(argc, argv);
108     if (ret < 0)
109         rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
110
111
112 The ``main()`` also allocates a mempool to hold the mbufs (Message Buffers)
113 used by the application:
114
115 .. code-block:: c
116
117    mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", 4096, 128, 0,
118                                             RTE_MBUF_DEFAULT_BUF_SIZE,
119                                             rte_socket_id());
120
121 Mbufs are the packet buffer structure used by DPDK. They are explained in
122 detail in the "Mbuf Library" section of the *DPDK Programmer's Guide*.
123
124 The ``main()`` function also initializes all the ports using the user defined
125 ``init_port()`` function which is explained in the next section:
126
127 .. code-block:: c
128
129    init_port();
130
131 Once the initialization is complete, we set the flow rule using the
132 following code:
133
134 .. code-block:: c
135
136    /* create flow for send packet with */
137    flow = generate_ipv4_flow(port_id, selected_queue,
138                                 SRC_IP, EMPTY_MASK,
139                                 DEST_IP, FULL_MASK, &error);
140    if (!flow) {
141           printf("Flow can't be created %d message: %s\n",
142                        error.type,
143                        error.message ? error.message : "(no stated reason)");
144           rte_exit(EXIT_FAILURE, "error in creating flow");
145    }
146
147 In the last part the application is ready to launch the
148 ``main_loop()`` function. Which is explained below.
149
150
151 .. code-block:: c
152
153    main_loop();
154
155 The Port Initialization  Function
156 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
157
158 The main functional part of the port initialization used in the flow filtering
159 application is shown below:
160
161 .. code-block:: c
162
163    init_port(void)
164    {
165            int ret;
166            uint16_t i;
167            struct rte_eth_conf port_conf = {
168                    .rxmode = {
169                            .split_hdr_size = 0,
170                            .ignore_offload_bitfield = 1,
171                            .offloads = DEV_RX_OFFLOAD_CRC_STRIP,
172                            },
173                    .txmode = {
174                            .offloads =
175                                    DEV_TX_OFFLOAD_VLAN_INSERT |
176                                    DEV_TX_OFFLOAD_IPV4_CKSUM  |
177                                    DEV_TX_OFFLOAD_UDP_CKSUM   |
178                                    DEV_TX_OFFLOAD_TCP_CKSUM   |
179                                    DEV_TX_OFFLOAD_SCTP_CKSUM  |
180                                    DEV_TX_OFFLOAD_TCP_TSO,
181                    },
182            };
183            struct rte_eth_txconf txq_conf;
184            struct rte_eth_rxconf rxq_conf;
185            struct rte_eth_dev_info dev_info;
186
187            printf(":: initializing port: %d\n", port_id);
188            ret = rte_eth_dev_configure(port_id,
189                    nr_queues, nr_queues, &port_conf);
190            if (ret < 0) {
191                    rte_exit(EXIT_FAILURE,
192                            ":: cannot configure device: err=%d, port=%u\n",
193                            ret, port_id);
194            }
195
196            rte_eth_dev_info_get(port_id, &dev_info);
197            rxq_conf = dev_info.default_rxconf;
198            rxq_conf.offloads = port_conf.rxmode.offloads;
199            /* only set Rx queues: something we care only so far */
200            for (i = 0; i < nr_queues; i++) {
201                    ret = rte_eth_rx_queue_setup(port_id, i, 512,
202                            rte_eth_dev_socket_id(port_id),
203                            &rxq_conf,
204                            mbuf_pool);
205                    if (ret < 0) {
206                             rte_exit(EXIT_FAILURE,
207                                     ":: Rx queue setup failed: err=%d, port=%u\n",
208                                     ret, port_id);
209                    }
210            }
211
212            txq_conf = dev_info.default_txconf;
213            txq_conf.offloads = port_conf.txmode.offloads;
214
215            for (i = 0; i < nr_queues; i++) {
216                    ret = rte_eth_tx_queue_setup(port_id, i, 512,
217                            rte_eth_dev_socket_id(port_id),
218                            &txq_conf);
219                    if (ret < 0) {
220                            rte_exit(EXIT_FAILURE,
221                                    ":: Tx queue setup failed: err=%d, port=%u\n",
222                                    ret, port_id);
223                    }
224           }
225
226            rte_eth_promiscuous_enable(port_id);
227            ret = rte_eth_dev_start(port_id);
228            if (ret < 0) {
229                    rte_exit(EXIT_FAILURE,
230                            "rte_eth_dev_start:err=%d, port=%u\n",
231                            ret, port_id);
232            }
233
234            assert_link_status();
235
236            printf(":: initializing port: %d done\n", port_id);
237    }
238
239 The Ethernet port is configured with default settings using the
240 ``rte_eth_dev_configure()`` function and the ``port_conf_default`` struct:
241
242 .. code-block:: c
243
244    struct rte_eth_conf port_conf = {
245            .rxmode = {
246                    .split_hdr_size = 0,
247                    .ignore_offload_bitfield = 1,
248                    .offloads = DEV_RX_OFFLOAD_CRC_STRIP,
249                    },
250            .txmode = {
251                    .offloads =
252                            DEV_TX_OFFLOAD_VLAN_INSERT |
253                            DEV_TX_OFFLOAD_IPV4_CKSUM  |
254                            DEV_TX_OFFLOAD_UDP_CKSUM   |
255                            DEV_TX_OFFLOAD_TCP_CKSUM   |
256                            DEV_TX_OFFLOAD_SCTP_CKSUM  |
257                            DEV_TX_OFFLOAD_TCP_TSO,
258                    },
259            };
260
261    ret = rte_eth_dev_configure(port_id, nr_queues, nr_queues, &port_conf);
262    if (ret < 0) {
263         rte_exit(EXIT_FAILURE,
264                  ":: cannot configure device: err=%d, port=%u\n",
265                  ret, port_id);
266    }
267    rte_eth_dev_info_get(port_id, &dev_info);
268    rxq_conf = dev_info.default_rxconf;
269    rxq_conf.offloads = port_conf.rxmode.offloads;
270
271 For this example we are configuring number of rx and tx queues that are connected
272 to a single port.
273
274 .. code-block:: c
275
276    for (i = 0; i < nr_queues; i++) {
277           ret = rte_eth_rx_queue_setup(port_id, i, 512,
278                                        rte_eth_dev_socket_id(port_id),
279                                        &rxq_conf,
280                                        mbuf_pool);
281           if (ret < 0) {
282                   rte_exit(EXIT_FAILURE,
283                           ":: Rx queue setup failed: err=%d, port=%u\n",
284                           ret, port_id);
285           }
286    }
287
288    for (i = 0; i < nr_queues; i++) {
289           ret = rte_eth_tx_queue_setup(port_id, i, 512,
290                                        rte_eth_dev_socket_id(port_id),
291                                        &txq_conf);
292           if (ret < 0) {
293                   rte_exit(EXIT_FAILURE,
294                            ":: Tx queue setup failed: err=%d, port=%u\n",
295                            ret, port_id);
296           }
297    }
298
299 In the next step we create and apply the flow rule. which is to send packets
300 with destination ip equals to 192.168.1.1 to queue number 1. The detail
301 explanation of the ``generate_ipv4_flow()`` appears later in this document:
302
303 .. code-block:: c
304
305    flow = generate_ipv4_flow(port_id, selected_queue,
306                              SRC_IP, EMPTY_MASK,
307                              DEST_IP, FULL_MASK, &error);
308
309 We are setting the RX port to promiscuous mode:
310
311 .. code-block:: c
312
313    rte_eth_promiscuous_enable(port_id);
314
315 The last step is to start the port.
316
317 .. code-block:: c
318
319    ret = rte_eth_dev_start(port_id);
320    if (ret < 0)  {
321         rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err%d, port=%u\n",
322                         ret, port_id);
323    }
324
325
326 The main_loop function
327 ~~~~~~~~~~~~~~~~~~~~~~
328
329 As we saw above the ``main()`` function calls an application function to handle
330 the main loop. For the flow filtering application the main_loop function
331 looks like the following:
332
333 .. code-block:: c
334
335    static void
336    main_loop(void)
337    {
338            struct rte_mbuf *mbufs[32];
339            struct ether_hdr *eth_hdr;
340            uint16_t nb_rx;
341            uint16_t i;
342            uint16_t j;
343
344            while (!force_quit) {
345                    for (i = 0; i < nr_queues; i++) {
346                            nb_rx = rte_eth_rx_burst(port_id,
347                                                    i, mbufs, 32);
348                            if (nb_rx) {
349                                    for (j = 0; j < nb_rx; j++) {
350                                            struct rte_mbuf *m = mbufs[j];
351
352                                            eth_hdr = rte_pktmbuf_mtod(m,
353                                                         struct ether_hdr *);
354                                            print_ether_addr("src=",
355                                                         &eth_hdr->s_addr);
356                                            print_ether_addr(" - dst=",
357                                                         &eth_hdr->d_addr);
358                                            printf(" - queue=0x%x",
359                                                            (unsigned int)i);
360                                            printf("\n");
361                                            rte_pktmbuf_free(m);
362                                    }
363                            }
364                    }
365            }
366            /* closing and releasing resources */
367            rte_flow_flush(port_id, &error);
368            rte_eth_dev_stop(port_id);
369            rte_eth_dev_close(port_id);
370    }
371
372 The main work of the application is reading the packets from all
373 queues and printing for each packet the destination queue:
374
375 .. code-block:: c
376
377     while (!force_quit) {
378         for (i = 0; i < nr_queues; i++) {
379                    nb_rx = rte_eth_rx_burst(port_id, i, mbufs, 32);
380                 if (nb_rx) {
381                         for (j = 0; j < nb_rx; j++) {
382                              struct rte_mbuf *m = mbufs[j];
383                              eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
384                              print_ether_addr("src=", &eth_hdr->s_addr);
385                              print_ether_addr(" - dst=", &eth_hdr->d_addr);
386                              printf(" - queue=0x%x", (unsigned int)i);
387                              printf("\n");
388                              rte_pktmbuf_free(m);
389                         }
390                 }
391            }
392     }
393
394
395 The forwarding loop can be interrupted and the application closed using
396 ``Ctrl-C``. Which results in closing the port and the device using
397 ``rte_eth_dev_stop`` and ``rte_eth_dev_close``
398
399 The generate_ipv4_flow function
400 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
401
402 The generate_ipv4_rule function is responsible for creating the flow rule.
403 This function is located in the ``flow_blocks.c`` file.
404
405 .. code-block:: c
406
407    static struct rte_flow *
408    generate_ipv4_flow(uint8_t port_id, uint16_t rx_q,
409                    uint32_t src_ip, uint32_t src_mask,
410                    uint32_t dest_ip, uint32_t dest_mask,
411                    struct rte_flow_error *error)
412    {
413            struct rte_flow_attr attr;
414            struct rte_flow_item pattern[MAX_PATTERN_NUM];
415            struct rte_flow_action action[MAX_PATTERN_NUM];
416            struct rte_flow *flow = NULL;
417            struct rte_flow_action_queue queue = { .index = rx_q };
418            struct rte_flow_item_eth eth_spec;
419            struct rte_flow_item_eth eth_mask;
420            struct rte_flow_item_vlan vlan_spec;
421            struct rte_flow_item_vlan vlan_mask;
422            struct rte_flow_item_ipv4 ip_spec;
423            struct rte_flow_item_ipv4 ip_mask;
424
425            memset(pattern, 0, sizeof(pattern));
426            memset(action, 0, sizeof(action));
427
428            /*
429             * set the rule attribute.
430             * in this case only ingress packets will be checked.
431             */
432            memset(&attr, 0, sizeof(struct rte_flow_attr));
433            attr.ingress = 1;
434
435            /*
436             * create the action sequence.
437             * one action only,  move packet to queue
438             */
439
440            action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
441            action[0].conf = &queue;
442            action[1].type = RTE_FLOW_ACTION_TYPE_END;
443
444            /*
445             * set the first level of the pattern (eth).
446             * since in this example we just want to get the
447             * ipv4 we set this level to allow all.
448             */
449            memset(&eth_spec, 0, sizeof(struct rte_flow_item_eth));
450            memset(&eth_mask, 0, sizeof(struct rte_flow_item_eth));
451            eth_spec.type = 0;
452            eth_mask.type = 0;
453            pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
454            pattern[0].spec = &eth_spec;
455            pattern[0].mask = &eth_mask;
456
457            /*
458             * setting the second level of the pattern (vlan).
459             * since in this example we just want to get the
460             * ipv4 we also set this level to allow all.
461             */
462            memset(&vlan_spec, 0, sizeof(struct rte_flow_item_vlan));
463            memset(&vlan_mask, 0, sizeof(struct rte_flow_item_vlan));
464            pattern[1].type = RTE_FLOW_ITEM_TYPE_VLAN;
465            pattern[1].spec = &vlan_spec;
466            pattern[1].mask = &vlan_mask;
467
468            /*
469             * setting the third level of the pattern (ip).
470             * in this example this is the level we care about
471             * so we set it according to the parameters.
472             */
473            memset(&ip_spec, 0, sizeof(struct rte_flow_item_ipv4));
474            memset(&ip_mask, 0, sizeof(struct rte_flow_item_ipv4));
475            ip_spec.hdr.dst_addr = htonl(dest_ip);
476            ip_mask.hdr.dst_addr = dest_mask;
477            ip_spec.hdr.src_addr = htonl(src_ip);
478            ip_mask.hdr.src_addr = src_mask;
479            pattern[2].type = RTE_FLOW_ITEM_TYPE_IPV4;
480            pattern[2].spec = &ip_spec;
481            pattern[2].mask = &ip_mask;
482
483            /* the final level must be always type end */
484            pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
485
486            int res = rte_flow_validate(port_id, &attr, pattern, action, error);
487            if(!res)
488                flow = rte_flow_create(port_id, &attr, pattern, action, error);
489
490            return flow;
491    }
492
493 The first part of the function is declaring the structures that will be used.
494
495 .. code-block:: c
496
497    struct rte_flow_attr attr;
498    struct rte_flow_item pattern[MAX_PATTERN_NUM];
499    struct rte_flow_action action[MAX_PATTERN_NUM];
500    struct rte_flow *flow;
501    struct rte_flow_error error;
502    struct rte_flow_action_queue queue = { .index = rx_q };
503    struct rte_flow_item_eth eth_spec;
504    struct rte_flow_item_eth eth_mask;
505    struct rte_flow_item_vlan vlan_spec;
506    struct rte_flow_item_vlan vlan_mask;
507    struct rte_flow_item_ipv4 ip_spec;
508    struct rte_flow_item_ipv4 ip_mask;
509
510 The following part create the flow attributes, in our case ingress.
511
512 .. code-block:: c
513
514    memset(&attr, 0, sizeof(struct rte_flow_attr));
515    attr.ingress = 1;
516
517 The third part defines the action to be taken when a packet matches
518 the rule. In this case send the packet to queue.
519
520 .. code-block:: c
521
522    action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
523    action[0].conf = &queue;
524    action[1].type = RTE_FLOW_ACTION_TYPE_END;
525
526 The forth part is responsible for creating the pattern and is build from
527 number of step. In each step we build one level of the pattern starting with
528 the lowest one.
529
530 Setting the first level of the pattern ETH:
531
532 .. code-block:: c
533
534    memset(&eth_spec, 0, sizeof(struct rte_flow_item_eth));
535    memset(&eth_mask, 0, sizeof(struct rte_flow_item_eth));
536    eth_spec.type = 0;
537    eth_mask.type = 0;
538    pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
539    pattern[0].spec = &eth_spec;
540    pattern[0].mask = &eth_mask;
541
542 Setting the second level of the pattern VLAN:
543
544 .. code-block:: c
545
546    memset(&vlan_spec, 0, sizeof(struct rte_flow_item_vlan));
547    memset(&vlan_mask, 0, sizeof(struct rte_flow_item_vlan));
548    pattern[1].type = RTE_FLOW_ITEM_TYPE_VLAN;
549    pattern[1].spec = &vlan_spec;
550    pattern[1].mask = &vlan_mask;
551
552 Setting the third level ip:
553
554 .. code-block:: c
555
556    memset(&ip_spec, 0, sizeof(struct rte_flow_item_ipv4));
557    memset(&ip_mask, 0, sizeof(struct rte_flow_item_ipv4));
558    ip_spec.hdr.dst_addr = htonl(dest_ip);
559    ip_mask.hdr.dst_addr = dest_mask;
560    ip_spec.hdr.src_addr = htonl(src_ip);
561    ip_mask.hdr.src_addr = src_mask;
562    pattern[2].type = RTE_FLOW_ITEM_TYPE_IPV4;
563    pattern[2].spec = &ip_spec;
564    pattern[2].mask = &ip_mask;
565
566 Closing the pattern part.
567
568 .. code-block:: c
569
570    pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
571
572 The last part of the function is to validate the rule and create it.
573
574 .. code-block:: c
575
576    int res = rte_flow_validate(port_id, &attr, pattern, action, &error);
577    if (!res)
578         flow = rte_flow_create(port_id, &attr, pattern, action, &error);
579