/* -*- P4_16 -*- */
#ifndef PARSERS_P4
#define PARSERS_P4

/* to be included into the parser block */

    state start {
        meta.chk_icmp        = 0;
        meta.chk_icmp6       = 0;
        meta.chk_icmp6_na_ns = 0;
        meta.chk_ipv4        = 0;
        meta.chk_udp_v6      = 0;
        meta.chk_udp_v4      = 0;
        meta.chk_tcp_v6      = 0;
        meta.chk_tcp_v4      = 0;
        meta.v4sum           = 0;
        meta.v6sum           = 0;
        meta.headerdiff      = 0;

        packet.extract(hdr.ethernet);
        transition select(hdr.ethernet.ethertype){
            TYPE_IPV4: ipv4;
            TYPE_IPV6: ipv6;
            TYPE_ARP: arp;

            default: accept;
        }
    }

    state ipv4 {
        packet.extract(hdr.ipv4);
		meta.length_without_ip_header = 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.length_without_ip_header = hdr.ipv6.payload_length;

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

    state icmp6 {
        packet.extract(hdr.icmp6);
        transition select(hdr.icmp6.type) {
            ICMP6_NS: icmp6_neighbor_solicitation;
            default: accept;
        }
    }

    state icmp6_neighbor_solicitation {
        packet.extract(hdr.icmp6_na_ns);

        /* BUG: This MIGHT fail */
        packet.extract(hdr.icmp6_option_link_layer_addr);

        transition accept;
    }

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

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

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

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


#endif
