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

Commit 4ba63412 authored by Haiyang Zhang's avatar Haiyang Zhang Committed by Greg Kroah-Hartman
Browse files

tools/hv: Fix IP reporting by KVP daemon with SRIOV



On Hyper-V the VF NIC has the same MAC as the related synthetic NIC.
VF NIC can work under the synthetic NIC transparently, without its
own IP address. The existing KVP daemon only gets IP from the first
NIC matching a MAC address, and may not be able to find the IP in
this case.

This patch fixes the problem by searching the NIC matching the MAC,
and having an IP address. So, the IP address will be found and
reported to the host successfully.

Signed-off-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 661e50bc
Loading
Loading
Loading
Loading
+65 −73
Original line number Diff line number Diff line
@@ -634,64 +634,6 @@ static char *kvp_if_name_to_mac(char *if_name)
	return mac_addr;
}


/*
 * Retrieve the interface name given tha MAC address.
 */

static char *kvp_mac_to_if_name(char *mac)
{
	DIR *dir;
	struct dirent *entry;
	FILE    *file;
	char    *p, *x;
	char    *if_name = NULL;
	char    buf[256];
	char dev_id[PATH_MAX];
	unsigned int i;

	dir = opendir(KVP_NET_DIR);
	if (dir == NULL)
		return NULL;

	while ((entry = readdir(dir)) != NULL) {
		/*
		 * Set the state for the next pass.
		 */
		snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR,
			 entry->d_name);

		file = fopen(dev_id, "r");
		if (file == NULL)
			continue;

		p = fgets(buf, sizeof(buf), file);
		if (p) {
			x = strchr(p, '\n');
			if (x)
				*x = '\0';

			for (i = 0; i < strlen(p); i++)
				p[i] = toupper(p[i]);

			if (!strcmp(p, mac)) {
				/*
				 * Found the MAC match; return the interface
				 * name. The caller will free the memory.
				 */
				if_name = strdup(entry->d_name);
				fclose(file);
				break;
			}
		}
		fclose(file);
	}

	closedir(dir);
	return if_name;
}


static void kvp_process_ipconfig_file(char *cmd,
					char *config_buf, unsigned int len,
					int element_size, int offset)
@@ -997,6 +939,70 @@ kvp_get_ip_info(int family, char *if_name, int op,
	return error;
}

/*
 * Retrieve the IP given the MAC address.
 */
static int kvp_mac_to_ip(struct hv_kvp_ipaddr_value *kvp_ip_val)
{
	char *mac = (char *)kvp_ip_val->adapter_id;
	DIR *dir;
	struct dirent *entry;
	FILE    *file;
	char    *p, *x;
	char    *if_name = NULL;
	char    buf[256];
	char dev_id[PATH_MAX];
	unsigned int i;
	int error = HV_E_FAIL;

	dir = opendir(KVP_NET_DIR);
	if (dir == NULL)
		return HV_E_FAIL;

	while ((entry = readdir(dir)) != NULL) {
		/*
		 * Set the state for the next pass.
		 */
		snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR,
			 entry->d_name);

		file = fopen(dev_id, "r");
		if (file == NULL)
			continue;

		p = fgets(buf, sizeof(buf), file);
		fclose(file);
		if (!p)
			continue;

		x = strchr(p, '\n');
		if (x)
			*x = '\0';

		for (i = 0; i < strlen(p); i++)
			p[i] = toupper(p[i]);

		if (strcmp(p, mac))
			continue;

		/*
		 * Found the MAC match.
		 * A NIC (e.g. VF) matching the MAC, but without IP, is skipped.
		 */
		if_name = entry->d_name;
		if (!if_name)
			continue;

		error = kvp_get_ip_info(0, if_name, KVP_OP_GET_IP_INFO,
					kvp_ip_val, MAX_IP_ADDR_SIZE * 2);

		if (!error && strlen((char *)kvp_ip_val->ip_addr))
			break;
	}

	closedir(dir);
	return error;
}

static int expand_ipv6(char *addr, int type)
{
@@ -1472,26 +1478,12 @@ int main(int argc, char *argv[])
		switch (op) {
		case KVP_OP_GET_IP_INFO:
			kvp_ip_val = &hv_msg->body.kvp_ip_val;
			if_name =
			kvp_mac_to_if_name((char *)kvp_ip_val->adapter_id);

			if (if_name == NULL) {
				/*
				 * We could not map the mac address to an
				 * interface name; return error.
				 */
				hv_msg->error = HV_E_FAIL;
				break;
			}
			error = kvp_get_ip_info(
						0, if_name, KVP_OP_GET_IP_INFO,
						kvp_ip_val,
						(MAX_IP_ADDR_SIZE * 2));
			error =  kvp_mac_to_ip(kvp_ip_val);

			if (error)
				hv_msg->error = error;

			free(if_name);
			break;

		case KVP_OP_SET_IP_INFO: