// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Hubble

syntax = "proto3";

import "google/protobuf/any.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.proto";

package flow;

option go_package = "github.com/cilium/cilium/api/v1/flow";

message Flow {
    google.protobuf.Timestamp time = 1;

    // uuid is a universally unique identifier for this flow.
    string uuid = 34;

    // emitter identifies the source that emitted the flow.
    Emitter emitter = 41;

    Verdict verdict = 2;
    // only applicable to Verdict = DROPPED.
    // deprecated in favor of drop_reason_desc.
    uint32 drop_reason = 3 [deprecated=true];

    // auth_type is the authentication type specified for the flow in Cilium Network Policy.
    // Only set on policy verdict events.
    AuthType auth_type = 35;

    // l2
    Ethernet ethernet = 4;
    // l3
    IP IP = 5;
    // l4
    Layer4 l4 = 6;

    Tunnel tunnel = 39;

    reserved 7; // removed, do not use

    Endpoint source = 8;
    Endpoint destination = 9;

    FlowType Type = 10;

    // NodeName is the name of the node from which this Flow was captured.
    string node_name = 11;
    // node labels in `foo=bar` format.
    repeated string node_labels = 37;

    reserved 12; // removed, do not use

    // all names the source IP can have.
    repeated string source_names = 13;
    // all names the destination IP can have.
    repeated string destination_names = 14;

    // L7 information. This field is set if and only if FlowType is L7.
    Layer7 l7 = 15;

    // Deprecated. This suffers from false negatives due to protobuf not being
    // able to distinguish between the value being false or it being absent.
    // Please use is_reply instead.
    bool reply = 16 [deprecated=true];

    reserved 17, 18; // removed, do not use

    // EventType of the originating Cilium event
    CiliumEventType event_type = 19;

    // source_service contains the service name of the source
    Service source_service = 20;
    // destination_service contains the service name of the destination
    Service destination_service = 21;

    // traffic_direction of the connection, e.g. ingress or egress
    TrafficDirection traffic_direction = 22;

    // policy_match_type is only applicable to the cilium event type PolicyVerdict
    // https://github.com/cilium/cilium/blob/e831859b5cc336c6d964a6d35bbd34d1840e21b9/pkg/monitor/datapath_policy.go#L50
    uint32 policy_match_type = 23;

    // Only applicable to cilium trace notifications, blank for other types.
    TraceObservationPoint trace_observation_point = 24;
    // Cilium datapath trace reason info.
    TraceReason trace_reason = 36;
    // Cilium datapath filename and line number. Currently only applicable when
    // Verdict = DROPPED.
    FileInfo file = 38;

    // IPTraceID relates to the trace ID in the IP options of a packet.
    IPTraceID ip_trace_id = 40;

    // only applicable to Verdict = DROPPED.
    DropReason drop_reason_desc = 25;

    // is_reply indicates that this was a packet (L4) or message (L7) in the
    // reply direction. May be absent (in which case it is unknown whether it
    // is a reply or not).
    google.protobuf.BoolValue is_reply = 26;

    // Only applicable to cilium debug capture events, blank for other types
    DebugCapturePoint debug_capture_point = 27;

    // interface is the network interface on which this flow was observed
    NetworkInterface interface = 28;

    // proxy_port indicates the port of the proxy to which the flow was forwarded
    uint32 proxy_port = 29;

    // trace_context contains information about a trace related to the flow, if
    // any.
    TraceContext trace_context = 30;

    // sock_xlate_point is the socket translation point.
    // Only applicable to TraceSock notifications, blank for other types
    SocketTranslationPoint sock_xlate_point = 31;

    // socket_cookie is the Linux kernel socket cookie for this flow.
    // Only applicable to TraceSock notifications, zero for other types
    uint64 socket_cookie = 32;

    // cgroup_id of the process which emitted this event.
    // Only applicable to TraceSock notifications, zero for other types
    uint64 cgroup_id = 33;

    // This is a temporary workaround to support summary field for pb.Flow without
    // duplicating logic from the old parser. This field will be removed once we
    // fully migrate to the new parser.
    string Summary = 100000 [deprecated=true];

    // extensions can be used to add arbitrary additional metadata to flows.
    // This can be used to extend functionality for other Hubble compatible
    // APIs, or experiment with new functionality without needing to change the public API.
    google.protobuf.Any extensions = 150000;

    // The CiliumNetworkPolicies allowing the egress of the flow.
    repeated Policy egress_allowed_by = 21001;
    // The CiliumNetworkPolicies allowing the ingress of the flow.
    repeated Policy ingress_allowed_by = 21002;

    // The CiliumNetworkPolicies denying the egress of the flow.
    repeated Policy egress_denied_by = 21004;
    // The CiliumNetworkPolicies denying the ingress of the flow.
    repeated Policy ingress_denied_by = 21005;

    // The set of Log values for policies that matched this flow.
    // If no matched policies have an explicit log value configured,
    // this list is empty. Duplicate values are elided; each
    // entry is unique.
    repeated string policy_log = 21006;

    // Aggregate contains flow aggregation counters when flow aggregation is enabled.
    // This field is only populated for aggregated flows.
    Aggregate aggregate = 21007;
}

// Emitter identifies the source that emits a Hubble flow.
message Emitter {
    // name identifies the emitter.
    // The name should be capitalized ("Hubble", not "hubble" nor "HUBBLE").
    string name = 1;
    // version identifiers the emitter version.
    // The version should not contain a 'v' prefix as sometimes seen ("1.19.0",
    // not "v1.19.0").
    string version = 2;
}

enum FlowType {
    UNKNOWN_TYPE = 0;
    L3_L4 = 1; // not sure about the underscore here, but `L34` also reads strange
    L7 = 2;
    SOCK = 3;
}

// These types correspond to definitions in pkg/policy/l4.go.
enum AuthType {
    DISABLED = 0;
    SPIRE = 1;
    TEST_ALWAYS_FAIL = 2;
}

enum TraceObservationPoint {
    // Cilium treats 0 as TO_LXC, but its's something we should work to remove.
    // This is intentionally set as unknown, so proto API can guarantee the
    // observation point is always going to be present on trace events.
    UNKNOWN_POINT = 0;

    // TO_PROXY indicates network packets are transmitted towards the l7 proxy.
    TO_PROXY = 1;
    // TO_HOST indicates network packets are transmitted towards the host
    // namespace.
    TO_HOST = 2;
    // TO_STACK indicates network packets are transmitted towards the Linux
    // kernel network stack on host machine.
    TO_STACK = 3;
    // TO_OVERLAY indicates network packets are transmitted towards the tunnel
    // device.
    TO_OVERLAY = 4;
    // TO_ENDPOINT indicates network packets are transmitted towards endpoints
    // (containers).
    TO_ENDPOINT = 101;
    // FROM_ENDPOINT indicates network packets were received from endpoints
    // (containers).
    FROM_ENDPOINT = 5;
    // FROM_PROXY indicates network packets were received from the l7 proxy.
    FROM_PROXY = 6;
    // FROM_HOST indicates network packets were received from the host
    // namespace.
    FROM_HOST = 7;
    // FROM_STACK indicates network packets were received from the Linux kernel
    // network stack on host machine.
    FROM_STACK = 8;
    // FROM_OVERLAY indicates network packets were received from the tunnel
    // device.
    FROM_OVERLAY = 9;
    // FROM_NETWORK indicates network packets were received from native
    // devices.
    FROM_NETWORK = 10;
    // TO_NETWORK indicates network packets are transmitted towards native
    // devices.
    TO_NETWORK = 11;
    // FROM_CRYPTO indicates network packets were received from the crypto
    // process for decryption.
    FROM_CRYPTO = 12;
    // TO_CRYPTO indicates network packets are transmitted towards the crypto
    // process for encryption.
    TO_CRYPTO = 13;

}

enum TraceReason {
    TRACE_REASON_UNKNOWN = 0;
    NEW = 1;
    ESTABLISHED = 2;
    REPLY = 3;
    RELATED = 4;
    REOPENED = 5 [deprecated=true];
    SRV6_ENCAP = 6;
    SRV6_DECAP = 7;
    ENCRYPT_OVERLAY = 8 [deprecated=true];
}

message FileInfo {
    string name = 1;
    uint32 line = 2;
}

message Layer4 {
    oneof protocol {
        TCP TCP = 1;
        UDP UDP = 2;
        // ICMP is technically not L4, but mutually exclusive with the above
        ICMPv4 ICMPv4 = 3;
        ICMPv6 ICMPv6 = 4;
        SCTP SCTP = 5;
        VRRP VRRP = 6;
        IGMP IGMP = 7;
    }
}

// This enum corresponds to Cilium's L7 accesslog [FlowType](https://github.com/cilium/cilium/blob/728c79e427438ab6f8d9375b62fccd6fed4ace3a/pkg/proxy/accesslog/record.go#L26):
enum L7FlowType {
    UNKNOWN_L7_TYPE = 0;
    REQUEST = 1;
    RESPONSE = 2;
    SAMPLE = 3;
}

// Message for L7 flow, which roughly corresponds to Cilium's accesslog [LogRecord](https://github.com/cilium/cilium/blob/728c79e427438ab6f8d9375b62fccd6fed4ace3a/pkg/proxy/accesslog/record.go#L141):
message Layer7 {
    L7FlowType type = 1;
    // Latency of the response
    uint64 latency_ns = 2;
    // L7 field. This field is set if and only if FlowType is L7.
    oneof record {
        DNS dns = 100;
        HTTP http = 101;
        Kafka kafka = 102 [deprecated = true];
    }
}

// TraceContext contains trace context propagation data, i.e. information about a
// distributed trace.
// For more information about trace context, check the [W3C Trace Context specification](https://www.w3.org/TR/trace-context/).
message TraceContext {
    // parent identifies the incoming request in a tracing system.
    TraceParent parent = 1;
}

