package netflow

import (
	"bytes"
	"errors"
	"fmt"
	"net"
	"regexp"
	"sync"
	"time"

	"github.com/netsampler/goflow2/v2/decoders/netflow"

	"github.com/influxdata/telegraf"
	"github.com/influxdata/telegraf/metric"
)

var regexpIPFIXPENMapping = regexp.MustCompile(`\d+\.\d+`)

type decoderFunc func([]byte) (interface{}, error)

type fieldMapping struct {
	name    string
	decoder decoderFunc
}

// Default field mappings common for Netflow version 9 and IPFIX
// From documentations at
// - https://www.cisco.com/en/US/technologies/tk648/tk362/technologies_white_paper09186a00800a3db9.html
// - https://www.iana.org/assignments/ipfix/ipfix.xhtml#ipfix-information-elements
var fieldMappingsNetflowCommon = map[uint16][]fieldMapping{
	// 0: reserved
	1:  {{"in_bytes", decodeUint}},          // IN_BYTES / octetDeltaCount
	2:  {{"in_packets", decodeUint}},        // IN_PKTS / packetDeltaCount
	3:  {{"flows", decodeUint}},             // FLOWS / deltaFlowCount
	4:  {{"protocol", decodeL4Proto}},       // PROTOCOL / protocolIdentifier
	5:  {{"src_tos", decodeHex}},            // SRC_TOS / ipClassOfService
	6:  {{"tcp_flags", decodeTCPFlags}},     // TCP_FLAGS / tcpControlBits
	7:  {{"src_port", decodeUint}},          // L4_SRC_PORT / sourceTransportPort
	8:  {{"src", decodeIP}},                 // IPV4_SRC_ADDR / sourceIPv4Address
	9:  {{"src_mask", decodeUint}},          // SRC_MASK / sourceIPv4PrefixLength
	10: {{"in_snmp", decodeUint}},           // INPUT_SNMP / ingressInterface
	11: {{"dst_port", decodeUint}},          // L4_DST_PORT / destinationTransportPort
	12: {{"dst", decodeIP}},                 // IPV4_DST_ADDR / destinationIPv4Address
	13: {{"dst_mask", decodeUint}},          // DST_MASK / destinationIPv4PrefixLength
	14: {{"out_snmp", decodeUint}},          // OUTPUT_SNMP / egressInterface
	15: {{"next_hop", decodeIP}},            // IPV4_NEXT_HOP / ipNextHopIPv4Address
	16: {{"bgp_src_as", decodeUint}},        // SRC_AS / bgpSourceAsNumber
	17: {{"bgp_dst_as", decodeUint}},        // DST_AS / bgpDestinationAsNumber
	18: {{"bgp_next_hop", decodeIP}},        // BGP_IPV4_NEXT_HOP / bgpNextHopIPv4Address
	19: {{"out_mcast_packets", decodeUint}}, // MUL_DST_PKTS / postMCastPacketDeltaCount
	20: {{"out_mcast_bytes", decodeUint}},   // MUL_DST_BYTES / postMCastOctetDeltaCount
	21: {{"last_switched", decodeUint}},     // LAST_SWITCHED / flowEndSysUpTime
	22: {{"first_switched", decodeUint}},    // FIRST_SWITCHED / flowStartSysUpTime
	23: {{"out_bytes", decodeUint}},         // OUT_BYTES / postOctetDeltaCount
	24: {{"out_packets", decodeUint}},       // OUT_PKTS / postPacketDeltaCount
	25: {{"min_packet_len", decodeUint}},    // MIN_PKT_LNGTH / minimumIpTotalLength
	26: {{"max_packet_len", decodeUint}},    // MAX_PKT_LNGTH / maximumIpTotalLength
	27: {{"src", decodeIP}},                 // IPV6_SRC_ADDR / sourceIPv6Address
	28: {{"dst", decodeIP}},                 // IPV6_DST_ADDR / destinationIPv6Address
	29: {{"src_mask", decodeUint}},          // IPV6_SRC_MASK / sourceIPv6PrefixLength
	30: {{"dst_mask", decodeUint}},          // IPV6_DST_MASK / destinationIPv6PrefixLength
	31: {{"flow_label", decodeHex}},         // IPV6_FLOW_LABEL / flowLabelIPv6
	32: {
		{"icmp_type", decodeByteFunc(0)}, // ICMP_TYPE / icmpTypeCodeIPv4
		{"icmp_code", decodeByteFunc(1)},
	},
	33: {{"igmp_type", decodeUint}},               // MUL_IGMP_TYPE / igmpType
	34: {{"sampling_interval", decodeUint}},       // SAMPLING_INTERVAL / samplingInterval (deprecated)
	35: {{"sampling_algo", decodeSampleAlgo}},     // SAMPLING_ALGORITHM / samplingAlgorithm (deprecated)
	36: {{"flow_active_timeout", decodeUint}},     // FLOW_ACTIVE_TIMEOUT / flowActiveTimeout
	37: {{"flow_inactive_timeout", decodeUint}},   // FLOW_INACTIVE_TIMEOUT / flowIdleTimeout
	38: {{"engine_type", decodeEngineType}},       // ENGINE_TYPE / engineType (deprecated)
	39: {{"engine_id", decodeHex}},                // ENGINE_ID / engineId (deprecated)
	40: {{"total_bytes_exported", decodeUint}},    // TOTAL_BYTES_EXP / exportedOctetTotalCount
	41: {{"total_messages_exported", decodeUint}}, // TOTAL_PKTS_EXP / exportedMessageTotalCount
	42: {{"total_flows_exported", decodeUint}},    // TOTAL_FLOWS_EXP / exportedFlowRecordTotalCount
	// 43: vendor proprietary / deprecated
	44: {{"ipv4_src_prefix", decodeIP}},           // IPV4_SRC_PREFIX / sourceIPv4Prefix
	45: {{"ipv4_dst_prefix", decodeIP}},           // IPV4_DST_PREFIX / destinationIPv4Prefix
	46: {{"mpls_top_label_type", decodeMPLSType}}, // MPLS_TOP_LABEL_TYPE / mplsTopLabelType
	47: {{"mpls_top_label_ip", decodeIP}},         // MPLS_TOP_LABEL_IP_ADDR / mplsTopLabelIPv4Address
	48: {{"flow_sampler_id", decodeUint}},         // FLOW_SAMPLER_ID / samplerId (deprecated)
	49: {{"flow_sampler_mode", decodeSampleAlgo}}, // FLOW_SAMPLER_MODE / samplerMode (deprecated)
	50: {{"flow_sampler_interval", decodeUint}},   // FLOW_SAMPLER_RANDOM_INTERVAL / samplerRandomInterval (deprecated)
	// 51: vendor proprietary / deprecated
	52: {{"min_ttl", decodeUint}},         // MIN_TTL / minimumTTL
	53: {{"max_ttl", decodeUint}},         // MAX_TTL / maximumTTL
	54: {{"fragment_id", decodeHex}},      // IPV4_IDENT / fragmentIdentification
	55: {{"dst_tos", decodeHex}},          // DST_TOS / postIpClassOfService
	56: {{"in_src_mac", decodeMAC}},       // IN_SRC_MAC / sourceMacAddress
	57: {{"out_dst_mac", decodeMAC}},      // OUT_DST_MAC / postDestinationMacAddress
	58: {{"vlan_src", decodeUint}},        // SRC_VLAN / vlanId
	59: {{"vlan_dst", decodeUint}},        // DST_VLAN / postVlanId
	60: {{"ip_version", decodeIPVersion}}, // IP_PROTOCOL_VERSION / ipVersion
	61: {{"direction", decodeDirection}},  // DIRECTION / flowDirection
	62: {{"next_hop", decodeIP}},          // IPV6_NEXT_HOP / ipNextHopIPv6Address
	63: {{"bgp_next_hop", decodeIP}},      // BPG_IPV6_NEXT_HOP / bgpNextHopIPv6Address
	64: {{"ipv6_extensions", decodeHex}},  // IPV6_OPTION_HEADERS / ipv6ExtensionHeaders
	// 65 - 69: vendor proprietary
	70: {{"mpls_label_1", decodeHex}},      // MPLS_LABEL_1 / mplsTopLabelStackSection
	71: {{"mpls_label_2", decodeHex}},      // MPLS_LABEL_2 / mplsLabelStackSection2
	72: {{"mpls_label_3", decodeHex}},      // MPLS_LABEL_3 / mplsLabelStackSection3
	73: {{"mpls_label_4", decodeHex}},      // MPLS_LABEL_4 / mplsLabelStackSection4
	74: {{"mpls_label_5", decodeHex}},      // MPLS_LABEL_5 / mplsLabelStackSection5
	75: {{"mpls_label_6", decodeHex}},      // MPLS_LABEL_6 / mplsLabelStackSection6
	76: {{"mpls_label_7", decodeHex}},      // MPLS_LABEL_7 / mplsLabelStackSection7
	77: {{"mpls_label_8", decodeHex}},      // MPLS_LABEL_8 / mplsLabelStackSection8
	78: {{"mpls_label_9", decodeHex}},      // MPLS_LABEL_9 / mplsLabelStackSection9
	79: {{"mpls_label_10", decodeHex}},     // MPLS_LABEL_10 / mplsLabelStackSection10
	80: {{"in_dst_mac", decodeMAC}},        // IN_DST_MAC / destinationMacAddress
	81: {{"out_src_mac", decodeMAC}},       // OUT_SRC_MAC / postSourceMacAddress
	82: {{"interface", decodeString}},      // IF_NAME / interfaceName
	83: {{"interface_desc", decodeString}}, // IF_DESC / interfaceDescription
	84: {{"sampler_name", decodeString}},   // SAMPLER_NAME / samplerName
	85: {{"in_total_bytes", decodeUint}},   // IN_PERMANENT_BYTES / octetTotalCount
	86: {{"in_total_packets", decodeUint}}, // IN_PERMANENT_PKTS / packetTotalCount
	// 87: vendor proprietary
	88: {{"fragment_offset", decodeUint}}, // FRAGMENT_OFFSET / fragmentOffset
	89: {
		{"fwd_status", decodeFwdStatus}, // FORWARDING STATUS / forwardingStatus
		{"fwd_reason", decodeFwdReason},
	},
	90: {{"mpls_vpn_rd", decodeHex}},        // MPLS PAL RD / mplsVpnRouteDistinguisher
	91: {{"mpls_prefix_len", decodeUint}},   // MPLS PREFIX LEN / mplsTopLabelPrefixLength
	92: {{"src_traffic_index", decodeUint}}, // SRC TRAFFIC INDEX / srcTrafficIndex
	93: {{"dst_traffic_index", decodeUint}}, // DST TRAFFIC INDEX / dstTrafficIndex
	94: {{"app_desc", decodeString}},        // APPLICATION DESCRIPTION / applicationDescription
	95: {{"app_id", decodeHex}},             // APPLICATION TAG / applicationId
	96: {{"app_name", decodeString}},        // APPLICATION NAME / applicationName
	// 97: undefined
	98: {{"out_dscp", decodeUint}},           // postipDiffServCodePoint / postIpDiffServCodePoint
	99: {{"replication_factor", decodeUint}}, // replication factor / multicastReplicationFactor
	// 100: deprecated / className
	101: {{"classification_engine_id", decodeUint}}, // undefined / classificationEngineId
	102: {{"l2_packet_section_offset", decodeUint}}, // layer2packetSectionOffset
	103: {{"l2_packet_section_size", decodeUint}},   // layer2packetSectionSize
	104: {{"l2_packet_section_data", decodeHex}},    // layer2packetSectionData
	// 105 - 127:  reserved

	// Common between Netflow v9 ASA extension
	// https://www.cisco.com/c/en/us/td/docs/security/asa/special/netflow/asa_netflow.html
	// and IPFIX.
	148: {{"flow_id", decodeUint}},         // flowId
	152: {{"flow_start_ms", decodeUint}},   // NF_F_FLOW_CREATE_TIME_MSEC / flowStartMilliseconds
	153: {{"flow_end_ms", decodeUint}},     // NF_F_FLOW_END_TIME_MSEC / flowEndMilliseconds
	176: {{"icmp_type", decodeUint}},       // NF_F_ICMP_TYPE / icmpTypeIPv4
	177: {{"icmp_code", decodeUint}},       // NF_F_ICMP_CODE / icmpCodeIPv4
	178: {{"icmp_type", decodeUint}},       // NF_F_ICMP_TYPE_IPV6 / icmpTypeIPv6
	179: {{"icmp_code", decodeUint}},       // NF_F_ICMP_CODE_IPV6 / icmpCodeIPv6
	225: {{"xlat_src", decodeIP}},          // NF_F_XLATE_SRC_ADDR_IPV4 / postNATSourceIPv4Address
	226: {{"xlat_dst", decodeIP}},          // NF_F_XLATE_DST_ADDR_IPV4 / postNATDestinationIPv4Address
	227: {{"xlat_src_port", decodeUint}},   // NF_F_XLATE_SRC_PORT / postNAPTSourceTransportPort
	228: {{"xlat_dst_port", decodeUint}},   // NF_F_XLATE_DST_PORT / postNAPTDestinationTransportPort
	231: {{"initiator_bytes", decodeUint}}, // NF_F_FWD_FLOW_DELTA_BYTES / initiatorOctets
	232: {{"responder_bytes", decodeUint}}, // NF_F_REV_FLOW_DELTA_BYTES / responderOctets
	233: {{"fw_event", decodeFWEvent}},     // NF_F_FW_EVENT / firewallEvent
	281: {{"xlat_src", decodeIP}},          // NF_F_XLATE_SRC_ADDR_IPV6 / postNATSourceIPv6Address
	282: {{"xlat_dst", decodeIP}},          // NF_F_XLATE_DST_ADDR_IPV6 / postNATDestinationIPv6Address
	323: {{"event_time_ms", decodeUint}},   // NF_F_EVENT_TIME_MSEC / observationTimeMilliseconds
	324: {{"event_time_us", decodeUint}},   // NF_F_EVENT_TIME_USEC / observationTimeMicroseconds
	325: {{"event_time_ns", decodeUint}},   // NF_F_EVENT_TIME_NSEC / observationTimeNanoseconds
}

