6c500c0a07f4e39f79502b261d7c095cb8eaaaab
[dpdk.git] / doc / guides / sample_app_ug / ip_reassembly.rst
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 IP Reassembly Sample Application
32 ================================
33
34 The L3 Forwarding application is a simple example of packet processing using the DPDK.
35 The application performs L3 forwarding with reassembly for fragmented IPv4 and IPv6 packets.
36
37 Overview
38 --------
39
40 The application demonstrates the use of the DPDK libraries to implement packet forwarding
41 with reassembly for IPv4 and IPv6 fragmented packets.
42 The initialization and run- time paths are very similar to those of the L2 forwarding application
43 (see Chapter 9 "L2 Forwarding Sample Application" for more information).
44 The main difference from the L2 Forwarding sample application is that
45 it reassembles fragmented IPv4 and IPv6 packets before forwarding.
46 The maximum allowed size of reassembled packet is 9.5 KB.
47
48 There are two key differences from the L2 Forwarding sample application:
49
50 *   The first difference is that the forwarding decision is taken based on information read from the input packet's IP header.
51
52 *   The second difference is that the application differentiates between IP and non-IP traffic by means of offload flags.
53
54 The Longest Prefix Match (LPM for IPv4, LPM6 for IPv6) table is used to store/lookup an outgoing port number, associated with that IPv4 address. Any unmatched packets are forwarded to the originating port.Compiling the Application
55 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
56
57 To compile the application:
58
59 #.  Go to the sample application directory:
60
61    .. code-block:: console
62
63         export RTE_SDK=/path/to/rte_sdk
64         cd ${RTE_SDK}/examples/ip_reassembly
65
66 #.  Set the target (a default target is used if not specified). For example:
67
68    .. code-block:: console
69
70         export RTE_TARGET=x86_64-native-linuxapp-gcc
71
72 See the *DPDK Getting Started Guide* for possible RTE_TARGET values.
73
74 #.  Build the application:
75
76    .. code-block:: console
77
78         make
79
80 Running the Application
81 -----------------------
82
83 The application has a number of command line options:
84
85 .. code-block:: console
86
87     ./build/ip_reassembly [EAL options] -- -p PORTMASK [-q NQ] [--maxflows=FLOWS>] [--flowttl=TTL[(s|ms)]]
88
89 where:
90
91 *   -p PORTMASK: Hexadecimal bitmask of ports to configure
92
93 *   -q NQ: Number of RX queues per lcore
94
95 *   --maxflows=FLOWS: determines maximum number of active fragmented flows (1-65535). Default value: 4096.
96
97 *   --flowttl=TTL[(s|ms)]: determines maximum Time To Live for fragmented packet.
98     If all fragments of the packet wouldn't appear within given time-out,
99     then they are consirdered as invalid and will be dropped.
100     Valid range is 1ms - 3600s. Default value: 1s.
101
102 To run the example in linuxapp environment with 2 lcores (2,4) over 2 ports(0,2) with 1 RX queue per lcore:
103
104 .. code-block:: console
105
106     ./build/ip_reassembly -c 0x14 -n 3 -- -p 5
107     EAL: coremask set to 14
108     EAL: Detected lcore 0 on socket 0
109     EAL: Detected lcore 1 on socket 1
110     EAL: Detected lcore 2 on socket 0
111     EAL: Detected lcore 3 on socket 1
112     EAL: Detected lcore 4 on socket 0
113     ...
114
115     Initializing port 0 on lcore 2... Address:00:1B:21:76:FA:2C, rxq=0 txq=2,0 txq=4,1
116     done: Link Up - speed 10000 Mbps - full-duplex
117     Skipping disabled port 1
118     Initializing port 2 on lcore 4... Address:00:1B:21:5C:FF:54, rxq=0 txq=2,0 txq=4,1
119     done: Link Up - speed 10000 Mbps - full-duplex
120     Skipping disabled port 3IP_FRAG: Socket 0: adding route 100.10.0.0/16 (port 0)
121     IP_RSMBL: Socket 0: adding route 100.20.0.0/16 (port 1)
122     ...
123
124     IP_RSMBL: Socket 0: adding route 0101:0101:0101:0101:0101:0101:0101:0101/48 (port 0)
125     IP_RSMBL: Socket 0: adding route 0201:0101:0101:0101:0101:0101:0101:0101/48 (port 1)
126     ...
127
128     IP_RSMBL: entering main loop on lcore 4
129     IP_RSMBL: -- lcoreid=4 portid=2
130     IP_RSMBL: entering main loop on lcore 2
131     IP_RSMBL: -- lcoreid=2 portid=0
132
133 To run the example in linuxapp environment with 1 lcore (4) over 2 ports(0,2) with 2 RX queues per lcore:
134
135 .. code-block:: console
136
137     ./build/ip_reassembly -c 0x10 -n 3 -- -p 5 -q 2
138
139 To test the application, flows should be set up in the flow generator that match the values in the
140 l3fwd_ipv4_route_array and/or l3fwd_ipv6_route_array table.
141
142 Please note that in order to test this application,
143 the traffic generator should be generating valid fragmented IP packets.
144 For IPv6, the only supported case is when no other extension headers other than
145 fragment extension header are present in the packet.
146
147 The default l3fwd_ipv4_route_array table is:
148
149 .. code-block:: c
150
151     struct l3fwd_ipv4_route l3fwd_ipv4_route_array[] = {
152         {IPv4(100, 10, 0, 0), 16, 0},
153         {IPv4(100, 20, 0, 0), 16, 1},
154         {IPv4(100, 30, 0, 0), 16, 2},
155         {IPv4(100, 40, 0, 0), 16, 3},
156         {IPv4(100, 50, 0, 0), 16, 4},
157         {IPv4(100, 60, 0, 0), 16, 5},
158         {IPv4(100, 70, 0, 0), 16, 6},
159         {IPv4(100, 80, 0, 0), 16, 7},
160     };
161
162 The default l3fwd_ipv6_route_array table is:
163
164 .. code-block:: c
165
166     struct l3fwd_ipv6_route l3fwd_ipv6_route_array[] = {
167         {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 0},
168         {{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 1},
169         {{3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 2},
170         {{4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 3},
171         {{5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 4},
172         {{6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 5},
173         {{7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 6},
174         {{8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 7},
175     };
176
177 For example, for the fragmented input IPv4 packet with destination address: 100.10.1.1,
178 a reassembled IPv4 packet be sent out from port #0 to the destination address 100.10.1.1
179 once all the fragments are collected.
180
181 Explanation
182 -----------
183
184 The following sections provide some explanation of the sample application code.
185 As mentioned in the overview section, the initialization and run-time paths are very similar to those of the L2 forwarding application
186 (see Chapter 9 "L2 Forwarding Sample Application" for more information).
187 The following sections describe aspects that are specific to the IP reassemble sample application.
188
189 IPv4 Fragment Table Initialization
190 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
191
192 This application uses the rte_ip_frag library. Please refer to Programmer's Guide for more detailed explanation of how to use this library.
193 Fragment table maintains information about already received fragments of the packet.
194 Each IP packet is uniquely identified by triple <Source IP address>, <Destination IP address>, <ID>.
195 To avoid lock contention, each RX queue has its own Fragment Table,
196 e.g. the application can't handle the situation when different fragments of the same packet arrive through different RX queues.
197 Each table entry can hold information about packet consisting of up to RTE_LIBRTE_IP_FRAG_MAX_FRAGS fragments.
198
199 .. code-block:: c
200
201     frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / MS_PER_S * max_flow_ttl;
202
203     if ((qconf->frag_tbl[queue] = rte_ip_frag_tbl_create(max_flow_num, IPV4_FRAG_TBL_BUCKET_ENTRIES, max_flow_num, frag_cycles, socket)) == NULL)
204     {
205         RTE_LOG(ERR, IP_RSMBL, "ip_frag_tbl_create(%u) on " "lcore: %u for queue: %u failed\n",  max_flow_num, lcore, queue);
206         return -1;
207     }
208
209 Mempools Initialization
210 ~~~~~~~~~~~~~~~~~~~~~~~
211
212 The reassembly application demands a lot of mbuf's to be allocated.
213 At any given time up to (2 \* max_flow_num \* RTE_LIBRTE_IP_FRAG_MAX_FRAGS \* <maximum number of mbufs per packet>)
214 can be stored inside Fragment Table waiting for remaining fragments.
215 To keep mempool size under reasonable limits and to avoid situation when one RX queue can starve other queues,
216 each RX queue uses its own mempool.
217
218 .. code-block:: c
219
220     nb_mbuf = RTE_MAX(max_flow_num, 2UL * MAX_PKT_BURST) * RTE_LIBRTE_IP_FRAG_MAX_FRAGS;
221     nb_mbuf *= (port_conf.rxmode.max_rx_pkt_len + BUF_SIZE - 1) / BUF_SIZE;
222     nb_mbuf *= 2; /* ipv4 and ipv6 */
223     nb_mbuf += RTE_TEST_RX_DESC_DEFAULT + RTE_TEST_TX_DESC_DEFAULT;
224     nb_mbuf = RTE_MAX(nb_mbuf, (uint32_t)NB_MBUF);
225
226     rte_snprintf(buf, sizeof(buf), "mbuf_pool_%u_%u", lcore, queue);
227
228     if ((rxq->pool = rte_mempool_create(buf, nb_mbuf, MBUF_SIZE, 0, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL,
229         rte_pktmbuf_init, NULL, socket, MEMPOOL_F_SP_PUT | MEMPOOL_F_SC_GET)) == NULL) {
230
231             RTE_LOG(ERR, IP_RSMBL, "mempool_create(%s) failed", buf);
232             return -1;
233     }
234
235 Packet Reassembly and Forwarding
236 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
237
238 For each input packet, the packet forwarding operation is done by the l3fwd_simple_forward() function.
239 If the packet is an IPv4 or IPv6 fragment, then it calls rte_ipv4_reassemble_packet() for IPv4 packets,
240 or rte_ipv6_reassemble_packet() for IPv6 packets.
241 These functions either return a pointer to valid mbuf that contains reassembled packet,
242 or NULL (if the packet can't be reassembled for some reason).
243 Then l3fwd_simple_forward() continues with the code for the packet forwarding decision
244 (that is, the identification of the output interface for the packet) and
245 actual transmit of the packet.
246
247 The rte_ipv4_reassemble_packet() or rte_ipv6_reassemble_packet() are responsible for:
248
249 #.  Searching the Fragment Table for entry with packet's <IP Source Address, IP Destination Address, Packet ID>
250
251 #.  If the entry is found, then check if that entry already timed-out.
252     If yes, then free all previously received fragments,
253     and remove information about them from the entry.
254
255 #.  If no entry with such key is found, then try to create a new one by one of two ways:
256
257     #.  Use as empty entry
258
259     #.  Delete a timed-out entry, free mbufs associated with it mbufs and store a new entry with specified key in it.
260
261 #.  Update the entry with new fragment information and check
262     if a packet can be reassembled (the packet's entry contains all fragments).
263
264     #.  If yes, then, reassemble the packet, mark table's entry as empty and return the reassembled mbuf to the caller.
265
266     #.  If no, then just return a NULL to the caller.
267
268 If at any stage of packet processing a reassembly function encounters an error
269 (can't insert new entry into the Fragment table, or invalid/timed-out fragment),
270 then it will free all associated with the packet fragments,
271 mark the table entry as invalid and return NULL to the caller.
272
273 Debug logging and Statistics Collection
274 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
275
276 The RTE_LIBRTE_IP_FRAG_TBL_STAT controls statistics collection for the IP Fragment Table.
277 This macro is disabled by default.
278 To make ip_reassembly print the statistics to the standard output,
279 the user must send either an USR1, INT or TERM signal to the process.
280 For all of these signals, the ip_reassembly process prints Fragment table statistics for each RX queue,
281 plus the INT and TERM will cause process termination as usual.