History

net: sch_ets: Make the ETS qdisc offloadable

Add hooks at appropriate points to make it possible to offload the ETS Qdisc.

Petr Machata committed 6 years ago

Commit d35eb521 parent dcc68b43 files · +127 −0Browse files

Unified · Split

3 files
  1. include/linux/netdevice.h +1 −0
  2. include/net/pkt_cls.h +31 −0
  3. net/sched/sch_ets.c +95 −0
include/linux/netdevice.h+1−0
@@ -849,6 +849,7 @@ enum tc_setup_type { · 848 unmodified lines
849849 TC_SETUP_QDISC_GRED,
850850 TC_SETUP_QDISC_TAPRIO,
851851 TC_SETUP_FT,
852+ TC_SETUP_QDISC_ETS,
852853 };
853854
854855 /* These structures hold the attributes of bpf state that are being passed
include/net/pkt_cls.h+31−0
@@ -823,4 +823,35 @@ struct tc_root_qopt_offload { · 822 unmodified lines
823823 bool ingress;
824824 };
825825
826+enum tc_ets_command {
827+ TC_ETS_REPLACE,
828+ TC_ETS_DESTROY,
829+ TC_ETS_STATS,
830+ TC_ETS_GRAFT,
831+};
832+
833+struct tc_ets_qopt_offload_replace_params {
834+ unsigned int bands;
835+ u8 priomap[TC_PRIO_MAX + 1];
836+ unsigned int quanta[TCQ_ETS_MAX_BANDS]; /* 0 for strict bands. */
837+ unsigned int weights[TCQ_ETS_MAX_BANDS];
838+ struct gnet_stats_queue *qstats;
839+};
840+
841+struct tc_ets_qopt_offload_graft_params {
842+ u8 band;
843+ u32 child_handle;
844+};
845+
846+struct tc_ets_qopt_offload {
847+ enum tc_ets_command command;
848+ u32 handle;
849+ u32 parent;
850+ union {
851+ struct tc_ets_qopt_offload_replace_params replace_params;
852+ struct tc_qopt_offload_stats stats;
853+ struct tc_ets_qopt_offload_graft_params graft_params;
854+ };
855+};
856+
826857 #endif
net/sched/sch_ets.c+95−0
@@ -102,6 +102,91 @@ static u32 ets_class_id(struct Qdisc *sch, const struct ets_class *cl) · 101 unmodified lines
102102 return TC_H_MAKE(sch->handle, band + 1);
103103 }
104104
105+static void ets_offload_change(struct Qdisc *sch)
106+{
107+ struct net_device *dev = qdisc_dev(sch);
108+ struct ets_sched *q = qdisc_priv(sch);
109+ struct tc_ets_qopt_offload qopt;
110+ unsigned int w_psum_prev = 0;
111+ unsigned int q_psum = 0;
112+ unsigned int q_sum = 0;
113+ unsigned int quantum;
114+ unsigned int w_psum;
115+ unsigned int weight;
116+ unsigned int i;
117+
118+ if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc)
119+ return;
120+
121+ qopt.command = TC_ETS_REPLACE;
122+ qopt.handle = sch->handle;
123+ qopt.parent = sch->parent;
124+ qopt.replace_params.bands = q->nbands;
125+ qopt.replace_params.qstats = &sch->qstats;
126+ memcpy(&qopt.replace_params.priomap,
127+ q->prio2band, sizeof(q->prio2band));
128+
129+ for (i = 0; i < q->nbands; i++)
130+ q_sum += q->classes[i].quantum;
131+
132+ for (i = 0; i < q->nbands; i++) {
133+ quantum = q->classes[i].quantum;
134+ q_psum += quantum;
135+ w_psum = quantum ? q_psum * 100 / q_sum : 0;
136+ weight = w_psum - w_psum_prev;
137+ w_psum_prev = w_psum;
138+
139+ qopt.replace_params.quanta[i] = quantum;
140+ qopt.replace_params.weights[i] = weight;
141+ }
142+
143+ dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_ETS, &qopt);
144+}
145+
146+static void ets_offload_destroy(struct Qdisc *sch)
147+{
148+ struct net_device *dev = qdisc_dev(sch);
149+ struct tc_ets_qopt_offload qopt;
150+
151+ if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc)
152+ return;
153+
154+ qopt.command = TC_ETS_DESTROY;
155+ qopt.handle = sch->handle;
156+ qopt.parent = sch->parent;
157+ dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_ETS, &qopt);
158+}
159+
160+static void ets_offload_graft(struct Qdisc *sch, struct Qdisc *new,
161+ struct Qdisc *old, unsigned long arg,
162+ struct netlink_ext_ack *extack)
163+{
164+ struct net_device *dev = qdisc_dev(sch);
165+ struct tc_ets_qopt_offload qopt;
166+
167+ qopt.command = TC_ETS_GRAFT;
168+ qopt.handle = sch->handle;
169+ qopt.parent = sch->parent;
170+ qopt.graft_params.band = arg - 1;
171+ qopt.graft_params.child_handle = new->handle;
172+
173+ qdisc_offload_graft_helper(dev, sch, new, old, TC_SETUP_QDISC_ETS,
174+ &qopt, extack);
175+}
176+
177+static int ets_offload_dump(struct Qdisc *sch)
178+{
179+ struct tc_ets_qopt_offload qopt;
180+
181+ qopt.command = TC_ETS_STATS;
182+ qopt.handle = sch->handle;
183+ qopt.parent = sch->parent;
184+ qopt.stats.bstats = &sch->bstats;
185+ qopt.stats.qstats = &sch->qstats;
186+
187+ return qdisc_offload_dump_helper(sch, TC_SETUP_QDISC_ETS, &qopt);
188+}
189+
105190 static bool ets_class_is_strict(struct ets_sched *q, const struct ets_class *cl)
106191 {
107192 unsigned int band = cl - q->classes;
@@ -154,6 +239,8 @@ static int ets_class_change(struct Qdisc *sch, u32 classid, u32 parentid, · 46 unmodified lines
154239 sch_tree_lock(sch);
155240 cl->quantum = quantum;
156241 sch_tree_unlock(sch);
242+
243+ ets_offload_change(sch);
157244 return 0;
158245 }
159246
@@ -173,6 +260,7 @@ static int ets_class_graft(struct Qdisc *sch, unsigned long arg, · 13 unmodified lines
173260 }
174261
175262 *old = qdisc_replace(sch, new, &cl->qdisc);
263+ ets_offload_graft(sch, new, *old, arg, extack);
176264 return 0;
177265 }
178266
@@ -589,6 +677,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, · 410 unmodified lines
589677
590678 sch_tree_unlock(sch);
591679
680+ ets_offload_change(sch);
592681 for (i = q->nbands; i < oldbands; i++) {
593682 qdisc_put(q->classes[i].qdisc);
594683 memset(&q->classes[i], 0, sizeof(q->classes[i]));
@@ -633,6 +722,7 @@ static void ets_qdisc_destroy(struct Qdisc *sch) · 38 unmodified lines
633722 struct ets_sched *q = qdisc_priv(sch);
634723 int band;
635724
725+ ets_offload_destroy(sch);
636726 tcf_block_put(q->block);
637727 for (band = 0; band < q->nbands; band++)
638728 qdisc_put(q->classes[band].qdisc);
@@ -645,6 +735,11 @@ static int ets_qdisc_dump(struct Qdisc *sch, struct sk_buff *skb) · 6 unmodified lines
645735 struct nlattr *nest;
646736 int band;
647737 int prio;
738+ int err;
739+
740+ err = ets_offload_dump(sch);
741+ if (err)
742+ return err;
648743
649744 opts = nla_nest_start_noflag(skb, TCA_OPTIONS);
650745 if (!opts)