/* -*- P4_16 -*- */
#ifndef HEADERS_P4
#define HEADERS_P4

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

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;
}

#endif