Browse code

- added new config vars: - tcp_connection_lifetime ( tcp connection timeout) - tcp_max_connections (default 2048) - tcp_poll_method (by default the best method for your OS is selected, if you don't like it/have problems you can force another using this var) - removed some too verbose debuging info - updated NEWS (seems everyone else forgot about it :-()

Andrei Pelinescu-Onciul authored on 08/07/2005 15:39:06
Showing 8 changed files
... ...
@@ -58,7 +58,7 @@ MAIN_NAME=ser
58 58
 VERSION = 0
59 59
 PATCHLEVEL = 10
60 60
 SUBLEVEL =   99
61
-EXTRAVERSION = -dev11-tcp
61
+EXTRAVERSION = -dev12-tcp
62 62
 
63 63
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
64 64
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
... ...
@@ -1140,6 +1140,9 @@ ifeq ($(OS), darwin)
1140 1140
 	else
1141 1141
 		LIBS= -lfl -lresolv  #dlopen is in libc
1142 1142
 	endif
1143
+	ifeq ($(NO_KQUEUE),)
1144
+		DEFS+=-DHAVE_KQUEUE
1145
+	endif
1143 1146
 	ifeq ($(NO_SELECT),)
1144 1147
 		DEFS+=-DHAVE_SELECT
1145 1148
 	endif
... ...
@@ -7,18 +7,31 @@ $Id$
7 7
 
8 8
 
9 9
 new archs:
10
-  - powerpc64 support
11
-  - alpha experimental support
10
+
11
+core:
12
+ - tcp: - improved  performance (io event handling), using OS specific
13
+           optimizations
14
+        - 1024 connections limit removed (see tcp_max_connections)
15
+new config variables:
16
+   tcp_connection_lifetime = value (s) - how long the lifetime of a
17
+      tcp connection will be exteneded after an IO event (accept, connect, 
18
+      read, write). Default: 120 s.
19
+   tcp_poll_method = poll|select|epoll_et|epoll-lt|kqueue|devpoll - poll
20
+      method used (by default the best one for the current OS is selected)
21
+   tcp_max_connections = no - maximum number of tcp connections (if the number
22
+      is exceeded no new tcp connections will be accepted). Default: 2048.
12 23
 
13 24
 
14
-0.8.99-dev changes
25
+0.9.0 changes
15 26
 
16 27
 
17 28
 new archs:
29
+ - alpha experimental support
18 30
  - mips2/cobalt experimental support
19 31
  - x86_64 support
20 32
  - OS X (darwin) support
21 33
  - sparc32 single cpu highly experimental support
34
+ - ppc64 support
22 35
 
23 36
 modules:
24 37
  - enum - support for more than one NAPTR
... ...
@@ -52,6 +52,8 @@
52 52
  *  2004-10-08  more escapes: \", \xHH, \nnn and minor optimizations (andrei)
53 53
  *  2004-10-19  added FROM_URI and TO_URI (andrei)
54 54
  *  2004-11-30  added force_send_socket
55
+ *  2005-07-08  added tcp_connection_lifetime, tcp_poll_method,
56
+ *               tcp_max_connections (andrei)
55 57
  */
56 58
 
57 59
 
... ...
@@ -209,6 +211,9 @@ TCP_CHILDREN	"tcp_children"
209 209
 TCP_ACCEPT_ALIASES	"tcp_accept_aliases"
210 210
 TCP_SEND_TIMEOUT	"tcp_send_timeout"
211 211
 TCP_CONNECT_TIMEOUT	"tcp_connect_timeout"
212
+TCP_CON_LIFETIME	"tcp_connection_lifetime"
213
+TCP_POLL_METHOD		"tcp_poll_method"
214
+TCP_MAX_CONNECTIONS	"tcp_max_connections"
212 215
 DISABLE_TLS		"disable_tls"
213 216
 TLSLOG			"tlslog"|"tls_log"
214 217
 TLS_PORT_NO		"tls_port_no"
... ...
@@ -372,6 +377,12 @@ EAT_ABLE	[\ \t\b\r]
372 372
 									return TCP_SEND_TIMEOUT; }
373 373
 <INITIAL>{TCP_CONNECT_TIMEOUT}		{ count(); yylval.strval=yytext;
374 374
 									return TCP_CONNECT_TIMEOUT; }
375
+<INITIAL>{TCP_CON_LIFETIME}		{ count(); yylval.strval=yytext;
376
+									return TCP_CON_LIFETIME; }
377
+<INITIAL>{TCP_POLL_METHOD}		{ count(); yylval.strval=yytext;
378
+									return TCP_POLL_METHOD; }
379
+<INITIAL>{TCP_MAX_CONNECTIONS}	{ count(); yylval.strval=yytext;
380
+									return TCP_MAX_CONNECTIONS; }
375 381
 <INITIAL>{DISABLE_TLS}	{ count(); yylval.strval=yytext; return DISABLE_TLS; }
376 382
 <INITIAL>{TLSLOG}		{ count(); yylval.strval=yytext; return TLS_PORT_NO; }
377 383
 <INITIAL>{TLS_PORT_NO}	{ count(); yylval.strval=yytext; return TLS_PORT_NO; }
... ...
@@ -53,11 +53,13 @@
53 53
  * 2004-03-30  added DISABLE_CORE and OPEN_FD_LIMIT (andrei)
54 54
  * 2004-04-29  added SOCK_MODE, SOCK_USER & SOCK_GROUP (andrei)
55 55
  * 2004-05-03  applied multicast support patch (MCAST_LOOPBACK) from janakj
56
-               added MCAST_TTL (andrei)
56
+ *             added MCAST_TTL (andrei)
57 57
  * 2004-07-05  src_ip & dst_ip will detect ip addresses between quotes
58 58
  *              (andrei)
59 59
  * 2004-10-19  added FROM_URI, TO_URI (andrei)
60 60
  * 2004-11-30  added force_send_socket (andrei)
61
+ * 2005-07-08  added TCP_CON_LIFETIME, TCP_POLL_METHOD, TCP_MAX_CONNECTIONS
62
+ *              (andrei)
61 63
  */
62 64
 
63 65
 
... ...
@@ -224,6 +226,9 @@ static struct socket_id* mk_listen_id(char*, int, int);
224 224
 %token TCP_CHILDREN
225 225
 %token TCP_CONNECT_TIMEOUT
226 226
 %token TCP_SEND_TIMEOUT
227
+%token TCP_CON_LIFETIME
228
+%token TCP_POLL_METHOD
229
+%token TCP_MAX_CONNECTIONS
227 230
 %token DISABLE_TLS
228 231
 %token TLSLOG
229 232
 %token TLS_PORT_NO
... ...
@@ -490,6 +495,51 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
490 490
 									#endif
491 491
 									}
492 492
 		| TCP_SEND_TIMEOUT EQUAL error { yyerror("number expected"); }
