Hi everyone,
I am trying to come up with a simple basic ping request-response program in P4 (ICMP handling) running on simple_switch binded to eth and wlan interface. Any references to such a program that already exists would be appreciated. Thank you!
Hi,
We did this exercise at the Technical University of Denmark (DTU) both for ARP and ICMP. I am not sure if you need to provide an answer in your university course exercise or not, so I generally tend to provide a limited answer (with few code parts) so people can develop the rest.
If we assume that ARP works fine (all hosts already know others host’s MAC-IP or ARP is working in your network), then you only have to worry about ICMP. P4 switches are probably not the most efficient entities to respond to some queries, but sometimes one can achieve a greater performance. ARP and ICMP are two possibilities, but there might be other interesting protocols (DNS?[1] [2]). If replying implies having to process the payload to a great extent, then I do not think a P4 switch is the best option. But let’s come back to ICMP.
There is a chance that different system build ICMP packets differently. Maybe the generated payload by some ping
programs is bigger in some systems, and others might add a sequence id
or some other extra values. In fact, I am pretty sure that for every type of ICMP packet (request, response, etc.) you can also find different payloads. If I were you, I would first capture the traffic with Wireshark and decide which headers you need. In my case, I extracted a total of 64 bits in 5 fields. I did not modify some fields, so you can ignore them. You might also follow public definitions with the standard headers. That should be enough.
I assume we just care about request (type 8) / response (type 0) packets. In general terms, you should follow the following steps:
- Parse Eth → IPv4 → ICMP
- Remember to change the destination port, you do not need tables for this.
- Check if this is an ICMP packet (IPv4 header should tell you). Possibly also detect if it is an ICMP request (
if
statement or a table should work to detect both things at the same time).
- Then modify the packet to make the original source look like the destination and make the original destination now be the source. We used to “impersonate hosts” but you can also use an invented MAC/IP for the switch and use that instead of the destination host’s data. You will have to then also detect destination IP and check if that is the made up one for the switch. All the process implies changing many parameters at Ethernet and IPv4 headers (like addresses).
- It is important to consider the checksum in IPv4 and ICMP. IPv4 checksum computation is available in the tutorial or in Andy’s repository (and probably many other repositories in GitHub). Not sure if that easy to find the ICMP one, so I believe it might be difficult to guess, so I post here the one I used. I cannot remember if this worked or if this is correct to be honest. It was a long time ago, but I think this is the final version. I think I assigned the ICMP checksum a 0 at Ingress block, but not sure if necessary (
hdr.icmp.chk = 0
).
update_checksum_with_payload(
hdr.icmp.isValid(),{
hdr.icmp.field_1,
hdr.icmp.field_2,
hdr.icmp.field_3,
hdr.icmp.field_4},
hdr.icmp.chk, # icmp.field_5
HashAlgorithm.csum16
);
Feel free to ask questions.
Hope this helps
Hi @ederollora - Thank you so much for such a detailed answer. It really gives me a lot of insight as to how should I proceed forward with my implementation. I will try this thing out as pointed out and reach out further in case I get into some issues. Thank you again!