Building upon your Embedded Xinu kernel from the previous assignment, flesh out an IPv4 layer consisting of a function for sending IPv4 datagrams and a function for receiving IPv4 datagrams. This may require refactoring code you have already written for the previous assignment.
The ipWrite function should take as parameters a pointer to the payload, a payload length, an IPv4 type field, and a destination IP address. This function builds the IPv4 header, and passes the packet down to the netWrite function with a destination MAC address. This function fills the various IPv4 header fields, assigns a unique packet identifier, calculates the IP header checksum, and looks up the destination MAC of the next hop.
Your receiving IPv4 function, called from the netDaemon, should check the IP header version, validate the checksum, verify that the destination IP address is for this host or broadcast, and then demultiplex the packet based on type.
The IP Layer of the network stack is meant to be independent of underlying Network Interface layers such as Ethernet. IPv4 datagrams can have a payload of up to 64KB. When given a packet that is longer than the underlying Network Interface's Maximum Transmission Units (MTU, which is 1500 bytes on Ethernet,) the IP Layer fragments the packet accordingly. Fragment packets share the same unique sequence identifier, and use the Fragment Offset field of the IPv4 header to specify where a fragment appears in the overall packet.
Implement fragmentation for outgoing IPv4 packets in your IP Layer.
Hosts on the receiving end of fragmented IPv4 datagrams perform fragment reassembly. When the first fragment of a datagram arrives, a conceptual timer is started; if the rest of the fragments do not arrive before the timer expires, all of the fragments are discarded. A fragmented datagram is not demultiplexed to higher layers unless all of its fragments arrive.
In the interest of simplicity for our embedded network stack implementation, you may assume that your stack is capable of assembling only one fragmented datagram at a time. Instead of a conceptual time-out, your implementation may give up on a fragmented datagram as soon as a fragment from some other datagram arrives.
Your ICMP implementation from the previous assignment will be helpful in testing this feature of your IP Layer.