// Default field mappings specific to Netflow version 9
// From documentation at https://www.cisco.com/c/en/us/td/docs/security/asa/special/netflow/asa_netflow.html
var fieldMappingsNetflowV9 = map[uint16][]fieldMapping{
	33000: {{"in_acl_id", decodeHex}},    // NF_F_INGRESS_ACL_ID
	33001: {{"out_acl_id", decodeHex}},   // NF_F_EGRESS_ACL_ID
	33002: {{"fw_event_ext", decodeHex}}, // NF_F_FW_EXT_EVENT
	40000: {{"username", decodeString}},  // NF_F_USERNAME
}

// Default field mappings specific to Netflow version 9
// From documentation at
// https://www.iana.org/assignments/ipfix/ipfix.xhtml#ipfix-information-elements
var fieldMappingsIPFIX = map[uint16][]fieldMapping{
	128: {{"bgp_next_as", decodeUint}},              // bgpNextAdjacentAsNumber
	129: {{"bgp_prev_as", decodeUint}},              // bgpPrevAdjacentAsNumber
	130: {{"exporter", decodeIP}},                   // exporterIPv4Address
	131: {{"exporter", decodeIP}},                   // exporterIPv6Address
	132: {{"dropped_bytes", decodeUint}},            // droppedOctetDeltaCount
	133: {{"dropped_packets", decodeUint}},          // droppedPacketDeltaCount
	134: {{"dropped_bytes_total", decodeUint}},      // droppedOctetTotalCount
	135: {{"dropped_packets_total", decodeUint}},    // droppedPacketTotalCount
	136: {{"flow_end_reason", decodeFlowEndReason}}, // flowEndReason
	137: {{"common_properties_id", decodeUint}},     // commonPropertiesId
	138: {{"observation_point_id", decodeUint}},     // observationPointId
	139: {
		{"icmp_type", decodeByteFunc(0)}, // icmpTypeCodeIPv6
		{"icmp_code", decodeByteFunc(1)},
	},
	140: {{"mpls_top_label_ip", decodeIP}}, // mplsTopLabelIPv6Address
	141: {{"linecard_id", decodeUint}},     // lineCardId
	142: {{"port_id", decodeUint}},         // portId
	143: {{"metering_pid", decodeUint}},    // meteringProcessId
	144: {{"exporting_pid", decodeUint}},   // exportingProcessId
	145: {{"template_id", decodeUint}},     // templateId
	146: {{"wlan_channel", decodeUint}},    // wlanChannelId
	147: {{"wlan_ssid", decodeString}},     // wlanSSID
	// 148: common
	149: {{"observation_domain_id", decodeUint}}, // observationDomainId
	150: {{"flow_start", decodeUint}},            // flowStartSeconds
	151: {{"flow_end", decodeUint}},              // flowEndSeconds
	// 152 - 153: common
	154: {{"flow_start_us", decodeUint}},            // flowStartMicroseconds
	155: {{"flow_end_us", decodeUint}},              // flowEndMicroseconds
	156: {{"flow_start_ns", decodeUint}},            // flowStartNanoseconds
	157: {{"flow_end_ns", decodeUint}},              // flowEndNanoseconds
	158: {{"flow_start_delta_us", decodeUint}},      // flowStartDeltaMicroseconds
	159: {{"flow_end_delta_us", decodeUint}},        // flowEndDeltaMicroseconds
	160: {{"system_init_ms", decodeUint}},           // systemInitTimeMilliseconds
	161: {{"flow_duration_ms", decodeUint}},         // flowDurationMilliseconds
	162: {{"flow_duration_us", decodeUint}},         // flowDurationMicroseconds
	163: {{"flow_count_total", decodeUint}},         // observedFlowTotalCount
	164: {{"ignored_packet_total", decodeUint}},     // ignoredPacketTotalCount
	165: {{"ignored_bytes_total", decodeUint}},      // ignoredOctetTotalCount
	166: {{"notsent_flow_count_total", decodeUint}}, // notSentFlowTotalCount
	167: {{"notsent_packet_total", decodeUint}},     // notSentPacketTotalCount
	168: {{"notsent_bytes_total", decodeUint}},      // notSentOctetTotalCount
	169: {{"ipv6_dst_prefix", decodeIP}},            // destinationIPv6Prefix
	170: {{"ipv6_src_prefix", decodeIP}},            // sourceIPv6Prefix
	171: {{"out_bytes_total", decodeUint}},          // postOctetTotalCount
	172: {{"out_packets_total", decodeUint}},        // postPacketTotalCount
	173: {{"flow_key_indicator", decodeHex}},        // flowKeyIndicator
	174: {{"out_mcast_packets_total", decodeUint}},  // postMCastPacketTotalCount
	175: {{"out_mcast_bytes_total", decodeUint}},    // postMCastOctetTotalCount
	// 176 - 179: common
	180: {{"udp_src_port", decodeUint}},             // udpSourcePort
	181: {{"udp_dst_port", decodeUint}},             // udpDestinationPort
	182: {{"tcp_src_port", decodeUint}},             // tcpSourcePort
	183: {{"tcp_dst_port", decodeUint}},             // tcpDestinationPort
	184: {{"tcp_seq_number", decodeUint}},           // tcpSequenceNumber
	185: {{"tcp_ack_number", decodeUint}},           // tcpAcknowledgementNumber
	186: {{"tcp_window_size", decodeUint}},          // tcpWindowSize
	187: {{"tcp_urgent_ptr", decodeUint}},           // tcpUrgentPointer
	188: {{"tcp_header_len", decodeUint}},           // tcpHeaderLength
	189: {{"ip_header_len", decodeUint}},            // ipHeaderLength
	190: {{"ipv4_total_len", decodeUint}},           // totalLengthIPv4
	191: {{"ipv6_payload_len", decodeUint}},         // payloadLengthIPv6
	192: {{"ttl", decodeUint}},                      // ipTTL
	193: {{"ipv6_next_header", decodeUint}},         // nextHeaderIPv6
	194: {{"mpls_payload_len", decodeUint}},         // mplsPayloadLength
	195: {{"dscp", decodeUint}},                     // ipDiffServCodePoint
	196: {{"precedence", decodeUint}},               // ipPrecedence
	197: {{"fragment_flags", decodeFragmentFlags}},  // fragmentFlags
	198: {{"bytes_sqr_sum", decodeUint}},            // octetDeltaSumOfSquares
	199: {{"bytes_sqr_sum_total", decodeUint}},      // octetTotalSumOfSquares
	200: {{"mpls_top_label_ttl", decodeUint}},       // mplsTopLabelTTL
	201: {{"mpls_stack_len", decodeUint}},           // mplsLabelStackLength
	202: {{"mpls_stack_depth", decodeUint}},         // mplsLabelStackDepth
	203: {{"mpls_top_label_exp", decodeUint}},       // mplsTopLabelExp
	204: {{"ip_payload_len", decodeUint}},           // ipPayloadLength
	205: {{"udp_msg_len", decodeUint}},              // udpMessageLength
	206: {{"mcast", decodeUint}},                    // isMulticast
	207: {{"ipv4_inet_header_len", decodeUint}},     // ipv4IHL
	208: {{"ipv4_options", decodeIPv4Options}},      // ipv4Options
	209: {{"tcp_options", decodeHex}},               // tcpOptions
	210: {{"padding", decodeHex}},                   // paddingOctets
	211: {{"collector", decodeIP}},                  // collectorIPv4Address
	212: {{"collector", decodeIP}},                  // collectorIPv6Address
	213: {{"export_interface", decodeUint}},         // exportInterface
	214: {{"export_proto_version", decodeUint}},     // exportProtocolVersion
	215: {{"export_transport_proto", decodeUint}},   // exportTransportProtocol
	216: {{"collector_transport_port", decodeUint}}, // collectorTransportPort
	217: {{"exporter_transport_port", decodeUint}},  // exporterTransportPort
	218: {{"tcp_syn_total", decodeUint}},            // tcpSynTotalCount
	219: {{"tcp_fin_total", decodeUint}},            // tcpFinTotalCount
	220: {{"tcp_rst_total", decodeUint}},            // tcpRstTotalCount
	221: {{"tcp_psh_total", decodeUint}},            // tcpPshTotalCount
	222: {{"tcp_ack_total", decodeUint}},            // tcpAckTotalCount
	223: {{"tcp_urg_total", decodeUint}},            // tcpUrgTotalCount
	224: {{"ip_total_len", decodeUint}},             // ipTotalLength
	// 225 - 228: common
	229: {{"nat_origin_addr_realm", decodeUint}}, // natOriginatingAddressRealm
	230: {{"nat_event", decodeUint}},             // natEvent
	// 231 - 233: common
	234: {{"in_vrf_id", decodeUint}},                      // ingressVRFID
	235: {{"out_vrf_id", decodeUint}},                     // egressVRFID
	236: {{"vrf_name", decodeString}},                     // VRFname
	237: {{"out_mpls_top_label_exp", decodeUint}},         // postMplsTopLabelExp
	238: {{"tcp_window_scale", decodeUint}},               // tcpWindowScale
	239: {{"biflow_direction", decodeBiflowDirection}},    // biflowDirection
	240: {{"eth_header_len", decodeUint}},                 // ethernetHeaderLength
	241: {{"eth_payload_len", decodeUint}},                // ethernetPayloadLength
	242: {{"eth_total_len", decodeUint}},                  // ethernetTotalLength
	243: {{"vlan_id", decodeUint}},                        // dot1qVlanId
	244: {{"vlan_priority", decodeUint}},                  // dot1qPriority
	245: {{"vlan_customer_id", decodeUint}},               // dot1qCustomerVlanId
	246: {{"vlan_customer_priority", decodeUint}},         // dot1qCustomerPriority
	247: {{"metro_evc_id", decodeString}},                 // metroEvcId
	248: {{"metro_evc_type", decodeUint}},                 // metroEvcType
	249: {{"pseudo_wire_id", decodeUint}},                 // pseudoWireId
	250: {{"pseudo_wire_type", decodeHex}},                // pseudoWireType
	251: {{"pseudo_wire_ctrl_word", decodeHex}},           // pseudoWireControlWord
	252: {{"in_phy_interface", decodeUint}},               // ingressPhysicalInterface
	253: {{"out_phy_interface", decodeUint}},              // egressPhysicalInterface
	254: {{"out_vlan_id", decodeUint}},                    // postDot1qVlanId
	255: {{"out_vlan_customer_id", decodeUint}},           // postDot1qCustomerVlanId
	256: {{"eth_type", decodeHex}},                        // ethernetType
	257: {{"out_precedence", decodeUint}},                 // postIpPrecedence
	258: {{"collection_time_ms", decodeUint}},             // collectionTimeMilliseconds
	259: {{"export_sctp_stream_id", decodeUint}},          // exportSctpStreamId
	260: {{"max_export_time", decodeUint}},                // maxExportSeconds
	261: {{"max_flow_end_time", decodeUint}},              // maxFlowEndSeconds
	262: {{"msg_md5", decodeHex}},                         // messageMD5Checksum
	263: {{"msg_scope", decodeUint}},                      // messageScope
	264: {{"min_export_time", decodeUint}},                // minExportSeconds
	265: {{"min_flow_start_time", decodeUint}},            // minFlowStartSeconds
	266: {{"opaque_bytes", decodeUint}},                   // opaqueOctets
	267: { /* MUST BE IGNORED according to standard */ },  // sessionScope
	268: {{"max_flow_end_time_us", decodeUint}},           // maxFlowEndMicroseconds
	269: {{"max_flow_end_time_ms", decodeUint}},           // maxFlowEndMilliseconds
	270: {{"max_flow_end_time_ns", decodeUint}},           // maxFlowEndNanoseconds
	271: {{"min_flow_start_time_us", decodeUint}},         // minFlowStartMicroseconds
	272: {{"min_flow_start_time_ms", decodeUint}},         // minFlowStartMilliseconds
	273: {{"min_flow_start_time_ns", decodeUint}},         // minFlowStartNanoseconds
	274: {{"collector_cert", decodeString}},               // collectorCertificate
	275: {{"exporter_cert", decodeString}},                // exporterCertificate
	276: {{"data_records_reliability", decodeBool}},       // dataRecordsReliability
	277: {{"observation_point_type", decodeOpsPointType}}, // observationPointType
	278: {{"connection_new_count", decodeUint}},           // newConnectionDeltaCount
	279: {{"connection_duration_sum", decodeUint}},        // connectionSumDurationSeconds
	280: {{"connection_transaction_id", decodeUint}},      // connectionTransactionId
	// 281 - 282: common
	283: {{"nat_pool_id", decodeUint}},     // natPoolId
	284: {{"nat_pool_name", decodeString}}, // natPoolName
	285: {
		{"anon_stability_class", decodeAnonStabilityClass}, // anonymizationFlags
		{"anon_flags", decodeAnonFlags},
	},
	286: {{"anon_technique", decodeAnonTechnique}},         // anonymizationTechnique
	287: {{"information_element", decodeUint}},             // informationElementIndex
	288: {{"p2p", decodeTechnology}},                       // p2pTechnology
	289: {{"tunnel", decodeTechnology}},                    // tunnelTechnology
	290: {{"encryption", decodeTechnology}},                // encryptedTechnology
	291: { /* IGNORED for parse-ability */ },               // basicList
	292: { /* IGNORED for parse-ability */ },               // subTemplateList
	293: { /* IGNORED for parse-ability */ },               // subTemplateMultiList
	294: {{"bgp_validity_state", decodeUint}},              // bgpValidityState
	295: {{"ipsec_spi", decodeUint}},                       // IPSecSPI
	296: {{"gre_key", decodeUint}},                         // greKey
	297: {{"nat_type", decodeIPNatType}},                   // natType
	298: {{"initiator_packets", decodeUint}},               // initiatorPackets
	299: {{"responder_packets", decodeUint}},               // responderPackets
	300: {{"observation_domain_name", decodeString}},       // observationDomainName
	301: {{"observation_seq_id", decodeUint}},              // selectionSequenceId
	302: {{"selector_id", decodeUint}},                     // selectorId
	303: {{"information_elem_id", decodeUint}},             // informationElementId
	304: {{"selector_algo", decodeSelectorAlgorithm}},      // selectorAlgorithm
	305: {{"sampling_packet_interval", decodeUint}},        // samplingPacketInterval
	306: {{"sampling_packet_space", decodeUint}},           // samplingPacketSpace
	307: {{"sampling_time_interval_us", decodeUint}},       // samplingTimeInterval
	308: {{"sampling_time_space_us", decodeUint}},          // samplingTimeSpace
	309: {{"sampling_size", decodeUint}},                   // samplingSize
	310: {{"sampling_population", decodeUint}},             // samplingPopulation
	311: {{"sampling_probability", decodeFloat64}},         // samplingProbability
	312: {{"datalink_frame_size", decodeUint}},             // dataLinkFrameSize
	313: {{"ip_header_packet_section", decodeHex}},         // ipHeaderPacketSection
	314: {{"ip_payload_packet_section", decodeHex}},        // ipPayloadPacketSection
	315: {{"datalink_frame_section", decodeHex}},           // dataLinkFrameSection
	316: {{"mpls_label_stack_section", decodeHex}},         // mplsLabelStackSection
	317: {{"mpls_payload_packet_section", decodeHex}},      // mplsPayloadPacketSection
	318: {{"selector_total_packets_observed", decodeUint}}, // selectorIdTotalPktsObserved
	319: {{"selector_total_packets_selected", decodeUint}}, // selectorIdTotalPktsSelected
	320: {{"absolute_error", decodeFloat64}},               // absoluteError
	321: {{"relative_error", decodeFloat64}},               // relativeError
	322: {{"event_time", decodeUint}},                      // observationTimeSeconds
	// 323 - 325: common
	326: {{"hash_digest", decodeHex}},                         // digestHashValue
	327: {{"hash_ip_payload_offset", decodeUint}},             // hashIPPayloadOffset
	328: {{"hash_ip_payload_size", decodeUint}},               // hashIPPayloadSize
	329: {{"hash_out_range_min", decodeUint}},                 // hashOutputRangeMin
	330: {{"hash_out_range_max", decodeUint}},                 // hashOutputRangeMax
	331: {{"hash_selected_range_min", decodeUint}},            // hashSelectedRangeMin
	332: {{"hash_selected_range_max", decodeUint}},            // hashSelectedRangeMax
	333: {{"hash_digest_out", decodeBool}},                    // hashDigestOutput
	334: {{"hash_init_val", decodeUint}},                      // hashInitialiserValue
	335: {{"selector_name", decodeString}},                    // selectorName
	336: {{"upper_confidence_interval_limit", decodeFloat64}}, // upperCILimit
	337: {{"lower_confidence_interval_limit", decodeFloat64}}, // upperCILimit
	338: {{"confidence_level", decodeFloat64}},                // confidenceLevel
	// 339 - 346: information element fields, do not map for now
	347: {{"virtual_station_interface_id", decodeHex}},      // virtualStationInterfaceId
	348: {{"virtual_station_interface_name", decodeString}}, // virtualStationInterfaceName
	349: {{"virtual_station_uuid", decodeHex}},              // virtualStationUUID
	350: {{"virtual_station_name", decodeString}},           // virtualStationName
	351: {{"l2_segment_id", decodeUint}},                    // layer2SegmentId
	352: {{"l2_bytes", decodeUint}},                         // layer2OctetDeltaCount
	353: {{"l2_bytes_total", decodeUint}},                   // layer2OctetTotalCount
	354: {{"in_unicast_packets_total", decodeUint}},         // ingressUnicastPacketTotalCount
	355: {{"in_mcast_packets_total", decodeUint}},           // ingressMulticastPacketTotalCount
	356: {{"in_broadcast_packets_total", decodeUint}},       // ingressBroadcastPacketTotalCount
	357: {{"out_unicast_packets_total", decodeUint}},        // egressUnicastPacketTotalCount
	358: {{"out_broadcast_packets_total", decodeUint}},      // egressBroadcastPacketTotalCount
	359: {{"monitoring_interval_start_ms", decodeUint}},     // monitoringIntervalStartMilliSeconds
	360: {{"monitoring_interval_end_ms", decodeUint}},       // monitoringIntervalEndMilliSeconds
	361: {{"port_range_start", decodeUint}},                 // portRangeStart
	362: {{"port_range_end", decodeUint}},                   // portRangeEnd
	363: {{"port_range_step_size", decodeUint}},             // portRangeStepSize
	364: {{"port_range_ports", decodeUint}},                 // portRangeNumPorts
	365: {{"station_mac", decodeMAC}},                       // staMacAddress
	366: {{"station", decodeIP}},                            // staIPv4Address
	367: {{"wtp_mac", decodeMAC}},                           // wtpMacAddress
	368: {{"in_interface_type", decodeUint}},                // ingressInterfaceType
	369: {{"out_interface_type", decodeUint}},               // egressInterfaceType
	370: {{"rtp_seq_number", decodeUint}},                   // rtpSequenceNumber
	371: {{"username", decodeString}},                       // userName
	372: {{"app_category", decodeString}},                   // applicationCategoryName
	373: {{"app_subcategory", decodeHex}},                   // applicationSubCategoryName
	374: {{"app_group", decodeString}},                      // applicationGroupName
	375: {{"flows_original_present", decodeUint}},           // originalFlowsPresent
	376: {{"flows_original_initiated", decodeUint}},         // originalFlowsInitiated
	377: {{"flows_original_completed", decodeUint}},         // originalFlowsCompleted
	378: {{"flow_src_ip_count", decodeUint}},                // distinctCountOfSourceIPAddress
	379: {{"flow_dst_ip_count", decodeUint}},                // distinctCountOfDestinationIPAddress
	380: {{"flow_src_ipv4_count", decodeUint}},              // distinctCountOfSourceIPv4Address
	381: {{"flow_dst_ipv4_count", decodeUint}},              // distinctCountOfDestinationIPv4Address
	382: {{"flow_src_ipv6_count", decodeUint}},              // distinctCountOfSourceIPv6Address
	383: {{"flow_dst_ipv6_count", decodeUint}},              // distinctCountOfDestinationIPv6Address
	384: {{"value_dist_method", decodeValueDistMethod}},     // valueDistributionMethod
	385: {{"rfc3550_jitter_ms", decodeUint}},                // rfc3550JitterMilliseconds
	386: {{"rfc3550_jitter_us", decodeUint}},                // rfc3550JitterMicroseconds
	387: {{"rfc3550_jitter_ns", decodeUint}},                // rfc3550JitterNanoseconds
	388: {{"vlan_dei", decodeBool}},                         // dot1qDEI
	389: {{"vlan_customer_dei", decodeUint}},                // dot1qCustomerDEI
	390: {{"flow_selector_algo", decodeSelectorAlgorithm}},  // flowSelectorAlgorithm
	391: {{"flow_selected_byte_count", decodeUint}},         // flowSelectedOctetDeltaCount
	392: {{"flow_selected_packet_count", decodeUint}},       // flowSelectedOctetDeltaCount
	393: {{"flow_selected_count", decodeUint}},              // flowSelectedFlowDeltaCount
	394: {{"selector_id_flows_observed_total", decodeUint}}, // selectorIDTotalFlowsObserved
	395: {{"selector_id_flows_selected_total", decodeUint}}, // selectorIDTotalFlowsSelected
	396: {{"sampling_flow_interval_count", decodeUint}},     // samplingFlowInterval
	397: {{"sampling_flow_spacing_count", decodeUint}},      // samplingFlowSpacing
	398: {{"sampling_flow_interval_ms", decodeUint}},        // flowSamplingTimeInterval
	399: {{"sampling_flow_spacing_ms", decodeUint}},         // flowSamplingTimeSpacing
	400: {{"flow_domain_hash_element_id", decodeUint}},      // hashFlowDomain
	401: {{"transport_byte_count", decodeUint}},             // transportOctetDeltaCount
	402: {{"transport_packet_count", decodeUint}},           // transportPacketDeltaCount
	403: {{"exporter_original_ip", decodeUint}},             // originalExporterIPv4Address
	404: {{"exporter_original_ip", decodeUint}},             // originalExporterIPv6Address
	405: {{"exporter_original_domain", decodeHex}},          // originalObservationDomainId
	406: {{"intermediate_process_id", decodeHex}},           // intermediateProcessId
	407: {{"ignored_data_records_total", decodeUint}},       // ignoredDataRecordTotalCount
	408: {{"datalink_frame_type", decodeDataLinkFrameType}}, // dataLinkFrameType
	409: {{"section_offset", decodeUint}},                   // sectionOffset
	410: {{"section_exported_bytes", decodeUint}},           // sectionExportedOctets
	411: {{"vlan_service_instance_tag", decodeHex}},         // dot1qServiceInstanceTag
	412: {{"vlan_service_instance_id", decodeUint}},         // dot1qServiceInstanceId
	413: {{"vlan_service_instance_priority", decodeUint}},   // dot1qServiceInstancePriority
	414: {{"vlan_customer_src_mac", decodeMAC}},             // dot1qCustomerSourceMacAddress
	415: {{"vlan_customer_dst_mac", decodeMAC}},             // dot1qCustomerDestinationMacAddress
	// 416: deprecated
	417: {{"post_layer2_bytes", decodeUint}},       // postLayer2OctetDeltaCount
	418: {{"post_mcast_layer2_bytes", decodeUint}}, // postMCastLayer2OctetDeltaCount
	// 419: deprecated
	420: {{"post_layer2_bytes_total", decodeUint}},                    // postLayer2OctetTotalCount
	421: {{"post_mcast_layer2_bytes_total", decodeUint}},              // postMCastLayer2OctetTotalCount
	422: {{"min_layer2_total_length", decodeUint}},                    // minimumLayer2TotalLength
	423: {{"max_layer2_total_length", decodeUint}},                    // maximumLayer2TotalLength
	424: {{"dropped_layer2_bytes", decodeUint}},                       // droppedLayer2OctetDeltaCount
	425: {{"dropped_layer2_bytes_total", decodeUint}},                 // droppedLayer2OctetTotalCount
	426: {{"ignored_layer2_bytes_total", decodeUint}},                 // ignoredLayer2OctetTotalCount
	427: {{"not_sent_layer2_bytes_total", decodeUint}},                // notSentLayer2OctetTotalCount
	428: {{"layer2_bytes_sumsqr", decodeUint}},                        // layer2OctetDeltaSumOfSquares
	429: {{"layer2_bytes_total_sumsqr", decodeUint}},                  // layer2OctetTotalSumOfSquares
	430: {{"layer2_frames", decodeUint}},                              // layer2FrameDeltaCount
	431: {{"layer2_frames_total", decodeUint}},                        // layer2FrameTotalCount
	432: {{"pseudo_wire_dst", decodeIP}},                              // pseudoWireDestinationIPv4Address
	433: {{"ignored_layer2_frames_total", decodeUint}},                // ignoredLayer2FrameTotalCount
	434: {{"mib_obj_value_int", decodeInt}},                           // mibObjectValueInteger
	435: {{"mib_obj_value_str", decodeString}},                        // mibObjectValueOctetString
	436: {{"mib_obj_value_oid", decodeHex}},                           // mibObjectValueOID
	437: {{"mib_obj_value_bits", decodeHex}},                          // mibObjectValueBits
	438: {{"mib_obj_value_ip", decodeIP}},                             // mibObjectValueIPAddress
	439: {{"mib_obj_value_counter", decodeUint}},                      // mibObjectValueCounter
	440: {{"mib_obj_value_gauge", decodeUint}},                        // mibObjectValueGauge
	441: {{"mib_obj_value_time", decodeUint}},                         // mibObjectValueTimeTicks
	442: {{"mib_obj_value_uint", decodeUint}},                         // mibObjectValueUnsigned
	443: {{"mib_obj_value_table", decodeHex}},                         // mibObjectValueTable
	444: {{"mib_obj_value_row", decodeHex}},                           // mibObjectValueRow
	445: {{"mib_oid", decodeHex}},                                     // mibObjectIdentifier
	446: {{"mib_sub_id", decodeUint}},                                 // mibSubIdentifier
	447: {{"mib_index_indicator", decodeHex}},                         // mibIndexIndicator
	448: {{"mib_capture_time_semantics", decodeCaptureTimeSemantics}}, // mibCaptureTimeSemantics
	449: {{"mib_context_engine_id", decodeHex}},                       // mibContextEngineID
	450: {{"mib_context_name", decodeString}},                         // mibContextName
	451: {{"mib_obj_name", decodeString}},                             // mibObjectName
	452: {{"mib_obj_desc", decodeString}},                             // mibObjectDescription
	453: {{"mib_obj_syntax", decodeString}},                           // mibObjectSyntax
	454: {{"mib_module_name", decodeString}},                          // mibModuleName
	455: {{"imsi", decodeString}},                                     // mobileIMSI
	456: {{"msisdn", decodeString}},                                   // mobileMSISDN
	457: {{"http_status_code", decodeUint}},                           // httpStatusCode
	458: {{"src_transport_port_limit", decodeUint}},                   // sourceTransportPortsLimit
	459: {{"http_request_method", decodeString}},                      // httpRequestMethod
	460: {{"http_request_host", decodeString}},                        // httpRequestHost
	461: {{"http_request_target", decodeString}},                      // httpRequestTarget
	462: {{"http_msg_version", decodeString}},                         // httpMessageVersion
	463: {{"nat_instance_id", decodeUint}},                            // natInstanceID
	464: {{"internal_addr_realm", decodeHex}},                         // internalAddressRealm
	465: {{"external_addr_realm", decodeHex}},                         // externalAddressRealm
	466: {{"nat_quota_exceeded_event", decodeUint}},                   // natQuotaExceededEvent
	467: {{"nat_threshold_event", decodeUint}},                        // natThresholdEvent
	468: {{"http_user_agent", decodeString}},                          // httpUserAgent
	469: {{"http_content_type", decodeString}},                        // httpContentType
	470: {{"http_reason_phrase", decodeString}},                       // httpReasonPhrase
	471: {{"max_session_entries", decodeUint}},                        // maxSessionEntries
	472: {{"max_bib_entries", decodeUint}},                            // maxBIBEntries
	473: {{"max_entries_per_user", decodeUint}},                       // maxEntriesPerUser
	474: {{"max_subscribers", decodeUint}},                            // maxSubscribers
	475: {{"max_fragments_pending_reassembly", decodeUint}},           // maxFragmentsPendingReassembly
	476: {{"addr_pool_threshold_high", decodeUint}},                   // addressPoolHighThreshold
	477: {{"addr_pool_threshold_low", decodeUint}},                    // addressPoolLowThreshold
	478: {{"addr_port_mapping_threshold_high", decodeUint}},           // addressPortMappingHighThreshold
	479: {{"addr_port_mapping_threshold_low", decodeUint}},            // addressPortMappingLowThreshold
	480: {{"addr_port_mapping_per_user_threshold_high", decodeUint}},  // addressPortMappingPerUserHighThreshold
	481: {{"global_addr_mapping_threshold_high", decodeUint}},         // globalAddressMappingHighThreshold
	482: {{"vpn_identifier", decodeIP}},                               // vpnIdentifier
	483: {{"bgp_community", decodeUint}},                              // bgpCommunity
	484: {{"bgp_src_community_list", decodeHex}},                      // bgpSourceCommunityList
	485: {{"bgp_dst_community_list", decodeHex}},                      // bgpDestinationCommunityList
	486: {{"bgp_extended_community", decodeHex}},                      // bgpExtendedCommunity
	487: {{"bgp_src_extended_community_list", decodeHex}},             // bgpSourceExtendedCommunityList
	488: {{"bgp_dst_extended_community_list", decodeHex}},             // bgpDestinationExtendedCommunityList
	489: {{"bgp_large_community", decodeHex}},                         // bgpLargeCommunity
	490: {{"bgp_src_large_community_list", decodeHex}},                // bgpSourceLargeCommunityList
	491: {{"bgp_dst_large_community_list", decodeHex}},                // bgpDestinationLargeCommunityList
}

