|
@@ -12,24 +12,22 @@
|
|
|
|
|
|
/* 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;
|
|
|
}
|
|
@@ -188,6 +201,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)
|