Skip to content

Commit

Permalink
PSA Counter Extern (#767)
Browse files Browse the repository at this point in the history
* create counter as an extern in psa

* counters read and written correctly

* remove unused file

* support counter write in runtime_CLI

* added liscense and counter reset

* added psa namespace

* patched runtime_CLI to better support counter writes

* mark counter_arrays as special

* syntax, remove macro, counter_array not PSA_Counter should be hidden

* style and renaming count primitive
  • Loading branch information
derek-so authored and antoninbas committed Apr 24, 2019
1 parent c39179f commit 884e01b
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 26 deletions.
2 changes: 1 addition & 1 deletion targets/psa_switch/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ THRIFT_IDL = $(srcdir)/thrift/psa_switch.thrift

noinst_LTLIBRARIES = libpsaswitch.la

libpsaswitch_la_SOURCES = psa_switch.cpp psa_switch.h primitives.cpp
libpsaswitch_la_SOURCES = psa_switch.cpp psa_switch.h primitives.cpp externs/psa_counter.h externs/psa_counter.cpp

libpsaswitch_la_LIBADD = \
$(top_builddir)/src/bm_sim/libbmsim.la \
Expand Down
58 changes: 58 additions & 0 deletions targets/psa_switch/externs/psa_counter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* Copyright 2019-present Derek So
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*
* Derek So ([email protected])
*
*/


#include "psa_counter.h"

namespace bm {

namespace psa {

void
PSA_Counter::count(const Data &index) {
_counter->get_counter(
index.get<size_t>()).increment_counter(get_packet());
}

Counter &
PSA_Counter::get_counter(size_t idx) {
return _counter->get_counter(idx);
}

const Counter &
PSA_Counter::get_counter(size_t idx) const {
return _counter->get_counter(idx);
}

Counter::CounterErrorCode
PSA_Counter::reset_counters(){
return _counter->reset_counters();
}

BM_REGISTER_EXTERN_W_NAME(Counter, PSA_Counter);
BM_REGISTER_EXTERN_W_NAME_METHOD(Counter, PSA_Counter, count, const Data &);

} // namespace bm::psa

} // namespace bm

int import_counters(){
return 0;
}
68 changes: 68 additions & 0 deletions targets/psa_switch/externs/psa_counter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* Copyright 2019-present Derek So
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*
* Derek So ([email protected])
*
*/


#ifndef PSA_SWITCH_PSA_COUNTER_H_
#define PSA_SWITCH_PSA_COUNTER_H_

#include <bm/bm_sim/extern.h>
#include <bm/bm_sim/counters.h>

namespace bm {

namespace psa {

class PSA_Counter : public bm::ExternType {
public:
static constexpr p4object_id_t spec_id = 0xffffffff;

BM_EXTERN_ATTRIBUTES {
BM_EXTERN_ATTRIBUTE_ADD(n_counters);
BM_EXTERN_ATTRIBUTE_ADD(type);
}

void init() override {
_counter = std::unique_ptr<CounterArray>(
new CounterArray(get_name() + ".$impl",
spec_id,
n_counters.get<size_t>()));
}

void count(const Data &index);

Counter &get_counter(size_t idx);

const Counter &get_counter(size_t idx) const;

Counter::CounterErrorCode reset_counters();

size_t size() const { return _counter->size(); };

private:
Data n_counters;
Data type;
std::unique_ptr<CounterArray> _counter;
};

} // namespace bm::psa

} // namespace bm

#endif
5 changes: 3 additions & 2 deletions targets/psa_switch/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@
#include "psa_switch.h"

namespace {
PsaSwitch *psa_switch;
bm::psa::PsaSwitch *psa_switch;
bm::TargetParserBasic *psa_switch_parser;
} // namespace

namespace pswitch_runtime {
shared_ptr<PsaSwitchIf> get_handler(PsaSwitch *sw);
shared_ptr<PsaSwitchIf> get_handler(bm::psa::PsaSwitch *sw);
} // namespace pswitch_runtime

int
main(int argc, char* argv[]) {
using bm::psa::PsaSwitch;
psa_switch = new PsaSwitch();
psa_switch_parser = new bm::TargetParserBasic();
psa_switch_parser->add_flag_option("enable-swap",
Expand Down
18 changes: 7 additions & 11 deletions targets/psa_switch/primitives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,9 @@
#include <random>
#include <thread>

template <typename... Args>
using ActionPrimitive = bm::ActionPrimitive<Args...>;

using bm::Data;
using bm::Field;
using bm::Header;
using bm::MeterArray;
using bm::CounterArray;
using bm::RegisterArray;
using bm::NamedCalculation;
using bm::HeaderStack;
namespace bm {

namespace psa {

class modify_field : public ActionPrimitive<Data &, const Data &> {
void operator ()(Data &dst, const Data &src) {
Expand Down Expand Up @@ -398,6 +390,10 @@ class truncate_ : public ActionPrimitive<const Data &> {

REGISTER_PRIMITIVE_W_NAME("truncate", truncate_);

} // namespace bm::psa

} // namespace psa

// dummy function, which ensures that this unit is not discarded by the linker
// it is being called by the constructor of PsaSwitch
// the previous alternative was to have all the primitives in a header file (the
Expand Down
10 changes: 10 additions & 0 deletions targets/psa_switch/psa_switch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ REGISTER_HASH(hash_ex);
REGISTER_HASH(bmv2_hash);

extern int import_primitives();
extern int import_counters();

namespace bm {

namespace psa {

packet_id_t PsaSwitch::packet_id = 0;

Expand Down Expand Up @@ -130,6 +135,7 @@ PsaSwitch::PsaSwitch(bool enable_swap)
force_arith_header("psa_egress_deparser_input_metadata");

import_primitives();
import_counters();
}

#define PACKET_LENGTH_REG_IDX 0
Expand Down Expand Up @@ -403,3 +409,7 @@ PsaSwitch::egress_thread(size_t worker_id) {
output_buffer.push_front(std::move(packet));
}
}

} // namespace bm::psa

} // namespace bm
66 changes: 54 additions & 12 deletions targets/psa_switch/psa_switch.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#include <vector>
#include <functional>

#include "externs/psa_counter.h"

// TODO(antonin)
// experimental support for priority queueing
// to enable it, uncomment this flag
Expand All @@ -51,19 +53,9 @@ using ts_res = std::chrono::microseconds;
using std::chrono::duration_cast;
using ticks = std::chrono::nanoseconds;

using bm::Switch;
using bm::Queue;
using bm::Packet;
using bm::PHV;
using bm::Parser;
using bm::Deparser;
using bm::Pipeline;
using bm::McSimplePreLAG;
using bm::Field;
using bm::FieldList;
using bm::packet_id_t;
using bm::p4object_id_t;
namespace bm {

namespace psa {

class PsaSwitch : public Switch {
public:
Expand Down Expand Up @@ -119,6 +111,52 @@ class PsaSwitch : public Switch {

void set_transmit_fn(TransmitFn fn);

// overriden interfaces
Counter::CounterErrorCode
read_counters(cxt_id_t cxt_id,
const std::string &counter_name,
size_t index,
MatchTableAbstract::counter_value_t *bytes,
MatchTableAbstract::counter_value_t *packets) override {
auto *context = get_context(cxt_id);
auto *ex = context->get_extern_instance(counter_name).get();
if (!ex) return Counter::CounterErrorCode::INVALID_COUNTER_NAME;
auto *counter = static_cast<PSA_Counter*>(ex);
if (index >= counter->size())
return Counter::CounterErrorCode::INVALID_INDEX;
counter->get_counter(index).query_counter(bytes, packets);
return Counter::CounterErrorCode::SUCCESS;
}

Counter::CounterErrorCode
write_counters(cxt_id_t cxt_id,
const std::string &counter_name,
size_t index,
MatchTableAbstract::counter_value_t bytes,
MatchTableAbstract::counter_value_t packets) override {
auto *context = get_context(cxt_id);
auto *ex = context->get_extern_instance(counter_name).get();
if (!ex) return Counter::CounterErrorCode::INVALID_COUNTER_NAME;
auto *counter = static_cast<PSA_Counter*>(ex);
if (index >= counter->size())
return Counter::CounterErrorCode::INVALID_INDEX;
counter->get_counter(index).write_counter(bytes, packets);
return Counter::CounterErrorCode::SUCCESS;
}

Counter::CounterErrorCode
reset_counters(cxt_id_t cxt_id,
const std::string &counter_name) override {
Context *context = get_context(cxt_id);
ExternType *ex = context->get_extern_instance(counter_name).get();
if (!ex) return Counter::CounterErrorCode::INVALID_COUNTER_NAME;
PSA_Counter *counter = static_cast<PSA_Counter*>(ex);
return counter->reset_counters();
}

// TODO(derek): override RuntimeInterface methods not yet supported
// by psa_switch and log an error msg / return error code

private:
static constexpr size_t nb_egress_threads = 4u;
static constexpr port_t PSA_PORT_RECIRCULATE = 0xfffffffa;
Expand Down Expand Up @@ -188,4 +226,8 @@ class PsaSwitch : public Switch {
bool with_queueing_metadata{false};
};

} // namespace bm::psa

} // namespace bm

#endif // PSA_SWITCH_PSA_SWITCH_H_
2 changes: 2 additions & 0 deletions targets/psa_switch/thrift/src/PsaSwitch_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ namespace thrift_provider = apache::thrift;

#include "psa_switch.h"

using namespace bm::psa;

namespace pswitch_runtime {

class PsaSwitchHandler : virtual public PsaSwitchIf {
Expand Down
33 changes: 33 additions & 0 deletions tools/runtime_CLI.py
Original file line number Diff line number Diff line change
Expand Up @@ -1907,6 +1907,39 @@ def do_counter_read(self, line):
def complete_counter_read(self, text, line, start_index, end_index):
return self._complete_counters(text)

@handle_bad_input
def do_counter_write(self, line):
"Write counter value: counter_write <name> <index> <packets> <bytes>"
args = line.split()
self.exactly_n_args(args, 4)
counter_name = args[0]
counter = self.get_res("counter", counter_name, ResType.counter_array)
index = args[1]
pkts = args[2]
byts = args[3]
try:
index = int(index)
except:
raise UIn_Error("Bad format for index")
try:
pkts = int(pkts)
except:
raise UIn_Error("Bad format for packets")
try:
byts = int(byts)
except:
raise UIn_Error("Bad format for bytes")
if counter.is_direct:
table_name = counter.binding
print "writing to direct counter for table", table_name
value = self.client.bm_mt_write_counter(0, table_name, index, BmCounterValue(packets=pkts, bytes = byts))
else:
self.client.bm_counter_write(0, counter_name, index, BmCounterValue(packets=pkts, bytes = byts))
print "%s[%d] has been updated" % (counter_name, index)

def complete_counter_write(self, text, line, start_index, end_index):
return self._complete_counters(text)

@handle_bad_input
def do_counter_reset(self, line):
"Reset counter: counter_reset <name>"
Expand Down

0 comments on commit 884e01b

Please sign in to comment.