1 .\" $Id: 8.t,v 1.1 2001/07/04 05:29:25 itojun Exp $
7 This section compares the following three approaches in terms of
8 their characteristics and actual behavior:
17 Comparison of assumption
19 Table 1 shows the assumptions made by each of the three approaches.
22 imposes too stringent requirement for the total length of packet headers.
24 is workable in most cases, although
25 this approach adds more restrictions than the specification claims.
27 assumes that the single packet header is smaller than MCLBYTES,
29 no restriction regarding the total length of packet headers.
30 With a standard mbuf chain,
33 can do, since there is no way to hold continuous region longer than MCLBYTES.
34 This characteristic can contribute to better specification conformance,
37 will impose fewer additional restrictions due to the
38 requirements of implementation.
40 Among the three approaches, only
42 avoids making unnecessary copies of intermediate header data and
43 avoids pointer reinitialization after calls to these functions.
44 These attributes result in smaller overhead during input packet processing.
48 we know of no other 4.4BSD-based IPv6/IPsec stack that addresses kernel
49 stack overflow issues,
50 although we are open to
51 new perspectives and new information.
53 Performance comparison based on simulated statistics
55 To compare the behavior and performance of
61 using the same set of traffic and
62 mbuf chains, we have gathered simulated statistics for
69 By running a kernel using the modified
73 gather statistics for these three functions against exactly the same traffic.
75 The comparison was made on a computer
76 (with Celeron 366MHz CPU, 192M bytes of memory)
77 running NetBSD 1.4.1 with the KAME IPv6/IPsec stack.
78 Network drivers allocate mbufs just as normal 4.4BSD does.
80 is called whenever it is needed to ensure continuity in packet data
81 during inbound packet processing.
82 The role of the computer is as an end node, not a router.
84 To describe the content of the following table,
85 we must look at the source code fragment.
89 shows the code fragment from our source code.
90 The code fragment will
91 (1) make the TCP header on the mbuf chain
95 continuous, and (2) point the region with pointer
97 We use a macro named IP6_EXTHDR_CHECK,
98 and the code before and after the macro expansion is shown in the figure.
103 \f[CR]/* ensure that *th from hdrlen is continuous */
104 /* before macro expansion... */
106 IP6_EXTHDR_CHECK(th, struct tcphdr *, m,
107 hdrlen, sizeof(*th));
109 return; /*m is already freed*/
112 /* after macro expansion... */
116 if (m->m_len < hdrlen + sizeof(*th)) {
117 n = m_pulldown(m, hdrlen, sizeof(*th), &off);
119 th = (struct tcphdr *)(mtod(n, caddr_t) + off);
123 th = (struct tcphdr *)(mtod(m, caddr_t) + hdrlen);
129 Figure \n[figure]: code fragment for trimming mbuf chain.
132 the first column identifies the test case.
133 The second column shows the number of times
134 the IP6_EXTHDR_CHECK macro was used.
135 In other words, it shows the number of times we have made checks against
137 The remaining columns show, from left to right,
138 the number of times memory allocation/copy was performed in each of the variants.
141 we counted the number of cases we passed
143 in excess of MHLEN (96 bytes in this installation).
148 .\"there were no such failures.
150 that there was no packet with a packet header portion larger than
151 MCLBYTES (2048 bytes).
152 .\" The percentage in parentheses is ratio against the number on the first column.
153 In the evaluation we have used
155 against IPv6 traffic only.
162 m_pullup m_pullup2 m_pulldown
164 total header length MHLEN(100) MCLBYTES(2048) \(mi
165 single header length \(mi \(mi MCLBYTES(2048)
168 avoids copy on intermediate headers
172 avoids pointer reinitialization
176 Table 1: assumptions in mbuf manipulation approaches.
181 c |c |cfI s s |cfI s s |cfI s
182 c |r |c c c |c c c |c c
183 r |r |r r r |r r r |r r.
184 test len checks m_pulldown m_pullup m_pullup2
185 call alloc copy alloc copy fail alloc copy
187 (1) 204923 1706 1595 1596 165 165 1541 1596 1596
188 (2) 1063995 23786 22931 23008 1171 1229 22557 22895 22953
189 (3) 520028 1245 948 957 432 432 813 945 945
190 (4) 438602 180 6 6 178 178 2 24 24
191 (5) 5570 2236 206 206 812 812 1424 1424 1424
194 Table 2: number of mbuf allocation/copy against traffic
201 test IPv6 input TCP UDP ICMPv6 1 mbuf 2 mbufs ext mbuf(s)
203 (1) 29334 20892 2699 5739 3624 15632 10078
204 (2) 313218 215919 15930 80263 38751 172976 101491
205 (3) 132267 117822 8561 5882 12782 59799 59686
206 (4) 73160 66512 5249 1343 7475 42053 23632
207 (5) 1433 148 53 52 103 1203 127
210 Table 3: Traffic characteristics for tests in Table 2
214 From these measured results, we obtain several interesting observations.
216 actually failed on IPv6 trafic.
217 If an IPv6 implementation uses
219 for IPv6 input processing,
220 it must be coded carefully so as to avoid trying
222 against any length longer than MHLEN.
223 To achieve this end, the code copies the data portion from the mbuf
224 chain to a separate buffer, and the cost of memory copies becomes a penalty.
226 Due to the nature of this simulation,
227 the comparison described above may contain an implicit bias.
228 Since the IPv6 protocol processing code is written by using
230 the code is somewhat biased toward
232 If a programmer had to write the entire IPv6 protocol processing with
234 only, he or she would use
237 extension headers buried deep inside the header chains,
238 thus making it unnecessary to call
240 In any case, a call to
242 will result in a data copy,
243 which causes extra overhead.
244 .\"The author thinks that this bias toward
246 .\"is therefore negligible.
248 In all cases, the number of length checks (second column) exceeds the
249 number of inbound packets.
250 This behavior is the same as in the original 4.4BSD stack;
251 we did not add a significant number of length checks to the code.
258 as necessary during the parsing of the headers.
259 For example, to process a TCP-over-IPv6 packet, at least 3
260 checks would be made against m->m_len;
261 these checks would be made
262 to grab the IPv6 header (40 bytes),
263 to grab the TCP header (20 bytes), and to grab the TCP header
264 and options (20 to 60 bytes).
265 The length of the TCP option part is kept inside the TCP header,
266 so the length needs to be checked twice for the TCP part.
267 .\"If the function call overhead is more significant than the actual
272 .\"we may be able to blindly call
274 .\"with the maximum TCP option length
275 .\"(60 bytes) in order to reduce the number of function calls.
278 Ao: box invis ht boxht*2
279 A: box at center of Ao "IPv6 header"
280 Bo: box invis ht boxht*2
281 B: box at center of Bo "TCP header" "(len)"
282 Co: box invis ht boxht*2
283 C: box at center of Co "TCP options"
286 arrow from 1/3 of the way between Ao.sw and Ao.se to Ao.sw
287 arrow from 2/3 of the way between Ao.sw and Ao.se to Ao.se
288 line invis from Ao.sw to Ao.se "40"
289 line from Ao.sw to 4/5 of the way between Ao.sw and A.sw
290 line from Ao.se to 4/5 of the way between Ao.se and A.se
292 arrow from 1/3 of the way between Bo.nw and Bo.ne to Bo.nw
293 arrow from 2/3 of the way between Bo.nw and Bo.ne to Bo.ne
294 line invis from Bo.nw to Bo.ne "20"
295 line from Bo.nw to 4/5 of the way between Bo.nw and B.nw
296 line from Bo.ne to 4/5 of the way between Bo.ne and B.ne
298 arrow from 1/3 of the way between Bo.sw and Co.se to Bo.sw
299 arrow from 2/3 of the way between Bo.sw and Co.se to Co.se
300 line invis from Bo.sw to Co.se "20 to 60"
301 line from Bo.sw to 4/5 of the way between Bo.sw and B.sw
302 line from Co.se to 4/5 of the way between Co.se and C.se
306 Figure \n[figure]: processing a TCP-over-IPv6 packet requires 3 length checks.
308 The results suggest that we call
310 more frequently in ICMPv6 processing than in the processing of other protocols.
311 These additional calls are made for parsing of ICMPv6 and for neighbor discovery options.
312 The use of loopback interface also contributes to the use of
315 In the tests, the number of copies made in the
317 case is similar to the number made in the
321 makes less copies than
323 against packets like below:
325 A packet is kept in multiple mbuf.
326 With mbuf allocation policy in
328 we will see two mbufs to hold single packet
329 if the packet is larger than MHLEN and smaller than MHLEN + MLEN,
330 or the packet is larger than MCLBYTES.
332 We have extension headers in multiple mbufs.
333 Header portion in the packet needs to occupy first mbuf and
336 To demonstrate the difference, we have generated an IPv6 packet with a
337 routing header, with 4 IPv6 addresses.
338 The test result is presented as the 5th test in Table 2.
339 Packet will look like
343 First 112 bytes are occupied by an IPv6 header and a routing header,
344 and the remaining 16 bytes are used for an ICMPv6 header and payload.
345 The packet met the above condition, and
347 made less copies than
349 To process single incoming ICMPv6 packet shown in the figure,
358 \f[CR]node A (source) = 2001:240:0:200:260:97ff:fe07:69ea
359 node B (destination) = 2001:240:0:200:a00:5aff:fe38:6f86
360 17:39:43.346078 A > B:
361 srcrt (type=0,segleft=4,[0]B,[1]B,[2]B,[3]B):
362 icmp6: echo request (len 88, hlim 64)
363 6000 0000 0058 2b40 2001 0240 0000 0200
364 0260 97ff fe07 69ea 2001 0240 0000 0200
365 0a00 5aff fe38 6f86 3a08 0004 0000 0000
366 2001 0240 0000 0200 0a00 5aff fe38 6f86
367 2001 0240 0000 0200 0a00 5aff fe38 6f86
368 2001 0240 0000 0200 0a00 5aff fe38 6f86
369 2001 0240 0000 0200 0a00 5aff fe38 6f86
370 8000 b650 030e 00c8 ce6e fd38 d553 0700
374 Figure \n[figure]: Packets with IPv6 routing header.
377 During the test, we experienced no kernel stack overflow,
378 thanks to a new calling sequence between IPv6 protocol handlers.
380 The number of copies and mbuf allocations vary very much by tests.
381 We need to investigate the traffic characteristic more carefully,
382 for example, about the average length of header portion in packets.