diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index fffdc603f4c..95ec28be683 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -103,7 +103,8 @@ extern int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp, struct tcf_result *res); extern int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct tcf_result *res); - +extern void tc_qdisc_flow_control(struct net_device *dev, u32 tcm_handle, + int flow_enable); /* Calculate maximal size of packet seen by hard_start_xmit routine of this device. */ diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 3d8981fde30..60e2fa9f194 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1029,6 +1029,35 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) return 0; } +/* + * enable/disable flow on qdisc. + */ +void +tc_qdisc_flow_control(struct net_device *dev, u32 tcm_handle, int enable_flow) +{ + struct Qdisc *q; + struct __qdisc_change_req { + struct nlattr attr; + struct tc_prio_qopt data; + } req = { + .attr = {sizeof(struct __qdisc_change_req), TCA_OPTIONS}, + .data = {3, {1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, 1} + }; + + /* override flow bit */ + req.data.enable_flow = enable_flow; + + /* look up using tcm handle */ + q = qdisc_lookup(dev, tcm_handle); + + /* call registered change function */ + if (q) { + if (q->ops->change(q, &(req.attr)) != 0) + pr_err("tc_qdisc_flow_control: qdisc change failed"); + } +} +EXPORT_SYMBOL(tc_qdisc_flow_control); + /* * Create/change qdisc. */