Make a switch able to resolve an IP address with ARP

Hi all,
As part of a project course, I have to implement a basic IP router in P4. Right now, I am focusing on implementing ARP.
I have been able to program the switches to reply to ARP requests by specifying their own MAC address (i.e., the MAC address of the Ethernet port on which they receive the ARP request). The code is located at this repository. I did not use Mininet yet, but used Veth pairs, to teach myself how Mininet works internally. Sorry if it is not yet idiomatic, but I am P4 novice.
The next step is to make the switches able to resolve the MAC address of other hosts. Consider, for example, the scenario where a switch S (whose IP is 192.168.1.1) has to send an IP packet to a host H (192.168.1.2). To do so, S needs to known H’s MAC address to construct the packet’s Ethernet frame. Therefore, it needs to resolve it by sending an ARP request.
I have the following questions:

  • Is it possible to do this using P4?
  • What topics, sections of the P4 language specification, or examples should I focus on in order to understand how to achieve it?

I think that the P4 switch will need to put the IP packet in a queue / table, wait until the corresponding MAC address is resolved and then send it. This, however, also requires to implement some timers so that packet does not stay in the switch’s queue forever, wasting memory; so I don’t consider it trivial.
Moreover, I think that this has to do with packet recirculation/resubmission, but I still can’t connect the dots.

Thank you for any insight.

Hi steddy, welcome to the forum.

This is pretty good that you already achieved it. As a nice extension, you could also play with the P4 code and make the switch behave as a proxy and answer as if the destination hosts did it. But this functionality might not indeed be necessary for your project course.

At this point, it would help to determine some of the things you mention. For instance,

Who is sending the ARP packet (I think I know what you mean, but I just want to clarify it)?

  • Is the controller sending the packet and then the switch sending it out a specific output port or,
  • Is the switch actually building the whole packet in the data plane (header.setValid(), etc.)?

There is a big difference between both options, and sometimes you might want to think where you want to implement. To prevent having a lot of time between your answer and my response, I will assume you want to do as much as possible in the data plane (with your P4 code).

It is possible. Now, it might not be an easy task. Let’s say Host_1 or the Controller send some information and your switch wants to re-send this packet but with the IP and MAC of Host_2. One option (1) is that you could store the original packet, then send the ARP request and then go back to the first packet, modify some fields and send it to Host_2. However, (2) you could also extract the application layer information and write it to a register. Then, send the ARP request. When you receive the ARP reply, assume that you need to send back the information stored at a particular register (this needs further planning, but you understand what I mean).

Yes, this what I meant. I hope any other person more aware about P4 or bmv2 can correct me, but I cannot remember any way to store a packet in the switch memory, then go with an independent task and come back to reference the packet you first buffered. Alternatively, you can then think if the controller could store it momentarily, which is not a bad idea (depending on your case).

Also, (1) consider that you could automate the control plane to resolve MACs occasionally but store the response in registers in th switch whenever a reply is received if you want that. Alternatively, (2) the controller can also install rules in a table with the IP as key and MAC as action parameter. It is always to do this process before you need to trigger it in the data plane.

I am not completely sure how to solve this issue by recirculating the packet. I could be wrong, of course, and I will check if someone corrects me. But if you clone a packet you can process it again, for instance, in case you need it sent to the destination but also store a value in a register or send it to the controller (more cases also apply, of course).

Cheers,

1 Like