Skip to content

Commit

Permalink
fq: support filtering a given tin
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johannes Berg committed Oct 11, 2017
1 parent 4133da7 commit 8c418b5
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 10 deletions.
7 changes: 7 additions & 0 deletions include/net/fq.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ typedef void fq_skb_free_t(struct fq *,
struct fq_flow *,
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 *,
struct fq_tin *,
int idx,
Expand Down
72 changes: 62 additions & 10 deletions include/net/fq_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 8c418b5

Please sign in to comment.