// TraceParent identifies the incoming request in a tracing system.
message TraceParent {
    // trace_id is a unique value that identifies a trace. It is a byte array
    // represented as a hex string.
    string trace_id = 1;
}

message Endpoint {
    uint32 ID = 1;
    uint32 identity = 2;
    string cluster_name = 7;
    string namespace = 3;
    // labels in `foo=bar` format.
    repeated string labels = 4;
    string pod_name = 5;
    repeated Workload workloads = 6;
}

message Workload {
    string name = 1;
    string kind = 2;
}

message TCP {
    uint32 source_port = 1;
    uint32 destination_port = 2;
    TCPFlags flags = 3;
}

message IP {
    string source = 1;
    // source_xlated is the post-translation source IP when the flow was
    // SNATed. When "source_xlated" is set, the "source" field is populated
    // with the pre-translation source IP address.
    string source_xlated = 5;
    string destination = 2;
    IPVersion ipVersion = 3;
    // This field indicates whether the TraceReasonEncryptMask is set or not.
    // https://github.com/cilium/cilium/blob/ba0ed147bd5bb342f67b1794c2ad13c6e99d5236/pkg/monitor/datapath_trace.go#L27
    bool encrypted = 4;
}

message Ethernet {
    string source = 1;
    string destination = 2;
}

message TCPFlags {
    bool FIN = 1;
    bool SYN = 2;
    bool RST = 3;
    bool PSH = 4;
    bool ACK = 5;
    bool URG = 6;
    bool ECE = 7;
    bool CWR = 8;
    bool NS = 9;
}

message UDP {
    uint32 source_port = 1;
    uint32 destination_port = 2;
}

message SCTP {
    uint32 source_port = 1;
    uint32 destination_port = 2;
}

message ICMPv4 {
    uint32 type = 1;
    uint32 code = 2;
}

message ICMPv6 {
    uint32 type = 1;
    uint32 code = 2;
}

message VRRP {
    uint32 type = 1;
    uint32 vrid = 2;
    uint32 priority = 3;
}

message IGMP {
    uint32 type = 1;
    string group_address = 2;
}

enum IPVersion {
    IP_NOT_USED = 0;
    IPv4 = 1;
    IPv6 = 2;
}

message Tunnel {
    enum Protocol {
        UNKNOWN = 0;
        VXLAN = 1;
        GENEVE = 2;
    }

    Protocol protocol = 1;
    IP IP = 2;
    Layer4 l4 = 3;
    uint32 vni = 4;
}

enum Verdict {
    // UNKNOWN is used if there is no verdict for this flow event
    VERDICT_UNKNOWN = 0;
    // FORWARDED is used for flow events where the trace point has forwarded
    // this packet or connection to the next processing entity.
    FORWARDED = 1;
    // DROPPED is used for flow events where the connection or packet has
    // been dropped (e.g. due to a malformed packet, it being rejected by a
    // network policy etc). The exact drop reason may be found in drop_reason_desc.
    DROPPED = 2;
    // ERROR is used for flow events where an error occurred during processing
    ERROR = 3;
    // AUDIT is used on policy verdict events in policy audit mode, to
    // denominate flows that would have been dropped by policy if audit mode
    // was turned off
    AUDIT = 4;
    // REDIRECTED is used for flow events which have been redirected to the proxy
    REDIRECTED = 5;
    // TRACED is used for flow events which have been observed at a trace point,
    // but no particular verdict has been reached yet
    TRACED = 6;
    // TRANSLATED is used for flow events where an address has been translated
    TRANSLATED = 7;
}

// These values are shared with pkg/monitor/api/drop.go and bpf/lib/common.h.
// Note that non-drop reasons (i.e. values less than api.DropMin) are not used
// here.
enum DropReason {
    // non-drop reasons
    DROP_REASON_UNKNOWN = 0;
    // drop reasons
    INVALID_SOURCE_MAC = 130 [deprecated = true];
    INVALID_DESTINATION_MAC = 131 [deprecated = true];
    INVALID_SOURCE_IP = 132;
    POLICY_DENIED = 133;
    INVALID_PACKET_DROPPED = 134;
    CT_TRUNCATED_OR_INVALID_HEADER = 135;
    CT_MISSING_TCP_ACK_FLAG = 136;
    CT_UNKNOWN_L4_PROTOCOL = 137;
    CT_CANNOT_CREATE_ENTRY_FROM_PACKET = 138 [deprecated = true];
    UNSUPPORTED_L3_PROTOCOL = 139;
    MISSED_TAIL_CALL = 140;
    ERROR_WRITING_TO_PACKET = 141;
    UNKNOWN_L4_PROTOCOL = 142;
    UNKNOWN_ICMPV4_CODE = 143;
    UNKNOWN_ICMPV4_TYPE = 144;
    UNKNOWN_ICMPV6_CODE = 145;
    UNKNOWN_ICMPV6_TYPE = 146;
    ERROR_RETRIEVING_TUNNEL_KEY = 147;
    ERROR_RETRIEVING_TUNNEL_OPTIONS = 148 [deprecated = true];
    INVALID_GENEVE_OPTION = 149 [deprecated = true];
    UNKNOWN_L3_TARGET_ADDRESS = 150;
    STALE_OR_UNROUTABLE_IP = 151;
    NO_MATCHING_LOCAL_CONTAINER_FOUND = 152 [deprecated = true];
    ERROR_WHILE_CORRECTING_L3_CHECKSUM = 153;
    ERROR_WHILE_CORRECTING_L4_CHECKSUM = 154;
    CT_MAP_INSERTION_FAILED = 155;
    INVALID_IPV6_EXTENSION_HEADER = 156;
    IP_FRAGMENTATION_NOT_SUPPORTED = 157;
    SERVICE_BACKEND_NOT_FOUND = 158;
    NO_TUNNEL_OR_ENCAPSULATION_ENDPOINT = 160;
    FAILED_TO_INSERT_INTO_PROXYMAP = 161;
    REACHED_EDT_RATE_LIMITING_DROP_HORIZON = 162;
    UNKNOWN_CONNECTION_TRACKING_STATE = 163;
    LOCAL_HOST_IS_UNREACHABLE = 164;
    NO_CONFIGURATION_AVAILABLE_TO_PERFORM_POLICY_DECISION = 165;
    UNSUPPORTED_L2_PROTOCOL = 166;
    NO_MAPPING_FOR_NAT_MASQUERADE = 167;
    UNSUPPORTED_PROTOCOL_FOR_NAT_MASQUERADE = 168;
    FIB_LOOKUP_FAILED = 169;
    ENCAPSULATION_TRAFFIC_IS_PROHIBITED = 170;
    INVALID_IDENTITY = 171;
    UNKNOWN_SENDER = 172;
    NAT_NOT_NEEDED = 173;
    IS_A_CLUSTERIP = 174;
    FIRST_LOGICAL_DATAGRAM_FRAGMENT_NOT_FOUND = 175;
    FORBIDDEN_ICMPV6_MESSAGE = 176;
    DENIED_BY_LB_SRC_RANGE_CHECK = 177;
    SOCKET_LOOKUP_FAILED = 178;
    SOCKET_ASSIGN_FAILED = 179;
    PROXY_REDIRECTION_NOT_SUPPORTED_FOR_PROTOCOL = 180;
    POLICY_DENY = 181;
    VLAN_FILTERED = 182;
    INVALID_VNI = 183;
    INVALID_TC_BUFFER = 184;
    NO_SID = 185;
    MISSING_SRV6_STATE = 186 [deprecated = true];
    NAT46 = 187;
    NAT64 = 188;
    AUTH_REQUIRED = 189;
    CT_NO_MAP_FOUND = 190;
    SNAT_NO_MAP_FOUND = 191;
    INVALID_CLUSTER_ID = 192;
    UNSUPPORTED_PROTOCOL_FOR_DSR_ENCAP = 193;
    NO_EGRESS_GATEWAY = 194;
    UNENCRYPTED_TRAFFIC = 195;
    TTL_EXCEEDED = 196;
    NO_NODE_ID = 197;
    DROP_RATE_LIMITED = 198;
    IGMP_HANDLED = 199;
    IGMP_SUBSCRIBED = 200;
    MULTICAST_HANDLED = 201;
    // A BPF program wants to tail call into bpf_host, but the host datapath
    // hasn't been loaded yet.
    DROP_HOST_NOT_READY = 202;
    // A BPF program wants to tail call some endpoint's policy program in
    // cilium_call_policy, but the program is not available.
    DROP_EP_NOT_READY = 203;
    // An Egress Gateway node matched a packet against an Egress Gateway policy
    // that didn't select a valid Egress IP.
    DROP_NO_EGRESS_IP = 204;
    // Punt packet to a user space proxy.
    DROP_PUNT_PROXY = 205;
}

enum TrafficDirection {
    TRAFFIC_DIRECTION_UNKNOWN = 0;
    INGRESS = 1;
    EGRESS = 2;
}

// These values are shared with pkg/monitor/api/datapath_debug.go and bpf/lib/dbg.h.
enum DebugCapturePoint {
    DBG_CAPTURE_POINT_UNKNOWN = 0;
    reserved 1 to 3;
    DBG_CAPTURE_DELIVERY = 4;
    DBG_CAPTURE_FROM_LB = 5;
    DBG_CAPTURE_AFTER_V46 = 6;
    DBG_CAPTURE_AFTER_V64 = 7;
    DBG_CAPTURE_PROXY_PRE = 8;
    DBG_CAPTURE_PROXY_POST = 9;
    DBG_CAPTURE_SNAT_PRE = 10;
    DBG_CAPTURE_SNAT_POST = 11;
}

message Policy {
	string name = 1;
	string namespace = 2;
	repeated string labels = 3;
	uint64 revision = 4;
	string kind = 5;
}

// EventTypeFilter is a filter describing a particular event type.
message EventTypeFilter {
	// type is the primary flow type as defined by:
	// github.com/cilium/cilium/pkg/monitor/api.MessageType*
	int32 type = 1;

	// match_sub_type is set to true when matching on the sub_type should
	// be done. This flag is required as 0 is a valid sub_type.
	bool match_sub_type = 2;

	// sub_type is the secondary type, e.g.
	// - github.com/cilium/cilium/pkg/monitor/api.Trace*
	int32 sub_type = 3;
}

// CiliumEventType from which the flow originated.
message CiliumEventType {
    // type of event the flow originated from, i.e.
    // github.com/cilium/cilium/pkg/monitor/api.MessageType*
    int32 type = 1;
    // sub_type may indicate more details depending on type, e.g.
	// - github.com/cilium/cilium/pkg/monitor/api.Trace*
    // - github.com/cilium/cilium/pkg/monitor/api.Drop*
    // - github.com/cilium/cilium/pkg/monitor/api.DbgCapture*
    int32 sub_type = 2;
}

// FlowFilter represent an individual flow filter. All fields are optional. If
// multiple fields are set, then all fields must match for the filter to match.
message FlowFilter {
    // uuid filters by a list of flow uuids.
    repeated string uuid = 29;
    // source_ip filters by a list of source ips. Each of the source ips can be
    // specified as an exact match (e.g. "1.1.1.1") or as a CIDR range (e.g.
    // "1.1.1.0/24").
    repeated string source_ip = 1;
    // source_ip_xlated filters by a list IPs. Each of the IPs can be specified
    // as an exact match (e.g. "1.1.1.1") or as a CIDR range (e.g.
    // "1.1.1.0/24").
    repeated string source_ip_xlated = 34;
    // source_pod filters by a list of source pod name prefixes, optionally
    // within a given namespace (e.g. "xwing", "kube-system/coredns-").
    // The pod name can be omitted to only filter by namespace
    // (e.g. "kube-system/") or the namespace can be omitted to filter for
    // pods in any namespace (e.g. "/xwing")
    repeated string source_pod = 2;
    // source_fqdn filters by a list of source fully qualified domain names
    repeated string source_fqdn = 7;
    // source_labels filters on a list of source label selectors. Selectors
    // support the full Kubernetes label selector syntax.
    repeated string source_label = 10;
    // source_service filters on a list of source service names. This field
    // supports the same syntax as the source_pod field.
    repeated string source_service = 16;
    // source_workload filters by a list of source workload.
    repeated Workload source_workload = 26;
    // source_cluster_name filters by a list of source cluster names.
    repeated string source_cluster_name = 37;

    // destination_ip filters by a list of destination ips. Each of the
    // destination ips can be specified as an exact match (e.g. "1.1.1.1") or
    // as a CIDR range (e.g. "1.1.1.0/24").
    repeated string destination_ip = 3;
    // destination_pod filters by a list of destination pod names
    repeated string destination_pod = 4;
    // destination_fqdn filters by a list of destination fully qualified domain names
    repeated string destination_fqdn = 8;
    // destination_label filters on a list of destination label selectors
    repeated string destination_label = 11;
    // destination_service filters on a list of destination service names
    repeated string destination_service = 17;
    // destination_workload filters by a list of destination workload.
    repeated Workload destination_workload = 27;
    // destination_cluster_name filters by a list of destination cluster names.
    repeated string destination_cluster_name = 38;

    // traffic_direction filters flow by direction of the connection, e.g.
    // ingress or egress.
    repeated TrafficDirection traffic_direction = 30;
    // only return Flows that were classified with a particular verdict.
    repeated Verdict verdict = 5;
    // only applicable to Verdict = DROPPED (e.g. "POLICY_DENIED", "UNSUPPORTED_L3_PROTOCOL")
    repeated DropReason drop_reason_desc = 33;
    // interface is the network interface on which this flow was observed.
    repeated NetworkInterface interface = 35;
    // event_type is the list of event types to filter on
    repeated EventTypeFilter event_type = 6;
    // http_status_code is a list of string prefixes (e.g. "4+", "404", "5+")
    // to filter on the HTTP status code
    repeated string http_status_code = 9;

    // protocol filters flows by L4 or L7 protocol, e.g. (e.g. "tcp", "http")
    repeated string protocol = 12;

    // source_port filters flows by L4 source port
    repeated string source_port = 13;
    // destination_port filters flows by L4 destination port
    repeated string destination_port = 14;
    // reply filters flows based on the direction of the flow.
    repeated bool reply = 15;
    // dns_query filters L7 DNS flows by query patterns (RE2 regex), e.g. 'kube.*local'.
    repeated string dns_query = 18;
    // source_identity filters by the security identity of the source endpoint.
    repeated uint32 source_identity = 19;
    // destination_identity filters by the security identity of the destination endpoint.
    repeated uint32 destination_identity = 20;

    // GET, POST, PUT, etc. methods. This type of field is well suited for an
    // enum but every single existing place is using a string already.
    repeated string http_method = 21;
    // http_path is a list of regular expressions to filter on the HTTP path.
    repeated string http_path = 22;
    // http_url is a list of regular expressions to filter on the HTTP URL.
    repeated string http_url = 31;
    // http_header is a list of key:value pairs to filter on the HTTP headers.
    repeated HTTPHeader http_header = 32;

    // tcp_flags filters flows based on TCP header flags
    repeated TCPFlags tcp_flags = 23;

    // node_name is a list of patterns to filter on the node name, e.g. "k8s*",
    // "test-cluster/*.domain.com", "cluster-name/" etc.
    repeated string node_name = 24;
    // node_labels filters on a list of node label selectors. Selectors support
    // the full Kubernetes label selector syntax.
    repeated string node_labels = 36;

    // filter based on IP version (ipv4 or ipv6)
    repeated IPVersion ip_version = 25;

    // trace_id filters flows by trace ID
    repeated string trace_id = 28;
    // ip_trace_id filters flows by IPTraceID
    repeated uint64 ip_trace_id = 39;

    // encrypted filters flows based on encryption status (WireGuard/IPsec).
    // When set to true, only encrypted flows are returned.
    // When set to false, only unencrypted flows are returned.
    repeated bool encrypted = 40;

    // Experimental contains filters that are not stable yet. Support for
    // experimental features is always optional and subject to change.
    message Experimental {
      // cel_expression takes a common expression language (CEL) expression
      // returning a boolean to determine if the filter matched or not.
      // You can use the `_flow` variable to access fields on the flow using
      // the flow.Flow protobuf field names.
      // See https://github.com/google/cel-spec/blob/v0.14.0/doc/intro.md#introduction
      // for more details on CEL and accessing the protobuf fields in CEL.
      // Using CEL has performance cost compared to other filters, so prefer
      // using non-CEL filters when possible, and try to specify CEL filters
      // last in the list of FlowFilters.
      repeated string cel_expression = 1;
    }
    // experimental contains filters that are not stable yet. Support for
    // experimental features is always optional and subject to change.
    Experimental experimental = 999;
}

// EventType are constants are based on the ones from <linux/perf_event.h>.
enum EventType {
    UNKNOWN = 0;
    // EventSample is equivalent to PERF_RECORD_SAMPLE.
    EventSample = 9;
    // RecordLost is equivalent to PERF_RECORD_LOST.
    RecordLost = 2;
}

// DNS flow. This is basically directly mapped from Cilium's [LogRecordDNS](https://github.com/cilium/cilium/blob/04f3889d627774f79e56d14ddbc165b3169e2d01/pkg/proxy/accesslog/record.go#L264):
message DNS {
    // DNS name that's being looked up: e.g. "isovalent.com."
    string query = 1;
    // List of IP addresses in the DNS response.
    repeated string ips = 2;
    // TTL in the DNS response.
    uint32 ttl = 3;
    // List of CNames in the DNS response.
    repeated string cnames = 4;
    // Corresponds to DNSDataSource defined in:
    //   https://github.com/cilium/cilium/blob/04f3889d627774f79e56d14ddbc165b3169e2d01/pkg/proxy/accesslog/record.go#L253
    string observation_source = 5;
    // Return code of the DNS request defined in:
    //   https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
    uint32 rcode = 6;
    // String representation of qtypes defined in:
    //   https://tools.ietf.org/html/rfc1035#section-3.2.3
    repeated string qtypes = 7;
    // String representation of rrtypes defined in:
    // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4
    repeated string rrtypes = 8;
}

message HTTPHeader {
    string key = 1;
    string value = 2;
}

// L7 information for HTTP flows. It corresponds to Cilium's [accesslog.LogRecordHTTP](https://github.com/cilium/cilium/blob/728c79e427438ab6f8d9375b62fccd6fed4ace3a/pkg/proxy/accesslog/record.go#L206) type.
message HTTP {
    uint32 code = 1;
    string method = 2;
    string url = 3;
    string protocol = 4;
    repeated HTTPHeader headers = 5;
}

// L7 information for Kafka flows. It corresponds to Cilium's [accesslog.LogRecordKafka](https://github.com/cilium/cilium/blob/728c79e427438ab6f8d9375b62fccd6fed4ace3a/pkg/proxy/accesslog/record.go#L229) type.
message Kafka {
    option deprecated = true;
    int32 error_code = 1;
    int32 api_version = 2;
    string api_key = 3;
    int32 correlation_id = 4;
    string topic = 5;
}

message Service {
    string name = 1;
    string namespace = 2;
}

message IPTraceID {
    uint64 trace_id = 1;
    uint32 ip_option_type = 2;
}

enum LostEventSource {
    UNKNOWN_LOST_EVENT_SOURCE = 0;
    // PERF_EVENT_RING_BUFFER indicates that events were dropped in the BPF
    // perf event ring buffer, indicating that userspace agent did not keep up
    // with the events produced by the datapath.
    PERF_EVENT_RING_BUFFER = 1;
    // OBSERVER_EVENTS_QUEUE indicates that events were dropped because the
    // Hubble events queue was full, indicating that the Hubble observer did
    // not keep up.
    OBSERVER_EVENTS_QUEUE = 2;

