include <core.p4> include <v1model.p4>

const bit<16> TYPE_IPV4 = 0x800; typedef bit<9> egressSpec_t; typedef bit<48> macAddr_t; typedef bit<32> ip4Addr_t;

header ethernet_t {

macAddr_t dstAddr;
macAddr_t 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;
ip4Addr_t srcAddr;
ip4Addr_t dstAddr;

}

struct metadata { empty }

struct headers {

ethernet_t   ethernet;
ipv4_t       ipv4;

}

parser MyParser(packet_in packet,

            out headers hdr,
            inout metadata meta,
            inout standard_metadata_t standard_metadata) {

state start { transition parse_ethernet; }

state parse_ethernet {
    packet.extract(hdr.ethernet);
    transition select(hdr.ethernet.etherType) {
        TYPE_IPV4: parse_ipv4;
        default: accept;
    }
}

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

}

control MyIngress(inout headers hdr,

              inout metadata meta,
              inout standard_metadata_t standard_metadata) {
action drop() {
    mark_to_drop(standard_metadata);
}

action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) {
    standard_metadata.egress_spec = port;
    hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
    hdr.ethernet.dstAddr = dstAddr;
    hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
}

table ipv4_lpm {
    key = { hdr.ipv4.dstAddr: lpm; }
    actions = { ipv4_forward; drop; NoAction; }
    size = 1024;
    default_action = drop();
}

apply {
    if (hdr.ipv4.isValid()) {
        ipv4_lpm.apply();
    }
}

}

control MyDeparser(packet_out packet, in headers hdr) {

apply {
    packet.emit(hdr.ethernet);
    packet.emit(hdr.ipv4);
}

}

V1Switch( MyParser(), MyIngress(), MyDeparser() ) main;