]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - include/net/fq_impl.h
net/mlx5e: Rx, Fix checksum calculation for new hardware
[mirror_ubuntu-bionic-kernel.git] / include / net / fq_impl.h
index ac1a2317941e7186abd01d3df0bf9ebc055be38b..89a012905ef0bf1084bb46815163d8d54f25b39c 100644 (file)
 
 /* functions that are embedded into includer */
 
-static struct sk_buff *fq_flow_dequeue(struct fq *fq,
-                                      struct fq_flow *flow)
+static void fq_adjust_removal(struct fq *fq,
+                             struct fq_flow *flow,
+                             struct sk_buff *skb)
 {
        struct fq_tin *tin = flow->tin;
-       struct fq_flow *i;
-       struct sk_buff *skb;
-
-       lockdep_assert_held(&fq->lock);
-
-       skb = __skb_dequeue(&flow->queue);
-       if (!skb)
-               return NULL;
 
        tin->backlog_bytes -= skb->len;
        tin->backlog_packets--;
        flow->backlog -= skb->len;
        fq->backlog--;
        fq->memory_usage -= skb->truesize;
+}
+
+static void fq_rejigger_backlog(struct fq *fq, struct fq_flow *flow)
+{
+       struct fq_flow *i;
 
        if (flow->backlog == 0) {
                list_del_init(&flow->backlogchain);
@@ -43,6 +41,21 @@ static struct sk_buff *fq_flow_dequeue(struct fq *fq,
                list_move_tail(&flow->backlogchain,
                               &i->backlogchain);
        }
+}
+
+static struct sk_buff *fq_flow_dequeue(struct fq *fq,
+                                      struct fq_flow *flow)
+{
+       struct sk_buff *skb;
+
+       lockdep_assert_held(&fq->lock);
+
+       skb = __skb_dequeue(&flow->queue);
+       if (!skb)
+               return NULL;
+
+       fq_adjust_removal(fq, flow, skb);
+       fq_rejigger_backlog(fq, flow);
 
        return skb;
 }
@@ -105,7 +118,7 @@ static struct fq_flow *fq_flow_classify(struct fq *fq,
 
        lockdep_assert_held(&fq->lock);
 
-       hash = skb_get_hash_perturb(skb, fq->perturbation);
+       hash = skb_get_hash_perturb(skb, &fq->perturbation);
        idx = reciprocal_scale(hash, fq->flows_cnt);
        flow = &fq->flows[idx];
 
@@ -191,6 +204,45 @@ static void fq_tin_enqueue(struct fq *fq,
        }
 }
 
+static void fq_flow_filter(struct fq *fq,
+                          struct fq_flow *flow,
+                          fq_skb_filter_t filter_func,
+                          void *filter_data,
+                          fq_skb_free_t free_func)
+{
+       struct fq_tin *tin = flow->tin;
+       struct sk_buff *skb, *tmp;
+
+       lockdep_assert_held(&fq->lock);
+
+       skb_queue_walk_safe(&flow->queue, skb, tmp) {
+               if (!filter_func(fq, tin, flow, skb, filter_data))
+                       continue;
+
+               __skb_unlink(skb, &flow->queue);
+               fq_adjust_removal(fq, flow, skb);
+               free_func(fq, tin, flow, skb);
+       }
+
+       fq_rejigger_backlog(fq, flow);
+}
+
+static void fq_tin_filter(struct fq *fq,
+                         struct fq_tin *tin,
+                         fq_skb_filter_t filter_func,
+                         void *filter_data,
+                         fq_skb_free_t free_func)
+{
+       struct fq_flow *flow;
+
+       lockdep_assert_held(&fq->lock);
+
+       list_for_each_entry(flow, &tin->new_flows, flowchain)
+               fq_flow_filter(fq, flow, filter_func, filter_data, free_func);
+       list_for_each_entry(flow, &tin->old_flows, flowchain)
+               fq_flow_filter(fq, flow, filter_func, filter_data, free_func);
+}
+
 static void fq_flow_reset(struct fq *fq,
                          struct fq_flow *flow,
                          fq_skb_free_t free_func)
@@ -255,7 +307,7 @@ static int fq_init(struct fq *fq, int flows_cnt)
        INIT_LIST_HEAD(&fq->backlogs);
        spin_lock_init(&fq->lock);
        fq->flows_cnt = max_t(u32, flows_cnt, 1);
-       fq->perturbation = prandom_u32();
+       get_random_bytes(&fq->perturbation, sizeof(fq->perturbation));
        fq->quantum = 300;
        fq->limit = 8192;
        fq->memory_limit = 16 << 20; /* 16 MBytes */