Skip to content

Commit

Permalink
Add calculator example
Browse files Browse the repository at this point in the history
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
  • Loading branch information
vbnogueira committed Nov 19, 2024
1 parent 0c3408b commit e5ba246
Show file tree
Hide file tree
Showing 8 changed files with 997 additions and 0 deletions.
1 change: 1 addition & 0 deletions backends/tc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,4 @@ endmacro(p4tc_add_test_with_args)

p4c_add_tests("p4tc" ${P4TC_COMPILER_DRIVER} "${P4_16_SUITES}" "")
p4tc_add_test_with_args("p4tc" ${P4TC_COMPILER_DRIVER} FALSE "testdata/p4tc_samples_stf/arp_respond.p4" "testdata/p4tc_samples_stf/arp_respond.p4" "-tf ${P4C_SOURCE_DIR}/testdata/p4tc_samples_stf/arp_respond.stf" "")
p4tc_add_test_with_args("p4tc" ${P4TC_COMPILER_DRIVER} FALSE "testdata/p4tc_samples_stf/calculator.p4" "testdata/p4tc_samples_stf/calculator.p4" "-tf ${P4C_SOURCE_DIR}/testdata/p4tc_samples_stf/calculator.stf" "")
239 changes: 239 additions & 0 deletions testdata/p4tc_samples_stf/calculator.p4
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
/* -*- P4_16 -*- */

/*
* P4 Calculator
*
* This program implements a simple protocol. It can be carried over Ethernet
* (Ethertype 0x1234).
*
* The Protocol header looks like this:
*
* 0 1 2 3
* +----------------+----------------+----------------+---------------+
* | P | 4 | Version | Op |
* +----------------+----------------+----------------+---------------+
* | Operand A |
* +----------------+----------------+----------------+---------------+
* | Operand B |
* +----------------+----------------+----------------+---------------+
* | Result |
* +----------------+----------------+----------------+---------------+
*
* P is an ASCII Letter 'P' (0x50)
* 4 is an ASCII Letter '4' (0x34)
* Version is currently 0.1 (0x01)
* Op is an operation to Perform:
* '+' (0x2b) Result = OperandA + OperandB
* '-' (0x2d) Result = OperandA - OperandB
* '&' (0x26) Result = OperandA & OperandB
* '|' (0x7c) Result = OperandA | OperandB
* '^' (0x5e) Result = OperandA ^ OperandB
*
* The device receives a packet, performs the requested operation, fills in the
* result and sends the packet back out of the same port it came in on, while
* swapping the source and destination addresses.
*
* If an unknown operation is specified or the header is not valid, the packet
* is dropped
*/

#include <core.p4>
#include <tc/pna.p4>


/*
* Define the headers the program will recognize
*/

/*
* Standard ethernet header
*/
header ethernet_t {
bit<48> dstAddr;
bit<48> srcAddr;
bit<16> etherType;
}

/*
* This is a custom protocol header for the calculator. We'll use
* ethertype 0x1234 for is (see parser)
*/
const bit<16> P4CALC_ETYPE = 0x1234;
const bit<8> P4CALC_P = 0x50; // 'P'
const bit<8> P4CALC_4 = 0x34; // '4'
const bit<8> P4CALC_VER = 0x01; // v0.1
const bit<8> P4CALC_PLUS = 0x2b; // '+'
const bit<8> P4CALC_MINUS = 0x2d; // '-'
const bit<8> P4CALC_AND = 0x26; // '&'
const bit<8> P4CALC_OR = 0x7c; // '|'
const bit<8> P4CALC_CARET = 0x5e; // '^'

header p4calc_t {
bit<8> p;
bit<8> four;
bit<8> ver;
bit<8> op;
bit<32> operand_a;
bit<32> operand_b;
bit<32> res;
}

/*
* All headers, used in the program needs to be assembed into a single struct.
* We only need to declare the type, but there is no need to instantiate it,
* because it is done "by the architecture", i.e. outside of P4 functions
*/
struct headers_t {
ethernet_t ethernet;
p4calc_t p4calc;
}

/*
* All metadata, globally used in the program, also needs to be assembed
* into a single struct. As in the case of the headers, we only need to
* declare the type, but there is no need to instantiate it,
* because it is done "by the architecture", i.e. outside of P4 functions
*/

struct metadata_t {
/* In our case it is empty */
}

/*************************************************************************
*********************** P A R S E R ***********************************
*************************************************************************/
parser MainParserImpl(
packet_in pkt,
out headers_t hdr,
inout metadata_t meta,
in pna_main_parser_input_metadata_t istd)
{

state start {
pkt.extract(hdr.ethernet);
transition select(hdr.ethernet.etherType) {
P4CALC_ETYPE : check_p4calc;
default : accept;
}
}

state check_p4calc {
transition select(pkt.lookahead<p4calc_t>().p,
pkt.lookahead<p4calc_t>().four,
pkt.lookahead<p4calc_t>().ver) {
(P4CALC_P, P4CALC_4, P4CALC_VER) : parse_p4calc;
default : accept;
}
}

state parse_p4calc {
pkt.extract(hdr.p4calc);
transition accept;
}
}


/*************************************************************************
********************** M A I N C O N T R O L ************************
*************************************************************************/
control MainControlImpl(
inout headers_t hdr,
inout metadata_t meta,
in pna_main_input_metadata_t istd,
inout pna_main_output_metadata_t ostd)
{

action send_back(bit<32> result) {
bit<48> tmp;

/* Put the result back in */
hdr.p4calc.res = result;

/* Swap the MAC addresses */
tmp = hdr.ethernet.dstAddr;
hdr.ethernet.dstAddr = hdr.ethernet.srcAddr;
hdr.ethernet.srcAddr = tmp;
/* Send the packet back to the port it came from */
send_to_port(istd.input_port);
}

action operation_add() {
send_back(hdr.p4calc.operand_a + hdr.p4calc.operand_b);
}

action operation_sub() {
send_back(hdr.p4calc.operand_a - hdr.p4calc.operand_b);
}

action operation_and() {
send_back(hdr.p4calc.operand_a & hdr.p4calc.operand_b);
}

action operation_or() {
send_back(hdr.p4calc.operand_a | hdr.p4calc.operand_b);
}

action operation_xor() {
send_back(hdr.p4calc.operand_a ^ hdr.p4calc.operand_b);
}

action operation_drop() {
drop_packet();
}

table calculate {
key = {
hdr.p4calc.op : exact @name("op");
}
actions = {
operation_add;
operation_sub;
operation_and;
operation_or;
operation_xor;
operation_drop;
}
const default_action = operation_drop();
const entries = {
P4CALC_PLUS : operation_add();
P4CALC_MINUS: operation_sub();
P4CALC_AND : operation_and();
P4CALC_OR : operation_or();
P4CALC_CARET: operation_xor();
}
}


apply {
if (hdr.p4calc.isValid()) {
calculate.apply();
} else {
operation_drop();
}
}
}


/*************************************************************************
*********************** D E P A R S E R *******************************
*************************************************************************/
control MainDeparserImpl(
packet_out pkt,
inout headers_t hdr,
in metadata_t meta,
in pna_main_output_metadata_t ostd)
{
apply {
pkt.emit(hdr.ethernet);
pkt.emit(hdr.p4calc);
}
}

/*************************************************************************
****************************** P N A **********************************
*************************************************************************/
PNA_NIC(
MainParserImpl(),
MainControlImpl(),
MainDeparserImpl()
) main;
2 changes: 2 additions & 0 deletions testdata/p4tc_samples_stf/calculator.stf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
packet 0 10000002 aabb1000 0001aabb 12345034 012b0000 00010000 00020000 000020
expect 0 10000001 aabb1000 0002aabb 12345034 012b0000 00010000 00020000 000320
80 changes: 80 additions & 0 deletions testdata/p4tc_samples_stf_outputs/calculator.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"schema_version" : "1.0.0",
"pipeline_name" : "calculator",
"externs" : [],
"tables" : [
{
"name" : "MainControlImpl/calculate",
"id" : 1,
"tentries" : 1024,
"permissions" : "0x3da4",
"nummask" : 8,
"keysize" : 8,
"keyfields" : [
{
"id" : 1,
"name" : "op",
"type" : "bit8",
"match_type" : "exact",
"bitwidth" : 8
}
],
"actions" : [
{
"id" : 1,
"name" : "MainControlImpl/operation_add",
"action_scope" : "TableAndDefault",
"annotations" : [],
"params" : [],
"default_hit_action" : false,
"default_miss_action" : false
},
{
"id" : 2,
"name" : "MainControlImpl/operation_sub",
"action_scope" : "TableAndDefault",
"annotations" : [],
"params" : [],
"default_hit_action" : false,
"default_miss_action" : false
},
{
"id" : 3,
"name" : "MainControlImpl/operation_and",
"action_scope" : "TableAndDefault",
"annotations" : [],
"params" : [],
"default_hit_action" : false,
"default_miss_action" : false
},
{
"id" : 4,
"name" : "MainControlImpl/operation_or",
"action_scope" : "TableAndDefault",
"annotations" : [],
"params" : [],
"default_hit_action" : false,
"default_miss_action" : false
},
{
"id" : 5,
"name" : "MainControlImpl/operation_xor",
"action_scope" : "TableAndDefault",
"annotations" : [],
"params" : [],
"default_hit_action" : false,
"default_miss_action" : false
},
{
"id" : 6,
"name" : "MainControlImpl/operation_drop",
"action_scope" : "TableAndDefault",
"annotations" : [],
"params" : [],
"default_hit_action" : false,
"default_miss_action" : true
}
]
}
]
}
42 changes: 42 additions & 0 deletions testdata/p4tc_samples_stf_outputs/calculator.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash -x

set -e

: "${TC:="tc"}"
$TC p4template create pipeline/calculator numtables 1

$TC p4template create action/calculator/MainControlImpl/operation_add actid 1
$TC p4template update action/calculator/MainControlImpl/operation_add state active

$TC p4template create action/calculator/MainControlImpl/operation_sub actid 2
$TC p4template update action/calculator/MainControlImpl/operation_sub state active

$TC p4template create action/calculator/MainControlImpl/operation_and actid 3
$TC p4template update action/calculator/MainControlImpl/operation_and state active

$TC p4template create action/calculator/MainControlImpl/operation_or actid 4
$TC p4template update action/calculator/MainControlImpl/operation_or state active

$TC p4template create action/calculator/MainControlImpl/operation_xor actid 5
$TC p4template update action/calculator/MainControlImpl/operation_xor state active

$TC p4template create action/calculator/MainControlImpl/operation_drop actid 6
$TC p4template update action/calculator/MainControlImpl/operation_drop state active

$TC p4template create table/calculator/MainControlImpl/calculate \
tblid 1 \
type exact \
keysz 8 permissions 0x3da4 tentries 1024 nummasks 1 \
table_acts act name calculator/MainControlImpl/operation_add \
act name calculator/MainControlImpl/operation_sub \
act name calculator/MainControlImpl/operation_and \
act name calculator/MainControlImpl/operation_or \
act name calculator/MainControlImpl/operation_xor \
act name calculator/MainControlImpl/operation_drop
$TC p4template update table/calculator/MainControlImpl/calculate default_miss_action permissions 0x1024 action calculator/MainControlImpl/operation_drop
$TC p4template create table/calculator/MainControlImpl/calculate entry op 0x2b permissions 0x1024 action calculator/MainControlImpl/operation_add
$TC p4template create table/calculator/MainControlImpl/calculate entry op 0x2d permissions 0x1024 action calculator/MainControlImpl/operation_sub
$TC p4template create table/calculator/MainControlImpl/calculate entry op 0x26 permissions 0x1024 action calculator/MainControlImpl/operation_and
$TC p4template create table/calculator/MainControlImpl/calculate entry op 0x7c permissions 0x1024 action calculator/MainControlImpl/operation_or
$TC p4template create table/calculator/MainControlImpl/calculate entry op 0x5e permissions 0x1024 action calculator/MainControlImpl/operation_xor
$TC p4template update pipeline/calculator state ready
Loading

0 comments on commit e5ba246

Please sign in to comment.