mirror of
https://github.com/akvorado/akvorado.git
synced 2025-12-11 22:14:02 +01:00
Currently, for NetFlow, persist data/options templates and options. This should allow the outlet to restart without loosing any message. Fix #2100
127 lines
3.5 KiB
Go
127 lines
3.5 KiB
Go
// SPDX-FileCopyrightText: 2025 Free Mobile
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
package netflow
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"github.com/netsampler/goflow2/v2/decoders/netflow"
|
|
)
|
|
|
|
// MarshalText implements encoding.TextMarshaler for templateKey.
|
|
func (tk templateKey) MarshalText() ([]byte, error) {
|
|
return fmt.Appendf(nil, "%d-%d-%d", tk.version, tk.obsDomainID, tk.templateID), nil
|
|
}
|
|
|
|
// UnmarshalText implements encoding.TextUnmarshaler for templateKey.
|
|
func (tk *templateKey) UnmarshalText(text []byte) error {
|
|
_, err := fmt.Sscanf(string(text), "%d-%d-%d", &tk.version, &tk.obsDomainID, &tk.templateID)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid template key %q: %w", string(text), err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MarshalText implements encoding.TextMarshaler for samplingRateKey.
|
|
func (srk samplingRateKey) MarshalText() ([]byte, error) {
|
|
return fmt.Appendf(nil, "%d-%d-%d", srk.version, srk.obsDomainID, srk.samplerID), nil
|
|
}
|
|
|
|
// UnmarshalText implements encoding.TextUnmarshaler for samplingRateKey.
|
|
func (srk *samplingRateKey) UnmarshalText(text []byte) error {
|
|
_, err := fmt.Sscanf(string(text), "%d-%d-%d", &srk.version, &srk.obsDomainID, &srk.samplerID)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid sampling rate key %q: %w", string(text), err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MarshalJSON encodes a set of NetFlow templates.
|
|
func (t *templates) MarshalJSON() ([]byte, error) {
|
|
type typedTemplate struct {
|
|
Type string
|
|
Template any
|
|
}
|
|
data := make(map[templateKey]typedTemplate, len(*t))
|
|
for k, v := range *t {
|
|
switch v := v.(type) {
|
|
case netflow.TemplateRecord:
|
|
data[k] = typedTemplate{
|
|
Type: "data",
|
|
Template: v,
|
|
}
|
|
case netflow.IPFIXOptionsTemplateRecord:
|
|
data[k] = typedTemplate{
|
|
Type: "ipfix-option",
|
|
Template: v,
|
|
}
|
|
case netflow.NFv9OptionsTemplateRecord:
|
|
data[k] = typedTemplate{
|
|
Type: "nfv9-option",
|
|
Template: v,
|
|
}
|
|
default:
|
|
return nil, fmt.Errorf("unknown template type %q", reflect.TypeOf(v).String())
|
|
}
|
|
}
|
|
return json.Marshal(&data)
|
|
}
|
|
|
|
// UnmarshalJSON decodes a set of NetFlow templates.
|
|
func (t *templates) UnmarshalJSON(data []byte) error {
|
|
type typedTemplate struct {
|
|
Type string
|
|
Template json.RawMessage
|
|
}
|
|
var templatesWithTypes map[templateKey]typedTemplate
|
|
if err := json.Unmarshal(data, &templatesWithTypes); err != nil {
|
|
return err
|
|
}
|
|
targetTemplates := make(templates, len(templatesWithTypes))
|
|
for k, v := range templatesWithTypes {
|
|
var targetTemplate any
|
|
var err error
|
|
switch v.Type {
|
|
case "data":
|
|
var tmpl netflow.TemplateRecord
|
|
err = json.Unmarshal(v.Template, &tmpl)
|
|
targetTemplate = tmpl
|
|
case "ipfix-option":
|
|
var tmpl netflow.IPFIXOptionsTemplateRecord
|
|
err = json.Unmarshal(v.Template, &tmpl)
|
|
targetTemplate = tmpl
|
|
case "nfv9-option":
|
|
var tmpl netflow.NFv9OptionsTemplateRecord
|
|
err = json.Unmarshal(v.Template, &tmpl)
|
|
targetTemplate = tmpl
|
|
default:
|
|
return fmt.Errorf("unknown type %q", v.Type)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
targetTemplates[k] = targetTemplate
|
|
}
|
|
*t = targetTemplates
|
|
return nil
|
|
}
|
|
|
|
// MarshalJSON encodes the NetFlow decoder's collection.
|
|
func (nd *Decoder) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(&nd.collection.Collection)
|
|
}
|
|
|
|
// UnmarshalJSON decodes the NetFlow decoder's collection.
|
|
func (nd *Decoder) UnmarshalJSON(data []byte) error {
|
|
if err := json.Unmarshal(data, &nd.collection.Collection); err != nil {
|
|
return err
|
|
}
|
|
for _, tao := range nd.collection.Collection {
|
|
tao.nd = nd
|
|
}
|
|
return nil
|
|
}
|