Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ core/extra.mk
core/extra.dpdk.mk
core/kmod/.cache.mk
*.retry
.mypy_cache
*.cache.mk

# Vagrant stores temporary files in env/.vagrant
env/.vagrant
Expand Down
77 changes: 70 additions & 7 deletions bessctl/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,22 @@ def get_var_attrs(cli, var_token, partial_word):
var_type = 'gate'
var_desc = 'input gate of a module (default 0)'

elif var_token == 'GATEHOOKCLASS':

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside: I'd like to simplify all this code at some point, if there were a good way to make this more table-driven for instance. I haven't quite figured out how to do that yet though.

var_type = 'name'
var_desc = 'name of a gatehook class'
try:
var_candidates = cli.bess.list_gatehook_classes().names
except:
pass

elif var_token == 'GATEHOOKCLASS...':
var_type = 'name+'
var_desc = 'one or more gatehook class names'
try:
var_candidates = cli.bess.list_gatehook_classes().names
except:
pass

elif var_token == '[ENV_VARS...]':
var_type = 'map'
var_desc = 'Environmental variables for configuration'
Expand Down Expand Up @@ -1447,27 +1463,29 @@ def _show_module(cli, module_name):
for gate in info.igates:
track_str = 'batches N/A packets N/A'
try:
track_str = 'batches %-16d packets %-16d' % (gate.cnt,
track_str = 'batches %-11d packets %-12d' % (gate.cnt,
gate.pkts)
except:
pass
cli.fout.write(' %5d: %s %s\n' %
cli.fout.write(' %3d: %s %s\t%s\n' %
(gate.igate, track_str,
', '.join('%s:%d ->' % (g.name, g.ogate)
for g in gate.ogates)))
for g in gate.ogates),
', '.join(gate.hook_name)))

if len(info.ogates) > 0:
cli.fout.write(' Output gates:\n')
for gate in info.ogates:
track_str = 'batches N/A packets N/A'
try:
track_str = 'batches %-16d packets %-16d' % (gate.cnt,
track_str = 'batches %-11d packets %-12d' % (gate.cnt,
gate.pkts)
except:
pass
cli.fout.write(
' %5d: %s -> %d:%s\n' %
(gate.ogate, track_str, gate.igate, gate.name))
' %3d: %s -> %d:%s\t%s\n' %
(gate.ogate, track_str, gate.igate, gate.name,
', '.join(gate.hook_name)))

if hasattr(info, 'dump'):
dump_str = pprint.pformat(info.dump, width=74)
Expand Down Expand Up @@ -1521,6 +1539,51 @@ def show_mclass_list(cli, cls_names):
_show_mclass(cli, cls_name, True)


@cmd('show gatehook', 'Show the status of all gatehook')
def show_gatehook_all(cli):
gatehooks = cli.bess.list_gatehooks().hooks

if not gatehooks:
raise cli.CommandError('There is no active gatehook to show.')

for gatehook in gatehooks:
if gatehook.HasField('igate'):
cli.fout.write('%-16s %d:%s\n' % (gatehook.hook_name, gatehook.igate,
gatehook.module_name))
else:
cli.fout.write('%-16s %s:%d\n' % (gatehook.hook_name,
gatehook.module_name, gatehook.ogate))


def _show_gatehook_class(cli, cls_name, detail):
info = cli.bess.get_gatehook_class_info(cls_name)
cli.fout.write('%-16s %s\n' % (info.name, info.help))

if detail:
if len(info.cmds) > 0:
cli.fout.write('\t\t commands: %s\n' %
(', '.join(map(lambda cmd, msg: "%s(%s)"
% (cmd, msg),
info.cmds,
info.cmd_args))))
else:
cli.fout.write('\t\t (no commands)\n')


@cmd('show gatehookclass', 'Show all gatehook classes')
def show_gatahook_class_all(cli):
gatehook_classes = cli.bess.list_gatehook_classes().names
for cls_name in gatehook_classes:
_show_gatehook_class(cli, cls_name, False)


@cmd('show gatehookclass GATEHOOKCLASS...',
'Show the details of specified gate classes')
def show_gatehook_class_list(cli, cls_names):
for cls_name in cls_names:
_show_gatehook_class(cli, cls_name, True)


@cmd('import plugin PLUGIN_FILE', 'Import the specified plugin (*.so)')
def import_plugin(cli, plugin):
cli.bess.pause_all()
Expand Down Expand Up @@ -1937,7 +2000,7 @@ def track_module_bits(cli, flag, module_name, direction, gate):
@cmd('track reset MODULE DIRECTION GATE',
'Reset counts of packets, batches, and bits on specified gate')
def track_reset(cli, module_name, direction, gate):
cli.bess.run_gate_command('track', module_name, direction, gate, 'reset',
cli.bess.run_gate_command('Track', module_name, direction, gate, 'reset',
'EmptyArg', {})


Expand Down
48 changes: 48 additions & 0 deletions core/bessctl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ static int collect_igates(Module* m, GetModuleInfoResponse* response) {
ogate->set_ogate(og->gate_idx());
ogate->set_name(og->module()->name());
}

for (const auto& hook : g->hooks()) {
igate->add_hook_name(hook->name());
}
}

return 0;
Expand All @@ -218,6 +222,10 @@ static int collect_ogates(Module* m, GetModuleInfoResponse* response) {
}
ogate->set_name(g->igate()->module()->name());
ogate->set_igate(g->igate()->gate_idx());

for (const auto& hook : g->hooks()) {
ogate->add_hook_name(hook->name());
}
}

return 0;
Expand Down Expand Up @@ -1367,6 +1375,46 @@ class BESSControlImpl final : public BESSControl::Service {
return Status::OK;
}

Status ListGateHookClass(ServerContext*, const EmptyRequest*,
ListGateHookClassResponse* response) override {
std::lock_guard<std::recursive_mutex> lock(mutex_);

for (const auto& pair : bess::GateHookFactory::all_gate_hook_factories()) {
const auto& factory = pair.second;
response->add_names(factory.hook_name());
}
return Status::OK;
}

Status GetGateHookClassInfo(ServerContext*,
const GetGateHookClassInfoRequest* request,
GetGateHookClassInfoResponse* response) override {
std::lock_guard<std::recursive_mutex> lock(mutex_);

VLOG(1) << "GetGateHookClassInfo from client:" << std::endl
<< request->DebugString();
if (!request->name().length()) {
return return_with_error(response, EINVAL,
"Argument must be a name in str");
}

const std::string& cls_name = request->name();
const auto& it = bess::GateHookFactory::all_gate_hook_factories().find(cls_name);
if (it == bess::GateHookFactory::all_gate_hook_factories().end()) {
return return_with_error(response, ENOENT, "No gatehook class '%s' found",
cls_name.c_str());
}
const bess::GateHookFactory* cls = &it->second;

response->set_name(cls->hook_name());
response->set_help(cls->help_text());
for (const auto& cmd : cls->cmds()) {
response->add_cmds(cmd.first);
response->add_cmd_args(cmd.second);
}
return Status::OK;
}

Status ListGateHooks(ServerContext*, const EmptyRequest*,
ListGateHooksResponse* response) override {
std::lock_guard<std::recursive_mutex> lock(mutex_);
Expand Down
6 changes: 4 additions & 2 deletions core/gate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ const GateHookCommands GateHook::cmds;
bool GateHookFactory::RegisterGateHook(GateHook::constructor_t constructor,
const GateHookCommands &cmds,
GateHook::init_func_t init_func,
const std::string &hook_name) {
const std::string &hook_name,
const std::string &help_text) {
return all_gate_hook_factories_holder()
.emplace(std::piecewise_construct, std::forward_as_tuple(hook_name),
std::forward_as_tuple(constructor, cmds, init_func, hook_name))
std::forward_as_tuple(constructor, cmds, init_func, hook_name,
help_text))
.second;
}

Expand Down
24 changes: 19 additions & 5 deletions core/gate.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,23 +119,35 @@ class GateHookFactory {
public:
GateHookFactory(GateHook::constructor_t constructor,
const GateHookCommands &cmds, GateHook::init_func_t init_func,
const std::string &hook_name)
const std::string &hook_name, const std::string &help_text)
: hook_constructor_(constructor),
cmds_(cmds),
hook_init_func_(init_func),
hook_name_(hook_name) {}
hook_name_(hook_name),
help_text_(help_text){}

static bool RegisterGateHook(GateHook::constructor_t constructor,
const GateHookCommands &cmds,
GateHook::init_func_t init_func,
const std::string &hook_name);
const std::string &hook_name,
const std::string &help_text);

static std::map<std::string, GateHookFactory> &all_gate_hook_factories_holder(
bool reset = false);

static const std::map<std::string, GateHookFactory>
&all_gate_hook_factories();

const std::string &hook_name() const { return hook_name_; }
const std::string &help_text() const { return help_text_; }

const std::vector<std::pair<std::string, std::string>> cmds() const {
std::vector<std::pair<std::string, std::string>> ret;
for (auto &cmd : cmds_)
ret.push_back(std::make_pair(cmd.cmd, cmd.arg_type));
return ret;
}

CommandResponse RunCommand(GateHook *hook, const std::string &user_cmd,
const google::protobuf::Any &arg) const;

Expand All @@ -146,6 +158,7 @@ class GateHookFactory {
const GateHookCommands cmds_;
GateHook::init_func_t hook_init_func_;
std::string hook_name_;
std::string help_text_;
};

inline CommandResponse GateHook::RunCommand(const std::string &cmd,
Expand Down Expand Up @@ -277,9 +290,10 @@ static inline bess::GateHook::init_func_t InitGateHookWithGenericArg(
};
}

#define ADD_GATE_HOOK(_HOOK) \
#define ADD_GATE_HOOK(_HOOK, _HELP) \
bool __gate_hook__##_HOOK = bess::GateHookFactory::RegisterGateHook( \
std::function<bess::GateHook *()>([]() { return new _HOOK(); }), \
_HOOK::cmds, InitGateHookWithGenericArg(&_HOOK::Init), _HOOK::kName);
_HOOK::cmds, InitGateHookWithGenericArg(&_HOOK::Init), _HOOK::kName, \
_HELP);

