November 2, 2022

BSD TCP/IP for Kyu - Receiving packets

This of course starts in the network driver. A packet gets received and gets passed to the IP layer. The IP layer then determines that it is a TCP packet and calls tcp_input with the packet.

In Kyu, my network driver places a received packet into a Kyu "netbuf". The netbuf structure itself has a 1600 byte "data" array that will hold any packet without fragmentation.

We want to transfer this to a BSD mbuf. A mbuf is 128 bytes in size with 108 bytes available for payload. This get augmented by mbuf that have clusters attached. The size of a cluster can vary, but in Net/3 it is 2048 bytes (see MCLBYTES). This value is set in machine/include/param.h It was traditionally 1024 bytes (and that is the value set for the i386). The value for sparc and hp300 is 2048.

I modify my value in machine/param.h from 1024 to 2048. This also requires changing MCLSHIFT from 10 to 11.

So, what does a Net/3 device driver do when it receives a packet? On page 103 of the book, we see that m_devget() gets called to copy the data to an mbuf chain. This routine is in uipc_mbuf.c and is described in the book on pages 44-46 (section 2.6). There are 4 cases:

Note that the mbuf chain does not include the ethernet header. It starts with the IP header.

The call to m_devget has 4 arguments:

struct mbuf *
m_devget(buf, totlen, off0, ifp, copy)
        char *buf;
        int totlen, off0;
        struct ifnet *ifp;
        void (*copy)();
The last argument is usually 0 (when 0, bcopy will be used to move data).

The argument "ifp" is a back pointer to the interface structure for the device that received the packet.

off is an offset when the packet has a trailing header. In this case m_devget will leave room at the start for the header and move it there.

buf and totlen are what you might expect -- the address of the device buffer and the size to be moved. The value of totlen is usually the received size minus 16 bytes for the ethernet header, and minus 4 bytes for the checksum.

Kyu always keeps the whole thing in the netbuf, exactly as received from the hardware. So the ethernet header is there at the start. The driver does not copy the checksum. The following variables are maintained:

So, if we have a Kyu netbuf (pointed to by nbp) that we want to get m_devget() to copy into an mbuf chain for us, we might make the call:
m = m_devget ( nbp->iptr, nbp->ilen, 0, NULL, 0 );
This would put NULL into the field that ought to point to ifnet, but that will have to do for now.


Have any comments? Questions? Drop me a line!

Kyu / [email protected]