Skip to content

Commit 32c87a7

Browse files
committed
pcn-firewall: update connection tracking module
this commit introduces the same connection tracking module used by pcn-iptables Main features: - avoid double lookup by ordering hashmap keys - avoid to call bpf_ktime_get_ns() by introducing a customized timestamp written by control plane Signed-off-by: Matteo Bertrone <m.bertrone@gmail.com>
1 parent 0d21175 commit 32c87a7

25 files changed

Lines changed: 808 additions & 443 deletions

src/services/pcn-firewall/src/Chain.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,6 @@ void Chain::updateChain() {
244244
if (j == 1)
245245
second = true;
246246

247-
std::cout << "++++Conntrack Map empty " << conntrack_map.empty() << std::endl;
248-
249247
// Looping through conntrack
250248
if (!conntrack_map.empty() && conntrack_break ^ second) {
251249
// At least one rule requires a matching on conntrack, so it can be

src/services/pcn-firewall/src/Firewall.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ struct ct_k {
4949
struct ct_v {
5050
uint64_t ttl;
5151
uint8_t state;
52+
uint8_t ipRev;
53+
uint8_t portRev;
5254
uint32_t sequence;
5355
} __attribute__((packed));
5456

@@ -143,7 +145,9 @@ class Firewall : public FirewallBase {
143145

144146
polycube::service::ProgramType getProgramType();
145147

146-
public:
148+
std::mutex program_mutex_;
149+
150+
public:
147151
Program(const std::string &code, const int &index,
148152
const ChainNameEnum &direction, Firewall &outer);
149153
virtual ~Program();
@@ -289,6 +293,13 @@ class Firewall : public FirewallBase {
289293
Firewall &outer);
290294
~ConntrackTableUpdate();
291295
std::string getCode();
296+
297+
void updateTimestamp();
298+
void updateTimestampTimer();
299+
void quitAndJoin();
300+
301+
std::thread timestamp_update_thread_;
302+
std::atomic<bool> quit_thread_;
292303
};
293304

294305
/*==========================

src/services/pcn-firewall/src/SessionTable.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,6 @@ std::shared_ptr<spdlog::logger> SessionTable::logger() {
8383

8484
std::string SessionTable::state_from_number_to_string(int state) {
8585
switch (state) {
86-
case (WILDCARD):
87-
return "WILDCARD";
8886
case (NEW):
8987
return "NEW";
9088
case (ESTABLISHED):
@@ -93,8 +91,10 @@ std::string SessionTable::state_from_number_to_string(int state) {
9391
return "SYN_SENT";
9492
case (SYN_RECV):
9593
return "SYN_RECV";
96-
case (FIN_WAIT):
97-
return "FIN_WAIT";
94+
case (FIN_WAIT_1):
95+
return "FIN_WAIT_1";
96+
case (FIN_WAIT_2):
97+
return "FIN_WAIT_2";
9898
case (LAST_ACK):
9999
return "LAST_ACK";
100100
case (TIME_WAIT):
@@ -105,9 +105,6 @@ std::string SessionTable::state_from_number_to_string(int state) {
105105

106106
uint32_t SessionTable::from_ttl_to_eta(uint64_t ttl, uint16_t state,
107107
uint16_t l4proto) {
108-
if (state == WILDCARD) {
109-
return -1;
110-
}
111108
if (state == NEW) {
112109
if (l4proto == IPPROTO_UDP) {
113110
ttl = ttl - UDP_NEW_TIMEOUT;
@@ -128,7 +125,7 @@ uint32_t SessionTable::from_ttl_to_eta(uint64_t ttl, uint16_t state,
128125
if (state == SYN_RECV) {
129126
ttl = ttl - TCP_SYN_RECV;
130127
}
131-
if (state == FIN_WAIT) {
128+
if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
132129
ttl = ttl - TCP_FIN_WAIT;
133130
}
134131
if (state == LAST_ACK) {
@@ -146,6 +143,8 @@ uint32_t SessionTable::from_ttl_to_eta(uint64_t ttl, uint16_t state,
146143
} else {
147144
return uptime_seconds - ttl;
148145
}
146+
147+
return 0;
149148
}
150149

151150
//uint64_t SessionTable::hex_string_to_uint64(const std::string &str) {

src/services/pcn-firewall/src/SessionTable.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@
3333
#define TCP_TIME_WAIT 120000000000
3434

3535
enum {
36-
WILDCARD,
3736
NEW,
3837
ESTABLISHED,
3938
RELATED,
4039
INVALID,
4140
SYN_SENT,
4241
SYN_RECV,
43-
FIN_WAIT,
42+
FIN_WAIT_1,
43+
FIN_WAIT_2,
4444
LAST_ACK,
4545
TIME_WAIT
4646
};

src/services/pcn-firewall/src/Utils.cpp

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818
#include "Firewall.h"
1919

2020
int Firewall::protocol_from_string_to_int(const std::string &proto) {
21-
if (proto == "TCP")
21+
if (proto == "TCP" || proto == "tcp")
2222
return IPPROTO_TCP;
23-
if (proto == "UDP")
23+
if (proto == "UDP" || proto == "udp")
2424
return IPPROTO_UDP;
25-
if (proto == "ICMP")
25+
if (proto == "ICMP" || proto == "icmp")
2626
return IPPROTO_ICMP;
27-
if (proto == "GRE")
27+
if (proto == "GRE" || proto == "gre")
2828
return IPPROTO_GRE;
2929
else
3030
throw std::runtime_error("Protocol not supported.");
@@ -43,13 +43,13 @@ void Firewall::replaceAll(std::string &str, const std::string &from,
4343
}
4444

4545
int ChainRule::protocol_from_string_to_int(const std::string &proto) {
46-
if (proto == "TCP")
46+
if (proto == "TCP" || proto == "tcp")
4747
return IPPROTO_TCP;
48-
if (proto == "UDP")
48+
if (proto == "UDP" || proto == "udp")
4949
return IPPROTO_UDP;
50-
if (proto == "ICMP")
50+
if (proto == "ICMP" || proto == "icmp")
5151
return IPPROTO_ICMP;
52-
if (proto == "GRE")
52+
if (proto == "GRE" || proto == "gre")
5353
return IPPROTO_GRE;
5454

5555
throw std::runtime_error("Protocol not supported.");
@@ -207,15 +207,14 @@ int ChainRule::ActionEnum_to_int(const ActionEnum &action) {
207207
}
208208

209209
static int ChainRuleConntrackEnum_to_int(const ConntrackstatusEnum &status) {
210-
// 0 is reserved for "wildcard"
211210
if (status == ConntrackstatusEnum::NEW) {
212-
return 1;
211+
return 0;
213212
} else if (status == ConntrackstatusEnum::ESTABLISHED) {
214-
return 2;
213+
return 1;
215214
} else if (status == ConntrackstatusEnum::RELATED) {
216-
return 3;
215+
return 2;
217216
} else if (status == ConntrackstatusEnum::INVALID) {
218-
return 4;
217+
return 3;
219218
}
220219
}
221220

@@ -482,46 +481,40 @@ bool Chain::portFromRulesToMap(
482481
}
483482

484483
bool Chain::conntrackFromRulesToMap(
485-
std::map<uint8_t, std::vector<uint64_t>> &statusMap,
486-
const std::vector<std::shared_ptr<ChainRule>> &rules) {
487-
std::vector<uint16_t> dontCareRules;
484+
std::map<uint8_t, std::vector<uint64_t>> &statusMap,
485+
const std::vector<std::shared_ptr<ChainRule>> &rules) {
486+
std::vector<uint8_t> statesVector({NEW, ESTABLISHED, RELATED, INVALID});
487+
uint32_t rule_id;
488+
uint8_t rule_state;
489+
bool conntrackRulePresent = false;
488490

489-
uint32_t ruleId;
490-
uint8_t status;
491491
for (auto const &rule : rules) {
492492
try {
493-
ruleId = rule->getId();
494-
status = ChainRuleConntrackEnum_to_int(rule->getConntrack());
495-
496-
} catch (std::runtime_error re) {
497-
// Not set: don't care rule.
498-
dontCareRules.push_back(ruleId);
499-
continue;
500-
}
501-
502-
auto it = statusMap.find(status);
503-
if (it == statusMap.end()) {
504-
// First entry
505-
std::vector<uint64_t> bitVector(
506-
FROM_NRULES_TO_NELEMENTS(Firewall::maxRules));
507-
SET_BIT(bitVector[ruleId / 63], ruleId % 63);
508-
statusMap.insert(
509-
std::pair<uint8_t, std::vector<uint64_t>>(status, bitVector));
510-
} else {
511-
SET_BIT((it->second)[ruleId / 63], ruleId % 63);
493+
rule_state = ChainRuleConntrackEnum_to_int(rule->getConntrack());
494+
conntrackRulePresent = true;
495+
} catch (...) {
512496
}
513497
}
514-
// Don't care rules are in all entries. Anyway, this loop is useless if there
515-
// are no rules at all requiring matching on this field.
516-
if (statusMap.size() != 0 && dontCareRules.size() != 0) {
498+
499+
if (!conntrackRulePresent)
500+
return false;
501+
502+
for (uint8_t state : statesVector) {
517503
std::vector<uint64_t> bitVector(
518-
FROM_NRULES_TO_NELEMENTS(Firewall::maxRules));
519-
statusMap.insert(std::pair<uint8_t, std::vector<uint64_t>>(0, bitVector));
520-
for (auto const &ruleNumber : dontCareRules) {
521-
for (auto &statusMapEntry : statusMap) {
522-
SET_BIT((statusMapEntry.second)[ruleNumber / 63], ruleNumber % 63);
504+
FROM_NRULES_TO_NELEMENTS(Firewall::maxRules));
505+
for (auto const &rule : rules) {
506+
try {
507+
rule_id = rule->getId();
508+
rule_state = ChainRuleConntrackEnum_to_int(rule->getConntrack());
509+
if (rule_state == state)
510+
SET_BIT(bitVector[rule_id / 63], rule_id % 63);
511+
} catch (std::runtime_error re) {
512+
// wildcard rule, set bit to 1
513+
SET_BIT(bitVector[rule_id / 63], rule_id % 63);
523514
}
524515
}
516+
statusMap.insert(
517+
std::pair<uint8_t, std::vector<uint64_t>>(state, bitVector));
525518
}
526519

527520
return false;

src/services/pcn-firewall/src/datapaths/Firewall_ChainForwarder_dp.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ static int handle_rx(struct CTXTYPE *ctx, struct pkt_metadata *md) {
2222
pcn_log(ctx, LOG_DEBUG, "[_CHAIN_NAME][ChainForwarder]: Receiving packet");
2323
#if defined(_INGRESS_LOGIC)
2424
#if _NR_ELEMENTS_INGRESS > 0
25+
pcn_log(ctx, LOG_DEBUG, "[_CHAIN_NAME][ChainForwarder]: calling INGRESS chain _NEXT_HOP_INGRESS_1");
2526
call_ingress_program(ctx, _NEXT_HOP_INGRESS_1);
2627
#endif
2728
pcn_log(ctx, LOG_DEBUG, "[_CHAIN_NAME][ChainForwarder]: No ingress chain");
@@ -30,6 +31,7 @@ static int handle_rx(struct CTXTYPE *ctx, struct pkt_metadata *md) {
3031

3132
#if defined(_EGRESS_LOGIC)
3233
#if _NR_ELEMENTS_EGRESS > 0
34+
pcn_log(ctx, LOG_DEBUG, "[_CHAIN_NAME][ChainForwarder]: calling EGRESS chain _NEXT_HOP_EGRESS_1");
3335
call_egress_program(ctx, _NEXT_HOP_EGRESS_1);
3436
#endif
3537
pcn_log(ctx, LOG_DEBUG, "[_CHAIN_NAME][ChainForwarder]: No egress chain");

0 commit comments

Comments
 (0)