net/mctp/device.c

Source file repositories/reference/linux-study-clean/net/mctp/device.c

File Facts

System
Linux kernel
Corpus path
net/mctp/device.c
Extension
.c
Size
12503 bytes
Lines
563
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

struct mctp_dump_cb {
	unsigned long ifindex;
	size_t a_idx;
};

/* unlocked: caller must hold rcu_read_lock.
 * Returned mctp_dev has its refcount incremented, or NULL if unset.
 */
struct mctp_dev *__mctp_dev_get(const struct net_device *dev)
{
	struct mctp_dev *mdev = rcu_dereference(dev->mctp_ptr);

	/* RCU guarantees that any mdev is still live.
	 * Zero refcount implies a pending free, return NULL.
	 */
	if (mdev)
		if (!refcount_inc_not_zero(&mdev->refs))
			return NULL;
	return mdev;
}

/* Returned mctp_dev does not have refcount incremented. The returned pointer
 * remains live while rtnl_lock is held, as that prevents mctp_unregister()
 */
struct mctp_dev *mctp_dev_get_rtnl(const struct net_device *dev)
{
	return rtnl_dereference(dev->mctp_ptr);
}

static int mctp_addrinfo_size(void)
{
	return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
		+ nla_total_size(1) // IFA_LOCAL
		+ nla_total_size(1) // IFA_ADDRESS
		;
}

/* flag should be NLM_F_MULTI for dump calls */
static int mctp_fill_addrinfo(struct sk_buff *skb,
			      struct mctp_dev *mdev, mctp_eid_t eid,
			      int msg_type, u32 portid, u32 seq, int flag)
{
	struct ifaddrmsg *hdr;
	struct nlmsghdr *nlh;

	nlh = nlmsg_put(skb, portid, seq,
			msg_type, sizeof(*hdr), flag);
	if (!nlh)
		return -EMSGSIZE;

	hdr = nlmsg_data(nlh);
	memset(hdr, 0, sizeof(*hdr));
	hdr->ifa_family = AF_MCTP;
	hdr->ifa_prefixlen = 0;
	hdr->ifa_flags = 0;
	hdr->ifa_scope = 0;
	hdr->ifa_index = mdev->dev->ifindex;

	if (nla_put_u8(skb, IFA_LOCAL, eid))
		goto cancel;

	if (nla_put_u8(skb, IFA_ADDRESS, eid))
		goto cancel;

	nlmsg_end(skb, nlh);

	return 0;

cancel:
	nlmsg_cancel(skb, nlh);
	return -EMSGSIZE;
}

static int mctp_dump_dev_addrinfo(struct mctp_dev *mdev, struct sk_buff *skb,
				  struct netlink_callback *cb)
{
	struct mctp_dump_cb *mcb = (void *)cb->ctx;
	u32 portid, seq;
	int rc = 0;

	portid = NETLINK_CB(cb->skb).portid;
	seq = cb->nlh->nlmsg_seq;
	for (; mcb->a_idx < mdev->num_addrs; mcb->a_idx++) {
		rc = mctp_fill_addrinfo(skb, mdev, mdev->addrs[mcb->a_idx],
					RTM_NEWADDR, portid, seq, NLM_F_MULTI);
		if (rc < 0)
			break;
	}

	return rc;

Annotation

Implementation Notes