Skip to content

Commit 9740aa3

Browse files
ronenscjpinsonneau
andauthored
conntrack: handle TCP flags (#391)
* Update ebpf-agent dependency go get github.com/netobserv/netobserv-ebpf-agent@latest go get github.com/netobserv/flowlogs-pipeline/pkg/pipeline go mod vendor * Fix Generic related build issues * Add Flags fields to decode_protobuf * Rename test funcions * Handle FIN_ACK * Add a test for MoveToFront * Validate TCPFlags field name is not empty * Add correct direction * Add test case for mismatch of AB field count * Add operational metric for tcp flags * Rename CorrectDirection -> SwapAB * Change test * Update README * Add json tag to conntrack api * Update docs * Rename variable * Make linter happy * Make linter happy Subjects() has been deprecated in Go 1.18: golang/go#46287 * Enable SwapAB only when the feature flag is set * Fix rebase errors * NETOBSERV-838 fix IsDuplicate * Add missing 'omitempty' * Add parenthesis for clarity * Add tests for IsDuplicate() --------- Co-authored-by: Julien Pinsonneau <[email protected]>
1 parent 203a766 commit 9740aa3

36 files changed

+804
-410
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,9 @@ While, in bidirectional setting, they are grouped together.
567567
568568
Bidirectional setting requires defining both `fieldGroupARef` and `fieldGroupBRef` sections to allow the connection
569569
tracking module to identify which set of fields can swap values and still be considered as the same connection.
570+
The pairs of fields that can swap are determined by their order in the fieldGroup.
571+
In the example below, `SrcAddr` and `DstAddr` are first in their fieldGroup, so they are swappable.
572+
The same is true for `SrcPort` and `DstPort` which are second.
570573
571574
The configuration example below defines a bidirectional setting. So flow-logs that have the values of `SrcAddr` and `SrcPort`
572575
swapped with `DstAddr` and `DstPort` are grouped together as long as they have the same `Proto` field.

docs/api.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,10 @@ Following is the supported API format for specifying connection tracking:
237237
endConnectionTimeout: duration of time to wait from the last flow log to end a connection
238238
heartbeatInterval: duration of time to wait between heartbeat reports of a connection
239239
maxConnectionsTracked: maximum number of connections we keep in our cache (0 means no limit)
240+
tcpFlags: settings for handling TCP flags
241+
fieldName: name of the field containing TCP flags
242+
detectEndConnection: detect end connections by FIN_ACK flag
243+
swapAB: swap source and destination when the first flowlog contains the SYN_ACK flag
240244
</pre>
241245
## Time-based Filters API
242246
Following is the supported API format for specifying metrics time-based filters:

docs/operational-metrics.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ Each table below provides documentation for an exported flowlogs-pipeline operat
3131
| **Labels** | type |
3232

3333

34+
### conntrack_tcp_flags
35+
| **Name** | conntrack_tcp_flags |
36+
|:---|:---|
37+
| **Description** | The total number of actions taken based on TCP flags. |
38+
| **Type** | counter |
39+
| **Labels** | action |
40+
41+
3442
### encode_prom_errors
3543
| **Name** | encode_prom_errors |
3644
|:---|:---|

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/netobserv/flowlogs-pipeline
22

3-
go 1.17
3+
go 1.18
44

55
require (
66
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
@@ -13,9 +13,9 @@ require (
1313
github.com/mariomac/guara v0.0.0-20220523124851-5fc279816f1f
1414
github.com/minio/minio-go/v7 v7.0.44
1515
github.com/mitchellh/mapstructure v1.4.3
16-
github.com/netobserv/gopipes v0.2.0
16+
github.com/netobserv/gopipes v0.3.0
1717
github.com/netobserv/loki-client-go v0.0.0-20220927092034-f37122a54500
18-
github.com/netobserv/netobserv-ebpf-agent v0.2.4-0.20221220155455-aa7838d82f4d
18+
github.com/netobserv/netobserv-ebpf-agent v0.2.4
1919
github.com/netsampler/goflow2 v1.1.1-0.20220509155230-5300494e4785
2020
github.com/pkg/errors v0.9.1
2121
github.com/prometheus/client_golang v1.12.1

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,10 +788,14 @@ github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV
788788
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
789789
github.com/netobserv/gopipes v0.2.0 h1:CnJQq32+xNuM85eVYy/HOf+StTJdh2K6RdaEg7NAJDg=
790790
github.com/netobserv/gopipes v0.2.0/go.mod h1:eGoHZW1ON8Dx/zmDXUhsbVNqatPjtpdO0UZBmGZGmVI=
791+
github.com/netobserv/gopipes v0.3.0 h1:IYmPnnAVCdSK7VmHmpFhrVBOEm45qpgbZmJz1sSW+60=
792+
github.com/netobserv/gopipes v0.3.0/go.mod h1:N7/Gz05EOF0CQQSKWsv3eof22Cj2PB08Pbttw98YFYU=
791793
github.com/netobserv/loki-client-go v0.0.0-20220927092034-f37122a54500 h1:RmnoJe/ci5q+QdM7upFdxiU+D8F3L3qTd5wXCwwHefw=
792794
github.com/netobserv/loki-client-go v0.0.0-20220927092034-f37122a54500/go.mod h1:LHXpc5tjKvsfZn0pwLKrvlgEhZcCaw3Di9mUEZGAI4E=
793795
github.com/netobserv/netobserv-ebpf-agent v0.2.4-0.20221220155455-aa7838d82f4d h1:1tn5bJBtv44nglFmMlAbxWYf78Lz3RFxqTxZUsrXKaQ=
794796
github.com/netobserv/netobserv-ebpf-agent v0.2.4-0.20221220155455-aa7838d82f4d/go.mod h1:sKo7bEgMHchUkD+0c0qTQXZxQDRdgiPzKD9kgdRxgLU=
797+
github.com/netobserv/netobserv-ebpf-agent v0.2.4 h1:I8dLLF4NJvnO8HPcZIzgEutMh9sP2YHWZcaZa+3osX8=
798+
github.com/netobserv/netobserv-ebpf-agent v0.2.4/go.mod h1:IRGkUU+tFKr7mbaT/KyQDmuY3Nk4V1IwEZkNezzYLj0=
795799
github.com/netobserv/prometheus-common v0.31.2-0.20220720134304-43e74fd22881 h1:hx5bi6xBovRjmwUoVJBzhJ3EDo4K4ZUsqqKrJuQ2vMI=
796800
github.com/netobserv/prometheus-common v0.31.2-0.20220720134304-43e74fd22881/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
797801
github.com/netsampler/goflow2 v1.1.1-0.20220509155230-5300494e4785 h1:qhDrIMXlk8YV7BxwA6UR/dQVdUzohjLlmrUXymsBx6g=

pkg/api/conntrack.go

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,33 +28,33 @@ const (
2828
)
2929

3030
type ConnTrack struct {
31-
// TODO: should by a pointer instead?
32-
KeyDefinition KeyDefinition `yaml:"keyDefinition,omitempty" doc:"fields that are used to identify the connection"`
33-
OutputRecordTypes []string `yaml:"outputRecordTypes,omitempty" enum:"ConnTrackOutputRecordTypeEnum" doc:"output record types to emit"`
34-
OutputFields []OutputField `yaml:"outputFields,omitempty" doc:"list of output fields"`
35-
Scheduling []ConnTrackSchedulingGroup `yaml:"scheduling,omitempty" doc:"list of timeouts and intervals to apply per selector"`
36-
MaxConnectionsTracked int `yaml:"maxConnectionsTracked,omitempty" doc:"maximum number of connections we keep in our cache (0 means no limit)"`
31+
KeyDefinition KeyDefinition `yaml:"keyDefinition,omitempty" json:"keyDefinition,omitempty" doc:"fields that are used to identify the connection"`
32+
OutputRecordTypes []string `yaml:"outputRecordTypes,omitempty" json:"outputRecordTypes,omitempty" enum:"ConnTrackOutputRecordTypeEnum" doc:"output record types to emit"`
33+
OutputFields []OutputField `yaml:"outputFields,omitempty" json:"outputFields,omitempty" doc:"list of output fields"`
34+
Scheduling []ConnTrackSchedulingGroup `yaml:"scheduling,omitempty" json:"scheduling,omitempty" doc:"list of timeouts and intervals to apply per selector"`
35+
MaxConnectionsTracked int `yaml:"maxConnectionsTracked,omitempty" json:"maxConnectionsTracked,omitempty" doc:"maximum number of connections we keep in our cache (0 means no limit)"`
36+
TCPFlags ConnTrackTCPFlags `yaml:"tcpFlags,omitempty" json:"tcpFlags,omitempty" doc:"settings for handling TCP flags"`
3737
}
3838

3939
type ConnTrackOutputRecordTypeEnum struct {
40-
NewConnection string `yaml:"newConnection" doc:"New connection"`
41-
EndConnection string `yaml:"endConnection" doc:"End connection"`
42-
Heartbeat string `yaml:"heartbeat" doc:"Heartbeat"`
43-
FlowLog string `yaml:"flowLog" doc:"Flow log"`
40+
NewConnection string `yaml:"newConnection" json:"newConnection" doc:"New connection"`
41+
EndConnection string `yaml:"endConnection" json:"endConnection" doc:"End connection"`
42+
Heartbeat string `yaml:"heartbeat" json:"heartbeat" doc:"Heartbeat"`
43+
FlowLog string `yaml:"flowLog" json:"flowLog" doc:"Flow log"`
4444
}
4545

4646
func ConnTrackOutputRecordTypeName(operation string) string {
4747
return GetEnumName(ConnTrackOutputRecordTypeEnum{}, operation)
4848
}
4949

5050
type KeyDefinition struct {
51-
FieldGroups []FieldGroup `yaml:"fieldGroups,omitempty" doc:"list of field group definitions"`
52-
Hash ConnTrackHash `yaml:"hash,omitempty" doc:"how to build the connection hash"`
51+
FieldGroups []FieldGroup `yaml:"fieldGroups,omitempty" json:"fieldGroups,omitempty" doc:"list of field group definitions"`
52+
Hash ConnTrackHash `yaml:"hash,omitempty" json:"hash,omitempty" doc:"how to build the connection hash"`
5353
}
5454

5555
type FieldGroup struct {
56-
Name string `yaml:"name,omitempty" doc:"field group name"`
57-
Fields []string `yaml:"fields" doc:"list of fields in the group"`
56+
Name string `yaml:"name,omitempty" json:"name,omitempty" doc:"field group name"`
57+
Fields []string `yaml:"fields" json:"fields" doc:"list of fields in the group"`
5858
}
5959

6060
// ConnTrackHash determines how to compute the connection hash.
@@ -64,35 +64,41 @@ type FieldGroup struct {
6464
// When they are not set, a different hash will be computed for A->B and B->A,
6565
// and they are tracked as different connections.
6666
type ConnTrackHash struct {
67-
FieldGroupRefs []string `yaml:"fieldGroupRefs,omitempty" doc:"list of field group names to build the hash"`
68-
FieldGroupARef string `yaml:"fieldGroupARef,omitempty" doc:"field group name of endpoint A"`
69-
FieldGroupBRef string `yaml:"fieldGroupBRef,omitempty" doc:"field group name of endpoint B"`
67+
FieldGroupRefs []string `yaml:"fieldGroupRefs,omitempty" json:"fieldGroupRefs,omitempty" doc:"list of field group names to build the hash"`
68+
FieldGroupARef string `yaml:"fieldGroupARef,omitempty" json:"fieldGroupARef,omitempty" doc:"field group name of endpoint A"`
69+
FieldGroupBRef string `yaml:"fieldGroupBRef,omitempty" json:"fieldGroupBRef,omitempty" doc:"field group name of endpoint B"`
7070
}
7171

7272
type OutputField struct {
73-
Name string `yaml:"name,omitempty" doc:"output field name"`
74-
Operation string `yaml:"operation,omitempty" enum:"ConnTrackOperationEnum" doc:"aggregate operation on the field value"`
75-
SplitAB bool `yaml:"splitAB,omitempty" doc:"When true, 2 output fields will be created. One for A->B and one for B->A flows."`
76-
Input string `yaml:"input,omitempty" doc:"The input field to base the operation on. When omitted, 'name' is used"`
73+
Name string `yaml:"name,omitempty" json:"name,omitempty" doc:"output field name"`
74+
Operation string `yaml:"operation,omitempty" json:"operation,omitempty" enum:"ConnTrackOperationEnum" doc:"aggregate operation on the field value"`
75+
SplitAB bool `yaml:"splitAB,omitempty" json:"splitAB,omitempty" doc:"When true, 2 output fields will be created. One for A->B and one for B->A flows."`
76+
Input string `yaml:"input,omitempty" json:"input,omitempty" doc:"The input field to base the operation on. When omitted, 'name' is used"`
7777
}
7878

7979
type ConnTrackOperationEnum struct {
80-
Sum string `yaml:"sum" doc:"sum"`
81-
Count string `yaml:"count" doc:"count"`
82-
Min string `yaml:"min" doc:"min"`
83-
Max string `yaml:"max" doc:"max"`
80+
Sum string `yaml:"sum" json:"sum" doc:"sum"`
81+
Count string `yaml:"count" json:"count" doc:"count"`
82+
Min string `yaml:"min" json:"min" doc:"min"`
83+
Max string `yaml:"max" json:"max" doc:"max"`
8484
}
8585

8686
type ConnTrackSchedulingGroup struct {
87-
Selector map[string]interface{} `yaml:"selector,omitempty" doc:"key-value map to match against connection fields to apply this scheduling"`
88-
EndConnectionTimeout Duration `yaml:"endConnectionTimeout,omitempty" doc:"duration of time to wait from the last flow log to end a connection"`
89-
HeartbeatInterval Duration `yaml:"heartbeatInterval,omitempty" doc:"duration of time to wait between heartbeat reports of a connection"`
87+
Selector map[string]interface{} `yaml:"selector,omitempty" json:"selector,omitempty" doc:"key-value map to match against connection fields to apply this scheduling"`
88+
EndConnectionTimeout Duration `yaml:"endConnectionTimeout,omitempty" json:"endConnectionTimeout,omitempty" doc:"duration of time to wait from the last flow log to end a connection"`
89+
HeartbeatInterval Duration `yaml:"heartbeatInterval,omitempty" json:"heartbeatInterval,omitempty" doc:"duration of time to wait between heartbeat reports of a connection"`
9090
}
9191

9292
func ConnTrackOperationName(operation string) string {
9393
return GetEnumName(ConnTrackOperationEnum{}, operation)
9494
}
9595

96+
type ConnTrackTCPFlags struct {
97+
FieldName string `yaml:"fieldName,omitempty" json:"fieldName,omitempty" doc:"name of the field containing TCP flags"`
98+
DetectEndConnection bool `yaml:"detectEndConnection,omitempty" json:"detectEndConnection,omitempty" doc:"detect end connections by FIN_ACK flag"`
99+
SwapAB bool `yaml:"swapAB,omitempty" json:"swapAB,omitempty" doc:"swap source and destination when the first flowlog contains the SYN_ACK flag"`
100+
}
101+
96102
func (ct *ConnTrack) Validate() error {
97103
isGroupAEmpty := ct.KeyDefinition.Hash.FieldGroupARef == ""
98104
isGroupBEmpty := ct.KeyDefinition.Hash.FieldGroupBRef == ""
@@ -201,9 +207,40 @@ func (ct *ConnTrack) Validate() error {
201207
msg: fmt.Errorf("found %v default selectors. There should be exactly 1", numOfDefault)}
202208
}
203209

210+
if len(ct.TCPFlags.FieldName) == 0 && (ct.TCPFlags.DetectEndConnection || ct.TCPFlags.SwapAB) {
211+
return conntrackInvalidError{emptyTCPFlagsField: true,
212+
msg: fmt.Errorf("TCPFlags.FieldName is empty although DetectEndConnection or SwapAB are enabled")}
213+
}
214+
if ct.TCPFlags.SwapAB && !isBidi {
215+
return conntrackInvalidError{swapABWithNoBidi: true,
216+
msg: fmt.Errorf("SwapAB is enabled although bidirection is not enabled (fieldGroupARef is empty)")}
217+
}
218+
219+
fieldsA, fieldsB := ct.GetABFields()
220+
if len(fieldsA) != len(fieldsB) {
221+
return conntrackInvalidError{mismatchABFieldsCount: true,
222+
msg: fmt.Errorf("mismatch between the field count of fieldGroupARef %v and fieldGroupBRef %v", len(fieldsA), len(fieldsB))}
223+
}
224+
204225
return nil
205226
}
206227

228+
func (ct *ConnTrack) GetABFields() ([]string, []string) {
229+
endpointAFieldGroupName := ct.KeyDefinition.Hash.FieldGroupARef
230+
endpointBFieldGroupName := ct.KeyDefinition.Hash.FieldGroupBRef
231+
var endpointAFields []string
232+
var endpointBFields []string
233+
for _, fg := range ct.KeyDefinition.FieldGroups {
234+
if fg.Name == endpointAFieldGroupName {
235+
endpointAFields = fg.Fields
236+
}
237+
if fg.Name == endpointBFieldGroupName {
238+
endpointBFields = fg.Fields
239+
}
240+
}
241+
return endpointAFields, endpointBFields
242+
}
243+
207244
// addToSet adds an item to a set and returns true if it's a new item. Otherwise, it returns false.
208245
func addToSet(set map[string]struct{}, item string) bool {
209246
if _, found := set[item]; found {
@@ -253,6 +290,9 @@ type conntrackInvalidError struct {
253290
undefinedSelectorKey bool
254291
defaultGroupAndNotLast bool
255292
exactlyOneDefaultSelector bool
293+
swapABWithNoBidi bool
294+
emptyTCPFlagsField bool
295+
mismatchABFieldsCount bool
256296
}
257297

258298
func (err conntrackInvalidError) Error() string {

pkg/api/conntrack_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,45 @@ func TestConnTrackValidate(t *testing.T) {
212212
},
213213
conntrackInvalidError{defaultGroupAndNotLast: true},
214214
},
215+
{
216+
"Empty TCPFlags field name 1",
217+
ConnTrack{
218+
Scheduling: []ConnTrackSchedulingGroup{{Selector: map[string]interface{}{}}},
219+
TCPFlags: ConnTrackTCPFlags{DetectEndConnection: true},
220+
},
221+
conntrackInvalidError{emptyTCPFlagsField: true},
222+
},
223+
{
224+
"Empty TCPFlags field name 2",
225+
ConnTrack{
226+
Scheduling: []ConnTrackSchedulingGroup{{Selector: map[string]interface{}{}}},
227+
TCPFlags: ConnTrackTCPFlags{SwapAB: true},
228+
},
229+
conntrackInvalidError{emptyTCPFlagsField: true},
230+
},
231+
{
232+
"Mismatch between field count of FieldGroupARef and FieldGroupBRef",
233+
ConnTrack{
234+
KeyDefinition: KeyDefinition{
235+
FieldGroups: []FieldGroup{
236+
{
237+
Name: "src",
238+
Fields: []string{"SrcIP", "SrcPort"},
239+
},
240+
{
241+
Name: "dst",
242+
Fields: []string{"DstIP"},
243+
},
244+
},
245+
Hash: ConnTrackHash{
246+
FieldGroupARef: "src",
247+
FieldGroupBRef: "dst",
248+
},
249+
},
250+
Scheduling: []ConnTrackSchedulingGroup{{Selector: map[string]interface{}{}}},
251+
},
252+
conntrackInvalidError{mismatchABFieldsCount: true},
253+
},
215254
}
216255

217256
for _, tt := range tests {
@@ -221,3 +260,27 @@ func TestConnTrackValidate(t *testing.T) {
221260
})
222261
}
223262
}
263+
264+
func TestGetABFields(t *testing.T) {
265+
fieldsA := []string{"SrcIP", "SrcPort"}
266+
fieldsB := []string{"DstIP", "DstPort"}
267+
conf := ConnTrack{
268+
Scheduling: []ConnTrackSchedulingGroup{{Selector: map[string]interface{}{}}},
269+
KeyDefinition: KeyDefinition{
270+
FieldGroups: []FieldGroup{
271+
{Name: "src", Fields: fieldsA},
272+
{Name: "dst", Fields: fieldsB},
273+
},
274+
Hash: ConnTrackHash{
275+
FieldGroupARef: "src",
276+
FieldGroupBRef: "dst",
277+
},
278+
},
279+
}
280+
281+
require.NoError(t, conf.Validate())
282+
283+
actualA, actualB := conf.GetABFields()
284+
require.Equal(t, fieldsA, actualA)
285+
require.Equal(t, fieldsB, actualB)
286+
}

pkg/config/generic_map.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import "github.com/netobserv/flowlogs-pipeline/pkg/utils"
2121

2222
type GenericMap map[string]interface{}
2323

24+
const duplicateFieldName = "Duplicate"
25+
2426
// Copy will create a flat copy of GenericMap
2527
func (m GenericMap) Copy() GenericMap {
2628
result := make(GenericMap, len(m))
@@ -33,8 +35,8 @@ func (m GenericMap) Copy() GenericMap {
3335
}
3436

3537
func (m GenericMap) IsDuplicate() bool {
36-
if duplicate, hasKey := m["Duplicate"]; hasKey {
37-
if isDuplicate, err := utils.ConvertToBool(duplicate); err != nil {
38+
if duplicate, hasKey := m[duplicateFieldName]; hasKey {
39+
if isDuplicate, err := utils.ConvertToBool(duplicate); err == nil {
3840
return isDuplicate
3941
}
4042
}

pkg/config/generic_map_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package config
33
import (
44
"fmt"
55
"testing"
6+
7+
"github.com/stretchr/testify/require"
68
)
79

810
func BenchmarkGenericMap_Copy(b *testing.B) {
@@ -15,3 +17,49 @@ func BenchmarkGenericMap_Copy(b *testing.B) {
1517
_ = m.Copy()
1618
}
1719
}
20+
21+
func TestGenericMap_IsDuplicate(t *testing.T) {
22+
table := []struct {
23+
name string
24+
input GenericMap
25+
expected bool
26+
}{
27+
{
28+
"Duplicate: true",
29+
GenericMap{duplicateFieldName: true},
30+
true,
31+
},
32+
{
33+
"Duplicate: false",
34+
GenericMap{duplicateFieldName: false},
35+
false,
36+
},
37+
{
38+
"Missing field",
39+
GenericMap{},
40+
false,
41+
},
42+
{
43+
"Convert 'true'",
44+
GenericMap{duplicateFieldName: "true"},
45+
true,
46+
},
47+
{
48+
"Convert 'false'",
49+
GenericMap{duplicateFieldName: "false"},
50+
false,
51+
},
52+
{
53+
"Conversion failure: 'maybe'",
54+
GenericMap{duplicateFieldName: "maybe"},
55+
false,
56+
},
57+
}
58+
59+
for _, testCase := range table {
60+
t.Run(testCase.name, func(tt *testing.T) {
61+
actual := testCase.input.IsDuplicate()
62+
require.Equal(tt, testCase.expected, actual)
63+
})
64+
}
65+
}

pkg/config/pipeline_builder_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ func TestKafkaPromPipeline(t *testing.T) {
152152

153153
b, err = json.Marshal(params[2])
154154
require.NoError(t, err)
155-
require.JSONEq(t, `{"name":"conntrack","extract":{"type":"conntrack","conntrack":{"KeyDefinition":{"FieldGroups":null,"Hash":{"FieldGroupRefs":null,"FieldGroupARef":"","FieldGroupBRef":""}},"OutputRecordTypes":null,"MaxConnectionsTracked":0,"OutputFields":null,"Scheduling":null}}}`, string(b))
155+
require.JSONEq(t, `{"name":"conntrack","extract":{"type":"conntrack","conntrack":{"keyDefinition":{"hash":{}},"tcpFlags":{}}}}`, string(b))
156156

157157
b, err = json.Marshal(params[3])
158158
require.NoError(t, err)

pkg/pipeline/decode/decode_protobuf.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ func PBFlowToMap(flow *pbflow.Record) config.GenericMap {
5252
"TimeReceived": time.Now().Unix(),
5353
"Interface": flow.Interface,
5454
"AgentIP": ipToStr(flow.AgentIp),
55+
"Flags": flow.Flags,
5556
}
5657
return out
5758
}

0 commit comments

Comments
 (0)