net/phonet/pn_dev.c

Source file repositories/reference/linux-study-clean/net/phonet/pn_dev.c

File Facts

System
Linux kernel
Corpus path
net/phonet/pn_dev.c
Extension
.c
Size
9942 bytes
Lines
442
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source 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

struct phonet_routes {
	spinlock_t		lock;
	struct net_device __rcu	*table[64];
};

struct phonet_net {
	struct phonet_device_list pndevs;
	struct phonet_routes routes;
};

static unsigned int phonet_net_id __read_mostly;

static struct phonet_net *phonet_pernet(struct net *net)
{
	return net_generic(net, phonet_net_id);
}

struct phonet_device_list *phonet_device_list(struct net *net)
{
	struct phonet_net *pnn = phonet_pernet(net);
	return &pnn->pndevs;
}

/* Allocate new Phonet device. */
static struct phonet_device *__phonet_device_alloc(struct net_device *dev)
{
	struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
	struct phonet_device *pnd = kmalloc_obj(*pnd, GFP_ATOMIC);
	if (pnd == NULL)
		return NULL;
	pnd->netdev = dev;
	bitmap_zero(pnd->addrs, 64);

	lockdep_assert_held(&pndevs->lock);
	list_add_rcu(&pnd->list, &pndevs->list);
	return pnd;
}

static struct phonet_device *__phonet_get(struct net_device *dev)
{
	struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
	struct phonet_device *pnd;

	lockdep_assert_held(&pndevs->lock);

	list_for_each_entry(pnd, &pndevs->list, list) {
		if (pnd->netdev == dev)
			return pnd;
	}
	return NULL;
}

static struct phonet_device *__phonet_get_rcu(struct net_device *dev)
{
	struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
	struct phonet_device *pnd;

	list_for_each_entry_rcu(pnd, &pndevs->list, list) {
		if (pnd->netdev == dev)
			return pnd;
	}
	return NULL;
}

static void phonet_device_destroy(struct net_device *dev)
{
	struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
	struct phonet_device *pnd;

	ASSERT_RTNL();

	spin_lock(&pndevs->lock);

	pnd = __phonet_get(dev);
	if (pnd)
		list_del_rcu(&pnd->list);

	spin_unlock(&pndevs->lock);

	if (pnd) {
		struct net *net = dev_net(dev);
		u32 ifindex = dev->ifindex;
		u8 addr;

		for_each_set_bit(addr, pnd->addrs, 64)
			phonet_address_notify(net, RTM_DELADDR, ifindex, addr);

		kfree_rcu(pnd, rcu);
	}
}

Annotation

Implementation Notes