// SPDX-FileCopyrightText: 2022 Free Mobile // SPDX-License-Identifier: AGPL-3.0-only package flows import ( "context" "net/netip" "testing" "time" "akvorado/common/helpers" "akvorado/common/pb" "akvorado/common/reporter" "akvorado/common/schema" "akvorado/outlet/flow/decoder" "akvorado/outlet/flow/decoder/netflow" ) func TestGetNetFlowData(t *testing.T) { r := reporter.NewMock(t) sch := schema.NewMock(t) bf := sch.NewFlowMessage() nfdecoder := netflow.New(r, decoder.Dependencies{Schema: sch}) ch := getNetFlowTemplates( context.Background(), 50, 30000, time.Date(2022, 3, 15, 14, 33, 0, 0, time.UTC), time.Date(2022, 3, 15, 15, 33, 0, 0, time.UTC)) got := []*schema.FlowMessage{} finalize := func() { bf.TimeReceived = 0 // Keep a copy of the current flow message clone := *bf got = append(got, &clone) // And clear the flow message bf.Clear() } for payload := range ch { if _, err := nfdecoder.Decode(decoder.RawFlow{ Payload: payload, Source: netip.MustParseAddr("::ffff:127.0.0.1"), }, decoder.Option{TimestampSource: pb.RawFlow_TS_INPUT}, bf, finalize); err != nil { t.Fatalf("Decode() error:\n%+v", err) } } ch = getNetFlowData( context.Background(), []generatedFlow{ { SrcAddr: netip.MustParseAddr("192.0.2.206"), DstAddr: netip.MustParseAddr("203.0.113.165"), EType: 0x800, IPFlow: IPFlow{ Octets: 1500, Packets: 1, Proto: 6, SrcPort: 443, DstPort: 34974, InputInt: 10, OutputInt: 20, SrcAS: 65201, DstAS: 65202, ForwardStatus: 64, SrcMask: 24, DstMask: 23, }, }, { SrcAddr: netip.MustParseAddr("2001:db8::1"), DstAddr: netip.MustParseAddr("2001:db8:2:0:cea5:d643:ec43:3772"), EType: 0x86dd, IPFlow: IPFlow{ Octets: 1300, Packets: 1, Proto: 6, SrcPort: 33179, DstPort: 443, InputInt: 20, OutputInt: 10, SrcAS: 65201, DstAS: 65202, ForwardStatus: 64, SrcMask: 48, DstMask: 48, }, }, { SrcAddr: netip.MustParseAddr("192.0.2.236"), DstAddr: netip.MustParseAddr("203.0.113.67"), EType: 0x800, IPFlow: IPFlow{ Octets: 1339, Packets: 1, Proto: 6, SrcPort: 443, DstPort: 33199, InputInt: 10, OutputInt: 20, SrcAS: 65201, DstAS: 65202, ForwardStatus: 64, SrcMask: 24, DstMask: 24, }, }, }, 100, time.Date(2022, 3, 15, 14, 33, 0, 0, time.UTC), time.Date(2022, 3, 15, 16, 33, 0, 0, time.UTC)) for payload := range ch { if _, err := nfdecoder.Decode(decoder.RawFlow{ Payload: payload, Source: netip.MustParseAddr("::ffff:127.0.0.1"), }, decoder.Option{TimestampSource: pb.RawFlow_TS_INPUT}, bf, finalize); err != nil { t.Fatalf("Decode() error:\n%+v", err) } } expected := []*schema.FlowMessage{ { SamplingRate: 30000, ExporterAddress: netip.MustParseAddr("::ffff:127.0.0.1"), SrcAddr: netip.MustParseAddr("::ffff:192.0.2.206"), DstAddr: netip.MustParseAddr("::ffff:203.0.113.165"), InIf: 10, OutIf: 20, SrcAS: 65201, DstAS: 65202, SrcNetMask: 24, DstNetMask: 23, OtherColumns: map[schema.ColumnKey]any{ schema.ColumnBytes: uint64(1500), schema.ColumnPackets: uint64(1), schema.ColumnEType: uint32(helpers.ETypeIPv4), schema.ColumnProto: uint32(6), schema.ColumnSrcPort: uint16(443), schema.ColumnDstPort: uint16(34974), schema.ColumnForwardingStatus: uint32(64), }, }, { SamplingRate: 30000, ExporterAddress: netip.MustParseAddr("::ffff:127.0.0.1"), SrcAddr: netip.MustParseAddr("::ffff:192.0.2.236"), DstAddr: netip.MustParseAddr("::ffff:203.0.113.67"), InIf: 10, OutIf: 20, SrcAS: 65201, DstAS: 65202, SrcNetMask: 24, DstNetMask: 24, OtherColumns: map[schema.ColumnKey]any{ schema.ColumnBytes: uint64(1339), schema.ColumnPackets: uint64(1), schema.ColumnEType: uint32(helpers.ETypeIPv4), schema.ColumnProto: uint32(6), schema.ColumnSrcPort: uint16(443), schema.ColumnDstPort: uint16(33199), schema.ColumnForwardingStatus: uint32(64), }, }, { SamplingRate: 30000, ExporterAddress: netip.MustParseAddr("::ffff:127.0.0.1"), SrcAddr: netip.MustParseAddr("2001:db8::1"), DstAddr: netip.MustParseAddr("2001:db8:2:0:cea5:d643:ec43:3772"), InIf: 20, OutIf: 10, SrcAS: 65201, DstAS: 65202, SrcNetMask: 48, DstNetMask: 48, OtherColumns: map[schema.ColumnKey]any{ schema.ColumnBytes: uint64(1300), schema.ColumnPackets: uint64(1), schema.ColumnEType: uint32(helpers.ETypeIPv6), schema.ColumnProto: uint32(6), schema.ColumnSrcPort: uint16(33179), schema.ColumnDstPort: uint16(443), schema.ColumnForwardingStatus: uint32(64), }, }, } if diff := helpers.Diff(got, expected); diff != "" { t.Fatalf("getNetFlowData() (-got, +want):\n%s", diff) } }