493
+		| TCP_CON_LIFETIME EQUAL NUMBER {
494
+									#ifdef USE_TCP
495
+										tcp_con_lifetime=$3;
496
+									#else
497
+										warn("tcp support not compiled in");
498
+									#endif
499
+									}
500
+		| TCP_CON_LIFETIME EQUAL error { yyerror("number expected"); }
501
+		| TCP_POLL_METHOD EQUAL ID {
502
+									#ifdef USE_TCP
503
+										tcp_poll_method=get_poll_type($3);
504
+										if (tcp_poll_method==POLL_NONE){
505
+											LOG(L_CRIT, "bad poll method name:"
506
+													" %s\n, try one of %s.\n",
507
+													$3, poll_support);
508
+											yyerror("bad tcp_poll_method "
509
+													"value");
510
+										}
511
+									#else
512
+										warn("tcp support not compiled in");
513
+									#endif
514
+									}
515
+		| TCP_POLL_METHOD EQUAL STRING {
516
+									#ifdef USE_TCP
517
+										tcp_poll_method=get_poll_type($3);
518
+										if (tcp_poll_method==POLL_NONE){
519
+											LOG(L_CRIT, "bad poll method name:"
520
+													" %s\n, try one of %s.\n",
521
+													$3, poll_support);
522
+											yyerror("bad tcp_poll_method "
523
+													"value");
524
+										}
525
+									#else
526
+										warn("tcp support not compiled in");
527
+									#endif
528
+									}
529
+		| TCP_POLL_METHOD EQUAL error { yyerror("poll method name expected"); }
530
+		| TCP_MAX_CONNECTIONS EQUAL NUMBER {
531
+									#ifdef USE_TCP
532
+										tcp_max_connections=$3;
533
+									#else
534
+										warn("tcp support not compiled in");
535
+									#endif
536
+									}
537
+		| TCP_MAX_CONNECTIONS EQUAL error { yyerror("number expected"); }
493 538
 		| DISABLE_TLS EQUAL NUMBER {
494 539
 									#ifdef USE_TLS
495 540
 										tls_disable=$3;
... ...
@@ -81,8 +81,10 @@ extern int tcp_disable;
81 81
 extern int tcp_accept_aliases;
82 82
 extern int tcp_connect_timeout;
83 83
 extern int tcp_send_timeout;
84
+extern int tcp_con_lifetime; /* connection lifetime */
84 85
 extern enum poll_types tcp_poll_method;
85 86
 extern int tcp_max_fd_no;
87
+extern int tcp_max_connections;
86 88
 #endif
87 89
 #ifdef USE_TLS
88 90
 extern int tls_disable;
... ...
@@ -374,7 +374,7 @@ char* check_poll_method(enum poll_types poll_method)
374 374
 #ifndef HAVE_KQUEUE
375 375
 			ret="kqueue not supported, try re-compiling with -DHAVE_KQUEUE";
376 376
 #else
377
-		/* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */
377
+		/* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD 2.9, Darwin */
378 378
 	#ifdef __OS_freebsd
379 379
 			if (os_ver<0x0401) /* if ver < 4.1 */
380 380
 				ret="kqueue not supported on FreeBSD < 4.1";
... ...
@@ -422,7 +422,7 @@ enum poll_types choose_poll_method()
422 422
 #endif
423 423
 #ifdef HAVE_KQUEUE
424 424
 	if (poll_method==0)
425
-		/* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */
425
+		/* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD 2.9, Darwin */
426 426
 	#ifdef __OS_freebsd
427 427
 		if (os_ver>=0x0401) /* if ver >= 4.1 */
428 428
 	#elif defined (__OS_netbsd)
... ...
@@ -44,13 +44,12 @@
44 44
 #define TCP_CON_MAX_ALIASES 4 /* maximum number of port aliases */
45 45
 
46 46
 #define TCP_BUF_SIZE 65535
47
-#define TCP_CON_TIMEOUT 120 /* in  seconds */
48
-#define TCP_CON_SEND_TIMEOUT 120 /* timeout after a send */
47
+#define DEFAULT_TCP_CONNECTION_LIFETIME 120 /* in  seconds */
49 48
 #define DEFAULT_TCP_SEND_TIMEOUT 10 /* if a send can't write for more then 10s,
50 49
 									   timeout */
51 50
 #define DEFAULT_TCP_CONNECT_TIMEOUT 10 /* if a connect doesn't complete in this
52 51
 										  time, timeout */
53
-#define DEFAULT_TCP_MAX_FD_NO 2048 /* maximum fd number */
52
+#define DEFAULT_TCP_MAX_CONNECTIONS 2048 /* maximum connections */
54 53
 #define TCP_CHILD_TIMEOUT 5 /* after 5 seconds, the child "returns" 
55 54
 							 the connection to the tcp master process */
56 55
 #define TCP_MAIN_SELECT_TIMEOUT 5 /* how often "tcp main" checks for timeout*/
... ...
@@ -56,6 +56,8 @@
56 56
  *               signals, poll & select (andrei)
57 57
  *  2005-06-26  *bsd kqueue support (andrei)
58 58
  *  2005-07-04  solaris /dev/poll support (andrei)
59
+ *  2005-07-08  tcp_max_connections, tcp_connection_lifetime, don't accept
60
+ *               more connections if tcp_max_connections is exceeded (andrei)
59 61
  */
60 62
 
61 63
 
... ...
@@ -133,8 +135,12 @@ struct tcp_child{
133 133
 int tcp_accept_aliases=0; /* by default don't accept aliases */
134 134
 int tcp_connect_timeout=DEFAULT_TCP_CONNECT_TIMEOUT;
135 135
 int tcp_send_timeout=DEFAULT_TCP_SEND_TIMEOUT;
136
+int tcp_con_lifetime=DEFAULT_TCP_CONNECTION_LIFETIME;
136 137
 enum poll_types tcp_poll_method=0; /* by default choose the best method */
137
-int tcp_max_fd_no=DEFAULT_TCP_MAX_FD_NO;
138
+int tcp_max_connections=DEFAULT_TCP_MAX_CONNECTIONS;
139
+int tcp_max_fd_no=0;
140
+
141
+static int tcp_connections_no=0; /* current open connections */
138 142
 
139 143
 /* connection hash table (after ip&port) , includes also aliases */
140 144
 struct tcp_conn_alias** tcpconn_aliases_hash=0;
... ...
@@ -412,10 +418,11 @@ struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su,
412 412
 		c->type=PROTO_TCP;
413 413
 		c->rcv.proto=PROTO_TCP;
414 414
 		c->flags=0;
415
-		c->timeout=get_ticks()+TCP_CON_TIMEOUT;
415
+		c->timeout=get_ticks()+tcp_con_lifetime;
416 416
 	}
417 417
 			
418 418
 		
419
+	tcp_connections_no++;
419 420
 	return c;
420 421
 	
421 422
 error:
... ...
@@ -703,9 +710,9 @@ int tcp_send(int type, char* buf, unsigned len, union sockaddr_union* to,
703 703
 	if (to){
704 704
 		su2ip_addr(&ip, to);
705 705
 		port=su_getport(to);
706
-		c=tcpconn_get(id, &ip, port, TCP_CON_SEND_TIMEOUT); 
706
+		c=tcpconn_get(id, &ip, port, tcp_con_lifetime); 
707 707
 	}else if (id){
708
-		c=tcpconn_get(id, 0, 0, TCP_CON_SEND_TIMEOUT);
708
+		c=tcpconn_get(id, 0, 0, tcp_con_lifetime);
709 709
 	}else{
710 710
 		LOG(L_CRIT, "BUG: tcp_send called with null id & to\n");
711 711
 		return -1;
... ...
@@ -715,7 +722,7 @@ int tcp_send(int type, char* buf, unsigned len, union sockaddr_union* to,
715 715
 		if (c==0) {
716 716
 			if (to){
717 717
 				/* try again w/o id */
718
-				c=tcpconn_get(0, &ip, port, TCP_CON_SEND_TIMEOUT);
718
+				c=tcpconn_get(0, &ip, port, tcp_con_lifetime);
719 719
 				goto no_id;
720 720
 			}else{
721 721
 				LOG(L_ERR, "ERROR: tcp_send: id %d not found, dropping\n",
... ...
@@ -983,6 +990,12 @@ static inline int handle_new_connect(struct socket_info* si)
983 983
 				" connection(%d): %s\n", errno, strerror(errno));
984 984
 		return -1;
985 985
 	}
986
+	if (tcp_connections_no>=tcp_max_connections){
987
+		LOG(L_ERR, "ERROR: maximum number of connections exceeded: %d/%d\n",
988
+					tcp_connections_no, tcp_max_connections);
989
+		close(new_sock);
990
+		return 1; /* success, because the accept was succesfull */
991
+	}
986 992
 	if (init_sock_opt(new_sock)<0){
987 993
 		LOG(L_ERR, "ERROR: handle_new_connect: init_sock_opt failed\n");
988 994
 		close(new_sock);
... ...
@@ -1037,6 +1050,7 @@ static void tcpconn_destroy(struct tcp_connection* tcpconn)
1037 1037
 #endif
1038 1038
 		_tcpconn_rm(tcpconn);
1039 1039
 		close(fd);
1040
+		tcp_connections_no--;
1040 1041
 	}else{
1041 1042
 		/* force timeout */
1042 1043
 		tcpconn->timeout=0;
... ...
@@ -1175,7 +1189,7 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
1175 1175
 				break;
1176 1176
 			}
1177 1177
 			/* update the timeout*/
1178
-			tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT;
1178
+			tcpconn->timeout=get_ticks()+tcp_con_lifetime;
1179 1179
 			tcpconn_put(tcpconn);
1180 1180
 			/* must be after the de-ref*/
1181 1181
 			io_watch_add(&io_h, tcpconn->s, F_TCPCONN, tcpconn);
... ...
@@ -1311,7 +1325,7 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
1311 1311
 			/* add tcpconn to the list*/
1312 1312
 			tcpconn_add(tcpconn);
1313 1313
 			/* update the timeout*/
1314
-			tcpconn->timeout=get_ticks()+TCP_CON_TIMEOUT;
1314
+			tcpconn->timeout=get_ticks()+tcp_con_lifetime;
1315 1315
 			io_watch_add(&io_h, tcpconn->s, F_TCPCONN, tcpconn);
1316 1316
 			break;
1317 1317
 		default:
... ...
@@ -1566,6 +1580,8 @@ void destroy_tcp()
1566 1566
 
1567 1567
 int init_tcp()
1568 1568
 {
1569
+	char* poll_err;
1570
+	
1569 1571
 	/* init lock */
1570 1572
 	tcpconn_lock=lock_alloc();
1571 1573
 	if (tcpconn_lock==0){
... ...
@@ -1604,6 +1620,25 @@ int init_tcp()
1604 1604
 	memset((void*)tcpconn_id_hash, 0, 
1605 1605
 			TCP_ID_HASH_SIZE * sizeof(struct tcp_connection*));
1606 1606
 	
1607
+	/* fix config variables */
1608
+	/* they can have only positive values due the config parser so we can
1609
+	 * ignore most of them */
1610
+		poll_err=check_poll_method(tcp_poll_method);
1611
+	
1612
+	/* set an appropiate poll method */
1613
+	if (poll_err || (tcp_poll_method==0)){
1614
+		tcp_poll_method=choose_poll_method();
1615
+		if (poll_err){
1616
+			LOG(L_ERR, "ERROR: init_tcp: %s, using %s instead\n",
1617
+					poll_err, poll_method_name(tcp_poll_method));
1618
+		}else{
1619
+			LOG(L_INFO, "init_tcp: using %s as the io watch method"
1620
+					" (auto detected)\n", poll_method_name(tcp_poll_method));
1621
+		}
1622
+	}else{
1623
+			LOG(L_INFO, "init_tcp: using %s io watch method (config)\n",
1624
+					poll_method_name(tcp_poll_method));
1625
+	}
1607 1626
 	
1608 1627
 	return 0;
1609 1628
 error:
... ...
@@ -1621,7 +1656,20 @@ int tcp_init_children()
1621 1621
 	int sockfd[2];
1622 1622
 	int reader_fd[2]; /* for comm. with the tcp children read  */
1623 1623
 	pid_t pid;
1624
+	struct socket_info *si;
1625
+	
1626
+	/* estimate max fd. no:
1627
+	 * 1 tcp send unix socket/all_proc, 
1628
+	 *  + 1 udp sock/udp proc + 1 tcp_child sock/tcp child*
1629
+	 *  + no_listen_tcp */
1630
+	for(r=0, si=tcp_listen; si; si=si->next, r++);
1631
+#ifdef USE_TLS
1632
+	if (! tls_disable)
1633
+		for (si=tls_listen; si; si=si->next; r++);
1634
+#endif
1624 1635
 	
1636
+	tcp_max_fd_no=process_count()*2 +r-1 /* timer */ +3; /* stdin/out/err*/
1637
+	tcp_max_fd_no+=tcp_max_connections;
1625 1638
 	
1626 1639
 	/* create the tcp sock_info structures */
1627 1640
 	/* copy the sockets --moved to main_loop*/