# 1 "../p4debug/bug1-bool/static-mapping.p4"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "../p4debug/bug1-bool/static-mapping.p4"
/* -*- P4_16 -*- */
# 1 "/usr/local/share/p4c/p4include/core.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* This is the P4-16 core library, which declares some built-in P4 constructs using P4 */




/// Standard error codes.  New error codes can be declared by users.
error {
    NoError, /// No error.
    PacketTooShort, /// Not enough bits in packet for 'extract'.
    NoMatch, /// 'select' expression has no matches.
    StackOutOfBounds, /// Reference to invalid element of a header stack.
    HeaderTooShort, /// Extracting too many bits into a varbit field.
    ParserTimeout /// Parser execution time limit exceeded.
}

extern packet_in {
    /// Read a header from the packet into a fixed-sized header @hdr and advance the cursor.
    /// May trigger error PacketTooShort or StackOutOfBounds.
    /// @T must be a fixed-size header type
    void extract<T>(out T hdr);
    /// Read bits from the packet into a variable-sized header @variableSizeHeader
    /// and advance the cursor.
    /// @T must be a header containing exactly 1 varbit field.
    /// May trigger errors PacketTooShort, StackOutOfBounds, or HeaderTooShort.
    void extract<T>(out T variableSizeHeader,
                    in bit<32> variableFieldSizeInBits);
    /// Read bits from the packet without advancing the cursor.
    /// @returns: the bits read from the packet.
    /// T may be an arbitrary fixed-size type.
    T lookahead<T>();
    /// Advance the packet cursor by the specified number of bits.
    void advance(in bit<32> sizeInBits);
    /// @return packet length in bytes.  This method may be unavailable on
    /// some target architectures.
    bit<32> length();
}

extern packet_out {
    /// Write @hdr into the output packet, advancing cursor.
    /// @T can be a header type, a header stack, a header_union, or a struct
    /// containing fields with such types.
    void emit<T>(in T hdr);
}

// TODO: remove from this file, convert to built-in
/// Check a predicate @check in the parser; if the predicate is true do nothing,
/// otherwise set the parser error to @toSignal, and transition to the `reject` state.
extern void verify(in bool check, in error toSignal);

/// Built-in action that does nothing.
action NoAction() {}

/// Standard match kinds for table key fields.
/// Some architectures may not support all these match kinds.
/// Architectures can declare additional match kinds.
match_kind {
    /// Match bits exactly.
    exact,
    /// Ternary match, using a mask.
    ternary,
    /// Longest-prefix match.
    lpm
}
# 3 "../p4debug/bug1-bool/static-mapping.p4" 2
# 1 "/usr/local/share/p4c/p4include/v1model.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* P4-16 declaration of the P4 v1.0 switch model */




# 1 "/usr/local/share/p4c/p4include/core.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* This is the P4-16 core library, which declares some built-in P4 constructs using P4 */
# 23 "/usr/local/share/p4c/p4include/v1model.p4" 2

match_kind {
    range,
    // Used for implementing dynamic_action_selection
    selector
}

// Are these correct?
@metadata @name("standard_metadata")
struct standard_metadata_t {
    bit<9> ingress_port;
    bit<9> egress_spec;
    bit<9> egress_port;
    bit<32> clone_spec;
    bit<32> instance_type;
    bit<1> drop;
    bit<16> recirculate_port;
    bit<32> packet_length;
    //
    // @alias is used to generate the field_alias section of the BMV2 JSON.
    // Field alias creates a mapping from the metadata name in P4 program to
    // the behavioral model's internal metadata name. Here we use it to
    // expose all metadata supported by simple switch to the user through
    // standard_metadata_t.
    //
    // flattening fields that exist in bmv2-ss
    // queueing metadata
    @alias("queueing_metadata.enq_timestamp") bit<32> enq_timestamp;
    @alias("queueing_metadata.enq_qdepth") bit<19> enq_qdepth;
    @alias("queueing_metadata.deq_timedelta") bit<32> deq_timedelta;
    @alias("queueing_metadata.deq_qdepth") bit<19> deq_qdepth;
    // intrinsic metadata
    @alias("intrinsic_metadata.ingress_global_timestamp") bit<48> ingress_global_timestamp;
    @alias("intrinsic_metadata.egress_global_timestamp") bit<48> egress_global_timestamp;
    @alias("intrinsic_metadata.lf_field_list") bit<32> lf_field_list;
    @alias("intrinsic_metadata.mcast_grp") bit<16> mcast_grp;
    @alias("intrinsic_metadata.resubmit_flag") bit<32> resubmit_flag;
    @alias("intrinsic_metadata.egress_rid") bit<16> egress_rid;
    /// Indicates that a verify_checksum() method has failed.
    // TODO: this should be deprecated in favor of parser_error
    bit<1> checksum_error;
    @alias("intrinsic_metadata.recirculate_flag") bit<32> recirculate_flag;
    /// Error produced by parsing
    error parser_error;
}

