aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/config.c')
-rw-r--r--net/tipc/config.c119
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
44static u32 config_port_ref; 45static DEFINE_MUTEX(config_mutex);
45 46static struct tipc_server cfgsrv;
46static DEFINE_SPINLOCK(config_lock);
47 47
48static const void *req_tlv_area; /* request message TLV area */ 48static const void *req_tlv_area; /* request message TLV area */
49static int req_tlv_space; /* request message TLV area size */ 49static 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 */
379exit: 368exit:
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
384static void cfg_named_msg_event(void *userdata, 373static 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
411static 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
420static 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
427int tipc_cfg_init(void) 431int 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
447failed:
448 pr_err("Unable to create configuration service\n");
449 return res;
450} 434}
451 435
452void tipc_cfg_reinit(void) 436void 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
467void tipc_cfg_stop(void) 445void tipc_cfg_stop(void)
468{ 446{
469 tipc_deleteport(config_port_ref); 447 tipc_server_stop(&cfgsrv);
470 config_port_ref = 0;
471} 448}