The Internet Protocol
IP can be thought of as being like a national delivery service that gets packages from a sender to a recipient, with the sender being oblivious to the routing and delivery mechanisms used by the delivery agent. The sender simply hands the package to the delivery agent, who then moves the package along until it is delivered.
Similarly, it is the function of IP to provide relaying and delivery decisions whenever an IP datagram has to be sent across a series of networks in order for it to be delivered to the final destination. The sending system will not care how the datagram gets to the destination system, but instead will choose the best route that is available at that specific moment. If this involves sending the datagram through another intermediary system, then that system will also make routing decisions according to the current condition of the network, forwarding the data on until it arrives at the destination system, as specified in the datagram's header.
Once the datagram is sent, IP forgets about it and moves on to the next datagram. IP does not offer any error-correction, flow-control or management services. It just send datagrams from one host to another, one network at a time.
A key concept here is the difference between IP datagrams and IP packets. The data that is generated by a host is an IP datagram, altough these datagrams get sent as IP packets. Although in many cases an IP datagram and an IP packet will be exactly the same, they are conceptually different entities, which is an important concept for understanding how IP actually works. IP packets are used to relay the IP datagrams to the destination system, one hop at a time. If a datagram is too large for a network to handle, the datagram will get fragmented into multiple IP packets, each of which can take their own path to the destination system, and which can be fragmented into more packets if needed.
When a system has to send a datagram to another system, it looks at the routing table and finds the appropriate network interface to send the outbound traffic through. Most TCP/IP packages provide end-user tools that allow you to manually create and delete routing entries for specific networks and hosts.
There are several application protocols that can be used to automatically build maps of the network and have them distributed to all of your systems without human intervention. The most popular of these for private networks is the Routing Information Protocol (RIP), which uses UDP broadcasts to distribute routing tables every thirty seconds. Another popular protocol is Open Shortest Path First (OSPF), which provides the same basic functionality as RIP but with more detail and less overhead. For external networks, neither of these protocols work well enough to support a significant number of networks, and other protocols (such as the Border Gateway Protocol) are more common for those environments.
In common practice, most network administrators only run these dynamic routing protocols on their routers (but not on their hosts) since they tend to consume a lot of CPU cycles, memory and network bandwidth. They then define "default" routes at the hosts, pointing them to the router(s) that serve the local network that the host is attached to. By using this model, clients only need to keep one entry in their routing tables, while the dedicated routers worry about keeping track of the overall network topology.
Default routes can be built manually (using the tools provided with the IP software in use on the local system), or can be assigned during system boot (using a protocol such as BOOTP or DHCP). In addition, a protocol called Router Discovery can provide network devices with default route information dynamically, updating the devices' routing tables as the network topology changes.
Every system that receives a packet - whether it is the final destination or a router along the delivery path - will inspect it. If the packet has become corrupt or has experienced some other form of temporary failure, then the packet will be destroyed right then and there. Whenever one of these transient errors occurs, the datagram is destroyed rather than being forwarded on.
However, if a problem occurs that is semi-permanent - such as the current device not having a routing table entry for the destination network, or if the packet does not meet certain criteria for forwarding across the next-hop network - then IP may call upon the Internet Control Message Protocol (ICMP) to return an error message back to the original sender, informing them of them failure. Although the datagram will still be destroyed by the last-hop device, it will also inform the sender of the problem, thereby allowing it to correct whatever condition was causing the failure to occur.
This distinction between transient and semi-permanent failures is an important one to make. Transient errors are caused by no fault of the sender (such as can happen when the Time-To-Live timer expires, or a checksum is miscalculated), while semi-permanent failures are problems with the packet or network that will always prevent delivery from occurring over this path. In the latter case, it is best to inform the sender of the problem so that it can take whatever corrective actions are required, or to notify the application that tried to send the data of the problem.
Part of the integrity-checking service is handled through the use of a checksum applied against the IP datagram's header (but not the data inside of the IP datagram). Every device that receives an IP datagram must examine the IP header and compare that information with the value stored in the header's checksum field. If the values do not match, then the datagram is assumed to be corrupt and is discarded immediately.
Another validation service provided by IP is checking to see if a datagram has outlived its usefulness. This is achieved through a Time-to-Live field provided in the IP datagram's header. When a system generates an IP packet, it stores a value in the Time-to-Live header field, and every system that forwards the packet will also decrease the value of the Time-to-Live field by one, before sending the datagram on. If the Time-to-Live value reaches zero before the datagram gets to its final destination, then the packet is destroyed.
One of the key differences between IP and other networking protocols is that IP offers direct support for prioritization, allowing network hosts and routers to send important packets before less important packets. This is particularly important with applications that are sensitive to high levels of delay resulting from network congestion.
In order to ensure that congestion doesn't break the mission-critical applications on your network, IP supports two key concepts: prioritization and type-of-service handling. Every IP datagram has an eight-bit field (called the "TOS byte") that consists of a three-bit precedence field used for prioritization, and a four-bit field that indicates specific handling characters desired for a datagram (the last bit is currently unused).
By using three bits for precedence, IP has eight levels of prioritization ("0" through "7"), which provide eight distinct priority levels to all IP traffic. Table 2-8 on page 50 lists the values of the Precedence field and their meaning as defined in RFC 791, with the highest priority level being "7" and the lowest being "0".
The remaining four bits of the TOS byte provide administrators with the ability to implement per-datagram routing based on the characteristics of the datagram's data. Thus, an IP datagram that contains Usenet News traffic can be marked as desiring a "low-cost" service, while Telnet traffic can be marked as desiring a "low-latency" service.
Originally, there were only three types of service defined in RFC 791. These services were identified with unique bits that were either on or off, depending on whether or not the specific type of service was desired. However, this interpretation was modified by RFC 1349, which added a fourth service class, and which also stated that the bits were to be interpreted as numeric values rather than independent flags. By making them numeric, the four bits provided for a maximum of sixteen possible values ("0" through "15"), rather than four distinct options (although the values cannot be combined, and must be used independently).