p4lang / tutorials

P4 language tutorials
Apache License 2.0
1.31k stars 875 forks source link

I want to know why I can't write the ternary rules to the flow table by python script. #613

Closed hugo0819 closed 1 month ago

hugo0819 commented 1 month ago

I want to modify the mycontroller.py of p4runtime in exercise, to implement ternary instead of lpm. But I ran into some problems to complete a simple forwarding rule. How should I change the code? Or are there any instructions/guidance for that?

    table ipv4_ternary {
        key = {
            hdr.ipv4.dstAddr: ternary;
        }
        actions = {
            ipv4_forward;
            drop;
            NoAction;
        }
        size = 1024;
        default_action = NoAction();
    }
def writeRules(p4info_helper, sw, dst_eth_addr, dst_ip_addr, dst_ip_mask, port):
    table_entry = p4info_helper.buildTableEntry(
        table_name="MyIngress.ipv4_ternary",
        match_fields={
            "hdr.ipv4.dstAddr": (dst_ip_addr, dst_ip_mask)
        },
        action_name="MyIngress.ipv4_forward",
        action_params={
            "dstAddr": dst_eth_addr,
            "port": port
        })
    sw.WriteTableEntry(table_entry)
    print("Installed ternary rule on %s" % sw.name)
writeRules(p4info_helper, sw=s1, dst_eth_addr="08:00:00:00:01:11", 
                 dst_ip_addr="10.0.1.1", dst_ip_mask="255.255.255.0", port=1)

writeRules(p4info_helper, sw=s1, dst_eth_addr="08:00:00:00:02:22",
                 dst_ip_addr="10.0.2.2", dst_ip_mask="255.255.255.0", port=2)

writeRules(p4info_helper, sw=s1, dst_eth_addr="08:00:00:00:03:33", 
                 dst_ip_addr="10.0.3.3", dst_ip_mask="255.255.255.0", port=3)

This is the error message after running it gRPC Error: UNKNOWN:Error received from peer ipv4:127.0.0.1:50051 {grpc_message:"", grpc_status:2, created_time:"2024-05-30T21:40:52.0102443+08:00"}

jafingerhut commented 1 month ago

I would recommend asking such questions at https://forum.p4.org, where there are more people reading, and thus a larger set of people who may answer, than those who follow issues on this Github repository.

hugo0819 commented 1 month ago

I've been trying to fix the problem at https://forum.p4.org from last week, I can read the post but I can't log in. When I click login, it appears that https://dex.opennetworking.org has closed the connection. I have been using proxy network in China, I can access other websites, but I can't log into this website, and I can't solve the network problem.

jafingerhut commented 1 month ago

Thanks for that experience report on forum.p4.org web site. I will ask to see if there are problems at the server end with supporting logins.

jafingerhut commented 1 month ago

Regarding your original question, I have an experiment to suggest, but I do not know in advance whether it will work.

Inside of your writeRules function, replace this:

"hdr.ipv4.dstAddr": (dst_ip_addr, dst_ip_mask)

with the following:

"hdr.ipv4.dstAddr": dst_ip_addr + "&&&" + dst_ip_mask
hugo0819 commented 1 month ago

Thank you very much for your support! I haven't tried it this way, but I have succeeded in other ways. I see from the s1_runtime.log that the priority must be provided and that value&mask==mask must be satisfied while used ternary to match. so I used writeRules(p4info_helper, sw=s1, dst_eth_addr="08:00:00:00:01:11", dst_ip_addr="10.0.1.1", dst_ip_mask="255.255.255.255", port=1, priority=1) success.

However, I don't need to provide priority when I use lpm matching, I also don't need to provide value&mask==mask when I use simple_switch_CLI to entry tables, like table_add MyIngress.ipv4_ternary MyIngress.ipv4_forward 10.0.1.1 255.255.255.0 => 08:00:00:00:01:11 1 1 , I'm still confused about all this.

jafingerhut commented 1 month ago

Most of the tutorials use the P4Runtime API to connect to the simple_switch_grpc process, send table update commands, and read table contents.

simple_switch_CLI does not use the P4Runtime API to do so, but instead a protocol that is custom to the https://github.com/p4lang/behavioral-model project that runs over Thrift. It existed before P4Runtime API even had a specification written for it. It has its own independent set of restrictions, which I believe are not documented anywhere except in its implementation code.

The P4Runtime API has the requirement that value&mask == mask, because then it makes a property called read-write symmetry straightforward to implement. That is, there is only one acceptable way to represent a particular value/mask match condition in P4Runtime API, as opposed to a very large number of equivalent ways with different values but the same mask.

Some APIs enforce that you must meet this condition value&mask == mask, others replace value with value&mask for you under the covers, hiding this requirement from you. It appears that the tutorials repository Python code that reads the s1-runtime.json files does not try to hide this requirement from you, so you must meet the requirement yourself.

Match kind lpm is an abbreviation for "longest prefix match". The priority is always the same as the length of the prefix, with longer prefixes winning over shorter prefixes if more than one entry matches a particular search key. There is NO way to specify a different priority than the prefix length for such tables, neither with simple_switch_CLI nor with P4Runtime API.

These articles might provide details that are useful for you: