net/sched/sch_cbs.c

Source file repositories/reference/linux-study-clean/net/sched/sch_cbs.c

File Facts

System
Linux kernel
Corpus path
net/sched/sch_cbs.c
Extension
.c
Size
14430 bytes
Lines
593
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

const struct net_device_ops *ops;
	int err;

	if (!q->offload)
		return;

	q->enqueue = cbs_enqueue_soft;
	q->dequeue = cbs_dequeue_soft;

	ops = dev->netdev_ops;
	if (!ops->ndo_setup_tc)
		return;

	cbs.queue = q->queue;
	cbs.enable = 0;

	err = ops->ndo_setup_tc(dev, TC_SETUP_QDISC_CBS, &cbs);
	if (err < 0)
		pr_warn("Couldn't disable CBS offload for queue %d\n",
			cbs.queue);
}

static int cbs_enable_offload(struct net_device *dev, struct cbs_sched_data *q,
			      const struct tc_cbs_qopt *opt,
			      struct netlink_ext_ack *extack)
{
	const struct net_device_ops *ops = dev->netdev_ops;
	struct tc_cbs_qopt_offload cbs = { };
	int err;

	if (!ops->ndo_setup_tc) {
		NL_SET_ERR_MSG(extack, "Specified device does not support cbs offload");
		return -EOPNOTSUPP;
	}

	cbs.queue = q->queue;

	cbs.enable = 1;
	cbs.hicredit = opt->hicredit;
	cbs.locredit = opt->locredit;
	cbs.idleslope = opt->idleslope;
	cbs.sendslope = opt->sendslope;

	err = ops->ndo_setup_tc(dev, TC_SETUP_QDISC_CBS, &cbs);
	if (err < 0) {
		NL_SET_ERR_MSG(extack, "Specified device failed to setup cbs hardware offload");
		return err;
	}

	q->enqueue = cbs_enqueue_offload;
	q->dequeue = cbs_dequeue_offload;

	return 0;
}

static void cbs_set_port_rate(struct net_device *dev, struct cbs_sched_data *q)
{
	struct ethtool_link_ksettings ecmd;
	int speed = SPEED_10;
	s64 port_rate;
	int err;

	err = netif_get_link_ksettings(dev, &ecmd);
	if (err < 0)
		goto skip;

	if (ecmd.base.speed && ecmd.base.speed != SPEED_UNKNOWN)
		speed = ecmd.base.speed;

skip:
	port_rate = speed * 1000 * BYTES_PER_KBIT;

	atomic64_set(&q->port_rate, port_rate);
	netdev_dbg(dev, "cbs: set %s's port_rate to: %lld, linkspeed: %d\n",
		   dev->name, (long long)atomic64_read(&q->port_rate),
		   speed);
}

static int cbs_dev_notifier(struct notifier_block *nb, unsigned long event,
			    void *ptr)
{
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
	struct cbs_sched_data *q;
	struct net_device *qdev;
	bool found = false;

	ASSERT_RTNL();

	if (event != NETDEV_UP && event != NETDEV_CHANGE)
		return NOTIFY_DONE;

Annotation

Implementation Notes