Skip to contentSkip to conversation

Tools: hv: kvp

PATCH In review K. Y. Srinivasan 2 participants 9 messages Sep 5, 2012 – Nov 23, 2012 Hyper-V/Azure core and drivers

lore
Share & tools
lore
#0 lore raw

v5 cover Tools: hv: kvp

This is a resubmission of the subset of the patches that were not accepted in an earlier submission. The only change in this patchset (relative to the previous version - V4) is that the example script for retrieving DHCP state prints the string "Disabled" to indicate that DHCP is not enabled. This was based on Greg's feedback.

K. Y. Srinivasan (6):
Tools: hv: Add an example script to retrieve dhcp state
Tools: hv: Gather DHCP information
Tools: hv: Add an example script to configure an interface
Tools: hv: Implement the KVP verb - KVP_OP_SET_IP_INFO
Tools: hv: Rename the function kvp_get_ip_address()
Tools: hv: Implement the KVP verb - KVP_OP_GET_IP_INFO

 include/linux/hyperv.h       |    2 +
 tools/hv/hv_get_dhcp_info.sh |   28 ++
 tools/hv/hv_kvp_daemon.c     |  573 +++++++++++++++++++++++++++++++++++++++++-
 tools/hv/hv_set_ifconfig.sh  |   68 +++++
 4 files changed, 665 insertions(+), 6 deletions(-)
 create mode 100755 tools/hv/hv_get_dhcp_info.sh
 create mode 100755 tools/hv/hv_set_ifconfig.sh
Signature · 1 line
1.7.4.1
#1 lore raw

PATCH v5 1/6 Tools: hv: Add an example script to retrieve dhcp state

To keep the KVP daemon code free of distro specific details, we invoke an external script to retrieve the DHCP state. This is an example script that was used to test the KVP code. This script has to be implemented in a Distro specific fashion. For instance on distros that ship with Network Manager enabled, this script can be based on NM APIs.

---
 tools/hv/hv_get_dhcp_info.sh |   28 ++++++++++++++++++++++++++++
 1 files changed, 28 insertions(+), 0 deletions(-)
 create mode 100755 tools/hv/hv_get_dhcp_info.sh
tools/hv/hv_get_dhcp_info.sh new file +28 -0
new file mode 100755
index 0000000..ccd3e95
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This example script retrieves the DHCP state of a given interface.
+# In the interest of keeping the KVP daemon code free of distro specific
+# information; the kvp daemon code invokes this external script to gather
+# DHCP setting for the specific interface.
+#
+# Input: Name of the interface
+#
+# Output: The script prints the string "Enabled" to stdout to indicate
+#	that DHCP is enabled on the interface. If DHCP is not enabled,
+#	the script prints the string "Disabled" to stdout.
+#
+# Each Distro is expected to implement this script in a distro specific
+# fashion. For instance on Distros that ship with Network Manager enabled,
+# this script can be based on the Network Manager APIs for retrieving DHCP
+# information.
+
+if_file="/etc/sysconfig/network-scripts/ifcfg-"$1
+
+dhcp=$(grep "dhcp" $if_file 2>/dev/null)
+
+if [ "$dhcp" != "" ];
+then
+echo "Enabled"
+else
+echo "Disabled"
+fi
Signature · 1 line
1.7.4.1
#2 lore raw

PATCH v5 2/6 Tools: hv: Gather DHCP information

Collect information on dhcp setting for the specified interface. We invoke an external (Distro specific) script to get this information.

---
 tools/hv/hv_kvp_daemon.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)
tools/hv/hv_kvp_daemon.c +31 -0
index cfa23a1..6fb2c1c 100644
@@ -524,6 +524,9 @@ static void kvp_get_ipconfig_info(char *if_name,
 				 struct hv_kvp_ipaddr_value *buffer)
 {
 	char cmd[512];
+	char dhcp_info[128];
+	char *p;
+	FILE *file;
 
 	/*
 	 * Get the address of default gateway (ipv4).
@@ -572,6 +575,34 @@ static void kvp_get_ipconfig_info(char *if_name,
 	 */
 	kvp_process_ipconfig_file(cmd, (char *)buffer->dns_addr,
 				(MAX_IP_ADDR_SIZE * 2), INET_ADDRSTRLEN, 0);
+
+	/*
+	 * Gather the DHCP state.
+	 * We will gather this state by invoking an external script.
+	 * The parameter to the script is the interface name.
+	 * Here is the expected output:
+	 *
+	 * Enabled: DHCP enabled.
+	 */
+
+	sprintf(cmd, "%s %s", "hv_get_dhcp_info", if_name);
+
+	file = popen(cmd, "r");
+	if (file == NULL)
+		return;
+
+	p = fgets(dhcp_info, sizeof(dhcp_info), file);
+	if (p == NULL) {
+		pclose(file);
+		return;
+	}
+
+	if (!strncmp(p, "Enabled", 7))
+		buffer->dhcp_enabled = 1;
+	else
+		buffer->dhcp_enabled = 0;
+
+	pclose(file);
 }
 
 
Signature · 1 line
1.7.4.1
#3 lore raw

PATCH v5 3/6 Tools: hv: Add an example script to configure an interface

In reply to K. Y. Srinivasan

To keep the KVP daemon code free of distro specific details, we invoke an external script to configure the interface. This is an example script that was used to test the KVP code. This script has to be implemented in a Distro specific fashion. For instance on distros that ship with Network Manager enabled, this script can be based on NM APIs.

---
 tools/hv/hv_set_ifconfig.sh |   68 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 68 insertions(+), 0 deletions(-)
 create mode 100755 tools/hv/hv_set_ifconfig.sh
tools/hv/hv_set_ifconfig.sh new file +68 -0
new file mode 100755
index 0000000..3e9427e
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+# This example script activates an interface based on the specified
+# configuration.
+#
+# In the interest of keeping the KVP daemon code free of distro specific
+# information; the kvp daemon code invokes this external script to configure
+# the interface.
+#
+# The only argument to this script is the configuration file that is to
+# be used to configure the interface.
+#
+# Each Distro is expected to implement this script in a distro specific
+# fashion. For instance on Distros that ship with Network Manager enabled,
+# this script can be based on the Network Manager APIs for configuring the
+# interface.
+#
+# This example script is based on a RHEL environment.
+#
+# Here is the format of the ip configuration file:
+#
+# HWADDR=macaddr
+# IF_NAME=interface name
+# DHCP=yes (This is optional; if yes, DHCP is configured)
+#
+# IPADDR=ipaddr1
+# IPADDR_1=ipaddr2
+# IPADDR_x=ipaddry (where y = x + 1)
+#
+# NETMASK=netmask1
+# NETMASK_x=netmasky (where y = x + 1)
+#
+# GATEWAY=ipaddr1
+# GATEWAY_x=ipaddry (where y = x + 1)
+#
+# DNSx=ipaddrx (where first DNS address is tagged as DNS1 etc)
+#
+# IPV6 addresses will be tagged as IPV6ADDR, IPV6 gateway will be
+# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
+# IPV6NETMASK.
+#
+# The host can specify multiple ipv4 and ipv6 addresses to be
+# configured for the interface. Furthermore, the configuration
+# needs to be persistent. A subsequent GET call on the interface
+# is expected to return the configuration that is set via the SET
+# call.
+#
+
+
+
+echo "IPV6INIT=yes" >> $1
+echo "NM_CONTROLLED=no" >> $1
+echo "PEERDNS=yes" >> $1
+echo "ONBOOT=yes" >> $1
+
+dhcp=$(grep "DHCP" $1 2>/dev/null)
+if [ "$dhcp" != "" ];
+then
+echo "BOOTPROTO=dhcp" >> $1;
+fi
+
+cp $1 /etc/sysconfig/network-scripts/
+
+
+interface=$(echo $1 | awk -F - '{ print $2 }')
+
+/sbin/ifdown $interface 2>/dev/null
+/sbin/ifup $interfac 2>/dev/null
Signature · 1 line
1.7.4.1
#4 lore raw

Re: [PATCH V5 3/6] Tools: hv: Add an example script to configure an interface

Quoted 6 lines · K. Y. Srinivasan

To keep the KVP daemon code free of distro specific details, we invoke an external script to configure the interface. This is an example script that was used to test the KVP code. This script has to be implemented in a Distro specific fashion. For instance on distros that ship with Network Manager enabled, this script can be based on NM APIs.

Quoted 6 lines
---
 tools/hv/hv_set_ifconfig.sh |   68 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 68 insertions(+), 0 deletions(-)
 create mode 100755 tools/hv/hv_set_ifconfig.sh

This already went in, but I overlooked this part:

Quoted 1 line

+# GATEWAY=ipaddr1

I guest GATEWAY means the default gateway.

Quoted 1 line

+# GATEWAY_x=ipaddry (where y = x + 1)

How can there be multiple gateways?
Or: What does GATEWAY_n mean here?

Olaf

#5 lore raw

RE: [PATCH V5 3/6] Tools: hv: Add an example script to configure an interface

Quoted 31 lines

-----Original Message-----
From: Olaf Hering [mailto:[email protected]]
Sent: Thursday, November 22, 2012 4:13 PM
To: KY Srinivasan
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]
Subject: Re: [PATCH V5 3/6] Tools: hv: Add an example script to configure an interface

Quoted 4 lines · K. Y. Srinivasan

To keep the KVP daemon code free of distro specific details, we invoke an external script to configure the interface. This is an example script that was used to test the KVP code. This script has to be implemented in a Distro specific fashion. For instance on distros that ship with Network Manager

enabled,

Quoted 6 lines

this script can be based on NM APIs.

---
 tools/hv/hv_set_ifconfig.sh |   68

+++++++++++++++++++++++++++++++++++++++++++

Quoted 2 lines
 1 files changed, 68 insertions(+), 0 deletions(-)
 create mode 100755 tools/hv/hv_set_ifconfig.sh

This already went in, but I overlooked this part:

Quoted 9 lines
Quoted 1 line

+# GATEWAY=ipaddr1

I guest GATEWAY means the default gateway.

Quoted 1 line

+# GATEWAY_x=ipaddry (where y = x + 1)

How can there be multiple gateways?
Or: What does GATEWAY_n mean here?

Olaf,

On windows, we can support multiple default gateways (I think). This is really implementing the host protocol. Minimally we can have an ipv4 default and an ipv6 default gateway.

Hope this helps,

Regards,

K. Y

���{.n�+�������+%�����ݶ��w��{.n�+����{��G�����{ay�ʇڙ�,j��f���h��������z_�(�階�ݢj"���m������G������?����&���~��iO��z��v�^�m���� ������?�I�

#6 lore raw

PATCH v5 4/6 Tools: hv: Implement the KVP verb - KVP_OP_SET_IP_INFO

In reply to K. Y. Srinivasan

Implement the KVP verb - KVP_OP_SET_IP_INFO. This operation configures the specified interface based on the given configuration. Since configuring an interface is very distro specific, we invoke an external (Distro specific) script to configure the interface.

---
 include/linux/hyperv.h   |    2 +
 tools/hv/hv_kvp_daemon.c |  443 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 445 insertions(+), 0 deletions(-)
include/linux/hyperv.h +2 -0
index 7585d55..e73b852 100644
@@ -191,6 +191,8 @@ enum hv_kvp_exchg_pool {
 #define HV_ERROR_NOT_SUPPORTED		0x80070032
 #define HV_ERROR_MACHINE_LOCKED		0x800704F7
 #define HV_ERROR_DEVICE_NOT_CONNECTED	0x8007048F
+#define HV_INVALIDARG			0x80070057
+#define HV_GUID_NOTFOUND		0x80041002
 
 #define ADDR_FAMILY_NONE	0x00
 #define ADDR_FAMILY_IPV4	0x01
tools/hv/hv_kvp_daemon.c +443 -0

491 lines not on this page · raw message

Signature · 1 line
1.7.4.1
#7 lore raw

PATCH v5 5/6 Tools: hv: Rename the function kvp_get_ip_address()

In reply to K. Y. Srinivasan

Rename the function kvp_get_ip_address() to better reflect the functionality being implemented.

---
 tools/hv/hv_kvp_daemon.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
tools/hv/hv_kvp_daemon.c +3 -3
index ac144b9..849c438 100644
@@ -765,7 +765,7 @@ static int kvp_process_ip_address(void *addrp,
 }
 
 static int
-kvp_get_ip_address(int family, char *if_name, int op,
+kvp_get_ip_info(int family, char *if_name, int op,
 		 void  *out_buffer, int length)
 {
 	struct ifaddrs *ifap;
@@ -1468,12 +1468,12 @@ int main(void)
 			strcpy(key_value, lic_version);
 			break;
 		case NetworkAddressIPv4:
-			kvp_get_ip_address(AF_INET, NULL, KVP_OP_ENUMERATE,
+			kvp_get_ip_info(AF_INET, NULL, KVP_OP_ENUMERATE,
 				key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
 			strcpy(key_name, "NetworkAddressIPv4");
 			break;
 		case NetworkAddressIPv6:
-			kvp_get_ip_address(AF_INET6, NULL, KVP_OP_ENUMERATE,
+			kvp_get_ip_info(AF_INET6, NULL, KVP_OP_ENUMERATE,
 				key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
 			strcpy(key_name, "NetworkAddressIPv6");
 			break;
Signature · 1 line
1.7.4.1
#8 lore raw

PATCH v5 6/6 Tools: hv: Implement the KVP verb - KVP_OP_GET_IP_INFO

In reply to K. Y. Srinivasan

Now implement the KVP verb - KVP_OP_GET_IP_INFO. This operation retrieves IP information for the specified interface.

---
 tools/hv/hv_kvp_daemon.c |   93 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 90 insertions(+), 3 deletions(-)
tools/hv/hv_kvp_daemon.c +90 -3
index 849c438..c8e1013 100644
@@ -603,6 +603,69 @@ static char *kvp_if_name_to_mac(char *if_name)
 }
 
 
+/*
+ * 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, *q, *x;
+	char    *if_name = NULL;
+	char    buf[256];
+	char *kvp_net_dir = "/sys/class/net/";
+	char dev_id[256];
+	int i;
+
+	dir = opendir(kvp_net_dir);
+	if (dir == NULL)
+		return NULL;
+
+	snprintf(dev_id, sizeof(dev_id), kvp_net_dir);
+	q = dev_id + strlen(kvp_net_dir);
+
+	while ((entry = readdir(dir)) != NULL) {
+		/*
+		 * Set the state for the next pass.
+		 */
+		*q = '\0';
+
+		strcat(dev_id, entry->d_name);
+		strcat(dev_id, "/address");
+
+		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, int len,
 					int element_size, int offset)
@@ -749,10 +812,10 @@ static int kvp_process_ip_address(void *addrp,
 	}
 
 	if ((length - *offset) < addr_length + 1)
-		return 1;
+		return HV_E_FAIL;
 	if (str == NULL) {
 		strcpy(buffer, "inet_ntop failed\n");
-		return 1;
+		return HV_E_FAIL;
 	}
 	if (*offset == 0)
 		strcpy(buffer, tmp);
@@ -796,7 +859,7 @@ kvp_get_ip_info(int family, char *if_name, int op,
 
 	if (getifaddrs(&ifap)) {
 		strcpy(buffer, "getifaddrs failed\n");
-		return 1;
+		return HV_E_FAIL;
 	}
 
 	curp = ifap;
@@ -1386,6 +1449,30 @@ int main(void)
 		}
 
 		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));
+
+			if (error)
+				hv_msg->error = error;
+
+			free(if_name);
+			break;
+
 		case KVP_OP_SET_IP_INFO:
 			kvp_ip_val = &hv_msg->body.kvp_ip_val;
 			if_name = kvp_get_if_name(
Signature · 1 line
1.7.4.1