aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2013-06-17 10:54:37 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-17 18:53:00 -0400
commitcc79dd1ba9c1021c2ac6ae200a65ec38ee8db351 (patch)
tree86ffd4e43a1fb2d833a750ea713ce81b0af5df63 /net/tipc
parent8941bbcd572a8860ad03c76e2f3d1dafa820b842 (diff)
tipc: change socket buffer overflow control to respect sk_rcvbuf
As per feedback from the netdev community, we change the buffer overflow protection algorithm in receiving sockets so that it always respects the nominal upper limit set in sk_rcvbuf. Instead of scaling up from a small sk_rcvbuf value, which leads to violation of the configured sk_rcvbuf limit, we now calculate the weighted per-message limit by scaling down from a much bigger value, still in the same field, according to the importance priority of the received message. To allow for administrative tunability of the socket receive buffer size, we create a tipc_rmem sysctl variable to allow the user to configure an even bigger value via sysctl command. It is a size of three (min/default/max) to be consistent with things like tcp_rmem. By default, the value initialized in tipc_rmem[1] is equal to the receive socket size needed by a TIPC_CRITICAL_IMPORTANCE message. This value is also set as the default value of sk_rcvbuf. Originally-by: Jon Maloy <jon.maloy@ericsson.com> Cc: Neil Horman <nhorman@tuxdriver.com> Cc: Jon Maloy <jon.maloy@ericsson.com> [Ying: added sysctl variation to Jon's original patch] Signed-off-by: Ying Xue <ying.xue@windriver.com> [PG: don't compile sysctl.c if not config'd; add Documentation] Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/Makefile1
-rw-r--r--net/tipc/core.c12
-rw-r--r--net/tipc/core.h9
-rw-r--r--net/tipc/port.h2
-rw-r--r--net/tipc/socket.c19
-rw-r--r--net/tipc/sysctl.c64
6 files changed, 96 insertions, 11 deletions
diff --git a/net/tipc/Makefile b/net/tipc/Makefile
index 4df8e02d9008..02636d0a90cf 100644
--- a/net/tipc/Makefile
+++ b/net/tipc/Makefile
@@ -11,3 +11,4 @@ tipc-y += addr.o bcast.o bearer.o config.o \
11 socket.o log.o eth_media.o 11 socket.o log.o eth_media.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/core.c b/net/tipc/core.c
index 7ec2c1eb94f1..b0e42a087291 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -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/**
@@ -142,13 +144,14 @@ static int tipc_core_start(void)
142 res = tipc_netlink_start(); 144 res = tipc_netlink_start();
143 if (!res) 145 if (!res)
144 res = tipc_socket_init(); 146 res = tipc_socket_init();
147 if (!res)
148 res = tipc_register_sysctl();
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..fe7f2b7c19fe 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -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
@@ -97,6 +98,14 @@ extern 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);
99 100
101#ifdef CONFIG_SYSCTL
102extern int tipc_register_sysctl(void);
103extern void tipc_unregister_sysctl(void);
104#else
105#define tipc_register_sysctl() 0
106#define tipc_unregister_sysctl()
107#endif
108
100/* 109/*
101 * TIPC timer and signal code 110 * TIPC timer and signal code
102 */ 111 */
diff --git a/net/tipc/port.h b/net/tipc/port.h
index fb66e2e5f4d1..2485649c408a 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -43,6 +43,8 @@
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#define CONN_OVERLOAD_LIMIT ((TIPC_FLOW_CONTROL_WIN * 2 + 1) * \
47 SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE))
46 48
47typedef void (*tipc_msg_err_event) (void *usr_handle, u32 portref, 49typedef void (*tipc_msg_err_event) (void *usr_handle, u32 portref,
48 struct sk_buff **buf, unsigned char const *data, 50 struct sk_buff **buf, unsigned char const *data,
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 515ce38e4f4c..aba4255f297b 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -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 {
@@ -203,6 +201,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol,
203 201
204 sock_init_data(sock, sk); 202 sock_init_data(sock, sk);
205 sk->sk_backlog_rcv = backlog_rcv; 203 sk->sk_backlog_rcv = backlog_rcv;
204 sk->sk_rcvbuf = sysctl_tipc_rmem[1];
206 sk->sk_data_ready = tipc_data_ready; 205 sk->sk_data_ready = tipc_data_ready;
207 sk->sk_write_space = tipc_write_space; 206 sk->sk_write_space = tipc_write_space;
208 tipc_sk(sk)->p = tp_ptr; 207 tipc_sk(sk)->p = tp_ptr;
@@ -1233,10 +1232,10 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
1233 * For all connectionless messages, by default new queue limits are 1232 * For all connectionless messages, by default new queue limits are
1234 * as belows: 1233 * as belows:
1235 * 1234 *
1236 * TIPC_LOW_IMPORTANCE (5MB) 1235 * TIPC_LOW_IMPORTANCE (4 MB)
1237 * TIPC_MEDIUM_IMPORTANCE (10MB) 1236 * TIPC_MEDIUM_IMPORTANCE (8 MB)
1238 * TIPC_HIGH_IMPORTANCE (20MB) 1237 * TIPC_HIGH_IMPORTANCE (16 MB)
1239 * TIPC_CRITICAL_IMPORTANCE (40MB) 1238 * TIPC_CRITICAL_IMPORTANCE (32 MB)
1240 * 1239 *
1241 * Returns overload limit according to corresponding message importance 1240 * Returns overload limit according to corresponding message importance
1242 */ 1241 */
@@ -1246,9 +1245,10 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf)
1246 unsigned int limit; 1245 unsigned int limit;
1247 1246
1248 if (msg_connected(msg)) 1247 if (msg_connected(msg))
1249 limit = CONN_OVERLOAD_LIMIT; 1248 limit = sysctl_tipc_rmem[2];
1250 else 1249 else
1251 limit = sk->sk_rcvbuf << (msg_importance(msg) + 5); 1250 limit = sk->sk_rcvbuf >> TIPC_CRITICAL_IMPORTANCE <<
1251 msg_importance(msg);
1252 return limit; 1252 return limit;
1253} 1253}
1254 1254
@@ -1847,7 +1847,8 @@ static const struct net_proto_family tipc_family_ops = {
1847static struct proto tipc_proto = { 1847static struct proto tipc_proto = {
1848 .name = "TIPC", 1848 .name = "TIPC",
1849 .owner = THIS_MODULE, 1849 .owner = THIS_MODULE,
1850 .obj_size = sizeof(struct tipc_sock) 1850 .obj_size = sizeof(struct tipc_sock),
1851 .sysctl_rmem = sysctl_tipc_rmem
1851}; 1852};
1852 1853
1853/** 1854/**
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}