net/core/dev_addr_lists.c

Source file repositories/reference/linux-study-clean/net/core/dev_addr_lists.c

File Facts

System
Linux kernel
Corpus path
net/core/dev_addr_lists.c
Extension
.c
Size
38862 bytes
Lines
1484
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 = dev->netdev_ops;
	int promisc_inc;
	int err;

	might_sleep();
	netdev_assert_locked_ops_compat(dev);

	__hw_addr_init(&uc_snap);
	__hw_addr_init(&mc_snap);
	__hw_addr_init(&uc_ref);
	__hw_addr_init(&mc_ref);

	if (!(dev->flags & IFF_UP) || !netif_device_present(dev))
		return;

	if (ops->ndo_set_rx_mode_async) {
		netif_addr_lock_bh(dev);
		err = netif_addr_lists_snapshot(dev, &uc_snap, &mc_snap,
						&uc_ref, &mc_ref);
		if (err) {
			netif_addr_unlock_bh(dev);
			netif_rx_mode_schedule_retry(dev);
			return;
		}

		promisc_inc = netif_uc_promisc_update(dev);
		netif_addr_unlock_bh(dev);
	} else {
		netif_addr_lock_bh(dev);
		promisc_inc = netif_uc_promisc_update(dev);
		netif_addr_unlock_bh(dev);
	}

	if (promisc_inc)
		__dev_set_promiscuity(dev, promisc_inc, false);

	if (ops->ndo_set_rx_mode_async) {
		err = ops->ndo_set_rx_mode_async(dev, &uc_snap, &mc_snap);

		netif_addr_lock_bh(dev);
		netif_addr_lists_reconcile(dev, &uc_snap, &mc_snap,
					   &uc_ref, &mc_ref);
		netif_addr_unlock_bh(dev);

		if (err)
			netif_rx_mode_schedule_retry(dev);
		else
			dev->rx_mode_retry_count = 0;
	} else if (ops->ndo_set_rx_mode) {
		netif_addr_lock_bh(dev);
		ops->ndo_set_rx_mode(dev);
		netif_addr_unlock_bh(dev);
	}
}

static void netdev_rx_mode_work(struct work_struct *work)
{
	struct net_device *dev;

	rtnl_lock();

	while (true) {
		spin_lock_bh(&rx_mode_lock);
		if (list_empty(&rx_mode_list)) {
			spin_unlock_bh(&rx_mode_lock);
			break;
		}
		dev = list_first_entry(&rx_mode_list, struct net_device,
				       rx_mode_node);
		list_del_init(&dev->rx_mode_node);
		/* We must free netdev tracker under
		 * the spinlock protection.
		 */
		netdev_tracker_free(dev, &dev->rx_mode_tracker);
		spin_unlock_bh(&rx_mode_lock);

		netdev_lock_ops(dev);
		netif_rx_mode_run(dev);
		netdev_unlock_ops(dev);
		/* Use __dev_put() because netdev_tracker_free() was already
		 * called above. Must be after netdev_unlock_ops() to prevent
		 * netdev_run_todo() from freeing the device while still in use.
		 */
		__dev_put(dev);
	}

	rtnl_unlock();
}

static void netif_rx_mode_queue(struct net_device *dev)

Annotation

Implementation Notes