[P4-dev] VL field bitwidth needs to be a multiple of 8

Antonin Bas antonin at barefootnetworks.com
Wed Jul 19 21:43:41 EDT 2017


This part shouldn't change. Only the first reference to ipv4, $valid$ (in the parser JSON specification) should be modified in the way I described.
If you claim there is no such reference in your JSON (which would be surprising based on your logs) then you should send us your P4 program and the generated JSON.
________________________________
From: Regis Martins <regisftm at gmail.com>
Sent: Wednesday, July 19, 2017 6:34:27 PM
To: Antonin Bas
Cc: p4-dev
Subject: Re: [P4-dev] VL field bitwidth needs to be a multiple of 8

Hi Antonin,

Here is what I found in the .json:

          "expression" : {
            "type" : "expression",
            "value" : {
              "op" : "and",
              "left" : {
                "type" : "expression",
                "value" : {
                  "op" : "==",
                  "left" : {
                    "type" : "field",
                    "value" : ["ipv4", "$valid$"]
                  },
                  "right" : {
                    "type" : "hexstr",
                    "value" : "0x01"
                  }
                }
              },
              "right" : {
                "type" : "expression",
                "value" : {
                  "op" : ">",
                  "left" : {
                    "type" : "field",
                    "value" : ["ipv4", "ttl"]
                  },
                  "right" : {
                    "type" : "hexstr",
                    "value" : "0x00"


I'm using P4C to generate it with the following params:

/usr/local/bin/p4c --target bmv2-ss-p4org -x p4-14 p4src/task_9.p4 -o p4prog

I'm not sure how to change it exactly...

​Thank you,

Regis Martins


On Wed, Jul 19, 2017 at 10:16 PM, Antonin Bas <antonin at barefootnetworks.com<mailto:antonin at barefootnetworks.com>> wrote:
That looks like another issue with the generated JSON. Each header has a $valid$ field added by the compiler which can be read to check if a header is valid. However, this is a read-only field. Here the JSON code tries to set that field to 1 to make the ipv4 header valid, but because the field is read-only, it has no effect. The ipv4 header is therefore not considered valid. The bmv2 implementation evaluates invalid fields as "00...0" in table lookups, which explains the logs that you are seeing (and also why the checksum verification is skipped).

I suggest that you open an issue on p4lang/p4c describing this issue.

I have yet another workaround for you but it requires you to modify the JSON file by hand :)

Locate the following:
            {
              "parameters" : [
                {
                  "type" : "field",
                  "value" : ["ipv4", "$valid$"]
                },
                {
                  "type" : "expression",
                  "value" : {
                    "type" : "expression",
                    "value" : {
                      "op" : "b2d",
                      "left" : null,
                      "right" : {
                        "type" : "bool",
                        "value" : true
                      }
                    }
                  }
                }
              ],
              "op" : "set"
            }

And replace it with:
            {
              "parameters" : [
                {
                  "op" : "add_header",
                  "parameters" : [{"type" : "header", "value" : "ipv4"}]
                }
              ],
              "op" : "primitive"
            }

Assuming I didn't make a typo, it should work.

On Wed, Jul 19, 2017 at 5:49 PM, Regis Martins <regisftm at gmail.com<mailto:regisftm at gmail.com>> wrote:
​Hello Antonin,

I just tried that...

Here is the output:

[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Processing packet received on port 1
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser 'parser': start
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser state 'start' has no switch, going to default next state
[21:31:05.731] [bmv2] [T] [thread 7478] [33.0] [cxt 0] Bytes parsed: 0
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Extracting header 'eth'
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser state 'parse_eth': key is 0800
[21:31:05.731] [bmv2] [T] [thread 7478] [33.0] [cxt 0] Bytes parsed: 14
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Extracting header 'tmp_hdr'
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'scalars.tmp' from expression, new value is 0
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Extracting variable-sized header 'tmp_hdr_0'
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.$valid$' from expression, new value is 1
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.version' from field 'tmp_hdr.version' (4)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.ihl' from field 'tmp_hdr.ihl' (5)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.diffserv' from field 'tmp_hdr.diffserv' (0)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.totalLen' from field 'tmp_hdr.totalLen' (84)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.id<http://ipv4.id>' from field 'tmp_hdr.id<http://tmp_hdr.id>' (58185)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.flags' from field 'tmp_hdr.flags' (2)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.fragOffset' from field 'tmp_hdr.fragOffset' (0)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.ttl' from field 'tmp_hdr.ttl' (64)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.protocol' from field 'tmp_hdr.protocol' (1)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.hdrChecksum' from field 'tmp_hdr.hdrChecksum' (16972)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.srcAddr' from field 'tmp_hdr.srcAddr' (167772170)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.dstAddr' from field 'tmp_hdr.dstAddr' (167772426)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser set: setting field 'ipv4.options_ipv4' from field 'tmp_hdr_0.options_ipv4' (0)
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser state 'parse_ipv4': key is 01
[21:31:05.731] [bmv2] [T] [thread 7478] [33.0] [cxt 0] Bytes parsed: 34
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Extracting header 'icmp'
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser state 'parse_icmp' has no switch, going to default next state
[21:31:05.731] [bmv2] [T] [thread 7478] [33.0] [cxt 0] Bytes parsed: 38
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Extracting header 'payld'
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser state 'parse_payld' has no switch, going to default next state
[21:31:05.731] [bmv2] [T] [thread 7478] [33.0] [cxt 0] Bytes parsed: 46
[21:31:05.731] [bmv2] [T] [thread 7478] [33.0] [cxt 0] Skipping checksum 'cksum' verification because target field invalid
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Parser 'parser': end
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Pipeline 'ingress': start
[21:31:05.731] [bmv2] [T] [thread 7478] [33.0] [cxt 0] p4src/task_9.p4(201) Condition "and" is true
[21:31:05.731] [bmv2] [T] [thread 7478] [33.0] [cxt 0] Applying table 'set_table'
[21:31:05.731] [bmv2] [D] [thread 7478] [33.0] [cxt 0] Looking up key:
* ipv4.srcAddr        : 00000000


​For some weird reason, set field is not working for ipv4.srcAddr... that should be * ipv4.srcAddr        : 0a00000a

If I remove the options_ipv4 field and the length and max_length parameters it works fine...

Any other advice?

Thank you,


Regis Martins


On Wed, Jul 19, 2017 at 8:06 PM, Regis Martins <regisftm at gmail.com<mailto:regisftm at gmail.com>> wrote:
Got it!

Let me test it.

Thanks again Antonin! You will have a note of thanks on my thesis! :)

Regards,

Regis Martins


On Wed, Jul 19, 2017 at 7:59 PM, Antonin Bas <antonin at barefootnetworks.com<mailto:antonin at barefootnetworks.com>> wrote:
Looks like a p4c-bm2-ss compiler bug to me. I opened a Github issue: https://github.com/p4lang/p4c/issues/781
Your P4 program is correct, but the generated bmv2 JSON is not. As a workaround (while waiting for the issue to be fixed), you may be able to replace (ihl << 2) with ((ihl << 2) - 20) * 8. This is no longer correct P4, but will leverage the p4c-bm2-ss bug to get your program running on bmv2.

On Wed, Jul 19, 2017 at 3:18 PM, Regis Martins <regisftm at gmail.com<mailto:regisftm at gmail.com>> wrote:
Hello people!

I'm trying to create a variable length field on my ipv4 header, as following:

...

header_type ipv4_t {
    fields {
        version     : 4;
        ihl         : 4;
        diffserv    : 8;
        totalLen    : 16;
        id          : 16;
        flags       : 3;
        fragOffset  : 13;
        ttl         : 8;
        protocol    : 8;
        hdrChecksum : 16;
        srcAddr     : 32;
        dstAddr     : 32;
        options_ipv4: *;
    }
    length          : (ihl << 2);
    max_length      : 60;
}


...


The compilation works fine, however the fist packet_in (it is a ping), abends the bmv2 with the following message:

[19:05:52.601] [bmv2] [D] [thread 6991] [33.0] [cxt 0] Parser 'parser': start
[19:05:52.601] [bmv2] [D] [thread 6991] [33.0] [cxt 0] Parser state 'start' has no switch, going to default next state
[19:05:52.601] [bmv2] [T] [thread 6991] [33.0] [cxt 0] Bytes parsed: 0
[19:05:52.601] [bmv2] [D] [thread 6991] [33.0] [cxt 0] Extracting header 'eth'
[19:05:52.601] [bmv2] [D] [thread 6991] [33.0] [cxt 0] Parser state 'parse_eth': key is 0800
[19:05:52.601] [bmv2] [T] [thread 6991] [33.0] [cxt 0] Bytes parsed: 14
[19:05:52.601] [bmv2] [D] [thread 6991] [33.0] [cxt 0] Extracting header 'tmp_hdr'
[19:05:52.601] [bmv2] [D] [thread 6991] [33.0] [cxt 0] Parser set: setting field 'scalars.tmp' from expression, new value is 4
[19:05:52.601] [bmv2] [D] [thread 6991] [33.0] [cxt 0] Extracting variable-sized header 'tmp_hdr_0'
simple_switch: parser.cpp:288: virtual void bm::ParserOpExtractVL::operator()(bm::Packet*, const char*, size_t*) const: Assertion `nbits % 8 == 0 && "VL field bitwidth needs to be a multiple of 8"' failed.

Any clue about what is happening?

Please, let me know if there you need further information...

Regards,

Regis Martins

_______________________________________________
P4-dev mailing list
P4-dev at lists.p4.org<mailto:P4-dev at lists.p4.org>
http://lists.p4.org/mailman/listinfo/p4-dev_lists.p4.org



--
Antonin





--
Antonin

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.p4.org/pipermail/p4-dev_lists.p4.org/attachments/20170720/567f2c51/attachment-0002.html>


More information about the P4-dev mailing list