Commit 25fc1989 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

net: sched: gred: store red flags per virtual queue

Right now ECN marking and HARD drop (the common RED flags) can only
be configured for the entire Qdisc.  In preparation for per-vq flags
store the values in the virtual queue structure.  Setting per-vq
flags will only be allowed when no flags are set for the entire Qdisc.
For the new flags we will also make sure undefined bits are 0.
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarJohn Hurley <john.hurley@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 80e22e96
...@@ -29,12 +29,15 @@ ...@@ -29,12 +29,15 @@
#define GRED_DEF_PRIO (MAX_DPs / 2) #define GRED_DEF_PRIO (MAX_DPs / 2)
#define GRED_VQ_MASK (MAX_DPs - 1) #define GRED_VQ_MASK (MAX_DPs - 1)
#define GRED_VQ_RED_FLAGS (TC_RED_ECN | TC_RED_HARDDROP)
struct gred_sched_data; struct gred_sched_data;
struct gred_sched; struct gred_sched;
struct gred_sched_data { struct gred_sched_data {
u32 limit; /* HARD maximal queue length */ u32 limit; /* HARD maximal queue length */
u32 DP; /* the drop parameters */ u32 DP; /* the drop parameters */
u32 red_flags; /* virtualQ version of red_flags */
u64 bytesin; /* bytes seen on virtualQ so far*/ u64 bytesin; /* bytes seen on virtualQ so far*/
u32 packetsin; /* packets seen on virtualQ so far*/ u32 packetsin; /* packets seen on virtualQ so far*/
u32 backlog; /* bytes on the virtualQ */ u32 backlog; /* bytes on the virtualQ */
...@@ -139,14 +142,14 @@ static inline void gred_store_wred_set(struct gred_sched *table, ...@@ -139,14 +142,14 @@ static inline void gred_store_wred_set(struct gred_sched *table,
table->wred_set.qidlestart = q->vars.qidlestart; table->wred_set.qidlestart = q->vars.qidlestart;
} }
static inline int gred_use_ecn(struct gred_sched *t) static int gred_use_ecn(struct gred_sched_data *q)
{ {
return t->red_flags & TC_RED_ECN; return q->red_flags & TC_RED_ECN;
} }
static inline int gred_use_harddrop(struct gred_sched *t) static int gred_use_harddrop(struct gred_sched_data *q)
{ {
return t->red_flags & TC_RED_HARDDROP; return q->red_flags & TC_RED_HARDDROP;
} }
static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch, static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch,
...@@ -212,7 +215,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch, ...@@ -212,7 +215,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch,
case RED_PROB_MARK: case RED_PROB_MARK:
qdisc_qstats_overlimit(sch); qdisc_qstats_overlimit(sch);
if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { if (!gred_use_ecn(q) || !INET_ECN_set_ce(skb)) {
q->stats.prob_drop++; q->stats.prob_drop++;
goto congestion_drop; goto congestion_drop;
} }
...@@ -222,7 +225,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch, ...@@ -222,7 +225,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch,
case RED_HARD_MARK: case RED_HARD_MARK:
qdisc_qstats_overlimit(sch); qdisc_qstats_overlimit(sch);
if (gred_use_harddrop(t) || !gred_use_ecn(t) || if (gred_use_harddrop(q) || !gred_use_ecn(q) ||
!INET_ECN_set_ce(skb)) { !INET_ECN_set_ce(skb)) {
q->stats.forced_drop++; q->stats.forced_drop++;
goto congestion_drop; goto congestion_drop;
...@@ -305,6 +308,7 @@ static int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps, ...@@ -305,6 +308,7 @@ static int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps,
{ {
struct gred_sched *table = qdisc_priv(sch); struct gred_sched *table = qdisc_priv(sch);
struct tc_gred_sopt *sopt; struct tc_gred_sopt *sopt;
bool red_flags_changed;
int i; int i;
if (!dps) if (!dps)
...@@ -329,6 +333,7 @@ static int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps, ...@@ -329,6 +333,7 @@ static int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps,
sch_tree_lock(sch); sch_tree_lock(sch);
table->DPs = sopt->DPs; table->DPs = sopt->DPs;
table->def = sopt->def_DP; table->def = sopt->def_DP;
red_flags_changed = table->red_flags != sopt->flags;
table->red_flags = sopt->flags; table->red_flags = sopt->flags;
/* /*
...@@ -348,6 +353,12 @@ static int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps, ...@@ -348,6 +353,12 @@ static int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps,
gred_disable_wred_mode(table); gred_disable_wred_mode(table);
} }
if (red_flags_changed)
for (i = 0; i < table->DPs; i++)
if (table->tab[i])
table->tab[i]->red_flags =
table->red_flags & GRED_VQ_RED_FLAGS;
for (i = table->DPs; i < MAX_DPs; i++) { for (i = table->DPs; i < MAX_DPs; i++) {
if (table->tab[i]) { if (table->tab[i]) {
pr_warn("GRED: Warning: Destroying shadowed VQ 0x%x\n", pr_warn("GRED: Warning: Destroying shadowed VQ 0x%x\n",
...@@ -379,6 +390,7 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp, ...@@ -379,6 +390,7 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp,
*prealloc = NULL; *prealloc = NULL;
if (!q) if (!q)
return -ENOMEM; return -ENOMEM;
q->red_flags = table->red_flags & GRED_VQ_RED_FLAGS;
} }
q->DP = dp; q->DP = dp;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment