Drivers: hv: Add KVP definitions for IP address injection
K. Y. Srinivasan [Mon, 13 Aug 2012 17:06:51 +0000 (10:06 -0700)]
Add the necessary definitions for supporting the IP injection functionality.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: Olaf Hering <olaf@aepfle.de>
Reviewed-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

drivers/hv/hv_util.c
include/linux/hyperv.h
tools/hv/hv_kvp_daemon.c

index d3ac6a4..a0667de 100644 (file)
@@ -263,7 +263,7 @@ static int util_probe(struct hv_device *dev,
                (struct hv_util_service *)dev_id->driver_data;
        int ret;
 
-       srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       srv->recv_buffer = kmalloc(PAGE_SIZE * 2, GFP_KERNEL);
        if (!srv->recv_buffer)
                return -ENOMEM;
        if (srv->util_init) {
@@ -274,7 +274,7 @@ static int util_probe(struct hv_device *dev,
                }
        }
 
-       ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0,
+       ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
                        srv->util_cb, dev->channel);
        if (ret)
                goto error;
index 68ed7f7..11afc4e 100644 (file)
 #define REG_U32 4
 #define REG_U64 8
 
+/*
+ * As we look at expanding the KVP functionality to include
+ * IP injection functionality, we need to maintain binary
+ * compatibility with older daemons.
+ *
+ * The KVP opcodes are defined by the host and it was unfortunate
+ * that I chose to treat the registration operation as part of the
+ * KVP operations defined by the host.
+ * Here is the level of compatibility
+ * (between the user level daemon and the kernel KVP driver) that we
+ * will implement:
+ *
+ * An older daemon will always be supported on a newer driver.
+ * A given user level daemon will require a minimal version of the
+ * kernel driver.
+ * If we cannot handle the version differences, we will fail gracefully
+ * (this can happen when we have a user level daemon that is more
+ * advanced than the KVP driver.
+ *
+ * We will use values used in this handshake for determining if we have
+ * workable user level daemon and the kernel driver. We begin by taking the
+ * registration opcode out of the KVP opcode namespace. We will however,
+ * maintain compatibility with the existing user-level daemon code.
+ */
+
+/*
+ * Daemon code not supporting IP injection (legacy daemon).
+ */
+
+#define KVP_OP_REGISTER        4
+
+/*
+ * Daemon code supporting IP injection.
+ * The KVP opcode field is used to communicate the
+ * registration information; so define a namespace that
+ * will be distinct from the host defined KVP opcode.
+ */
+
+#define KVP_OP_REGISTER1 100
+
 enum hv_kvp_exchg_op {
        KVP_OP_GET = 0,
        KVP_OP_SET,
        KVP_OP_DELETE,
        KVP_OP_ENUMERATE,
-       KVP_OP_REGISTER,
+       KVP_OP_GET_IP_INFO,
+       KVP_OP_SET_IP_INFO,
        KVP_OP_COUNT /* Number of operations, must be last. */
 };
 
@@ -140,6 +181,26 @@ enum hv_kvp_exchg_pool {
        KVP_POOL_COUNT /* Number of pools, must be last. */
 };
 
+#define ADDR_FAMILY_NONE       0x00
+#define ADDR_FAMILY_IPV4       0x01
+#define ADDR_FAMILY_IPV6       0x02
+
+#define MAX_ADAPTER_ID_SIZE    128
+#define MAX_IP_ADDR_SIZE       1024
+#define MAX_GATEWAY_SIZE       512
+
+
+struct hv_kvp_ipaddr_value {
+       __u16   adapter_id[MAX_ADAPTER_ID_SIZE];
+       __u8    addr_family;
+       __u8    dhcp_enabled;
+       __u16   ip_addr[MAX_IP_ADDR_SIZE];
+       __u16   sub_net[MAX_IP_ADDR_SIZE];
+       __u16   gate_way[MAX_GATEWAY_SIZE];
+       __u16   dns_addr[MAX_IP_ADDR_SIZE];
+} __attribute__((packed));
+
+
 struct hv_kvp_hdr {
        __u8 operation;
        __u8 pool;
@@ -181,16 +242,26 @@ struct hv_kvp_register {
 };
 
 struct hv_kvp_msg {
-       struct hv_kvp_hdr       kvp_hdr;
+       union {
+               struct hv_kvp_hdr       kvp_hdr;
+               int error;
+       };
        union {
                struct hv_kvp_msg_get           kvp_get;
                struct hv_kvp_msg_set           kvp_set;
                struct hv_kvp_msg_delete        kvp_delete;
                struct hv_kvp_msg_enumerate     kvp_enum_data;
+               struct hv_kvp_ipaddr_value      kvp_ip_val;
                struct hv_kvp_register          kvp_register;
        } body;
 } __attribute__((packed));
 
+struct hv_kvp_ip_msg {
+       __u8 operation;
+       __u8 pool;
+       struct hv_kvp_ipaddr_value      kvp_ip_val;
+} __attribute__((packed));
+
 #ifdef __KERNEL__
 #include <linux/scatterlist.h>
 #include <linux/list.h>
@@ -982,6 +1053,7 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver);
 #define HV_S_CONT                      0x80070103
 #define HV_ERROR_NOT_SUPPORTED         0x80070032
 #define HV_ERROR_MACHINE_LOCKED                0x800704F7
+#define HV_ERROR_DEVICE_NOT_CONNECTED  0x8007048F
 
 /*
  * While we want to handle util services as regular devices,
index d9834b3..8fbcf7b 100644 (file)
@@ -69,7 +69,7 @@ enum key_index {
 };
 
 static char kvp_send_buffer[4096];
-static char kvp_recv_buffer[4096];
+static char kvp_recv_buffer[4096 * 2];
 static struct sockaddr_nl addr;
 
 static char *os_name = "";