/* -*- P4_16 -*- */
#include <core.p4>
#include <tna.p4>
/*************************************************************************
************* C O N S T A N T S A N D T Y P E S *******************
**************************************************************************/
const bit<16> ETHERTYPE_TPID = 0x8100;
const bit<16> ETHERTYPE_IPV4 = 0x0800;
const bit<8> PROTOCOL_UDP = 0x11;
const bit<48> ENCAP_MAC_SRC = 0xac1f6b62b9fe;
const bit<48> ENCAP_MAC_DST = 0xac1f6b62b967;
const bit<32> ENCAP_IP_SRC = 0x0A620BFE;
const bit<32> ENCAP_IP_DST = 0x0A620B04;
const bit<16> ENCAP_UDP_DST = 0xD431; //54321
/* Table Sizes */
const int IPV4_HOST_SIZE = 65536;
const int IPV4_LPM_SIZE = 12288;
/*************************************************************************
*********************** H E A D E R S *********************************
*************************************************************************/
/* Define all the headers the program will recognize */
/* The actual sets of headers processed by each gress can differ */
/* Standard ethernet header */
header ethernet_h {
bit<48> dstAddr;
bit<48> srcAddr;
bit<16> etherType;
}
header ipv4_h {
bit<4> version;
bit<4> ihl;
bit<6> dscp;
bit<2> ecn;
bit<16> totalLen;
bit<16> identification;
bit<3> flags;
bit<13> fragOffset;
bit<8> ttl;
bit<8> protocol;
bit<16> hdrChecksum;
bit<32> srcAddr;
bit<32> dstAddr;
}//20 bytes
header udp_h {
bit<16> srcPort;
bit<16> dstPort;
bit<16> _length;
bit<16> checksum;
}
/*************************************************************************
************** I N G R E S S P R O C E S S I N G *******************
*************************************************************************/
/*********************** H E A D E R S ************************/
struct my_ingress_headers_t {
ethernet_h ethernet;
ipv4_h ipv4;
udp_h udp;
}
/****** G L O B A L I N G R E S S M E T A D A T A *********/
struct my_ingress_metadata_t {
}
/*********************** P A R S E R **************************/
parser IngressParser(packet_in pkt,
/* User */
out my_ingress_headers_t hdr,
out my_ingress_metadata_t meta,
/* Intrinsic */
out ingress_intrinsic_metadata_t ig_intr_md)
{
/* This is a mandatory state, required by Tofino Architecture */
state start {
pkt.extract(ig_intr_md);
pkt.advance(PORT_METADATA_SIZE);
transition parse_ethernet;
}
state parse_ethernet {
pkt.extract(hdr.ethernet);
transition select(hdr.ethernet.etherType) {
ETHERTYPE_IPV4: parse_ipv4;
default: accept;
}
}
state parse_ipv4 {
pkt.extract(hdr.ipv4);
transition select(hdr.ipv4.protocol) {
PROTOCOL_UDP: parse_udp;
default: accept;
}
}
state parse_udp {
pkt.extract(hdr.udp);
transition accept;
}
}
/***************** M A T C H - A C T I O N *********************/
control Ingress(
/* User */
inout my_ingress_headers_t hdr,
inout my_ingress_metadata_t meta,
/* Intrinsic */
in ingress_intrinsic_metadata_t ig_intr_md,
in ingress_intrinsic_metadata_from_parser_t ig_prsr_md,
inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md,
inout ingress_intrinsic_metadata_for_tm_t ig_tm_md)
{
action drop_l2() {
ig_dprsr_md.drop_ctl = 1;
}
/*action send_l2(PortId_t port) {
ig_tm_md.ucast_egress_port = port;
}
table forward_l2 {
key = { hdr.ethernet.dst_addr : exact; }
actions = { send_l2; drop_l2; }
default_action = send_l2(46);
size = IPV4_LPM_SIZE;
}*/
Random<bit<11>>() randomNum;
apply {
bit<11> num = randomNum.get();
if (num < 102) { // forward 1/10
ig_tm_md.ucast_egress_port = (bit<9>)46;
}
else {
drop_l2();
}
/*
bit<3> prob = randomNum.get();
hdr.udp.srcPort = (bit<16>) prob;
hdr.udp.checksum = 0;
forward_l2.apply();
*/
/*bit<3> prob = randomNum.get();
if (prob < 1) { // forward 1/8
forward_l2.apply();
}
else {
drop_l2();
}*/
//ig_tm_md.ucast_egress_port = (bit<9>)prob;
/* Change UDP src port to force pakcets to be enqueued in different CPUs
/*
if (hdr.udp.isValid()) {
hdr.udp.srcPort = hdr.udp.checksum;
hdr.udp.checksum = 0;
}
*/
/* Discard packets according to the checksum
/*
// 0x28F0 -> 1/10
// 0x2000 -> 1/8
// 0x028F -> 1/100
if (hdr.udp.checksum < 0x2000) {
forward_l2.apply();
}
else{
drop_l2();
}
*/
}
}
/********************* D E P A R S E R ************************/
control IngressDeparser(packet_out pkt,
/* User */
inout my_ingress_headers_t hdr,
in my_ingress_metadata_t meta,
/* Intrinsic */
in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md)
{
apply {
pkt.emit(hdr);
}
}
/*************************************************************************
**************** E G R E S S P R O C E S S I N G *******************
*************************************************************************/
/*********************** H E A D E R S ************************/
struct my_egress_headers_t {
ethernet_h outer_ethernet;
ipv4_h outer_ipv4;
udp_h outer_udp;
ethernet_h ethernet;
ipv4_h ipv4;
udp_h udp;
}
/******** G L O B A L E G R E S S M E T A D A T A *********/
struct my_egress_metadata_t {
}
/*********************** P A R S E R **************************/
parser EgressParser(packet_in pkt,
/* User */
out my_egress_headers_t hdr,
out my_egress_metadata_t meta,
/* Intrinsic */
out egress_intrinsic_metadata_t eg_intr_md)
{
/* This is a mandatory state, required by Tofino Architecture */
state start {
pkt.extract(eg_intr_md);
transition parse_ethernet;
}
state parse_ethernet {
pkt.extract(hdr.ethernet);
transition select(hdr.ethernet.etherType) {
ETHERTYPE_IPV4: parse_ipv4;
default: accept;
}
}
state parse_ipv4 {
pkt.extract(hdr.ipv4);
transition select(hdr.ipv4.protocol) {
PROTOCOL_UDP: parse_udp;
default: accept;
}
}
state parse_udp {
pkt.extract(hdr.udp);
transition accept;
}
}
/***************** M A T C H - A C T I O N *********************/
control Egress(
/* User */
inout my_egress_headers_t hdr,
inout my_egress_metadata_t meta,
/* Intrinsic */
in egress_intrinsic_metadata_t eg_intr_md,
in egress_intrinsic_metadata_from_parser_t eg_prsr_md,
inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md,
inout egress_intrinsic_metadata_for_output_port_t eg_oport_md)
{
Random<bit<8>>() randomPort;
action encap(){
hdr.outer_ethernet.setValid();
hdr.outer_ethernet.srcAddr = ENCAP_MAC_SRC;
hdr.outer_ethernet.dstAddr = ENCAP_MAC_DST;
hdr.outer_ethernet.etherType = ETHERTYPE_IPV4;
hdr.outer_ipv4.setValid();
hdr.outer_ipv4.version = 4;
hdr.outer_ipv4.ihl = 5;
hdr.outer_ipv4.dscp = 0;
hdr.outer_ipv4.ecn = 0;
hdr.outer_ipv4.totalLen = hdr.ipv4.totalLen;
hdr.outer_ipv4.totalLen = hdr.outer_ipv4.totalLen + 28;
hdr.outer_ipv4.identification = 0xabcd;
hdr.outer_ipv4.flags = 4;
hdr.outer_ipv4.fragOffset = 0;
hdr.outer_ipv4.ttl = 31;
hdr.outer_ipv4.hdrChecksum = 0;
hdr.outer_ipv4.protocol = PROTOCOL_UDP;
hdr.outer_ipv4.srcAddr = ENCAP_IP_SRC;
hdr.outer_ipv4.dstAddr = ENCAP_IP_DST;
hdr.outer_udp.setValid();
hdr.outer_udp.srcPort = 0;
hdr.outer_udp.dstPort = ENCAP_UDP_DST;
hdr.outer_udp._length = hdr.udp._length;
hdr.outer_udp._length = hdr.outer_udp._length + 8;
hdr.outer_udp.checksum = 0;
}
table encapsulate_t {
key = {
}
actions = {
encap;
NoAction;
}
default_action = encap;
size = 1;
}
apply {
encapsulate_t.apply();
bit<8> port = randomPort.get();
hdr.outer_udp.srcPort = (bit<16>)port;
}
}
/********************* D E P A R S E R ************************/
control EgressDeparser(packet_out pkt,
/* User */
inout my_egress_headers_t hdr,
in my_egress_metadata_t meta,
/* Intrinsic */
in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md)
{
Checksum() ipv4_checksum;
apply {
hdr.outer_ipv4.hdrChecksum = ipv4_checksum.update({
hdr.outer_ipv4.version,
hdr.outer_ipv4.ihl,
hdr.outer_ipv4.dscp,
hdr.outer_ipv4.ecn,
hdr.outer_ipv4.totalLen,
hdr.outer_ipv4.identification,
hdr.outer_ipv4.flags,
hdr.outer_ipv4.fragOffset,
hdr.outer_ipv4.ttl,
hdr.outer_ipv4.protocol,
hdr.outer_ipv4.srcAddr,
hdr.outer_ipv4.dstAddr
});
pkt.emit(hdr.outer_ethernet);
pkt.emit(hdr.outer_ipv4);
pkt.emit(hdr.outer_udp);
pkt.emit(hdr.ethernet);
pkt.emit(hdr.ipv4);
pkt.emit(hdr.udp);
}
}
/************ F I N A L P A C K A G E ******************************/
Pipeline(
IngressParser(),
Ingress(),
IngressDeparser(),
EgressParser(),
Egress(),
EgressDeparser()
) pipe;
Switch(pipe) main;