Browse code

script: udp_mtu fallback script config & commands

new config variables:
- udp_mtu = number - size in bytes after which fallback to
another protocol will be attempted. Default 0 (off),
recommended 1300.
- udp_mtu_try_proto = TCP|TLS|SCTP|UDP - protocol to fallback to.
Default: UDP (off).
- force_rport = yes|no - global force_rport().

new script commands:
- udp_mtu_try_proto(TCP|TLS|SCTP|UDP) - like udp_mtu_try_proto
above but works on a per packet basis and not globally.


Author: Andrei Pelinescu-Onciul <andrei@iptel.org>

Andrei Pelinescu-Onciul authored on 18/12/2008 16:09:16
Showing 7 changed files
... ...
@@ -200,6 +200,10 @@ modules:
200 200
                         - t_set_retr(t1, t2) - changes the retransmissions
201 201
                            intervals on the fly, on a per transaction basis.
202 202
 core:
203
+             - fallback to tcp or other congestion controlled transport 
204
+               protocol if a forwarded udp sip request is greater then 
205
+               udp_mtu (config). Default off. See udp_mtu and 
206
+               udp_mtu_try_proto.
203 207
              - sctp support (one-to-many, work in progress, for now linux
204 208
                only with no fallback to one-to-one on full send buffers)
205 209
              - partial cygwin (windows) support revived: core+static modules, 
... ...
@@ -220,6 +224,17 @@ core:
220 224
                between the short name and long name in cache as CNAME record
221 225
 
222 226
 new config variables:
227
+  udp_mtu = number - fallback to another protocol (udp_mtu_try_proto must be
228
+                     set also either globally or per packet) if the constructed
229
+                     request size is greater then udp_mtu.
230
+                     Recommended size: 1300. Default: 0 (off).
231
+  udp_mtu_try_proto = TCP|TLS|SCTP|UDP - if udp_mtu !=0 and udp forwarded
232
+                     request size (after adding all the "local" headers) >
233
+                     udp_mtu, use this protocol instead of udp. Only the
234
+                     Via header will be updated (e.g. The Record-Route
235
+                     will be the one built for udp).
236
+                     Default: UDP (off). Recommended: TCP.
237
+  force_rport =yes/no - like force_rport(), but works globally.
223 238
   disable_sctp = yes/no - disable sctp support (default auto, see enable_sctp)
224 239
   enable_sctp = 0/1/2  - disable (0)/enable (1)/auto (2) sctp support, 
225 240
                          default auto (2)
... ...
@@ -240,8 +255,8 @@ new config variables:
240 255
                       hosts (default: 0).
241 256
   server_id = number - A configurable unique server id that can be used to
242 257
                        discriminate server instances within a cluster of
243
-                       servers when all other information, such as IP adddresses
244
-                       are same.
258
+                       servers when all other information, such as IP addresses
259
+                       are the same.
245 260
   loadpath = <modules path> - directory where to load the modules from (-L
246 261
      equivalent); modules can be loaded simply by specifying their name
247 262
      (loadmodule "maxfwd")
... ...
@@ -336,6 +351,11 @@ new config variables:
336 351
     is not initialized at startup and cannot be enabled runtime,
337 352
     that saves some memory.
338 353
 
354
+new script commands:
355
+  udp_mtu_try_proto(TCP|TLS|SCTP|UDP) - same as udp_mtu_try_proto=... (see
356
+    above), but works per packet and not globally.
357
+
358
+
339 359
 build system:
340 360
  - check defines and includes used at compile time and if different 
