Skip to content

Commit 4402b0d

Browse files
sangjinhanchanglan
authored andcommitted
Clean up code and C++-ify
1 parent e3d54ff commit 4402b0d

2 files changed

Lines changed: 79 additions & 113 deletions

File tree

core/modules/bpf.cc

Lines changed: 58 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,18 +1098,6 @@ static bpf_filter_func_t bpf_jit_compile(struct bpf_insn *prog, u_int nins,
10981098
/* Note: unmatched packets are sent to gate 0 */
10991099
#define SNAPLEN 0xffff
11001100

1101-
static int compare_filter(const void *filter1, const void *filter2) {
1102-
struct filter *f1 = (struct filter *)filter1;
1103-
struct filter *f2 = (struct filter *)filter2;
1104-
1105-
if (f1->priority > f2->priority)
1106-
return -1;
1107-
else if (f1->priority < f2->priority)
1108-
return 1;
1109-
else
1110-
return 0;
1111-
}
1112-
11131101
const Commands BPF::cmds = {
11141102
{"add", "BPFArg", MODULE_CMD_FUNC(&BPF::CommandAdd), 0},
11151103
{"clear", "EmptyArg", MODULE_CMD_FUNC(&BPF::CommandClear), 0}};
@@ -1119,61 +1107,55 @@ CommandResponse BPF::Init(const bess::pb::BPFArg &arg) {
11191107
}
11201108

11211109
void BPF::DeInit() {
1122-
for (int i = 0; i < n_filters_; i++) {
1110+
for (auto &filter: filters_) {
11231111
#ifdef __x86_64
1124-
munmap(reinterpret_cast<void *>(filters_[i].func), filters_[i].mmap_size);
1112+
munmap(reinterpret_cast<void *>(filter.func), filter.mmap_size);
11251113
#else
1126-
pcap_freecode(&(filters_[i].il_code));
1114+
pcap_freecode(&filter.il_code);
11271115
#endif
1128-
free(filters_[i].exp);
11291116
}
11301117

1131-
n_filters_ = 0;
1118+
filters_.clear();
11321119
}
11331120

11341121
CommandResponse BPF::CommandAdd(const bess::pb::BPFArg &arg) {
1135-
if (n_filters_ + arg.filters_size() > MAX_FILTERS) {
1136-
return CommandFailure(EINVAL, "Too many filters");
1137-
}
1138-
1139-
struct filter *filter = &filters_[n_filters_];
1140-
11411122
for (const auto &f : arg.filters()) {
1142-
const char *exp = f.filter().c_str();
1143-
int64_t gate = f.gate();
1144-
if (gate < 0 || gate >= MAX_GATES) {
1123+
if (f.gate() < 0 || f.gate() >= MAX_GATES) {
11451124
return CommandFailure(EINVAL, "Invalid gate");
11461125
}
1147-
filter->priority = f.priority();
1148-
filter->gate = f.gate();
1149-
filter->exp = strdup(exp);
1150-
#ifdef __x86_64
1151-
struct bpf_program il_code;
1126+
1127+
Filter filter;
1128+
filter.priority = f.priority();
1129+
filter.gate = f.gate();
1130+
filter.exp = f.filter();
1131+
1132+
struct bpf_program il;
11521133
if (pcap_compile_nopcap(SNAPLEN, DLT_EN10MB, // Ethernet
1153-
&il_code, exp, 1, // optimize (IL only)
1134+
&il, filter.exp.c_str(),
1135+
1, // optimize (IL only)
11541136
PCAP_NETMASK_UNKNOWN) == -1) {
11551137
return CommandFailure(EINVAL, "BPF compilation error");
11561138
}
1157-
filter->func =
1158-
bpf_jit_compile(il_code.bf_insns, il_code.bf_len, &filter->mmap_size);
1159-
pcap_freecode(&il_code);
1160-
if (!filter->func) {
1161-
free(filter->exp);
1139+
1140+
#ifdef __x86_64
1141+
filter.func = bpf_jit_compile(il.bf_insns, il.bf_len, &filter.mmap_size);
1142+
pcap_freecode(&il);
1143+
if (!filter.func) {
11621144
return CommandFailure(ENOMEM, "BPF JIT compilation error");
11631145
}
11641146
#else
1165-
if (pcap_compile_nopcap(SNAPLEN, DLT_EN10MB, // Ethernet
1166-
&(filter->il_code), exp, 1, // optimize (IL only)
1167-
PCAP_NETMASK_UNKNOWN) == -1) {
1168-
return CommandFailure(EINVAL, "BPF compilation error");
1169-
}
1147+
filter.il_code = il;
11701148
#endif
1171-
n_filters_++;
1172-
qsort(filters_, n_filters_, sizeof(struct filter), &compare_filter);
11731149

1174-
filter++;
1150+
filters_.push_back(filter);
11751151
}
11761152

1153+
std::sort(filters_.begin(), filters_.end(),
1154+
[](const Filter &a, const Filter &b) {
1155+
// descending order of priority number
1156+
return b.priority < a.priority;
1157+
});
1158+
11771159
return CommandSuccess();
11781160
}
11791161

@@ -1182,8 +1164,19 @@ CommandResponse BPF::CommandClear(const bess::pb::EmptyArg &) {
11821164
return CommandSuccess();
11831165
}
11841166

1185-
inline void BPF::process_batch_1filter(bess::PacketBatch *batch) {
1186-
struct filter *filter = &filters_[0];
1167+
inline bool BPF::Match(const Filter &filter, u_char *pkt, u_int wirelen,
1168+
u_int buflen) {
1169+
#ifdef __x86_64
1170+
int ret = filter.func(pkt, wirelen, buflen);
1171+
#else
1172+
int ret = bpf_filter(filter.il_code.bf_insns, pkt, wirelen, buflen);
1173+
#endif
1174+
1175+
return ret != 0;
1176+
}
1177+
1178+
void BPF::ProcessBatch1Filter(bess::PacketBatch *batch) {
1179+
const Filter &filter = filters_[0];
11871180

11881181
bess::PacketBatch out_batches[2];
11891182
bess::Packet **ptrs[2];
@@ -1195,75 +1188,47 @@ inline void BPF::process_batch_1filter(bess::PacketBatch *batch) {
11951188

11961189
for (int i = 0; i < cnt; i++) {
11971190
bess::Packet *pkt = batch->pkts()[i];
1198-
int ret;
1199-
int idx;
1200-
1201-
#ifdef __x86_64
1202-
ret = filter->func(pkt->head_data<uint8_t *>(), pkt->total_len(),
1203-
pkt->head_len());
1204-
#else
1205-
ret = bpf_filter(filter->il_code.bf_insns, pkt->head_data<uint8_t *>(),
1206-
pkt->total_len(), pkt->head_len());
12071191

1208-
if (ret != 0) {
1209-
ret = 1;
1192+
if (Match(filter, pkt->head_data<u_char *>(), pkt->total_len(),
1193+
pkt->head_len())) {
1194+
*(ptrs[1]++) = pkt;
1195+
} else {
1196+
*(ptrs[0]++) = pkt;
12101197
}
1211-
#endif
1212-
1213-
idx = ret & 1;
1214-
*(ptrs[idx]++) = pkt;
12151198
}
12161199

12171200
out_batches[0].set_cnt(ptrs[0] - out_batches[0].pkts());
12181201
out_batches[1].set_cnt(ptrs[1] - out_batches[1].pkts());
12191202

1220-
if (out_batches[0].cnt())
1221-
RunChooseModule(0, &out_batches[0]);
1222-
1223-
/* matched packets */
1224-
if (out_batches[1].cnt())
1225-
RunChooseModule(filter->gate, &out_batches[1]);
1203+
RunChooseModule(0, &out_batches[0]);
1204+
RunChooseModule(filter.gate, &out_batches[1]); // matched packets
12261205
}
12271206

12281207
void BPF::ProcessBatch(bess::PacketBatch *batch) {
12291208
gate_idx_t out_gates[bess::PacketBatch::kMaxBurst];
1230-
int n_filters = n_filters_;
1231-
int cnt;
1209+
int n_filters = filters_.size();
12321210

12331211
if (n_filters == 0) {
12341212
RunNextModule(batch);
12351213
return;
1236-
}
1237-
1238-
if (n_filters == 1) {
1239-
process_batch_1filter(batch);
1214+
} else if (n_filters == 1) {
1215+
ProcessBatch1Filter(batch);
12401216
return;
12411217
}
12421218

1243-
cnt = batch->cnt();
1244-
1245-
/* slow version for general cases */
1246-
for (int i = 0; i < cnt; i++) {
1219+
// slow version for general cases
1220+
for (int i = 0; i < batch->cnt(); i++) {
1221+
gate_idx_t gate = 0; // default gate for unmatched pkts
12471222
bess::Packet *pkt = batch->pkts()[i];
1248-
struct filter *filter = &filters_[0];
1249-
gate_idx_t gate = 0; /* default gate for unmatched pkts */
12501223

1251-
for (int j = 0; j < n_filters; j++, filter++) {
1252-
#ifdef __x86_64
1253-
if (filter->func(pkt->head_data<uint8_t *>(), pkt->total_len(),
1254-
pkt->head_len()) != 0) {
1255-
gate = filter->gate;
1224+
// high priority filters are checked first
1225+
for (const Filter &filter : filters_) {
1226+
if (Match(filter, pkt->head_data<uint8_t *>(), pkt->total_len(),
1227+
pkt->head_len())) {
1228+
gate = filter.gate;
12561229
break;
12571230
}
1258-
#else
1259-
if (bpf_filter(filter->il_code.bf_insns, pkt->head_data<uint8_t *>(),
1260-
pkt->total_len(), pkt->head_len())) {
1261-
gate = filter->gate;
1262-
break;
1263-
}
1264-
#endif
12651231
}
1266-
12671232
out_gates[i] = gate;
12681233
}
12691234

core/modules/bpf.h

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
11
#ifndef BESS_MODULES_BPF_H_
22
#define BESS_MODULES_BPF_H_
33

4-
#include "../module.h"
5-
#include "../module_msg.pb.h"
64
#include <pcap.h>
7-
#define MAX_FILTERS 128
85

9-
#ifdef __x86_64
10-
typedef u_int (*bpf_filter_func_t)(u_char *, u_int, u_int);
11-
#endif
6+
#include <vector>
127

13-
struct filter {
14-
#ifdef __x86_64
15-
bpf_filter_func_t func;
16-
size_t mmap_size; /* needed for munmap() */
17-
#else
18-
bpf_program il_code;
19-
#endif
20-
int gate;
21-
int priority; /* higher number == higher priority */
22-
char *exp; /* original filter expression string */
23-
};
8+
#include "../module.h"
9+
#include "../module_msg.pb.h"
10+
11+
using bpf_filter_func_t = u_int (*)(u_char *, u_int, u_int);
2412

2513
class BPF final : public Module {
2614
public:
@@ -37,10 +25,23 @@ class BPF final : public Module {
3725
CommandResponse CommandClear(const bess::pb::EmptyArg &arg);
3826

3927
private:
40-
struct filter filters_[MAX_FILTERS + 1] = {};
41-
int n_filters_ = {};
28+
struct Filter {
29+
#ifdef __x86_64
30+
bpf_filter_func_t func;
31+
size_t mmap_size; // needed for munmap()
32+
#else
33+
bpf_program il_code;
34+
#endif
35+
int gate;
36+
int priority; // higher number == higher priority
37+
std::string exp; // original filter expression string
38+
};
39+
40+
static bool Match(const Filter &, u_char *, u_int, u_int);
41+
42+
void ProcessBatch1Filter(bess::PacketBatch *batch);
4243

43-
inline void process_batch_1filter(bess::PacketBatch *batch);
44+
std::vector<Filter> filters_;
4445
};
4546

4647
#endif // BESS_MODULES_BPF_H_

0 commit comments

Comments
 (0)