Copy to CPU

Description

This program illustrates as simply as possible how to send packets to CPU (e.g. to a controller).

The P4 program does the following:

  • incoming packets are mirrored to the CPU port using the clone_ingress_pkt_to_egress action primitive
  • packets mirrored to CPU are encapsulated with a custom cpu_header which includes 2 fields: device (1 byte, set to 0) and reason (one byte, set to 0xab)
  • the original packet is dropped in the egress pipeline

Take a look at the [P4 code] (p4src/copy_to_cpu.p4). The program is very short and should be easy to understand. You will notice that we use a mirror session id of 250 in the program. This number is not relevant in itself, but needs to be consistent between the P4 program and the runtime application.

Running the demo

We provide a small demo to let you test the program. It consists of the following scripts:

  • [run_switch.sh] (run_switch.sh): compile the P4 program and starts the switch, also configures the data plane by running the CLI [commands] (commands.txt)
  • [receive.py] (receive.py): sniff packets on port 3 (veth6) and print a hexdump of them
  • [send_one.py] (send_one.py): send one simple IPv4 packet on port 0 (veth0)

If you take a look at [commands.txt] (commands.txt), you'll notice the following command: mirroring_add 250 3. This means that all the cloned packets with mirror id 250 will be sent to port 3, which is our de facto CPU port. This is the reason why [receive.py] (receive.py) listens for incoming packets on port 3.

To run the demo:

  • start the switch and configure the tables and the mirroring session: sudo ./run_switch.sh
  • start the CPU port listener: sudo python receive.py
  • send packets with sudo python send_one.py. Every time you send one packet, it should be displayed by the listener, encapsulated with our CPU header.

This is a very simple example obviously. Feel free to build upon it. For example, instead of dropping the original packet, you could try to broadcast it out of every non-ingress port to have a working L2 switch. You could also build a L2 controller which receives CPU packets and modifies tables appropriately.