Skip to content

Commit

Permalink
Merge pull request #303 from s41m0n/dynmon/key_export_feature
Browse files Browse the repository at this point in the history
Dynmon enhancement - Key export feature
  • Loading branch information
frisso committed May 15, 2020
2 parents 6437c4d + 37e0a3c commit ad26207
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/services/pcn-dynmon/src/Dynmon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ std::vector<std::shared_ptr<Metrics>> Dynmon::getMetricsList() {
Metrics(*this, it->getName(), value.dump(), Utils::genTimestampMicroSeconds());
metrics.push_back(std::make_shared<Metrics>(metric));
} catch (const std::exception &ex) {
logger()->warn("{0}",ex.what());
logger()->warn("Unable to read {0} map", it->getMapName());
}
}
Expand Down
47 changes: 38 additions & 9 deletions src/services/pcn-dynmon/src/MapExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <iostream>
#include <string>

#include <linux/bpf.h>

#include "polycube/services/table_desc.h"

#define INT "int"
Expand Down Expand Up @@ -114,18 +116,45 @@ json MapExtractor::extractFromMap(BaseCube &cube_ref, string map_name, int index
auto value_desc = json::parse(string{desc.leaf_desc});
cube_ref.logger()->debug("{0} leaf_desc:\n{1}",map_name,value_desc.dump(2));

// Getting the RawTable
// Getting the RawTable, but parse entries only if map type is supported
auto table = cube_ref.get_raw_table(map_name, index, type);

// Getting the map entries
auto entries = getMapEntries(table, desc.key_size, desc.leaf_size);

json j_entries;
// Extracting the value of each map entry
for (auto &entry : entries) {
int offset = 0;
auto j_entry = recExtract(value_desc, entry->getValue(), offset);
j_entries.push_back(j_entry);
switch (desc.type) {
case BPF_MAP_TYPE_LRU_HASH:
case BPF_MAP_TYPE_HASH: {
// Case to handle simple hash types (key->value)

// Getting the map entries
auto entries = getMapEntries(table, desc.key_size, desc.leaf_size);

json key_desc = json::parse(string{desc.key_desc});
cube_ref.logger()->debug("{0} key_desc:\n{1}", map_name, key_desc.dump(2));
for (auto &entry : entries) {
int val_offset = 0, key_offset = 0;
json entry_obj;
entry_obj["key"] = recExtract(key_desc, entry->getKey(), key_offset);
entry_obj["value"] = recExtract(value_desc, entry->getValue(), val_offset);
j_entries.push_back(entry_obj);
}
break;
}
case BPF_MAP_TYPE_ARRAY: {
// Case to handle simple array types (index->value)

// Getting the map entries
auto entries = getMapEntries(table, desc.key_size, desc.leaf_size);

for (auto &entry : entries) {
int offset = 0;
auto j_entry = recExtract(value_desc, entry->getValue(), offset);
j_entries.push_back(j_entry);
}
break;
}
default: {
throw runtime_error("Unhandled Map Type " + std::to_string(desc.type) + " extraction.");
}
}
return j_entries;
}
Expand Down
86 changes: 86 additions & 0 deletions src/services/pcn-dynmon/test/test2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#! /bin/bash

# include helper.bash file: used to provide some common function across testing scripts
source "${BASH_SOURCE%/*}/helpers.bash"

# function cleanup: is invoked each time script exit (with or without errors)
# please remember to cleanup all entities previously created:
# namespaces, veth, cubes, ..
function cleanup {
set +e
polycubectl dynmon del dm
delete_veth 2
}
trap cleanup EXIT

# Enable verbose output
set -x

# Makes the script exit, at first error
# Errors are thrown by commands returning not 0 value
set -e

DIR=$(dirname "$0")

TYPE="TC"

if [ -n "$1" ]; then
TYPE=$1
fi

# helper.bash function, creates namespaces and veth connected to them
create_veth 2

# create instance of service dynmon
polycubectl dynmon add dm type=$TYPE
polycubectl dm show

# attaching the monitor to veth1
polycubectl attach dm veth1



# injecting a dataplane configuration
curl -H "Content-Type: application/json" "localhost:9000/polycube/v1/dynmon/dm/dataplane" --upload-file $DIR/test_map_extraction.json
polycubectl dm show

set +e
sudo ip netns exec ns1 ping 10.0.0.2 -c 1 -w 1
set -e

polycubectl dm metrics show

expected_sh='[{"key":{"saddr":1,"daddr":2,"sport":11,"dport":22,"proto":0},"value":0}]'
expected_sa='[{"timestamp":1010,"length":1010}]'
expected_shh='Unhandled Map Type 13 extraction.'
simple_hash_value=$(polycubectl dm metrics SIMPLE_HASH value show)
simple_array_value=$(polycubectl dm metrics SIMPLE_ARRAY value show)
set +e
simple_hash_hash_value=$(polycubectl dm metrics SIMPLE_HASH_OF_HASH value show)
set -e

if [ "$simple_array_value" != "$expected_sa" ]
then
echo "SIMPLE_ARRAY extraction failed"
echo "Expected: $expected_sa"
echo "Got: $simple_array_value"
exit 1
fi

if [ "$simple_hash_value" != "$expected_sh" ]
then
echo "SIMPLE_HASH extraction failed"
echo "Expected: $expected_sh"
echo "Got: $simple_hash_value"
exit 1
fi

if [ "$simple_hash_hash_value" != "$expected_shh" ]
then
echo "SIMPLE_HASH_OF_HASH extraction failed"
echo "Expected: $expected_shh"
echo "Got: $simple_hash_hash_value"
exit 1
fi

echo "All tests passed!"
33 changes: 33 additions & 0 deletions src/services/pcn-dynmon/test/test_map_extraction.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "Feature extractor probe",
"code": "#define IPPROTO_ICMP 1\n\nstruct features {\n uint64_t timestamp;\n uint16_t length;\n} __attribute__((packed));\n\nstruct session_key {\n __be32 saddr;\n __be32 daddr;\n __be16 sport;\n __be16 dport;\n __u8 proto;\n} __attribute__((packed));\n\n\nBPF_ARRAY(SIMPLE_ARRAY, struct features, 1);\nBPF_TABLE(\"hash\", struct session_key, int, SIMPLE_HASH, 1);\nBPF_HASH_OF_MAPS(SIMPLE_HASH_OF_HASH, \"SIMPLE_ARRAY\", 1);\n\nstatic __always_inline int handle_rx(struct CTXTYPE *ctx, struct pkt_metadata *md) {\n struct session_key key = {.saddr=1, .daddr=2, .sport=11, .dport=22, .proto=0};\n int i = 0;\n int *value = SIMPLE_HASH.lookup_or_try_init(&key, &i);\n \n struct features newVal = {.timestamp=1010, .length=1010};\n SIMPLE_ARRAY.update(&i, &newVal);\n\n return RX_OK;\n}\n",
"metrics": [
{
"name": "SIMPLE_HASH_OF_HASH",
"map-name": "SIMPLE_HASH_OF_HASH",
"open-metrics-metadata": {
"help": "This metric is a simple hash of hash map.",
"type": "counter",
"labels": []
}
},
{
"name": "SIMPLE_ARRAY",
"map-name": "SIMPLE_ARRAY",
"open-metrics-metadata": {
"help": "This metric is a simple array.",
"type": "counter",
"labels": []
}
},
{
"name": "SIMPLE_HASH",
"map-name": "SIMPLE_HASH",
"open-metrics-metadata": {
"help": "This is a simple hash map.",
"type": "counter",
"labels": []
}
}
]
}

0 comments on commit ad26207

Please sign in to comment.