    // HUBBLE_RING_BUFFER indicates that the event was dropped because it could
    // not be read from Hubble's ring buffer in time before being overwritten.
    HUBBLE_RING_BUFFER = 3;
}

// LostEvent is a message which notifies consumers about a loss of events
// that happened before the events were captured by Hubble.
message LostEvent {
    // source is the location where events got lost.
    LostEventSource source = 1;
    // num_events_lost is the number of events that haven been lost at source.
    uint64 num_events_lost = 2;
    // cpu on which the event was lost if the source of lost events is
    // PERF_EVENT_RING_BUFFER.
    google.protobuf.Int32Value cpu = 3;
    // first is the timestamp of the first event that was lost.
    google.protobuf.Timestamp first = 4;
    // last is the timestamp of the last event that was lost.
    google.protobuf.Timestamp last = 5;
}

// AgentEventType is the type of agent event. These values are shared with type
// AgentNotification in pkg/monitor/api/types.go.
enum AgentEventType {
    AGENT_EVENT_UNKNOWN = 0;
    // used for AGENT_EVENT_GENERIC in monitor API, but there are currently no
    // such events;
    reserved 1;
    AGENT_STARTED = 2;
    POLICY_UPDATED = 3;
    POLICY_DELETED = 4;
    ENDPOINT_REGENERATE_SUCCESS = 5;
    ENDPOINT_REGENERATE_FAILURE = 6;
    ENDPOINT_CREATED = 7;
    ENDPOINT_DELETED = 8;
    IPCACHE_UPSERTED = 9;
    IPCACHE_DELETED = 10;
    SERVICE_UPSERTED = 11 [deprecated = true];
    SERVICE_DELETED = 12 [deprecated = true];
}

message AgentEvent {
    AgentEventType type = 1;
    oneof notification {
        AgentEventUnknown unknown = 100;
        TimeNotification agent_start = 101;
        // used for POLICY_UPDATED and POLICY_DELETED
        PolicyUpdateNotification policy_update = 102;
        // used for ENDPOINT_REGENERATE_SUCCESS and ENDPOINT_REGENERATE_FAILURE
        EndpointRegenNotification endpoint_regenerate = 103;
        // used for ENDPOINT_CREATED and ENDPOINT_DELETED
        EndpointUpdateNotification endpoint_update = 104;
        // used for IPCACHE_UPSERTED and IPCACHE_DELETED
        IPCacheNotification ipcache_update = 105;
        ServiceUpsertNotification service_upsert = 106 [deprecated = true];
        ServiceDeleteNotification service_delete = 107 [deprecated = true];
    }
}

message AgentEventUnknown {
    string type = 1;
    string notification = 2;
}

message TimeNotification {
    google.protobuf.Timestamp time = 1;
}

message PolicyUpdateNotification {
    repeated string labels = 1;
    uint64 revision = 2;
    int64 rule_count = 3;
}

message EndpointRegenNotification {
    uint64 id = 1;
    repeated string labels = 2;
    string error = 3;
}

message EndpointUpdateNotification {
    uint64 id = 1;
    repeated string labels = 2;
    string error = 3;
    string pod_name = 4;
    string namespace = 5;
}

message IPCacheNotification {
    string cidr = 1;
    uint32 identity = 2;
    google.protobuf.UInt32Value old_identity = 3;
    string host_ip = 4;
    string old_host_ip = 5;
    uint32 encrypt_key = 6;
    string namespace = 7;
    string pod_name = 8;
}

message ServiceUpsertNotificationAddr {
    option deprecated = true;

    string ip = 1;
    uint32 port = 2;
}

message ServiceUpsertNotification {
    option deprecated = true;

    uint32 id = 1;
    ServiceUpsertNotificationAddr frontend_address = 2;
    repeated ServiceUpsertNotificationAddr backend_addresses = 3;
    string type = 4;
    string traffic_policy = 5 [deprecated = true];
    string name = 6;
    string namespace = 7;
    string ext_traffic_policy = 8;
    string int_traffic_policy = 9;
}

message ServiceDeleteNotification {
    option deprecated = true;

    uint32 id = 1;
}

message NetworkInterface {
    uint32 index = 1;
    string name = 2;
}

// This mirrors enum xlate_point in bpf/lib/trace_sock.h
enum SocketTranslationPoint {
    SOCK_XLATE_POINT_UNKNOWN = 0;
    SOCK_XLATE_POINT_PRE_DIRECTION_FWD = 1; // Pre service translation
    SOCK_XLATE_POINT_POST_DIRECTION_FWD = 2; // Post service translation
    SOCK_XLATE_POINT_PRE_DIRECTION_REV = 3;   // Pre reverse service translation
    SOCK_XLATE_POINT_POST_DIRECTION_REV = 4; // Post reverse service translation
}

