Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added TCP Flags to Flow Record metrics #68

Merged
merged 25 commits into from
Jan 18, 2023
Merged

Added TCP Flags to Flow Record metrics #68

merged 25 commits into from
Jan 18, 2023

Conversation

shach33
Copy link
Contributor

@shach33 shach33 commented Nov 21, 2022

I added a 16 bit flag to every record. The TCP header is read and 8 flags (fin, syn, rst, psh, ack, urg, ece, cwr) are added to bits 0-7 in flags member of metrics struct.
During accumulation, the flags member is bitwise OR'ed to get all flags in bits 0-7.

@mariomac
Copy link

mariomac commented Nov 21, 2022

@shach33 Thank you for your contribution! In order to facilitate the C code review, could you keep the original indent configuration? It's 4 spaces, no tab.

proto/flow.proto Outdated Show resolved Hide resolved
@ronensc
Copy link

ronensc commented Dec 5, 2022

@shach33 Thank you very much for this PR! :)
I am interested in the TCP flags to allow the connection tracking module in FLP to identify which of the endpoints started the connection (i.e. who sent the first SYN).

IIUC accumulating all the flags of the flowlogs with bitwise OR won't allow me to find which endpoint started the connection.

As known, in TCP the 3-step handshake goes like this:

  1. client -> server: SYN
  2. server -> client: SYN+ACK
  3. client -> server: ACK

I think that it is most likely that the packets of step 1 and 3 will end up in the same flowlog. In this case, that flowlog will have both SYN and ACK flags making it indistinguishable from the flowlog of step 2.
Please correct me if I'm wrong.

cc @eranra @jotak @mariomac

@praveingk
Copy link
Collaborator

praveingk commented Dec 6, 2022

@shach33 Thank you very much for this PR! :) I am interested in the TCP flags to allow the connection tracking module in FLP to identify which of the endpoints started the connection (i.e. who sent the first SYN).

IIUC accumulating all the flags of the flowlogs with bitwise OR won't allow me to find which endpoint started the connection.

As known, in TCP the 3-step handshake goes like this:

  1. client -> server: SYN
  2. server -> client: SYN+ACK
  3. client -> server: ACK

I think that it is most likely that the packets of step 1 and 3 will end up in the same flowlog. In this case, that flowlog will have both SYN and ACK flags making it indistinguishable from the flowlog of step 2. Please correct me if I'm wrong.

cc @eranra @jotak @mariomac

Hi @ronensc , Thanks for highlighting that. Yes, you are right, we might need to capture only Syn/Fin/Rst in the MSB of the u16 flag, which might help in getting that info.

For eg. The logic in the ebpf code could be :

#define TCP_SYN_BIT 0x80
#define TCP_FIN_BIT 0x40
#define TCP_RST_BIT 0x20

if tcp->syn==1 && tcp->ack==0 {
    flags_t = flags_t | TCP_SYN_BIT;
}
if tcp->fin==1 && tcp->ack==0 {
    flags_t = flags_t | TCP_FIN_BIT;
}
if tcp->rst==1 && tcp->ack==0 {
    flags_t = flags_t | TCP_RST_BIT;
}

// Rest of the logic to aggregate flags_t from the TCP header

Does that work? Additionally, We would like to know more such use-cases where aggregation of flags_t is not very useful., so that we can address them here.
Also, would like to know if there are more information from the TCP header you would like us to capture in the flags.

@ronensc
Copy link

ronensc commented Dec 6, 2022

Thanks @praveingk
I had a discussion with @eranra about your suggestion.
We think that it might work for the use case of identifying the first SYN. But, if we set the SYN flag in a flowlog only when the ACK flag is not set in the packet, then the flowlog of the SYN+ACK packet won't have the SYN flag set. So using the term "TCP flags" in the context of flowlogs feels inaccurate. We can use a different term for these flags such as "start" to avoid confusion.

We also talked about that in latency measurements, we need to spot both the SYN and SYN+ACK flowlogs. And in the suggested approach this is not possible.

We suggest other alternatives:

  1. Aggregate packets into flowlogs based on their TCP flags. In other words, packets with different TCP flags will end up in different flowlogs.

  2. Instead of having a bitwise-or aggregation of the TCP flags, having a list of the unique TCP flags combination. For example, if a flowlog consists of 3 packets with the flags [SYN, ACK, ACK] then the flowlog will have the 2-item list [SYN, ACK]. And if a flowlog consists of 3 pakcets with the flags [SYN+ACK, ACK, ACK] then the flowlog will have the 2-item list [SYN+ACK, ACK].

@praveingk
Copy link
Collaborator

