net/openvswitch/vport-netdev.c

Source file repositories/reference/linux-study-clean/net/openvswitch/vport-netdev.c

File Facts

System
Linux kernel
Corpus path
net/openvswitch/vport-netdev.c
Extension
.c
Size
6206 bytes
Lines
255
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration 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

ovs_is_internal_dev(vport->dev)) {
		err = -EINVAL;
		goto error_put;
	}

	return ovs_netdev_link(vport, false);
error_put:
	netdev_put(vport->dev, &vport->dev_tracker);
error_free_vport:
	ovs_vport_free(vport);
	return ERR_PTR(err);
}

static void vport_netdev_free(struct rcu_head *rcu)
{
	struct vport *vport = container_of(rcu, struct vport, rcu);

	netdev_put(vport->dev, &vport->dev_tracker);
	ovs_vport_free(vport);
}

void ovs_netdev_detach_dev(struct vport *vport)
{
	ASSERT_RTNL();
	netdev_rx_handler_unregister(vport->dev);
	netdev_upper_dev_unlink(vport->dev,
				netdev_master_upper_dev_get(vport->dev));
	dev_set_promiscuity(vport->dev, -1);

	/* paired with smp_mb() in netdev_destroy() */
	smp_wmb();

	vport->dev->priv_flags &= ~IFF_OVS_DATAPATH;
}

static void netdev_destroy(struct vport *vport)
{
	/* When called from ovs_db_notify_wq() after a dp_device_event(), the
	 * port has already been detached, so we can avoid taking the RTNL by
	 * checking this first.
	 */
	if (netif_is_ovs_port(vport->dev)) {
		rtnl_lock();
		/* Check again while holding the lock to ensure we don't race
		 * with the netdev notifier and detach twice.
		 */
		if (netif_is_ovs_port(vport->dev))
			ovs_netdev_detach_dev(vport);
		rtnl_unlock();
	}

	/* paired with smp_wmb() in ovs_netdev_detach_dev() */
	smp_mb();

	call_rcu(&vport->rcu, vport_netdev_free);
}

void ovs_netdev_tunnel_destroy(struct vport *vport)
{
	rtnl_lock();
	if (netif_is_ovs_port(vport->dev))
		ovs_netdev_detach_dev(vport);

	/* We can be invoked by both explicit vport deletion and
	 * underlying netdev deregistration; delete the link only
	 * if it's not already shutting down.
	 */
	if (vport->dev->reg_state == NETREG_REGISTERED)
		rtnl_delete_link(vport->dev, 0, NULL);

	/* We can't put the device reference yet, since it can still be in
	 * use, but rtnl_unlock()->netdev_run_todo() will block until all
	 * the references are released, so the RCU call must be before it.
	 */
	call_rcu(&vport->rcu, vport_netdev_free);
	rtnl_unlock();
}
EXPORT_SYMBOL_GPL(ovs_netdev_tunnel_destroy);

/* Returns null if this device is not attached to a datapath. */
struct vport *ovs_netdev_get_vport(struct net_device *dev)
{
	if (likely(netif_is_ovs_port(dev)))
		return (struct vport *)
			rcu_dereference_rtnl(dev->rx_handler_data);
	else
		return NULL;
}

static struct vport_ops ovs_netdev_vport_ops = {

Annotation

Implementation Notes