]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
bypass: compress flow keys structure
authorEric Leblond <eric@regit.org>
Sun, 9 Jun 2019 21:00:53 +0000 (23:00 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 18 Jun 2019 05:07:02 +0000 (07:07 +0200)
ebpf/bypass_filter.c
ebpf/xdp_filter.c
src/source-af-packet.c
src/util-ebpf.c
src/util-ebpf.h

index 7ad1a16226a23cd1fe3b04493272ac83c0dbe96b..eda9650edcf50f96b0e4f9333b216b6e4e477358 100644 (file)
 #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]);
index ff00cef3f2484426d756e8e044968688ca3ffea1..9ef2d92f7bfb552748e1fa3cdc94760dd6bf71f6 100644 (file)
@@ -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) {
index 52676838d29ece778709dc3ff3240efa8bfa4395..98ad3337ea48ae36c9a676e41048ea603e67254c 100644 (file)
@@ -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]);
index c507494f516298dc8034ca7d9684f359d960079f..59b79670952244df7e712b411743c9d4fb75a9cb 100644 (file)
@@ -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,
index 818283d7af25597e1a6face4edc274bcb34c2d22..f66cc7c95530ecff251741f5900e9e4f2c57f980 100644 (file)
@@ -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_ {