/*
 * 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 "../define.p4"
#include "../header.p4"
#include "../action.p4"


control Forwarding (
    inout parsed_headers_t hdr,
    inout fabric_metadata_t fabric_metadata,
    inout standard_metadata_t standard_metadata) {

    direct_counter(CounterType.packets_and_bytes) bridging_counter;
    direct_counter(CounterType.packets_and_bytes) mpls_counter;
    direct_counter(CounterType.packets_and_bytes) unicast_v4_counter;
    direct_counter(CounterType.packets_and_bytes) multicast_v4_counter;
    direct_counter(CounterType.packets_and_bytes) unicast_v6_counter;
    direct_counter(CounterType.packets_and_bytes) multicast_v6_counter;
    direct_counter(CounterType.packets_and_bytes) acl_counter;

    action set_next_id(next_id_t next_id) {
        fabric_metadata.next_id = next_id;
    }

    action pop_mpls_and_next(next_id_t next_id) {
        hdr.mpls.setInvalid();
        if (hdr.ipv4.isValid()) {
            hdr.ethernet.ether_type = ETHERTYPE_IPV4;
        } else {
            hdr.ethernet.ether_type = ETHERTYPE_IPV6;
        }
        fabric_metadata.next_id = next_id;
    }

    action push_mpls (mpls_label_t label, bit<3> tc) {
        //Suppose that the maximum number of label is one.
        hdr.mpls.setValid();
        hdr.ethernet.ether_type = ETHERTYPE_MPLS;
        hdr.mpls.label = label;
        hdr.mpls.tc = tc;
        hdr.mpls.bos = 1;
        hdr.mpls.ttl = 64;
    }

    action push_mpls_and_next_v4 (mpls_label_t label,
                                  next_id_t next_id) {
        set_next_id(next_id);
        push_mpls(label, hdr.ipv4.diffserv[7:5]);
    }

    action push_mpls_and_next_v6 (mpls_label_t label, next_id_t next_id) {
        set_next_id(next_id);
        push_mpls(label, hdr.ipv6.traffic_class[7:5]);
    }

    action duplicate_to_controller() {
        fabric_metadata.next_type = NEXT_TYPE_PUNT;
        standard_metadata.egress_spec = CPU_PORT;
    }



    table bridging {
        key = {
            hdr.vlan_tag.vlan_id: exact;
            hdr.ethernet.dst_addr: ternary;
        }

        actions = {
            set_next_id;
        }
        counters = bridging_counter;
    }

    table mpls {
        key = {
            hdr.mpls.label: exact;
        }

        actions = {
            pop_mpls_and_next;
        }
        counters = mpls_counter;
    }

    table unicast_v4 {
        key = {
            hdr.ipv4.dst_addr: lpm;
        }

        actions = {
            set_next_id;
            push_mpls_and_next_v4;
        }
        counters = unicast_v4_counter;
    }

    table multicast_v4 {
        key = {
            hdr.vlan_tag.vlan_id: exact;
            hdr.ipv4.dst_addr: lpm;
        }

        actions = {
            set_next_id;
        }
        counters = multicast_v4_counter;
    }

    table unicast_v6 {
        key = {
            hdr.ipv6.dst_addr: lpm;
        }

        actions = {
            set_next_id;
            push_mpls_and_next_v6;
        }
        counters = unicast_v6_counter;
    }

    table multicast_v6 {
        key = {
            hdr.vlan_tag.vlan_id: exact;
            hdr.ipv6.dst_addr: lpm;
        }

        actions = {
            set_next_id;
        }
        counters = multicast_v6_counter;
    }

    table acl {
        key = {
            standard_metadata.ingress_port: ternary;
            fabric_metadata.ip_proto: ternary;
            hdr.ethernet.dst_addr: ternary;
            hdr.ethernet.src_addr: ternary;
            hdr.ethernet.ether_type: ternary;
            hdr.vlan_tag.vlan_id: ternary;
            hdr.vlan_tag.pri: ternary;
            hdr.mpls.tc: ternary;
            hdr.mpls.bos: ternary;
            hdr.mpls.label: ternary;
            hdr.ipv4.src_addr: ternary;
            hdr.ipv4.dst_addr: ternary;
            hdr.ipv4.protocol: ternary;
            hdr.ipv6.src_addr: ternary;
            hdr.ipv6.dst_addr: ternary;
            hdr.ipv6.next_hdr: ternary;
            hdr.tcp.src_port: ternary;
            hdr.tcp.dst_port: ternary;
            hdr.udp.src_port: ternary;
            hdr.udp.dst_port: ternary;
            hdr.icmp.icmp_type: ternary;
            hdr.icmp.icmp_code: ternary;
        }

        actions = {
            set_next_id;
            duplicate_to_controller;
            drop;
            nop;
        }

        const default_action = nop();
        counters = acl_counter;
    }

    apply {
        if(fabric_metadata.fwd_type == FWD_BRIDGING) bridging.apply();
        else if (fabric_metadata.fwd_type == FWD_MPLS) mpls.apply();
        else if (fabric_metadata.fwd_type == FWD_IPV4_UNICAST) unicast_v4.apply();
        else if (fabric_metadata.fwd_type == FWD_IPV4_MULTICAST) multicast_v4.apply();
        else if (fabric_metadata.fwd_type == FWD_IPV6_UNICAST) unicast_v6.apply();
        else if (fabric_metadata.fwd_type == FWD_IPV6_MULTICAST) multicast_v6.apply();
        acl.apply();
    }
}
