- 1 General
- 1.1 Which files in the stub code can I modify?
- 1.2 What is the best methodology for debugging my router?
- 1.3 What are good references for dealing with protocol headers?
- 1.4 What kind of sanity checks should I perform on the packet header?
- 1.5 What sort of routing entries do we need to support in the routing table?
- 2 Topology Issues
- 2.1 How do I know that my topology is set up and working?
- 2.2 Trouble connecting to a topology
- 2.3 I tried running the skeleton code and then accessing one of the webservers, however it doesn’t work. Is there something wrong?
- 2.4 When I run traceroute, why don’t get a reply from the hop before my router?
- 2.5 Ping/traceroute/etc appears to work, but I don’t see the return packets inside my router. What’s up with that?
- 3 Ethernet
- 4 ARP
- 4.1 What ARP functionality do I have to handle?
- 4.2 How do I implement the ARP cache? Is a static table sufficient? Do I need a hash table?
- 4.3 How do we implement the arp queue timeout? Should we use multiple threads or a timer?
- 4.4 Why are the ARP packets I get from sr_send_packet( .. ) 60 bytes instead of 42?
- 4.5 How many ARP requests must I send to a host withouh a response before I send an ICMP host unreachable packet back to the sending host?
- 5 IPv4
- 6 Checksums
- 7 ICMP
- 7.1 If I generate an ICMP message, what is the right TTL to use?
- 7.2 What types of ICMP messages do I have to generate
- 7.3 Does the client have to reply to ICMP Echo Requests on all three interfaces or just on the primary interface?
- 7.4 Do I have to generate ICMP Host Unreachable messages for ICMP packets?
- 7.5 What source address should I use when responding with a port unreachable?
- 7.6 What is the timeout of a host unreach?
Which files in the stub code can I modify?
The only files in the provided source that you may modify are sr_router.h and sr_router.c (this does not include bugfixes). You may, however, add your own files and update the Makefile to support them.
What is the best methodology for debugging my router?
Debugging the source code for logic errors, crashes and memory leaks should not be any different than any other program. The use of valgrind and gdb is encouraged
In order to facilitate debugging of network traffic handled by your router, the sr stub code supports tcpdump compatible packet logging for all packets sent from and coming to the router. It is highly recommended that you get comfortable logging packets and viewing the logfiles in tcpdump as soon as possible.
To log packets, use the -l command line option for sr to specify a log file. All packets will then be written to this log file.
elaine15:~/tmp/sr_skel> ./sr -t 17 -l logfile
To view the log file using tcpdump use the -r command. It is also recommended that you use the -e command to print out headers, the -vvv command for verbose output and the -x command to print out the hex values of the packets. Output should look as follows:
elaine15:~/tmp/sr_skel> /usr/class/cs244a/bin/tcpdump -e -vvv -x -r logfile 19:51:31.809693 0:e0:81:3:fd:9e Broadcast arp 84: arp who-has 172.24.74.40 tell vr-firewall.Stanford.EDU 0001 0800 0604 0001 00e0 8103 fd9e ac18 4a11 0000 0000 0000 ac18 4a28 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000a 0000 0260 0000 0000 0002 92d0 0000 0000 0000 0000
Another very useful tool you may want to play around with is WireShark.
What are good references for dealing with protocol headers?
- Unix Network Programming, Stevens
- Network sorcery RFC source book
- RFC 826 (ARP)
- RFC 791 (IP)
- RFC 792 (ICMP)
What kind of sanity checks should I perform on the packet header?
Your code must be stable (e.g. not crash) with any packet it receives. You should also discard packets that are obviously corrupted e.g. if the IP version is not IPv4, if the packet length is negative or above the Ethernet MTU etc.
What sort of routing entries do we need to support in the routing table?
You have to support two cases:
- Routes where the next hop is explicitly stated.
- Routes where the next hop is ‘0.0.0.0′ which denotes that all matches to this route lie in the collision domain of the interface associated with the route. In this case, the next hop is the destination address of the IP packet.
How do I know that my topology is set up and working?
The very first thing you are going to want to do when ready to start playing around with the skeleton code is connect to the VN server and verify that your topology exists. Once the code is compiled, run ./sr with your topology number (using the -t command line option to specify the topology number. A session using topology number 17 might look as follows:
elaine15:~/tmp/sr_skel> ./sr -t 17 Destination: 0.0.0.0 Gateway : 172.24.74.17 Mask : 0.0.0.0 Interface : eth0 Client pepe connecting to Server vr-server-b:12345 Requesting topology 17 Sending c_open (type=1 len=108) Received Hardware Info with 19 entries Fixed IP: 172.24.74.17 INTERFACE: eth0 Speed: 10 Hardware Address: 70:00:00:11:00:01 Ethernet IP: 172.24.74.40 Subnet: 0.0.0.0 Mask: 0.0.0.0 INTERFACE: eth1 Speed: 0 Hardware Address: 70:00:00:11:00:02 Ethernet IP: 172.24.74.241 Subnet: 0.0.0.0 Mask: 0.0.0.0 INTERFACE: eth2 Speed: 0 Hardware Address: 70:00:00:11:00:06 Ethernet IP: 172.24.74.242 Subnet: 0.0.0.0 Mask: 0.0.0.0 Interface: eth0 ip address 172.24.74.40 Interface: eth1 hardware address 70:00:00:11:00:02 ip address 172.24.74.241 Interface: eth2 hardware address 70:00:00:11:00:06 ip address 172.24.74.242
You can ignore most of this information, but do verify that the IPs on the router’s interfaces do match those on the router of topology assigned to you.
To verify that your router does, in fact, receive packets, try pinging one of the interfaces. Your router should print the following:
*** -> Received packet of length 60 *** -> Received packet of length 60 *** -> Received packet of length 60
What packet do you think this is? If you are able to connect to the server and see packets, you are correctly set up to start the assignment.
Trouble connecting to a topology
I’m having trouble connecting to my topology, the error I’m getting is:
client casado connecting to Server 18.104.22.168:12345 Requesting topology 122 Sending c_open (type=1 len=108) vns server closed session. Reason: reservehost failed sr_destroy_INSTANCE leaking memory
The most likely cause for this error is that there is already a router connected to your topology. Typically this happens when students forget to properly kill their routers (often using ctrl^z which only suspends them). You determine if a router is connected to your topology by going to the following web page: http://vns-1.stanford.edu/summary. If there is a router on your topology then it is already in use. The page gives an indication of the user doing the connection as well as the connecting IP address. If the router is yours, kill the process and it will free up. If another student has mistakingly connected to your topology you’ll have to contact them directly or your Prof/TA.
I tried running the skeleton code and then accessing one of the webservers, however it doesn’t work. Is there something wrong?
No, that is how it should be .The skeleton code currently does pretty much nothing. It sits there, waits for packets and just drops them. With the skeleton code you can’t access any web page. You will see the ARP requests from the first hop, but since the stub code does not reply, the first hop does not know which hardware address to send the first TCP packet (SYN) to. To access the web pages you will have to write code. Actually if you can access a web page you have completed significant portions of the assignment!
When I run traceroute, why don’t get a reply from the hop before my router?
The vns-firewall does not respond to timed out packets with the expected ICMP message- or rather, it does, but filtering on the Stanford network may keep your instance of traceroute from receiving the packet, particularly if you are working from off campus. As long as you are getting traceroute replies from 1) your router, and 2) the application server where appropriate, things are fine even if you’re getting the “three asterisk” output at the line where you would expect to see the firewall.
Ping/traceroute/etc appears to work, but I don’t see the return packets inside my router. What’s up with that?
If you’re printing debug information or logging packets, on some topologies you may see what seems like an impossible series of events:
- You run ping, traceroute, an ftp download, or some other command aimed at a server on your topology.
- Your router gets a packet from the firewall destined for one of the servers. You route it to the server appropriately after doing your ARP processing and other appropriate bits.
- You see the ping or download complete, but never see the return path (echo response from the server, etc.) inside your router.
What’s happening here is that your topology is slightly malfunctioning- your router is working correctly, but at the application server packets are being routed back out through the firewall directly rather than passing through your topology. This happens because interactions between the servers and the topologies that they are multiplexed to are governed by special routing rules called policy routes; policy routes enable a routing decision to be made based on both the source and destination address of a packet, rather than just the destination alone. Policy routes are used to make it appear like a single Linux server exists on several hundred topologies at the same time. Unfortunately, there are some limitations on policy routes enforced by the operating system; one of them is that there is a limited number of policy routes that a single server can hold. For most applications, this is never an issue as the server never binds to more than a small handful of IP addresses; even with a policy route for each one, you’d never run out. VNS, however, bumps up against the routing limits that are set by the operating system; because we might have a server that is multiplexed onto a large number of topologies, we can run out of policy route slots or have multiple topologies try to use the same slot. When this occurs, the system attempts to fail gracefully by routing packets back out directly through the firewall, preserving the forward path for the topology, but sending return-route packets (such as ICMP echo reply packets generated by the server) back out directly through the system firewall, rather than through the associated topology.
If your concerned that the reverse route might have problems on your topology, email email@example.com- in some cases its possible to manually restore the proper routing for the return path.
Do I have to deal with the ethernet preamble/crc?
No, sr_handlepacket( .. ) delivers ethernet packets without the preamble and without the CRC. Likewise, sr_send_packet(..) expects an ethernet packet without the preamble and CRC. All packets to/from these functions have the following header format:
DST SRC FRAME DATA MAC MAC TYPE +-------+-------+-------+-------------------+ |6 bytes|6 bytes|2 bytes| 46 - 1500 bytes | +-------+-------+-------+-------------------+
Does the Ethernet MTU include the header?
No, you can expect packets of up to 1514 bytes
What ARP functionality do I have to handle?
You have to handle both ARP requests and replies.
How do I implement the ARP cache? Is a static table sufficient? Do I need a hash table?
A static, hard-coded ARP cache is NOT acceptable. You should have a sufficiently sized (e.g. 100) entry table that is dynamically filled with values when ARP replies are received. You do NOT have to implement any sophisticated search alogrithm such as hashing or RB Trees, a linear search is perfectly acceptable.
How do we implement the arp queue timeout? Should we use multiple threads or a timer?
The answer to this question depends on whether you are required by your instructor to implement guarantees on timeouts by your instructor. If you are, then yes, you should use threading or signals to ensure that the ARP queue is cleaned out on time (similar argument for ARP cache). Otherwise, you actually can take the simple solution and only check the ARP queue timeout whenever another packet is received. This is not entirely correct behavior as a packet could be in the ARP queue for a very long time. But usually retransmits will arrive soon after the first packet, it performs pretty well in reality.
Why are the ARP packets I get from sr_send_packet( .. ) 60 bytes instead of 42?
The minimum size for the data segment of an Ethernet packet is 46 bytes, whereas an ARP packet is 28 bytes. The OS pads an extra 18 bytes on to the end of ARP packets to meet this minimum length requirement. You don’t have to worry about adding padding when generating ARP packets it will be added by the OS.
How many ARP requests must I send to a host withouh a response before I send an ICMP host unreachable packet back to the sending host?
Do I have to handle Muticast in my router?
No, you don’t.
How do I have to deal with fragmented packets?
Just ignore fragmentation. Today on the internet fragmentation is actually pretty rare. Treat fragmented packets as normal packets and you should be fine.
Do I have to be able to handle IP Options
No, other than that your client may not crash if it receives a packet with ip options, you don’t have to do anything with them. You don’t have to parse them and it is acceptable to drop such packets or generate incorrect checksums for them.
Do I have to check/decrement the TTL in the IP header if the packet is addressed to me?
No you don’t.
Section 22.214.171.124 of the router rfc (1812) states:
“Note in particular that a router MUST NOT check the TTL of a packet except when forwarding it.”
Which types of checksums (TCP/UDP/ICMP/IP) do we have to verify/calculate??
There are three types of checksums:
IP Checksums – All IP packets have these and for any forwarded/generated IP packet you have to verify/calculate it.
TCP/UDP checksum – this is an end-to-end checksum that you don’t have to worry about. Due to the way it is calculated IP header modifications won’t change its value.
ICMP Checksum – You should verify/calculate this for ICMP messages that you receive/send (but *NOT*for ICMP message that you forward, these should be treated as IP packets only). For infos how to do this see RFC 792.
How do I write and test a function that calculates the IP Checksum
The algorithm as well as sample source code is in Peterson & Davie, page 95. Be careful what parts of the package you calculate the checksum over. TCP and ICMP for example need to be treated differently. A great way to test if your function is working is to run it on arriving packets. If you get the same checksum that is already contained in the packet it looks like your algorithm is working. If you use this test, make sure not to include the old checksum (the one that is in the packet when it arrived) in your checksum calculation. In the original calculation this checksum was zero! A good way to check if you’ve calculated the correct checksum is to use WireShark, which will indicate if the checksum values are correct.
WireShark reports that the ICMP checksums generated by the Unix ping application are wrong. What is going on!?
An older version of the stub code only saved the first 96 bytes of the packets it receives and the generated ICMP packets are 98 bytes, hence WireShark’s checksum does not take into account the last 2 bytes. The latest version of the stub code has the packet dump length increased to 100 bytes. You may also modify sr_router.h to increase PACKET_DUMP_SIZE yourself.
If I generate an ICMP message, what is the right TTL to use?
There is no “right” value, however 64 is a good choice. You can easily test what your current operating system uses:
[root@gadshome appenz]# /usr/sbin/tcpdump -x &  1435 tcpdump: listening on wlan0 [root@gadshome appenz]# ping 126.96.36.199 PING 188.8.131.52 (184.108.40.206) from 192.168.1.104 : 56(84) bytes of data. 64 bytes from 220.127.116.11: icmp_seq=0 ttl=238 time=33.461 msec 11:23:03.258943 192.168.1.104 > CS.Stanford.EDU: icmp: echo request (DF) 4500 0054 0000 4000 4001 8d18 c0a8 0168 ab40 4040 0800 dbaa 9c05 0000 1703 703c 0a0d 0400 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
Byte 9 ist the TTL. Linux uses the TTL to 64 (Hex 40) as well, at least for PING messages.
What types of ICMP messages do I have to generate
You should support the following:
- Host unreachable (if no host replies to arp requests on the local networks)
- Port unreachable (if router receives a TCP or UDP packet addressed to one of its interfaces.
- Timeout (TTL of the arriving packet is one or zero)
- ICMP Echo reply (on receipt of an ICMP echo request to one of the router’s interfaces)
All other ICMP message that you receive you can ignore, however you should forward any icmp message that is not for the virtual router itself.
Does the client have to reply to ICMP Echo Requests on all three interfaces or just on the primary interface?
The client has to reply to all ICMP requests destined to IPs owned by the router’s interfaces
Do I have to generate ICMP Host Unreachable messages for ICMP packets?
For regular ICMP packets (such as ping packets destined for an application server) yes, you do. For ICMP error messages (such as Host Unreachable messages), no, you do not. While RFC 792 states that ICMP messages should not be sent about ICMP messages, later RFCs (particularly RFC 1812 and 1122) have qualified that point, stating instead that ICMP messages should not be sent as a result of receiving ICMP error messages. This distinction allows hosts to be notified in the event of an actual error (such as a ping packet being ignored), but prevents the network from being spammed with error messages flying back and forth in response to other errors.
What source address should I use when responding with a port unreachable?
Use the destination address of the packet you are responding to
What is the timeout of a host unreach?
Host unreach should be sent after 5 failed ARP attempts. Host unreaches should be sent back to the client after 5-7 seconds of sending the first ARP.