message DebugEvent {
    DebugEventType type = 1;
    Endpoint source = 2;
    google.protobuf.UInt32Value hash = 3;
    google.protobuf.UInt32Value arg1 = 4;
    google.protobuf.UInt32Value arg2 = 5;
    google.protobuf.UInt32Value arg3 = 6;
    string message = 7;
    google.protobuf.Int32Value cpu = 8;
}

// These values are shared with pkg/monitor/api/datapath_debug.go and bpf/lib/dbg.h.
enum DebugEventType {
    DBG_EVENT_UNKNOWN = 0;
    DBG_GENERIC = 1;
    DBG_LOCAL_DELIVERY = 2;
    DBG_ENCAP = 3;
    DBG_LXC_FOUND = 4;
    DBG_POLICY_DENIED = 5;
    DBG_CT_LOOKUP = 6;
    DBG_CT_LOOKUP_REV = 7;
    DBG_CT_MATCH = 8;
    DBG_CT_CREATED = 9;
    DBG_CT_CREATED2 = 10;
    DBG_ICMP6_HANDLE = 11;
    DBG_ICMP6_REQUEST = 12;
    DBG_ICMP6_NS = 13;
    DBG_ICMP6_TIME_EXCEEDED = 14;
    DBG_CT_VERDICT = 15;
    DBG_DECAP = 16;
    DBG_PORT_MAP = 17;
    DBG_ERROR_RET = 18;
    DBG_TO_HOST = 19;
    DBG_TO_STACK = 20;
    DBG_PKT_HASH = 21;
    DBG_LB6_LOOKUP_FRONTEND = 22;
    DBG_LB6_LOOKUP_FRONTEND_FAIL = 23;
    DBG_LB6_LOOKUP_BACKEND_SLOT = 24;
    DBG_LB6_LOOKUP_BACKEND_SLOT_SUCCESS = 25;
    DBG_LB6_LOOKUP_BACKEND_SLOT_V2_FAIL = 26;
    DBG_LB6_LOOKUP_BACKEND_FAIL = 27;
    DBG_LB6_REVERSE_NAT_LOOKUP = 28;
    DBG_LB6_REVERSE_NAT = 29;
    DBG_LB4_LOOKUP_FRONTEND = 30;
    DBG_LB4_LOOKUP_FRONTEND_FAIL = 31;
    DBG_LB4_LOOKUP_BACKEND_SLOT = 32;
    DBG_LB4_LOOKUP_BACKEND_SLOT_SUCCESS = 33;
    DBG_LB4_LOOKUP_BACKEND_SLOT_V2_FAIL = 34;
    DBG_LB4_LOOKUP_BACKEND_FAIL = 35;
    DBG_LB4_REVERSE_NAT_LOOKUP = 36;
    DBG_LB4_REVERSE_NAT = 37;
    DBG_LB4_LOOPBACK_SNAT = 38;
    DBG_LB4_LOOPBACK_SNAT_REV = 39;
    DBG_CT_LOOKUP4 = 40;
    DBG_RR_BACKEND_SLOT_SEL = 41;
    DBG_REV_PROXY_LOOKUP = 42;
    DBG_REV_PROXY_FOUND = 43;
    DBG_REV_PROXY_UPDATE = 44;
    DBG_L4_POLICY = 45;
    DBG_NETDEV_IN_CLUSTER = 46;
    DBG_NETDEV_ENCAP4 = 47;
    DBG_CT_LOOKUP4_1 = 48;
    DBG_CT_LOOKUP4_2 = 49;
    DBG_CT_CREATED4 = 50;
    DBG_CT_LOOKUP6_1 = 51;
    DBG_CT_LOOKUP6_2 = 52;
    DBG_CT_CREATED6 = 53;
    DBG_SKIP_PROXY = 54;
    DBG_L4_CREATE = 55;
    DBG_IP_ID_MAP_FAILED4 = 56;
    DBG_IP_ID_MAP_FAILED6 = 57;
    DBG_IP_ID_MAP_SUCCEED4 = 58;
    DBG_IP_ID_MAP_SUCCEED6 = 59;
    DBG_LB_STALE_CT = 60;
    DBG_INHERIT_IDENTITY = 61;
    DBG_SK_LOOKUP4 = 62;
    DBG_SK_LOOKUP6 = 63;
    DBG_SK_ASSIGN = 64;
    DBG_L7_LB = 65;
    DBG_SKIP_POLICY = 66;
    DBG_LB6_LOOPBACK_SNAT = 67;
    DBG_LB6_LOOPBACK_SNAT_REV = 68;
}

// Aggregate contains flow aggregation counters
message Aggregate {
    // ingress_flow_count is the count of flows in the ingress direction
    uint32 ingress_flow_count = 1;

    // egress_flow_count is the count of flows in the egress direction  
    uint32 egress_flow_count = 2;

    // unknown_direction_flow_count is the count of flows with unknown traffic direction
    uint32 unknown_direction_flow_count = 3;
}
