interface: switch to using clsact for filters
[project/qosify.git] / qosify-bpf.c
index b7e7093960927b7d5d5dcf4fe1baa94bd5b887d6..54a1e38e266842a716fbf3858d1fb16dd3912b49 100644 (file)
@@ -44,13 +44,21 @@ struct {
        __uint(max_entries, 1);
 } config SEC(".maps");
 
-typedef struct {
+struct {
        __uint(type, BPF_MAP_TYPE_ARRAY);
        __uint(pinning, 1);
        __type(key, __u32);
        __type(value, __u8);
        __uint(max_entries, 1 << 16);
-} port_array_t;
+} tcp_ports SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_ARRAY);
+       __uint(pinning, 1);
+       __type(key, __u32);
+       __type(value, __u8);
+       __uint(max_entries, 1 << 16);
+} udp_ports SEC(".maps");
 
 struct {
        __uint(type, BPF_MAP_TYPE_LRU_HASH);
@@ -60,9 +68,6 @@ struct {
        __uint(max_entries, QOSIFY_FLOW_BUCKETS);
 } flow_map SEC(".maps");
 
-port_array_t tcp_ports SEC(".maps");
-port_array_t udp_ports SEC(".maps");
-
 struct {
        __uint(type, BPF_MAP_TYPE_HASH);
        __uint(pinning, 1);
@@ -258,10 +263,12 @@ parse_l4proto(struct qosify_config *config, struct __sk_buff *skb,
                return;
        }
 
+       src = READ_ONCE(udp->source);
+       dest = READ_ONCE(udp->dest);
        if (ingress)
-               key = udp->source;
+               key = src;
        else
-               key = udp->dest;
+               key = dest;
 
        if (proto == IPPROTO_TCP) {
                value = bpf_map_lookup_elem(&tcp_ports, &key);
@@ -283,6 +290,7 @@ check_flow_bulk(struct qosify_flow_config *config, struct __sk_buff *skb,
        bool trigger = false;
        __s32 delta;
        __u32 time;
+       int segs = 1;
 
        if (!config->bulk_trigger_pps)
                return;
@@ -295,7 +303,9 @@ check_flow_bulk(struct qosify_flow_config *config, struct __sk_buff *skb,
        if ((u32)delta > FLOW_TIMEOUT)
                goto reset;
 
-       flow->pkt_count++;
+       if (skb->gso_segs)
+               segs = skb->gso_segs;
+       flow->pkt_count += segs;
        if (flow->pkt_count > config->bulk_trigger_pps) {
                flow->bulk_timeout = config->bulk_trigger_timeout + 1;
                trigger = true;
@@ -324,11 +334,18 @@ static __always_inline void
 check_flow_prio(struct qosify_flow_config *config, struct __sk_buff *skb,
                struct flow_bucket *flow, __u8 *out_val)
 {
+       int cur_len = skb->len;
+
        if (flow->bulk_timeout)
                return;
 
-       if (config->prio_max_avg_pkt_len &&
-           ewma(&flow->pkt_len_avg, skb->len) <= config->prio_max_avg_pkt_len)
+       if (!config->prio_max_avg_pkt_len)
+               return;
+
+       if (skb->gso_segs > 1)
+               cur_len /= skb->gso_segs;
+
+       if (ewma(&flow->pkt_len_avg, cur_len) <= config->prio_max_avg_pkt_len)
                *out_val = config->dscp_prio;
 }
 
@@ -461,7 +478,7 @@ int classify(struct __sk_buff *skb)
 
        config = get_config();
        if (!config)
-               return TC_ACT_OK;
+               return TC_ACT_UNSPEC;
 
        if (module_flags & QOSIFY_IP_ONLY)
                type = skb->protocol;
@@ -474,7 +491,7 @@ int classify(struct __sk_buff *skb)
        else if (type == bpf_htons(ETH_P_IPV6))
                ip_val = parse_ipv6(config, skb, &offset, ingress, &dscp);
        else
-               return TC_ACT_OK;
+               return TC_ACT_UNSPEC;
 
        if (ip_val) {
                if (!ip_val->seen)
@@ -483,13 +500,13 @@ int classify(struct __sk_buff *skb)
        }
 
        if (dscp_lookup_class(&dscp, ingress, &class))
-               return TC_ACT_OK;
+               return TC_ACT_UNSPEC;
 
        if (class) {
                check_flow(&class->config, skb, &dscp);
 
                if (dscp_lookup_class(&dscp, ingress, &class))
-                       return TC_ACT_OK;
+                       return TC_ACT_UNSPEC;
        }
 
        dscp &= GENMASK(5, 0);
@@ -501,7 +518,7 @@ int classify(struct __sk_buff *skb)
        else if (type == bpf_htons(ETH_P_IPV6))
                ipv6_change_dsfield(skb, iph_offset, INET_ECN_MASK, dscp, force);
 
-       return TC_ACT_OK;
+       return TC_ACT_UNSPEC;
 }
 
 char _license[] SEC("license") = "GPL";