// Decoder structure
type netflowDecoder struct {
	penFiles []string
	log      telegraf.Logger

	templates     map[string]netflow.NetFlowTemplateSystem
	mappingsV9    map[uint16]fieldMapping
	mappingsIPFIX map[uint16]fieldMapping
	mappingsPEN   map[string]fieldMapping

	logged map[string]bool
	sync.Mutex
}

func (d *netflowDecoder) decode(srcIP net.IP, payload []byte) ([]telegraf.Metric, error) {
	var metrics []telegraf.Metric

	t := time.Now()
	src := srcIP.String()

	// Prepare the templates used to decode the messages
	d.Lock()
	if _, ok := d.templates[src]; !ok {
		d.templates[src] = netflow.CreateTemplateSystem()
	}
	templates := d.templates[src]
	d.Unlock()

	// Decode the overall message
	var msg9 netflow.NFv9Packet
	var msg10 netflow.IPFIXPacket
	buf := bytes.NewBuffer(payload)
	if err := netflow.DecodeMessageVersion(buf, templates, &msg9, &msg10); err != nil {
		if errors.Is(err, netflow.ErrorTemplateNotFound) {
			msg := "Skipping packet until the device resends the required template..."
			d.log.Warnf("%v. %s", err, msg)
			return nil, nil
		}
		return nil, fmt.Errorf("decoding message failed: %w", err)
	}

	// Extract metrics
	switch {
	case msg9.Version == 9:
		msg := msg9
		for _, flowsets := range msg.FlowSets {
			switch fs := flowsets.(type) {
			case netflow.TemplateFlowSet:
			case netflow.NFv9OptionsTemplateFlowSet:
			case netflow.OptionsDataFlowSet:
				for _, record := range fs.Records {
					tags := map[string]string{
						"source":  src,
						"version": "NetFlowV9",
					}
					fields := make(map[string]interface{})
					for _, value := range record.ScopesValues {
						decodedFields, err := d.decodeValueV9(value)
						if err != nil {
							d.log.Errorf("decoding option record %+v failed: %v", record, err)
							continue
						}
						for _, field := range decodedFields {
							fields[field.Key] = field.Value
						}
					}
					for _, value := range record.OptionsValues {
						decodedFields, err := d.decodeValueV9(value)
						if err != nil {
							d.log.Errorf("decoding option record %+v failed: %v", record, err)
							continue
						}
						for _, field := range decodedFields {
							fields[field.Key] = field.Value
						}
					}
					metrics = append(metrics, metric.New("netflow_options", tags, fields, t))
				}
			case netflow.DataFlowSet:
				for _, record := range fs.Records {
					tags := map[string]string{
						"source":  src,
						"version": "NetFlowV9",
					}
					fields := make(map[string]interface{})
					for _, value := range record.Values {
						decodedFields, err := d.decodeValueV9(value)
						if err != nil {
							d.log.Errorf("decoding record %+v failed: %v", record, err)
							continue
						}
						for _, field := range decodedFields {
							fields[field.Key] = field.Value
						}
					}
					metrics = append(metrics, metric.New("netflow", tags, fields, t))
				}
			}
		}
	case msg10.Version == 10:
		msg := msg10
		for _, flowsets := range msg.FlowSets {
			switch fs := flowsets.(type) {
			case netflow.TemplateFlowSet:
			case netflow.IPFIXOptionsTemplateFlowSet:
			case netflow.OptionsDataFlowSet:
				for _, record := range fs.Records {
					tags := map[string]string{
						"source":  src,
						"version": "IPFIX",
					}
					fields := make(map[string]interface{})
					for _, value := range record.ScopesValues {
						decodedFields, err := d.decodeValueIPFIX(value)
						if err != nil {
							d.log.Errorf("decoding option record %+v failed: %v", record, err)
							continue
						}
						for _, field := range decodedFields {
							fields[field.Key] = field.Value
						}
					}
					for _, value := range record.OptionsValues {
						decodedFields, err := d.decodeValueIPFIX(value)
						if err != nil {
							d.log.Errorf("decoding option record %+v failed: %v", record, err)
							continue
						}
						for _, field := range decodedFields {
							fields[field.Key] = field.Value
						}
					}
					metrics = append(metrics, metric.New("netflow_options", tags, fields, t))
				}
			case netflow.DataFlowSet:
				for _, record := range fs.Records {
					tags := map[string]string{
						"source":  srcIP.String(),
						"version": "IPFIX",
					}
					fields := make(map[string]interface{})
					t := time.Now()
					for _, value := range record.Values {
						decodedFields, err := d.decodeValueIPFIX(value)
						if err != nil {
							d.log.Errorf("decoding value %+v failed: %v", value, err)
							continue
						}
						for _, field := range decodedFields {
							fields[field.Key] = field.Value
						}
					}
					metrics = append(metrics, metric.New("netflow", tags, fields, t))
				}
			}
		}
	default:
		return nil, errors.New("invalid message of type")
	}

	return metrics, nil
}

func (d *netflowDecoder) init() error {
	if err := initL4ProtoMapping(); err != nil {
		return fmt.Errorf("initializing layer 4 protocol mapping failed: %w", err)
	}
	if err := initIPv4OptionMapping(); err != nil {
		return fmt.Errorf("initializing IPv4 options mapping failed: %w", err)
	}

	d.templates = make(map[string]netflow.NetFlowTemplateSystem)
	d.mappingsV9 = make(map[uint16]fieldMapping)
	d.mappingsIPFIX = make(map[uint16]fieldMapping)
	d.mappingsPEN = make(map[string]fieldMapping)
	for _, fn := range d.penFiles {
		d.log.Debugf("Loading PEN mapping file %q...", fn)
		mappings, err := loadMapping(fn)
		if err != nil {
			return err
		}
		for k, v := range mappings {
			if !regexpIPFIXPENMapping.MatchString(k) {
				return fmt.Errorf("key %q in file %q does not match pattern <PEN>.<element-id>; maybe wrong file", k, fn)
			}
			if _, found := d.mappingsPEN[k]; found {
				return fmt.Errorf("duplicate entries for ID %q", k)
			}
			d.mappingsPEN[k] = v
		}
	}
	d.log.Infof("Loaded %d PEN mappings...", len(d.mappingsPEN))

	d.logged = make(map[string]bool)

	return nil
}