enum CounterType {
    packets,
    bytes,
    packets_and_bytes
}

enum MeterType {
    packets,
    bytes
}

extern counter {
    counter(bit<32> size, CounterType type);
    void count(in bit<32> index);
}

extern direct_counter {
    direct_counter(CounterType type);
    void count();
}

extern meter {
    meter(bit<32> size, MeterType type);
    void execute_meter<T>(in bit<32> index, out T result);
}

extern direct_meter<T> {
    direct_meter(MeterType type);
    void read(out T result);
}

extern register<T> {
    register(bit<32> size);
    void read(out T result, in bit<32> index);
    void write(in bit<32> index, in T value);
}

// used as table implementation attribute
extern action_profile {
    action_profile(bit<32> size);
}

// Get a random number in the range lo..hi
extern void random<T>(out T result, in T lo, in T hi);
// If the type T is a named struct, the name is used
// to generate the control-plane API.
extern void digest<T>(in bit<32> receiver, in T data);

enum HashAlgorithm {
    crc32,
    crc32_custom,
    crc16,
    crc16_custom,
    random,
    identity,
    csum16,
    xor16
}

extern void mark_to_drop();
extern void hash<O, T, D, M>(out O result, in HashAlgorithm algo, in T base, in D data, in M max);

extern action_selector {
    action_selector(HashAlgorithm algorithm, bit<32> size, bit<32> outputWidth);
}

enum CloneType {
    I2E,
    E2E
}

@deprecated("Please use verify_checksum/update_checksum instead.")
extern Checksum16 {
    Checksum16();
    bit<16> get<D>(in D data);
}

/**
Verifies the checksum of the supplied data.
If this method detects that a checksum of the data is not correct it
sets the standard_metadata checksum_error bit.
@param T          Must be a tuple type where all the fields are bit-fields or varbits.
                  The total dynamic length of the fields is a multiple of the output size.
@param O          Checksum type; must be bit<X> type.
@param condition  If 'false' the verification always succeeds.
@param data       Data whose checksum is verified.
@param checksum   Expected checksum of the data; note that is must be a left-value.
@param algo       Algorithm to use for checksum (not all algorithms may be supported).
                  Must be a compile-time constant.
*/
extern void verify_checksum<T, O>(in bool condition, in T data, inout O checksum, HashAlgorithm algo);
/**
Computes the checksum of the supplied data.
@param T          Must be a tuple type where all the fields are bit-fields or varbits.
                  The total dynamic length of the fields is a multiple of the output size.
@param O          Output type; must be bit<X> type.
@param condition  If 'false' the checksum is not changed
@param data       Data whose checksum is computed.
@param checksum   Checksum of the data.
@param algo       Algorithm to use for checksum (not all algorithms may be supported).
                  Must be a compile-time constant.
*/
extern void update_checksum<T, O>(in bool condition, in T data, inout O checksum, HashAlgorithm algo);

/**
Verifies the checksum of the supplied data including the payload.
The payload is defined as "all bytes of the packet which were not parsed by the parser".
If this method detects that a checksum of the data is not correct it
sets the standard_metadata checksum_error bit.
@param T          Must be a tuple type where all the fields are bit-fields or varbits.
                  The total dynamic length of the fields is a multiple of the output size.
@param O          Checksum type; must be bit<X> type.
@param condition  If 'false' the verification always succeeds.
@param data       Data whose checksum is verified.
@param checksum   Expected checksum of the data; note that is must be a left-value.
@param algo       Algorithm to use for checksum (not all algorithms may be supported).
                  Must be a compile-time constant.
*/
extern void verify_checksum_with_payload<T, O>(in bool condition, in T data, inout O checksum, HashAlgorithm algo);
/**
Computes the checksum of the supplied data including the payload.
The payload is defined as "all bytes of the packet which were not parsed by the parser".
@param T          Must be a tuple type where all the fields are bit-fields or varbits.
                  The total dynamic length of the fields is a multiple of the output size.
@param O          Output type; must be bit<X> type.
@param condition  If 'false' the checksum is not changed
@param data       Data whose checksum is computed.
@param checksum   Checksum of the data.
@param algo       Algorithm to use for checksum (not all algorithms may be supported).
                  Must be a compile-time constant.
*/
extern void update_checksum_with_payload<T, O>(in bool condition, in T data, inout O checksum, HashAlgorithm algo);

extern void resubmit<T>(in T data);
extern void recirculate<T>(in T data);
extern void clone(in CloneType type, in bit<32> session);
extern void clone3<T>(in CloneType type, in bit<32> session, in T data);

extern void truncate(in bit<32> length);

// The name 'standard_metadata' is reserved

// Architecture.
// M should be a struct of structs
// H should be a struct of headers or stacks

parser Parser<H, M>(packet_in b,
                    out H parsedHdr,
                    inout M meta,
                    inout standard_metadata_t standard_metadata);

/* The only legal statements in the implementation of the
VerifyChecksum control are: block statements, calls to the
verify_checksum and verify_checksum_with_payload methods,
and return statements. */
control VerifyChecksum<H, M>(inout H hdr,
                             inout M meta);
@pipeline
control Ingress<H, M>(inout H hdr,
                      inout M meta,
                      inout standard_metadata_t standard_metadata);
@pipeline
control Egress<H, M>(inout H hdr,
                     inout M meta,
                     inout standard_metadata_t standard_metadata);

/* The only legal statements in the implementation of the
ComputeChecksum control are: block statements, calls to the
update_checksum and update_checksum_with_payload methods,
and return statements. */
control ComputeChecksum<H, M>(inout H hdr,
                              inout M meta);
@deparser
control Deparser<H>(packet_out b, in H hdr);

package V1Switch<H, M>(Parser<H, M> p,
                       VerifyChecksum<H, M> vr,
                       Ingress<H, M> ig,
                       Egress<H, M> eg,
                       ComputeChecksum<H, M> ck,
                       Deparser<H> dep
                       );
# 4 "../p4debug/bug1-bool/static-mapping.p4" 2

# 1 "../p4debug/bug1-bool/headers.p4" 1
/* -*- P4_16 -*- */



# 1 "/usr/local/share/p4c/p4include/core.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* This is the P4-16 core library, which declares some built-in P4 constructs using P4 */
# 6 "../p4debug/bug1-bool/headers.p4" 2
# 1 "/usr/local/share/p4c/p4include/v1model.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* P4-16 declaration of the P4 v1.0 switch model */
# 7 "../p4debug/bug1-bool/headers.p4" 2

typedef bit<48> mac_addr_t;
typedef bit<32> ipv4_addr_t;
typedef bit<128> ipv6_addr_t;
typedef bit<9> port_t;
typedef bit<16> mcast_t;
typedef bit<16> task_t;


const bit<16> TYPE_IPV4 = 0x0800;
const bit<16> TYPE_IPV6 = 0x86DD;
const bit<16> TYPE_CPU = 0x4242;
const bit<16> TYPE_DEBUG = 0x2323;


const bit<8> PROTO_ICMP = 1;
const bit<8> PROTO_TCP = 6;
const bit<8> PROTO_UDP = 17;
const bit<8> PROTO_ICMP6 = 58;

const bit<8> TCP_SEQ_LEN = 4;

const bit<8> ICMP6_ECHO_REQUEST = 128;
const bit<8> ICMP6_ECHO_REPLY = 129;
const bit<8> ICMP6_NS = 135;
const bit<8> ICMP6_NA = 136;


const task_t TASK_ICMP6_NS = 1;
const task_t TASK_ICMP6_GENERAL = 2;
const task_t TASK_DEBUG = 3;
const task_t TASK_ICMP6_REPLY = 4;


header ethernet_t {
    mac_addr_t dst_addr;
    mac_addr_t src_addr;
    bit<16> ethertype;
}

header ipv4_t {
    bit<4> version;
    bit<4> ihl;
    bit<6> diff_serv;
    bit<2> ecn;
    bit<16> totalLen;
    bit<16> identification;
    bit<3> flags;
    bit<13> fragOffset;
    bit<8> ttl;
    bit<8> protocol;
    bit<16> hdrChecksum;
    ipv4_addr_t src_addr;
    ipv4_addr_t dst_addr;
}

/* https://en.wikipedia.org/wiki/IPv6_packet */
header ipv6_t {
    bit<4> version;
    bit<8> traffic_class;
    bit<20> flow_label;
    bit<16> payload_length;
    bit<8> next_header;
    bit<8> hop_limit;
    ipv6_addr_t src_addr;
    ipv6_addr_t dst_addr;
}

header tcp_t{
    bit<16> src_port;
    bit<16> dst_port;
    int<32> seqNo;
    int<32> ackNo;
    bit<4> data_offset;
    bit<4> res;
    bit<1> cwr;
    bit<1> ece;
    bit<1> urg;
    bit<1> ack;
    bit<1> psh;
    bit<1> rst;
    bit<1> syn;
    bit<1> fin;
    bit<16> window;
    bit<16> checksum;
    bit<16> urgentPtr;
}

header udp_t {
    bit<16> src_port;
    bit<16> dst_port;
    bit<16> payload_length;
    bit<16> checksum;
}

header icmp6_t {
    bit<8> type;
    bit<8> code;
    bit<16> checksum;
}

header icmp_t {
    bit<8> type;
    bit<8> code;
    bit<16> checksum;
    bit<32> rest;
}

header cpu_t {
    task_t task;
    bit<16> ingress_port;
    bit<16> ethertype;
}

struct headers {
    ethernet_t ethernet;
    ipv4_t ipv4;
    ipv6_t ipv6;
    tcp_t tcp;
    udp_t udp;
    icmp6_t icmp6;
    icmp_t icmp;
    cpu_t cpu;
}

struct metadata {
    port_t ingress_port;
    task_t task;
    bit<16> tcp_length;
    bit<32> cast_length;
    bool do_cksum;
}
# 6 "../p4debug/bug1-bool/static-mapping.p4" 2
# 1 "../p4debug/bug1-bool/parsers.p4" 1
/* -*- P4_16 -*- */



# 1 "/usr/local/share/p4c/p4include/core.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* This is the P4-16 core library, which declares some built-in P4 constructs using P4 */
# 6 "../p4debug/bug1-bool/parsers.p4" 2
# 1 "/usr/local/share/p4c/p4include/v1model.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* P4-16 declaration of the P4 v1.0 switch model */
# 7 "../p4debug/bug1-bool/parsers.p4" 2

# 1 "../p4debug/bug1-bool/headers.p4" 1
/* -*- P4_16 -*- */
# 9 "../p4debug/bug1-bool/parsers.p4" 2

parser MyParser(packet_in packet,
                out headers hdr,
                inout metadata meta,
                inout standard_metadata_t standard_metadata) {

    state start {
        packet.extract(hdr.ethernet);
        transition select(hdr.ethernet.ethertype){
            TYPE_IPV4: ipv4;
            TYPE_IPV6: ipv6;
            default: accept;
        }
    }

    state ipv4 {
        packet.extract(hdr.ipv4);
  meta.tcp_length = hdr.ipv4.totalLen - 16w20;

        transition select(hdr.ipv4.protocol){
            PROTO_TCP: tcp;
            PROTO_UDP: udp;
            PROTO_ICMP: icmp;

            default: accept;
        }
    }

    state ipv6 {
        packet.extract(hdr.ipv6);
  meta.tcp_length = hdr.ipv6.payload_length;

        transition select(hdr.ipv6.next_header){
            PROTO_TCP: tcp;
            PROTO_UDP: udp;
            PROTO_ICMP6: icmp6;
            default: accept;
        }
    }

    /* Leaf */
    state tcp {
       packet.extract(hdr.tcp);
       transition accept;
    }

    state udp {
       packet.extract(hdr.udp);
       transition accept;
    }

    state icmp6 {
       packet.extract(hdr.icmp6);
       transition accept;
    }

    state icmp {
       packet.extract(hdr.icmp);
       transition accept;
    }

}

/*************************************************************************
************************  D E P A R S E R  *******************************
*************************************************************************/

control MyDeparser(packet_out packet, in headers hdr) {
    apply {
        /* always */
        packet.emit(hdr.ethernet);

        /* only if information is sent to the controller */
        packet.emit(hdr.cpu);

        /* either */
        packet.emit(hdr.ipv4);
        packet.emit(hdr.ipv6);

        /* either */
        packet.emit(hdr.tcp);
        packet.emit(hdr.udp);
        packet.emit(hdr.icmp);
        packet.emit(hdr.icmp6);
    }
}
# 7 "../p4debug/bug1-bool/static-mapping.p4" 2
# 1 "../p4debug/bug1-bool/checksums.p4" 1
/* -*- P4_16 -*- */



# 1 "/usr/local/share/p4c/p4include/core.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* This is the P4-16 core library, which declares some built-in P4 constructs using P4 */
# 6 "../p4debug/bug1-bool/checksums.p4" 2
# 1 "/usr/local/share/p4c/p4include/v1model.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* P4-16 declaration of the P4 v1.0 switch model */
# 7 "../p4debug/bug1-bool/checksums.p4" 2

# 1 "../p4debug/bug1-bool/headers.p4" 1
/* -*- P4_16 -*- */
# 9 "../p4debug/bug1-bool/checksums.p4" 2

/*************************************************************************
*************   C H E C K S U M    V E R I F I C A T I O N   *************
*************************************************************************/

control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
    apply {}
}

/*************************************************************************
**************   C H E C K S U M    C O M P U T A T I O N   **************
*************************************************************************/

control MyComputeChecksum(inout headers hdr, inout metadata meta) {
    apply {
        update_checksum_with_payload(meta.do_cksum,
    {
                hdr.ipv6.src_addr, /* 128 */
     hdr.ipv6.dst_addr, /* 128 */
                meta.cast_length, /* 32 */
                24w0, /* 24 0's */
                PROTO_ICMP6 /* 8 */
            },
            hdr.icmp6.checksum,
            HashAlgorithm.csum16
        );
    }
}
# 8 "../p4debug/bug1-bool/static-mapping.p4" 2
# 1 "../p4debug/bug1-bool/settings.p4" 1
/* -*- P4_16 -*- */
/* table sizes, register widths, and such */



# 1 "/usr/local/share/p4c/p4include/core.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* This is the P4-16 core library, which declares some built-in P4 constructs using P4 */
# 7 "../p4debug/bug1-bool/settings.p4" 2
# 1 "/usr/local/share/p4c/p4include/v1model.p4" 1
/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* P4-16 declaration of the P4 v1.0 switch model */
# 8 "../p4debug/bug1-bool/settings.p4" 2
# 9 "../p4debug/bug1-bool/static-mapping.p4" 2


/*************************************************************************
**************  I N G R E S S   P R O C E S S I N G   *******************
*************************************************************************/

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

    /********************** ACTIONS ***********************************/

    action drop() {
        mark_to_drop();
    }

 action set_egress_port (port_t out_port) {
        standard_metadata.egress_spec = out_port;
 }

    action controller_debug() {
        meta.task = TASK_DEBUG;
        meta.ingress_port = standard_metadata.ingress_port;
        clone3(CloneType.I2E, 100, meta);
    }

    action controller_reply(task_t task) {
        meta.task = task;
        meta.ingress_port = standard_metadata.ingress_port;
        clone3(CloneType.I2E, 100, meta);
    }

    action multicast_pkg(mcast_t mcast_grp) { /* Output PKG on correct ports (plural) */
        standard_metadata.mcast_grp = mcast_grp;
    }

    action icmp6_neighbor_solicitation(ipv6_addr_t addr) {
        /* egress = ingress */
        standard_metadata.egress_spec = standard_metadata.ingress_port;

        hdr.ipv6.dst_addr = hdr.ipv6.src_addr;
        hdr.ipv6.src_addr = addr;
        hdr.icmp6.type = ICMP6_NA;
    }

    action icmp6_echo_reply() {
        mac_addr_t mac_tmp = hdr.ethernet.dst_addr;
        hdr.ethernet.dst_addr = hdr.ethernet.src_addr;
        hdr.ethernet.src_addr = mac_tmp;

        ipv6_addr_t addr_tmp = hdr.ipv6.dst_addr;
        hdr.ipv6.dst_addr = hdr.ipv6.src_addr;
        hdr.ipv6.src_addr = addr_tmp;

        hdr.icmp6.type = ICMP6_ECHO_REPLY;

        meta.do_cksum = true;
        meta.cast_length = (bit<32>) hdr.ipv6.payload_length;
    }

    /* this needs SESSIONS!!
    - icmp6: (src addr, dst addr, ID??, )
    - tcp: (src port, dst port, dst_addr, src addr)
    - udp: (src port, dst port, dst_addr, src addr)
    */
    // action nat64_static(ipv4_addr_t nataddr, ipv6_addr_t nat64_prefix) {
    //     hdr.ipv4.dst_addr = hdr.ipv6.dst_addr - nat64_prefix;
    //     hdr.ipv4.dst_addr = hdr.ipv6.dst_addr - nat64_prefix;
    // }

    /********************** Reply to NDP for US ***********************************/
    table ndp_answer {
        key = {
            hdr.ipv6.dst_addr: exact; /* our multicast embedded mac address */
            hdr.icmp6.type: exact;
        }
        actions = {
            controller_debug;
            icmp6_neighbor_solicitation;
            NoAction;
        }
        size = 64;
        default_action = NoAction;
    }

    /********************** debugging / general support ***********************************/

    table port2mcast {
        key = {
            standard_metadata.ingress_port : exact;
        }
        actions = {
   multicast_pkg;
            controller_debug;
            NoAction;
        }
        size = 64;
        default_action = NoAction;
//        default_action = controller_debug;
    }

    /* Handle multicast registration of NDP */
    table addr2mcast {
        key = {
            hdr.ipv6.dst_addr: exact;
        }
        actions = {
   multicast_pkg;
            controller_debug;
            NoAction;
        }
        size = 64;
        default_action = NoAction;
//        default_action = controller_debug;
    }

    /********************** NDP support ***********************************/


    table ndp {
        key = {
            hdr.ipv6.dst_addr: lpm;
            standard_metadata.ingress_port : exact;
        }
        actions = {
   multicast_pkg;
            controller_debug;
            NoAction;
        }
        size = 64;
//        default_action = NoAction;
        default_action = controller_debug;
    }


    /********************** ADDRESS TABLES ***********************************/
    action icmp6_answer() {

        if(hdr.icmp6.isValid()) {
            if(hdr.icmp6.code == ICMP6_ECHO_REQUEST) {
                ipv6_addr_t tmp = hdr.ipv6.src_addr;
                hdr.ipv6.src_addr = hdr.ipv6.dst_addr;
                hdr.ipv6.dst_addr = tmp;
                hdr.icmp6.code = ICMP6_ECHO_REPLY;
            }
        }

        /* do something:
        - change src/dst
        - change type
        */
    }


 /********************** ROUTING (egress definiton) TABLES ***********************************/

    table v6_addresses {
        key = {
            hdr.ipv6.dst_addr: exact;
        }
        actions = {
            controller_debug;
            controller_reply;
            icmp6_echo_reply;
            NoAction;
        }
        size = 64;
        default_action = NoAction;

    }

    table v6_networks {
        key = {
            hdr.ipv6.dst_addr: lpm;
        }
        actions = {
   set_egress_port;
            controller_debug;
            controller_reply;
            NoAction;
        }
        size = 64;
        default_action = NoAction;
    }

    table v4_networks {
        key = {
            hdr.ipv4.dst_addr: lpm;
        }
        actions = {
   set_egress_port;
            NoAction;
        }
        size = 64;
        default_action = NoAction;
    }

 /********************** APPLYING TABLES ***********************************/
    apply {
        if(hdr.ipv6.isValid()) {
            /* FIXME: structure / use .hit to do logic */
            // ndp_answer.apply();
            //ndp.apply(); /* flood or if it is us - answer */

            v6_addresses.apply();
            v6_networks.apply();
        }
        if(hdr.ipv4.isValid()) {
            v4_networks.apply();
        }
    }
}

/*************************************************************************
****************  E G R E S S   P R O C E S S I N G   *******************
*************************************************************************/

control MyEgress(inout headers hdr,
                 inout metadata meta,
                 inout standard_metadata_t standard_metadata) {
 apply {
        // ingress clone
        if (standard_metadata.instance_type == 1){
            hdr.cpu.setValid();
            hdr.cpu.task = meta.task;
            hdr.cpu.ethertype = hdr.ethernet.ethertype;
            hdr.cpu.ingress_port = (bit<16>)meta.ingress_port;

            hdr.ethernet.ethertype = TYPE_CPU;
        }
 }
}

/*************************************************************************
***********************  S W I T C H  *******************************
*************************************************************************/

V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;


        //     truncate((bit<32>)22); //ether+cpu header