#endif // BESS_GATE_H_
4 changes: 2 additions & 2 deletions core/gate_hooks/pcapng.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void BytesToHexDump(const void *src, size_t len, char *dst) {

} // namespace

const std::string Pcapng::kName = "pcapng";
const std::string Pcapng::kName = "PcapNg";

Pcapng::Pcapng()
: bess::GateHook(Pcapng::kName, Pcapng::kPriority),
Expand Down Expand Up @@ -247,4 +247,4 @@ void Pcapng::ProcessBatch(const bess::PacketBatch *batch) {
}
}

ADD_GATE_HOOK(Pcapng)
ADD_GATE_HOOK(Pcapng, "metadata-dump-able packet dump")
4 changes: 2 additions & 2 deletions core/gate_hooks/tcpdump.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#include "../utils/pcap.h"
#include "../utils/time.h"

const std::string Tcpdump::kName = "tcpdump";
const std::string Tcpdump::kName = "TcpDump";

bool TcpdumpOpener::InitFifo(int fd) {
static const struct pcap_hdr hdr = {
Expand Down Expand Up @@ -104,4 +104,4 @@ void Tcpdump::ProcessBatch(const bess::PacketBatch *batch) {
}
}

ADD_GATE_HOOK(Tcpdump)
ADD_GATE_HOOK(Tcpdump, "dump traffic on a network")
4 changes: 2 additions & 2 deletions core/gate_hooks/track.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
// Ethernet overhead in bytes
static const size_t kEthernetOverhead = 24;

const std::string Track::kName = "track";
const std::string Track::kName = "Track";

const GateHookCommands Track::cmds = {{"reset", "EmptyArg",
GATE_HOOK_CMD_FUNC(&Track::CommandReset),
Expand Down Expand Up @@ -74,4 +74,4 @@ void Track::ProcessBatch(const bess::PacketBatch *batch) {
}
}

ADD_GATE_HOOK(Track)
ADD_GATE_HOOK(Track, "count the packets and batches")
25 changes: 22 additions & 3 deletions protobuf/bess_msg.proto
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ message GetModuleInfoResponse {
uint64 pkts = 4; /// # of packets seen
uint64 bytes = 5; /// # of bytes seen
double timestamp = 6; /// The time that cnt/pkts counters were read
repeated string hook_name = 7; /// List of hooks per gate
}
message OGate {
uint64 ogate = 1; /// Output gate ID
Expand All @@ -420,6 +421,7 @@ message GetModuleInfoResponse {
double timestamp = 5; /// The time thatcnt/pkts counters were read
string name = 6; /// Name of the "next" module it connects to
uint64 igate = 7; /// Input gate ID of the "next" module
repeated string hook_name = 8; /// List of hooks per gate
}
message Attribute {
string name = 1; /// Name of per-packet metadata attribute
Expand All @@ -442,7 +444,7 @@ message ConnectModulesRequest {
uint64 ogate = 3; /// m1's output gate ID
uint64 igate = 4; /// m2's input gate ID
/// If true do not attach default hooks at the input/output gate.
/// (Currently, the only default hook is the "track" hook at the ogate)
/// (Currently, the only default hook is the "Track" hook at the ogate)
bool skip_default_hooks = 5;
}

Expand Down Expand Up @@ -490,9 +492,26 @@ message CommandResponse {
// Gate hooks
// -------------------------------------------------------------------------

/// Enable/Disable the "track" hook on a gate (or all gates)
message ListGateHookClassResponse {
Error error = 1;
repeated string names = 2; /// List of gatehook types
}

message GetGateHookClassInfoRequest {
string name = 1; /// Name of gatehook type
}

message GetGateHookClassInfoResponse {
Error error = 1;
string name = 2; /// Name of gatehook type
string help = 3; /// 1=line description of the gatehook type
repeated string cmds = 4; /// List of commands supported by the gatehook
repeated string cmd_args = 5; /// Corresponding Protobuf message types
}

/// Enable/Disable the "Track" hook on a gate (or all gates)
///
/// "track" hook accumulates the number of total packets, batches and bits
/// "Track" hook accumulates the number of total packets, batches and bits
/// passing through a gate. This incurs some amount of CPU overheads. While
/// the cost is very small, remember that the delay adds up at every gate.
///
Expand Down
8 changes: 7 additions & 1 deletion protobuf/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,16 @@ service BESSControl {
// Gate hooks
// -------------------------------------------------------------------------

/// Enumerate all gatehook types available
rpc ListGateHookClass (EmptyRequest) returns (ListGateHookClassResponse) {}

/// Query detailed information of a gatehook type
rpc GetGateHookClassInfo (GetGateHookClassInfoRequest) returns (GetGateHookClassInfoResponse) {}

/// Enable/Disable a gate hook.
rpc ConfigureGateHook (ConfigureGateHookRequest) returns (CommandResponse) {}

/// Enable/Disable a gate hook.
/// Enumerate all gatehook installed
rpc ListGateHooks (EmptyRequest) returns (ListGateHooksResponse) {}

/// Send command to gate hook instance.
Expand Down
Loading