func (d *netflowDecoder) decodeValueV9(field netflow.DataField) ([]telegraf.Field, error) {
	raw := field.Value.([]byte)
	elementID := field.Type

	// Check the user-specified mapping
	if m, found := d.mappingsV9[elementID]; found {
		v, err := m.decoder(raw)
		if err != nil {
			return nil, err
		}
		return []telegraf.Field{{Key: m.name, Value: v}}, nil
	}

	// Check the version specific default field mappings
	if mappings, found := fieldMappingsNetflowV9[elementID]; found {
		fields := make([]telegraf.Field, 0, len(mappings))
		for _, m := range mappings {
			v, err := m.decoder(raw)
			if err != nil {
				return nil, err
			}
			fields = append(fields, telegraf.Field{Key: m.name, Value: v})
		}
		return fields, nil
	}

	// Check the common default field mappings
	if mappings, found := fieldMappingsNetflowCommon[elementID]; found {
		fields := make([]telegraf.Field, 0, len(mappings))
		for _, m := range mappings {
			v, err := m.decoder(raw)
			if err != nil {
				return nil, err
			}
			fields = append(fields, telegraf.Field{Key: m.name, Value: v})
		}
		return fields, nil
	}

	// Fallback to IPFIX mappings as some devices seem to send IPFIX elements in
	// Netflow v9 packets. See https://github.com/influxdata/telegraf/issues/14902
	// and https://github.com/influxdata/telegraf/issues/14903.
	if mappings, found := fieldMappingsIPFIX[elementID]; found {
		fields := make([]telegraf.Field, 0, len(mappings))
		for _, m := range mappings {
			v, err := m.decoder(raw)
			if err != nil {
				return nil, err
			}
			fields = append(fields, telegraf.Field{Key: m.name, Value: v})
		}
		return fields, nil
	}

	// Return the raw data if no mapping was found
	key := fmt.Sprintf("type_%d", elementID)
	if !d.logged[key] {
		d.log.Debugf("unknown Netflow v9 data field %v", field)
		d.logged[key] = true
	}
	v, err := decodeHex(raw)
	if err != nil {
		return nil, err
	}

	return []telegraf.Field{{Key: key, Value: v}}, nil
}

func (d *netflowDecoder) decodeValueIPFIX(field netflow.DataField) ([]telegraf.Field, error) {
	raw := field.Value.([]byte)

	// Checking for reverse elements according to RFC5103
	var prefix string
	elementID := field.Type
	if field.Type&0x4000 != 0 {
		prefix = "rev_"
		elementID = field.Type & (0x4000 ^ 0xffff)
	}

	// Handle messages with Private Enterprise Numbers (PENs)
	if field.PenProvided {
		key := fmt.Sprintf("%d.%d", field.Pen, elementID)
		if m, found := d.mappingsPEN[key]; found {
			name := prefix + m.name
			v, err := m.decoder(raw)
			if err != nil {
				return nil, err
			}
			return []telegraf.Field{{Key: name, Value: v}}, nil
		}
		if !d.logged[key] {
			d.log.Debugf("unknown IPFIX PEN data field %v", field)
			d.logged[key] = true
		}
		name := fmt.Sprintf("type_%d_%s%d", field.Pen, prefix, elementID)
		v, err := decodeHex(raw)
		if err != nil {
			return nil, err
		}
		return []telegraf.Field{{Key: name, Value: v}}, nil
	}

	// Check the user-specified mapping
	if m, found := d.mappingsIPFIX[elementID]; found {
		v, err := m.decoder(raw)
		if err != nil {
			return nil, err
		}
		return []telegraf.Field{{Key: prefix + m.name, Value: v}}, nil
	}

	// Check the version specific default field mappings
	if mappings, found := fieldMappingsIPFIX[elementID]; found {
		fields := make([]telegraf.Field, 0, len(mappings))
		for _, m := range mappings {
			v, err := m.decoder(raw)
			if err != nil {
				return nil, err
			}
			fields = append(fields, telegraf.Field{Key: prefix + m.name, Value: v})
		}
		return fields, nil
	}

	// Check the common default field mappings
	if mappings, found := fieldMappingsNetflowCommon[elementID]; found {
		fields := make([]telegraf.Field, 0, len(mappings))
		for _, m := range mappings {
			v, err := m.decoder(raw)
			if err != nil {
				return nil, err
			}
			fields = append(fields, telegraf.Field{Key: prefix + m.name, Value: v})
		}
		return fields, nil
	}

	// Return the raw data if no mapping was found
	key := fmt.Sprintf("type_%d", elementID)
	if !d.logged[key] {
		d.log.Debugf("unknown IPFIX data field %v", field)
		d.logged[key] = true
	}
	v, err := decodeHex(raw)
	if err != nil {
		return nil, err
	}
	return []telegraf.Field{{Key: key, Value: v}}, nil
}
