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 hep protocol support as parser in telegraf #6167

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,27 @@ func getParserConfig(name string, tbl *ast.Table) (*parsers.Config, error) {
}
}

//for hep parser
if node, ok := tbl.Fields["hep_header"]; ok {
if kv, ok := node.(*ast.KeyValue); ok {
if ary, ok := kv.Value.(*ast.Array); ok {
for _, elem := range ary.Value {
if str, ok := elem.(*ast.String); ok {
c.HepHeader = append(c.HepHeader, str.Value)
}
}
}
}
}

if node, ok := tbl.Fields["hep_measurement_name"]; ok {
if kv, ok := node.(*ast.KeyValue); ok {
if str, ok := kv.Value.(*ast.String); ok {
c.HepMeasurementNAme = str.Value
}
}
}

if node, ok := tbl.Fields["form_urlencoded_tag_keys"]; ok {
if kv, ok := node.(*ast.KeyValue); ok {
if ary, ok := kv.Value.(*ast.Array); ok {
Expand Down Expand Up @@ -1779,6 +1800,8 @@ func getParserConfig(name string, tbl *ast.Table) (*parsers.Config, error) {
delete(tbl.Fields, "csv_timestamp_column")
delete(tbl.Fields, "csv_timestamp_format")
delete(tbl.Fields, "csv_trim_space")
delete(tbl.Fields, "hep_header")
delete(tbl.Fields, "hep_measurement_name")
delete(tbl.Fields, "form_urlencoded_tag_keys")

return c, nil
Expand Down
19 changes: 19 additions & 0 deletions plugins/parsers/hep/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# HEP

The HEP data format parses a HEP packet into metric fields.

**NOTE:** All HEP packets are stores as Tags unless provided specifically
provided with `hep_header` array and body is parsed with JSON parser.
All the JSON parser features were imported in Hep parser. Please check Json Parser for more details.

Any field/header can be ignored using already telegraf filters.

### Configuration

```toml
[[inputs.socket_listener]]
service_address = "udp://:8094"
data_format = "hep"
hep_header = ["protocol"]

```
152 changes: 152 additions & 0 deletions plugins/parsers/hep/hep.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package hep

import (
"encoding/binary"
"fmt"
"net"
"strconv"
"time"
)

// HEP chuncks
const (
Version = 1 // Chunk 0x0001 IP protocol family (0x02=IPv4, 0x0a=IPv6)
Protocol = 2 // Chunk 0x0002 IP protocol ID (0x06=TCP, 0x11=UDP)
IP4SrcIP = 3 // Chunk 0x0003 IPv4 source address
IP4DstIP = 4 // Chunk 0x0004 IPv4 destination address
IP6SrcIP = 5 // Chunk 0x0005 IPv6 source address
IP6DstIP = 6 // Chunk 0x0006 IPv6 destination address
SrcPort = 7 // Chunk 0x0007 Protocol source port
DstPort = 8 // Chunk 0x0008 Protocol destination port
Tsec = 9 // Chunk 0x0009 Unix timestamp, seconds
Tmsec = 10 // Chunk 0x000a Unix timestamp, microseconds
ProtoType = 11 // Chunk 0x000b Protocol type (DNS, LOG, RTCP, SIP)
NodeID = 12 // Chunk 0x000c Capture client ID
NodePW = 14 // Chunk 0x000e Authentication key (plain text / TLS connection)
Payload = 15 // Chunk 0x000f Captured packet payload
CID = 17 // Chunk 0x0011 Correlation ID
Vlan = 18 // Chunk 0x0012 VLAN
NodeName = 19 // Chunk 0x0013 NodeName
)

// HEP represents HEP packet
type HEP struct {
Version uint32
Protocol uint32
SrcIP string
DstIP string
SrcPort uint32
DstPort uint32
Tsec uint32
Tmsec uint32
ProtoType uint32
NodeID uint32
NodePW string
Payload string
CID string
Vlan uint32
ProtoString string
Timestamp time.Time
NodeName string
}

func (h *HEP) parseHEP(packet []byte) error {
length := binary.BigEndian.Uint16(packet[4:6])
if int(length) != len(packet) {
return fmt.Errorf("HEP packet length is %d but should be %d", len(packet), length)
}
currentByte := uint16(6)

for currentByte < length {
hepChunk := packet[currentByte:]
if len(hepChunk) < 6 {
return fmt.Errorf("HEP chunk must be >= 6 byte long but is %d", len(hepChunk))
}
//chunkVendorId := binary.BigEndian.Uint16(hepChunk[:2])
chunkType := binary.BigEndian.Uint16(hepChunk[2:4])
chunkLength := binary.BigEndian.Uint16(hepChunk[4:6])
if len(hepChunk) < int(chunkLength) || int(chunkLength) < 6 {
return fmt.Errorf("HEP chunk with %d byte < chunkLength %d or chunkLength < 6", len(hepChunk), chunkLength)
}
chunkBody := hepChunk[6:chunkLength]

switch chunkType {
case Version, Protocol, ProtoType:
if len(chunkBody) != 1 {
return fmt.Errorf("HEP chunkType %d should be 1 byte long but is %d", chunkType, len(chunkBody))
}
case SrcPort, DstPort, Vlan:
if len(chunkBody) != 2 {
return fmt.Errorf("HEP chunkType %d should be 2 byte long but is %d", chunkType, len(chunkBody))
}
case IP4SrcIP, IP4DstIP, Tsec, Tmsec, NodeID:
if len(chunkBody) != 4 {
return fmt.Errorf("HEP chunkType %d should be 4 byte long but is %d", chunkType, len(chunkBody))
}
case IP6SrcIP, IP6DstIP:
if len(chunkBody) != 16 {
return fmt.Errorf("HEP chunkType %d should be 16 byte long but is %d", chunkType, len(chunkBody))
}
}

switch chunkType {
case Version:
h.Version = uint32(chunkBody[0])
case Protocol:
h.Protocol = uint32(chunkBody[0])
case IP4SrcIP:
h.SrcIP = net.IP(chunkBody).To4().String()
case IP4DstIP:
h.DstIP = net.IP(chunkBody).To4().String()
case IP6SrcIP:
h.SrcIP = net.IP(chunkBody).To16().String()
case IP6DstIP:
h.DstIP = net.IP(chunkBody).To16().String()
case SrcPort:
h.SrcPort = uint32(binary.BigEndian.Uint16(chunkBody))
case DstPort:
h.DstPort = uint32(binary.BigEndian.Uint16(chunkBody))
case Tsec:
h.Tsec = binary.BigEndian.Uint32(chunkBody)
case Tmsec:
h.Tmsec = binary.BigEndian.Uint32(chunkBody)
case ProtoType:
h.ProtoType = uint32(chunkBody[0])
switch h.ProtoType {
case 1:
h.ProtoString = "sip"
case 5:
h.ProtoString = "rtcp"
case 34:
h.ProtoString = "rtpagent"
case 35:
h.ProtoString = "rtcpxr"
case 38:
h.ProtoString = "horaclifix"
case 53:
h.ProtoString = "dns"
case 100:
h.ProtoString = "log"
case 112:
h.ProtoString = "alert"
default:
h.ProtoString = strconv.Itoa(int(h.ProtoType))
}
case NodeID:
h.NodeID = binary.BigEndian.Uint32(chunkBody)
case NodePW:
h.NodePW = string(chunkBody)
case Payload:
h.Payload = string(chunkBody)
case CID:
h.CID = string(chunkBody)
case Vlan:
h.Vlan = uint32(binary.BigEndian.Uint16(chunkBody))
case NodeName:
h.NodeName = string(chunkBody)
default:
}
currentByte += chunkLength
}
return nil
}
Loading