Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9c7a7ac authored by Nogah Frankel's avatar Nogah Frankel Committed by David S. Miller
Browse files

net: sch: prio: Add offload ability for grafting a child



Offload sch_prio graft command for capable drivers.
Warn in case of a failure, unless the graft was done as part of a destroy
operation (the new qdisc is a noop) or if all the qdiscs (the parent, the
old child, and the new one) are not offloaded.

Signed-off-by: default avatarNogah Frankel <nogahf@mellanox.com>
Reviewed-by: default avatarYuval Mintz <yuvalm@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 98ceb7b6
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -806,6 +806,7 @@ enum tc_prio_command {
	TC_PRIO_REPLACE,
	TC_PRIO_DESTROY,
	TC_PRIO_STATS,
	TC_PRIO_GRAFT,
};

struct tc_prio_qopt_offload_params {
@@ -818,6 +819,11 @@ struct tc_prio_qopt_offload_params {
	struct gnet_stats_queue *qstats;
};

struct tc_prio_qopt_offload_graft_params {
	u8 band;
	u32 child_handle;
};

struct tc_prio_qopt_offload {
	enum tc_prio_command command;
	u32 handle;
@@ -825,6 +831,8 @@ struct tc_prio_qopt_offload {
	union {
		struct tc_prio_qopt_offload_params replace_params;
		struct tc_qopt_offload_stats stats;
		struct tc_prio_qopt_offload_graft_params graft_params;
	};
};

#endif
+32 −0
Original line number Diff line number Diff line
@@ -308,12 +308,44 @@ static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
		      struct Qdisc **old, struct netlink_ext_ack *extack)
{
	struct prio_sched_data *q = qdisc_priv(sch);
	struct tc_prio_qopt_offload graft_offload;
	struct net_device *dev = qdisc_dev(sch);
	unsigned long band = arg - 1;
	bool any_qdisc_is_offloaded;
	int err;

	if (new == NULL)
		new = &noop_qdisc;

	*old = qdisc_replace(sch, new, &q->queues[band]);

	if (!tc_can_offload(dev))
		return 0;

	graft_offload.handle = sch->handle;
	graft_offload.parent = sch->parent;
	graft_offload.graft_params.band = band;
	graft_offload.graft_params.child_handle = new->handle;
	graft_offload.command = TC_PRIO_GRAFT;

	err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_PRIO,
					    &graft_offload);

	/* Don't report error if the graft is part of destroy operation. */
	if (err && new != &noop_qdisc) {
		/* Don't report error if the parent, the old child and the new
		 * one are not offloaded.
		 */
		any_qdisc_is_offloaded = sch->flags & TCQ_F_OFFLOADED;
		any_qdisc_is_offloaded |= new->flags & TCQ_F_OFFLOADED;
		if (*old)
			any_qdisc_is_offloaded |= (*old)->flags &
						   TCQ_F_OFFLOADED;

		if (any_qdisc_is_offloaded)
			NL_SET_ERR_MSG(extack, "Offloading graft operation failed.");
	}

	return 0;
}