Skip to content

Commit bffb860

Browse files
authored
NETOBSERV-1275: Introduce new "INNER" direction for inner-node traffic (#378)
* Introduce new "INNER" direction for inner-node traffic Related PR: netobserv/flowlogs-pipeline#483 The flows (and duplicates) generated for inner-node traffic differs compared to node-to-node traffic, and reinterpret direction isn't able to decide between ingress or egress. This is causing discrepancies with the dedup mechanism that filters out flows where Duplicate=true and also favors ingress over egress, since the Duplicate flag can be set randomly on ingress or on egress. To fix that, the proposed solution is to create this new INNER direction specifically for this kind of traffic. Deduping this INNER traffic can then rely solely on the Duplicate flag, since that flag was set from a single Agent (single node) there will always be only one Duplicate=false. * fix fmt * Fix test * Update texts & API for doc * fix linter
1 parent 2ec3c5d commit bffb860

File tree

12 files changed

+48
-24
lines changed

12 files changed

+48
-24
lines changed

pkg/model/filters/filters.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ func SplitForReportersMerge(q SingleQuery) (SingleQuery, SingleQuery) {
7878
// (Note that we use DstOwnerName both as an optimization as it's a Loki index,
7979
// and as convenience because looking for empty fields won't work if they aren't indexed)
8080
q1 := SingleQuery{
81-
NewMatch(fields.FlowDirection, `"`+constants.Ingress+`"`),
81+
NewMatch(fields.FlowDirection, `"`+string(constants.Ingress)+`","`+string(constants.Inner)+`"`),
8282
}
8383
q2 := SingleQuery{
84-
NewMatch(fields.FlowDirection, `"`+constants.Egress+`"`),
84+
NewMatch(fields.FlowDirection, `"`+string(constants.Egress)+`"`),
8585
NewMatch(fields.DstOwnerName, `""`),
8686
}
8787
for _, m := range q {

pkg/model/filters/filters_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,12 @@ func TestParseCommon(t *testing.T) {
7878
}
7979

8080
func TestSplitForReportersMerge_NoSplit(t *testing.T) {
81-
q1, q2 := SplitForReportersMerge(SingleQuery{NewMatch("srcns", "a"), NewMatch("FlowDirection", constants.Ingress)})
81+
q1, q2 := SplitForReportersMerge(SingleQuery{NewMatch("srcns", "a"), NewMatch("FlowDirection", string(constants.Ingress))})
8282
assert.Nil(t, q2)
8383
assert.Len(t, q1, 2)
8484
assert.Equal(t, SingleQuery{
8585
NewMatch("srcns", "a"),
86-
NewMatch("FlowDirection", constants.Ingress),
86+
NewMatch("FlowDirection", string(constants.Ingress)),
8787
}, q1)
8888
}
8989

@@ -92,13 +92,13 @@ func TestSplitForReportersMerge(t *testing.T) {
9292

9393
assert.Len(t, q1, 3)
9494
assert.Equal(t, SingleQuery{
95-
NewMatch("FlowDirection", `"`+constants.Ingress+`"`),
95+
NewMatch("FlowDirection", `"`+string(constants.Ingress)+`","`+string(constants.Inner)+`"`),
9696
NewMatch("srcns", "a"),
9797
NewMatch("dstns", "b"),
9898
}, q1)
9999
assert.Len(t, q2, 4)
100100
assert.Equal(t, SingleQuery{
101-
NewMatch("FlowDirection", `"`+constants.Egress+`"`),
101+
NewMatch("FlowDirection", `"`+string(constants.Egress)+`"`),
102102
NewMatch("DstK8S_OwnerName", `""`),
103103
NewMatch("srcns", "a"),
104104
NewMatch("dstns", "b"),

pkg/server/server_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ func TestLokiConfigurationForTopology(t *testing.T) {
327327
req2 := lokiMock.Calls[1].Arguments[1].(*http.Request)
328328
queries := []string{req1.URL.Query().Get("query"), req2.URL.Query().Get("query")}
329329
expected := []string{
330-
`topk(100,sum by(SrcK8S_Name,SrcK8S_Type,SrcK8S_OwnerName,SrcK8S_OwnerType,SrcK8S_Namespace,SrcAddr,SrcK8S_HostName,DstK8S_Name,DstK8S_Type,DstK8S_OwnerName,DstK8S_OwnerType,DstK8S_Namespace,DstAddr,DstK8S_HostName) (rate({app="netobserv-flowcollector",FlowDirection="0"}|~` + "`" + `Duplicate":false` + "`" + `|json|unwrap Bytes|__error__=""[1m])))`,
330+
`topk(100,sum by(SrcK8S_Name,SrcK8S_Type,SrcK8S_OwnerName,SrcK8S_OwnerType,SrcK8S_Namespace,SrcAddr,SrcK8S_HostName,DstK8S_Name,DstK8S_Type,DstK8S_OwnerName,DstK8S_OwnerType,DstK8S_Namespace,DstAddr,DstK8S_HostName) (rate({app="netobserv-flowcollector",FlowDirection=~"^0$|^2$"}|~` + "`" + `Duplicate":false` + "`" + `|json|unwrap Bytes|__error__=""[1m])))`,
331331
`topk(100,sum by(SrcK8S_Name,SrcK8S_Type,SrcK8S_OwnerName,SrcK8S_OwnerType,SrcK8S_Namespace,SrcAddr,SrcK8S_HostName,DstK8S_Name,DstK8S_Type,DstK8S_OwnerName,DstK8S_OwnerType,DstK8S_Namespace,DstAddr,DstK8S_HostName) (rate({app="netobserv-flowcollector",FlowDirection="1",DstK8S_OwnerName=""}|~` + "`" + `Duplicate":false` + "`" + `|json|unwrap Bytes|__error__=""[1m])))`,
332332
}
333333
// We don't predict the order so sort both actual and expected

pkg/utils/constants/constants.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package constants
33
type MetricType string
44
type RecordType string
55
type PacketLoss string
6+
type Direction string
67

78
const (
89
AppLabel = "app"
@@ -28,8 +29,9 @@ const (
2829
PacketLossSent PacketLoss = "sent"
2930
PacketLossAll PacketLoss = "all"
3031
DefaultPacketLoss PacketLoss = PacketLossAll
31-
Ingress = "0"
32-
Egress = "1"
32+
Ingress Direction = "0"
33+
Egress Direction = "1"
34+
Inner Direction = "2"
3335
)
3436

3537
var AnyConnectionType = []string{

web/locales/en/plugin__netobserv-plugin.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"Log type": "Log type",
4747
"Only available when FlowCollector.processor.logTypes option equals \"CONNECTIONS\", \"ENDED_CONNECTIONS\" or \"ALL\"": "Only available when FlowCollector.processor.logTypes option equals \"CONNECTIONS\", \"ENDED_CONNECTIONS\" or \"ALL\"",
4848
"Only available when FlowCollector.processor.logTypes option equals \"FLOWS\" or \"ALL\"": "Only available when FlowCollector.processor.logTypes option equals \"FLOWS\" or \"ALL\"",
49-
"A flow might be reported from several interfaces, and from both source and destination nodes, making it appear several times. By default, duplicates are hidden. Showing duplicates is not possible in Overview and Topology tabs to avoid altering metric calculations. Use the Direction filter to switch between ingress / egress traffic.": "A flow might be reported from several interfaces, and from both source and destination nodes, making it appear several times. By default, duplicates are hidden. Showing duplicates is not possible in Overview and Topology tabs to avoid altering metric calculations. Use the Direction filter to switch between ingress / egress traffic.",
49+
"A flow might be reported from several interfaces, and from both source and destination nodes, making it appear several times. By default, duplicates are hidden. Showing duplicates is not possible in Overview and Topology tabs to avoid altering metric calculations. Use the Direction filter to switch between ingress, egress and inner-node traffic.": "A flow might be reported from several interfaces, and from both source and destination nodes, making it appear several times. By default, duplicates are hidden. Showing duplicates is not possible in Overview and Topology tabs to avoid altering metric calculations. Use the Direction filter to switch between ingress, egress and inner-node traffic.",
5050
"Duplicated flows": "Duplicated flows",
5151
"Show duplicates": "Show duplicates",
5252
"Whether each query result has to match all the filters or just any of them": "Whether each query result has to match all the filters or just any of them",
@@ -230,6 +230,7 @@
230230
"reporting": "reporting",
231231
"Ingress": "Ingress",
232232
"Egress": "Egress",
233+
"Inner": "Inner",
233234
"dropped": "dropped",
234235
"dropped by": "dropped by",
235236
"sent": "sent",
@@ -369,7 +370,7 @@
369370
"Protocol": "Protocol",
370371
"The value of the protocol number in the IP packet header": "The value of the protocol number in the IP packet header",
371372
"Direction": "Direction",
372-
"The direction of the Flow observed at the Observation Point.": "The direction of the Flow observed at the Observation Point.",
373+
"The direction of the Flow observed at the Node observation point.": "The direction of the Flow observed at the Node observation point.",
373374
"Interface": "Interface",
374375
"The network interface of the Flow.": "The network interface of the Flow.",
375376
"The total aggregated number of bytes.": "The total aggregated number of bytes.",
@@ -450,7 +451,7 @@
450451
"A IANA name like TCP, UDP": "A IANA name like TCP, UDP",
451452
"Empty double quotes \"\" for undefined protocol": "Empty double quotes \"\" for undefined protocol",
452453
"Unknown direction": "Unknown direction",
453-
"Specify the direction of the Flow observed at the Observation Point.": "Specify the direction of the Flow observed at the Observation Point.",
454+
"Specify the direction of the Flow observed at the Node observation point.": "Specify the direction of the Flow observed at the Node observation point.",
454455
"Network interface": "Network interface",
455456
"Specify a network interface.": "Specify a network interface.",
456457
"Specify a single conversation hash Id.": "Specify a single conversation hash Id.",

web/src/api/ipfix.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { RecordType } from '../model/flow-query';
33

44
// Please keep this file documented: it is used in doc generation
55
// To regenerate doc, run `make generate-doc` - and also check this page:
6-
// eslint-disable-next-line max-len
76
// https://github.com/netobserv/network-observability-operator/blob/main/docs/GeneratingAsciidocAPI.md#generate-asciidoc-for-flows-json-format-reference
87

98
export interface Record {
@@ -32,6 +31,15 @@ export enum FlowDirection {
3231
/** Incoming traffic, from node observation point */
3332
Ingress = '0',
3433
/** Outgoing traffic, from node observation point */
34+
Egress = '1',
35+
/** Inner traffic, ie. same source and destination node */
36+
Inner = '2'
37+
}
38+
39+
export enum InterfaceDirection {
40+
/** Incoming traffic, from network interface observation point */
41+
Ingress = '0',
42+
/** Outgoing traffic, from network interface observation point */
3543
Egress = '1'
3644
}
3745

@@ -72,6 +80,8 @@ export interface Fields {
7280
Proto: number;
7381
/** Network interface */
7482
Interface?: string;
83+
/** Flow direction from the network interface observation point */
84+
IfDirection?: InterfaceDirection;
7585
/** TCP flags */
7686
Flags?: number;
7787
/** Number of packets in this flow */

web/src/components/dropdowns/query-options-dropdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ export const QueryOptionsPanel: React.FC<QueryOptionsDropdownProps> = ({
149149
<Tooltip
150150
content={t(
151151
// eslint-disable-next-line max-len
152-
'A flow might be reported from several interfaces, and from both source and destination nodes, making it appear several times. By default, duplicates are hidden. Showing duplicates is not possible in Overview and Topology tabs to avoid altering metric calculations. Use the Direction filter to switch between ingress / egress traffic.'
152+
'A flow might be reported from several interfaces, and from both source and destination nodes, making it appear several times. By default, duplicates are hidden. Showing duplicates is not possible in Overview and Topology tabs to avoid altering metric calculations. Use the Direction filter to switch between ingress, egress and inner-node traffic.'
153153
)}
154154
>
155155
<div className="pf-c-select__menu-group-title">

web/src/components/netflow-record/record-field.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,13 @@ export const RecordField: React.FC<{
390390
case ColumnsId.flowdir:
391391
return singleContainer(
392392
simpleTextWithTooltip(
393-
value === FlowDirection.Ingress ? t('Ingress') : value === FlowDirection.Egress ? t('Egress') : t('n/a')
393+
value === FlowDirection.Ingress
394+
? t('Ingress')
395+
: value === FlowDirection.Egress
396+
? t('Egress')
397+
: value === FlowDirection.Inner
398+
? t('Inner')
399+
: t('n/a')
394400
)
395401
);
396402
case ColumnsId.packets:

web/src/utils/columns.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ export const getExtraColumns = (t: TFunction): Column[] => {
736736
{
737737
id: ColumnsId.flowdir,
738738
name: t('Direction'),
739-
tooltip: t('The direction of the Flow observed at the Observation Point.'),
739+
tooltip: t('The direction of the Flow observed at the Node observation point.'),
740740
fieldName: 'FlowDirection',
741741
quickFilter: 'direction',
742742
isSelected: false,

web/src/utils/filter-definitions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ export const getFilterDefinitions = (
454454
}
455455
return invalid(t('Unknown direction'));
456456
},
457-
hint: t('Specify the direction of the Flow observed at the Observation Point.'),
457+
hint: t('Specify the direction of the Flow observed at the Node observation point.'),
458458
encoder: simpleFiltersEncoder('FlowDirection'),
459459
overlap: false
460460
},

0 commit comments

Comments
 (0)