mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-08 14:23:19 +00:00
fq: support filtering a given tin
Add to the FQ API a way to filter a given tin, in order to remove frames that fulfil certain criteria according to a filter function. This will be used by mac80211 to remove frames belonging to an AP VLAN interface that's being removed. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Acked-by: Toke Høiland-Jørgensen <toke@toke.dk> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
4133da7306
commit
8c418b5b15
@ -90,6 +90,13 @@ typedef void fq_skb_free_t(struct fq *,
|
|||||||
struct fq_flow *,
|
struct fq_flow *,
|
||||||
struct sk_buff *);
|
struct sk_buff *);
|
||||||
|
|
||||||
|
/* Return %true to filter (drop) the frame. */
|
||||||
|
typedef bool fq_skb_filter_t(struct fq *,
|
||||||
|
struct fq_tin *,
|
||||||
|
struct fq_flow *,
|
||||||
|
struct sk_buff *,
|
||||||
|
void *);
|
||||||
|
|
||||||
typedef struct fq_flow *fq_flow_get_default_t(struct fq *,
|
typedef struct fq_flow *fq_flow_get_default_t(struct fq *,
|
||||||
struct fq_tin *,
|
struct fq_tin *,
|
||||||
int idx,
|
int idx,
|
||||||
|
@ -12,24 +12,22 @@
|
|||||||
|
|
||||||
/* functions that are embedded into includer */
|
/* functions that are embedded into includer */
|
||||||
|
|
||||||
static struct sk_buff *fq_flow_dequeue(struct fq *fq,
|
static void fq_adjust_removal(struct fq *fq,
|
||||||
struct fq_flow *flow)
|
struct fq_flow *flow,
|
||||||
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct fq_tin *tin = flow->tin;
|
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_bytes -= skb->len;
|
||||||
tin->backlog_packets--;
|
tin->backlog_packets--;
|
||||||
flow->backlog -= skb->len;
|
flow->backlog -= skb->len;
|
||||||
fq->backlog--;
|
fq->backlog--;
|
||||||
fq->memory_usage -= skb->truesize;
|
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) {
|
if (flow->backlog == 0) {
|
||||||
list_del_init(&flow->backlogchain);
|
list_del_init(&flow->backlogchain);
|
||||||
@ -43,6 +41,21 @@ static struct sk_buff *fq_flow_dequeue(struct fq *fq,
|
|||||||
list_move_tail(&flow->backlogchain,
|
list_move_tail(&flow->backlogchain,
|
||||||
&i->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;
|
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,
|
static void fq_flow_reset(struct fq *fq,
|
||||||
struct fq_flow *flow,
|
struct fq_flow *flow,
|
||||||
fq_skb_free_t free_func)
|
fq_skb_free_t free_func)
|
||||||
|
Loading…
Reference in New Issue
Block a user