1 .\" $Id: 2.t,v 1.1 2001/07/04 05:29:25 itojun Exp $
3 .\".ds RH KAME approach
7 This section describes the approaches we at the KAME project
8 took against the problems mentioned in the previous section.
9 We introduce a new function called
13 for adjusting payload data in the mbuf.
14 We also change the calling sequence for the protocol input function.
16 What is the KAME project?
18 In the early days of IPv6/IPsec development,
19 the Japanese research community felt it very important to make
20 a reference code available in a freely-redistributable form
21 for educational, research and deployment purposes.
22 The KAME project is a consortium of 7 Japanese companies and
23 an academic research group.
24 The project aims to deliver IPv6/IPsec reference implementation
25 for 4.4BSD, under BSD license.
26 The KAME project intends to deliver the most
27 spec-conformant IPv6/IPsec implementation possible.
31 Here we introduce a new function,
33 to address the 3 problems with
35 that we have described above.
36 The actual source code is included at the end of this paper.
37 The function prototype is as follows:
41 m_pulldown(m, off, len, offp)
48 will ensure that the data region in the mbuf chain,
53 is put into a continuous memory region.
55 must be smaller than, or equal to, MCLBYTES (2048 bytes).
56 The function returns a pointer to an intermediate mbuf in the chain
57 (we refer to the pointer as \fIn\fP), and puts the new offset in
63 is NULL, the resulting region can be located by
64 .I "mtod(n, caddr_t)";
67 is non-null, it will be located at
68 .I "mtod(n, caddr_t) + *offp".
71 will remain untouched,
72 so it is safe to keep the pointers to the mbuf chain.
73 For example, consider the mbuf chain
80 define pointer { box ht boxht*1/4 }
81 define payload { box }
84 IPd: payload with .n at bottom of IPp "mbuf1" "50 bytes"
89 TCPd: payload with .n at bottom of TCPp "mbuf2" "20 bytes"
91 arrow from IP.IPp.center to TCP.TCPp.center
95 Figure \n[figure]: mbuf chain before the call to \fIm_pulldown\fP
104 the mbuf chain will remain unchanged.
105 The return value will be a pointer to mbuf1, and
116 then the mbuf chain will be modified as shown
118 in Figure \n[figure],
120 by allocating a new mbuf, mbuf3,
121 into the middle and moving data from both mbuf1 and mbuf2.
122 The function returns a pointer to mbuf3.
125 define pointer { box ht boxht*1/4 }
126 define payload { box }
129 IPd: payload with .n at bottom of IPp "mbuf1" "40 bytes"
134 INTd: payload with .n at bottom of INTp "mbuf3" "20 bytes"
139 TCPd: payload with .n at bottom of TCPp "mbuf2'" "10 bytes"
141 arrow from IP.IPp.center to INT.INTp.center
142 arrow from INT.INTp.center to TCP.TCPp.center
146 Figure \n[figure]: mbuf chain after call to \fIm_pulldown\fP, with \fIoff = 40\fP and \fIlen = 20\fP
150 function solves all 3 problems in
152 that were described in the previous section.
154 does not copy mbufs when copying is not necessary.
155 Since it does not modify the mbuf chain prior to the speficied offset
157 it is not necessary for the caller to re-initialize the pointers into the mbuf data
161 we always needed to specify the data payload length, starting from the very first byte
167 as the offset to the data payload we are interested in.
168 This change avoids extra data manipulation when we are only interested in
169 the intermediate data portion of the packet.
170 It also eases the assumption regarding total packet header length.
173 assumes that the total packet header length is smaller than or equal to MHLEN
176 assumes that single packet header length is smaller than or equal to MCLBYTES
178 With mbuf framework this is the best we
179 can do, since there is no way to hold continuous region longer than
180 MCLBYTES in a standard mbuf chain.
182 New function prototype for inbound packet processing
184 For IPv6 processing, our code does not make a deep function call chain.
185 Rather, we make a loop in the very last part of
187 as shown in Figure 8.
188 IPPROTO_DONE is a pseudo-protocol type value that identifies the end of the
189 extension header chain.
190 If more protocol headers exist,
191 each header processing code will update the pointer variables
192 and return the next extension header type.
193 If the final header in the chain has been reached,
194 IPPROTO_DONE is returned.
197 With this code, we no longer have a deep call chain for IPv6/IPsec processing.
200 will make calls to each extension header processor
202 This avoids the possibility of overflowing the kernel stack due to multiple
203 extension header processing.
206 A: ellipse "\fIip6_input\fP"
212 B: ellipse "\fIrthdr6_input\fP"
213 move to last ellipse .s
215 C: ellipse "\fIah_input\fP"
216 D: ellipse "\fIesp_input\fP"
217 E: ellipse "\fItcp_input\fP"
219 arrow from 1/4 <A.e, A.ne> to 1/4 <B.w, B.nw>
220 arrow from 1/4 <B.w, B.sw> to 1/4 <A.e, A.se>
222 arrow from 1/4 <A.e, A.ne> to 1/4 <C.w, C.nw>
223 arrow from 1/4 <C.w, C.sw> to 1/4 <A.e, A.se>
225 arrow from 1/4 <A.e, A.ne> to 1/4 <D.w, D.nw>
226 arrow from 1/4 <D.w, D.sw> to 1/4 <A.e, A.se>
228 arrow from 3/8 <A.e, A.ne> to 1/4 <E.w, E.nw>
229 arrow from 3/8 <E.w, E.sw> to 1/4 <A.e, A.se>
233 Figure \n[figure]: KAME avoids function call chain by making a loop in \fIip6_input\fP
236 Regardless of the calling sequence imposed by the
238 function prototype, it is important not to use up the kernel
239 stack region in protocol handlers.
240 Sometimes it is necessary to decrease the size of kernel stack usage
241 by using pointer variables and dynamically allocated regions.
247 \f[CR]struct ip6protosw {
248 int (*pr_input) __P((struct mbuf **, int *, int));
249 /* and other members */
255 /* in the very last part */
256 extern struct ip6protosw inet6sw[];
257 /* the first one in extension header chain */
259 while (nxt != IPPROTO_DONE)
260 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
263 /* in each header processing code */
265 foohdr_input(mp, offp, proto)
270 /* some processing, may modify mbuf chain */
272 if (we have more header to go) {
284 Figure 8: KAME IPv6 header chain processing code.