aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-06-17 18:53:09 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-17 18:53:09 -0400
commitc7b67aef0fa5f665ca47f45d254e806e919d01ac (patch)
tree5130503fa11ba0c7ec74174165ba332ed513b88a
parentdafcc4380deec21d160c31411f33c8813f67f517 (diff)
parent2537af9dcabbdd6c93c041a955d3a9ae42c0c008 (diff)
Merge branch 'tipc'
Paul Gortmaker says: ==================== This is a rework of the content sent earlier[1], with the following changes: -drop the Kconfig --> modparam conversion patch; this was requested to be replaced[2] with a dynamic port quantity resizing. Ying and Erik were discussing how best to achieve this, and then vacation schedules got in the way, so implementing that will come (hopefully) in the next round. -rework the sk_rcvbuf patch to allow memory resizing via sysctl as per what Ying and Neil discussed[3] -add 4 more seemingly straigtforward and relatively small changes from Ying (the last 4 in the series). -add cosmetic UAPI comment update patch from Ying. That said, the largest change is still the one where we make use of the fact that linux supports kernel threads and do the server like operations within kernel threads. As Jon says: We remove the last remnants of the TIPC native API, to make it possible to simplify locking policy and solve a problem with lost topology events. First, we introduce a socket-based alternative to the native API. Second, we convert the two remaining users of the native API, the TIPC internal topology server and the configuarion server, to use the new API. Third, we remove the remaining code pertaining to the native API. I have re-tested this collection of commits between 32 and 64 bit x86 machines using the standard tipc test suite, and build tested for ppc. [1] http://patchwork.ozlabs.org/patch/247687/ [2] http://patchwork.ozlabs.org/patch/247680/ [3] http://patchwork.ozlabs.org/patch/247688/ ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/sysctl/net.txt17
-rw-r--r--include/uapi/linux/tipc.h2
-rw-r--r--include/uapi/linux/tipc_config.h2
-rw-r--r--net/tipc/Makefile3
-rw-r--r--net/tipc/bcast.c3
-rw-r--r--net/tipc/bcast.h3
-rw-r--r--net/tipc/config.c119
-rw-r--r--net/tipc/core.c22
-rw-r--r--net/tipc/core.h17
-rw-r--r--net/tipc/discover.c7
-rw-r--r--net/tipc/eth_media.c15
-rw-r--r--net/tipc/ib_media.c13
-rw-r--r--net/tipc/link.c88
-rw-r--r--net/tipc/msg.c19
-rw-r--r--net/tipc/msg.h8
-rw-r--r--net/tipc/name_table.c10
-rw-r--r--net/tipc/name_table.h11
-rw-r--r--net/tipc/node_subscr.c2
-rw-r--r--net/tipc/port.c320
-rw-r--r--net/tipc/port.h85
-rw-r--r--net/tipc/server.c596
-rw-r--r--net/tipc/server.h94
-rw-r--r--net/tipc/socket.c146
-rw-r--r--net/tipc/subscr.c348
-rw-r--r--net/tipc/subscr.h21
-rw-r--r--net/tipc/sysctl.c64
26 files changed, 1158 insertions, 877 deletions
diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt
index 85ab72dcdc3c..5369879eafe2 100644
--- a/Documentation/sysctl/net.txt
+++ b/Documentation/sysctl/net.txt
@@ -26,7 +26,7 @@ Table : Subdirectories in /proc/sys/net
26 ipv4 IP version 4 x25 X.25 protocol 26 ipv4 IP version 4 x25 X.25 protocol
27 ipx IPX token-ring IBM token ring 27 ipx IPX token-ring IBM token ring
28 bridge Bridging decnet DEC net 28 bridge Bridging decnet DEC net
29 ipv6 IP version 6 29 ipv6 IP version 6 tipc TIPC
30.............................................................................. 30..............................................................................
31 31
321. /proc/sys/net/core - Network core options 321. /proc/sys/net/core - Network core options
@@ -207,3 +207,18 @@ IPX.
207The /proc/net/ipx_route table holds a list of IPX routes. For each route it 207The /proc/net/ipx_route table holds a list of IPX routes. For each route it
208gives the destination network, the router node (or Directly) and the network 208gives the destination network, the router node (or Directly) and the network
209address of the router (or Connected) for internal networks. 209address of the router (or Connected) for internal networks.
210
2116. TIPC
212-------------------------------------------------------
213
214The TIPC protocol now has a tunable for the receive memory, similar to the
215tcp_rmem - i.e. a vector of 3 INTEGERs: (min, default, max)
216
217 # cat /proc/sys/net/tipc/tipc_rmem
218 4252725 34021800 68043600
219 #
220
221The max value is set to CONN_OVERLOAD_LIMIT, and the default and min values
222are scaled (shifted) versions of that same value. Note that the min value
223is not at this point in time used in any meaningful way, but the triplet is
224preserved in order to be consistent with things like tcp_rmem.
diff --git a/include/uapi/linux/tipc.h b/include/uapi/linux/tipc.h
index f2d90091cc20..852373d27dbb 100644
--- a/include/uapi/linux/tipc.h
+++ b/include/uapi/linux/tipc.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * include/linux/tipc.h: Include file for TIPC socket interface 2 * include/uapi/linux/tipc.h: Header for TIPC socket interface
3 * 3 *
4 * Copyright (c) 2003-2006, Ericsson AB 4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005, 2010-2011, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h
index 0b1e3f218a36..6b0bff09b3a7 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * include/linux/tipc_config.h: Include file for TIPC configuration interface 2 * include/uapi/linux/tipc_config.h: Header for TIPC configuration interface
3 * 3 *
4 * Copyright (c) 2003-2006, Ericsson AB 4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005-2007, 2010-2011, Wind River Systems 5 * Copyright (c) 2005-2007, 2010-2011, Wind River Systems
diff --git a/net/tipc/Makefile b/net/tipc/Makefile
index 4df8e02d9008..b282f7130d2b 100644
--- a/net/tipc/Makefile
+++ b/net/tipc/Makefile
@@ -8,6 +8,7 @@ tipc-y += addr.o bcast.o bearer.o config.o \
8 core.o handler.o link.o discover.o msg.o \ 8 core.o handler.o link.o discover.o msg.o \
9 name_distr.o subscr.o name_table.o net.o \ 9 name_distr.o subscr.o name_table.o net.o \
10 netlink.o node.o node_subscr.o port.o ref.o \ 10 netlink.o node.o node_subscr.o port.o ref.o \
11 socket.o log.o eth_media.o 11 socket.o log.o eth_media.o server.o
12 12
13tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o 13tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o
14tipc-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index e5f3da507823..716de1ac6cb5 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -578,8 +578,7 @@ u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr)
578 * Returns 0 (packet sent successfully) under all circumstances, 578 * Returns 0 (packet sent successfully) under all circumstances,
579 * since the broadcast link's pseudo-bearer never blocks 579 * since the broadcast link's pseudo-bearer never blocks
580 */ 580 */
581static int tipc_bcbearer_send(struct sk_buff *buf, 581static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1,
582 struct tipc_bearer *unused1,
583 struct tipc_media_addr *unused2) 582 struct tipc_media_addr *unused2)
584{ 583{
585 int bp_index; 584 int bp_index;
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index a93306557e00..6ee587b469fd 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -75,7 +75,8 @@ void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node);
75/** 75/**
76 * tipc_nmap_equal - test for equality of node maps 76 * tipc_nmap_equal - test for equality of node maps
77 */ 77 */
78static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b) 78static inline int tipc_nmap_equal(struct tipc_node_map *nm_a,
79 struct tipc_node_map *nm_b)
79{ 80{
80 return !memcmp(nm_a, nm_b, sizeof(*nm_a)); 81 return !memcmp(nm_a, nm_b, sizeof(*nm_a));
81} 82}
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}
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 7ec2c1eb94f1..fd4eeeaa972a 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -2,7 +2,7 @@
2 * net/tipc/core.c: TIPC module code 2 * net/tipc/core.c: TIPC module code
3 * 3 *
4 * Copyright (c) 2003-2006, Ericsson AB 4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005-2006, 2010-2011, Wind River Systems 5 * Copyright (c) 2005-2006, 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
@@ -39,6 +39,7 @@
39#include "name_table.h" 39#include "name_table.h"
40#include "subscr.h" 40#include "subscr.h"
41#include "config.h" 41#include "config.h"
42#include "port.h"
42 43
43#include <linux/module.h> 44#include <linux/module.h>
44 45
@@ -50,7 +51,7 @@ u32 tipc_own_addr __read_mostly;
50int tipc_max_ports __read_mostly; 51int tipc_max_ports __read_mostly;
51int tipc_net_id __read_mostly; 52int tipc_net_id __read_mostly;
52int tipc_remote_management __read_mostly; 53int tipc_remote_management __read_mostly;
53 54int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */
54 55
55/** 56/**
56 * tipc_buf_acquire - creates a TIPC message buffer 57 * tipc_buf_acquire - creates a TIPC message buffer
@@ -118,6 +119,7 @@ static void tipc_core_stop(void)
118 tipc_nametbl_stop(); 119 tipc_nametbl_stop();
119 tipc_ref_table_stop(); 120 tipc_ref_table_stop();
120 tipc_socket_stop(); 121 tipc_socket_stop();
122 tipc_unregister_sysctl();
121} 123}
122 124
123/** 125/**
@@ -135,20 +137,21 @@ static int tipc_core_start(void)
135 if (!res) 137 if (!res)
136 res = tipc_nametbl_init(); 138 res = tipc_nametbl_init();
137 if (!res) 139 if (!res)
138 res = tipc_subscr_start();
139 if (!res)
140 res = tipc_cfg_init();
141 if (!res)
142 res = tipc_netlink_start(); 140 res = tipc_netlink_start();
143 if (!res) 141 if (!res)
144 res = tipc_socket_init(); 142 res = tipc_socket_init();
143 if (!res)
144 res = tipc_register_sysctl();
145 if (!res)
146 res = tipc_subscr_start();
147 if (!res)
148 res = tipc_cfg_init();
145 if (res) 149 if (res)
146 tipc_core_stop(); 150 tipc_core_stop();
147 151
148 return res; 152 return res;
149} 153}
150 154
151
152static int __init tipc_init(void) 155static int __init tipc_init(void)
153{ 156{
154 int res; 157 int res;
@@ -160,6 +163,11 @@ static int __init tipc_init(void)
160 tipc_max_ports = CONFIG_TIPC_PORTS; 163 tipc_max_ports = CONFIG_TIPC_PORTS;
161 tipc_net_id = 4711; 164 tipc_net_id = 4711;
162 165
166 sysctl_tipc_rmem[0] = CONN_OVERLOAD_LIMIT >> 4 << TIPC_LOW_IMPORTANCE;
167 sysctl_tipc_rmem[1] = CONN_OVERLOAD_LIMIT >> 4 <<
168 TIPC_CRITICAL_IMPORTANCE;
169 sysctl_tipc_rmem[2] = CONN_OVERLOAD_LIMIT;
170
163 res = tipc_core_start(); 171 res = tipc_core_start();
164 if (res) 172 if (res)
165 pr_err("Unable to start in single node mode\n"); 173 pr_err("Unable to start in single node mode\n");
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 0207db04179a..be72f8cebc53 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -1,8 +1,8 @@
1/* 1/*
2 * net/tipc/core.h: Include file for TIPC global declarations 2 * net/tipc/core.h: Include file for TIPC global declarations
3 * 3 *
4 * Copyright (c) 2005-2006, Ericsson AB 4 * Copyright (c) 2005-2006, 2013 Ericsson AB
5 * Copyright (c) 2005-2007, 2010-2011, Wind River Systems 5 * Copyright (c) 2005-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
@@ -80,6 +80,7 @@ extern u32 tipc_own_addr __read_mostly;
80extern int tipc_max_ports __read_mostly; 80extern int tipc_max_ports __read_mostly;
81extern int tipc_net_id __read_mostly; 81extern int tipc_net_id __read_mostly;
82extern int tipc_remote_management __read_mostly; 82extern int tipc_remote_management __read_mostly;
83extern int sysctl_tipc_rmem[3] __read_mostly;
83 84
84/* 85/*
85 * Other global variables 86 * Other global variables
@@ -96,6 +97,18 @@ extern int tipc_netlink_start(void);
96extern void tipc_netlink_stop(void); 97extern void tipc_netlink_stop(void);
97extern int tipc_socket_init(void); 98extern int tipc_socket_init(void);
98extern void tipc_socket_stop(void); 99extern void tipc_socket_stop(void);
100extern int tipc_sock_create_local(int type, struct socket **res);
101extern void tipc_sock_release_local(struct socket *sock);
102extern int tipc_sock_accept_local(struct socket *sock,
103 struct socket **newsock, int flags);
104
105#ifdef CONFIG_SYSCTL
106extern int tipc_register_sysctl(void);
107extern void tipc_unregister_sysctl(void);
108#else
109#define tipc_register_sysctl() 0
110#define tipc_unregister_sysctl()
111#endif
99 112
100/* 113/*
101 * TIPC timer and signal code 114 * TIPC timer and signal code
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index eedff58d0387..ecc758c6eacf 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -70,8 +70,7 @@ struct tipc_link_req {
70 * @dest_domain: network domain of node(s) which should respond to message 70 * @dest_domain: network domain of node(s) which should respond to message
71 * @b_ptr: ptr to bearer issuing message 71 * @b_ptr: ptr to bearer issuing message
72 */ 72 */
73static struct sk_buff *tipc_disc_init_msg(u32 type, 73static struct sk_buff *tipc_disc_init_msg(u32 type, u32 dest_domain,
74 u32 dest_domain,
75 struct tipc_bearer *b_ptr) 74 struct tipc_bearer *b_ptr)
76{ 75{
77 struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE); 76 struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE);
@@ -346,8 +345,8 @@ exit:
346 * 345 *
347 * Returns 0 if successful, otherwise -errno. 346 * Returns 0 if successful, otherwise -errno.
348 */ 347 */
349int tipc_disc_create(struct tipc_bearer *b_ptr, 348int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest,
350 struct tipc_media_addr *dest, u32 dest_domain) 349 u32 dest_domain)
351{ 350{
352 struct tipc_link_req *req; 351 struct tipc_link_req *req;
353 352
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index fc60bea63169..40ea40cf6204 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -62,7 +62,7 @@ static struct eth_bearer eth_bearers[MAX_ETH_BEARERS];
62static int eth_started; 62static int eth_started;
63 63
64static int recv_notification(struct notifier_block *nb, unsigned long evt, 64static int recv_notification(struct notifier_block *nb, unsigned long evt,
65 void *dv); 65 void *dv);
66/* 66/*
67 * Network device notifier info 67 * Network device notifier info
68 */ 68 */
@@ -162,8 +162,7 @@ static void setup_bearer(struct work_struct *work)
162 */ 162 */
163static int enable_bearer(struct tipc_bearer *tb_ptr) 163static int enable_bearer(struct tipc_bearer *tb_ptr)
164{ 164{
165 struct net_device *dev = NULL; 165 struct net_device *dev;
166 struct net_device *pdev = NULL;
167 struct eth_bearer *eb_ptr = &eth_bearers[0]; 166 struct eth_bearer *eb_ptr = &eth_bearers[0];
168 struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS]; 167 struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
169 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; 168 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
@@ -178,15 +177,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr)
178 } 177 }
179 178
180 /* Find device with specified name */ 179 /* Find device with specified name */
181 read_lock(&dev_base_lock); 180 dev = dev_get_by_name(&init_net, driver_name);
182 for_each_netdev(&init_net, pdev) {
183 if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) {
184 dev = pdev;
185 dev_hold(dev);
186 break;
187 }
188 }
189 read_unlock(&dev_base_lock);
190 if (!dev) 181 if (!dev)
191 return -ENODEV; 182 return -ENODEV;
192 183
diff --git a/net/tipc/ib_media.c b/net/tipc/ib_media.c
index baa9df4327d9..ad2e1ec4117e 100644
--- a/net/tipc/ib_media.c
+++ b/net/tipc/ib_media.c
@@ -155,8 +155,7 @@ static void setup_bearer(struct work_struct *work)
155 */ 155 */
156static int enable_bearer(struct tipc_bearer *tb_ptr) 156static int enable_bearer(struct tipc_bearer *tb_ptr)
157{ 157{
158 struct net_device *dev = NULL; 158 struct net_device *dev;
159 struct net_device *pdev = NULL;
160 struct ib_bearer *ib_ptr = &ib_bearers[0]; 159 struct ib_bearer *ib_ptr = &ib_bearers[0];
161 struct ib_bearer *stop = &ib_bearers[MAX_IB_BEARERS]; 160 struct ib_bearer *stop = &ib_bearers[MAX_IB_BEARERS];
162 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; 161 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
@@ -171,15 +170,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr)
171 } 170 }
172 171
173 /* Find device with specified name */ 172 /* Find device with specified name */
174 read_lock(&dev_base_lock); 173 dev = dev_get_by_name(&init_net, driver_name);
175 for_each_netdev(&init_net, pdev) {
176 if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) {
177 dev = pdev;
178 dev_hold(dev);
179 break;
180 }
181 }
182 read_unlock(&dev_base_lock);
183 if (!dev) 174 if (!dev)
184 return -ENODEV; 175 return -ENODEV;
185 176
diff --git a/net/tipc/link.c b/net/tipc/link.c
index a80feee5197a..0cc3d9015c5d 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -2,7 +2,7 @@
2 * net/tipc/link.c: TIPC link code 2 * net/tipc/link.c: TIPC link code
3 * 3 *
4 * Copyright (c) 1996-2007, 2012, Ericsson AB 4 * Copyright (c) 1996-2007, 2012, Ericsson AB
5 * Copyright (c) 2004-2007, 2010-2011, 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
@@ -41,6 +41,8 @@
41#include "discover.h" 41#include "discover.h"
42#include "config.h" 42#include "config.h"
43 43
44#include <linux/pkt_sched.h>
45
44/* 46/*
45 * Error message prefixes 47 * Error message prefixes
46 */ 48 */
@@ -771,8 +773,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
771 * link_bundle_buf(): Append contents of a buffer to 773 * link_bundle_buf(): Append contents of a buffer to
772 * the tail of an existing one. 774 * the tail of an existing one.
773 */ 775 */
774static int link_bundle_buf(struct tipc_link *l_ptr, 776static int link_bundle_buf(struct tipc_link *l_ptr, struct sk_buff *bundler,
775 struct sk_buff *bundler,
776 struct sk_buff *buf) 777 struct sk_buff *buf)
777{ 778{
778 struct tipc_msg *bundler_msg = buf_msg(bundler); 779 struct tipc_msg *bundler_msg = buf_msg(bundler);
@@ -1057,40 +1058,6 @@ static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf,
1057} 1058}
1058 1059
1059/* 1060/*
1060 * tipc_send_buf_fast: Entry for data messages where the
1061 * destination node is known and the header is complete,
1062 * inclusive total message length.
1063 * Returns user data length.
1064 */
1065int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode)
1066{
1067 struct tipc_link *l_ptr;
1068 struct tipc_node *n_ptr;
1069 int res;
1070 u32 selector = msg_origport(buf_msg(buf)) & 1;
1071 u32 dummy;
1072
1073 read_lock_bh(&tipc_net_lock);
1074 n_ptr = tipc_node_find(destnode);
1075 if (likely(n_ptr)) {
1076 tipc_node_lock(n_ptr);
1077 l_ptr = n_ptr->active_links[selector];
1078 if (likely(l_ptr)) {
1079 res = link_send_buf_fast(l_ptr, buf, &dummy);
1080 tipc_node_unlock(n_ptr);
1081 read_unlock_bh(&tipc_net_lock);
1082 return res;
1083 }
1084 tipc_node_unlock(n_ptr);
1085 }
1086 read_unlock_bh(&tipc_net_lock);
1087 res = msg_data_sz(buf_msg(buf));
1088 tipc_reject_msg(buf, TIPC_ERR_NO_NODE);
1089 return res;
1090}
1091
1092
1093/*
1094 * tipc_link_send_sections_fast: Entry for messages where the 1061 * tipc_link_send_sections_fast: Entry for messages where the
1095 * destination processor is known and the header is complete, 1062 * destination processor is known and the header is complete,
1096 * except for total message length. 1063 * except for total message length.
@@ -1098,8 +1065,7 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode)
1098 */ 1065 */
1099int tipc_link_send_sections_fast(struct tipc_port *sender, 1066int tipc_link_send_sections_fast(struct tipc_port *sender,
1100 struct iovec const *msg_sect, 1067 struct iovec const *msg_sect,
1101 const u32 num_sect, 1068 const u32 num_sect, unsigned int total_len,
1102 unsigned int total_len,
1103 u32 destaddr) 1069 u32 destaddr)
1104{ 1070{
1105 struct tipc_msg *hdr = &sender->phdr; 1071 struct tipc_msg *hdr = &sender->phdr;
@@ -1115,7 +1081,10 @@ again:
1115 * (Must not hold any locks while building message.) 1081 * (Must not hold any locks while building message.)
1116 */ 1082 */
1117 res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, 1083 res = tipc_msg_build(hdr, msg_sect, num_sect, total_len,
1118 sender->max_pkt, !sender->user_port, &buf); 1084 sender->max_pkt, &buf);
1085 /* Exit if build request was invalid */
1086 if (unlikely(res < 0))
1087 return res;
1119 1088
1120 read_lock_bh(&tipc_net_lock); 1089 read_lock_bh(&tipc_net_lock);
1121 node = tipc_node_find(destaddr); 1090 node = tipc_node_find(destaddr);
@@ -1132,10 +1101,6 @@ exit:
1132 return res; 1101 return res;
1133 } 1102 }
1134 1103
1135 /* Exit if build request was invalid */
1136 if (unlikely(res < 0))
1137 goto exit;
1138
1139 /* Exit if link (or bearer) is congested */ 1104 /* Exit if link (or bearer) is congested */
1140 if (link_congested(l_ptr) || 1105 if (link_congested(l_ptr) ||
1141 tipc_bearer_blocked(l_ptr->b_ptr)) { 1106 tipc_bearer_blocked(l_ptr->b_ptr)) {
@@ -1189,8 +1154,7 @@ exit:
1189 */ 1154 */
1190static int link_send_sections_long(struct tipc_port *sender, 1155static int link_send_sections_long(struct tipc_port *sender,
1191 struct iovec const *msg_sect, 1156 struct iovec const *msg_sect,
1192 u32 num_sect, 1157 u32 num_sect, unsigned int total_len,
1193 unsigned int total_len,
1194 u32 destaddr) 1158 u32 destaddr)
1195{ 1159{
1196 struct tipc_link *l_ptr; 1160 struct tipc_link *l_ptr;
@@ -1204,6 +1168,7 @@ static int link_send_sections_long(struct tipc_port *sender,
1204 const unchar *sect_crs; 1168 const unchar *sect_crs;
1205 int curr_sect; 1169 int curr_sect;
1206 u32 fragm_no; 1170 u32 fragm_no;
1171 int res = 0;
1207 1172
1208again: 1173again:
1209 fragm_no = 1; 1174 fragm_no = 1;
@@ -1250,18 +1215,15 @@ again:
1250 else 1215 else
1251 sz = fragm_rest; 1216 sz = fragm_rest;
1252 1217
1253 if (likely(!sender->user_port)) { 1218 if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) {
1254 if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) { 1219 res = -EFAULT;
1255error: 1220error:
1256 for (; buf_chain; buf_chain = buf) { 1221 for (; buf_chain; buf_chain = buf) {
1257 buf = buf_chain->next; 1222 buf = buf_chain->next;
1258 kfree_skb(buf_chain); 1223 kfree_skb(buf_chain);
1259 }
1260 return -EFAULT;
1261 } 1224 }
1262 } else 1225 return res;
1263 skb_copy_to_linear_data_offset(buf, fragm_crs, 1226 }
1264 sect_crs, sz);
1265 sect_crs += sz; 1227 sect_crs += sz;
1266 sect_rest -= sz; 1228 sect_rest -= sz;
1267 fragm_crs += sz; 1229 fragm_crs += sz;
@@ -1281,8 +1243,10 @@ error:
1281 msg_set_fragm_no(&fragm_hdr, ++fragm_no); 1243 msg_set_fragm_no(&fragm_hdr, ++fragm_no);
1282 prev = buf; 1244 prev = buf;
1283 buf = tipc_buf_acquire(fragm_sz + INT_H_SIZE); 1245 buf = tipc_buf_acquire(fragm_sz + INT_H_SIZE);
1284 if (!buf) 1246 if (!buf) {
1247 res = -ENOMEM;
1285 goto error; 1248 goto error;
1249 }
1286 1250
1287 buf->next = NULL; 1251 buf->next = NULL;
1288 prev->next = buf; 1252 prev->next = buf;
@@ -1446,7 +1410,7 @@ static void link_reset_all(unsigned long addr)
1446} 1410}
1447 1411
1448static void link_retransmit_failure(struct tipc_link *l_ptr, 1412static void link_retransmit_failure(struct tipc_link *l_ptr,
1449 struct sk_buff *buf) 1413 struct sk_buff *buf)
1450{ 1414{
1451 struct tipc_msg *msg = buf_msg(buf); 1415 struct tipc_msg *msg = buf_msg(buf);
1452 1416
@@ -1901,8 +1865,8 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
1901 * Send protocol message to the other endpoint. 1865 * Send protocol message to the other endpoint.
1902 */ 1866 */
1903void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, 1867void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ,
1904 int probe_msg, u32 gap, u32 tolerance, 1868 int probe_msg, u32 gap, u32 tolerance,
1905 u32 priority, u32 ack_mtu) 1869 u32 priority, u32 ack_mtu)
1906{ 1870{
1907 struct sk_buff *buf = NULL; 1871 struct sk_buff *buf = NULL;
1908 struct tipc_msg *msg = l_ptr->pmsg; 1872 struct tipc_msg *msg = l_ptr->pmsg;
@@ -1988,6 +1952,7 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ,
1988 return; 1952 return;
1989 1953
1990 skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); 1954 skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg));
1955 buf->priority = TC_PRIO_CONTROL;
1991 1956
1992 /* Defer message if bearer is already blocked */ 1957 /* Defer message if bearer is already blocked */
1993 if (tipc_bearer_blocked(l_ptr->b_ptr)) { 1958 if (tipc_bearer_blocked(l_ptr->b_ptr)) {
@@ -2145,8 +2110,7 @@ exit:
2145 * another bearer. Owner node is locked. 2110 * another bearer. Owner node is locked.
2146 */ 2111 */
2147static void tipc_link_tunnel(struct tipc_link *l_ptr, 2112static void tipc_link_tunnel(struct tipc_link *l_ptr,
2148 struct tipc_msg *tunnel_hdr, 2113 struct tipc_msg *tunnel_hdr, struct tipc_msg *msg,
2149 struct tipc_msg *msg,
2150 u32 selector) 2114 u32 selector)
2151{ 2115{
2152 struct tipc_link *tunnel; 2116 struct tipc_link *tunnel;
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index f2db8a87d9c5..ced60e2fc4f7 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -51,8 +51,8 @@ u32 tipc_msg_tot_importance(struct tipc_msg *m)
51} 51}
52 52
53 53
54void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, 54void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize,
55 u32 hsize, u32 destnode) 55 u32 destnode)
56{ 56{
57 memset(m, 0, hsize); 57 memset(m, 0, hsize);
58 msg_set_version(m); 58 msg_set_version(m);
@@ -73,8 +73,8 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type,
73 * Returns message data size or errno 73 * Returns message data size or errno
74 */ 74 */
75int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, 75int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
76 u32 num_sect, unsigned int total_len, 76 u32 num_sect, unsigned int total_len, int max_size,
77 int max_size, int usrmem, struct sk_buff **buf) 77 struct sk_buff **buf)
78{ 78{
79 int dsz, sz, hsz, pos, res, cnt; 79 int dsz, sz, hsz, pos, res, cnt;
80 80
@@ -92,14 +92,9 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
92 return -ENOMEM; 92 return -ENOMEM;
93 skb_copy_to_linear_data(*buf, hdr, hsz); 93 skb_copy_to_linear_data(*buf, hdr, hsz);
94 for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { 94 for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) {
95 if (likely(usrmem)) 95 skb_copy_to_linear_data_offset(*buf, pos,
96 res = !copy_from_user((*buf)->data + pos, 96 msg_sect[cnt].iov_base,
97 msg_sect[cnt].iov_base, 97 msg_sect[cnt].iov_len);
98 msg_sect[cnt].iov_len);
99 else
100 skb_copy_to_linear_data_offset(*buf, pos,
101 msg_sect[cnt].iov_base,
102 msg_sect[cnt].iov_len);
103 pos += msg_sect[cnt].iov_len; 98 pos += msg_sect[cnt].iov_len;
104 } 99 }
105 if (likely(res)) 100 if (likely(res))
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index ba2a72beea68..5e4ccf5c27df 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -719,9 +719,9 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n)
719} 719}
720 720
721u32 tipc_msg_tot_importance(struct tipc_msg *m); 721u32 tipc_msg_tot_importance(struct tipc_msg *m);
722void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, 722void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize,
723 u32 hsize, u32 destnode); 723 u32 destnode);
724int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, 724int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
725 u32 num_sect, unsigned int total_len, 725 u32 num_sect, unsigned int total_len, int max_size,
726 int max_size, int usrmem, struct sk_buff **buf); 726 struct sk_buff **buf);
727#endif 727#endif
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 24b167914311..09dcd54b04e1 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -440,7 +440,7 @@ found:
440 * sequence overlapping with the requested sequence 440 * sequence overlapping with the requested sequence
441 */ 441 */
442static void tipc_nameseq_subscribe(struct name_seq *nseq, 442static void tipc_nameseq_subscribe(struct name_seq *nseq,
443 struct tipc_subscription *s) 443 struct tipc_subscription *s)
444{ 444{
445 struct sub_seq *sseq = nseq->sseqs; 445 struct sub_seq *sseq = nseq->sseqs;
446 446
@@ -662,7 +662,7 @@ exit:
662 * tipc_nametbl_publish - add name publication to network name tables 662 * tipc_nametbl_publish - add name publication to network name tables
663 */ 663 */
664struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, 664struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
665 u32 scope, u32 port_ref, u32 key) 665 u32 scope, u32 port_ref, u32 key)
666{ 666{
667 struct publication *publ; 667 struct publication *publ;
668 668
@@ -753,7 +753,7 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
753 * subseq_list - print specified sub-sequence contents into the given buffer 753 * subseq_list - print specified sub-sequence contents into the given buffer
754 */ 754 */
755static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth, 755static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth,
756 u32 index) 756 u32 index)
757{ 757{
758 char portIdStr[27]; 758 char portIdStr[27];
759 const char *scope_str[] = {"", " zone", " cluster", " node"}; 759 const char *scope_str[] = {"", " zone", " cluster", " node"};
@@ -792,7 +792,7 @@ static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth,
792 * nameseq_list - print specified name sequence contents into the given buffer 792 * nameseq_list - print specified name sequence contents into the given buffer
793 */ 793 */
794static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth, 794static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth,
795 u32 type, u32 lowbound, u32 upbound, u32 index) 795 u32 type, u32 lowbound, u32 upbound, u32 index)
796{ 796{
797 struct sub_seq *sseq; 797 struct sub_seq *sseq;
798 char typearea[11]; 798 char typearea[11];
@@ -849,7 +849,7 @@ static int nametbl_header(char *buf, int len, u32 depth)
849 * nametbl_list - print specified name table contents into the given buffer 849 * nametbl_list - print specified name table contents into the given buffer
850 */ 850 */
851static int nametbl_list(char *buf, int len, u32 depth_info, 851static int nametbl_list(char *buf, int len, u32 depth_info,
852 u32 type, u32 lowbound, u32 upbound) 852 u32 type, u32 lowbound, u32 upbound)
853{ 853{
854 struct hlist_head *seq_head; 854 struct hlist_head *seq_head;
855 struct name_seq *seq; 855 struct name_seq *seq;
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index 71cb4dc712df..f02f48b9a216 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -87,14 +87,15 @@ extern rwlock_t tipc_nametbl_lock;
87struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space); 87struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space);
88u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); 88u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node);
89int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, 89int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
90 struct tipc_port_list *dports); 90 struct tipc_port_list *dports);
91struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, 91struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
92 u32 scope, u32 port_ref, u32 key); 92 u32 scope, u32 port_ref, u32 key);
93int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); 93int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key);
94struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, 94struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
95 u32 scope, u32 node, u32 ref, u32 key); 95 u32 scope, u32 node, u32 ref,
96struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, 96 u32 key);
97 u32 node, u32 ref, u32 key); 97struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, u32 node,
98 u32 ref, u32 key);
98void tipc_nametbl_subscribe(struct tipc_subscription *s); 99void tipc_nametbl_subscribe(struct tipc_subscription *s);
99void tipc_nametbl_unsubscribe(struct tipc_subscription *s); 100void tipc_nametbl_unsubscribe(struct tipc_subscription *s);
100int tipc_nametbl_init(void); 101int tipc_nametbl_init(void);
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
index 5e34b015da45..8a7384c04add 100644
--- a/net/tipc/node_subscr.c
+++ b/net/tipc/node_subscr.c
@@ -42,7 +42,7 @@
42 * tipc_nodesub_subscribe - create "node down" subscription for specified node 42 * tipc_nodesub_subscribe - create "node down" subscription for specified node
43 */ 43 */
44void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr, 44void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr,
45 void *usr_handle, net_ev_handler handle_down) 45 void *usr_handle, net_ev_handler handle_down)
46{ 46{
47 if (in_own_node(addr)) { 47 if (in_own_node(addr)) {
48 node_sub->node = NULL; 48 node_sub->node = NULL;
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 18098cac62f2..b3ed2fcab4fb 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -2,7 +2,7 @@
2 * net/tipc/port.c: TIPC port code 2 * net/tipc/port.c: TIPC port code
3 * 3 *
4 * Copyright (c) 1992-2007, Ericsson AB 4 * Copyright (c) 1992-2007, Ericsson AB
5 * Copyright (c) 2004-2008, 2010-2011, Wind River Systems 5 * Copyright (c) 2004-2008, 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
@@ -46,11 +46,7 @@
46 46
47#define MAX_REJECT_SIZE 1024 47#define MAX_REJECT_SIZE 1024
48 48
49static struct sk_buff *msg_queue_head;
50static struct sk_buff *msg_queue_tail;
51
52DEFINE_SPINLOCK(tipc_port_list_lock); 49DEFINE_SPINLOCK(tipc_port_list_lock);
53static DEFINE_SPINLOCK(queue_lock);
54 50
55static LIST_HEAD(ports); 51static LIST_HEAD(ports);
56static void port_handle_node_down(unsigned long ref); 52static void port_handle_node_down(unsigned long ref);
@@ -119,7 +115,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq,
119 msg_set_nameupper(hdr, seq->upper); 115 msg_set_nameupper(hdr, seq->upper);
120 msg_set_hdr_sz(hdr, MCAST_H_SIZE); 116 msg_set_hdr_sz(hdr, MCAST_H_SIZE);
121 res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, 117 res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE,
122 !oport->user_port, &buf); 118 &buf);
123 if (unlikely(!buf)) 119 if (unlikely(!buf))
124 return res; 120 return res;
125 121
@@ -206,14 +202,15 @@ exit:
206} 202}
207 203
208/** 204/**
209 * tipc_createport_raw - create a generic TIPC port 205 * tipc_createport - create a generic TIPC port
210 * 206 *
211 * Returns pointer to (locked) TIPC port, or NULL if unable to create it 207 * Returns pointer to (locked) TIPC port, or NULL if unable to create it
212 */ 208 */
213struct tipc_port *tipc_createport_raw(void *usr_handle, 209struct tipc_port *tipc_createport(struct sock *sk,
214 u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), 210 u32 (*dispatcher)(struct tipc_port *,
215 void (*wakeup)(struct tipc_port *), 211 struct sk_buff *),
216 const u32 importance) 212 void (*wakeup)(struct tipc_port *),
213 const u32 importance)
217{ 214{
218 struct tipc_port *p_ptr; 215 struct tipc_port *p_ptr;
219 struct tipc_msg *msg; 216 struct tipc_msg *msg;
@@ -231,14 +228,13 @@ struct tipc_port *tipc_createport_raw(void *usr_handle,
231 return NULL; 228 return NULL;
232 } 229 }
233 230
234 p_ptr->usr_handle = usr_handle; 231 p_ptr->sk = sk;
235 p_ptr->max_pkt = MAX_PKT_DEFAULT; 232 p_ptr->max_pkt = MAX_PKT_DEFAULT;
236 p_ptr->ref = ref; 233 p_ptr->ref = ref;
237 INIT_LIST_HEAD(&p_ptr->wait_list); 234 INIT_LIST_HEAD(&p_ptr->wait_list);
238 INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); 235 INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
239 p_ptr->dispatcher = dispatcher; 236 p_ptr->dispatcher = dispatcher;
240 p_ptr->wakeup = wakeup; 237 p_ptr->wakeup = wakeup;
241 p_ptr->user_port = NULL;
242 k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); 238 k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref);
243 INIT_LIST_HEAD(&p_ptr->publications); 239 INIT_LIST_HEAD(&p_ptr->publications);
244 INIT_LIST_HEAD(&p_ptr->port_list); 240 INIT_LIST_HEAD(&p_ptr->port_list);
@@ -275,7 +271,6 @@ int tipc_deleteport(u32 ref)
275 buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); 271 buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
276 tipc_nodesub_unsubscribe(&p_ptr->subscription); 272 tipc_nodesub_unsubscribe(&p_ptr->subscription);
277 } 273 }
278 kfree(p_ptr->user_port);
279 274
280 spin_lock_bh(&tipc_port_list_lock); 275 spin_lock_bh(&tipc_port_list_lock);
281 list_del(&p_ptr->port_list); 276 list_del(&p_ptr->port_list);
@@ -448,7 +443,7 @@ int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr,
448 int res; 443 int res;
449 444
450 res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, 445 res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE,
451 !p_ptr->user_port, &buf); 446 &buf);
452 if (!buf) 447 if (!buf)
453 return res; 448 return res;
454 449
@@ -668,215 +663,6 @@ void tipc_port_reinit(void)
668 spin_unlock_bh(&tipc_port_list_lock); 663 spin_unlock_bh(&tipc_port_list_lock);
669} 664}
670 665
671
672/*
673 * port_dispatcher_sigh(): Signal handler for messages destinated
674 * to the tipc_port interface.
675 */
676static void port_dispatcher_sigh(void *dummy)
677{
678 struct sk_buff *buf;
679
680 spin_lock_bh(&queue_lock);
681 buf = msg_queue_head;
682 msg_queue_head = NULL;
683 spin_unlock_bh(&queue_lock);
684
685 while (buf) {
686 struct tipc_port *p_ptr;
687 struct user_port *up_ptr;
688 struct tipc_portid orig;
689 struct tipc_name_seq dseq;
690 void *usr_handle;
691 int connected;
692 int peer_invalid;
693 int published;
694 u32 message_type;
695
696 struct sk_buff *next = buf->next;
697 struct tipc_msg *msg = buf_msg(buf);
698 u32 dref = msg_destport(msg);
699
700 message_type = msg_type(msg);
701 if (message_type > TIPC_DIRECT_MSG)
702 goto reject; /* Unsupported message type */
703
704 p_ptr = tipc_port_lock(dref);
705 if (!p_ptr)
706 goto reject; /* Port deleted while msg in queue */
707
708 orig.ref = msg_origport(msg);
709 orig.node = msg_orignode(msg);
710 up_ptr = p_ptr->user_port;
711 usr_handle = up_ptr->usr_handle;
712 connected = p_ptr->connected;
713 peer_invalid = connected && !tipc_port_peer_msg(p_ptr, msg);
714 published = p_ptr->published;
715
716 if (unlikely(msg_errcode(msg)))
717 goto err;
718
719 switch (message_type) {
720
721 case TIPC_CONN_MSG:{
722 tipc_conn_msg_event cb = up_ptr->conn_msg_cb;
723 u32 dsz;
724
725 tipc_port_unlock(p_ptr);
726 if (unlikely(!cb))
727 goto reject;
728 if (unlikely(!connected)) {
729 if (tipc_connect(dref, &orig))
730 goto reject;
731 } else if (peer_invalid)
732 goto reject;
733 dsz = msg_data_sz(msg);
734 if (unlikely(dsz &&
735 (++p_ptr->conn_unacked >=
736 TIPC_FLOW_CONTROL_WIN)))
737 tipc_acknowledge(dref,
738 p_ptr->conn_unacked);
739 skb_pull(buf, msg_hdr_sz(msg));
740 cb(usr_handle, dref, &buf, msg_data(msg), dsz);
741 break;
742 }
743 case TIPC_DIRECT_MSG:{
744 tipc_msg_event cb = up_ptr->msg_cb;
745
746 tipc_port_unlock(p_ptr);
747 if (unlikely(!cb || connected))
748 goto reject;
749 skb_pull(buf, msg_hdr_sz(msg));
750 cb(usr_handle, dref, &buf, msg_data(msg),
751 msg_data_sz(msg), msg_importance(msg),
752 &orig);
753 break;
754 }
755 case TIPC_MCAST_MSG:
756 case TIPC_NAMED_MSG:{
757 tipc_named_msg_event cb = up_ptr->named_msg_cb;
758
759 tipc_port_unlock(p_ptr);
760 if (unlikely(!cb || connected || !published))
761 goto reject;
762 dseq.type = msg_nametype(msg);
763 dseq.lower = msg_nameinst(msg);
764 dseq.upper = (message_type == TIPC_NAMED_MSG)
765 ? dseq.lower : msg_nameupper(msg);
766 skb_pull(buf, msg_hdr_sz(msg));
767 cb(usr_handle, dref, &buf, msg_data(msg),
768 msg_data_sz(msg), msg_importance(msg),
769 &orig, &dseq);
770 break;
771 }
772 }
773 if (buf)
774 kfree_skb(buf);
775 buf = next;
776 continue;
777err:
778 switch (message_type) {
779
780 case TIPC_CONN_MSG:{
781 tipc_conn_shutdown_event cb =
782 up_ptr->conn_err_cb;
783
784 tipc_port_unlock(p_ptr);
785 if (!cb || !connected || peer_invalid)
786 break;
787 tipc_disconnect(dref);
788 skb_pull(buf, msg_hdr_sz(msg));
789 cb(usr_handle, dref, &buf, msg_data(msg),
790 msg_data_sz(msg), msg_errcode(msg));
791 break;
792 }
793 case TIPC_DIRECT_MSG:{
794 tipc_msg_err_event cb = up_ptr->err_cb;
795
796 tipc_port_unlock(p_ptr);
797 if (!cb || connected)
798 break;
799 skb_pull(buf, msg_hdr_sz(msg));
800 cb(usr_handle, dref, &buf, msg_data(msg),
801 msg_data_sz(msg), msg_errcode(msg), &orig);
802 break;
803 }
804 case TIPC_MCAST_MSG:
805 case TIPC_NAMED_MSG:{
806 tipc_named_msg_err_event cb =
807 up_ptr->named_err_cb;
808
809 tipc_port_unlock(p_ptr);
810 if (!cb || connected)
811 break;
812 dseq.type = msg_nametype(msg);
813 dseq.lower = msg_nameinst(msg);
814 dseq.upper = (message_type == TIPC_NAMED_MSG)
815 ? dseq.lower : msg_nameupper(msg);
816 skb_pull(buf, msg_hdr_sz(msg));
817 cb(usr_handle, dref, &buf, msg_data(msg),
818 msg_data_sz(msg), msg_errcode(msg), &dseq);
819 break;
820 }
821 }
822 if (buf)
823 kfree_skb(buf);
824 buf = next;
825 continue;
826reject:
827 tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
828 buf = next;
829 }
830}
831
832/*
833 * port_dispatcher(): Dispatcher for messages destinated
834 * to the tipc_port interface. Called with port locked.
835 */
836static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf)
837{
838 buf->next = NULL;
839 spin_lock_bh(&queue_lock);
840 if (msg_queue_head) {
841 msg_queue_tail->next = buf;
842 msg_queue_tail = buf;
843 } else {
844 msg_queue_tail = msg_queue_head = buf;
845 tipc_k_signal((Handler)port_dispatcher_sigh, 0);
846 }
847 spin_unlock_bh(&queue_lock);
848 return 0;
849}
850
851/*
852 * Wake up port after congestion: Called with port locked
853 */
854static void port_wakeup_sh(unsigned long ref)
855{
856 struct tipc_port *p_ptr;
857 struct user_port *up_ptr;
858 tipc_continue_event cb = NULL;
859 void *uh = NULL;
860
861 p_ptr = tipc_port_lock(ref);
862 if (p_ptr) {
863 up_ptr = p_ptr->user_port;
864 if (up_ptr) {
865 cb = up_ptr->continue_event_cb;
866 uh = up_ptr->usr_handle;
867 }
868 tipc_port_unlock(p_ptr);
869 }
870 if (cb)
871 cb(uh, ref);
872}
873
874
875static void port_wakeup(struct tipc_port *p_ptr)
876{
877 tipc_k_signal((Handler)port_wakeup_sh, p_ptr->ref);
878}
879
880void tipc_acknowledge(u32 ref, u32 ack) 666void tipc_acknowledge(u32 ref, u32 ack)
881{ 667{
882 struct tipc_port *p_ptr; 668 struct tipc_port *p_ptr;
@@ -893,50 +679,6 @@ void tipc_acknowledge(u32 ref, u32 ack)
893 tipc_net_route_msg(buf); 679 tipc_net_route_msg(buf);
894} 680}
895 681
896/*
897 * tipc_createport(): user level call.
898 */
899int tipc_createport(void *usr_handle,
900 unsigned int importance,
901 tipc_msg_err_event error_cb,
902 tipc_named_msg_err_event named_error_cb,
903 tipc_conn_shutdown_event conn_error_cb,
904 tipc_msg_event msg_cb,
905 tipc_named_msg_event named_msg_cb,
906 tipc_conn_msg_event conn_msg_cb,
907 tipc_continue_event continue_event_cb, /* May be zero */
908 u32 *portref)
909{
910 struct user_port *up_ptr;
911 struct tipc_port *p_ptr;
912
913 up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
914 if (!up_ptr) {
915 pr_warn("Port creation failed, no memory\n");
916 return -ENOMEM;
917 }
918 p_ptr = tipc_createport_raw(NULL, port_dispatcher, port_wakeup,
919 importance);
920 if (!p_ptr) {
921 kfree(up_ptr);
922 return -ENOMEM;
923 }
924
925 p_ptr->user_port = up_ptr;
926 up_ptr->usr_handle = usr_handle;
927 up_ptr->ref = p_ptr->ref;
928 up_ptr->err_cb = error_cb;
929 up_ptr->named_err_cb = named_error_cb;
930 up_ptr->conn_err_cb = conn_error_cb;
931 up_ptr->msg_cb = msg_cb;
932 up_ptr->named_msg_cb = named_msg_cb;
933 up_ptr->conn_msg_cb = conn_msg_cb;
934 up_ptr->continue_event_cb = continue_event_cb;
935 *portref = p_ptr->ref;
936 tipc_port_unlock(p_ptr);
937 return 0;
938}
939
940int tipc_portimportance(u32 ref, unsigned int *importance) 682int tipc_portimportance(u32 ref, unsigned int *importance)
941{ 683{
942 struct tipc_port *p_ptr; 684 struct tipc_port *p_ptr;
@@ -1184,7 +926,7 @@ static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_se
1184 int res; 926 int res;
1185 927
1186 res = tipc_msg_build(&sender->phdr, msg_sect, num_sect, total_len, 928 res = tipc_msg_build(&sender->phdr, msg_sect, num_sect, total_len,
1187 MAX_MSG_SIZE, !sender->user_port, &buf); 929 MAX_MSG_SIZE, &buf);
1188 if (likely(buf)) 930 if (likely(buf))
1189 tipc_port_recv_msg(buf); 931 tipc_port_recv_msg(buf);
1190 return res; 932 return res;
@@ -1322,43 +1064,3 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest,
1322 } 1064 }
1323 return -ELINKCONG; 1065 return -ELINKCONG;
1324} 1066}
1325
1326/**
1327 * tipc_send_buf2port - send message buffer to port identity
1328 */
1329int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest,
1330 struct sk_buff *buf, unsigned int dsz)
1331{
1332 struct tipc_port *p_ptr;
1333 struct tipc_msg *msg;
1334 int res;
1335
1336 p_ptr = (struct tipc_port *)tipc_ref_deref(ref);
1337 if (!p_ptr || p_ptr->connected)
1338 return -EINVAL;
1339
1340 msg = &p_ptr->phdr;
1341 msg_set_type(msg, TIPC_DIRECT_MSG);
1342 msg_set_destnode(msg, dest->node);
1343 msg_set_destport(msg, dest->ref);
1344 msg_set_hdr_sz(msg, BASIC_H_SIZE);
1345 msg_set_size(msg, BASIC_H_SIZE + dsz);
1346 if (skb_cow(buf, BASIC_H_SIZE))
1347 return -ENOMEM;
1348
1349 skb_push(buf, BASIC_H_SIZE);
1350 skb_copy_to_linear_data(buf, msg, BASIC_H_SIZE);
1351
1352 if (in_own_node(dest->node))
1353 res = tipc_port_recv_msg(buf);
1354 else
1355 res = tipc_send_buf_fast(buf, dest->node);
1356 if (likely(res != -ELINKCONG)) {
1357 if (res > 0)
1358 p_ptr->sent++;
1359 return res;
1360 }
1361 if (port_unreliable(p_ptr))
1362 return dsz;
1363 return -ELINKCONG;
1364}
diff --git a/net/tipc/port.h b/net/tipc/port.h
index fb66e2e5f4d1..5a7026b9c345 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -2,7 +2,7 @@
2 * net/tipc/port.h: Include file for TIPC port code 2 * net/tipc/port.h: Include file for TIPC port code
3 * 3 *
4 * Copyright (c) 1994-2007, Ericsson AB 4 * Copyright (c) 1994-2007, Ericsson AB
5 * Copyright (c) 2004-2007, 2010-2011, 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
@@ -43,60 +43,12 @@
43#include "node_subscr.h" 43#include "node_subscr.h"
44 44
45#define TIPC_FLOW_CONTROL_WIN 512 45#define TIPC_FLOW_CONTROL_WIN 512
46 46#define CONN_OVERLOAD_LIMIT ((TIPC_FLOW_CONTROL_WIN * 2 + 1) * \
47typedef void (*tipc_msg_err_event) (void *usr_handle, u32 portref, 47 SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE))
48 struct sk_buff **buf, unsigned char const *data,
49 unsigned int size, int reason,
50 struct tipc_portid const *attmpt_destid);
51
52typedef void (*tipc_named_msg_err_event) (void *usr_handle, u32 portref,
53 struct sk_buff **buf, unsigned char const *data,
54 unsigned int size, int reason,
55 struct tipc_name_seq const *attmpt_dest);
56
57typedef void (*tipc_conn_shutdown_event) (void *usr_handle, u32 portref,
58 struct sk_buff **buf, unsigned char const *data,
59 unsigned int size, int reason);
60
61typedef void (*tipc_msg_event) (void *usr_handle, u32 portref,
62 struct sk_buff **buf, unsigned char const *data,
63 unsigned int size, unsigned int importance,
64 struct tipc_portid const *origin);
65
66typedef void (*tipc_named_msg_event) (void *usr_handle, u32 portref,
67 struct sk_buff **buf, unsigned char const *data,
68 unsigned int size, unsigned int importance,
69 struct tipc_portid const *orig,
70 struct tipc_name_seq const *dest);
71
72typedef void (*tipc_conn_msg_event) (void *usr_handle, u32 portref,
73 struct sk_buff **buf, unsigned char const *data,
74 unsigned int size);
75
76typedef void (*tipc_continue_event) (void *usr_handle, u32 portref);
77
78/**
79 * struct user_port - TIPC user port (used with native API)
80 * @usr_handle: user-specified field
81 * @ref: object reference to associated TIPC port
82 *
83 * <various callback routines>
84 */
85struct user_port {
86 void *usr_handle;
87 u32 ref;
88 tipc_msg_err_event err_cb;
89 tipc_named_msg_err_event named_err_cb;
90 tipc_conn_shutdown_event conn_err_cb;
91 tipc_msg_event msg_cb;
92 tipc_named_msg_event named_msg_cb;
93 tipc_conn_msg_event conn_msg_cb;
94 tipc_continue_event continue_event_cb;
95};
96 48
97/** 49/**
98 * struct tipc_port - TIPC port structure 50 * struct tipc_port - TIPC port structure
99 * @usr_handle: pointer to additional user-defined information about port 51 * @sk: pointer to socket handle
100 * @lock: pointer to spinlock for controlling access to port 52 * @lock: pointer to spinlock for controlling access to port
101 * @connected: non-zero if port is currently connected to a peer port 53 * @connected: non-zero if port is currently connected to a peer port
102 * @conn_type: TIPC type used when connection was established 54 * @conn_type: TIPC type used when connection was established
@@ -110,7 +62,6 @@ struct user_port {
110 * @port_list: adjacent ports in TIPC's global list of ports 62 * @port_list: adjacent ports in TIPC's global list of ports
111 * @dispatcher: ptr to routine which handles received messages 63 * @dispatcher: ptr to routine which handles received messages
112 * @wakeup: ptr to routine to call when port is no longer congested 64 * @wakeup: ptr to routine to call when port is no longer congested
113 * @user_port: ptr to user port associated with port (if any)
114 * @wait_list: adjacent ports in list of ports waiting on link congestion 65 * @wait_list: adjacent ports in list of ports waiting on link congestion
115 * @waiting_pkts: 66 * @waiting_pkts:
116 * @sent: # of non-empty messages sent by port 67 * @sent: # of non-empty messages sent by port
@@ -123,7 +74,7 @@ struct user_port {
123 * @subscription: "node down" subscription used to terminate failed connections 74 * @subscription: "node down" subscription used to terminate failed connections
124 */ 75 */
125struct tipc_port { 76struct tipc_port {
126 void *usr_handle; 77 struct sock *sk;
127 spinlock_t *lock; 78 spinlock_t *lock;
128 int connected; 79 int connected;
129 u32 conn_type; 80 u32 conn_type;
@@ -137,7 +88,6 @@ struct tipc_port {
137 struct list_head port_list; 88 struct list_head port_list;
138 u32 (*dispatcher)(struct tipc_port *, struct sk_buff *); 89 u32 (*dispatcher)(struct tipc_port *, struct sk_buff *);
139 void (*wakeup)(struct tipc_port *); 90 void (*wakeup)(struct tipc_port *);
140 struct user_port *user_port;
141 struct list_head wait_list; 91 struct list_head wait_list;
142 u32 waiting_pkts; 92 u32 waiting_pkts;
143 u32 sent; 93 u32 sent;
@@ -156,24 +106,16 @@ struct tipc_port_list;
156/* 106/*
157 * TIPC port manipulation routines 107 * TIPC port manipulation routines
158 */ 108 */
159struct tipc_port *tipc_createport_raw(void *usr_handle, 109struct tipc_port *tipc_createport(struct sock *sk,
160 u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), 110 u32 (*dispatcher)(struct tipc_port *,
161 void (*wakeup)(struct tipc_port *), const u32 importance); 111 struct sk_buff *),
112 void (*wakeup)(struct tipc_port *),
113 const u32 importance);
162 114
163int tipc_reject_msg(struct sk_buff *buf, u32 err); 115int tipc_reject_msg(struct sk_buff *buf, u32 err);
164 116
165int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode);
166
167void tipc_acknowledge(u32 port_ref, u32 ack); 117void tipc_acknowledge(u32 port_ref, u32 ack);
168 118
169int tipc_createport(void *usr_handle,
170 unsigned int importance, tipc_msg_err_event error_cb,
171 tipc_named_msg_err_event named_error_cb,
172 tipc_conn_shutdown_event conn_error_cb, tipc_msg_event msg_cb,
173 tipc_named_msg_event named_msg_cb,
174 tipc_conn_msg_event conn_msg_cb,
175 tipc_continue_event continue_event_cb, u32 *portref);
176
177int tipc_deleteport(u32 portref); 119int tipc_deleteport(u32 portref);
178 120
179int tipc_portimportance(u32 portref, unsigned int *importance); 121int tipc_portimportance(u32 portref, unsigned int *importance);
@@ -186,9 +128,9 @@ int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable);
186int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); 128int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable);
187 129
188int tipc_publish(u32 portref, unsigned int scope, 130int tipc_publish(u32 portref, unsigned int scope,
189 struct tipc_name_seq const *name_seq); 131 struct tipc_name_seq const *name_seq);
190int tipc_withdraw(u32 portref, unsigned int scope, 132int tipc_withdraw(u32 portref, unsigned int scope,
191 struct tipc_name_seq const *name_seq); 133 struct tipc_name_seq const *name_seq);
192 134
193int tipc_connect(u32 portref, struct tipc_portid const *port); 135int tipc_connect(u32 portref, struct tipc_portid const *port);
194 136
@@ -220,9 +162,6 @@ int tipc_send2port(u32 portref, struct tipc_portid const *dest,
220 unsigned int num_sect, struct iovec const *msg_sect, 162 unsigned int num_sect, struct iovec const *msg_sect,
221 unsigned int total_len); 163 unsigned int total_len);
222 164
223int tipc_send_buf2port(u32 portref, struct tipc_portid const *dest,
224 struct sk_buff *buf, unsigned int dsz);
225
226int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, 165int tipc_multicast(u32 portref, struct tipc_name_seq const *seq,
227 unsigned int section_count, struct iovec const *msg, 166 unsigned int section_count, struct iovec const *msg,
228 unsigned int total_len); 167 unsigned int total_len);
diff --git a/net/tipc/server.c b/net/tipc/server.c
new file mode 100644
index 000000000000..19da5abe0fa6
--- /dev/null
+++ b/net/tipc/server.c
@@ -0,0 +1,596 @@
1/*
2 * net/tipc/server.c: TIPC server infrastructure
3 *
4 * Copyright (c) 2012-2013, Wind River Systems
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the names of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU General Public License ("GPL") version 2 as published by the Free
21 * Software Foundation.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include "server.h"
37#include "core.h"
38#include <net/sock.h>
39
40/* Number of messages to send before rescheduling */
41#define MAX_SEND_MSG_COUNT 25
42#define MAX_RECV_MSG_COUNT 25
43#define CF_CONNECTED 1
44
45#define sock2con(x) ((struct tipc_conn *)(x)->sk_user_data)
46
47/**
48 * struct tipc_conn - TIPC connection structure
49 * @kref: reference counter to connection object
50 * @conid: connection identifier
51 * @sock: socket handler associated with connection
52 * @flags: indicates connection state
53 * @server: pointer to connected server
54 * @rwork: receive work item
55 * @usr_data: user-specified field
56 * @rx_action: what to do when connection socket is active
57 * @outqueue: pointer to first outbound message in queue
58 * @outqueue_lock: controll access to the outqueue
59 * @outqueue: list of connection objects for its server
60 * @swork: send work item
61 */
62struct tipc_conn {
63 struct kref kref;
64 int conid;
65 struct socket *sock;
66 unsigned long flags;
67 struct tipc_server *server;
68 struct work_struct rwork;
69 int (*rx_action) (struct tipc_conn *con);
70 void *usr_data;
71 struct list_head outqueue;
72 spinlock_t outqueue_lock;
73 struct work_struct swork;
74};
75
76/* An entry waiting to be sent */
77struct outqueue_entry {
78 struct list_head list;
79 struct kvec iov;
80 struct sockaddr_tipc dest;
81};
82
83static void tipc_recv_work(struct work_struct *work);
84static void tipc_send_work(struct work_struct *work);
85static void tipc_clean_outqueues(struct tipc_conn *con);
86
87static void tipc_conn_kref_release(struct kref *kref)
88{
89 struct tipc_conn *con = container_of(kref, struct tipc_conn, kref);
90 struct tipc_server *s = con->server;
91
92 if (con->sock) {
93 tipc_sock_release_local(con->sock);
94 con->sock = NULL;
95 }
96
97 tipc_clean_outqueues(con);
98
99 if (con->conid)
100 s->tipc_conn_shutdown(con->conid, con->usr_data);
101
102 kfree(con);
103}
104
105static void conn_put(struct tipc_conn *con)
106{
107 kref_put(&con->kref, tipc_conn_kref_release);
108}
109
110static void conn_get(struct tipc_conn *con)
111{
112 kref_get(&con->kref);
113}
114
115static struct tipc_conn *tipc_conn_lookup(struct tipc_server *s, int conid)
116{
117 struct tipc_conn *con;
118
119 spin_lock_bh(&s->idr_lock);
120 con = idr_find(&s->conn_idr, conid);
121 if (con)
122 conn_get(con);
123 spin_unlock_bh(&s->idr_lock);
124 return con;
125}
126
127static void sock_data_ready(struct sock *sk, int unused)
128{
129 struct tipc_conn *con;
130
131 read_lock(&sk->sk_callback_lock);
132 con = sock2con(sk);
133 if (con && test_bit(CF_CONNECTED, &con->flags)) {
134 conn_get(con);
135 if (!queue_work(con->server->rcv_wq, &con->rwork))
136 conn_put(con);
137 }
138 read_unlock(&sk->sk_callback_lock);
139}
140
141static void sock_write_space(struct sock *sk)
142{
143 struct tipc_conn *con;
144
145 read_lock(&sk->sk_callback_lock);
146 con = sock2con(sk);
147 if (con && test_bit(CF_CONNECTED, &con->flags)) {
148 conn_get(con);
149 if (!queue_work(con->server->send_wq, &con->swork))
150 conn_put(con);
151 }
152 read_unlock(&sk->sk_callback_lock);
153}
154
155static void tipc_register_callbacks(struct socket *sock, struct tipc_conn *con)
156{
157 struct sock *sk = sock->sk;
158
159 write_lock_bh(&sk->sk_callback_lock);
160
161 sk->sk_data_ready = sock_data_ready;
162 sk->sk_write_space = sock_write_space;
163 sk->sk_user_data = con;
164
165 con->sock = sock;
166
167 write_unlock_bh(&sk->sk_callback_lock);
168}
169
170static void tipc_unregister_callbacks(struct tipc_conn *con)
171{
172 struct sock *sk = con->sock->sk;
173
174 write_lock_bh(&sk->sk_callback_lock);
175 sk->sk_user_data = NULL;
176 write_unlock_bh(&sk->sk_callback_lock);
177}
178
179static void tipc_close_conn(struct tipc_conn *con)
180{
181 struct tipc_server *s = con->server;
182
183 if (test_and_clear_bit(CF_CONNECTED, &con->flags)) {
184 spin_lock_bh(&s->idr_lock);
185 idr_remove(&s->conn_idr, con->conid);
186 s->idr_in_use--;
187 spin_unlock_bh(&s->idr_lock);
188
189 tipc_unregister_callbacks(con);
190
191 /* We shouldn't flush pending works as we may be in the
192 * thread. In fact the races with pending rx/tx work structs
193 * are harmless for us here as we have already deleted this
194 * connection from server connection list and set
195 * sk->sk_user_data to 0 before releasing connection object.
196 */
197 kernel_sock_shutdown(con->sock, SHUT_RDWR);
198
199 conn_put(con);
200 }
201}
202
203static struct tipc_conn *tipc_alloc_conn(struct tipc_server *s)
204{
205 struct tipc_conn *con;
206 int ret;
207
208 con = kzalloc(sizeof(struct tipc_conn), GFP_ATOMIC);
209 if (!con)
210 return ERR_PTR(-ENOMEM);
211
212 kref_init(&con->kref);
213 INIT_LIST_HEAD(&con->outqueue);
214 spin_lock_init(&con->outqueue_lock);
215 INIT_WORK(&con->swork, tipc_send_work);
216 INIT_WORK(&con->rwork, tipc_recv_work);
217
218 spin_lock_bh(&s->idr_lock);
219 ret = idr_alloc(&s->conn_idr, con, 0, 0, GFP_ATOMIC);
220 if (ret < 0) {
221 kfree(con);
222 spin_unlock_bh(&s->idr_lock);
223 return ERR_PTR(-ENOMEM);
224 }
225 con->conid = ret;
226 s->idr_in_use++;
227 spin_unlock_bh(&s->idr_lock);
228
229 set_bit(CF_CONNECTED, &con->flags);
230 con->server = s;
231
232 return con;
233}
234
235static int tipc_receive_from_sock(struct tipc_conn *con)
236{
237 struct msghdr msg = {};
238 struct tipc_server *s = con->server;
239 struct sockaddr_tipc addr;
240 struct kvec iov;
241 void *buf;
242 int ret;
243
244 buf = kmem_cache_alloc(s->rcvbuf_cache, GFP_ATOMIC);
245 if (!buf) {
246 ret = -ENOMEM;
247 goto out_close;
248 }
249
250 iov.iov_base = buf;
251 iov.iov_len = s->max_rcvbuf_size;
252 msg.msg_name = &addr;
253 ret = kernel_recvmsg(con->sock, &msg, &iov, 1, iov.iov_len,
254 MSG_DONTWAIT);
255 if (ret <= 0) {
256 kmem_cache_free(s->rcvbuf_cache, buf);
257 goto out_close;
258 }
259
260 s->tipc_conn_recvmsg(con->conid, &addr, con->usr_data, buf, ret);
261
262 kmem_cache_free(s->rcvbuf_cache, buf);
263
264 return 0;
265
266out_close:
267 if (ret != -EWOULDBLOCK)
268 tipc_close_conn(con);
269 else if (ret == 0)
270 /* Don't return success if we really got EOF */
271 ret = -EAGAIN;
272
273 return ret;
274}
275
276static int tipc_accept_from_sock(struct tipc_conn *con)
277{
278 struct tipc_server *s = con->server;
279 struct socket *sock = con->sock;
280 struct socket *newsock;
281 struct tipc_conn *newcon;
282 int ret;
283
284 ret = tipc_sock_accept_local(sock, &newsock, O_NONBLOCK);
285 if (ret < 0)
286 return ret;
287
288 newcon = tipc_alloc_conn(con->server);
289 if (IS_ERR(newcon)) {
290 ret = PTR_ERR(newcon);
291 sock_release(newsock);
292 return ret;
293 }
294
295 newcon->rx_action = tipc_receive_from_sock;
296 tipc_register_callbacks(newsock, newcon);
297
298 /* Notify that new connection is incoming */
299 newcon->usr_data = s->tipc_conn_new(newcon->conid);
300
301 /* Wake up receive process in case of 'SYN+' message */
302 newsock->sk->sk_data_ready(newsock->sk, 0);
303 return ret;
304}
305
306static struct socket *tipc_create_listen_sock(struct tipc_conn *con)
307{
308 struct tipc_server *s = con->server;
309 struct socket *sock = NULL;
310 int ret;
311
312 ret = tipc_sock_create_local(s->type, &sock);
313 if (ret < 0)
314 return NULL;
315 ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE,
316 (char *)&s->imp, sizeof(s->imp));
317 if (ret < 0)
318 goto create_err;
319 ret = kernel_bind(sock, (struct sockaddr *)s->saddr, sizeof(*s->saddr));
320 if (ret < 0)
321 goto create_err;
322
323 switch (s->type) {
324 case SOCK_STREAM:
325 case SOCK_SEQPACKET:
326 con->rx_action = tipc_accept_from_sock;
327
328 ret = kernel_listen(sock, 0);
329 if (ret < 0)
330 goto create_err;
331 break;
332 case SOCK_DGRAM:
333 case SOCK_RDM:
334 con->rx_action = tipc_receive_from_sock;
335 break;
336 default:
337 pr_err("Unknown socket type %d\n", s->type);
338 goto create_err;
339 }
340 return sock;
341
342create_err:
343 sock_release(sock);
344 con->sock = NULL;
345 return NULL;
346}
347
348static int tipc_open_listening_sock(struct tipc_server *s)
349{
350 struct socket *sock;
351 struct tipc_conn *con;
352
353 con = tipc_alloc_conn(s);
354 if (IS_ERR(con))
355 return PTR_ERR(con);
356
357 sock = tipc_create_listen_sock(con);
358 if (!sock)
359 return -EINVAL;
360
361 tipc_register_callbacks(sock, con);
362 return 0;
363}
364
365static struct outqueue_entry *tipc_alloc_entry(void *data, int len)
366{
367 struct outqueue_entry *entry;
368 void *buf;
369
370 entry = kmalloc(sizeof(struct outqueue_entry), GFP_ATOMIC);
371 if (!entry)
372 return NULL;
373
374 buf = kmalloc(len, GFP_ATOMIC);
375 if (!buf) {
376 kfree(entry);
377 return NULL;
378 }
379
380 memcpy(buf, data, len);
381 entry->iov.iov_base = buf;
382 entry->iov.iov_len = len;
383
384 return entry;
385}
386
387static void tipc_free_entry(struct outqueue_entry *e)
388{
389 kfree(e->iov.iov_base);
390 kfree(e);
391}
392
393static void tipc_clean_outqueues(struct tipc_conn *con)
394{
395 struct outqueue_entry *e, *safe;
396
397 spin_lock_bh(&con->outqueue_lock);
398 list_for_each_entry_safe(e, safe, &con->outqueue, list) {
399 list_del(&e->list);
400 tipc_free_entry(e);
401 }
402 spin_unlock_bh(&con->outqueue_lock);
403}
404
405int tipc_conn_sendmsg(struct tipc_server *s, int conid,
406 struct sockaddr_tipc *addr, void *data, size_t len)
407{
408 struct outqueue_entry *e;
409 struct tipc_conn *con;
410
411 con = tipc_conn_lookup(s, conid);
412 if (!con)
413 return -EINVAL;
414
415 e = tipc_alloc_entry(data, len);
416 if (!e) {
417 conn_put(con);
418 return -ENOMEM;
419 }
420
421 if (addr)
422 memcpy(&e->dest, addr, sizeof(struct sockaddr_tipc));
423
424 spin_lock_bh(&con->outqueue_lock);
425 list_add_tail(&e->list, &con->outqueue);
426 spin_unlock_bh(&con->outqueue_lock);
427
428 if (test_bit(CF_CONNECTED, &con->flags))
429 if (!queue_work(s->send_wq, &con->swork))
430 conn_put(con);
431
432 return 0;
433}
434
435void tipc_conn_terminate(struct tipc_server *s, int conid)
436{
437 struct tipc_conn *con;
438
439 con = tipc_conn_lookup(s, conid);
440 if (con) {
441 tipc_close_conn(con);
442 conn_put(con);
443 }
444}
445
446static void tipc_send_to_sock(struct tipc_conn *con)
447{
448 int count = 0;
449 struct tipc_server *s = con->server;
450 struct outqueue_entry *e;
451 struct msghdr msg;
452 int ret;
453
454 spin_lock_bh(&con->outqueue_lock);
455 while (1) {
456 e = list_entry(con->outqueue.next, struct outqueue_entry,
457 list);
458 if ((struct list_head *) e == &con->outqueue)
459 break;
460 spin_unlock_bh(&con->outqueue_lock);
461
462 memset(&msg, 0, sizeof(msg));
463 msg.msg_flags = MSG_DONTWAIT;
464
465 if (s->type == SOCK_DGRAM || s->type == SOCK_RDM) {
466 msg.msg_name = &e->dest;
467 msg.msg_namelen = sizeof(struct sockaddr_tipc);
468 }
469 ret = kernel_sendmsg(con->sock, &msg, &e->iov, 1,
470 e->iov.iov_len);
471 if (ret == -EWOULDBLOCK || ret == 0) {
472 cond_resched();
473 goto out;
474 } else if (ret < 0) {
475 goto send_err;
476 }
477
478 /* Don't starve users filling buffers */
479 if (++count >= MAX_SEND_MSG_COUNT) {
480 cond_resched();
481 count = 0;
482 }
483
484 spin_lock_bh(&con->outqueue_lock);
485 list_del(&e->list);
486 tipc_free_entry(e);
487 }
488 spin_unlock_bh(&con->outqueue_lock);
489out:
490 return;
491
492send_err:
493 tipc_close_conn(con);
494}
495
496static void tipc_recv_work(struct work_struct *work)
497{
498 struct tipc_conn *con = container_of(work, struct tipc_conn, rwork);
499 int count = 0;
500
501 while (test_bit(CF_CONNECTED, &con->flags)) {
502 if (con->rx_action(con))
503 break;
504
505 /* Don't flood Rx machine */
506 if (++count >= MAX_RECV_MSG_COUNT) {
507 cond_resched();
508 count = 0;
509 }
510 }
511 conn_put(con);
512}
513
514static void tipc_send_work(struct work_struct *work)
515{
516 struct tipc_conn *con = container_of(work, struct tipc_conn, swork);
517
518 if (test_bit(CF_CONNECTED, &con->flags))
519 tipc_send_to_sock(con);
520
521 conn_put(con);
522}
523
524static void tipc_work_stop(struct tipc_server *s)
525{
526 destroy_workqueue(s->rcv_wq);
527 destroy_workqueue(s->send_wq);
528}
529
530static int tipc_work_start(struct tipc_server *s)
531{
532 s->rcv_wq = alloc_workqueue("tipc_rcv", WQ_UNBOUND, 1);
533 if (!s->rcv_wq) {
534 pr_err("can't start tipc receive workqueue\n");
535 return -ENOMEM;
536 }
537
538 s->send_wq = alloc_workqueue("tipc_send", WQ_UNBOUND, 1);
539 if (!s->send_wq) {
540 pr_err("can't start tipc send workqueue\n");
541 destroy_workqueue(s->rcv_wq);
542 return -ENOMEM;
543 }
544
545 return 0;
546}
547
548int tipc_server_start(struct tipc_server *s)
549{
550 int ret;
551
552 spin_lock_init(&s->idr_lock);
553 idr_init(&s->conn_idr);
554 s->idr_in_use = 0;
555
556 s->rcvbuf_cache = kmem_cache_create(s->name, s->max_rcvbuf_size,
557 0, SLAB_HWCACHE_ALIGN, NULL);
558 if (!s->rcvbuf_cache)
559 return -ENOMEM;
560
561 ret = tipc_work_start(s);
562 if (ret < 0) {
563 kmem_cache_destroy(s->rcvbuf_cache);
564 return ret;
565 }
566 s->enabled = 1;
567
568 return tipc_open_listening_sock(s);
569}
570
571void tipc_server_stop(struct tipc_server *s)
572{
573 struct tipc_conn *con;
574 int total = 0;
575 int id;
576
577 if (!s->enabled)
578 return;
579
580 s->enabled = 0;
581 spin_lock_bh(&s->idr_lock);
582 for (id = 0; total < s->idr_in_use; id++) {
583 con = idr_find(&s->conn_idr, id);
584 if (con) {
585 total++;
586 spin_unlock_bh(&s->idr_lock);
587 tipc_close_conn(con);
588 spin_lock_bh(&s->idr_lock);
589 }
590 }
591 spin_unlock_bh(&s->idr_lock);
592
593 tipc_work_stop(s);
594 kmem_cache_destroy(s->rcvbuf_cache);
595 idr_destroy(&s->conn_idr);
596}
diff --git a/net/tipc/server.h b/net/tipc/server.h
new file mode 100644
index 000000000000..98b23f20bc0f
--- /dev/null
+++ b/net/tipc/server.h
@@ -0,0 +1,94 @@
1/*
2 * net/tipc/server.h: Include file for TIPC server code
3 *
4 * Copyright (c) 2012-2013, Wind River Systems
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the names of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU General Public License ("GPL") version 2 as published by the Free
21 * Software Foundation.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#ifndef _TIPC_SERVER_H
37#define _TIPC_SERVER_H
38
39#include "core.h"
40
41#define TIPC_SERVER_NAME_LEN 32
42
43/**
44 * struct tipc_server - TIPC server structure
45 * @conn_idr: identifier set of connection
46 * @idr_lock: protect the connection identifier set
47 * @idr_in_use: amount of allocated identifier entry
48 * @rcvbuf_cache: memory cache of server receive buffer
49 * @rcv_wq: receive workqueue
50 * @send_wq: send workqueue
51 * @max_rcvbuf_size: maximum permitted receive message length
52 * @tipc_conn_new: callback will be called when new connection is incoming
53 * @tipc_conn_shutdown: callback will be called when connection is shut down
54 * @tipc_conn_recvmsg: callback will be called when message arrives
55 * @saddr: TIPC server address
56 * @name: server name
57 * @imp: message importance
58 * @type: socket type
59 * @enabled: identify whether server is launched or not
60 */
61struct tipc_server {
62 struct idr conn_idr;
63 spinlock_t idr_lock;
64 int idr_in_use;
65 struct kmem_cache *rcvbuf_cache;
66 struct workqueue_struct *rcv_wq;
67 struct workqueue_struct *send_wq;
68 int max_rcvbuf_size;
69 void *(*tipc_conn_new) (int conid);
70 void (*tipc_conn_shutdown) (int conid, void *usr_data);
71 void (*tipc_conn_recvmsg) (int conid, struct sockaddr_tipc *addr,
72 void *usr_data, void *buf, size_t len);
73 struct sockaddr_tipc *saddr;
74 const char name[TIPC_SERVER_NAME_LEN];
75 int imp;
76 int type;
77 int enabled;
78};
79
80int tipc_conn_sendmsg(struct tipc_server *s, int conid,
81 struct sockaddr_tipc *addr, void *data, size_t len);
82
83/**
84 * tipc_conn_terminate - terminate connection with server
85 *
86 * Note: Must call it in process context since it might sleep
87 */
88void tipc_conn_terminate(struct tipc_server *s, int conid);
89
90int tipc_server_start(struct tipc_server *s);
91
92void tipc_server_stop(struct tipc_server *s);
93
94#endif
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 515ce38e4f4c..ce8249c76827 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2,7 +2,7 @@
2 * net/tipc/socket.c: TIPC socket API 2 * net/tipc/socket.c: TIPC socket API
3 * 3 *
4 * Copyright (c) 2001-2007, 2012 Ericsson AB 4 * Copyright (c) 2001-2007, 2012 Ericsson AB
5 * Copyright (c) 2004-2008, 2010-2012, Wind River Systems 5 * Copyright (c) 2004-2008, 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
@@ -43,8 +43,6 @@
43#define SS_LISTENING -1 /* socket is listening */ 43#define SS_LISTENING -1 /* socket is listening */
44#define SS_READY -2 /* socket is connectionless */ 44#define SS_READY -2 /* socket is connectionless */
45 45
46#define CONN_OVERLOAD_LIMIT ((TIPC_FLOW_CONTROL_WIN * 2 + 1) * \
47 SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE))
48#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ 46#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */
49 47
50struct tipc_sock { 48struct tipc_sock {
@@ -65,12 +63,15 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
65static void wakeupdispatch(struct tipc_port *tport); 63static void wakeupdispatch(struct tipc_port *tport);
66static void tipc_data_ready(struct sock *sk, int len); 64static void tipc_data_ready(struct sock *sk, int len);
67static void tipc_write_space(struct sock *sk); 65static void tipc_write_space(struct sock *sk);
66static int release(struct socket *sock);
67static int accept(struct socket *sock, struct socket *new_sock, int flags);
68 68
69static const struct proto_ops packet_ops; 69static const struct proto_ops packet_ops;
70static const struct proto_ops stream_ops; 70static const struct proto_ops stream_ops;
71static const struct proto_ops msg_ops; 71static const struct proto_ops msg_ops;
72 72
73static struct proto tipc_proto; 73static struct proto tipc_proto;
74static struct proto tipc_proto_kern;
74 75
75static int sockets_enabled; 76static int sockets_enabled;
76 77
@@ -143,7 +144,7 @@ static void reject_rx_queue(struct sock *sk)
143} 144}
144 145
145/** 146/**
146 * tipc_create - create a TIPC socket 147 * tipc_sk_create - create a TIPC socket
147 * @net: network namespace (must be default network) 148 * @net: network namespace (must be default network)
148 * @sock: pre-allocated socket structure 149 * @sock: pre-allocated socket structure
149 * @protocol: protocol indicator (must be 0) 150 * @protocol: protocol indicator (must be 0)
@@ -154,8 +155,8 @@ static void reject_rx_queue(struct sock *sk)
154 * 155 *
155 * Returns 0 on success, errno otherwise 156 * Returns 0 on success, errno otherwise
156 */ 157 */
157static int tipc_create(struct net *net, struct socket *sock, int protocol, 158static int tipc_sk_create(struct net *net, struct socket *sock, int protocol,
158 int kern) 159 int kern)
159{ 160{
160 const struct proto_ops *ops; 161 const struct proto_ops *ops;
161 socket_state state; 162 socket_state state;
@@ -185,13 +186,17 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol,
185 } 186 }
186 187
187 /* Allocate socket's protocol area */ 188 /* Allocate socket's protocol area */
188 sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto); 189 if (!kern)
190 sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto);
191 else
192 sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto_kern);
193
189 if (sk == NULL) 194 if (sk == NULL)
190 return -ENOMEM; 195 return -ENOMEM;
191 196
192 /* Allocate TIPC port for socket to use */ 197 /* Allocate TIPC port for socket to use */
193 tp_ptr = tipc_createport_raw(sk, &dispatch, &wakeupdispatch, 198 tp_ptr = tipc_createport(sk, &dispatch, &wakeupdispatch,
194 TIPC_LOW_IMPORTANCE); 199 TIPC_LOW_IMPORTANCE);
195 if (unlikely(!tp_ptr)) { 200 if (unlikely(!tp_ptr)) {
196 sk_free(sk); 201 sk_free(sk);
197 return -ENOMEM; 202 return -ENOMEM;
@@ -203,6 +208,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol,
203 208
204 sock_init_data(sock, sk); 209 sock_init_data(sock, sk);
205 sk->sk_backlog_rcv = backlog_rcv; 210 sk->sk_backlog_rcv = backlog_rcv;
211 sk->sk_rcvbuf = sysctl_tipc_rmem[1];
206 sk->sk_data_ready = tipc_data_ready; 212 sk->sk_data_ready = tipc_data_ready;
207 sk->sk_write_space = tipc_write_space; 213 sk->sk_write_space = tipc_write_space;
208 tipc_sk(sk)->p = tp_ptr; 214 tipc_sk(sk)->p = tp_ptr;
@@ -220,6 +226,78 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol,
220} 226}
221 227
222/** 228/**
229 * tipc_sock_create_local - create TIPC socket from inside TIPC module
230 * @type: socket type - SOCK_RDM or SOCK_SEQPACKET
231 *
232 * We cannot use sock_creat_kern here because it bumps module user count.
233 * Since socket owner and creator is the same module we must make sure
234 * that module count remains zero for module local sockets, otherwise
235 * we cannot do rmmod.
236 *
237 * Returns 0 on success, errno otherwise
238 */
239int tipc_sock_create_local(int type, struct socket **res)
240{
241 int rc;
242 struct sock *sk;
243
244 rc = sock_create_lite(AF_TIPC, type, 0, res);
245 if (rc < 0) {
246 pr_err("Failed to create kernel socket\n");
247 return rc;
248 }
249 tipc_sk_create(&init_net, *res, 0, 1);
250
251 sk = (*res)->sk;
252
253 return 0;
254}
255
256/**
257 * tipc_sock_release_local - release socket created by tipc_sock_create_local
258 * @sock: the socket to be released.
259 *
260 * Module reference count is not incremented when such sockets are created,
261 * so we must keep it from being decremented when they are released.
262 */
263void tipc_sock_release_local(struct socket *sock)
264{
265 release(sock);
266 sock->ops = NULL;
267 sock_release(sock);
268}
269
270/**
271 * tipc_sock_accept_local - accept a connection on a socket created
272 * with tipc_sock_create_local. Use this function to avoid that
273 * module reference count is inadvertently incremented.
274 *
275 * @sock: the accepting socket
276 * @newsock: reference to the new socket to be created
277 * @flags: socket flags
278 */
279
280int tipc_sock_accept_local(struct socket *sock, struct socket **newsock,
281 int flags)
282{
283 struct sock *sk = sock->sk;
284 int ret;
285
286 ret = sock_create_lite(sk->sk_family, sk->sk_type,
287 sk->sk_protocol, newsock);
288 if (ret < 0)
289 return ret;
290
291 ret = accept(sock, *newsock, flags);
292 if (ret < 0) {
293 sock_release(*newsock);
294 return ret;
295 }
296 (*newsock)->ops = sock->ops;
297 return ret;
298}
299
300/**
223 * release - destroy a TIPC socket 301 * release - destroy a TIPC socket
224 * @sock: socket to destroy 302 * @sock: socket to destroy
225 * 303 *
@@ -324,7 +402,9 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
324 else if (addr->addrtype != TIPC_ADDR_NAMESEQ) 402 else if (addr->addrtype != TIPC_ADDR_NAMESEQ)
325 return -EAFNOSUPPORT; 403 return -EAFNOSUPPORT;
326 404
327 if (addr->addr.nameseq.type < TIPC_RESERVED_TYPES) 405 if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) &&
406 (addr->addr.nameseq.type != TIPC_TOP_SRV) &&
407 (addr->addr.nameseq.type != TIPC_CFG_SRV))
328 return -EACCES; 408 return -EACCES;
329 409
330 return (addr->scope > 0) ? 410 return (addr->scope > 0) ?
@@ -519,8 +599,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
519 res = -EISCONN; 599 res = -EISCONN;
520 goto exit; 600 goto exit;
521 } 601 }
522 if ((tport->published) || 602 if (tport->published) {
523 ((sock->type == SOCK_STREAM) && (total_len != 0))) {
524 res = -EOPNOTSUPP; 603 res = -EOPNOTSUPP;
525 goto exit; 604 goto exit;
526 } 605 }
@@ -810,7 +889,7 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
810 * Returns 0 if successful, otherwise errno 889 * Returns 0 if successful, otherwise errno
811 */ 890 */
812static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, 891static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
813 struct tipc_port *tport) 892 struct tipc_port *tport)
814{ 893{
815 u32 anc_data[3]; 894 u32 anc_data[3];
816 u32 err; 895 u32 err;
@@ -1011,8 +1090,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
1011 1090
1012 lock_sock(sk); 1091 lock_sock(sk);
1013 1092
1014 if (unlikely((sock->state == SS_UNCONNECTED) || 1093 if (unlikely((sock->state == SS_UNCONNECTED))) {
1015 (sock->state == SS_CONNECTING))) {
1016 res = -ENOTCONN; 1094 res = -ENOTCONN;
1017 goto exit; 1095 goto exit;
1018 } 1096 }
@@ -1233,10 +1311,10 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
1233 * For all connectionless messages, by default new queue limits are 1311 * For all connectionless messages, by default new queue limits are
1234 * as belows: 1312 * as belows:
1235 * 1313 *
1236 * TIPC_LOW_IMPORTANCE (5MB) 1314 * TIPC_LOW_IMPORTANCE (4 MB)
1237 * TIPC_MEDIUM_IMPORTANCE (10MB) 1315 * TIPC_MEDIUM_IMPORTANCE (8 MB)
1238 * TIPC_HIGH_IMPORTANCE (20MB) 1316 * TIPC_HIGH_IMPORTANCE (16 MB)
1239 * TIPC_CRITICAL_IMPORTANCE (40MB) 1317 * TIPC_CRITICAL_IMPORTANCE (32 MB)
1240 * 1318 *
1241 * Returns overload limit according to corresponding message importance 1319 * Returns overload limit according to corresponding message importance
1242 */ 1320 */
@@ -1246,9 +1324,10 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf)
1246 unsigned int limit; 1324 unsigned int limit;
1247 1325
1248 if (msg_connected(msg)) 1326 if (msg_connected(msg))
1249 limit = CONN_OVERLOAD_LIMIT; 1327 limit = sysctl_tipc_rmem[2];
1250 else 1328 else
1251 limit = sk->sk_rcvbuf << (msg_importance(msg) + 5); 1329 limit = sk->sk_rcvbuf >> TIPC_CRITICAL_IMPORTANCE <<
1330 msg_importance(msg);
1252 return limit; 1331 return limit;
1253} 1332}
1254 1333
@@ -1327,7 +1406,7 @@ static int backlog_rcv(struct sock *sk, struct sk_buff *buf)
1327 */ 1406 */
1328static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) 1407static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
1329{ 1408{
1330 struct sock *sk = (struct sock *)tport->usr_handle; 1409 struct sock *sk = tport->sk;
1331 u32 res; 1410 u32 res;
1332 1411
1333 /* 1412 /*
@@ -1358,7 +1437,7 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
1358 */ 1437 */
1359static void wakeupdispatch(struct tipc_port *tport) 1438static void wakeupdispatch(struct tipc_port *tport)
1360{ 1439{
1361 struct sock *sk = (struct sock *)tport->usr_handle; 1440 struct sock *sk = tport->sk;
1362 1441
1363 sk->sk_write_space(sk); 1442 sk->sk_write_space(sk);
1364} 1443}
@@ -1531,7 +1610,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
1531 1610
1532 buf = skb_peek(&sk->sk_receive_queue); 1611 buf = skb_peek(&sk->sk_receive_queue);
1533 1612
1534 res = tipc_create(sock_net(sock->sk), new_sock, 0, 0); 1613 res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1);
1535 if (res) 1614 if (res)
1536 goto exit; 1615 goto exit;
1537 1616
@@ -1657,8 +1736,8 @@ restart:
1657 * 1736 *
1658 * Returns 0 on success, errno otherwise 1737 * Returns 0 on success, errno otherwise
1659 */ 1738 */
1660static int setsockopt(struct socket *sock, 1739static int setsockopt(struct socket *sock, int lvl, int opt, char __user *ov,
1661 int lvl, int opt, char __user *ov, unsigned int ol) 1740 unsigned int ol)
1662{ 1741{
1663 struct sock *sk = sock->sk; 1742 struct sock *sk = sock->sk;
1664 struct tipc_port *tport = tipc_sk_port(sk); 1743 struct tipc_port *tport = tipc_sk_port(sk);
@@ -1716,8 +1795,8 @@ static int setsockopt(struct socket *sock,
1716 * 1795 *
1717 * Returns 0 on success, errno otherwise 1796 * Returns 0 on success, errno otherwise
1718 */ 1797 */
1719static int getsockopt(struct socket *sock, 1798static int getsockopt(struct socket *sock, int lvl, int opt, char __user *ov,
1720 int lvl, int opt, char __user *ov, int __user *ol) 1799 int __user *ol)
1721{ 1800{
1722 struct sock *sk = sock->sk; 1801 struct sock *sk = sock->sk;
1723 struct tipc_port *tport = tipc_sk_port(sk); 1802 struct tipc_port *tport = tipc_sk_port(sk);
@@ -1841,13 +1920,20 @@ static const struct proto_ops stream_ops = {
1841static const struct net_proto_family tipc_family_ops = { 1920static const struct net_proto_family tipc_family_ops = {
1842 .owner = THIS_MODULE, 1921 .owner = THIS_MODULE,
1843 .family = AF_TIPC, 1922 .family = AF_TIPC,
1844 .create = tipc_create 1923 .create = tipc_sk_create
1845}; 1924};
1846 1925
1847static struct proto tipc_proto = { 1926static struct proto tipc_proto = {
1848 .name = "TIPC", 1927 .name = "TIPC",
1849 .owner = THIS_MODULE, 1928 .owner = THIS_MODULE,
1850 .obj_size = sizeof(struct tipc_sock) 1929 .obj_size = sizeof(struct tipc_sock),
1930 .sysctl_rmem = sysctl_tipc_rmem
1931};
1932
1933static struct proto tipc_proto_kern = {
1934 .name = "TIPC",
1935 .obj_size = sizeof(struct tipc_sock),
1936 .sysctl_rmem = sysctl_tipc_rmem
1851}; 1937};
1852 1938
1853/** 1939/**
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 6b42d47029af..d38bb45d82e9 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -2,7 +2,7 @@
2 * net/tipc/subscr.c: TIPC network topology service 2 * net/tipc/subscr.c: TIPC network topology service
3 * 3 *
4 * Copyright (c) 2000-2006, Ericsson AB 4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005-2007, 2010-2011, Wind River Systems 5 * Copyright (c) 2005-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
@@ -41,33 +41,42 @@
41 41
42/** 42/**
43 * struct tipc_subscriber - TIPC network topology subscriber 43 * struct tipc_subscriber - TIPC network topology subscriber
44 * @port_ref: object reference to server port connecting to subscriber 44 * @conid: connection identifier to server connecting to subscriber
45 * @lock: pointer to spinlock controlling access to subscriber's server port 45 * @lock: controll access to subscriber
46 * @subscriber_list: adjacent subscribers in top. server's list of subscribers
47 * @subscription_list: list of subscription objects for this subscriber 46 * @subscription_list: list of subscription objects for this subscriber
48 */ 47 */
49struct tipc_subscriber { 48struct tipc_subscriber {
50 u32 port_ref; 49 int conid;
51 spinlock_t *lock; 50 spinlock_t lock;
52 struct list_head subscriber_list;
53 struct list_head subscription_list; 51 struct list_head subscription_list;
54}; 52};
55 53
56/** 54static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr,
57 * struct top_srv - TIPC network topology subscription service 55 void *usr_data, void *buf, size_t len);
58 * @setup_port: reference to TIPC port that handles subscription requests 56static void *subscr_named_msg_event(int conid);
59 * @subscription_count: number of active subscriptions (not subscribers!) 57static void subscr_conn_shutdown_event(int conid, void *usr_data);
60 * @subscriber_list: list of ports subscribing to service 58
61 * @lock: spinlock govering access to subscriber list 59static atomic_t subscription_count = ATOMIC_INIT(0);
62 */ 60
63struct top_srv { 61static struct sockaddr_tipc topsrv_addr __read_mostly = {
64 u32 setup_port; 62 .family = AF_TIPC,
65 atomic_t subscription_count; 63 .addrtype = TIPC_ADDR_NAMESEQ,
66 struct list_head subscriber_list; 64 .addr.nameseq.type = TIPC_TOP_SRV,
67 spinlock_t lock; 65 .addr.nameseq.lower = TIPC_TOP_SRV,
66 .addr.nameseq.upper = TIPC_TOP_SRV,
67 .scope = TIPC_NODE_SCOPE
68}; 68};
69 69
70static struct top_srv topsrv; 70static struct tipc_server topsrv __read_mostly = {
71 .saddr = &topsrv_addr,
72 .imp = TIPC_CRITICAL_IMPORTANCE,
73 .type = SOCK_SEQPACKET,
74 .max_rcvbuf_size = sizeof(struct tipc_subscr),
75 .name = "topology_server",
76 .tipc_conn_recvmsg = subscr_conn_msg_event,
77 .tipc_conn_new = subscr_named_msg_event,
78 .tipc_conn_shutdown = subscr_conn_shutdown_event,
79};
71 80
72/** 81/**
73 * htohl - convert value to endianness used by destination 82 * htohl - convert value to endianness used by destination
@@ -81,20 +90,13 @@ static u32 htohl(u32 in, int swap)
81 return swap ? swab32(in) : in; 90 return swap ? swab32(in) : in;
82} 91}
83 92
84/** 93static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower,
85 * subscr_send_event - send a message containing a tipc_event to the subscriber 94 u32 found_upper, u32 event, u32 port_ref,
86 *
87 * Note: Must not hold subscriber's server port lock, since tipc_send() will
88 * try to take the lock if the message is rejected and returned!
89 */
90static void subscr_send_event(struct tipc_subscription *sub,
91 u32 found_lower,
92 u32 found_upper,
93 u32 event,
94 u32 port_ref,
95 u32 node) 95 u32 node)
96{ 96{
97 struct iovec msg_sect; 97 struct tipc_subscriber *subscriber = sub->subscriber;
98 struct kvec msg_sect;
99 int ret;
98 100
99 msg_sect.iov_base = (void *)&sub->evt; 101 msg_sect.iov_base = (void *)&sub->evt;
100 msg_sect.iov_len = sizeof(struct tipc_event); 102 msg_sect.iov_len = sizeof(struct tipc_event);
@@ -104,7 +106,10 @@ static void subscr_send_event(struct tipc_subscription *sub,
104 sub->evt.found_upper = htohl(found_upper, sub->swap); 106 sub->evt.found_upper = htohl(found_upper, sub->swap);
105 sub->evt.port.ref = htohl(port_ref, sub->swap); 107 sub->evt.port.ref = htohl(port_ref, sub->swap);
106 sub->evt.port.node = htohl(node, sub->swap); 108 sub->evt.port.node = htohl(node, sub->swap);
107 tipc_send(sub->server_ref, 1, &msg_sect, msg_sect.iov_len); 109 ret = tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL,
110 msg_sect.iov_base, msg_sect.iov_len);
111 if (ret < 0)
112 pr_err("Sending subscription event failed, no memory\n");
108} 113}
109 114
110/** 115/**
@@ -112,10 +117,8 @@ static void subscr_send_event(struct tipc_subscription *sub,
112 * 117 *
113 * Returns 1 if there is overlap, otherwise 0. 118 * Returns 1 if there is overlap, otherwise 0.
114 */ 119 */
115int tipc_subscr_overlap(struct tipc_subscription *sub, 120int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower,
116 u32 found_lower,
117 u32 found_upper) 121 u32 found_upper)
118
119{ 122{
120 if (found_lower < sub->seq.lower) 123 if (found_lower < sub->seq.lower)
121 found_lower = sub->seq.lower; 124 found_lower = sub->seq.lower;
@@ -131,13 +134,9 @@ int tipc_subscr_overlap(struct tipc_subscription *sub,
131 * 134 *
132 * Protected by nameseq.lock in name_table.c 135 * Protected by nameseq.lock in name_table.c
133 */ 136 */
134void tipc_subscr_report_overlap(struct tipc_subscription *sub, 137void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower,
135 u32 found_lower, 138 u32 found_upper, u32 event, u32 port_ref,
136 u32 found_upper, 139 u32 node, int must)
137 u32 event,
138 u32 port_ref,
139 u32 node,
140 int must)
141{ 140{
142 if (!tipc_subscr_overlap(sub, found_lower, found_upper)) 141 if (!tipc_subscr_overlap(sub, found_lower, found_upper))
143 return; 142 return;
@@ -147,21 +146,24 @@ void tipc_subscr_report_overlap(struct tipc_subscription *sub,
147 subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); 146 subscr_send_event(sub, found_lower, found_upper, event, port_ref, node);
148} 147}
149 148
150/**
151 * subscr_timeout - subscription timeout has occurred
152 */
153static void subscr_timeout(struct tipc_subscription *sub) 149static void subscr_timeout(struct tipc_subscription *sub)
154{ 150{
155 struct tipc_port *server_port; 151 struct tipc_subscriber *subscriber = sub->subscriber;
152
153 /* The spin lock per subscriber is used to protect its members */
154 spin_lock_bh(&subscriber->lock);
156 155
157 /* Validate server port reference (in case subscriber is terminating) */ 156 /* Validate if the connection related to the subscriber is
158 server_port = tipc_port_lock(sub->server_ref); 157 * closed (in case subscriber is terminating)
159 if (server_port == NULL) 158 */
159 if (subscriber->conid == 0) {
160 spin_unlock_bh(&subscriber->lock);
160 return; 161 return;
162 }
161 163
162 /* Validate timeout (in case subscription is being cancelled) */ 164 /* Validate timeout (in case subscription is being cancelled) */
163 if (sub->timeout == TIPC_WAIT_FOREVER) { 165 if (sub->timeout == TIPC_WAIT_FOREVER) {
164 tipc_port_unlock(server_port); 166 spin_unlock_bh(&subscriber->lock);
165 return; 167 return;
166 } 168 }
167 169
@@ -171,8 +173,7 @@ static void subscr_timeout(struct tipc_subscription *sub)
171 /* Unlink subscription from subscriber */ 173 /* Unlink subscription from subscriber */
172 list_del(&sub->subscription_list); 174 list_del(&sub->subscription_list);
173 175
174 /* Release subscriber's server port */ 176 spin_unlock_bh(&subscriber->lock);
175 tipc_port_unlock(server_port);
176 177
177 /* Notify subscriber of timeout */ 178 /* Notify subscriber of timeout */
178 subscr_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, 179 subscr_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper,
@@ -181,64 +182,54 @@ static void subscr_timeout(struct tipc_subscription *sub)
181 /* Now destroy subscription */ 182 /* Now destroy subscription */
182 k_term_timer(&sub->timer); 183 k_term_timer(&sub->timer);
183 kfree(sub); 184 kfree(sub);
184 atomic_dec(&topsrv.subscription_count); 185 atomic_dec(&subscription_count);
185} 186}
186 187
187/** 188/**
188 * subscr_del - delete a subscription within a subscription list 189 * subscr_del - delete a subscription within a subscription list
189 * 190 *
190 * Called with subscriber port locked. 191 * Called with subscriber lock held.
191 */ 192 */
192static void subscr_del(struct tipc_subscription *sub) 193static void subscr_del(struct tipc_subscription *sub)
193{ 194{
194 tipc_nametbl_unsubscribe(sub); 195 tipc_nametbl_unsubscribe(sub);
195 list_del(&sub->subscription_list); 196 list_del(&sub->subscription_list);
196 kfree(sub); 197 kfree(sub);
197 atomic_dec(&topsrv.subscription_count); 198 atomic_dec(&subscription_count);
198} 199}
199 200
200/** 201/**
201 * subscr_terminate - terminate communication with a subscriber 202 * subscr_terminate - terminate communication with a subscriber
202 * 203 *
203 * Called with subscriber port locked. Routine must temporarily release lock 204 * Note: Must call it in process context since it might sleep.
204 * to enable subscription timeout routine(s) to finish without deadlocking;
205 * the lock is then reclaimed to allow caller to release it upon return.
206 * (This should work even in the unlikely event some other thread creates
207 * a new object reference in the interim that uses this lock; this routine will
208 * simply wait for it to be released, then claim it.)
209 */ 205 */
210static void subscr_terminate(struct tipc_subscriber *subscriber) 206static void subscr_terminate(struct tipc_subscriber *subscriber)
211{ 207{
212 u32 port_ref; 208 tipc_conn_terminate(&topsrv, subscriber->conid);
209}
210
211static void subscr_release(struct tipc_subscriber *subscriber)
212{
213 struct tipc_subscription *sub; 213 struct tipc_subscription *sub;
214 struct tipc_subscription *sub_temp; 214 struct tipc_subscription *sub_temp;
215 215
216 /* Invalidate subscriber reference */ 216 spin_lock_bh(&subscriber->lock);
217 port_ref = subscriber->port_ref;
218 subscriber->port_ref = 0;
219 spin_unlock_bh(subscriber->lock);
220 217
221 /* Sever connection to subscriber */ 218 /* Invalidate subscriber reference */
222 tipc_shutdown(port_ref); 219 subscriber->conid = 0;
223 tipc_deleteport(port_ref);
224 220
225 /* Destroy any existing subscriptions for subscriber */ 221 /* Destroy any existing subscriptions for subscriber */
226 list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, 222 list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
227 subscription_list) { 223 subscription_list) {
228 if (sub->timeout != TIPC_WAIT_FOREVER) { 224 if (sub->timeout != TIPC_WAIT_FOREVER) {
225 spin_unlock_bh(&subscriber->lock);
229 k_cancel_timer(&sub->timer); 226 k_cancel_timer(&sub->timer);
230 k_term_timer(&sub->timer); 227 k_term_timer(&sub->timer);
228 spin_lock_bh(&subscriber->lock);
231 } 229 }
232 subscr_del(sub); 230 subscr_del(sub);
233 } 231 }
234 232 spin_unlock_bh(&subscriber->lock);
235 /* Remove subscriber from topology server's subscriber list */
236 spin_lock_bh(&topsrv.lock);
237 list_del(&subscriber->subscriber_list);
238 spin_unlock_bh(&topsrv.lock);
239
240 /* Reclaim subscriber lock */
241 spin_lock_bh(subscriber->lock);
242 233
243 /* Now destroy subscriber */ 234 /* Now destroy subscriber */
244 kfree(subscriber); 235 kfree(subscriber);
@@ -247,7 +238,7 @@ static void subscr_terminate(struct tipc_subscriber *subscriber)
247/** 238/**
248 * subscr_cancel - handle subscription cancellation request 239 * subscr_cancel - handle subscription cancellation request
249 * 240 *
250 * Called with subscriber port locked. Routine must temporarily release lock 241 * Called with subscriber lock held. Routine must temporarily release lock
251 * to enable the subscription timeout routine to finish without deadlocking; 242 * to enable the subscription timeout routine to finish without deadlocking;
252 * the lock is then reclaimed to allow caller to release it upon return. 243 * the lock is then reclaimed to allow caller to release it upon return.
253 * 244 *
@@ -274,10 +265,10 @@ static void subscr_cancel(struct tipc_subscr *s,
274 /* Cancel subscription timer (if used), then delete subscription */ 265 /* Cancel subscription timer (if used), then delete subscription */
275 if (sub->timeout != TIPC_WAIT_FOREVER) { 266 if (sub->timeout != TIPC_WAIT_FOREVER) {
276 sub->timeout = TIPC_WAIT_FOREVER; 267 sub->timeout = TIPC_WAIT_FOREVER;
277 spin_unlock_bh(subscriber->lock); 268 spin_unlock_bh(&subscriber->lock);
278 k_cancel_timer(&sub->timer); 269 k_cancel_timer(&sub->timer);
279 k_term_timer(&sub->timer); 270 k_term_timer(&sub->timer);
280 spin_lock_bh(subscriber->lock); 271 spin_lock_bh(&subscriber->lock);
281 } 272 }
282 subscr_del(sub); 273 subscr_del(sub);
283} 274}
@@ -285,7 +276,7 @@ static void subscr_cancel(struct tipc_subscr *s,
285/** 276/**
286 * subscr_subscribe - create subscription for subscriber 277 * subscr_subscribe - create subscription for subscriber
287 * 278 *
288 * Called with subscriber port locked. 279 * Called with subscriber lock held.
289 */ 280 */
290static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, 281static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,
291 struct tipc_subscriber *subscriber) 282 struct tipc_subscriber *subscriber)
@@ -304,7 +295,7 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,
304 } 295 }
305 296
306 /* Refuse subscription if global limit exceeded */ 297 /* Refuse subscription if global limit exceeded */
307 if (atomic_read(&topsrv.subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { 298 if (atomic_read(&subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) {
308 pr_warn("Subscription rejected, limit reached (%u)\n", 299 pr_warn("Subscription rejected, limit reached (%u)\n",
309 TIPC_MAX_SUBSCRIPTIONS); 300 TIPC_MAX_SUBSCRIPTIONS);
310 subscr_terminate(subscriber); 301 subscr_terminate(subscriber);
@@ -335,10 +326,10 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,
335 } 326 }
336 INIT_LIST_HEAD(&sub->nameseq_list); 327 INIT_LIST_HEAD(&sub->nameseq_list);
337 list_add(&sub->subscription_list, &subscriber->subscription_list); 328 list_add(&sub->subscription_list, &subscriber->subscription_list);
338 sub->server_ref = subscriber->port_ref; 329 sub->subscriber = subscriber;
339 sub->swap = swap; 330 sub->swap = swap;
340 memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); 331 memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr));
341 atomic_inc(&topsrv.subscription_count); 332 atomic_inc(&subscription_count);
342 if (sub->timeout != TIPC_WAIT_FOREVER) { 333 if (sub->timeout != TIPC_WAIT_FOREVER) {
343 k_init_timer(&sub->timer, 334 k_init_timer(&sub->timer,
344 (Handler)subscr_timeout, (unsigned long)sub); 335 (Handler)subscr_timeout, (unsigned long)sub);
@@ -348,196 +339,51 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,
348 return sub; 339 return sub;
349} 340}
350 341
351/** 342/* Handle one termination request for the subscriber */
352 * subscr_conn_shutdown_event - handle termination request from subscriber 343static void subscr_conn_shutdown_event(int conid, void *usr_data)
353 *
354 * Called with subscriber's server port unlocked.
355 */
356static void subscr_conn_shutdown_event(void *usr_handle,
357 u32 port_ref,
358 struct sk_buff **buf,
359 unsigned char const *data,
360 unsigned int size,
361 int reason)
362{ 344{
363 struct tipc_subscriber *subscriber = usr_handle; 345 subscr_release((struct tipc_subscriber *)usr_data);
364 spinlock_t *subscriber_lock;
365
366 if (tipc_port_lock(port_ref) == NULL)
367 return;
368
369 subscriber_lock = subscriber->lock;
370 subscr_terminate(subscriber);
371 spin_unlock_bh(subscriber_lock);
372} 346}
373 347
374/** 348/* Handle one request to create a new subscription for the subscriber */
375 * subscr_conn_msg_event - handle new subscription request from subscriber 349static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr,
376 * 350 void *usr_data, void *buf, size_t len)
377 * Called with subscriber's server port unlocked.
378 */
379static void subscr_conn_msg_event(void *usr_handle,
380 u32 port_ref,
381 struct sk_buff **buf,
382 const unchar *data,
383 u32 size)
384{ 351{
385 struct tipc_subscriber *subscriber = usr_handle; 352 struct tipc_subscriber *subscriber = usr_data;
386 spinlock_t *subscriber_lock;
387 struct tipc_subscription *sub; 353 struct tipc_subscription *sub;
388 354
389 /* 355 spin_lock_bh(&subscriber->lock);
390 * Lock subscriber's server port (& make a local copy of lock pointer, 356 sub = subscr_subscribe((struct tipc_subscr *)buf, subscriber);
391 * in case subscriber is deleted while processing subscription request) 357 if (sub)
392 */ 358 tipc_nametbl_subscribe(sub);
393 if (tipc_port_lock(port_ref) == NULL) 359 spin_unlock_bh(&subscriber->lock);
394 return;
395
396 subscriber_lock = subscriber->lock;
397
398 if (size != sizeof(struct tipc_subscr)) {
399 subscr_terminate(subscriber);
400 spin_unlock_bh(subscriber_lock);
401 } else {
402 sub = subscr_subscribe((struct tipc_subscr *)data, subscriber);
403 spin_unlock_bh(subscriber_lock);
404 if (sub != NULL) {
405
406 /*
407 * We must release the server port lock before adding a
408 * subscription to the name table since TIPC needs to be
409 * able to (re)acquire the port lock if an event message
410 * issued by the subscription process is rejected and
411 * returned. The subscription cannot be deleted while
412 * it is being added to the name table because:
413 * a) the single-threading of the native API port code
414 * ensures the subscription cannot be cancelled and
415 * the subscriber connection cannot be broken, and
416 * b) the name table lock ensures the subscription
417 * timeout code cannot delete the subscription,
418 * so the subscription object is still protected.
419 */
420 tipc_nametbl_subscribe(sub);
421 }
422 }
423} 360}
424 361
425/** 362
426 * subscr_named_msg_event - handle request to establish a new subscriber 363/* Handle one request to establish a new subscriber */
427 */ 364static void *subscr_named_msg_event(int conid)
428static void subscr_named_msg_event(void *usr_handle,
429 u32 port_ref,
430 struct sk_buff **buf,
431 const unchar *data,
432 u32 size,
433 u32 importance,
434 struct tipc_portid const *orig,
435 struct tipc_name_seq const *dest)
436{ 365{
437 struct tipc_subscriber *subscriber; 366 struct tipc_subscriber *subscriber;
438 u32 server_port_ref;
439 367
440 /* Create subscriber object */ 368 /* Create subscriber object */
441 subscriber = kzalloc(sizeof(struct tipc_subscriber), GFP_ATOMIC); 369 subscriber = kzalloc(sizeof(struct tipc_subscriber), GFP_ATOMIC);
442 if (subscriber == NULL) { 370 if (subscriber == NULL) {
443 pr_warn("Subscriber rejected, no memory\n"); 371 pr_warn("Subscriber rejected, no memory\n");
444 return; 372 return NULL;
445 } 373 }
446 INIT_LIST_HEAD(&subscriber->subscription_list); 374 INIT_LIST_HEAD(&subscriber->subscription_list);
447 INIT_LIST_HEAD(&subscriber->subscriber_list); 375 subscriber->conid = conid;
448 376 spin_lock_init(&subscriber->lock);
449 /* Create server port & establish connection to subscriber */
450 tipc_createport(subscriber,
451 importance,
452 NULL,
453 NULL,
454 subscr_conn_shutdown_event,
455 NULL,
456 NULL,
457 subscr_conn_msg_event,
458 NULL,
459 &subscriber->port_ref);
460 if (subscriber->port_ref == 0) {
461 pr_warn("Subscriber rejected, unable to create port\n");
462 kfree(subscriber);
463 return;
464 }
465 tipc_connect(subscriber->port_ref, orig);
466
467 /* Lock server port (& save lock address for future use) */
468 subscriber->lock = tipc_port_lock(subscriber->port_ref)->lock;
469
470 /* Add subscriber to topology server's subscriber list */
471 spin_lock_bh(&topsrv.lock);
472 list_add(&subscriber->subscriber_list, &topsrv.subscriber_list);
473 spin_unlock_bh(&topsrv.lock);
474
475 /* Unlock server port */
476 server_port_ref = subscriber->port_ref;
477 spin_unlock_bh(subscriber->lock);
478
479 /* Send an ACK- to complete connection handshaking */
480 tipc_send(server_port_ref, 0, NULL, 0);
481 377
482 /* Handle optional subscription request */ 378 return (void *)subscriber;
483 if (size != 0) {
484 subscr_conn_msg_event(subscriber, server_port_ref,
485 buf, data, size);
486 }
487} 379}
488 380
489int tipc_subscr_start(void) 381int tipc_subscr_start(void)
490{ 382{
491 struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV}; 383 return tipc_server_start(&topsrv);
492 int res;
493
494 spin_lock_init(&topsrv.lock);
495 INIT_LIST_HEAD(&topsrv.subscriber_list);
496
497 res = tipc_createport(NULL,
498 TIPC_CRITICAL_IMPORTANCE,
499 NULL,
500 NULL,
501 NULL,
502 NULL,
503 subscr_named_msg_event,
504 NULL,
505 NULL,
506 &topsrv.setup_port);
507 if (res)
508 goto failed;
509
510 res = tipc_publish(topsrv.setup_port, TIPC_NODE_SCOPE, &seq);
511 if (res) {
512 tipc_deleteport(topsrv.setup_port);
513 topsrv.setup_port = 0;
514 goto failed;
515 }
516
517 return 0;
518
519failed:
520 pr_err("Failed to create subscription service\n");
521 return res;
522} 384}
523 385
524void tipc_subscr_stop(void) 386void tipc_subscr_stop(void)
525{ 387{
526 struct tipc_subscriber *subscriber; 388 tipc_server_stop(&topsrv);
527 struct tipc_subscriber *subscriber_temp;
528 spinlock_t *subscriber_lock;
529
530 if (topsrv.setup_port) {
531 tipc_deleteport(topsrv.setup_port);
532 topsrv.setup_port = 0;
533
534 list_for_each_entry_safe(subscriber, subscriber_temp,
535 &topsrv.subscriber_list,
536 subscriber_list) {
537 subscriber_lock = subscriber->lock;
538 spin_lock_bh(subscriber_lock);
539 subscr_terminate(subscriber);
540 spin_unlock_bh(subscriber_lock);
541 }
542 }
543} 389}
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h
index 218d2e07f0cc..393e417bee3f 100644
--- a/net/tipc/subscr.h
+++ b/net/tipc/subscr.h
@@ -2,7 +2,7 @@
2 * net/tipc/subscr.h: Include file for TIPC network topology service 2 * net/tipc/subscr.h: Include file for TIPC network topology service
3 * 3 *
4 * Copyright (c) 2003-2006, Ericsson AB 4 * Copyright (c) 2003-2006, Ericsson AB
5 * Copyright (c) 2005-2007, Wind River Systems 5 * Copyright (c) 2005-2007, 2012-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
@@ -37,10 +37,14 @@
37#ifndef _TIPC_SUBSCR_H 37#ifndef _TIPC_SUBSCR_H
38#define _TIPC_SUBSCR_H 38#define _TIPC_SUBSCR_H
39 39
40#include "server.h"
41
40struct tipc_subscription; 42struct tipc_subscription;
43struct tipc_subscriber;
41 44
42/** 45/**
43 * struct tipc_subscription - TIPC network topology subscription object 46 * struct tipc_subscription - TIPC network topology subscription object
47 * @subscriber: pointer to its subscriber
44 * @seq: name sequence associated with subscription 48 * @seq: name sequence associated with subscription
45 * @timeout: duration of subscription (in ms) 49 * @timeout: duration of subscription (in ms)
46 * @filter: event filtering to be done for subscription 50 * @filter: event filtering to be done for subscription
@@ -52,28 +56,23 @@ struct tipc_subscription;
52 * @evt: template for events generated by subscription 56 * @evt: template for events generated by subscription
53 */ 57 */
54struct tipc_subscription { 58struct tipc_subscription {
59 struct tipc_subscriber *subscriber;
55 struct tipc_name_seq seq; 60 struct tipc_name_seq seq;
56 u32 timeout; 61 u32 timeout;
57 u32 filter; 62 u32 filter;
58 struct timer_list timer; 63 struct timer_list timer;
59 struct list_head nameseq_list; 64 struct list_head nameseq_list;
60 struct list_head subscription_list; 65 struct list_head subscription_list;
61 u32 server_ref;
62 int swap; 66 int swap;
63 struct tipc_event evt; 67 struct tipc_event evt;
64}; 68};
65 69
66int tipc_subscr_overlap(struct tipc_subscription *sub, 70int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower,
67 u32 found_lower,
68 u32 found_upper); 71 u32 found_upper);
69 72
70void tipc_subscr_report_overlap(struct tipc_subscription *sub, 73void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower,
71 u32 found_lower, 74 u32 found_upper, u32 event, u32 port_ref,
72 u32 found_upper, 75 u32 node, int must);
73 u32 event,
74 u32 port_ref,
75 u32 node,
76 int must_report);
77 76
78int tipc_subscr_start(void); 77int tipc_subscr_start(void);
79 78
diff --git a/net/tipc/sysctl.c b/net/tipc/sysctl.c
new file mode 100644
index 000000000000..f3fef93325a8
--- /dev/null
+++ b/net/tipc/sysctl.c
@@ -0,0 +1,64 @@
1/*
2 * net/tipc/sysctl.c: sysctl interface to TIPC subsystem
3 *
4 * Copyright (c) 2013, Wind River Systems
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the names of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU General Public License ("GPL") version 2 as published by the Free
21 * Software Foundation.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include "core.h"
37
38#include <linux/sysctl.h>
39
40static struct ctl_table_header *tipc_ctl_hdr;
41
42static struct ctl_table tipc_table[] = {
43 {
44 .procname = "tipc_rmem",
45 .data = &sysctl_tipc_rmem,
46 .maxlen = sizeof(sysctl_tipc_rmem),
47 .mode = 0644,
48 .proc_handler = proc_dointvec,
49 },
50 {}
51};
52
53int tipc_register_sysctl(void)
54{
55 tipc_ctl_hdr = register_net_sysctl(&init_net, "net/tipc", tipc_table);
56 if (tipc_ctl_hdr == NULL)
57 return -ENOMEM;
58 return 0;
59}
60
61void tipc_unregister_sysctl(void)
62{
63 unregister_net_sysctl_table(tipc_ctl_hdr);
64}