net/ncsi/ncsi-cmd.c

Source file repositories/reference/linux-study-clean/net/ncsi/ncsi-cmd.c

File Facts

System
Linux kernel
Corpus path
net/ncsi/ncsi-cmd.c
Extension
.c
Size
10496 bytes
Lines
409
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

if (ncsi_cmd_handlers[i].type == type) {
			if (ncsi_cmd_handlers[i].handler)
				nch = &ncsi_cmd_handlers[i];
			else
				nch = NULL;

			break;
		}
	}

	if (!nch) {
		netdev_err(nca->ndp->ndev.dev,
			   "Cannot send packet with type 0x%02x\n", nca->type);
		return -ENOENT;
	}

	/* Get packet payload length and allocate the request
	 * It is expected that if length set as negative in
	 * handler structure means caller is initializing it
	 * and setting length in nca before calling xmit function
	 */
	if (nch->payload >= 0)
		nca->payload = nch->payload;
	nr = ncsi_alloc_command(nca);
	if (!nr)
		return -ENOMEM;

	/* track netlink information */
	if (nca->req_flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) {
		nr->snd_seq = nca->info->snd_seq;
		nr->snd_portid = nca->info->snd_portid;
		nr->nlhdr = *nca->info->nlhdr;
	}

	/* Prepare the packet */
	nca->id = nr->id;
	ret = nch->handler(nr->cmd, nca);
	if (ret) {
		ncsi_free_request(nr);
		return ret;
	}

	/* Fill the ethernet header */
	eh = skb_push(nr->cmd, sizeof(*eh));
	eh->h_proto = htons(ETH_P_NCSI);
	eth_broadcast_addr(eh->h_dest);

	/* If mac address received from device then use it for
	 * source address as unicast address else use broadcast
	 * address as source address
	 */
	if (nca->ndp->gma_flag == 1)
		memcpy(eh->h_source, nca->ndp->ndev.dev->dev_addr, ETH_ALEN);
	else
		eth_broadcast_addr(eh->h_source);

	/* Start the timer for the request that might not have
	 * corresponding response. Given NCSI is an internal
	 * connection a 1 second delay should be sufficient.
	 */
	nr->enabled = true;
	mod_timer(&nr->timer, jiffies + 1 * HZ);

	/* Send NCSI packet */
	skb_get(nr->cmd);
	ret = dev_queue_xmit(nr->cmd);
	if (ret < 0) {
		ncsi_free_request(nr);
		return ret;
	}

	return 0;
}

Annotation

Implementation Notes