Commit f7051bf0 authored by Jialin Li's avatar Jialin Li
Browse files

add mem_switch p4 code

parent e6ab50df
/* -*- P4_16 -*- */
#include <core.p4>
#include <tna.p4>
typedef bit<48> mac_addr_t;
typedef bit<32> ipv4_addr_t;
#define ETHERTYPE_TPID 0x8100
#define ETHERTYPE_IPV4 0x0800
#define IP_PROTOCOL_UDP 17
const int MAC_TABLE_SIZE = 65536;
const int MEM_TABLE_SIZE = 64;
const bit<3> L2_LEARN_DIGEST = 1;
/*************************************************************************
*********************** 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> dst_addr;
bit<48> src_addr;
bit<16> ether_type;
}
header vlan_tag_h {
bit<16> tpid;
bit<3> pcp;
bit<1> dei;
bit<12> vid;
bit<16> ether_type;
}
header ipv4_h {
bit<4> version;
bit<4> ihl;
bit<8> diffserv;
bit<16> total_len;
bit<16> identification;
bit<3> flags;
bit<13> frag_offset;
bit<8> ttl;
bit<8> protocol;
bit<16> hdr_checksum;
bit<32> src_addr;
bit<32> dst_addr;
}
header udp_h {
bit<16> src_port;
bit<16> dst_port;
bit<16> len;
bit<16> checksum;
}
header mem_h {
bit<8> op_type;
bit<64> req_id;
bit<64> addr;
bit<16> len;
bit<64> as_id;
}
/*************************************************************************
************** 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;
mem_h mem;
}
/****** 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 {
bit<9> mac_move;
bit<1> is_static;
bit<1> smac_hit;
PortId_t ingress_port;
}
/*********************** P A R S E R **************************/
parser IngressParser(
packet_in pkt,
out my_ingress_headers_t hdr,
out my_ingress_metadata_t meta,
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 meta_init;
}
state meta_init {
meta.mac_move = 0;
meta.is_static = 0;
meta.smac_hit = 0;
meta.ingress_port = ig_intr_md.ingress_port;
transition parse_ethernet;
}
state parse_ethernet {
pkt.extract(hdr.ethernet);
transition select(hdr.ethernet.ether_type) {
ETHERTYPE_IPV4: parse_ipv4;
default: accept;
}
}
state parse_ipv4 {
pkt.extract(hdr.ipv4);
transition select(hdr.ipv4.protocol) {
IP_PROTOCOL_UDP: parse_udp;
default: accept;
}
}
state parse_udp {
pkt.extract(hdr.udp);
transition parse_mem;
}
state parse_mem {
pkt.extract(hdr.mem);
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() {
ig_dprsr_md.drop_ctl = 1;
}
action send(PortId_t port) {
ig_tm_md.ucast_egress_port = port;
}
action smac_hit(PortId_t port, bit<1> is_static) {
meta.mac_move = ig_intr_md.ingress_port ^ port;
meta.smac_hit = 1;
meta.is_static = is_static;
}
action smac_miss() { }
action smac_drop() {
drop(); exit;
}
@idletime_precision(3)
table smac {
key = {
hdr.ethernet.src_addr : exact;
}
actions = {
smac_hit; smac_miss; smac_drop;
}
size = MAC_TABLE_SIZE;
const default_action = smac_miss();
idle_timeout = true;
}
action mac_learn_notify() {
ig_dprsr_md.digest_type = L2_LEARN_DIGEST;
}
table smac_results {
key = {
meta.mac_move : ternary;
meta.is_static : ternary;
meta.smac_hit : ternary;
}
actions = {
mac_learn_notify; NoAction; smac_drop;
}
const entries = {
( _, _, 0) : mac_learn_notify();
( 0, _, 1) : NoAction();
( _, 0, 1) : mac_learn_notify();
( _, 1, 1) : smac_drop();
}
}
action dmac_unicast(PortId_t port) {
send(port);
}
action dmac_miss() {
ig_tm_md.mcast_grp_a = 1;
}
action dmac_drop() {
drop();
exit;
}
table dmac {
key = {
hdr.ethernet.dst_addr : exact;
}
actions = {
dmac_unicast; dmac_miss; dmac_drop;
}
size = MAC_TABLE_SIZE;
default_action = dmac_miss();
}
action mem_forward(PortId_t port) {
ig_tm_md.mcast_grp_a = 0;
send(port);
}
action mem_miss() {
drop();
exit;
}
table mem {
key = {
hdr.mem.as_id : exact;
}
actions = {
mem_forward; mem_miss;
}
size = MEM_TABLE_SIZE;
default_action = mem_miss();
}
apply {
ig_tm_md.bypass_egress = 1w1;
smac.apply();
smac_results.apply();
switch (dmac.apply().action_run) {
dmac_unicast: { /* Unicast source pruning */
if (ig_intr_md.ingress_port ==
ig_tm_md.ucast_egress_port) {
drop();
}
}
dmac_miss: {
if (hdr.mem.isValid()) {
mem.apply();
}
}
}
}
}
/********************* D E P A R S E R ************************/
/* This struct is needed for proper digest receive API generation */
struct l2_digest_t {
bit<48> src_mac;
bit<9> ingress_port;
bit<9> mac_move;
bit<1> is_static;
bit<1> smac_hit;
}
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)
{
Digest <l2_digest_t>() l2_digest;
apply {
if (ig_dprsr_md.digest_type == L2_LEARN_DIGEST) {
l2_digest.pack({
hdr.ethernet.src_addr,
meta.ingress_port,
meta.mac_move,
meta.is_static,
meta.smac_hit });
}
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 ethernet;
vlan_tag_h vlan_tag;
ipv4_h ipv4;
}
/******** 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(pkt.lookahead<bit<16>>()) {
ETHERTYPE_TPID: parse_vlan_tag;
ETHERTYPE_IPV4: parse_ipv4;
default: accept;
}
}
state parse_vlan_tag {
pkt.extract(hdr.vlan_tag);
transition select(hdr.vlan_tag.ether_type) {
ETHERTYPE_IPV4: parse_ipv4;
default: accept;
}
}
state parse_ipv4 {
pkt.extract(hdr.ipv4);
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)
{
apply {
}
}
/********************* 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)
{
apply {
pkt.emit(hdr);
}
}
/************ F I N A L P A C K A G E ******************************/
Pipeline(
IngressParser(),
Ingress(),
IngressDeparser(),
EgressParser(),
Egress(),
EgressDeparser()
) pipe;
Switch(pipe) main;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment