Skip to content

Commit

Permalink
PSA fixes for metadata fields class-of-service, timestamp, instance (#…
Browse files Browse the repository at this point in the history
…939)

* PSA fixes for metadata fields class-of-service, timestamp, instance
For both unicast and multicast packets, copy the class_of_service
field value from ingress to egress.

For all ingress packets, whether new from a port, recirculated, or
resubmitted, initialize the ingress_timestamp in one common place,
just before ingress parsing begins, as suggested in the PSA
specification.

Similarly for the egress_timestamp field initialized just before the
egress parsing begins.

For unicast packets, initialize the instance field seen by the egress
code to 0, as required by the PSA spec.

In the code for handling recirculated packets, eliminate some
redundant initialization of ingress_port and packet_path fields for
the ingress control.  They were redundant because ingress processing
always copied them from the pre-ingress-parser fields to the
pre-ingress-control fields every time ingress processing was
performed.

Initialize the egress_port field sent as input to the ingress
deparser.

* PSA make log message for received port show the value of ingress_port
This is the same as what was shown before this change for new packets
received on an external port, but shows the recirculation port number
for recirculated packets.
  • Loading branch information
jafingerhut authored Aug 23, 2020
1 parent 24e3e41 commit 5f9ad70
Showing 1 changed file with 27 additions and 16 deletions.
43 changes: 27 additions & 16 deletions targets/psa_switch/psa_switch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,6 @@ PsaSwitch::receive_(port_t port_num, const char *buffer, int len) {
// each add_header / remove_header primitive call
packet->set_register(PACKET_LENGTH_REG_IDX, len);

phv->get_field("psa_ingress_input_metadata.ingress_timestamp").set(
get_ts().count());

input_buffer.push_front(std::move(packet));
return 0;
}
Expand Down Expand Up @@ -292,12 +289,13 @@ PsaSwitch::ingress_thread() {
input_buffer.pop_back(&packet);
if (packet == nullptr) break;

port_t ingress_port = packet->get_ingress_port();
phv = packet->get_phv();
auto ingress_port =
phv->get_field("psa_ingress_parser_input_metadata.ingress_port").
get_uint();
BMLOG_DEBUG_PKT(*packet, "Processing packet received on port {}",
ingress_port);

phv = packet->get_phv();

/* Ingress cloning and resubmitting work on the packet before parsing.
`buffer_state` contains the `data_size` field which tracks how many
bytes are parsed by the parser ("lifted" into p4 headers). Here, we
Expand All @@ -308,11 +306,19 @@ PsaSwitch::ingress_thread() {

const Packet::buffer_state_t packet_in_state = packet->save_buffer_state();

// The PSA specification says that for all packets, whether they
// are new ones from a port, or resubmitted, or recirculated, the
// ingress_timestamp should be the time near when the packet began
// ingress processing. This one place for assigning a value to
// ingress_timestamp covers all cases.
phv->get_field("psa_ingress_input_metadata.ingress_timestamp").set(
get_ts().count());

Parser *parser = this->get_parser("ingress_parser");
parser->parse(packet.get());

// pass relevant values from ingress parser
// ingress_timestamp is already set at receive time
// ingress_timestamp is already set above
phv->get_field("psa_ingress_input_metadata.ingress_port").set(
phv->get_field("psa_ingress_parser_input_metadata.ingress_port"));
phv->get_field("psa_ingress_input_metadata.packet_path").set(
Expand Down Expand Up @@ -346,7 +352,8 @@ PsaSwitch::ingress_thread() {

packet->restore_buffer_state(packet_in_state);
phv->reset_metadata();
phv->get_field("psa_ingress_parser_input_metadata.packet_path").set(PACKET_PATH_RESUBMIT);
phv->get_field("psa_ingress_parser_input_metadata.packet_path").set(
PACKET_PATH_RESUBMIT);

input_buffer.push_front(std::move(packet));
continue;
Expand All @@ -356,6 +363,8 @@ PsaSwitch::ingress_thread() {
deparser->deparse(packet.get());

auto &f_packet_path = phv->get_field("psa_egress_parser_input_metadata.packet_path");
const auto &f_ig_cos = phv->get_field("psa_ingress_output_metadata.class_of_service");
const auto ig_cos = f_ig_cos.get_uint();

// handling multicast
unsigned int mgid = 0u;
Expand All @@ -368,6 +377,7 @@ PsaSwitch::ingress_thread() {
mgid);
const auto pre_out = pre->replicate({mgid});
auto &f_instance = phv->get_field("psa_egress_input_metadata.instance");
auto &f_eg_cos = phv->get_field("psa_egress_input_metadata.class_of_service");
auto packet_size = packet->get_register(PACKET_LENGTH_REG_IDX);
for(const auto &out : pre_out){
auto egress_port = out.egress_port;
Expand All @@ -378,6 +388,7 @@ PsaSwitch::ingress_thread() {
f_instance.set(instance);
// TODO use appropriate enum member from JSON
f_packet_path.set(PACKET_PATH_NORMAL_MULTICAST);
f_eg_cos.set(ig_cos);
std::unique_ptr<Packet> packet_copy = packet->clone_with_phv_ptr();
packet_copy->set_register(PACKET_LENGTH_REG_IDX, packet_size);
enqueue(egress_port, std::move(packet_copy));
Expand All @@ -386,10 +397,14 @@ PsaSwitch::ingress_thread() {
}

const auto &f_egress_port = phv->get_field("psa_ingress_output_metadata.egress_port");
auto &f_instance = phv->get_field("psa_egress_input_metadata.instance");
auto &f_eg_cos = phv->get_field("psa_egress_input_metadata.class_of_service");
port_t egress_port = f_egress_port.get_uint();
BMLOG_DEBUG_PKT(*packet, "Egress port is {}", egress_port);
f_instance.set(0);
// TODO use appropriate enum member from JSON
f_packet_path.set(PACKET_PATH_NORMAL_UNICAST);
f_eg_cos.set(ig_cos);

enqueue(egress_port, std::move(packet));
}
Expand Down Expand Up @@ -419,6 +434,8 @@ PsaSwitch::egress_thread(size_t worker_id) {
phv->reset();

phv->get_field("psa_egress_parser_input_metadata.egress_port").set(port);
phv->get_field("psa_egress_input_metadata.egress_timestamp").set(
get_ts().count());

Parser *parser = this->get_parser("egress_parser");
parser->parse(packet.get());
Expand All @@ -427,8 +444,6 @@ PsaSwitch::egress_thread(size_t worker_id) {
phv->get_field("psa_egress_parser_input_metadata.egress_port"));
phv->get_field("psa_egress_input_metadata.packet_path").set(
phv->get_field("psa_egress_parser_input_metadata.packet_path"));
phv->get_field("psa_egress_input_metadata.egress_timestamp")
.set(get_ts().count());
phv->get_field("psa_egress_input_metadata.parser_error").set(
packet->get_error_code().get());

Expand All @@ -441,6 +456,8 @@ PsaSwitch::egress_thread(size_t worker_id) {
egress_mau->apply(packet.get());
packet->reset_exit();
// TODO(peter): add stf test where exit is invoked but packet still gets recirc'd
phv->get_field("psa_egress_deparser_input_metadata.egress_port").set(
phv->get_field("psa_egress_parser_input_metadata.egress_port"));

Deparser *deparser = this->get_deparser("egress_deparser");
deparser->deparse(packet.get());
Expand All @@ -456,12 +473,6 @@ PsaSwitch::egress_thread(size_t worker_id) {
.set(PSA_PORT_RECIRCULATE);
phv->get_field("psa_ingress_parser_input_metadata.packet_path")
.set(PACKET_PATH_RECIRCULATE);
phv->get_field("psa_ingress_input_metadata.ingress_port")
.set(PSA_PORT_RECIRCULATE);
phv->get_field("psa_ingress_input_metadata.packet_path")
.set(PACKET_PATH_RECIRCULATE);
phv->get_field("psa_ingress_input_metadata.ingress_timestamp")
.set(get_ts().count());
input_buffer.push_front(std::move(packet));
continue;
}
Expand Down

0 comments on commit 5f9ad70

Please sign in to comment.