diff --git a/bpf/flow.h b/bpf/flow.h index fa06e1d8f..f36ce12d6 100644 --- a/bpf/flow.h +++ b/bpf/flow.h @@ -45,6 +45,9 @@ typedef struct flow_id_t { u16 src_port; u16 dst_port; u8 transport_protocol; + // ICMP protocol + u8 icmp_type; + u8 icmp_code; // OS interface index u32 if_index; } __attribute__((packed)) flow_id; diff --git a/bpf/flows.c b/bpf/flows.c index bee299da2..40ea1a1c6 100644 --- a/bpf/flows.c +++ b/bpf/flows.c @@ -13,7 +13,6 @@ until an entry is available. 4) When hash collision is detected, we send the new entry to userpace via ringbuffer. */ - #include #include #include @@ -55,6 +54,15 @@ #define FIN_ACK_FLAG 0x200 #define RST_ACK_FLAG 0x400 +// SCTP protocol header structure, its defined here because its not +// exported by the kernel headers like other protocols. +struct sctphdr { + __be16 source; + __be16 dest; + __be32 vtag; + __le32 checksum; +}; + // Common Ringbuffer as a conduit for ingress/egress flows to userspace struct { __uint(type, BPF_MAP_TYPE_RINGBUF); @@ -104,71 +112,111 @@ static inline void set_flags(struct tcphdr *th, u16 *flags) { *flags |= CWR_FLAG; } } -// sets flow fields from IPv4 header information -static inline int fill_iphdr(struct iphdr *ip, void *data_end, flow_id *id, u16 *flags) { - if ((void *)ip + sizeof(*ip) > data_end) { - return DISCARD; - } - __builtin_memcpy(id->src_ip, ip4in6, sizeof(ip4in6)); - __builtin_memcpy(id->dst_ip, ip4in6, sizeof(ip4in6)); - __builtin_memcpy(id->src_ip + sizeof(ip4in6), &ip->saddr, sizeof(ip->saddr)); - __builtin_memcpy(id->dst_ip + sizeof(ip4in6), &ip->daddr, sizeof(ip->daddr)); - id->transport_protocol = ip->protocol; - id->src_port = 0; - id->dst_port = 0; - switch (ip->protocol) { +// L4_info structure contains L4 headers parsed information. +struct l4_info_t { + // TCP/UDP/SCTP source port in host byte order + u16 src_port; + // TCP/UDP/SCTP destination port in host byte order + u16 dst_port; + // ICMPv4/ICMPv6 type value + u8 icmp_type; + // ICMPv4/ICMPv6 code value + u8 icmp_code; + // TCP flags + u16 flags; +}; + +// Extract L4 info for the supported protocols +static inline void fill_l4info(void *l4_hdr_start, void *data_end, u8 protocol, + struct l4_info_t *l4_info) { + switch (protocol) { case IPPROTO_TCP: { - struct tcphdr *tcp = (void *)ip + sizeof(*ip); + struct tcphdr *tcp = l4_hdr_start; if ((void *)tcp + sizeof(*tcp) <= data_end) { - id->src_port = __bpf_ntohs(tcp->source); - id->dst_port = __bpf_ntohs(tcp->dest); - set_flags(tcp, flags); + l4_info->src_port = __bpf_ntohs(tcp->source); + l4_info->dst_port = __bpf_ntohs(tcp->dest); + set_flags(tcp, &l4_info->flags); } } break; case IPPROTO_UDP: { - struct udphdr *udp = (void *)ip + sizeof(*ip); + struct udphdr *udp = l4_hdr_start; if ((void *)udp + sizeof(*udp) <= data_end) { - id->src_port = __bpf_ntohs(udp->source); - id->dst_port = __bpf_ntohs(udp->dest); + l4_info->src_port = __bpf_ntohs(udp->source); + l4_info->dst_port = __bpf_ntohs(udp->dest); + } + } break; + case IPPROTO_SCTP: { + struct sctphdr *sctph = l4_hdr_start; + if ((void *)sctph + sizeof(*sctph) <= data_end) { + l4_info->src_port = __bpf_ntohs(sctph->source); + l4_info->dst_port = __bpf_ntohs(sctph->dest); + } + } break; + case IPPROTO_ICMP: { + struct icmphdr *icmph = l4_hdr_start; + if ((void *)icmph + sizeof(*icmph) <= data_end) { + l4_info->icmp_type = icmph->type; + l4_info->icmp_code = icmph->code; + } + } break; + case IPPROTO_ICMPV6: { + struct icmp6hdr *icmp6h = l4_hdr_start; + if ((void *)icmp6h + sizeof(*icmp6h) <= data_end) { + l4_info->icmp_type = icmp6h->icmp6_type; + l4_info->icmp_code = icmp6h->icmp6_code; } } break; default: break; } +} + +// sets flow fields from IPv4 header information +static inline int fill_iphdr(struct iphdr *ip, void *data_end, flow_id *id, u16 *flags) { + struct l4_info_t l4_info; + void *l4_hdr_start; + + l4_hdr_start = (void *)ip + sizeof(*ip); + if (l4_hdr_start > data_end) { + return DISCARD; + } + __builtin_memset(&l4_info, 0, sizeof(l4_info)); + __builtin_memcpy(id->src_ip, ip4in6, sizeof(ip4in6)); + __builtin_memcpy(id->dst_ip, ip4in6, sizeof(ip4in6)); + __builtin_memcpy(id->src_ip + sizeof(ip4in6), &ip->saddr, sizeof(ip->saddr)); + __builtin_memcpy(id->dst_ip + sizeof(ip4in6), &ip->daddr, sizeof(ip->daddr)); + id->transport_protocol = ip->protocol; + fill_l4info(l4_hdr_start, data_end, ip->protocol, &l4_info); + id->src_port = l4_info.src_port; + id->dst_port = l4_info.dst_port; + id->icmp_type = l4_info.icmp_type; + id->icmp_code = l4_info.icmp_code; + *flags = l4_info.flags; + return SUBMIT; } // sets flow fields from IPv6 header information static inline int fill_ip6hdr(struct ipv6hdr *ip, void *data_end, flow_id *id, u16 *flags) { - if ((void *)ip + sizeof(*ip) > data_end) { + struct l4_info_t l4_info; + void *l4_hdr_start; + + l4_hdr_start = (void *)ip + sizeof(*ip); + if (l4_hdr_start > data_end) { return DISCARD; } - + __builtin_memset(&l4_info, 0, sizeof(l4_info)); __builtin_memcpy(id->src_ip, ip->saddr.in6_u.u6_addr8, 16); __builtin_memcpy(id->dst_ip, ip->daddr.in6_u.u6_addr8, 16); id->transport_protocol = ip->nexthdr; - id->src_port = 0; - id->dst_port = 0; - switch (ip->nexthdr) { - case IPPROTO_TCP: { - struct tcphdr *tcp = (void *)ip + sizeof(*ip); - if ((void *)tcp + sizeof(*tcp) <= data_end) { - id->src_port = __bpf_ntohs(tcp->source); - id->dst_port = __bpf_ntohs(tcp->dest); - set_flags(tcp, flags); - } - } break; - case IPPROTO_UDP: { - struct udphdr *udp = (void *)ip + sizeof(*ip); - if ((void *)udp + sizeof(*udp) <= data_end) { - id->src_port = __bpf_ntohs(udp->source); - id->dst_port = __bpf_ntohs(udp->dest); - } - } break; - default: - break; - } + fill_l4info(l4_hdr_start, data_end, ip->nexthdr, &l4_info); + id->src_port = l4_info.src_port; + id->dst_port = l4_info.dst_port; + id->icmp_type = l4_info.icmp_type; + id->icmp_code = l4_info.icmp_code; + *flags = l4_info.flags; + return SUBMIT; } // sets flow fields from Ethernet header information @@ -207,6 +255,7 @@ static inline int flow_monitor(struct __sk_buff *skb, u8 direction) { void *data = (void *)(long)skb->data; flow_id id; + __builtin_memset(&id, 0, sizeof(id)); u64 current_time = bpf_ktime_get_ns(); struct ethhdr *eth = data; u16 flags = 0; diff --git a/examples/flowlogs-dump/server/flowlogs-dump-collector.go b/examples/flowlogs-dump/server/flowlogs-dump-collector.go index 3d2c8ab96..2728e0b3b 100644 --- a/examples/flowlogs-dump/server/flowlogs-dump-collector.go +++ b/examples/flowlogs-dump/server/flowlogs-dump-collector.go @@ -72,7 +72,7 @@ func main() { for records := range receivedRecords { for _, record := range records.Entries { if record.EthProtocol == ipv6 { - log.Printf("%s: %v %s IP %s:%d > %s:%d: protocol:%s dir:%d bytes:%d packets:%d flags:%d ends: %v\n", + log.Printf("%s: %v %s IP %s:%d > %s:%d: protocol:%s type: %d code: %d dir:%d bytes:%d packets:%d flags:%d ends: %v\n", ipProto[record.EthProtocol], record.TimeFlowStart.AsTime().Local().Format("15:04:05.000000"), record.Interface, @@ -81,6 +81,8 @@ func main() { net.IP(record.Network.GetDstAddr().GetIpv6()).To16(), record.Transport.DstPort, protocolByNumber[record.Transport.Protocol], + record.Icmp.IcmpType, + record.Icmp.IcmpCode, record.Direction, record.Bytes, record.Packets, @@ -88,7 +90,7 @@ func main() { record.TimeFlowEnd.AsTime().Local().Format("15:04:05.000000"), ) } else { - log.Printf("%s: %v %s IP %s:%d > %s:%d: protocol:%s dir:%d bytes:%d packets:%d flags:%d ends: %v\n", + log.Printf("%s: %v %s IP %s:%d > %s:%d: protocol:%s type: %d code: %d dir:%d bytes:%d packets:%d flags:%d ends: %v\n", ipProto[record.EthProtocol], record.TimeFlowStart.AsTime().Local().Format("15:04:05.000000"), record.Interface, @@ -97,6 +99,8 @@ func main() { ipIntToNetIP(record.Network.GetDstAddr().GetIpv4()).String(), record.Transport.DstPort, protocolByNumber[record.Transport.Protocol], + record.Icmp.IcmpType, + record.Icmp.IcmpCode, record.Direction, record.Bytes, record.Packets, diff --git a/pkg/ebpf/bpf_bpfeb.go b/pkg/ebpf/bpf_bpfeb.go index c228fd42e..4eb412d70 100644 --- a/pkg/ebpf/bpf_bpfeb.go +++ b/pkg/ebpf/bpf_bpfeb.go @@ -25,6 +25,8 @@ type BpfFlowIdT struct { SrcPort uint16 DstPort uint16 TransportProtocol uint8 + IcmpType uint8 + IcmpCode uint8 IfIndex uint32 } diff --git a/pkg/ebpf/bpf_bpfeb.o b/pkg/ebpf/bpf_bpfeb.o index a758051fb..047164e04 100644 Binary files a/pkg/ebpf/bpf_bpfeb.o and b/pkg/ebpf/bpf_bpfeb.o differ diff --git a/pkg/ebpf/bpf_bpfel.go b/pkg/ebpf/bpf_bpfel.go index 6ada0f674..4de7b8d26 100644 --- a/pkg/ebpf/bpf_bpfel.go +++ b/pkg/ebpf/bpf_bpfel.go @@ -25,6 +25,8 @@ type BpfFlowIdT struct { SrcPort uint16 DstPort uint16 TransportProtocol uint8 + IcmpType uint8 + IcmpCode uint8 IfIndex uint32 } diff --git a/pkg/ebpf/bpf_bpfel.o b/pkg/ebpf/bpf_bpfel.o index 13db62889..b33fe54ec 100644 Binary files a/pkg/ebpf/bpf_bpfel.o and b/pkg/ebpf/bpf_bpfel.o differ diff --git a/pkg/ebpf/tracer.go b/pkg/ebpf/tracer.go index e93fec387..32b2641ba 100644 --- a/pkg/ebpf/tracer.go +++ b/pkg/ebpf/tracer.go @@ -6,6 +6,7 @@ import ( "io/fs" "strings" + "github.com/cilium/ebpf" "github.com/cilium/ebpf/ringbuf" "github.com/cilium/ebpf/rlimit" "github.com/netobserv/netobserv-ebpf-agent/pkg/ifaces" @@ -72,6 +73,12 @@ func NewFlowFetcher( return nil, fmt.Errorf("rewriting BPF constants definition: %w", err) } if err := spec.LoadAndAssign(&objects, nil); err != nil { + var ve *ebpf.VerifierError + if errors.As(err, &ve) { + // Using %+v will print the whole verifier error, not just the last + // few lines. + log.Infof("Verifier error: %+v", ve) + } return nil, fmt.Errorf("loading and assigning BPF objects: %w", err) } diff --git a/pkg/exporter/ipfix.go b/pkg/exporter/ipfix.go index 8b88ab206..67f18adce 100644 --- a/pkg/exporter/ipfix.go +++ b/pkg/exporter/ipfix.go @@ -122,6 +122,14 @@ func SendTemplateRecordv4(log *logrus.Entry, exporter *ipfixExporter.ExportingPr if err != nil { return 0, nil, err } + err = addElementToTemplate(log, "icmpTypeIPv4", nil, &elements) + if err != nil { + return 0, nil, err + } + err = addElementToTemplate(log, "icmpCodeIPv4", nil, &elements) + if err != nil { + return 0, nil, err + } err = AddRecordValuesToTemplate(log, &elements) if err != nil { return 0, nil, err @@ -183,6 +191,14 @@ func SendTemplateRecordv6(log *logrus.Entry, exporter *ipfixExporter.ExportingPr if err != nil { return 0, nil, err } + err = addElementToTemplate(log, "icmpTypeIPv6", nil, &elements) + if err != nil { + return 0, nil, err + } + err = addElementToTemplate(log, "icmpCodeIPv6", nil, &elements) + if err != nil { + return 0, nil, err + } err = AddRecordValuesToTemplate(log, &elements) if err != nil { return 0, nil, err @@ -299,6 +315,10 @@ func setIEValue(record *flow.Record, ieValPtr *entities.InfoElementWithValue) { ieVal.SetUnsigned16Value(record.Id.SrcPort) case "destinationTransportPort": ieVal.SetUnsigned16Value(record.Id.DstPort) + case "icmpTypeIPv4", "icmpTypeIPv6": + ieVal.SetUnsigned8Value(record.Id.IcmpType) + case "icmpCodeIPv4", "icmpCodeIPv6": + ieVal.SetUnsigned8Value(record.Id.IcmpCode) } } func setEntities(record *flow.Record, elements *[]entities.InfoElementWithValue) { diff --git a/pkg/exporter/kafka_proto_test.go b/pkg/exporter/kafka_proto_test.go index 5d7f94a68..884bd73ce 100644 --- a/pkg/exporter/kafka_proto_test.go +++ b/pkg/exporter/kafka_proto_test.go @@ -34,6 +34,7 @@ func TestProtoConversion(t *testing.T) { record.Id.DstIp = IPAddrFromNetIP(net.ParseIP("127.3.2.1")) record.Id.SrcPort = 4321 record.Id.DstPort = 1234 + record.Id.IcmpType = 8 record.Id.TransportProtocol = 210 record.TimeFlowStart = time.Now().Add(-5 * time.Second) record.TimeFlowEnd = time.Now() @@ -58,6 +59,7 @@ func TestProtoConversion(t *testing.T) { assert.EqualValues(t, 4321, r.Transport.SrcPort) assert.EqualValues(t, 1234, r.Transport.DstPort) assert.EqualValues(t, 210, r.Transport.Protocol) + assert.EqualValues(t, 8, r.Icmp.IcmpType) assert.Equal(t, record.TimeFlowStart.UnixMilli(), r.TimeFlowStart.AsTime().UnixMilli()) assert.Equal(t, record.TimeFlowEnd.UnixMilli(), r.TimeFlowEnd.AsTime().UnixMilli()) assert.EqualValues(t, 789, r.Bytes) diff --git a/pkg/exporter/proto.go b/pkg/exporter/proto.go index 991863b88..94f9bcea0 100644 --- a/pkg/exporter/proto.go +++ b/pkg/exporter/proto.go @@ -54,6 +54,10 @@ func v4FlowToPB(fr *flow.Record) *pbflow.Record { SrcPort: uint32(fr.Id.SrcPort), DstPort: uint32(fr.Id.DstPort), }, + Icmp: &pbflow.Icmp{ + IcmpType: uint32(fr.Id.IcmpType), + IcmpCode: uint32(fr.Id.IcmpCode), + }, Bytes: fr.Metrics.Bytes, TimeFlowStart: ×tamppb.Timestamp{ Seconds: fr.TimeFlowStart.Unix(), @@ -88,6 +92,10 @@ func v6FlowToPB(fr *flow.Record) *pbflow.Record { SrcPort: uint32(fr.Id.SrcPort), DstPort: uint32(fr.Id.DstPort), }, + Icmp: &pbflow.Icmp{ + IcmpType: uint32(fr.Id.IcmpType), + IcmpCode: uint32(fr.Id.IcmpCode), + }, Bytes: fr.Metrics.Bytes, TimeFlowStart: ×tamppb.Timestamp{ Seconds: fr.TimeFlowStart.Unix(), diff --git a/pkg/flow/record_test.go b/pkg/flow/record_test.go index dfbf8bf19..8f1fc59b0 100644 --- a/pkg/flow/record_test.go +++ b/pkg/flow/record_test.go @@ -23,6 +23,8 @@ func TestRecordBinaryEncoding(t *testing.T) { 0x0e, 0x0f, // transport: u16 src_port 0x10, 0x11, // transport: u16 dst_port 0x12, // transport: u8 transport_protocol + 0x00, // icmp: u8 icmp_type + 0x00, // icmp: u8 icmp_code 0x13, 0x14, 0x15, 0x16, // interface index 0x06, 0x07, 0x08, 0x09, // u32 packets 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, // u64 bytes @@ -45,6 +47,8 @@ func TestRecordBinaryEncoding(t *testing.T) { SrcPort: 0x0f0e, DstPort: 0x1110, TransportProtocol: 0x12, + IcmpType: 0x00, + IcmpCode: 0x00, IfIndex: 0x16151413, }, Metrics: ebpf.BpfFlowMetrics{ diff --git a/pkg/grpc/grpc_test.go b/pkg/grpc/grpc_test.go index faeb740e7..efdd355bf 100644 --- a/pkg/grpc/grpc_test.go +++ b/pkg/grpc/grpc_test.go @@ -162,6 +162,10 @@ func BenchmarkIPv4GRPCCommunication(b *testing.B) { SrcPort: 23000, DstPort: 443, }, + Icmp: &pbflow.Icmp{ + IcmpType: 8, + IcmpCode: 10, + }, } records := &pbflow.Records{} for i := 0; i < 100; i++ { @@ -211,6 +215,10 @@ func BenchmarkIPv6GRPCCommunication(b *testing.B) { SrcPort: 23000, DstPort: 443, }, + Icmp: &pbflow.Icmp{ + IcmpType: 8, + IcmpCode: 10, + }, } records := &pbflow.Records{} for i := 0; i < 100; i++ { diff --git a/pkg/pbflow/flow.pb.go b/pkg/pbflow/flow.pb.go index 903e6f68e..af4bee082 100644 --- a/pkg/pbflow/flow.pb.go +++ b/pkg/pbflow/flow.pb.go @@ -179,6 +179,7 @@ type Record struct { // Agent IP address to help identifying the source of the flow AgentIp *IP `protobuf:"bytes,12,opt,name=agent_ip,json=agentIp,proto3" json:"agent_ip,omitempty"` Flags uint32 `protobuf:"varint,13,opt,name=flags,proto3" json:"flags,omitempty"` + Icmp *Icmp `protobuf:"bytes,14,opt,name=icmp,proto3" json:"icmp,omitempty"` } func (x *Record) Reset() { @@ -304,6 +305,13 @@ func (x *Record) GetFlags() uint32 { return 0 } +func (x *Record) GetIcmp() *Icmp { + if x != nil { + return x.Icmp + } + return nil +} + type DataLink struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -559,6 +567,61 @@ func (x *Transport) GetProtocol() uint32 { return 0 } +type Icmp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IcmpType uint32 `protobuf:"varint,1,opt,name=icmp_type,json=icmpType,proto3" json:"icmp_type,omitempty"` + IcmpCode uint32 `protobuf:"varint,2,opt,name=icmp_code,json=icmpCode,proto3" json:"icmp_code,omitempty"` +} + +func (x *Icmp) Reset() { + *x = Icmp{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_flow_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Icmp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Icmp) ProtoMessage() {} + +func (x *Icmp) ProtoReflect() protoreflect.Message { + mi := &file_proto_flow_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Icmp.ProtoReflect.Descriptor instead. +func (*Icmp) Descriptor() ([]byte, []int) { + return file_proto_flow_proto_rawDescGZIP(), []int{7} +} + +func (x *Icmp) GetIcmpType() uint32 { + if x != nil { + return x.IcmpType + } + return 0 +} + +func (x *Icmp) GetIcmpCode() uint32 { + if x != nil { + return x.IcmpCode + } + return 0 +} + var File_proto_flow_proto protoreflect.FileDescriptor var file_proto_flow_proto_rawDesc = []byte{ @@ -570,7 +633,7 @@ var file_proto_flow_proto_rawDesc = []byte{ 0x07, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x22, 0x94, 0x04, 0x0a, 0x06, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, + 0x65, 0x73, 0x22, 0xb6, 0x04, 0x0a, 0x06, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x65, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x2f, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, @@ -603,34 +666,40 @@ var file_proto_flow_proto_rawDesc = []byte{ 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3c, 0x0a, 0x08, 0x44, 0x61, 0x74, - 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x5f, 0x6d, 0x61, 0x63, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x73, 0x72, 0x63, 0x4d, 0x61, 0x63, 0x12, 0x17, - 0x0a, 0x07, 0x64, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x06, 0x64, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x22, 0x57, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x12, 0x25, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, - 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x12, 0x25, 0x0a, 0x08, 0x64, 0x73, 0x74, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, - 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, - 0x22, 0x3d, 0x0a, 0x02, 0x49, 0x50, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x07, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x14, 0x0a, 0x04, - 0x69, 0x70, 0x76, 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, - 0x76, 0x36, 0x42, 0x0b, 0x0a, 0x09, 0x69, 0x70, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, - 0x5d, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, - 0x73, 0x72, 0x63, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, - 0x73, 0x72, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x70, - 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x64, 0x73, 0x74, 0x50, 0x6f, - 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2a, 0x24, - 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x49, - 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x47, 0x52, 0x45, - 0x53, 0x53, 0x10, 0x01, 0x32, 0x3e, 0x0a, 0x09, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x12, 0x31, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x0f, 0x2e, 0x70, 0x62, 0x66, 0x6c, - 0x6f, 0x77, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x1a, 0x16, 0x2e, 0x70, 0x62, 0x66, - 0x6c, 0x6f, 0x77, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x20, 0x0a, 0x04, 0x69, 0x63, 0x6d, + 0x70, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, + 0x2e, 0x49, 0x63, 0x6d, 0x70, 0x52, 0x04, 0x69, 0x63, 0x6d, 0x70, 0x22, 0x3c, 0x0a, 0x08, 0x44, + 0x61, 0x74, 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x5f, 0x6d, + 0x61, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x73, 0x72, 0x63, 0x4d, 0x61, 0x63, + 0x12, 0x17, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x06, 0x64, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x22, 0x57, 0x0a, 0x07, 0x4e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x25, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, + 0x49, 0x50, 0x52, 0x07, 0x73, 0x72, 0x63, 0x41, 0x64, 0x64, 0x72, 0x12, 0x25, 0x0a, 0x08, 0x64, + 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, + 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x50, 0x52, 0x07, 0x64, 0x73, 0x74, 0x41, 0x64, + 0x64, 0x72, 0x22, 0x3d, 0x0a, 0x02, 0x49, 0x50, 0x12, 0x14, 0x0a, 0x04, 0x69, 0x70, 0x76, 0x34, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x07, 0x48, 0x00, 0x52, 0x04, 0x69, 0x70, 0x76, 0x34, 0x12, 0x14, + 0x0a, 0x04, 0x69, 0x70, 0x76, 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x04, + 0x69, 0x70, 0x76, 0x36, 0x42, 0x0b, 0x0a, 0x09, 0x69, 0x70, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, + 0x79, 0x22, 0x5d, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x19, + 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, + 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x64, 0x73, 0x74, + 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x22, 0x40, 0x0a, 0x04, 0x49, 0x63, 0x6d, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x63, 0x6d, 0x70, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x69, 0x63, 0x6d, + 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x63, 0x6d, 0x70, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x69, 0x63, 0x6d, 0x70, 0x43, 0x6f, + 0x64, 0x65, 0x2a, 0x24, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, + 0x45, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x01, 0x32, 0x3e, 0x0a, 0x09, 0x43, 0x6f, 0x6c, 0x6c, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x31, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x0f, 0x2e, + 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x1a, 0x16, + 0x2e, 0x70, 0x62, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x62, + 0x66, 0x6c, 0x6f, 0x77, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -646,7 +715,7 @@ func file_proto_flow_proto_rawDescGZIP() []byte { } var file_proto_flow_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_flow_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_proto_flow_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_proto_flow_proto_goTypes = []interface{}{ (Direction)(0), // 0: pbflow.Direction (*CollectorReply)(nil), // 1: pbflow.CollectorReply @@ -656,26 +725,28 @@ var file_proto_flow_proto_goTypes = []interface{}{ (*Network)(nil), // 5: pbflow.Network (*IP)(nil), // 6: pbflow.IP (*Transport)(nil), // 7: pbflow.Transport - (*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp + (*Icmp)(nil), // 8: pbflow.Icmp + (*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp } var file_proto_flow_proto_depIdxs = []int32{ 3, // 0: pbflow.Records.entries:type_name -> pbflow.Record 0, // 1: pbflow.Record.direction:type_name -> pbflow.Direction - 8, // 2: pbflow.Record.time_flow_start:type_name -> google.protobuf.Timestamp - 8, // 3: pbflow.Record.time_flow_end:type_name -> google.protobuf.Timestamp + 9, // 2: pbflow.Record.time_flow_start:type_name -> google.protobuf.Timestamp + 9, // 3: pbflow.Record.time_flow_end:type_name -> google.protobuf.Timestamp 4, // 4: pbflow.Record.data_link:type_name -> pbflow.DataLink 5, // 5: pbflow.Record.network:type_name -> pbflow.Network 7, // 6: pbflow.Record.transport:type_name -> pbflow.Transport 6, // 7: pbflow.Record.agent_ip:type_name -> pbflow.IP - 6, // 8: pbflow.Network.src_addr:type_name -> pbflow.IP - 6, // 9: pbflow.Network.dst_addr:type_name -> pbflow.IP - 2, // 10: pbflow.Collector.Send:input_type -> pbflow.Records - 1, // 11: pbflow.Collector.Send:output_type -> pbflow.CollectorReply - 11, // [11:12] is the sub-list for method output_type - 10, // [10:11] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name + 8, // 8: pbflow.Record.icmp:type_name -> pbflow.Icmp + 6, // 9: pbflow.Network.src_addr:type_name -> pbflow.IP + 6, // 10: pbflow.Network.dst_addr:type_name -> pbflow.IP + 2, // 11: pbflow.Collector.Send:input_type -> pbflow.Records + 1, // 12: pbflow.Collector.Send:output_type -> pbflow.CollectorReply + 12, // [12:13] is the sub-list for method output_type + 11, // [11:12] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_proto_flow_proto_init() } @@ -768,6 +839,18 @@ func file_proto_flow_proto_init() { return nil } } + file_proto_flow_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Icmp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_proto_flow_proto_msgTypes[5].OneofWrappers = []interface{}{ (*IP_Ipv4)(nil), @@ -779,7 +862,7 @@ func file_proto_flow_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_flow_proto_rawDesc, NumEnums: 1, - NumMessages: 7, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/flow.proto b/proto/flow.proto index 9e291f729..c7b459a1d 100644 --- a/proto/flow.proto +++ b/proto/flow.proto @@ -41,6 +41,7 @@ message Record { // Agent IP address to help identifying the source of the flow IP agent_ip = 12; uint32 flags = 13; + Icmp icmp = 14; } message DataLink { @@ -68,6 +69,11 @@ message Transport { uint32 protocol = 3; } +message Icmp { + uint32 icmp_type = 1; + uint32 icmp_code = 2; +} + // as defined by field 61 in // https://www.iana.org/assignments/ipfix/ipfix.xhtml enum Direction {