drivers/net/net_failover.c

Source file repositories/reference/linux-study-clean/drivers/net/net_failover.c

File Facts

System
Linux kernel
Corpus path
drivers/net/net_failover.c
Extension
.c
Size
23536 bytes
Lines
824
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

const struct net_device_ops *ops = primary_dev->netdev_ops;

		if (ops->ndo_select_queue)
			txq = ops->ndo_select_queue(primary_dev, skb, sb_dev);
		else
			txq = netdev_pick_tx(primary_dev, skb, NULL);
	} else {
		txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
	}

	/* Save the original txq to restore before passing to the driver */
	qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;

	if (unlikely(txq >= dev->real_num_tx_queues)) {
		do {
			txq -= dev->real_num_tx_queues;
		} while (txq >= dev->real_num_tx_queues);
	}

	return txq;
}

/* fold stats, assuming all rtnl_link_stats64 fields are u64, but
 * that some drivers can provide 32bit values only.
 */
static void net_failover_fold_stats(struct rtnl_link_stats64 *_res,
				    const struct rtnl_link_stats64 *_new,
				    const struct rtnl_link_stats64 *_old)
{
	const u64 *new = (const u64 *)_new;
	const u64 *old = (const u64 *)_old;
	u64 *res = (u64 *)_res;
	int i;

	for (i = 0; i < sizeof(*_res) / sizeof(u64); i++) {
		u64 nv = new[i];
		u64 ov = old[i];
		s64 delta = nv - ov;

		/* detects if this particular field is 32bit only */
		if (((nv | ov) >> 32) == 0)
			delta = (s64)(s32)((u32)nv - (u32)ov);

		/* filter anomalies, some drivers reset their stats
		 * at down/up events.
		 */
		if (delta > 0)
			res[i] += delta;
	}
}

static void net_failover_get_stats(struct net_device *dev,
				   struct rtnl_link_stats64 *stats)
{
	struct net_failover_info *nfo_info = netdev_priv(dev);
	const struct rtnl_link_stats64 *new;
	struct rtnl_link_stats64 temp;
	struct net_device *slave_dev;

	spin_lock(&nfo_info->stats_lock);
	memcpy(stats, &nfo_info->failover_stats, sizeof(*stats));

	rcu_read_lock();

	slave_dev = rcu_dereference(nfo_info->primary_dev);
	if (slave_dev) {
		new = dev_get_stats(slave_dev, &temp);
		net_failover_fold_stats(stats, new, &nfo_info->primary_stats);
		memcpy(&nfo_info->primary_stats, new, sizeof(*new));
	}

	slave_dev = rcu_dereference(nfo_info->standby_dev);
	if (slave_dev) {
		new = dev_get_stats(slave_dev, &temp);
		net_failover_fold_stats(stats, new, &nfo_info->standby_stats);
		memcpy(&nfo_info->standby_stats, new, sizeof(*new));
	}

	rcu_read_unlock();

	memcpy(&nfo_info->failover_stats, stats, sizeof(*stats));
	spin_unlock(&nfo_info->stats_lock);
}

static int net_failover_change_mtu(struct net_device *dev, int new_mtu)
{
	struct net_failover_info *nfo_info = netdev_priv(dev);
	struct net_device *primary_dev, *standby_dev;
	int ret = 0;

Annotation

Implementation Notes