"...composable_kernel.git" did not exist on "13af8cc43ef5674707f1a009f836602f47db4b33"
Commit edb4215d authored by Jialin Li's avatar Jialin Li
Browse files

tofino: add tofino switch p4 code; add tofino net to tcp_single and udp_single experiments

parent a8fd899d
...@@ -34,7 +34,7 @@ import simbricks.nodeconfig as node ...@@ -34,7 +34,7 @@ import simbricks.nodeconfig as node
kinds_of_host = ['qemu'] kinds_of_host = ['qemu']
kinds_of_nic = ['cv','cb','ib'] kinds_of_nic = ['cv','cb','ib']
kinds_of_net = ['wire', 'switch', 'dumbbell', 'bridge'] kinds_of_net = ['wire', 'switch', 'dumbbell', 'bridge', 'tofino']
kinds_of_app = ['TCPs'] kinds_of_app = ['TCPs']
experiments = [] experiments = []
...@@ -49,6 +49,8 @@ for n in kinds_of_net: ...@@ -49,6 +49,8 @@ for n in kinds_of_net:
net_class = sim.NS3DumbbellNet net_class = sim.NS3DumbbellNet
if n == 'bridge': if n == 'bridge':
net_class = sim.NS3BridgeNet net_class = sim.NS3BridgeNet
if n == 'tofino':
net_class = sim.TofinoNet
# set nic sim # set nic sim
...@@ -56,28 +58,28 @@ for n in kinds_of_net: ...@@ -56,28 +58,28 @@ for n in kinds_of_net:
net = net_class() net = net_class()
e = exp.Experiment('qemu-' + c + '-' + n + '-' + 'TCPs') e = exp.Experiment('qemu-' + c + '-' + n + '-' + 'TCPs')
e.add_network(net) e.add_network(net)
if c == 'cv': if c == 'cv':
servers = sim.create_basic_hosts(e, 1, 'server', net, sim.CorundumVerilatorNIC, sim.QemuHost, servers = sim.create_basic_hosts(e, 1, 'server', net, sim.CorundumVerilatorNIC, sim.QemuHost,
node.CorundumLinuxNode, node.IperfTCPServer) node.CorundumLinuxNode, node.IperfTCPServer)
clients = sim.create_basic_hosts(e, 1, 'client', net, sim.CorundumVerilatorNIC, sim.QemuHost, clients = sim.create_basic_hosts(e, 1, 'client', net, sim.CorundumVerilatorNIC, sim.QemuHost,
node.CorundumLinuxNode, node.IperfTCPClient, ip_start = 2) node.CorundumLinuxNode, node.IperfTCPClient, ip_start = 2)
if c == 'cb': if c == 'cb':
servers = sim.create_basic_hosts(e, 1, 'server', net, sim.CorundumBMNIC, sim.QemuHost, servers = sim.create_basic_hosts(e, 1, 'server', net, sim.CorundumBMNIC, sim.QemuHost,
node.CorundumLinuxNode, node.IperfTCPServer) node.CorundumLinuxNode, node.IperfTCPServer)
clients = sim.create_basic_hosts(e, 1, 'client', net, sim.CorundumBMNIC, sim.QemuHost, clients = sim.create_basic_hosts(e, 1, 'client', net, sim.CorundumBMNIC, sim.QemuHost,
node.CorundumLinuxNode, node.IperfTCPClient, ip_start = 2) node.CorundumLinuxNode, node.IperfTCPClient, ip_start = 2)
if c == 'ib': if c == 'ib':
servers = sim.create_basic_hosts(e, 1, 'server', net, sim.I40eNIC, sim.QemuHost, servers = sim.create_basic_hosts(e, 1, 'server', net, sim.I40eNIC, sim.QemuHost,
node.I40eLinuxNode, node.IperfTCPServer) node.I40eLinuxNode, node.IperfTCPServer)
clients = sim.create_basic_hosts(e, 1, 'client', net, sim.I40eNIC, sim.QemuHost, clients = sim.create_basic_hosts(e, 1, 'client', net, sim.I40eNIC, sim.QemuHost,
node.I40eLinuxNode, node.IperfTCPClient, ip_start = 2) node.I40eLinuxNode, node.IperfTCPClient, ip_start = 2)
clients[0].wait = True clients[0].wait = True
clients[0].node_config.app.server_ip = servers[0].node_config.ip clients[0].node_config.app.server_ip = servers[0].node_config.ip
......
...@@ -34,7 +34,7 @@ import simbricks.nodeconfig as node ...@@ -34,7 +34,7 @@ import simbricks.nodeconfig as node
kinds_of_host = ['qemu'] kinds_of_host = ['qemu']
kinds_of_nic = ['cv','cb','ib'] kinds_of_nic = ['cv','cb','ib']
kinds_of_net = ['wire', 'switch', 'dumbbell', 'bridge'] kinds_of_net = ['wire', 'switch', 'dumbbell', 'bridge', 'tofino']
kinds_of_app = ['UDPs'] kinds_of_app = ['UDPs']
rate = '200m' rate = '200m'
...@@ -51,6 +51,8 @@ for n in kinds_of_net: ...@@ -51,6 +51,8 @@ for n in kinds_of_net:
net_class = sim.NS3DumbbellNet net_class = sim.NS3DumbbellNet
if n == 'bridge': if n == 'bridge':
net_class = sim.NS3BridgeNet net_class = sim.NS3BridgeNet
if n == 'tofino':
net_class = sim.TofinoNet
# set nic sim # set nic sim
...@@ -58,28 +60,28 @@ for n in kinds_of_net: ...@@ -58,28 +60,28 @@ for n in kinds_of_net:
net = net_class() net = net_class()
e = exp.Experiment('qemu-' + c + '-' + n + '-' + 'UDPs') e = exp.Experiment('qemu-' + c + '-' + n + '-' + 'UDPs')
e.add_network(net) e.add_network(net)
if c == 'cv': if c == 'cv':
servers = sim.create_basic_hosts(e, 1, 'server', net, sim.CorundumVerilatorNIC, sim.QemuHost, servers = sim.create_basic_hosts(e, 1, 'server', net, sim.CorundumVerilatorNIC, sim.QemuHost,
node.CorundumLinuxNode, node.IperfUDPServer) node.CorundumLinuxNode, node.IperfUDPServer)
clients = sim.create_basic_hosts(e, 1, 'client', net, sim.CorundumVerilatorNIC, sim.QemuHost, clients = sim.create_basic_hosts(e, 1, 'client', net, sim.CorundumVerilatorNIC, sim.QemuHost,
node.CorundumLinuxNode, node.IperfUDPClient, ip_start = 2) node.CorundumLinuxNode, node.IperfUDPClient, ip_start = 2)
if c == 'cb': if c == 'cb':
servers = sim.create_basic_hosts(e, 1, 'server', net, sim.CorundumBMNIC, sim.QemuHost, servers = sim.create_basic_hosts(e, 1, 'server', net, sim.CorundumBMNIC, sim.QemuHost,
node.CorundumLinuxNode, node.IperfUDPServer) node.CorundumLinuxNode, node.IperfUDPServer)
clients = sim.create_basic_hosts(e, 1, 'client', net, sim.CorundumBMNIC, sim.QemuHost, clients = sim.create_basic_hosts(e, 1, 'client', net, sim.CorundumBMNIC, sim.QemuHost,
node.CorundumLinuxNode, node.IperfUDPClient, ip_start = 2) node.CorundumLinuxNode, node.IperfUDPClient, ip_start = 2)
if c == 'ib': if c == 'ib':
servers = sim.create_basic_hosts(e, 1, 'server', net, sim.I40eNIC, sim.QemuHost, servers = sim.create_basic_hosts(e, 1, 'server', net, sim.I40eNIC, sim.QemuHost,
node.I40eLinuxNode, node.IperfUDPServer) node.I40eLinuxNode, node.IperfUDPServer)
clients = sim.create_basic_hosts(e, 1, 'client', net, sim.I40eNIC, sim.QemuHost, clients = sim.create_basic_hosts(e, 1, 'client', net, sim.I40eNIC, sim.QemuHost,
node.I40eLinuxNode, node.IperfUDPClient, ip_start = 2) node.I40eLinuxNode, node.IperfUDPClient, ip_start = 2)
clients[0].wait = True clients[0].wait = True
clients[0].node_config.app.server_ip = servers[0].node_config.ip clients[0].node_config.app.server_ip = servers[0].node_config.ip
clients[0].node_config.app.rate = rate clients[0].node_config.app.rate = rate
......
/* -*- 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 *******************
**************************************************************************/
enum bit<16> ether_type_t {
IPV4 = 0x0800,
ARP = 0x0806,
TPID = 0x8100,
TPID2 = 0x9100,
IPV6 = 0x86DD
}
const ReplicationId_t L2_MCAST_RID = 0xFFFF;
const int MAC_TABLE_SIZE = 65536;
const int VLAN_PORT_TABLE_SIZE = 1 << (7 + 12);
/* We can use up to 8 different digest types */
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;
}
header vlan_tag_h {
bit<16> tpid;
bit<3> pcp;
bit<1> dei;
bit<12> vid;
}
header etherII_h {
ether_type_t ether_type;
}
/*** Internal Headers ***/
typedef bit<4> header_type_t; /* These fields can be coombined into one */
typedef bit<4> header_info_t; /* 8-bit field as well. Exercise for the brave */
const header_type_t HEADER_TYPE_BRIDGE = 0xB;
const header_type_t HEADER_TYPE_MIRROR_INGRESS = 0xC;
const header_type_t HEADER_TYPE_MIRROR_EGRESS = 0xD;
const header_type_t HEADER_TYPE_RESUBMIT = 0xA;
/*
* This is a common "preamble" header that must be present in all internal
* headers. The only time you do not need it is when you know that you are
* not going to have more than one internal header type ever
*/
#define INTERNAL_HEADER \
header_type_t header_type; \
header_info_t header_info
header inthdr_h {
INTERNAL_HEADER;
}
/* Bridged metadata */
header bridge_h {
INTERNAL_HEADER;
bit<7> pad0;
PortId_t ingress_port;
bit<3> pcp;
bit<1> dei;
bit<12> vid;
}
/*************************************************************************
************** 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 {
bridge_h bridge;
ethernet_h ethernet;
vlan_tag_h vlan_tag;
etherII_h etherII;
}
/****** G L O B A L I N G R E S S M E T A D A T A *********/
struct port_metadata_t {
bit<3> port_pcp;
bit<12> port_vid;
bit<9> l2_xid;
}
struct my_ingress_metadata_t {
port_metadata_t port_properties;
bit<3> pcp;
bit<1> dei;
bit<12> vid;
bit<9> mac_move; /* Should have the same size as PortId_t */
bit<1> is_static;
bit<1> smac_hit;
PortId_t ingress_port;
}
/*********************** 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);
meta.port_properties = port_metadata_unpack<port_metadata_t>(pkt);
transition meta_init;
}
state meta_init {
meta.pcp = 0;
meta.dei = 0;
meta.vid = 0;
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(pkt.lookahead<bit<16>>()) {
(bit<16>)ether_type_t.TPID &&& 0xEFFF: parse_vlan_tag;
default: parse_etherII;
}
}
state parse_vlan_tag {
pkt.extract(hdr.vlan_tag);
meta.pcp = hdr.vlan_tag.pcp;
meta.dei = hdr.vlan_tag.dei;
meta.vid = hdr.vlan_tag.vid;
transition parse_etherII;
}
state parse_etherII {
pkt.extract(hdr.etherII);
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 = {
meta.vid : exact;
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 = (MulticastGroupId_t)meta.vid;
ig_tm_md.rid = L2_MCAST_RID;
/* Set the exclusion id here, since parser can't acces ig_tm_md */
ig_tm_md.level2_exclusion_id = meta.port_properties.l2_xid;
}
action dmac_multicast(MulticastGroupId_t mcast_grp) {
ig_tm_md.mcast_grp_a = mcast_grp;
ig_tm_md.rid = L2_MCAST_RID;
/* Set the exclusion id here, since parser can't acces ig_tm_md */
ig_tm_md.level2_exclusion_id = meta.port_properties.l2_xid;
}
action dmac_drop() {
drop();
exit;
}
table dmac {
key = {
meta.vid : exact;
hdr.ethernet.dst_addr : exact;
}
actions = {
dmac_unicast; dmac_miss; dmac_multicast; dmac_drop;
}
size = MAC_TABLE_SIZE;
default_action = dmac_miss();
}
apply {
/* Assign Port-based VLAN to untagged/priority-tagged packets */
if (meta.vid == 0) {
meta.vid = meta.port_properties.port_vid;
}
if (!hdr.vlan_tag.isValid()) {
meta.pcp = meta.port_properties.port_pcp;
}
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();
}
}
}
/* Bridge metadata to the egress pipeline */
hdr.bridge.setValid();
hdr.bridge.header_type = HEADER_TYPE_BRIDGE;
hdr.bridge.header_info = 0; /* Ignore */
hdr.bridge.ingress_port = ig_intr_md.ingress_port;
hdr.bridge.pcp = meta.pcp;
hdr.bridge.dei = meta.dei;
hdr.bridge.vid = meta.vid;
}
}
/********************* D E P A R S E R ************************/
/* This struct is needed for proper digest receive API generation */
struct l2_digest_t {
bit<12> vid;
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({
meta.vid,
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;
etherII_h etherII;
}
/******** 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 {
bridge_h bridge;
PortId_t ingress_port;
bit<3> pcp;
bit<1> dei;
bit<12> vid;
}
/*********************** 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)
{
inthdr_h inthdr;
/* This is a mandatory state, required by Tofino Architecture */
state start {
pkt.extract(eg_intr_md);
inthdr = pkt.lookahead<inthdr_h>();
transition select(inthdr.header_type, inthdr.header_info) {
( HEADER_TYPE_BRIDGE, _ ) : parse_bridge;
default : reject;
}
}
state parse_bridge {
pkt.extract(meta.bridge);
meta.ingress_port = meta.bridge.ingress_port;
meta.pcp = meta.bridge.pcp;
meta.dei = meta.bridge.dei;
meta.vid = meta.bridge.vid;
transition parse_ethernet;
}
state parse_ethernet {
pkt.extract(hdr.ethernet);
transition select(pkt.lookahead<bit<16>>()) {
(bit<16>)ether_type_t.TPID &&& 0xEFFF: parse_vlan_tag;
default: parse_etherII;
}
}
state parse_vlan_tag {
pkt.extract(hdr.vlan_tag);
transition parse_etherII;
}
state parse_etherII {
pkt.extract(hdr.etherII);
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)
{
action drop() {
eg_dprsr_md.drop_ctl = eg_dprsr_md.drop_ctl | 1;
}
action send_tagged() {
hdr.vlan_tag.setValid();
hdr.vlan_tag.tpid = (bit<16>)ether_type_t.TPID;
#ifdef P4C_1719_FIXED
hdr.vlan_tag.pcp = meta.pcp;
hdr.vlan_tag.dei = meta.dei;
#else
hdr.vlan_tag.pcp = 0;
hdr.vlan_tag.dei = 0;
#endif
hdr.vlan_tag.vid = meta.vid;
}
action send_untagged() {
hdr.vlan_tag.setInvalid();
}
action not_a_member() {
drop();
}
table egr_vlan_port {
key = {
meta.vid : exact;
#ifdef USE_MASK
eg_intr_md.egress_port & 0x7F : exact @name("egress_port");
#else
eg_intr_md.egress_port[6:0] : exact @name("egress_port");
#endif
}
actions = {
send_tagged;
send_untagged;
not_a_member;
}
default_action = not_a_member();
size = VLAN_PORT_TABLE_SIZE;
}
apply {
#ifdef P4_SOURCE_PRUNING
if (meta.ingress_port == eg_intr_md.egress_port) {
drop();
} else {
#endif
egr_vlan_port.apply();
#ifdef P4_SOURCE_PRUNING
}
#endif
}
}
/********************* 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;
This diff is collapsed.
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