blob: b5b8aa65cee57f776e2a4f87b690bbc8e2cbe142 [file] [log] [blame]
// Copyright (c) 2017, Google Inc.
//
// P4_16 specification for a L3 forwarding app.
// Note: This code has not been tested and is expected to contain bugs.
#ifndef P4_SPEC_L3_FWD_P4_
#define P4_SPEC_L3_FWD_P4_
#include "headers.p4"
#include "parser.p4"
#ifdef P4_EXPLICIT_LAG
#include "lag.p4"
#endif
//------------------------------------------------------------------------------
// IPv4/v6 L3 Forwarding
//------------------------------------------------------------------------------
control l3_fwd(inout parsed_packet_t hdr,
inout local_metadata_t local_metadata,
inout standard_metadata_t standard_metadata) {
@proto_package("l3_fwd")
action set_nexthop(@proto_tag(1) PortNum port,
@proto_tag(2) EthernetAddress smac,
@proto_tag(3) EthernetAddress dmac) {
standard_metadata.egress_spec = port;
hdr.ethernet.src_addr = smac;
hdr.ethernet.dst_addr = dmac;
// if (hdr.ipv4_base.isValid()) {
hdr.ipv4_base.ttl = hdr.ipv4_base.ttl - 1;
// } else if (hdr.ipv6_base.isValid()) {
// hdr.ipv6_base.hop_limit = hdr.ipv6_base.hop_limit - 1;
// }
}
// Hit implies that the packet needs to be L3 forwarded.
// Equivalent of BCM MY_STATION table
@proto_package("l3_fwd")
table l3_routing_classifier_table {
key = {
hdr.ethernet.dst_addr : exact @proto_tag(1);
}
actions = {
@proto_tag(1) NoAction;
}
const default_action = NoAction();
}
action_selector(HashAlgorithm.crc16, 32w1024, 32w14) wcmp_action_profile;
// LPM forwarding tables for IPV4 packets.
@proto_package("l3_fwd")
table l3_ipv4_override_table {
key = {
hdr.ipv4_base.dst_addr : lpm @proto_tag(1);
hdr.ipv4_base.dst_addr : selector @proto_tag(2);
hdr.ipv4_base.src_addr : selector @proto_tag(3);
hdr.ipv4_base.protocol : selector @proto_tag(4);
local_metadata.l4_src_port : selector @proto_tag(5);
local_metadata.l4_dst_port : selector @proto_tag(6);
}
actions = {
@proto_tag(1) set_nexthop;
@proto_tag(2) NoAction;
}
const default_action = NoAction();
// TODO(samarabdi): do we need to specify selector size?
implementation = wcmp_action_profile;
}
@proto_package("l3_fwd")
table l3_ipv4_vrf_table {
key = {
local_metadata.vrf_id: exact @proto_tag(1);
hdr.ipv4_base.dst_addr : lpm @proto_tag(2);
hdr.ipv4_base.dst_addr : selector @proto_tag(3);
hdr.ipv4_base.src_addr : selector @proto_tag(4);
hdr.ipv4_base.protocol : selector @proto_tag(5);
local_metadata.l4_src_port : selector @proto_tag(6);
local_metadata.l4_dst_port : selector @proto_tag(7);
}
actions = {
@proto_tag(1) set_nexthop;
@proto_tag(2) NoAction;
}
const default_action = NoAction();
implementation = wcmp_action_profile;
}
@proto_package("l3_fwd")
table l3_ipv4_fallback_table {
key = {
hdr.ipv4_base.dst_addr : lpm @proto_tag(1);
hdr.ipv4_base.dst_addr : selector @proto_tag(2);
hdr.ipv4_base.src_addr : selector @proto_tag(3);
hdr.ipv4_base.protocol : selector @proto_tag(4);
local_metadata.l4_src_port : selector @proto_tag(5);
local_metadata.l4_dst_port : selector @proto_tag(6);
}
actions = {
@proto_tag(1) set_nexthop;
@proto_tag(2) NoAction;
}
const default_action = NoAction();
implementation = wcmp_action_profile;
}
// LPM forwarding tables for IPV6 packets.
// @proto_package("l3_fwd")
// table l3_ipv6_override_table {
// key = {
// hdr.ipv6_base.dst_addr : lpm @proto_tag(1);
// hdr.ipv6_base.dst_addr : selector @proto_tag(2);
// hdr.ipv6_base.src_addr : selector @proto_tag(3);
// hdr.ipv6_base.flow_label : selector @proto_tag(4);
// local_metadata.l4_src_port : selector @proto_tag(5);
// local_metadata.l4_dst_port : selector @proto_tag(6);
// }
// actions = {
// @proto_tag(1) set_nexthop;
// }
// implementation = wcmp_action_profile;
// }
// @proto_package("l3_fwd")
// table l3_ipv6_vrf_table {
// key = {
// local_metadata.vrf_id: exact @proto_tag(1);
// hdr.ipv6_base.dst_addr : lpm @proto_tag(2);
// hdr.ipv6_base.dst_addr : selector @proto_tag(3);
// hdr.ipv6_base.src_addr : selector @proto_tag(4);
// hdr.ipv6_base.flow_label : selector @proto_tag(5);
// local_metadata.l4_src_port : selector @proto_tag(6);
// local_metadata.l4_dst_port : selector @proto_tag(7);
// }
// actions = {
// @proto_tag(1) set_nexthop;
// }
// implementation = wcmp_action_profile;
// }
// @proto_package("l3_fwd")
// table l3_ipv6_fallback_table {
// key = {
// hdr.ipv6_base.dst_addr : lpm @proto_tag(1);
// hdr.ipv6_base.dst_addr : selector @proto_tag(2);
// hdr.ipv6_base.src_addr : selector @proto_tag(3);
// hdr.ipv6_base.flow_label : selector @proto_tag(4);
// local_metadata.l4_src_port : selector @proto_tag(5);
// local_metadata.l4_dst_port : selector @proto_tag(6);
// }
// actions = {
// @proto_tag(1) set_nexthop;
// }
// implementation = wcmp_action_profile;
// }
apply {
if(l3_routing_classifier_table.apply().hit) {
if (hdr.ipv4_base.isValid()) {
if(!l3_ipv4_override_table.apply().hit) {
if(!l3_ipv4_vrf_table.apply().hit) {
l3_ipv4_fallback_table.apply();
}
}
if(hdr.ipv4_base.ttl == 0) {
mark_to_drop();
return;
}
}// else if (hdr.ipv6_base.isValid()) {
// if(!l3_ipv6_override_table.apply().hit) {
// if(!l3_ipv6_vrf_table.apply().hit) {
// l3_ipv6_fallback_table.apply();
// }
// }
// if(hdr.ipv6_base.hop_limit == 0) {
// mark_to_drop();
// return;
// }
// }
}
}
#ifdef P4_EXPLICIT_LAG
lag_handling() lag;
lag(hdr, local_metadata, standard_metadata);
#endif
} // end l3_fwd
#endif // P4_SPEC_L3_FWD_P4_