New upstream version 18.02
[deb_dpdk.git] / doc / guides / sample_app_ug / vmdq_dcb_forwarding.rst
1 ..  SPDX-License-Identifier: BSD-3-Clause
2     Copyright(c) 2010-2014 Intel Corporation.
3
4 VMDQ and DCB Forwarding Sample Application
5 ==========================================
6
7 The VMDQ and DCB Forwarding sample application is a simple example of packet processing using the DPDK.
8 The application performs L2 forwarding using VMDQ and DCB to divide the incoming traffic into queues.
9 The traffic splitting is performed in hardware by the VMDQ and DCB features of the Intel® 82599 and X710/XL710 Ethernet Controllers.
10
11 Overview
12 --------
13
14 This sample application can be used as a starting point for developing a new application that is based on the DPDK and
15 uses VMDQ and DCB for traffic partitioning.
16
17 The VMDQ and DCB filters work on MAC and VLAN traffic to divide the traffic into input queues on the basis of the Destination MAC
18 address, VLAN ID and VLAN user priority fields.
19 VMDQ filters split the traffic into 16 or 32 groups based on the Destination MAC and VLAN ID.
20 Then, DCB places each packet into one of queues within that group, based upon the VLAN user priority field.
21
22 All traffic is read from a single incoming port (port 0) and output on port 1, without any processing being performed.
23 With Intel® 82599 NIC, for example, the traffic is split into 128 queues on input, where each thread of the application reads from
24 multiple queues. When run with 8 threads, that is, with the -c FF option, each thread receives and forwards packets from 16 queues.
25
26 As supplied, the sample application configures the VMDQ feature to have 32 pools with 4 queues each as indicated in :numref:`figure_vmdq_dcb_example`.
27 The Intel® 82599 10 Gigabit Ethernet Controller NIC also supports the splitting of traffic into 16 pools of 8 queues. While the
28 Intel® X710 or XL710 Ethernet Controller NICs support many configurations of VMDQ pools of 4 or 8 queues each. For simplicity, only 16
29 or 32 pools is supported in this sample. And queues numbers for each VMDQ pool can be changed by setting CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM
30 in config/common_* file.
31 The nb-pools, nb-tcs and enable-rss parameters can be passed on the command line, after the EAL parameters:
32
33 .. code-block:: console
34
35     ./build/vmdq_dcb [EAL options] -- -p PORTMASK --nb-pools NP --nb-tcs TC --enable-rss
36
37 where, NP can be 16 or 32, TC can be 4 or 8, rss is disabled by default.
38
39 .. _figure_vmdq_dcb_example:
40
41 .. figure:: img/vmdq_dcb_example.*
42
43    Packet Flow Through the VMDQ and DCB Sample Application
44
45
46 In Linux* user space, the application can display statistics with the number of packets received on each queue.
47 To have the application display the statistics, send a SIGHUP signal to the running application process.
48
49 The VMDQ and DCB Forwarding sample application is in many ways simpler than the L2 Forwarding application
50 (see :doc:`l2_forward_real_virtual`)
51 as it performs unidirectional L2 forwarding of packets from one port to a second port.
52 No command-line options are taken by this application apart from the standard EAL command-line options.
53
54 .. note::
55
56     Since VMD queues are being used for VMM, this application works correctly
57     when VTd is disabled in the BIOS or Linux* kernel (intel_iommu=off).
58
59 Compiling the Application
60 -------------------------
61
62
63
64 To compile the sample application see :doc:`compiling`.
65
66 The application is located in the ``vmdq_dcb`` sub-directory.
67
68 Running the Application
69 -----------------------
70
71 To run the example in a linuxapp environment:
72
73 .. code-block:: console
74
75     user@target:~$ ./build/vmdq_dcb -l 0-3 -n 4 -- -p 0x3 --nb-pools 32 --nb-tcs 4
76
77 Refer to the *DPDK Getting Started Guide* for general information on running applications and
78 the Environment Abstraction Layer (EAL) options.
79
80 Explanation
81 -----------
82
83 The following sections provide some explanation of the code.
84
85 Initialization
86 ~~~~~~~~~~~~~~
87
88 The EAL, driver and PCI configuration is performed largely as in the L2 Forwarding sample application,
89 as is the creation of the mbuf pool.
90 See :doc:`l2_forward_real_virtual`.
91 Where this example application differs is in the configuration of the NIC port for RX.
92
93 The VMDQ and DCB hardware feature is configured at port initialization time by setting the appropriate values in the
94 rte_eth_conf structure passed to the rte_eth_dev_configure() API.
95 Initially in the application,
96 a default structure is provided for VMDQ and DCB configuration to be filled in later by the application.
97
98 .. code-block:: c
99
100     /* empty vmdq+dcb configuration structure. Filled in programmatically */
101     static const struct rte_eth_conf vmdq_dcb_conf_default = {
102         .rxmode = {
103             .mq_mode        = ETH_MQ_RX_VMDQ_DCB,
104             .split_hdr_size = 0,
105             .header_split   = 0, /**< Header Split disabled */
106             .hw_ip_checksum = 0, /**< IP checksum offload disabled */
107             .hw_vlan_filter = 0, /**< VLAN filtering disabled */
108             .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
109         },
110         .txmode = {
111             .mq_mode = ETH_MQ_TX_VMDQ_DCB,
112         },
113         /*
114          * should be overridden separately in code with
115          * appropriate values
116          */
117         .rx_adv_conf = {
118             .vmdq_dcb_conf = {
119                 .nb_queue_pools = ETH_32_POOLS,
120                 .enable_default_pool = 0,
121                 .default_pool = 0,
122                 .nb_pool_maps = 0,
123                 .pool_map = {{0, 0},},
124                 .dcb_tc = {0},
125             },
126             .dcb_rx_conf = {
127                 .nb_tcs = ETH_4_TCS,
128                 /** Traffic class each UP mapped to. */
129                 .dcb_tc = {0},
130             },
131             .vmdq_rx_conf = {
132                 .nb_queue_pools = ETH_32_POOLS,
133                 .enable_default_pool = 0,
134                 .default_pool = 0,
135                 .nb_pool_maps = 0,
136                 .pool_map = {{0, 0},},
137             },
138         },
139         .tx_adv_conf = {
140             .vmdq_dcb_tx_conf = {
141                 .nb_queue_pools = ETH_32_POOLS,
142                 .dcb_tc = {0},
143             },
144         },
145     };
146
147 The get_eth_conf() function fills in an rte_eth_conf structure with the appropriate values,
148 based on the global vlan_tags array,
149 and dividing up the possible user priority values equally among the individual queues
150 (also referred to as traffic classes) within each pool. With Intel® 82599 NIC,
151 if the number of pools is 32, then the user priority fields are allocated 2 to a queue.
152 If 16 pools are used, then each of the 8 user priority fields is allocated to its own queue within the pool.
153 With Intel® X710/XL710 NICs, if number of tcs is 4, and number of queues in pool is 8,
154 then the user priority fields are allocated 2 to one tc, and a tc has 2 queues mapping to it, then
155 RSS will determine the destination queue in 2.
156 For the VLAN IDs, each one can be allocated to possibly multiple pools of queues,
157 so the pools parameter in the rte_eth_vmdq_dcb_conf structure is specified as a bitmask value.
158 For destination MAC, each VMDQ pool will be assigned with a MAC address. In this sample, each VMDQ pool
159 is assigned to the MAC like 52:54:00:12:<port_id>:<pool_id>, that is,
160 the MAC of VMDQ pool 2 on port 1 is 52:54:00:12:01:02.
161
162 .. code-block:: c
163
164     const uint16_t vlan_tags[] = {
165         0, 1, 2, 3, 4, 5, 6, 7,
166         8, 9, 10, 11, 12, 13, 14, 15,
167         16, 17, 18, 19, 20, 21, 22, 23,
168         24, 25, 26, 27, 28, 29, 30, 31
169     };
170
171     /* pool mac addr template, pool mac addr is like: 52 54 00 12 port# pool# */
172     static struct ether_addr pool_addr_template = {
173         .addr_bytes = {0x52, 0x54, 0x00, 0x12, 0x00, 0x00}
174     };
175
176     /* Builds up the correct configuration for vmdq+dcb based on the vlan tags array
177      * given above, and the number of traffic classes available for use. */
178     static inline int
179     get_eth_conf(struct rte_eth_conf *eth_conf)
180     {
181         struct rte_eth_vmdq_dcb_conf conf;
182         struct rte_eth_vmdq_rx_conf  vmdq_conf;
183         struct rte_eth_dcb_rx_conf   dcb_conf;
184         struct rte_eth_vmdq_dcb_tx_conf tx_conf;
185         uint8_t i;
186
187         conf.nb_queue_pools = (enum rte_eth_nb_pools)num_pools;
188         vmdq_conf.nb_queue_pools = (enum rte_eth_nb_pools)num_pools;
189         tx_conf.nb_queue_pools = (enum rte_eth_nb_pools)num_pools;
190         conf.nb_pool_maps = num_pools;
191         vmdq_conf.nb_pool_maps = num_pools;
192         conf.enable_default_pool = 0;
193         vmdq_conf.enable_default_pool = 0;
194         conf.default_pool = 0; /* set explicit value, even if not used */
195         vmdq_conf.default_pool = 0;
196
197         for (i = 0; i < conf.nb_pool_maps; i++) {
198             conf.pool_map[i].vlan_id = vlan_tags[i];
199             vmdq_conf.pool_map[i].vlan_id = vlan_tags[i];
200             conf.pool_map[i].pools = 1UL << i ;
201             vmdq_conf.pool_map[i].pools = 1UL << i;
202         }
203         for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++){
204             conf.dcb_tc[i] = i % num_tcs;
205             dcb_conf.dcb_tc[i] = i % num_tcs;
206             tx_conf.dcb_tc[i] = i % num_tcs;
207         }
208         dcb_conf.nb_tcs = (enum rte_eth_nb_tcs)num_tcs;
209         (void)(rte_memcpy(eth_conf, &vmdq_dcb_conf_default, sizeof(*eth_conf)));
210         (void)(rte_memcpy(&eth_conf->rx_adv_conf.vmdq_dcb_conf, &conf,
211                   sizeof(conf)));
212         (void)(rte_memcpy(&eth_conf->rx_adv_conf.dcb_rx_conf, &dcb_conf,
213                   sizeof(dcb_conf)));
214         (void)(rte_memcpy(&eth_conf->rx_adv_conf.vmdq_rx_conf, &vmdq_conf,
215                   sizeof(vmdq_conf)));
216         (void)(rte_memcpy(&eth_conf->tx_adv_conf.vmdq_dcb_tx_conf, &tx_conf,
217                   sizeof(tx_conf)));
218         if (rss_enable) {
219             eth_conf->rxmode.mq_mode= ETH_MQ_RX_VMDQ_DCB_RSS;
220             eth_conf->rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IP |
221                                 ETH_RSS_UDP |
222                                 ETH_RSS_TCP |
223                                 ETH_RSS_SCTP;
224         }
225         return 0;
226     }
227
228     ......
229
230     /* Set mac for each pool.*/
231     for (q = 0; q < num_pools; q++) {
232         struct ether_addr mac;
233         mac = pool_addr_template;
234         mac.addr_bytes[4] = port;
235         mac.addr_bytes[5] = q;
236         printf("Port %u vmdq pool %u set mac %02x:%02x:%02x:%02x:%02x:%02x\n",
237             port, q,
238             mac.addr_bytes[0], mac.addr_bytes[1],
239             mac.addr_bytes[2], mac.addr_bytes[3],
240             mac.addr_bytes[4], mac.addr_bytes[5]);
241         retval = rte_eth_dev_mac_addr_add(port, &mac,
242                 q + vmdq_pool_base);
243         if (retval) {
244             printf("mac addr add failed at pool %d\n", q);
245             return retval;
246         }
247     }
248
249 Once the network port has been initialized using the correct VMDQ and DCB values,
250 the initialization of the port's RX and TX hardware rings is performed similarly to that
251 in the L2 Forwarding sample application.
252 See :doc:`l2_forward_real_virtual` for more information.
253
254 Statistics Display
255 ~~~~~~~~~~~~~~~~~~
256
257 When run in a linuxapp environment,
258 the VMDQ and DCB Forwarding sample application can display statistics showing the number of packets read from each RX queue.
259 This is provided by way of a signal handler for the SIGHUP signal,
260 which simply prints to standard output the packet counts in grid form.
261 Each row of the output is a single pool with the columns being the queue number within that pool.
262
263 To generate the statistics output, use the following command:
264
265 .. code-block:: console
266
267     user@host$ sudo killall -HUP vmdq_dcb_app
268
269 Please note that the statistics output will appear on the terminal where the vmdq_dcb_app is running,
270 rather than the terminal from which the HUP signal was sent.