Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d814b67e authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'hv_netvsc-Fix-send-indirection-table-offset'



Haiyang Zhang says:

====================
hv_netvsc: Fix send indirection table offset

Fix send indirection table offset issues related to guest and
host bugs.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 35fc59c9 171c1fd9
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -609,7 +609,8 @@ struct nvsp_5_send_indirect_table {
	/* The number of entries in the send indirection table */
	u32 count;

	/* The offset of the send indirection table from top of this struct.
	/* The offset of the send indirection table from the beginning of
	 * struct nvsp_message.
	 * The send indirection table tells which channel to put the send
	 * traffic on. Each entry is a channel number.
	 */
+30 −8
Original line number Diff line number Diff line
@@ -1178,20 +1178,39 @@ static int netvsc_receive(struct net_device *ndev,
}

static void netvsc_send_table(struct net_device *ndev,
			      const struct nvsp_message *nvmsg)
			      struct netvsc_device *nvscdev,
			      const struct nvsp_message *nvmsg,
			      u32 msglen)
{
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	u32 count, *tab;
	u32 count, offset, *tab;
	int i;

	count = nvmsg->msg.v5_msg.send_table.count;
	offset = nvmsg->msg.v5_msg.send_table.offset;

	if (count != VRSS_SEND_TAB_SIZE) {
		netdev_err(ndev, "Received wrong send-table size:%u\n", count);
		return;
	}

	tab = (u32 *)((unsigned long)&nvmsg->msg.v5_msg.send_table +
		      nvmsg->msg.v5_msg.send_table.offset);
	/* If negotiated version <= NVSP_PROTOCOL_VERSION_6, the offset may be
	 * wrong due to a host bug. So fix the offset here.
	 */
	if (nvscdev->nvsp_version <= NVSP_PROTOCOL_VERSION_6 &&
	    msglen >= sizeof(struct nvsp_message_header) +
	    sizeof(union nvsp_6_message_uber) + count * sizeof(u32))
		offset = sizeof(struct nvsp_message_header) +
			 sizeof(union nvsp_6_message_uber);

	/* Boundary check for all versions */
	if (offset > msglen - count * sizeof(u32)) {
		netdev_err(ndev, "Received send-table offset too big:%u\n",
			   offset);
		return;
	}

	tab = (void *)nvmsg + offset;

	for (i = 0; i < count; i++)
		net_device_ctx->tx_table[i] = tab[i];
@@ -1210,11 +1229,13 @@ static void netvsc_send_vf(struct net_device *ndev,
}

static void netvsc_receive_inband(struct net_device *ndev,
				   const struct nvsp_message *nvmsg)
				  struct netvsc_device *nvscdev,
				  const struct nvsp_message *nvmsg,
				  u32 msglen)
{
	switch (nvmsg->hdr.msg_type) {
	case NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE:
		netvsc_send_table(ndev, nvmsg);
		netvsc_send_table(ndev, nvscdev, nvmsg, msglen);
		break;

	case NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION:
@@ -1232,6 +1253,7 @@ static int netvsc_process_raw_pkt(struct hv_device *device,
{
	struct vmbus_channel *channel = nvchan->channel;
	const struct nvsp_message *nvmsg = hv_pkt_data(desc);
	u32 msglen = hv_pkt_datalen(desc);

	trace_nvsp_recv(ndev, channel, nvmsg);

@@ -1247,7 +1269,7 @@ static int netvsc_process_raw_pkt(struct hv_device *device,
		break;

	case VM_PKT_DATA_INBAND:
		netvsc_receive_inband(ndev, nvmsg);
		netvsc_receive_inband(ndev, net_device, nvmsg, msglen);
		break;

	default: