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