Thanks @praveingk I had a discussion with @eranra about your suggestion. We think that I might work for the use case of identifying the first SYN. But, if we set the SYN flag in a flowlog only when the ACK flag is not set in the packet, then the flowlog of the SYN+ACK packet won't have the SYN flag set. So using the term "TCP flags" in the context of flowlogs feels inaccurate. We can use a different term for these flags such as "start" to avoid confusion.

We also talked about that in latency measurements, we need to spot both the SYN and SYN+ACK flowlogs. And in the suggested approach this is not possible.

We suggest other alternatives:

  1. Aggregate packets into flowlogs based on their TCP flags. In other words, packets with different TCP flags will end up in different flowlogs.
  2. Instead of having a bitwise-or aggregation of the TCP flags, having a list of the unique TCP flags combination. For example, if a flowlog consists of 3 packets with the flags [SYN, ACK, ACK] then the flowlog will have the 2-item list [SYN, ACK]. And if a flowlog consists of 3 pakcets with the flags [SYN+ACK, ACK, ACK] then the flowlog will have the 2-item list [SYN+ACK, ACK].

@ronensc : Yes, I understand the point, and I agree. Can you confirm if the list of combinations that can be incorporated in the eBPF code are below:

  1. SYN
  2. FIN
  3. RST
  4. SYN+ACK
  5. FIN+ACK
  6. RST+ACK
  7. URG
  8. PSH
  9. ECE
  10. CWR

@ronensc
Copy link

ronensc commented Dec 7, 2022

I think this list is sufficient.
@eranra WDYT?

@eranra
Copy link
Collaborator

eranra commented Dec 7, 2022

I think this list is sufficient. @eranra WDYT?

This is precisely what we need !!!

@ronensc @praveingk @shach33 ^^^

@mariomac
Copy link

mariomac commented Dec 9, 2022

@ronensc with respect to:

Instead of having a bitwise-or aggregation of the TCP flags, having a list of the unique TCP flags combination. For example, if a flowlog consists of 3 packets with the flags [SYN, ACK, ACK] then the flowlog will have the 2-item list [SYN, ACK]. And if a flowlog consists of 3 pakcets with the flags [SYN+ACK, ACK, ACK] then the flowlog will have the 2-item list [SYN+ACK, ACK].

I have concerns with respect to the implementation on that. AFAIK, eBPF doesn't allow dynamic memory to be created. That would mean that, for each record, you'd need to create a big-enough, fixed-size array to store the flag sequences. I'm afraid this could impact in the overall memory and performance.

bpf/flows.c Outdated Show resolved Hide resolved
proto/flow.proto Outdated Show resolved Hide resolved
@shach33
Copy link
Contributor Author

shach33 commented Dec 12, 2022

I am working on it. Will push the changes soon.

@praveingk
Copy link
Collaborator

@ronensc with respect to:

Instead of having a bitwise-or aggregation of the TCP flags, having a list of the unique TCP flags combination. For example, if a flowlog consists of 3 packets with the flags [SYN, ACK, ACK] then the flowlog will have the 2-item list [SYN, ACK]. And if a flowlog consists of 3 pakcets with the flags [SYN+ACK, ACK, ACK] then the flowlog will have the 2-item list [SYN+ACK, ACK].

I have concerns with respect to the implementation on that. AFAIK, eBPF doesn't allow dynamic memory to be created. That would mean that, for each record, you'd need to create a big-enough, fixed-size array to store the flag sequences. I'm afraid this could impact in the overall memory and performance.

Hi @mariomac , including the combinations, we have only 10 possibilities, which can be stored in u16 with a bit mask. That should be ok right?

@mariomac
Copy link

@praveingk yes, a 16-bit number it's fine. Maybe I misunderstood @ronensc message and I thought some kind of list/array would be implemented to store that information.

@ronensc
Copy link

ronensc commented Dec 14, 2022

@praveingk yes, a 16-bit number it's fine. Maybe I misunderstood @ronensc message and I thought some kind of list/array would be implemented to store that information.

@mariomac you got me right. I wan't aware of eBPF limitations...

bpf/flows.c Outdated Show resolved Hide resolved
pkg/exporter/kafka_proto_test.go Show resolved Hide resolved
bpf/flows.c Outdated Show resolved Hide resolved
bpf/flows.c Outdated Show resolved Hide resolved
bpf/flows.c Outdated Show resolved Hide resolved
pkg/flow/record.go Outdated Show resolved Hide resolved
@praveingk
Copy link
Collaborator

@shach33 Can you rebase this PR to main branch since there are merge conflicts. After the rebase, I would like to add flags to ipfix export as well.

Copy link

@mariomac mariomac left a comment

Choose a reason for hiding this comment

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

