Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Compiler Bug] 'std::out_of_range' #298

Closed
tudang opened this issue Feb 12, 2017 · 2 comments
Closed

[Compiler Bug] 'std::out_of_range' #298

tudang opened this issue Feb 12, 2017 · 2 comments

Comments

@tudang
Copy link

tudang commented Feb 12, 2017

The program test.p4 is compiled successfully without any errors or warnings. However, running bmv2 give me the following error:

/home/bmv2/targets/simple_switch/simple_switch learner.json \
   -i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 --log-console
Thrift port was not specified, will use 9090
Calling target program-options parser
terminate called after throwing an instance of 'std::out_of_range'
 what():  _Map_base::at
// test.p4
#include <core.p4>
#include <v1model.p4>

typedef bit<48> EthernetAddress;
typedef bit<32> IPv4Address;
typedef bit<4> PortId;

const PortId DROP_PORT = 0xF;

header ethernet_t {
    EthernetAddress dstAddr;
    EthernetAddress srcAddr;
    bit<16> etherType;
}

header ipv4_t {
    bit<4> version;
    bit<4> ihl;
    bit<8> diffserv;
    bit<16> totalLen;
    bit<16> identification;
    bit<3> flags;
    bit<13> fragOffset;
    bit<8> ttl;
    bit<8> protocol;
    bit<16> hdrChecksum;
    IPv4Address srcAddr;
    IPv4Address dstAddr;
}

header udp_t {
    bit<16> srcPort;
    bit<16> dstPort;
    bit<16> length_;
    bit<16> checksum;
}


#define MSGTYPE_SIZE    16
#define INSTANCE_SIZE   32
#define ROUND_SIZE      16
#define INSTANCE_COUNT  65536


header myhdr_t {
    bit<MSGTYPE_SIZE>   msgtype;
    bit<INSTANCE_SIZE>  inst;
    bit<ROUND_SIZE>     rnd;
}

struct headers {
    @name("ethernet")
    ethernet_t ethernet;
    @name("ipv4")
    ipv4_t ipv4;
    @name("udp")
    udp_t udp;
    @name("myhdr")
    myhdr_t myhdr;
}

struct ingress_metadata_t {
    bit<ROUND_SIZE> round;
    bit<1> set_drop;
}

struct metadata {
    @name("ingress_metadata")
    ingress_metadata_t   local_metadata;
}

#define ETHERTYPE_IPV4 16w0x0800
#define UDP_PROTOCOL 8w0x11
#define myhdr_PROTOCOL 16w0x8888

parser TopParser(packet_in b, out headers p, inout metadata meta, inout standard_metadata_t standard_metadata) {
    state start {
        transition parse_ethernet;
    }

    state parse_ethernet {
        b.extract(p.ethernet);
        transition select(p.ethernet.etherType) {
            ETHERTYPE_IPV4 : parse_ipv4;
        }
    }

    state parse_ipv4 {
        b.extract(p.ipv4);
        transition select(p.ipv4.protocol) {
            UDP_PROTOCOL : parse_udp;
            default : accept;
        }
    }

    state parse_udp {
        b.extract(p.udp);
        transition select(p.udp.dstPort) {
            myhdr_PROTOCOL : parse_myhdr;
            default : accept;
        }
    }

    state parse_myhdr {
        b.extract(p.myhdr);
        transition accept;
    }
}

control TopDeparser(packet_out packet, in headers hdr) {
    apply {
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);
        packet.emit(hdr.udp);
        packet.emit(hdr.myhdr);
    }
}

control verifyChecksum(in headers hdr, inout metadata meta) {
    Checksum16() ipv4_checksum;
    apply {
        if (hdr.ipv4.hdrChecksum == ipv4_checksum.get({hdr.ipv4.version, hdr.ipv4.ihl, hdr.ipv4.diffserv, hdr.ipv4.totalLen, hdr.ipv4.identification, hdr.ipv4.flags, hdr.ipv4.fragOffset, hdr.ipv4.ttl, hdr.ipv4.protocol, hdr.ipv4.srcAddr, hdr.ipv4.dstAddr }))
            mark_to_drop();
    }
}

control computeChecksum(inout headers hdr, inout metadata meta) {
    Checksum16() ipv4_checksum;
    apply {
        hdr.ipv4.hdrChecksum = ipv4_checksum.get({hdr.ipv4.version, hdr.ipv4.ihl, hdr.ipv4.diffserv, hdr.ipv4.totalLen, hdr.ipv4.identification, hdr.ipv4.flags, hdr.ipv4.fragOffset, hdr.ipv4.ttl, hdr.ipv4.protocol, hdr.ipv4.srcAddr, hdr.ipv4.dstAddr });
    }
}

control egress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {

    action _drop() {
        mark_to_drop();
    }

    table drop_tbl {
        key = { meta.local_metadata.set_drop : exact; }
        actions = {
            _drop;
             NoAction;
        }
        size = 2;
        default_action =  NoAction();
    }

    apply {
      drop_tbl.apply();
    }
}

control ingress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
    register<bit<ROUND_SIZE>>(INSTANCE_COUNT) registerRound;

    action read_round() {
        registerRound.read(meta.local_metadata.round, hdr.myhdr.inst);
    }

    table round_tbl {
        key = {}
        actions = {
            read_round;
        }
        size = 8;
        default_action = read_round;
    }

    apply {
        if (hdr.ipv4.isValid()) {
            if (hdr.myhdr.isValid()) {
                round_tbl.apply();
            }
        }
    }
}

V1Switch(TopParser(), verifyChecksum(), ingress(), egress(), computeChecksum(), TopDeparser()) main;
@mihaibudiu
Copy link
Contributor

The bug is caused by the @name annotation on some struct fields; in particular, the local_metadata field of the metadata struct has an annotation @name("ingress_metadata"). The compiler mistakenly uses in the output json file both names (local_metadata and ingress_metadata) - depending on context. If you remove the annotation the program will load correctly.

Maybe you can remove the annotation until we fix this bug.

mihaibudiu pushed a commit to mihaibudiu/p4c-clone that referenced this issue Feb 12, 2017
ChrisDodd pushed a commit that referenced this issue Feb 13, 2017
* Fix for issue #298

* cpplint fixes
@sethfowler
Copy link
Contributor

A fix for this issue was landed; closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants