/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.
 */

#include <core.p4>
#include <v1model.p4>
#include "include/defines.p4"
#include "include/headers.p4"

struct metadata_t {
    intrinsic_metadata_t intrinsic_metadata;
    ecmp_group_id_t ecmp_group_id;
}

#include "include/parsers.p4"
#include "include/port_counters.p4"
#include "include/checksums.p4"
#include "include/actions.p4"
#include "include/packet_io.p4"

control ingress(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t standard_metadata) {
    direct_counter(CounterType.packets) table0_counter;
    direct_counter(CounterType.packets) ecmp_counter;

    action do_ecmp(ecmp_group_id_t ecmp_group_id) {
        meta.ecmp_group_id = ecmp_group_id;
    }

    table table0 {
        /*
        Disabling timeout here as P4runtime doesn't allow setting timeouts.
        This way the FlowRuleTranslator will produce instances of PiTableEntry without timeout.
        */
        support_timeout = false;
        key = {
            standard_metadata.ingress_port : ternary;
            hdr.ethernet.dstAddr           : ternary;
            hdr.ethernet.srcAddr           : ternary;
            hdr.ethernet.etherType         : ternary;
        }
        actions = {
            set_egress_port(standard_metadata);
            send_to_cpu(standard_metadata);
            do_ecmp();
            drop(standard_metadata);
        }
        counters = table0_counter;
        default_action = drop(standard_metadata);
    }

    action_selector(HashAlgorithm.crc16, 32w64, 32w16) ecmp_selector;
    table ecmp {
        support_timeout = false;
        key = {
            meta.ecmp_group_id             : exact;
            // Not for matching.
            // Inputs to the hash function of the action selector.
            hdr.ipv4.srcAddr               : selector;
            hdr.ipv4.dstAddr               : selector;
            hdr.ipv4.protocol              : selector;
            hdr.tcp.srcPort                : selector;
            hdr.tcp.dstPort                : selector;
            hdr.udp.srcPort                : selector;
            hdr.udp.dstPort                : selector;
        }
        actions = {
            set_egress_port(standard_metadata);
        }
        implementation = ecmp_selector;
        counters = ecmp_counter;
    }

    PacketIoIngressControl() packet_io_ingress_control;
    PortCountersControl() port_counters_control;

    apply {
        packet_io_ingress_control.apply(hdr, standard_metadata);
        if (!hdr.packet_out.isValid()) {
            switch(table0.apply().action_run) {
                do_ecmp: {
                    ecmp.apply();
                }
            }
        }

        port_counters_control.apply(hdr, meta, standard_metadata);
    }
}

control egress(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t standard_metadata) {

    PacketIoEgressControl() packet_io_egress_control;
    apply {
        packet_io_egress_control.apply(hdr, standard_metadata);
    }
}

V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main;
