aboutsummaryrefslogtreecommitdiffstats
path: root/tools/hv
diff options
context:
space:
mode:
authorHaiyang Zhang <haiyangz@microsoft.com>2018-03-05 00:17:11 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-03-06 12:57:16 -0500
commit4ba6341286f20d3b300a8f159aa2a61eca0f4b17 (patch)
treef7e7dcf98e61e81b38c1a164492819d4c38abd98 /tools/hv
parent661e50bc853209e41a5c14a290ca4decc43cbfd1 (diff)
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: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'tools/hv')
-rw-r--r--tools/hv/hv_kvp_daemon.c138
1 files changed, 65 insertions, 73 deletions
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 4c99c57736ce..dbf6e8bd98ba 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -634,64 +634,6 @@ static char *kvp_if_name_to_mac(char *if_name)
634 return mac_addr; 634 return mac_addr;
635} 635}
636 636
637
638/*
639 * Retrieve the interface name given tha MAC address.
640 */
641
642static char *kvp_mac_to_if_name(char *mac)
643{
644 DIR *dir;
645 struct dirent *entry;
646 FILE *file;
647 char *p, *x;
648 char *if_name = NULL;
649 char buf[256];
650 char dev_id[PATH_MAX];
651 unsigned int i;
652
653 dir = opendir(KVP_NET_DIR);
654 if (dir == NULL)
655 return NULL;
656
657 while ((entry = readdir(dir)) != NULL) {
658 /*
659 * Set the state for the next pass.
660 */
661 snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR,
662 entry->d_name);
663
664 file = fopen(dev_id, "r");
665 if (file == NULL)
666 continue;
667
668 p = fgets(buf, sizeof(buf), file);
669 if (p) {
670 x = strchr(p, '\n');
671 if (x)
672 *x = '\0';
673
674 for (i = 0; i < strlen(p); i++)
675 p[i] = toupper(p[i]);
676
677 if (!strcmp(p, mac)) {
678 /*
679 * Found the MAC match; return the interface
680 * name. The caller will free the memory.
681 */
682 if_name = strdup(entry->d_name);
683 fclose(file);
684 break;
685 }
686 }
687 fclose(file);
688 }
689
690 closedir(dir);
691 return if_name;
692}
693
694
695static void kvp_process_ipconfig_file(char *cmd, 637static void kvp_process_ipconfig_file(char *cmd,
696 char *config_buf, unsigned int len, 638 char *config_buf, unsigned int len,
697 int element_size, int offset) 639 int element_size, int offset)
@@ -997,6 +939,70 @@ getaddr_done:
997 return error; 939 return error;
998} 940}
999 941
942/*
943 * Retrieve the IP given the MAC address.
944 */
945static int kvp_mac_to_ip(struct hv_kvp_ipaddr_value *kvp_ip_val)
946{
947 char *mac = (char *)kvp_ip_val->adapter_id;
948 DIR *dir;
949 struct dirent *entry;
950 FILE *file;
951 char *p, *x;
952 char *if_name = NULL;
953 char buf[256];
954 char dev_id[PATH_MAX];
955 unsigned int i;
956 int error = HV_E_FAIL;
957
958 dir = opendir(KVP_NET_DIR);
959 if (dir == NULL)
960 return HV_E_FAIL;
961
962 while ((entry = readdir(dir)) != NULL) {
963 /*
964 * Set the state for the next pass.
965 */
966 snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR,
967 entry->d_name);
968
969 file = fopen(dev_id, "r");
970 if (file == NULL)
971 continue;
972
973 p = fgets(buf, sizeof(buf), file);
974 fclose(file);
975 if (!p)
976 continue;
977
978 x = strchr(p, '\n');
979 if (x)
980 *x = '\0';
981
982 for (i = 0; i < strlen(p); i++)
983 p[i] = toupper(p[i]);
984
985 if (strcmp(p, mac))
986 continue;
987
988 /*
989 * Found the MAC match.
990 * A NIC (e.g. VF) matching the MAC, but without IP, is skipped.
991 */
992 if_name = entry->d_name;
993 if (!if_name)
994 continue;
995
996 error = kvp_get_ip_info(0, if_name, KVP_OP_GET_IP_INFO,
997 kvp_ip_val, MAX_IP_ADDR_SIZE * 2);
998
999 if (!error && strlen((char *)kvp_ip_val->ip_addr))
1000 break;
1001 }
1002
1003 closedir(dir);
1004 return error;
1005}
1000 1006
1001static int expand_ipv6(char *addr, int type) 1007static int expand_ipv6(char *addr, int type)
1002{ 1008{
@@ -1472,26 +1478,12 @@ int main(int argc, char *argv[])
1472 switch (op) { 1478 switch (op) {
1473 case KVP_OP_GET_IP_INFO: 1479 case KVP_OP_GET_IP_INFO:
1474 kvp_ip_val = &hv_msg->body.kvp_ip_val; 1480 kvp_ip_val = &hv_msg->body.kvp_ip_val;
1475 if_name =
1476 kvp_mac_to_if_name((char *)kvp_ip_val->adapter_id);
1477 1481
1478 if (if_name == NULL) { 1482 error = kvp_mac_to_ip(kvp_ip_val);
1479 /*
1480 * We could not map the mac address to an
1481 * interface name; return error.
1482 */
1483 hv_msg->error = HV_E_FAIL;
1484 break;
1485 }
1486 error = kvp_get_ip_info(
1487 0, if_name, KVP_OP_GET_IP_INFO,
1488 kvp_ip_val,
1489 (MAX_IP_ADDR_SIZE * 2));
1490 1483
1491 if (error) 1484 if (error)
1492 hv_msg->error = error; 1485 hv_msg->error = error;
1493 1486
1494 free(if_name);
1495 break; 1487 break;
1496 1488
1497 case KVP_OP_SET_IP_INFO: 1489 case KVP_OP_SET_IP_INFO: