Real time Controller

Hey there while searching for python based controller for my p4 code all controller seems to be using the utils folder files and creating the mininet based codes but what should I do such that I can process packets from my real ports instead of the mininet ones.

Also if possible how to convert the mininet implementations to non-mininet implementations like I could pass my real ports in it.

Look here, install the bmv2 switch according to the link below.
There are also some information on how to populate the tables and compile your code using the p4c compiler.

then you can start your switch and attach it to physical interface using the command

sudo ./simple_switch -i 0@<iface0> -i 1@<iface1> <path to JSON file>

however, if you want to attach your interface to one of the switches in the mininet, one way to do it is to find the file p4_mininet.py and inside the start function you can add these lines:

        """ This is to attach Switch S0 to a physical interface for
            communication with external hosts """
        if self.device_id == 0:
            args.extend(['-i', str(10) + "@" + "eth100"])

replace 0 with the id of switch you are interested in and replace eth100 with the name of interface you want to attach.

this way every time you run the mininet the interface gets attached automatically.
another more dynamic way to do it is via the simple_switch_CLI.

start a CLI session by running
simple_switch_CLI --thrift-port 9090

replace 9090 with the thrift port of the switch which is usually 9090 + switch id

then you can run the command port_add

RuntimeCmd: help port_add
Add a port to the switch (behavior depends on device manager used): port_add <iface_name> <port_num> [pcap_path]

Hey thanks for the answer.
I have already installed all necessary requirements.

And thanks for the suggestion for integrating real ports with mininet but,

I probably wasn’t clear while writing I want to run a simple_switch_grpc bmv2 P4 switch on which I wanted to install rules,etc using the controller.
What I mean is where can I find a controller documenation, example with support for real ports instead of mininet like I don’t want mininet in it [all examples seems to have mininet in it].

I can suggest you these links, they might be helpful.

Hey thanks for the suggestion,
I want to use a python controller like
tutorials/exercises/p4runtime/mycontroller.py at master · p4lang/tutorials (github.com)
but without the mininet part.
Can you suggest me regarding this.

The example Controller that you posted does not have a mininet part.

You are right that this controller doesn’t have mininet part in particular but the overall example
tutorials/exercises/p4runtime at master · p4lang/tutorials (github.com)
when makefile is executed is running on mininet.

So what I need is proper example where I can start an simple_switch_grpc switch on bmv2 with my real hardware ports like eth0,eth1 as interfaces and then install rules on it using p4runtime controller.

You can start a simple switch process with

sudo simple_switch_grpc -i 1@ens16 -i 2@ens17 --device-id 0 --no-p4 --thrift-port 9090 -- --grpc-server-addr 0.0.0.0:50051 --cpu-port 16

and simply pass your real interfaces with -i

Don’t forget to change the grpc port when you start multiple bmv2 instances.

Then you can configure the switch via p4runtime as usual by starting your controller in a separate terminal.

From the point of view of the controller there is no difference whether the bmv2 is used with virtual interfaces (mininet) or real interfaces. So you can program your controller as usual, you just have to start the bmv2 processes before (which is done automatically if you use the mininet environment).

Just have a look at the run_exercise.py that is used to build the mininet topology, there you will find how the bmv2‘s are created.

Hey thanks for the quick reply it seems like you are suggesting P4Runtime CLI for controller but I want to make an python controller file as mentioned above.

No… you can write your controller as usual in python …

Just a quick doubt say suppose in the following example
demian91/Simple-P4runtime-Controller: Simple P4Runtime controller demonstrating the packet-in/packet-out functionality (github.com)

as given there is controller.py for controller and then there is run_mininet.py which starts the p4 switch.

So if I run the command

sudo simple_switch_grpc -i 1@ens16 -i 2@ens17 --device-id 0 --no-p4 --thrift-port 9090 – --grpc-server-addr 0.0.0.0:50051 --cpu-port 16

Will it be the same what we are doing in the run_mininet.py and if not can you please tell me the parts that I need to implement more in the controller.py for a functional controller.

The command starts a bmv2 process, passes the specified interfaces to it, and tells the bmv2 on which port it should run a grpc server… Thats it.
Then you can connect with your controller to the bmv2 and configure it as you like.

You are very vague with “for a functional controller”. It’s up to you what you consider a functional controller, i.e., what it has to configure on your bmv2.

Hey sorry if my explanation feels vague, for now I just want to make a simple switch which should do basic forwading

So, I did run the command

sudo simple_switch_grpc -i 1@wlx0c0e761be19c -i 2@enp2s0 --device-id 0 --no-p4 --log-console --thrift-port 9090 – --grpc-server-addr 0.0.0.0:50051

and then in another terminal I created a controller which just connects to the switch

controller.py

import argparse
import grpc
import os
import sys
from time import sleep
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "utils/"))
import bmv2
from switch import ShutdownAllSwitchConnections
from utils.convert import encodeNum
import helper

def printGrpcError(e):
    print("gRPC Error:", e.details(), end="")
    status_code = e.code()
    print("(%s)" % status_code.name, end="")
    traceback = sys.exc_info()[2]
    print("[%s:%d]" % (traceback.tb_frame.f_code.co_filename, traceback.tb_lineno))


def main(p4info_file_path, bmv2_file_path):
    # Instantiate a P4Runtime helper from the p4info file
    p4info_helper = helper.P4InfoHelper(p4info_file_path)

    try:
        # Create a switch connection object for s1 and s2;
        # this is backed by a P4Runtime gRPC connection.
        # Also, dump all P4Runtime messages sent to switch to given txt files.
        s1 = bmv2.Bmv2SwitchConnection(
            name="s0",
            address="0.0.0.0:50051",
            device_id=0,
            proto_dump_file="p4runtime.log",
        )

        # Send master arbitration update message to establish this controller as
        # master (required by P4Runtime before performing any other write operation)

        if s1.MasterArbitrationUpdate() == None:
            print("Failed to establish the connection")

        # Install the P4 program on the switches
        s1.SetForwardingPipelineConfig(
            p4info=p4info_helper.p4info, bmv2_json_file_path=bmv2_file_path
        )
        print("Installed P4 Program using SetForwardingPipelineConfig on s1")
        
    except KeyboardInterrupt:
        print(" Shutting down.")
    except grpc.RpcError as e:
        printGrpcError(e)

    ShutdownAllSwitchConnections()



if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="P4Runtime Controller")
    parser.add_argument(
        "--p4info",
        help="p4info proto in text format from p4c",
        type=str,
        action="store",
        required=False,
        default="./firmeware.p4info.txt",
    )
    parser.add_argument(
        "--bmv2-json",
        help="BMv2 JSON file from p4c",
        type=str,
        action="store",
        required=False,
        default="./simple.json",
    )
    args = parser.parse_args()

    if not os.path.exists(args.p4info):
        parser.print_help()
        print("\np4info file %s not found!" % args.p4info)
        parser.exit(1)
    if not os.path.exists(args.bmv2_json):
        parser.print_help()
        print("\nBMv2 JSON file %s not found!" % args.bmv2_json)
        parser.exit(2)
    main(args.p4info, args.bmv2_json)

With command

python3 s_controller.py --p4info basic.p4.p4info.txt --bmv2-json basic.json

and it gives the output

Installed P4 Program using SetForwardingPipelineConfig on s1

So I am assuming the p4 program is installed correctly on switch and now I can write further rules right?

I have other doubt when we are passing the p4info file to the switch are the tables being auto installed or I have to custom add table entries in it.

And If the above is correct how can I verify the flow of packets I tried reading through the log console but the sheer no. of packets information is too much for me to process so is there any simple way?

I strongly suggest that you make the P4 tutorials.

The p4info file only tells your controller the structure of the tables; it does not contain table entries, that’s the job of your controller.

Here is a posting linking to a recently-published example of a P4 program that runs on the BMv2 software switch, and a controller program written in Python, that does not use Mininet: A simple P4 program plus controller in Python for demonstrating PacketIn messages from switch to controller