aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hv/hv_kvp.c114
-rw-r--r--include/linux/hyperv.h17
-rw-r--r--tools/hv/hv_kvp_daemon.c66
3 files changed, 135 insertions, 62 deletions
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 0012eed6d872..eb4d0730f44d 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -48,13 +48,24 @@ static struct {
48 void *kvp_context; /* for the channel callback */ 48 void *kvp_context; /* for the channel callback */
49} kvp_transaction; 49} kvp_transaction;
50 50
51/*
52 * Before we can accept KVP messages from the host, we need
53 * to handshake with the user level daemon. This state tracks
54 * if we are in the handshake phase.
55 */
56static bool in_hand_shake = true;
57
58/*
59 * This state maintains the version number registered by the daemon.
60 */
61static int dm_reg_value;
62
51static void kvp_send_key(struct work_struct *dummy); 63static void kvp_send_key(struct work_struct *dummy);
52 64
53#define TIMEOUT_FIRED 1
54 65
55static void kvp_respond_to_host(char *key, char *value, int error); 66static void kvp_respond_to_host(char *key, char *value, int error);
56static void kvp_work_func(struct work_struct *dummy); 67static void kvp_work_func(struct work_struct *dummy);
57static void kvp_register(void); 68static void kvp_register(int);
58 69
59static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); 70static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
60static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); 71static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
@@ -68,7 +79,7 @@ static u8 *recv_buffer;
68 */ 79 */
69 80
70static void 81static void
71kvp_register(void) 82kvp_register(int reg_value)
72{ 83{
73 84
74 struct cn_msg *msg; 85 struct cn_msg *msg;
@@ -83,7 +94,7 @@ kvp_register(void)
83 msg->id.idx = CN_KVP_IDX; 94 msg->id.idx = CN_KVP_IDX;
84 msg->id.val = CN_KVP_VAL; 95 msg->id.val = CN_KVP_VAL;
85 96
86 kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER; 97 kvp_msg->kvp_hdr.operation = reg_value;
87 strcpy(version, HV_DRV_VERSION); 98 strcpy(version, HV_DRV_VERSION);
88 msg->len = sizeof(struct hv_kvp_msg); 99 msg->len = sizeof(struct hv_kvp_msg);
89 cn_netlink_send(msg, 0, GFP_ATOMIC); 100 cn_netlink_send(msg, 0, GFP_ATOMIC);
@@ -97,9 +108,43 @@ kvp_work_func(struct work_struct *dummy)
97 * If the timer fires, the user-mode component has not responded; 108 * If the timer fires, the user-mode component has not responded;
98 * process the pending transaction. 109 * process the pending transaction.
99 */ 110 */
100 kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED); 111 kvp_respond_to_host("Unknown key", "Guest timed out", HV_E_FAIL);
112}
113
114static int kvp_handle_handshake(struct hv_kvp_msg *msg)
115{
116 int ret = 1;
117
118 switch (msg->kvp_hdr.operation) {
119 case KVP_OP_REGISTER:
120 dm_reg_value = KVP_OP_REGISTER;
121 pr_info("KVP: IP injection functionality not available\n");
122 pr_info("KVP: Upgrade the KVP daemon\n");
123 break;
124 case KVP_OP_REGISTER1:
125 dm_reg_value = KVP_OP_REGISTER1;
126 break;
127 default:
128 pr_info("KVP: incompatible daemon\n");
129 pr_info("KVP: KVP version: %d, Daemon version: %d\n",
130 KVP_OP_REGISTER1, msg->kvp_hdr.operation);
131 ret = 0;
132 }
133
134 if (ret) {
135 /*
136 * We have a compatible daemon; complete the handshake.
137 */
138 pr_info("KVP: user-mode registering done.\n");
139 kvp_register(dm_reg_value);
140 kvp_transaction.active = false;
141 if (kvp_transaction.kvp_context)
142 hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
143 }
144 return ret;
101} 145}
102 146
147
103/* 148/*
104 * Callback when data is received from user mode. 149 * Callback when data is received from user mode.
105 */ 150 */
@@ -109,27 +154,52 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
109{ 154{
110 struct hv_kvp_msg *message; 155 struct hv_kvp_msg *message;
111 struct hv_kvp_msg_enumerate *data; 156 struct hv_kvp_msg_enumerate *data;
157 int error = 0;
112 158
113 message = (struct hv_kvp_msg *)msg->data; 159 message = (struct hv_kvp_msg *)msg->data;
114 switch (message->kvp_hdr.operation) { 160
161 /*
162 * If we are negotiating the version information
163 * with the daemon; handle that first.
164 */
165
166 if (in_hand_shake) {
167 if (kvp_handle_handshake(message))
168 in_hand_shake = false;
169 return;
170 }
171
172 /*
173 * Based on the version of the daemon, we propagate errors from the
174 * daemon differently.
175 */
176
177 data = &message->body.kvp_enum_data;
178
179 switch (dm_reg_value) {
115 case KVP_OP_REGISTER: 180 case KVP_OP_REGISTER:
116 pr_info("KVP: user-mode registering done.\n"); 181 /*
117 kvp_register(); 182 * Null string is used to pass back error condition.
118 kvp_transaction.active = false; 183 */
119 hv_kvp_onchannelcallback(kvp_transaction.kvp_context); 184 if (data->data.key[0] == 0)
185 error = HV_S_CONT;
120 break; 186 break;
121 187
122 default: 188 case KVP_OP_REGISTER1:
123 data = &message->body.kvp_enum_data;
124 /* 189 /*
125 * Complete the transaction by forwarding the key value 190 * We use the message header information from
126 * to the host. But first, cancel the timeout. 191 * the user level daemon to transmit errors.
127 */ 192 */
128 if (cancel_delayed_work_sync(&kvp_work)) 193 error = message->error;
129 kvp_respond_to_host(data->data.key, 194 break;
130 data->data.value,
131 !strlen(data->data.key));
132 } 195 }
196
197 /*
198 * Complete the transaction by forwarding the key value
199 * to the host. But first, cancel the timeout.
200 */
201 if (cancel_delayed_work_sync(&kvp_work))
202 kvp_respond_to_host(data->data.key, data->data.value, error);
133} 203}
134 204
135static void 205static void
@@ -287,6 +357,7 @@ kvp_respond_to_host(char *key, char *value, int error)
287 */ 357 */
288 return; 358 return;
289 359
360 icmsghdrp->status = error;
290 361
291 /* 362 /*
292 * If the error parameter is set, terminate the host's enumeration 363 * If the error parameter is set, terminate the host's enumeration
@@ -294,15 +365,12 @@ kvp_respond_to_host(char *key, char *value, int error)
294 */ 365 */
295 if (error) { 366 if (error) {
296 /* 367 /*
297 * Something failed or the we have timedout; 368 * Something failed or we have timedout;
298 * terminate the current host-side iteration. 369 * terminate the current host-side iteration.
299 */ 370 */
300 icmsghdrp->status = HV_S_CONT;
301 goto response_done; 371 goto response_done;
302 } 372 }
303 373
304 icmsghdrp->status = HV_S_OK;
305
306 kvp_msg = (struct hv_kvp_msg *) 374 kvp_msg = (struct hv_kvp_msg *)
307 &recv_buffer[sizeof(struct vmbuspipe_hdr) + 375 &recv_buffer[sizeof(struct vmbuspipe_hdr) +
308 sizeof(struct icmsg_hdr)]; 376 sizeof(struct icmsg_hdr)];
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 11afc4e0849a..b587c448e8ab 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -181,6 +181,17 @@ enum hv_kvp_exchg_pool {
181 KVP_POOL_COUNT /* Number of pools, must be last. */ 181 KVP_POOL_COUNT /* Number of pools, must be last. */
182}; 182};
183 183
184/*
185 * Some Hyper-V status codes.
186 */
187
188#define HV_S_OK 0x00000000
189#define HV_E_FAIL 0x80004005
190#define HV_S_CONT 0x80070103
191#define HV_ERROR_NOT_SUPPORTED 0x80070032
192#define HV_ERROR_MACHINE_LOCKED 0x800704F7
193#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
194
184#define ADDR_FAMILY_NONE 0x00 195#define ADDR_FAMILY_NONE 0x00
185#define ADDR_FAMILY_IPV4 0x01 196#define ADDR_FAMILY_IPV4 0x01
186#define ADDR_FAMILY_IPV6 0x02 197#define ADDR_FAMILY_IPV6 0x02
@@ -1048,12 +1059,6 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver);
1048#define ICMSGHDRFLAG_REQUEST 2 1059#define ICMSGHDRFLAG_REQUEST 2
1049#define ICMSGHDRFLAG_RESPONSE 4 1060#define ICMSGHDRFLAG_RESPONSE 4
1050 1061
1051#define HV_S_OK 0x00000000
1052#define HV_E_FAIL 0x80004005
1053#define HV_S_CONT 0x80070103
1054#define HV_ERROR_NOT_SUPPORTED 0x80070032
1055#define HV_ERROR_MACHINE_LOCKED 0x800704F7
1056#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
1057 1062
1058/* 1063/*
1059 * While we want to handle util services as regular devices, 1064 * While we want to handle util services as regular devices,
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 8fbcf7b3c69d..069e2b38decb 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -71,13 +71,14 @@ enum key_index {
71static char kvp_send_buffer[4096]; 71static char kvp_send_buffer[4096];
72static char kvp_recv_buffer[4096 * 2]; 72static char kvp_recv_buffer[4096 * 2];
73static struct sockaddr_nl addr; 73static struct sockaddr_nl addr;
74static int in_hand_shake = 1;
74 75
75static char *os_name = ""; 76static char *os_name = "";
76static char *os_major = ""; 77static char *os_major = "";
77static char *os_minor = ""; 78static char *os_minor = "";
78static char *processor_arch; 79static char *processor_arch;
79static char *os_build; 80static char *os_build;
80static char *lic_version; 81static char *lic_version = "Unknown version";
81static struct utsname uts_buf; 82static struct utsname uts_buf;
82 83
83 84
@@ -394,7 +395,7 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
394 return 1; 395 return 1;
395} 396}
396 397
397static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size, 398static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
398 __u8 *value, int value_size) 399 __u8 *value, int value_size)
399{ 400{
400 struct kvp_record *record; 401 struct kvp_record *record;
@@ -406,16 +407,12 @@ static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
406 record = kvp_file_info[pool].records; 407 record = kvp_file_info[pool].records;
407 408
408 if (index >= kvp_file_info[pool].num_records) { 409 if (index >= kvp_file_info[pool].num_records) {
409 /* 410 return 1;
410 * This is an invalid index; terminate enumeration;
411 * - a NULL value will do the trick.
412 */
413 strcpy(value, "");
414 return;
415 } 411 }
416 412
417 memcpy(key, record[index].key, key_size); 413 memcpy(key, record[index].key, key_size);
418 memcpy(value, record[index].value, value_size); 414 memcpy(value, record[index].value, value_size);
415 return 0;
419} 416}
420 417
421 418
@@ -646,6 +643,8 @@ int main(void)
646 char *p; 643 char *p;
647 char *key_value; 644 char *key_value;
648 char *key_name; 645 char *key_name;
646 int op;
647 int pool;
649 648
650 daemon(1, 0); 649 daemon(1, 0);
651 openlog("KVP", 0, LOG_USER); 650 openlog("KVP", 0, LOG_USER);
@@ -687,7 +686,7 @@ int main(void)
687 message->id.val = CN_KVP_VAL; 686 message->id.val = CN_KVP_VAL;
688 687
689 hv_msg = (struct hv_kvp_msg *)message->data; 688 hv_msg = (struct hv_kvp_msg *)message->data;
690 hv_msg->kvp_hdr.operation = KVP_OP_REGISTER; 689 hv_msg->kvp_hdr.operation = KVP_OP_REGISTER1;
691 message->ack = 0; 690 message->ack = 0;
692 message->len = sizeof(struct hv_kvp_msg); 691 message->len = sizeof(struct hv_kvp_msg);
693 692
@@ -721,12 +720,21 @@ int main(void)
721 incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); 720 incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
722 hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; 721 hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
723 722
724 switch (hv_msg->kvp_hdr.operation) { 723 /*
725 case KVP_OP_REGISTER: 724 * We will use the KVP header information to pass back
725 * the error from this daemon. So, first copy the state
726 * and set the error code to success.
727 */
728 op = hv_msg->kvp_hdr.operation;
729 pool = hv_msg->kvp_hdr.pool;
730 hv_msg->error = HV_S_OK;
731
732 if ((in_hand_shake) && (op == KVP_OP_REGISTER1)) {
726 /* 733 /*
727 * Driver is registering with us; stash away the version 734 * Driver is registering with us; stash away the version
728 * information. 735 * information.
729 */ 736 */
737 in_hand_shake = 0;
730 p = (char *)hv_msg->body.kvp_register.version; 738 p = (char *)hv_msg->body.kvp_register.version;
731 lic_version = malloc(strlen(p) + 1); 739 lic_version = malloc(strlen(p) + 1);
732 if (lic_version) { 740 if (lic_version) {
@@ -737,44 +745,39 @@ int main(void)
737 syslog(LOG_ERR, "malloc failed"); 745 syslog(LOG_ERR, "malloc failed");
738 } 746 }
739 continue; 747 continue;
748 }
740 749
741 /* 750 switch (op) {
742 * The current protocol with the kernel component uses a
743 * NULL key name to pass an error condition.
744 * For the SET, GET and DELETE operations,
745 * use the existing protocol to pass back error.
746 */
747
748 case KVP_OP_SET: 751 case KVP_OP_SET:
749 if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool, 752 if (kvp_key_add_or_modify(pool,
750 hv_msg->body.kvp_set.data.key, 753 hv_msg->body.kvp_set.data.key,
751 hv_msg->body.kvp_set.data.key_size, 754 hv_msg->body.kvp_set.data.key_size,
752 hv_msg->body.kvp_set.data.value, 755 hv_msg->body.kvp_set.data.value,
753 hv_msg->body.kvp_set.data.value_size)) 756 hv_msg->body.kvp_set.data.value_size))
754 strcpy(hv_msg->body.kvp_set.data.key, ""); 757 hv_msg->error = HV_S_CONT;
755 break; 758 break;
756 759
757 case KVP_OP_GET: 760 case KVP_OP_GET:
758 if (kvp_get_value(hv_msg->kvp_hdr.pool, 761 if (kvp_get_value(pool,
759 hv_msg->body.kvp_set.data.key, 762 hv_msg->body.kvp_set.data.key,
760 hv_msg->body.kvp_set.data.key_size, 763 hv_msg->body.kvp_set.data.key_size,
761 hv_msg->body.kvp_set.data.value, 764 hv_msg->body.kvp_set.data.value,
762 hv_msg->body.kvp_set.data.value_size)) 765 hv_msg->body.kvp_set.data.value_size))
763 strcpy(hv_msg->body.kvp_set.data.key, ""); 766 hv_msg->error = HV_S_CONT;
764 break; 767 break;
765 768
766 case KVP_OP_DELETE: 769 case KVP_OP_DELETE:
767 if (kvp_key_delete(hv_msg->kvp_hdr.pool, 770 if (kvp_key_delete(pool,
768 hv_msg->body.kvp_delete.key, 771 hv_msg->body.kvp_delete.key,
769 hv_msg->body.kvp_delete.key_size)) 772 hv_msg->body.kvp_delete.key_size))
770 strcpy(hv_msg->body.kvp_delete.key, ""); 773 hv_msg->error = HV_S_CONT;
771 break; 774 break;
772 775
773 default: 776 default:
774 break; 777 break;
775 } 778 }
776 779
777 if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE) 780 if (op != KVP_OP_ENUMERATE)
778 goto kvp_done; 781 goto kvp_done;
779 782
780 /* 783 /*
@@ -782,13 +785,14 @@ int main(void)
782 * both the key and the value; if not read from the 785 * both the key and the value; if not read from the
783 * appropriate pool. 786 * appropriate pool.
784 */ 787 */
785 if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) { 788 if (pool != KVP_POOL_AUTO) {
786 kvp_pool_enumerate(hv_msg->kvp_hdr.pool, 789 if (kvp_pool_enumerate(pool,
787 hv_msg->body.kvp_enum_data.index, 790 hv_msg->body.kvp_enum_data.index,
788 hv_msg->body.kvp_enum_data.data.key, 791 hv_msg->body.kvp_enum_data.data.key,
789 HV_KVP_EXCHANGE_MAX_KEY_SIZE, 792 HV_KVP_EXCHANGE_MAX_KEY_SIZE,
790 hv_msg->body.kvp_enum_data.data.value, 793 hv_msg->body.kvp_enum_data.data.value,
791 HV_KVP_EXCHANGE_MAX_VALUE_SIZE); 794 HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
795 hv_msg->error = HV_S_CONT;
792 goto kvp_done; 796 goto kvp_done;
793 } 797 }
794 798
@@ -841,11 +845,7 @@ int main(void)
841 strcpy(key_name, "ProcessorArchitecture"); 845 strcpy(key_name, "ProcessorArchitecture");
842 break; 846 break;
843 default: 847 default:
844 strcpy(key_value, "Unknown Key"); 848 hv_msg->error = HV_S_CONT;
845 /*
846 * We use a null key name to terminate enumeration.
847 */
848 strcpy(key_name, "");
849 break; 849 break;
850 } 850 }
851 /* 851 /*