Much better, thanks! Few minor comments.

bpf/flows.c Outdated Show resolved Hide resolved
pkg/exporter/proto.go Outdated Show resolved Hide resolved
@codecov-commenter
Copy link

codecov-commenter commented Jan 11, 2023

Codecov Report

Merging #68 (509b40d) into main (6a351f2) will increase coverage by 0.10%.
The diff coverage is 6.66%.

❗ Current head 509b40d differs from pull request most recent head d5a2ef2. Consider uploading reports for the commit d5a2ef2 to get more accurate results

@@            Coverage Diff             @@
##             main      #68      +/-   ##
==========================================
+ Coverage   41.50%   41.60%   +0.10%     
==========================================
  Files          29       29              
  Lines        1983     1978       -5     
==========================================
  Hits          823      823              
+ Misses       1122     1116       -6     
- Partials       38       39       +1     
Flag Coverage Δ
unittests 41.60% <6.66%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
pkg/agent/ip.go 70.40% <ø> (ø)
pkg/exporter/ipfix.go 0.00% <0.00%> (ø)
pkg/exporter/proto.go 100.00% <100.00%> (ø)
pkg/flow/record.go 83.33% <100.00%> (+0.47%) ⬆️
pkg/exporter/grpc_proto.go 57.14% <0.00%> (-14.29%) ⬇️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@mariomac mariomac self-requested a review January 12, 2023 10:04
@@ -97,7 +138,7 @@ static inline int fill_iphdr(struct iphdr *ip, void *data_end, flow_id *id) {
}

// sets flow fields from IPv6 header information
static inline int fill_ip6hdr(struct ipv6hdr *ip, void *data_end, flow_id *id) {
static inline int fill_ip6hdr(struct ipv6hdr *ip, void *data_end, flow_id *id, u16 *flags) {
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't we call set_flags here too, in case IPPROTO_TCP block?

Choose a reason for hiding this comment

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

Good catch! We always forget to test IPv6 :-(

Copy link
Member

@jotak jotak left a comment

Choose a reason for hiding this comment

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

lgtm!

@jotak
Copy link
Member

jotak commented Jan 18, 2023

Merging!
Kudos @shach33 @praveingk

@jotak jotak merged commit 45b4757 into netobserv:main Jan 18, 2023
shach33 added a commit to praveingk/netobserv-ebpf-agent that referenced this pull request Apr 6, 2023
* Test commit

* Adding TCP flags

* Adding TCP flags to record metrics.TODO: Remove log stmts

* Updated tcp flags u32-> u16

* Updated indentation in C file

* Update flow.h

* Indent fixed. Tab -> 4 space

fixing indents

Indent fixes for flows.c

Indent fixes for flows.c-II

Still fixing indents

* Removed extra file

* Added clang-format config to bpf/. To use clang-format -i <file.c>

* Fixed message record member sequences

* Added TCP Flags combinations Read from flw

Updated changes according to comments on PR

* Removed log statements.

Rebase merges

* Fixing merge conflits

* Revert the renaming of grpc_test file

* Simplify setting flags for v4,v6

* Add flags to ipfix exporter

* Update protobuf

* Remove type conversions due to conflicts

* Remove .gitignore change

* Fix indentation

* Remove commented line

* Fixed typecast errors since move to go 1.18

* Reverting commit d1e9c44. Added changes as separate PR

* set flags for v6

Co-authored-by: Pravein Govindan Kannan <pravein.govindan.kannan@ibm.com>
shach33 added a commit to praveingk/netobserv-ebpf-agent that referenced this pull request Apr 6, 2023
* Test commit

* Adding TCP flags

* Adding TCP flags to record metrics.TODO: Remove log stmts

* Updated tcp flags u32-> u16

* Updated indentation in C file

* Update flow.h

* Indent fixed. Tab -> 4 space

fixing indents

Indent fixes for flows.c

Indent fixes for flows.c-II

Still fixing indents

* Removed extra file

* Added clang-format config to bpf/. To use clang-format -i <file.c>

* Fixed message record member sequences

* Added TCP Flags combinations Read from flw

Updated changes according to comments on PR

* Removed log statements.

Rebase merges

* Fixing merge conflits

* Revert the renaming of grpc_test file

* Simplify setting flags for v4,v6

* Add flags to ipfix exporter

* Update protobuf

* Remove type conversions due to conflicts

* Remove .gitignore change

* Fix indentation

* Remove commented line

* Fixed typecast errors since move to go 1.18

* Reverting commit d1e9c44. Added changes as separate PR

* set flags for v6

Co-authored-by: Pravein Govindan Kannan <pravein.govindan.kannan@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants