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

Antonin Bas antonin at barefootnetworks.com
Wed Jul 19 21:16:07 EDT 2017


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> 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' from field '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> 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> 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>
>>> 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
>>>> 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/20170719/f6305033/attachment-0002.html>


More information about the P4-dev mailing list