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
849 TC_SETUP_QDISC_GRED,849 TC_SETUP_QDISC_GRED,
850 TC_SETUP_QDISC_TAPRIO,850 TC_SETUP_QDISC_TAPRIO,
851 TC_SETUP_FT,851 TC_SETUP_FT,
852 TC_SETUP_QDISC_ETS,
852};853};
853 854
854/* These structures hold the attributes of bpf state that are being passed855/* 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
823 bool ingress;823 bool ingress;
824};824};
825 825
826enum tc_ets_command {
827 TC_ETS_REPLACE,
828 TC_ETS_DESTROY,
829 TC_ETS_STATS,
830 TC_ETS_GRAFT,
831};
832
833struct 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
841struct tc_ets_qopt_offload_graft_params {
842 u8 band;
843 u32 child_handle;
844};
845
846struct 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
826#endif857#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
102 return TC_H_MAKE(sch->handle, band + 1);102 return TC_H_MAKE(sch->handle, band + 1);
103}103}
104 104
105static 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
146static 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
160static 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
177static 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
105static bool ets_class_is_strict(struct ets_sched *q, const struct ets_class *cl)190static bool ets_class_is_strict(struct ets_sched *q, const struct ets_class *cl)
106{191{
107 unsigned int band = cl - q->classes;192 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
154 sch_tree_lock(sch);239 sch_tree_lock(sch);
155 cl->quantum = quantum;240 cl->quantum = quantum;
156 sch_tree_unlock(sch);241 sch_tree_unlock(sch);
242
243 ets_offload_change(sch);
157 return 0;244 return 0;
158}245}
159 246
@@ -173,6 +260,7 @@ static int ets_class_graft(struct Qdisc *sch, unsigned long arg, · 13 unmodified lines
173 }260 }
174 261
175 *old = qdisc_replace(sch, new, &cl->qdisc);262 *old = qdisc_replace(sch, new, &cl->qdisc);
263 ets_offload_graft(sch, new, *old, arg, extack);
176 return 0;264 return 0;
177}265}
178 266
@@ -589,6 +677,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, · 410 unmodified lines
589 677
590 sch_tree_unlock(sch);678 sch_tree_unlock(sch);
591 679
680 ets_offload_change(sch);
592 for (i = q->nbands; i < oldbands; i++) {681 for (i = q->nbands; i < oldbands; i++) {
593 qdisc_put(q->classes[i].qdisc);682 qdisc_put(q->classes[i].qdisc);
594 memset(&q->classes[i], 0, sizeof(q->classes[i]));683 memset(&q->classes[i], 0, sizeof(q->classes[i]));
@@ -633,6 +722,7 @@ static void ets_qdisc_destroy(struct Qdisc *sch) · 38 unmodified lines
633 struct ets_sched *q = qdisc_priv(sch);722 struct ets_sched *q = qdisc_priv(sch);
634 int band;723 int band;
635 724
725 ets_offload_destroy(sch);
636 tcf_block_put(q->block);726 tcf_block_put(q->block);
637 for (band = 0; band < q->nbands; band++)727 for (band = 0; band < q->nbands; band++)
638 qdisc_put(q->classes[band].qdisc);728 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
645 struct nlattr *nest;735 struct nlattr *nest;
646 int band;736 int band;
647 int prio;737 int prio;
738 int err;
739
740 err = ets_offload_dump(sch);
741 if (err)
742 return err;
648 743
649 opts = nla_nest_start_noflag(skb, TCA_OPTIONS);744 opts = nla_nest_start_noflag(skb, TCA_OPTIONS);
650 if (!opts)745 if (!opts)