Skip to content

Commit 3983a57

Browse files
authored
fix(conntrack): delete keys in eBPF instead of user space (#831)
# Description Delete TCP connections in `retina_conntrack` map directly in the eBPF layer instead of relying on the userspace process to delete it later when the connection is closing and has exceeded its lifetime. * remove `is_closing` flag from `retina_conntrack` map, update userspace and bpf program accordingly * delete connection from `retina_conntrack` map if connection is timed out or when FIN or RST flags are set * invoke `bpf_map_delete_elem` in`_ct_should_report_packet` and remove update `seen_flags` and `last_report` ## Related Issue fix #807 ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/contributing). - [x] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [x] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project. --------- Signed-off-by: Simone Rodigari <[email protected]>
1 parent 11f190d commit 3983a57

File tree

4 files changed

+13
-21
lines changed

4 files changed

+13
-21
lines changed

pkg/plugin/conntrack/_cprog/conntrack.c

+9-17
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ struct ct_entry {
6161
*/
6262
__u8 flags_seen_tx_dir;
6363
__u8 flags_seen_rx_dir;
64-
bool is_closing; // is_closing indicates if the connection is closing.
6564
};
6665

6766
struct {
@@ -72,7 +71,6 @@ struct {
7271
__uint(pinning, LIBBPF_PIN_BY_NAME); // needs pinning so this can be access from other processes .i.e debug cli
7372
} retina_conntrack SEC(".maps");
7473

75-
7674
/**
7775
* Helper function to reverse a key.
7876
* @arg reverse_key The key to store the reversed key.
@@ -177,7 +175,6 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
177175
return false;
178176
}
179177
new_value.eviction_time = now + CT_CONNECTION_LIFETIME_TCP;
180-
new_value.is_closing = (p->flags & (TCP_FIN | TCP_RST)) != 0x0;
181178
new_value.traffic_direction = _ct_get_traffic_direction(observation_point);
182179
p->traffic_direction = new_value.traffic_direction;
183180

@@ -221,12 +218,13 @@ static __always_inline bool _ct_handle_new_connection(struct packet *p, struct c
221218
* @arg protocol The protocol of the packet (TCP or UDP).
222219
* Returns true if the packet should be reported to userspace. False otherwise.
223220
*/
224-
static __always_inline bool _ct_should_report_packet(struct ct_entry *entry, __u8 flags, __u8 direction, __u8 protocol) {
221+
static __always_inline bool _ct_should_report_packet(struct ct_entry *entry, __u8 flags, __u8 direction, struct ct_v4_key *key) {
225222
// Check for null parameters.
226223
if (!entry) {
227224
return false;
228225
}
229226

227+
__u8 protocol = key->proto;
230228
__u64 now = bpf_mono_now();
231229
__u32 eviction_time = READ_ONCE(entry->eviction_time);
232230
__u8 seen_flags;
@@ -243,15 +241,9 @@ static __always_inline bool _ct_should_report_packet(struct ct_entry *entry, __u
243241

244242
// Check if the connection timed out or if it is a TCP connection and FIN or RST flags are set.
245243
if (now >= eviction_time || (protocol == IPPROTO_TCP && flags & (TCP_FIN | TCP_RST))) {
246-
// The connection is closing or closed. Mark the connection as closing. Update the flags seen and last report time.
247-
WRITE_ONCE(entry->is_closing, true);
248-
if (direction == CT_PACKET_DIR_TX) {
249-
WRITE_ONCE(entry->flags_seen_tx_dir, flags);
250-
WRITE_ONCE(entry->last_report_tx_dir, now);
251-
} else {
252-
WRITE_ONCE(entry->flags_seen_rx_dir, flags);
253-
WRITE_ONCE(entry->last_report_rx_dir, now);
254-
}
244+
// The connection is closing or closed. Delete the connection from the map
245+
bpf_map_delete_elem(&retina_conntrack, key);
246+
255247
return true; // Report the last packet received.
256248
}
257249
// Update the eviction time of the connection.
@@ -287,7 +279,8 @@ static __always_inline bool _ct_should_report_packet(struct ct_entry *entry, __u
287279
* @arg observation_point The point in the network stack where the packet is observed.
288280
* Returns true if the packet should be report to userspace. False otherwise.
289281
*/
290-
static __always_inline __attribute__((unused)) bool ct_process_packet(struct packet *p, __u8 observation_point) {
282+
static __always_inline __attribute__((unused)) bool ct_process_packet(struct packet *p, __u8 observation_point) {
283+
291284
if (!p) {
292285
return false;
293286
}
@@ -307,14 +300,13 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
307300
// Update the packet accordingly.
308301
p->is_reply = false;
309302
p->traffic_direction = entry->traffic_direction;
310-
return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_TX, key.proto);
303+
return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_TX, &key);
311304
}
312305

313306
// The connection is not found in the send direction. Check the reply direction by reversing the key.
314307
struct ct_v4_key reverse_key;
315308
__builtin_memset(&reverse_key, 0, sizeof(struct ct_v4_key));
316309
_ct_reverse_key(&reverse_key, &key);
317-
318310
// Lookup the connection in the map based on the reverse key.
319311
entry = bpf_map_lookup_elem(&retina_conntrack, &reverse_key);
320312

@@ -323,7 +315,7 @@ static __always_inline __attribute__((unused)) bool ct_process_packet(struct pac
323315
// Update the packet accordingly.
324316
p->is_reply = true;
325317
p->traffic_direction = entry->traffic_direction;
326-
return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_RX, key.proto);
318+
return _ct_should_report_packet(entry, p->flags, CT_PACKET_DIR_RX, &key);
327319
}
328320

329321
// If the connection is still not found, the connection is new.

pkg/plugin/conntrack/conntrack_bpfel_x86.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/plugin/conntrack/conntrack_linux.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,12 @@ func (ct *Conntrack) Run(ctx context.Context) error {
9292
var noOfCtEntries, entriesDeleted int
9393
// List of keys to be deleted
9494
var keysToDelete []conntrackCtV4Key
95+
9596
iter := ct.ctMap.Iterate()
9697
for iter.Next(&key, &value) {
9798
noOfCtEntries++
9899
// Check if the connection is closing or has expired
99-
if value.IsClosing || ktime.MonotonicOffset.Seconds()+float64(value.EvictionTime) < float64((time.Now().Unix())) {
100+
if ktime.MonotonicOffset.Seconds()+float64(value.EvictionTime) < float64((time.Now().Unix())) {
100101
// Iterating a hash map from which keys are being deleted is not safe.
101102
// So, we store the keys to be deleted in a list and delete them after the iteration.
102103
keyCopy := key // Copy the key to avoid using the same key in the next iteration
@@ -115,7 +116,6 @@ func (ct *Conntrack) Run(ctx context.Context) error {
115116
zap.String("proto", decodeProto(key.Proto)),
116117
zap.Uint32("eviction_time", value.EvictionTime),
117118
zap.Uint8("traffic_direction", value.TrafficDirection),
118-
zap.Bool("is_closing", value.IsClosing),
119119
zap.String("flags_seen_tx_dir", decodeFlags(value.FlagsSeenTxDir)),
120120
zap.String("flags_seen_rx_dir", decodeFlags(value.FlagsSeenRxDir)),
121121
zap.Uint32("last_reported_tx_dir", value.LastReportTxDir),

pkg/plugin/packetparser/packetparser_bpfel_x86.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)