From: Eric Leblond Date: Sun, 9 Jun 2019 21:00:53 +0000 (+0200) Subject: bypass: compress flow keys structure X-Git-Tag: suricata-5.0.0-rc1~303 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d119845d9862313817e5bc8c7d413cd3cfeeffe5;p=thirdparty%2Fsuricata.git bypass: compress flow keys structure --- diff --git a/ebpf/bypass_filter.c b/ebpf/bypass_filter.c index 7ad1a16226..eda9650edc 100644 --- a/ebpf/bypass_filter.c +++ b/ebpf/bypass_filter.c @@ -33,31 +33,32 @@ #define LINUX_VERSION_CODE 263682 struct flowv4_keys { - __be32 src; - __be32 dst; + __u32 src; + __u32 dst; union { - __be32 ports; - __be16 port16[2]; + __u32 ports; + __u16 port16[2]; }; - __u32 ip_proto; - __u16 vlan_id[2]; + __u8 ip_proto:1; + __u16 vlan0:15; + __u16 vlan1; }; struct flowv6_keys { - __be32 src[4]; - __be32 dst[4]; + __u32 src[4]; + __u32 dst[4]; union { - __be32 ports; - __be16 port16[2]; + __u32 ports; + __u16 port16[2]; }; - __u32 ip_proto; - __u16 vlan_id[2]; + __u8 ip_proto:1; + __u16 vlan0:15; + __u16 vlan1; }; struct pair { - __u32 packets; - __u32 bytes; - __u32 hash; + __u64 packets; + __u64 bytes; }; struct bpf_map_def SEC("maps") flow_table_v4 = { @@ -90,14 +91,18 @@ static __always_inline int ipv4_filter(struct __sk_buff *skb, __u16 vlan0, __u16 struct flowv4_keys tuple; struct pair *value; __u16 port; + __u8 ip_proto; nhoff = skb->cb[0]; - tuple.ip_proto = load_byte(skb, nhoff + offsetof(struct iphdr, protocol)); + ip_proto = load_byte(skb, nhoff + offsetof(struct iphdr, protocol)); /* only support TCP and UDP for now */ - switch (tuple.ip_proto) { + switch (ip_proto) { case IPPROTO_TCP: + tuple.ip_proto = 1; + break; case IPPROTO_UDP: + tuple.ip_proto = 0; break; default: return -1; @@ -112,8 +117,8 @@ static __always_inline int ipv4_filter(struct __sk_buff *skb, __u16 vlan0, __u16 port = tuple.port16[1]; tuple.port16[1] = tuple.port16[0]; tuple.port16[0] = port; - tuple.vlan_id[0] = vlan0; - tuple.vlan_id[1] = vlan1; + tuple.vlan0 = vlan0; + tuple.vlan1 = vlan1; #if 0 if ((tuple.port16[0] == 22) || (tuple.port16[1] == 22)) @@ -163,7 +168,10 @@ static __always_inline int ipv6_filter(struct __sk_buff *skb, __u16 vlan0, __u16 /* only support direct TCP and UDP for now */ switch (nhdr) { case IPPROTO_TCP: + tuple.ip_proto = 1; + break; case IPPROTO_UDP: + tuple.ip_proto = 0; break; default: return -1; @@ -183,10 +191,9 @@ static __always_inline int ipv6_filter(struct __sk_buff *skb, __u16 vlan0, __u16 port = tuple.port16[1]; tuple.port16[1] = tuple.port16[0]; tuple.port16[0] = port; - tuple.ip_proto = nhdr; - tuple.vlan_id[0] = vlan0; - tuple.vlan_id[1] = vlan1; + tuple.vlan0 = vlan0; + tuple.vlan1 = vlan1; //char fmt[] = "Now Got IPv6 port %u and %u\n"; //bpf_trace_printk(fmt, sizeof(fmt), tuple.port16[0], tuple.port16[1]); diff --git a/ebpf/xdp_filter.c b/ebpf/xdp_filter.c index ff00cef3f2..9ef2d92f7b 100644 --- a/ebpf/xdp_filter.c +++ b/ebpf/xdp_filter.c @@ -72,8 +72,9 @@ struct flowv4_keys { __u32 ports; __u16 port16[2]; }; - __u32 ip_proto; - __u16 vlan_id[2]; + __u8 ip_proto:1; + __u16 vlan0:15; + __u16 vlan1; }; struct flowv6_keys { @@ -83,13 +84,14 @@ struct flowv6_keys { __u32 ports; __u16 port16[2]; }; - __u32 ip_proto; - __u16 vlan_id[2]; + __u8 ip_proto:1; + __u16 vlan0:15; + __u16 vlan1; }; struct pair { - __u32 packets; - __u32 bytes; + __u64 packets; + __u64 bytes; }; struct bpf_map_def SEC("maps") flow_table_v4 = { @@ -258,7 +260,11 @@ static int __always_inline filter_ipv4(struct xdp_md *ctx, void *data, __u64 nh_ if ((void *)(iph + 1) > data_end) return XDP_PASS; - tuple.ip_proto = (__u32) iph->protocol; + if (iph->protocol == IPPROTO_TCP) { + tuple.ip_proto = 1; + } else { + tuple.ip_proto = 0; + } tuple.src = iph->saddr; tuple.dst = iph->daddr; @@ -273,8 +279,8 @@ static int __always_inline filter_ipv4(struct xdp_md *ctx, void *data, __u64 nh_ tuple.port16[0] = (__u16)sport; tuple.port16[1] = (__u16)dport; - tuple.vlan_id[0] = vlan0; - tuple.vlan_id[1] = vlan1; + tuple.vlan0 = vlan0; + tuple.vlan1 = vlan1; value = bpf_map_lookup_elem(&flow_table_v4, &tuple); #if 0 @@ -404,14 +410,18 @@ static int __always_inline filter_ipv6(struct xdp_md *ctx, void *data, __u64 nh_ if (sport == -1) return XDP_PASS; - tuple.ip_proto = ip6h->nexthdr; + if (ip6h->nexthdr == IPPROTO_TCP) { + tuple.ip_proto = 1; + } else { + tuple.ip_proto = 0; + } __builtin_memcpy(tuple.src, ip6h->saddr.s6_addr32, sizeof(tuple.src)); __builtin_memcpy(tuple.dst, ip6h->daddr.s6_addr32, sizeof(tuple.dst)); tuple.port16[0] = sport; tuple.port16[1] = dport; - tuple.vlan_id[0] = vlan0; - tuple.vlan_id[1] = vlan1; + tuple.vlan0 = vlan0; + tuple.vlan1 = vlan1; value = bpf_map_lookup_elem(&flow_table_v6, &tuple); if (value) { diff --git a/src/source-af-packet.c b/src/source-af-packet.c index 52676838d2..98ad3337ea 100644 --- a/src/source-af-packet.c +++ b/src/source-af-packet.c @@ -2403,10 +2403,14 @@ static int AFPBypassCallback(Packet *p) keys[0]->dst = htonl(GET_IPV4_DST_ADDR_U32(p)); keys[0]->port16[0] = GET_TCP_SRC_PORT(p); keys[0]->port16[1] = GET_TCP_DST_PORT(p); - keys[0]->vlan_id[0] = p->vlan_id[0]; - keys[0]->vlan_id[1] = p->vlan_id[1]; + keys[0]->vlan0 = p->vlan_id[0]; + keys[0]->vlan1 = p->vlan_id[1]; - keys[0]->ip_proto = IPV4_GET_IPPROTO(p); + if (IPV4_GET_IPPROTO(p) == IPPROTO_TCP) { + keys[0]->ip_proto = 1; + } else { + keys[0]->ip_proto = 0; + } if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[0], p->afp_v.nr_cpus) == 0) { SCFree(keys[0]); @@ -2421,10 +2425,10 @@ static int AFPBypassCallback(Packet *p) keys[1]->dst = htonl(GET_IPV4_SRC_ADDR_U32(p)); keys[1]->port16[0] = GET_TCP_DST_PORT(p); keys[1]->port16[1] = GET_TCP_SRC_PORT(p); - keys[1]->vlan_id[0] = p->vlan_id[0]; - keys[1]->vlan_id[1] = p->vlan_id[1]; + keys[1]->vlan0 = p->vlan_id[0]; + keys[1]->vlan1 = p->vlan_id[1]; - keys[1]->ip_proto = IPV4_GET_IPPROTO(p); + keys[1]->ip_proto = keys[0]->ip_proto; if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1], p->afp_v.nr_cpus) == 0) { SCFree(keys[0]); @@ -2453,9 +2457,14 @@ static int AFPBypassCallback(Packet *p) } keys[0]->port16[0] = GET_TCP_SRC_PORT(p); keys[0]->port16[1] = GET_TCP_DST_PORT(p); - keys[0]->vlan_id[0] = p->vlan_id[0]; - keys[0]->vlan_id[1] = p->vlan_id[1]; - keys[0]->ip_proto = IPV6_GET_NH(p); + keys[0]->vlan0 = p->vlan_id[0]; + keys[0]->vlan1 = p->vlan_id[1]; + + if (IPV6_GET_NH(p) == IPPROTO_TCP) { + keys[0]->ip_proto = 1; + } else { + keys[0]->ip_proto = 0; + } if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[0], p->afp_v.nr_cpus) == 0) { SCFree(keys[0]); @@ -2472,9 +2481,10 @@ static int AFPBypassCallback(Packet *p) } keys[1]->port16[0] = GET_TCP_DST_PORT(p); keys[1]->port16[1] = GET_TCP_SRC_PORT(p); - keys[1]->vlan_id[0] = p->vlan_id[0]; - keys[1]->vlan_id[1] = p->vlan_id[1]; - keys[1]->ip_proto = IPV6_GET_NH(p); + keys[1]->vlan0 = p->vlan_id[0]; + keys[1]->vlan1 = p->vlan_id[1]; + + keys[1]->ip_proto = keys[0]->ip_proto; if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1], p->afp_v.nr_cpus) == 0) { SCFree(keys[0]); @@ -2537,9 +2547,13 @@ static int AFPXDPBypassCallback(Packet *p) * (as in eBPF filter) so we need to pass from host to network order */ keys[0]->port16[0] = htons(p->sp); keys[0]->port16[1] = htons(p->dp); - keys[0]->vlan_id[0] = p->vlan_id[0]; - keys[0]->vlan_id[1] = p->vlan_id[1]; - keys[0]->ip_proto = IPV4_GET_IPPROTO(p); + keys[0]->vlan0 = p->vlan_id[0]; + keys[0]->vlan1 = p->vlan_id[1]; + if (IPV4_GET_IPPROTO(p) == IPPROTO_TCP) { + keys[0]->ip_proto = 1; + } else { + keys[0]->ip_proto = 0; + } if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[0], p->afp_v.nr_cpus) == 0) { SCFree(keys[0]); @@ -2554,9 +2568,9 @@ static int AFPXDPBypassCallback(Packet *p) keys[1]->dst = p->src.addr_data32[0]; keys[1]->port16[0] = htons(p->dp); keys[1]->port16[1] = htons(p->sp); - keys[1]->vlan_id[0] = p->vlan_id[0]; - keys[1]->vlan_id[1] = p->vlan_id[1]; - keys[1]->ip_proto = IPV4_GET_IPPROTO(p); + keys[1]->vlan0 = p->vlan_id[0]; + keys[1]->vlan1 = p->vlan_id[1]; + keys[1]->ip_proto = keys[0]->ip_proto; if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1], p->afp_v.nr_cpus) == 0) { SCFree(keys[0]); @@ -2585,9 +2599,13 @@ static int AFPXDPBypassCallback(Packet *p) } keys[0]->port16[0] = htons(GET_TCP_SRC_PORT(p)); keys[0]->port16[1] = htons(GET_TCP_DST_PORT(p)); - keys[0]->vlan_id[0] = p->vlan_id[0]; - keys[0]->vlan_id[1] = p->vlan_id[1]; - keys[0]->ip_proto = IPV6_GET_NH(p); + keys[0]->vlan0 = p->vlan_id[0]; + keys[0]->vlan1 = p->vlan_id[1]; + if (IPV6_GET_NH(p) == IPPROTO_TCP) { + keys[0]->ip_proto = 1; + } else { + keys[0]->ip_proto = 0; + } if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[0], p->afp_v.nr_cpus) == 0) { SCFree(keys[0]); @@ -2604,9 +2622,9 @@ static int AFPXDPBypassCallback(Packet *p) } keys[1]->port16[0] = htons(GET_TCP_DST_PORT(p)); keys[1]->port16[1] = htons(GET_TCP_SRC_PORT(p)); - keys[1]->vlan_id[0] = p->vlan_id[0]; - keys[1]->vlan_id[1] = p->vlan_id[1]; - keys[1]->ip_proto = IPV6_GET_NH(p); + keys[1]->vlan0 = p->vlan_id[0]; + keys[1]->vlan1 = p->vlan_id[1]; + keys[1]->ip_proto = keys[0]->ip_proto; if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1], p->afp_v.nr_cpus) == 0) { SCFree(keys[0]); diff --git a/src/util-ebpf.c b/src/util-ebpf.c index c507494f51..59b7967095 100644 --- a/src/util-ebpf.c +++ b/src/util-ebpf.c @@ -724,9 +724,13 @@ static int EBPFForEachFlowV4Table(ThreadVars *th_v, LiveDevice *dev, const char flow_key.dst.addr_data32[1] = 0; flow_key.dst.addr_data32[2] = 0; flow_key.dst.addr_data32[3] = 0; - flow_key.vlan_id[0] = next_key.vlan_id[0]; - flow_key.vlan_id[1] = next_key.vlan_id[1]; - flow_key.proto = next_key.ip_proto; + flow_key.vlan_id[0] = next_key.vlan0; + flow_key.vlan_id[1] = next_key.vlan1; + if (next_key.ip_proto == 1) { + flow_key.proto = IPPROTO_TCP; + } else { + flow_key.proto = IPPROTO_UDP; + } flow_key.recursion_level = 0; dead_flow = EBPFOpFlowForKey(flowstats, &next_key, &flow_key, ctime, pkts_cnt, bytes_cnt, @@ -833,9 +837,13 @@ static int EBPFForEachFlowV6Table(ThreadVars *th_v, flow_key.dst.addr_data32[2] = ntohl(next_key.dst[2]); flow_key.dst.addr_data32[3] = ntohl(next_key.dst[3]); } - flow_key.vlan_id[0] = next_key.vlan_id[0]; - flow_key.vlan_id[1] = next_key.vlan_id[1]; - flow_key.proto = next_key.ip_proto; + flow_key.vlan_id[0] = next_key.vlan0; + flow_key.vlan_id[1] = next_key.vlan1; + if (next_key.ip_proto == 1) { + flow_key.proto = IPPROTO_TCP; + } else { + flow_key.proto = IPPROTO_UDP; + } flow_key.recursion_level = 0; pkts_cnt = EBPFOpFlowForKey(flowstats, &next_key, &flow_key, ctime, pkts_cnt, bytes_cnt, diff --git a/src/util-ebpf.h b/src/util-ebpf.h index 818283d7af..f66cc7c955 100644 --- a/src/util-ebpf.h +++ b/src/util-ebpf.h @@ -40,8 +40,9 @@ struct flowv4_keys { __be32 ports; __be16 port16[2]; }; - __u32 ip_proto; - __u16 vlan_id[2]; + __u8 ip_proto:1; + __u16 vlan0:15; + __u16 vlan1; }; struct flowv6_keys { @@ -51,13 +52,14 @@ struct flowv6_keys { __be32 ports; __be16 port16[2]; }; - __u32 ip_proto; - __u16 vlan_id[2]; + __u8 ip_proto:1; + __u16 vlan0:15; + __u16 vlan1; }; struct pair { - uint32_t packets; - uint32_t bytes; + uint64_t packets; + uint64_t bytes; }; typedef struct EBPFBypassData_ {