341 361
    force rebuilding everything in the current dir (creates a new file: 
... ...
@@ -46,6 +46,7 @@
46 46
  *              (andrei)
47 47
  *  2007-06-14  run_actions & do_action need a ctx or handle now, no more 
48 48
  *               static vars (andrei)
49
+ *  2008-12-17  added UDP_MTU_TRY_PROTO_T (andrei)
49 50
  */
50 51
 
51 52
 
... ...
@@ -731,6 +732,10 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
731 732
 			msg->msg_flags|=FL_FORCE_RPORT;
732 733
 			ret=1; /* continue processing */
733 734
 			break;
735
+		case UDP_MTU_TRY_PROTO_T:
736
+			msg->msg_flags|= (unsigned int)a->val[0].u.number & FL_MTU_FB_MASK;
737
+			ret=1; /* continue processing */
738
+			break;
734 739
 		case SET_ADV_ADDR_T:
735 740
 			if (a->val[0].type!=STR_ST){
736 741
 				LOG(L_CRIT, "BUG: do_action: bad set_advertised_address() "
... ...
@@ -143,6 +143,8 @@ ROUTE_SEND onsend_route
143 143
 EXEC	exec
144 144
 FORCE_RPORT		"force_rport"|"add_rport"
145 145
 FORCE_TCP_ALIAS		"force_tcp_alias"|"add_tcp_alias"
146
+UDP_MTU		"udp_mtu"
147
+UDP_MTU_TRY_PROTO	"udp_mtu_try_proto"
146 148
 SETFLAG		setflag
147 149
 RESETFLAG	resetflag
148 150
 ISFLAGSET	isflagset
... ...
@@ -463,6 +465,9 @@ EAT_ABLE	[\ \t\b\r]
463 465
 <INITIAL>{FORCE_RPORT}	{ count(); yylval.strval=yytext; return FORCE_RPORT; }
464 466
 <INITIAL>{FORCE_TCP_ALIAS}	{ count(); yylval.strval=yytext;
465 467
 								return FORCE_TCP_ALIAS; }
468
+<INITIAL>{UDP_MTU}	{ count(); yylval.strval=yytext; return UDP_MTU; }
469
+<INITIAL>{UDP_MTU_TRY_PROTO}	{ count(); yylval.strval=yytext;
470
+									return UDP_MTU_TRY_PROTO; }
466 471
 <INITIAL>{IF}	{ count(); yylval.strval=yytext; return IF; }
467 472
 <INITIAL>{ELSE}	{ count(); yylval.strval=yytext; return ELSE; }
468 473
 
... ...
@@ -117,6 +117,7 @@
117 117
 #include "tcp_init.h"
118 118
 #include "tcp_options.h"
119 119
 #include "sctp_options.h"
120
+#include "msg_translator.h"
120 121
 
121 122
 #include "config.h"
122 123
 #include "cfg_core.h"
... ...
@@ -244,6 +245,8 @@ static void free_socket_id_lst(struct socket_id* i);
244 245
 %token REVERT_URI
245 246
 %token FORCE_RPORT
246 247
 %token FORCE_TCP_ALIAS
248
+%token UDP_MTU
249
+%token UDP_MTU_TRY_PROTO
247 250
 %token IF
248 251
 %token ELSE
249 252
 %token SET_ADV_ADDRESS
... ...
@@ -1248,6 +1251,15 @@ assign_stm:
1248 1251
 	| STUN_ALLOW_FP EQUAL NUMBER { IF_STUN(stun_allow_fp=$3) ; }
1249 1252
 	| STUN_ALLOW_FP EQUAL error{ yyerror("number expected"); }
1250 1253
     | SERVER_ID EQUAL NUMBER { server_id=$3; }
1254
+	| UDP_MTU EQUAL NUMBER { default_core_cfg.udp_mtu=$3; }
1255
+	| UDP_MTU EQUAL error { yyerror("number expected"); }
1256
+	| FORCE_RPORT EQUAL NUMBER 
1257
+		{ default_core_cfg.force_rport=$3; fix_global_req_flags(0); }
1258
+	| FORCE_RPORT EQUAL error { yyerror("boolean value expected"); }
1259
+	| UDP_MTU_TRY_PROTO EQUAL proto
1260
+		{ default_core_cfg.udp_mtu_try_proto=$3; fix_global_req_flags(0); }
1261
+	| UDP_MTU_TRY_PROTO EQUAL error
1262
+		{ yyerror("TCP, TLS, SCTP or UDP expected"); }
1251 1263
 	| cfg_var
1252 1264
 	| error EQUAL { yyerror("unknown config variable"); }
1253 1265
 	;
... ...
@@ -2322,6 +2334,10 @@ cmd:
2322 2334
 		#endif
2323 2335
 	}
2324 2336
 	| FORCE_TCP_ALIAS LPAREN error RPAREN	{$$=0; yyerror("bad argument, number expected"); }
2337
+	| UDP_MTU_TRY_PROTO LPAREN proto RPAREN
2338
+		{ $$=mk_action(UDP_MTU_TRY_PROTO_T, 1, NUMBER_ST, $3); }
2339
+	| UDP_MTU_TRY_PROTO LPAREN error RPAREN
2340
+		{ $$=0; yyerror("bad argument, UDP, TCP, TLS or SCTP expected"); }
2325 2341
 	| SET_ADV_ADDRESS LPAREN listen_id RPAREN {
2326 2342
 		$$=0;
2327 2343
 		if ((str_tmp=pkg_malloc(sizeof(str)))==0) {
... ...
@@ -342,6 +342,7 @@ int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
342 342
 	struct socket_info* orig_send_sock; /* initial send_sock */
343 343
 	int ret;
344 344
 	struct ip_addr ip; /* debugging only */
345
+	char proto;
345 346
 #ifdef USE_DNS_FAILOVER
346 347
 	struct socket_info* prev_send_sock;
347 348
 	int err;
... ...
@@ -354,6 +355,7 @@ int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
354 355
 	
355 356
 	buf=0;
356 357
 	orig_send_sock=send_info->send_sock;
358
+	proto=send_info->proto;
357 359
 	ret=0;
358 360
 
359 361
 	if(dst){
... ...
@@ -361,7 +363,7 @@ int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
361 363
 		if (cfg_get(core, core_cfg, use_dns_failover)){
362 364
 			dns_srv_handle_init(&dns_srv_h);
363 365
 			err=dns_sip_resolve2su(&dns_srv_h, &send_info->to, dst, port,
364
-									&send_info->proto, dns_flags);
366
+									&proto, dns_flags);
365 367
 			if (err!=0){
366 368
 				LOG(L_ERR, "ERROR: forward_request: resolving \"%.*s\""
367 369
 						" failed: %s [%d]\n", dst->len, ZSW(dst->s),
... ...
@@ -371,7 +373,7 @@ int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
371 373
 			}
372 374
 		}else
373 375
 #endif
374
-		if (sip_hostport2su(&send_info->to, dst, port, &send_info->proto)<0){
376
+		if (sip_hostport2su(&send_info->to, dst, port, &proto)<0){
375 377
 			LOG(L_ERR, "ERROR: forward_request: bad host name %.*s,"
376 378
 						" dropping packet\n", dst->len, ZSW(dst->s));
377 379
 			ret=E_BAD_ADDRESS;
... ...
@@ -410,12 +412,11 @@ int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
410 412
 	do{
411 413
 #endif
412 414
 		if (orig_send_sock==0) /* no forced send_sock => find it **/
413
-			send_info->send_sock=get_send_socket(msg, &send_info->to,
414
-												send_info->proto);
415
+			send_info->send_sock=get_send_socket(msg, &send_info->to, proto);
415 416
 		if (send_info->send_sock==0){
416 417
 			LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
417 418
 						"no corresponding listening socket\n",
418
-						send_info->to.s.sa_family, send_info->proto);
419
+						send_info->to.s.sa_family, proto);
419 420
 			ret=ser_error=E_NO_SOCKET;
420 421
 #ifdef USE_DNS_FAILOVER
421 422
 			/* continue, maybe we find a socket for some other ip */
... ...
@@ -431,6 +432,7 @@ int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
431 432
 			prev_send_sock=send_info->send_sock;
432 433
 #endif
433 434
 			if (buf) pkg_free(buf);
435
+			send_info->proto=proto;
434 436
 			buf = build_req_buf_from_sip_req(msg, &len, send_info);
435 437
 			if (!buf){
436 438
 				LOG(L_ERR, "ERROR: forward_request: building failed\n");
... ...
@@ -496,7 +498,7 @@ int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
496 498
 	}while(dst && cfg_get(core, core_cfg, use_dns_failover) &&
497 499
 			dns_srv_handle_next(&dns_srv_h, err) && 
498 500
 			((err=dns_sip_resolve2su(&dns_srv_h, &send_info->to, dst, port,
499
-								  &send_info->proto, dns_flags))==0));
501
+										&proto, dns_flags))==0));
500 502
 	if ((err!=0) && (err!=-E_DNS_EOR)){
501 503
 		LOG(L_ERR, "ERROR:  resolving %.*s host name in uri"
502 504
 							" failed: %s [%d] (dropping packet)\n",
... ...
@@ -564,6 +564,32 @@ static int fix_actions(struct action* a)
564 564
 				t->val[0].u.data=si;
565 565
 				t->val[0].type=SOCKETINFO_ST;
566 566
 				break;
567
+			case UDP_MTU_TRY_PROTO_T:
568
+				if (t->val[0].type!=NUMBER_ST){
569
+					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
570
+								"%d for udp_mtu_try_proto\n",
571
+								t->val[0].type);
572
+					return E_BUG;
573
+				}
574
+				switch(t->val[0].u.number){
575
+					case PROTO_UDP:
576
+						t->val[0].u.number=0;
577
+						break;
578
+					case PROTO_TCP:
579
+						t->val[0].u.number=FL_MTU_TCP_FB;
580
+						break;
581
+					case PROTO_TLS:
582
+						t->val[0].u.number=FL_MTU_TLS_FB;
583
+						break;
584
+					case PROTO_SCTP:
585
+						t->val[0].u.number=FL_MTU_SCTP_FB;
586
+						break;
587
+					default:
588
+						LOG(L_CRIT, "BUG: fix actions: invalid argument for"
589
+									" udp_mtu_try_proto (%d)\n", 
590
+									(unsigned int)t->val[0].u.number);
591
+				}
592
+				break;
567 593
 		}
568 594
 	}
569 595
 	return 0;
... ...
@@ -35,6 +35,7 @@
35 35
  *  2004-02-24  added LOAD_AVP_T and AVP_TO_URI_T (bogdan)
36 36
  *  2005-12-11  added SND{IP,PORT,PROTO,AF}_O & TO{IP,PORT}_O (andrei)
37 37
  *  2005-12-19  select framework added SELECT_O and SELECT_ST (mma)
38
+ *  2008-12-17  added UDP_MTU_TRY_PROTO_T (andrei)
38 39
  */
39 40
 
40 41
 
... ...
@@ -89,7 +90,8 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
89 90
 		AVP_TO_URI_T,
90 91
 		FORCE_SEND_SOCKET_T,
91 92
 		ASSIGN_T,
92
-		ADD_T
93
+		ADD_T,
94
+		UDP_MTU_TRY_PROTO_T
93 95
 };
94 96
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
95 97
 		EXPR_ST, ACTIONS_ST, MODEXP_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST,