aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv/hv_kvp.c
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2012-08-16 21:32:12 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-08-17 11:23:57 -0400
commit03db7724af1315f644ddc26e9539789eac4a016a (patch)
treece3c2a6a641af101c514d6e24d379927136f12ae /drivers/hv/hv_kvp.c
parentab6dd8e5ecf8c1a38ee1b9b9dfa9ab129dc3e200 (diff)
Drivers: hv: kvp: Support the new IP injection messages
Implement support for the new IP injection messages in the driver code. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv/hv_kvp.c')
-rw-r--r--drivers/hv/hv_kvp.c141
1 files changed, 135 insertions, 6 deletions
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index eb4d0730f44d..d9060502b073 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -63,7 +63,7 @@ static int dm_reg_value;
63static void kvp_send_key(struct work_struct *dummy); 63static void kvp_send_key(struct work_struct *dummy);
64 64
65 65
66static void kvp_respond_to_host(char *key, char *value, int error); 66static void kvp_respond_to_host(struct hv_kvp_msg *msg, int error);
67static void kvp_work_func(struct work_struct *dummy); 67static void kvp_work_func(struct work_struct *dummy);
68static void kvp_register(int); 68static void kvp_register(int);
69 69
@@ -108,7 +108,7 @@ kvp_work_func(struct work_struct *dummy)
108 * If the timer fires, the user-mode component has not responded; 108 * If the timer fires, the user-mode component has not responded;
109 * process the pending transaction. 109 * process the pending transaction.
110 */ 110 */
111 kvp_respond_to_host("Unknown key", "Guest timed out", HV_E_FAIL); 111 kvp_respond_to_host(NULL, HV_E_FAIL);
112} 112}
113 113
114static int kvp_handle_handshake(struct hv_kvp_msg *msg) 114static int kvp_handle_handshake(struct hv_kvp_msg *msg)
@@ -199,9 +199,118 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
199 * to the host. But first, cancel the timeout. 199 * to the host. But first, cancel the timeout.
200 */ 200 */
201 if (cancel_delayed_work_sync(&kvp_work)) 201 if (cancel_delayed_work_sync(&kvp_work))
202 kvp_respond_to_host(data->data.key, data->data.value, error); 202 kvp_respond_to_host(message, error);
203} 203}
204 204
205
206static int process_ob_ipinfo(void *in_msg, void *out_msg, int op)
207{
208 struct hv_kvp_msg *in = in_msg;
209 struct hv_kvp_ip_msg *out = out_msg;
210 int len;
211
212 switch (op) {
213 case KVP_OP_GET_IP_INFO:
214 /*
215 * Transform all parameters into utf16 encoding.
216 */
217 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.ip_addr,
218 strlen((char *)in->body.kvp_ip_val.ip_addr),
219 UTF16_HOST_ENDIAN,
220 (wchar_t *)out->kvp_ip_val.ip_addr,
221 MAX_IP_ADDR_SIZE);
222 if (len < 0)
223 return len;
224
225 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.sub_net,
226 strlen((char *)in->body.kvp_ip_val.sub_net),
227 UTF16_HOST_ENDIAN,
228 (wchar_t *)out->kvp_ip_val.sub_net,
229 MAX_IP_ADDR_SIZE);
230 if (len < 0)
231 return len;
232
233 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.gate_way,
234 strlen((char *)in->body.kvp_ip_val.gate_way),
235 UTF16_HOST_ENDIAN,
236 (wchar_t *)out->kvp_ip_val.gate_way,
237 MAX_GATEWAY_SIZE);
238 if (len < 0)
239 return len;
240
241 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.dns_addr,
242 strlen((char *)in->body.kvp_ip_val.dns_addr),
243 UTF16_HOST_ENDIAN,
244 (wchar_t *)out->kvp_ip_val.dns_addr,
245 MAX_IP_ADDR_SIZE);
246 if (len < 0)
247 return len;
248
249 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.adapter_id,
250 strlen((char *)in->body.kvp_ip_val.adapter_id),
251 UTF16_HOST_ENDIAN,
252 (wchar_t *)out->kvp_ip_val.adapter_id,
253 MAX_IP_ADDR_SIZE);
254 if (len < 0)
255 return len;
256
257 out->kvp_ip_val.dhcp_enabled =
258 in->body.kvp_ip_val.dhcp_enabled;
259 }
260
261 return 0;
262}
263
264static void process_ib_ipinfo(void *in_msg, void *out_msg, int op)
265{
266 struct hv_kvp_ip_msg *in = in_msg;
267 struct hv_kvp_msg *out = out_msg;
268
269 switch (op) {
270 case KVP_OP_SET_IP_INFO:
271 /*
272 * Transform all parameters into utf8 encoding.
273 */
274 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.ip_addr,
275 MAX_IP_ADDR_SIZE,
276 UTF16_LITTLE_ENDIAN,
277 (__u8 *)out->body.kvp_ip_val.ip_addr,
278 MAX_IP_ADDR_SIZE);
279
280 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.sub_net,
281 MAX_IP_ADDR_SIZE,
282 UTF16_LITTLE_ENDIAN,
283 (__u8 *)out->body.kvp_ip_val.sub_net,
284 MAX_IP_ADDR_SIZE);
285
286 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.gate_way,
287 MAX_GATEWAY_SIZE,
288 UTF16_LITTLE_ENDIAN,
289 (__u8 *)out->body.kvp_ip_val.gate_way,
290 MAX_GATEWAY_SIZE);
291
292 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.dns_addr,
293 MAX_IP_ADDR_SIZE,
294 UTF16_LITTLE_ENDIAN,
295 (__u8 *)out->body.kvp_ip_val.dns_addr,
296 MAX_IP_ADDR_SIZE);
297
298 out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
299
300 default:
301 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
302 MAX_ADAPTER_ID_SIZE,
303 UTF16_LITTLE_ENDIAN,
304 (__u8 *)out->body.kvp_ip_val.adapter_id,
305 MAX_ADAPTER_ID_SIZE);
306
307 out->body.kvp_ip_val.addr_family = in->kvp_ip_val.addr_family;
308 }
309}
310
311
312
313
205static void 314static void
206kvp_send_key(struct work_struct *dummy) 315kvp_send_key(struct work_struct *dummy)
207{ 316{
@@ -237,6 +346,12 @@ kvp_send_key(struct work_struct *dummy)
237 */ 346 */
238 347
239 switch (message->kvp_hdr.operation) { 348 switch (message->kvp_hdr.operation) {
349 case KVP_OP_SET_IP_INFO:
350 process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
351 break;
352 case KVP_OP_GET_IP_INFO:
353 process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
354 break;
240 case KVP_OP_SET: 355 case KVP_OP_SET:
241 switch (in_msg->body.kvp_set.data.value_type) { 356 switch (in_msg->body.kvp_set.data.value_type) {
242 case REG_SZ: 357 case REG_SZ:
@@ -313,17 +428,19 @@ kvp_send_key(struct work_struct *dummy)
313 */ 428 */
314 429
315static void 430static void
316kvp_respond_to_host(char *key, char *value, int error) 431kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error)
317{ 432{
318 struct hv_kvp_msg *kvp_msg; 433 struct hv_kvp_msg *kvp_msg;
319 struct hv_kvp_exchg_msg_value *kvp_data; 434 struct hv_kvp_exchg_msg_value *kvp_data;
320 char *key_name; 435 char *key_name;
436 char *value;
321 struct icmsg_hdr *icmsghdrp; 437 struct icmsg_hdr *icmsghdrp;
322 int keylen = 0; 438 int keylen = 0;
323 int valuelen = 0; 439 int valuelen = 0;
324 u32 buf_len; 440 u32 buf_len;
325 struct vmbus_channel *channel; 441 struct vmbus_channel *channel;
326 u64 req_id; 442 u64 req_id;
443 int ret;
327 444
328 /* 445 /*
329 * If a transaction is not active; log and return. 446 * If a transaction is not active; log and return.
@@ -376,6 +493,16 @@ kvp_respond_to_host(char *key, char *value, int error)
376 sizeof(struct icmsg_hdr)]; 493 sizeof(struct icmsg_hdr)];
377 494
378 switch (kvp_transaction.kvp_msg->kvp_hdr.operation) { 495 switch (kvp_transaction.kvp_msg->kvp_hdr.operation) {
496 case KVP_OP_GET_IP_INFO:
497 ret = process_ob_ipinfo(msg_to_host,
498 (struct hv_kvp_ip_msg *)kvp_msg,
499 KVP_OP_GET_IP_INFO);
500 if (ret < 0)
501 icmsghdrp->status = HV_E_FAIL;
502
503 goto response_done;
504 case KVP_OP_SET_IP_INFO:
505 goto response_done;
379 case KVP_OP_GET: 506 case KVP_OP_GET:
380 kvp_data = &kvp_msg->body.kvp_get.data; 507 kvp_data = &kvp_msg->body.kvp_get.data;
381 goto copy_value; 508 goto copy_value;
@@ -389,7 +516,7 @@ kvp_respond_to_host(char *key, char *value, int error)
389 } 516 }
390 517
391 kvp_data = &kvp_msg->body.kvp_enum_data.data; 518 kvp_data = &kvp_msg->body.kvp_enum_data.data;
392 key_name = key; 519 key_name = msg_to_host->body.kvp_enum_data.data.key;
393 520
394 /* 521 /*
395 * The windows host expects the key/value pair to be encoded 522 * The windows host expects the key/value pair to be encoded
@@ -403,6 +530,7 @@ kvp_respond_to_host(char *key, char *value, int error)
403 kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */ 530 kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */
404 531
405copy_value: 532copy_value:
533 value = msg_to_host->body.kvp_enum_data.data.value;
406 valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN, 534 valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
407 (wchar_t *) kvp_data->value, 535 (wchar_t *) kvp_data->value,
408 (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2); 536 (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2);
@@ -455,7 +583,8 @@ void hv_kvp_onchannelcallback(void *context)
455 return; 583 return;
456 } 584 }
457 585
458 vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); 586 vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
587 &requestid);
459 588
460 if (recvlen > 0) { 589 if (recvlen > 0) {
461 icmsghdrp = (struct icmsg_hdr *)&recv_buffer[ 590 icmsghdrp = (struct icmsg_hdr *)&recv_buffer[