diff options
Diffstat (limited to 'net/tipc/config.c')
-rw-r--r-- | net/tipc/config.c | 119 |
1 files changed, 48 insertions, 71 deletions
diff --git a/net/tipc/config.c b/net/tipc/config.c index f67866c765dd..c301a9a592d8 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/config.c: TIPC configuration management code | 2 | * net/tipc/config.c: TIPC configuration management code |
3 | * | 3 | * |
4 | * Copyright (c) 2002-2006, Ericsson AB | 4 | * Copyright (c) 2002-2006, Ericsson AB |
5 | * Copyright (c) 2004-2007, 2010-2012, Wind River Systems | 5 | * Copyright (c) 2004-2007, 2010-2013, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -38,12 +38,12 @@ | |||
38 | #include "port.h" | 38 | #include "port.h" |
39 | #include "name_table.h" | 39 | #include "name_table.h" |
40 | #include "config.h" | 40 | #include "config.h" |
41 | #include "server.h" | ||
41 | 42 | ||
42 | #define REPLY_TRUNCATED "<truncated>\n" | 43 | #define REPLY_TRUNCATED "<truncated>\n" |
43 | 44 | ||
44 | static u32 config_port_ref; | 45 | static DEFINE_MUTEX(config_mutex); |
45 | 46 | static struct tipc_server cfgsrv; | |
46 | static DEFINE_SPINLOCK(config_lock); | ||
47 | 47 | ||
48 | static const void *req_tlv_area; /* request message TLV area */ | 48 | static const void *req_tlv_area; /* request message TLV area */ |
49 | static int req_tlv_space; /* request message TLV area size */ | 49 | static int req_tlv_space; /* request message TLV area size */ |
@@ -181,18 +181,7 @@ static struct sk_buff *cfg_set_own_addr(void) | |||
181 | if (tipc_own_addr) | 181 | if (tipc_own_addr) |
182 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 182 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
183 | " (cannot change node address once assigned)"); | 183 | " (cannot change node address once assigned)"); |
184 | |||
185 | /* | ||
186 | * Must temporarily release configuration spinlock while switching into | ||
187 | * networking mode as it calls tipc_eth_media_start(), which may sleep. | ||
188 | * Releasing the lock is harmless as other locally-issued configuration | ||
189 | * commands won't occur until this one completes, and remotely-issued | ||
190 | * configuration commands can't be received until a local configuration | ||
191 | * command to enable the first bearer is received and processed. | ||
192 | */ | ||
193 | spin_unlock_bh(&config_lock); | ||
194 | tipc_core_start_net(addr); | 184 | tipc_core_start_net(addr); |
195 | spin_lock_bh(&config_lock); | ||
196 | return tipc_cfg_reply_none(); | 185 | return tipc_cfg_reply_none(); |
197 | } | 186 | } |
198 | 187 | ||
@@ -248,7 +237,7 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
248 | { | 237 | { |
249 | struct sk_buff *rep_tlv_buf; | 238 | struct sk_buff *rep_tlv_buf; |
250 | 239 | ||
251 | spin_lock_bh(&config_lock); | 240 | mutex_lock(&config_mutex); |
252 | 241 | ||
253 | /* Save request and reply details in a well-known location */ | 242 | /* Save request and reply details in a well-known location */ |
254 | req_tlv_area = request_area; | 243 | req_tlv_area = request_area; |
@@ -377,37 +366,31 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
377 | 366 | ||
378 | /* Return reply buffer */ | 367 | /* Return reply buffer */ |
379 | exit: | 368 | exit: |
380 | spin_unlock_bh(&config_lock); | 369 | mutex_unlock(&config_mutex); |
381 | return rep_tlv_buf; | 370 | return rep_tlv_buf; |
382 | } | 371 | } |
383 | 372 | ||
384 | static void cfg_named_msg_event(void *userdata, | 373 | static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr, |
385 | u32 port_ref, | 374 | void *usr_data, void *buf, size_t len) |
386 | struct sk_buff **buf, | ||
387 | const unchar *msg, | ||
388 | u32 size, | ||
389 | u32 importance, | ||
390 | struct tipc_portid const *orig, | ||
391 | struct tipc_name_seq const *dest) | ||
392 | { | 375 | { |
393 | struct tipc_cfg_msg_hdr *req_hdr; | 376 | struct tipc_cfg_msg_hdr *req_hdr; |
394 | struct tipc_cfg_msg_hdr *rep_hdr; | 377 | struct tipc_cfg_msg_hdr *rep_hdr; |
395 | struct sk_buff *rep_buf; | 378 | struct sk_buff *rep_buf; |
379 | int ret; | ||
396 | 380 | ||
397 | /* Validate configuration message header (ignore invalid message) */ | 381 | /* Validate configuration message header (ignore invalid message) */ |
398 | req_hdr = (struct tipc_cfg_msg_hdr *)msg; | 382 | req_hdr = (struct tipc_cfg_msg_hdr *)buf; |
399 | if ((size < sizeof(*req_hdr)) || | 383 | if ((len < sizeof(*req_hdr)) || |
400 | (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || | 384 | (len != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || |
401 | (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { | 385 | (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { |
402 | pr_warn("Invalid configuration message discarded\n"); | 386 | pr_warn("Invalid configuration message discarded\n"); |
403 | return; | 387 | return; |
404 | } | 388 | } |
405 | 389 | ||
406 | /* Generate reply for request (if can't, return request) */ | 390 | /* Generate reply for request (if can't, return request) */ |
407 | rep_buf = tipc_cfg_do_cmd(orig->node, | 391 | rep_buf = tipc_cfg_do_cmd(addr->addr.id.node, ntohs(req_hdr->tcm_type), |
408 | ntohs(req_hdr->tcm_type), | 392 | buf + sizeof(*req_hdr), |
409 | msg + sizeof(*req_hdr), | 393 | len - sizeof(*req_hdr), |
410 | size - sizeof(*req_hdr), | ||
411 | BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); | 394 | BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); |
412 | if (rep_buf) { | 395 | if (rep_buf) { |
413 | skb_push(rep_buf, sizeof(*rep_hdr)); | 396 | skb_push(rep_buf, sizeof(*rep_hdr)); |
@@ -415,57 +398,51 @@ static void cfg_named_msg_event(void *userdata, | |||
415 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); | 398 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); |
416 | rep_hdr->tcm_len = htonl(rep_buf->len); | 399 | rep_hdr->tcm_len = htonl(rep_buf->len); |
417 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); | 400 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); |
418 | } else { | ||
419 | rep_buf = *buf; | ||
420 | *buf = NULL; | ||
421 | } | ||
422 | 401 | ||
423 | /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */ | 402 | ret = tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, |
424 | tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); | 403 | rep_buf->len); |
404 | if (ret < 0) | ||
405 | pr_err("Sending cfg reply message failed, no memory\n"); | ||
406 | |||
407 | kfree_skb(rep_buf); | ||
408 | } | ||
425 | } | 409 | } |
426 | 410 | ||
411 | static struct sockaddr_tipc cfgsrv_addr __read_mostly = { | ||
412 | .family = AF_TIPC, | ||
413 | .addrtype = TIPC_ADDR_NAMESEQ, | ||
414 | .addr.nameseq.type = TIPC_CFG_SRV, | ||
415 | .addr.nameseq.lower = 0, | ||
416 | .addr.nameseq.upper = 0, | ||
417 | .scope = TIPC_ZONE_SCOPE | ||
418 | }; | ||
419 | |||
420 | static struct tipc_server cfgsrv __read_mostly = { | ||
421 | .saddr = &cfgsrv_addr, | ||
422 | .imp = TIPC_CRITICAL_IMPORTANCE, | ||
423 | .type = SOCK_RDM, | ||
424 | .max_rcvbuf_size = 64 * 1024, | ||
425 | .name = "cfg_server", | ||
426 | .tipc_conn_recvmsg = cfg_conn_msg_event, | ||
427 | .tipc_conn_new = NULL, | ||
428 | .tipc_conn_shutdown = NULL | ||
429 | }; | ||
430 | |||
427 | int tipc_cfg_init(void) | 431 | int tipc_cfg_init(void) |
428 | { | 432 | { |
429 | struct tipc_name_seq seq; | 433 | return tipc_server_start(&cfgsrv); |
430 | int res; | ||
431 | |||
432 | res = tipc_createport(NULL, TIPC_CRITICAL_IMPORTANCE, | ||
433 | NULL, NULL, NULL, | ||
434 | NULL, cfg_named_msg_event, NULL, | ||
435 | NULL, &config_port_ref); | ||
436 | if (res) | ||
437 | goto failed; | ||
438 | |||
439 | seq.type = TIPC_CFG_SRV; | ||
440 | seq.lower = seq.upper = tipc_own_addr; | ||
441 | res = tipc_publish(config_port_ref, TIPC_ZONE_SCOPE, &seq); | ||
442 | if (res) | ||
443 | goto failed; | ||
444 | |||
445 | return 0; | ||
446 | |||
447 | failed: | ||
448 | pr_err("Unable to create configuration service\n"); | ||
449 | return res; | ||
450 | } | 434 | } |
451 | 435 | ||
452 | void tipc_cfg_reinit(void) | 436 | void tipc_cfg_reinit(void) |
453 | { | 437 | { |
454 | struct tipc_name_seq seq; | 438 | tipc_server_stop(&cfgsrv); |
455 | int res; | ||
456 | |||
457 | seq.type = TIPC_CFG_SRV; | ||
458 | seq.lower = seq.upper = 0; | ||
459 | tipc_withdraw(config_port_ref, TIPC_ZONE_SCOPE, &seq); | ||
460 | 439 | ||
461 | seq.lower = seq.upper = tipc_own_addr; | 440 | cfgsrv_addr.addr.nameseq.lower = tipc_own_addr; |
462 | res = tipc_publish(config_port_ref, TIPC_ZONE_SCOPE, &seq); | 441 | cfgsrv_addr.addr.nameseq.upper = tipc_own_addr; |
463 | if (res) | 442 | tipc_server_start(&cfgsrv); |
464 | pr_err("Unable to reinitialize configuration service\n"); | ||
465 | } | 443 | } |
466 | 444 | ||
467 | void tipc_cfg_stop(void) | 445 | void tipc_cfg_stop(void) |
468 | { | 446 | { |
469 | tipc_deleteport(config_port_ref); | 447 | tipc_server_stop(&cfgsrv); |
470 | config_port_ref = 0; | ||
471 | } | 448 | } |