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

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
......@@ -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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment