Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
soc:nikhilcrao [2006/06/16 02:51] nikhilcrao |
soc:nikhilcrao [2006/07/17 21:13] (current) nikhilcrao |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Nikhil Rao, Implementing IPv6 support in gPXE ====== | ====== Nikhil Rao, Implementing IPv6 support in gPXE ====== | ||
+ | |||
+ | |||
+ | //Quicklink: [[revised timeline|Timeline]]// | ||
===== About the project ===== | ===== About the project ===== | ||
My project is titled Implementing IPv6 support in gPXE. Here are some snippets from [[soc:nikhil:proposal|my proposal]]. | My project is titled Implementing IPv6 support in gPXE. Here are some snippets from [[soc:nikhil:proposal|my proposal]]. | ||
- | [[revised timeline]] | ||
==== Synopsis ==== | ==== Synopsis ==== | ||
Line 47: | Line 49: | ||
I have tried to update my blog as frequently as possible with my thoughts. Here are some important notes which have been edited after IRC conversations, e-mails and IM sessions with Michael and Marty. | I have tried to update my blog as frequently as possible with my thoughts. Here are some important notes which have been edited after IRC conversations, e-mails and IM sessions with Michael and Marty. | ||
+ | |||
+ | ==== Implementing TCP ==== | ||
==== gPXE network infrastructure ==== | ==== gPXE network infrastructure ==== | ||
Line 309: | Line 313: | ||
The ''rx_process()'' function processes the transport layer headers and passes the information to the application layer. The application's callback function ''xxx_operations::newdata()'' is invoked to send data to the application layer. | The ''rx_process()'' function processes the transport layer headers and passes the information to the application layer. The application's callback function ''xxx_operations::newdata()'' is invoked to send data to the application layer. | ||
+ | |||
==== Receiving packets ==== | ==== Receiving packets ==== | ||
Line 315: | Line 320: | ||
=== Device layer processing === | === Device layer processing === | ||
- | Receiving a packet is completed in a single time slice in which net_step() runs. net_step() calls net_poll() which polls the device for data. If data is available, it enqueues the data in rx_queue and sets the link layer protocol in the packet buffer to the protocol implemented in the network device. net_step() then checks if a packet is available to process and calls net_rx_process() to process the packet. | + | Receiving a packet is completed in a single time slice in which ''net_step()'' runs.'' net_step()'' calls'' net_poll()'' which polls the device for data. If data is available, it enqueues the data in ''rx_queue'' and sets the link layer protocol in the packet buffer to the protocol implemented in the network device. ''net_step()'' then checks if a packet is available to process and calls ''net_rx_process()'' to process the packet. |
=== Link layer processing === | === Link layer processing === | ||
- | net_rx_process() parses the link layer header in the received packet. It determines which network layer protocol to use and sets the network protocol pointer of the packet buffer to this protocol. It strips off the link layer header and sends the packet to the network layer using the rx_process() routine of the network layer protocol | + | ''net_rx_process()'' parses the link layer header in the received packet. It determines which network layer protocol to use and sets the network protocol pointer of the packet buffer to this protocol. It strips off the link layer header and sends the packet to the network layer using the ''rx_process()'' routine of the network layer protocol |
net_protocol = find_net_protocol(llhdr.net_proto); | net_protocol = find_net_protocol(llhdr.net_proto); | ||
Line 327: | Line 332: | ||
=== Network layer processing === | === Network layer processing === | ||
- | Currently ipv4_protocol.rx_process() points to ipv4_rx(), which copies the packet to uip_buf and invokes the uIP stack. We need to replace this function with one that processes the network layer headers and transmits the packet to the transport layer. Something that looks like this: | + | Currently ''ipv4_protocol.rx_process()'' points to ''ipv4_rx()'', which copies the packet to ''uip_buf'' and invokes the uIP stack. We need to replace this function with one that processes the network layer headers and transmits the packet to the transport layer. Something that looks like this: |
struct ipv4_hdr { | struct ipv4_hdr { | ||
Line 396: | Line 401: | ||
} | } | ||
- | There are bunch of functions which need to be implemented. ipv4_reassemble() for example, takes the fragment, reassembles the whole packet and then calls trans_rx_send() to send it to the transport layer. | + | There are bunch of functions which need to be implemented. ''ipv4_reassemble()'' for example, takes the fragment, reassembles the whole packet and then calls ''trans_rx_send()'' to send it to the transport layer. |
=== Transport layer processing === | === Transport layer processing === | ||
- | Let us assume that UDP is the transport layer protocol specified in iphdr->protocol (=17), then trans_protocol->rx_process() points to udp_rx_process(). UDP processing is simple: calculate and verify the checksum, demux and get the connection, invoke the application's callback functions. | + | Let us assume that UDP is the transport layer protocol specified in ''iphdr->protocol'' (=17), then ''trans_protocol->rx_process()'' points to ''udp_rx_process()''. UDP processing is simple: calculate and verify the checksum, demux and get the connection, invoke the application's callback functions. |
static int udp_rx_process(struct pk_buff *pkb) { | static int udp_rx_process(struct pk_buff *pkb) { | ||
struct udp_header *udphdr; | struct udp_header *udphdr; | ||
| | ||
- | /* We need to create the UDP pseudo-header in order to compute the checksum. This depends on the network layer protocol. We could encapsulate this information in the generic network layer header but we need to pass that around along with the packet buffer. Another idea is to store the pseudo-header in the packet buffer in the network layer and use it to compute the cheksum. | + | /* We need to create the UDP pseudo-header in order to compute the checksum. |
+ | * This depends on the network layer protocol. We could store the pseudo-header | ||
+ | * in the packet buffer in the network layer and use it to compute the cheksum. | ||
* // in trans_rx_send(pkb) - after find_trans_protocol() | * // in trans_rx_send(pkb) - after find_trans_protocol() | ||
* ... | * ... | ||
Line 424: | Line 431: | ||
} | } | ||
- | TCP would require a much more complicated trans_protocol->rx_process() function which would check the state of the TCP connection and proceed accordingly. | + | TCP would require a much more complicated ''trans_protocol->rx_process()'' function which would check the state of the TCP connection and proceed accordingly. |
Line 482: | Line 490: | ||
When the ''IP_FRAG_FIN'' flag is set, the packet is sent to the transport layer protocol for processing. The ''reass_buffer'' is discarded and memory is released. | When the ''IP_FRAG_FIN'' flag is set, the packet is sent to the transport layer protocol for processing. The ''reass_buffer'' is discarded and memory is released. | ||
+ | |||
+ | ==== More on IP fragment reassembly ==== | ||
+ | |||
+ | Last night, Michael and I had a long IM session in which we discussed the reassembly requirements. Here are the main points: | ||
+ | |||
+ | - We assume that the fragments are received in order. We do not need to remember where in the original packet the recived fragment fits. This greatly simplifies the process of reassembling fragments. | ||
+ | - If a fragment is received out of order, we simply assume that the missing fragment (before it) is lost and we discard the reassembly buffer. | ||
+ | - If the offset field of a fragment is equal to 0, then we create a new reassembly buffer for the fragment series as described in the earlier note. | ||
+ | - If the offset field if not set, we identify the fragment series. If the offset + total_length of the last received fragment in the fragment series is equal to the offset of the received fragment, we add the fragment to the fragment series. Else we discard the fragment series. | ||
+ | - If the more fragments field is not set, i.e. this is the last fragment of the series, on successfully adding the fragment, we invoke the transport layer's ''rx_proces()'' function and pass the reassembled buffer into it. | ||
+ | - We need to write ''realloc_pkb()'' which will take a packet buffer and a new length, allocate a new packet buffer for the new length, copy the contents of the old packet buffer into the new one, and then free up the old packet buffer. This function will be useful in maintaining the reassembled buffer. | ||
+ | |||
+ | (I apologise for the verbose and hasty notes. I will compile a more elaborate one with code snippets soon) | ||
==== To do list ==== | ==== To do list ==== | ||
+ | |||
+ | - Document revised TX and RX paths through the network stack((Last night, Michael was hard at work simplifying the TX and RX data paths through the network stack.)). | ||
+ | - Figure out a way to pass generic information between layers | ||
+ | - Complete the UDP implementation | ||
+ | - Complete the IPv4 implementation | ||
+ | - Debug/test the UDP/IPv4 stack | ||
+ | - Implement fragment reassembly | ||
===== Some fun stuff ===== | ===== Some fun stuff ===== |