Browse code

sctp: assoc_tracking option

Association tracking can now be turned on/off at runtime.
Turning it off saves some memory and gives slightly better
performance at the cost of having to turn off some other features
that depend on it (right now that will be sctp_assoc_reuse).

Andrei Pelinescu-Onciul authored on 26/06/2009 17:55:05
Showing 4 changed files
... ...
@@ -48,6 +48,7 @@ struct cfg_group_sctp sctp_default_cfg;
48 48
 
49 49
 
50 50
 static int set_autoclose(void* cfg_h, str* gname, str* name, void** val);
51
+static int set_assoc_tracking(void* cfg_h, str* gname, str* name, void** val);
51 52
 static int set_assoc_reuse(void* cfg_h, str* gname, str* name, void** val);
52 53
 static int set_srto_initial(void* cfg_h, str* gname, str* name, void** val);
53 54
 static int set_srto_max(void* cfg_h, str* gname, str* name, void** val);
... ...
@@ -77,8 +78,11 @@ static cfg_def_t sctp_cfg_def[] = {
77 77
 		"milliseconds before aborting a send" },
78 78
 	{ "send_retries", CFG_VAR_INT| CFG_ATOMIC, 0, MAX_SCTP_SEND_RETRIES, 0, 0,
79 79
 		"re-send attempts on failure" },
80
+	{ "assoc_tracking", CFG_VAR_INT| CFG_ATOMIC, 0, 1, set_assoc_tracking, 0,
81
+		"connection/association tracking (see also assoc_reuse)" },
80 82
 	{ "assoc_reuse", CFG_VAR_INT| CFG_ATOMIC, 0, 1, set_assoc_reuse, 0,
81
-		"connection/association reuse (for now used only for replies)" },
83
+		"connection/association reuse (for now used only for replies)"
84
+		", depends on assoc_tracking being set"},
82 85
 	{ "srto_initial", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_srto_initial, 0,
83 86
 		"initial value of the retr. timeout, used in RTO calculations,"
84 87
 			" in msecs" },
... ...
@@ -124,8 +128,10 @@ void init_sctp_options()
124 124
 	sctp_default_cfg.send_ttl=DEFAULT_SCTP_SEND_TTL;   /* in milliseconds */
125 125
 	sctp_default_cfg.send_retries=DEFAULT_SCTP_SEND_RETRIES;
126 126
 #ifdef SCTP_CONN_REUSE
127
+	sctp_default_cfg.assoc_tracking=1; /* on by default */
127 128
 	sctp_default_cfg.assoc_reuse=1; /* on by default */
128 129
 #else
130
+	sctp_default_cfg.assoc_tracking=0;
129 131
 	sctp_default_cfg.assoc_reuse=0;
130 132
 #endif /* SCTP_CONN_REUSE */
131 133
 #endif
... ...
@@ -148,13 +154,27 @@ void sctp_options_check()
148 148
 	W_OPT_NSCTP(autoclose);
149 149
 	W_OPT_NSCTP(send_ttl);
150 150
 	W_OPT_NSCTP(send_retries);
151
-#else
151
+	W_OPT_NSCTP(assoc_tracking);
152
+	W_OPT_NSCTP(assoc_reuse);
153
+#else /* USE_SCTP */
152 154
 	if (sctp_default_cfg.send_retries>MAX_SCTP_SEND_RETRIES) {
153 155
 		WARN("sctp: sctp_send_retries too high (%d), setting it to %d\n",
154 156
 				sctp_default_cfg.send_retries, MAX_SCTP_SEND_RETRIES);
155 157
 		sctp_default_cfg.send_retries=MAX_SCTP_SEND_RETRIES;
156 158
 	}
157
-#endif
159
+#ifndef CONN_REUSE
160
+	if (sctp_default_cfg.assoc_tracking || sctp_default_cfg.assoc_reuse){
161
+		WARN("sctp_options: assoc_tracking and assoc_reuse support cannnot"
162
+				" be enabled (CONN_REUSE support not compiled-in)\n");
163
+		sctp_default_cfg.assoc_tracking=0;
164
+		sctp_default_cfg.assoc_reuse=0;
165
+	}
166
+#else /* CONN_REUSE */
167
+	if (sctp_default_cfg.assoc_reuse && sctp_default_cfg.assoc_tracking==0){
168
+		sctp_default_cfg.assoc_tracking=1;
169
+	}
170
+#endif /* CONN_REUSE */
171
+#endif /* USE_SCTP */
158 172
 }
159 173
 
160 174
 
... ...
@@ -218,14 +238,55 @@ static int set_autoclose(void* cfg_h, str* gname, str* name, void** val)
218 218
 
219 219
 
220 220
 
221
+static int set_assoc_tracking(void* cfg_h, str* gname, str* name, void** val)
222
+{
223
+	int optval;
224
+	
225
+	optval=(int)(long)(*val);
226
+#ifndef SCTP_CONN_REUSE
227
+	if (optval!=0){
228
+		ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
229
+		return -1;
230
+	}
231
+#else /* SCTP_CONN_REUSE */
232
+	if (optval==0){
233
+		/* turn tracking off */
234
+		/* check if assoc_reuse is off */
235
+		if (cfg_get(sctp, cfg_h, assoc_reuse)!=0){
236
+			ERR("cannot turn sctp assoc_tracking off while assoc_reuse is"
237
+					" still on, please turn assoc_reuse off first\n");
238
+			return -1;
239
+		}
240
+		sctp_con_tracking_flush();
241
+	}else if (optval==1 && cfg_get(sctp, cfg_h, assoc_reuse)==0){
242
+		/* turning from off to on, make sure we flush the tracked list
243
+		   again, just incase the off flush was racing with a new connection*/
244
+		sctp_con_tracking_flush();
245
+	}
246
+#endif /* SCTP_CONN_REUSE */
247
+	return 0;
248
+}
249
+
250
+
251
+
221 252
 static int set_assoc_reuse(void* cfg_h, str* gname, str* name, void** val)
222 253
 {
254
+	int optval;
255
+	
256
+	optval=(int)(long)(*val);
223 257
 #ifndef SCTP_CONN_REUSE
224
-	if ((int)(long)(*val)!=0){
258
+	if (optval!=0){
225 259
 		ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
226 260
 		return -1;
227 261
 	}
228
-#endif /* SCTP_AUTOCLOSE */
262
+#else /* SCTP_CONN_REUSE */
263
+	if (optval==1 && cfg_get(sctp, cfg_h, assoc_tracking)==0){
264
+		/* conn reuse on, but assoc_tracking off => not possible */
265
+		ERR("cannot turn sctp assoc_reuse on while assoc_tracking is"
266
+					" off, please turn assoc_tracking on first\n");
267
+		return -1;
268
+	}
269
+#endif /* SCTP_CONN_REUSE */
229 270
 	return 0;
230 271
 }
231 272
 
... ...
@@ -45,7 +45,9 @@ struct cfg_group_sctp{
45 45
 	unsigned int autoclose; /* in seconds */
46 46
 	unsigned int send_ttl; /* in milliseconds */
47 47
 	unsigned int send_retries;
48
-	int assoc_reuse; /* reuse the request connection for sending the reply*/
48
+	int assoc_tracking; /* track associations */
49
+	int assoc_reuse; /* reuse the request connection for sending the reply,
50
+					    depends on assoc_tracking */
49 51
 	unsigned int srto_initial; /** initial retr. timeout */
50 52
 	unsigned int srto_max;     /** max retr. timeout */
51 53
 	unsigned int srto_min;     /** min retr. timeout */
... ...
@@ -1526,6 +1526,29 @@ inline static int _sctp_con_del_addr_locked(unsigned h,
1526 1526
 
1527 1527
 
1528 1528
 
1529
+/** delete all tracked associations entries.
1530
+ */
1531
+void sctp_con_tracking_flush()
1532
+{
1533
+	unsigned h;
1534
+	struct sctp_con_elem* e;
1535
+	struct sctp_con_elem* tmp;
1536
+	
1537
+	for (h=0; h<SCTP_ID_HASH_SIZE; h++){
1538
+again:
1539
+		LOCK_SCTP_ID_H(h);
1540
+			clist_foreach_safe(&sctp_con_id_hash[h], e, tmp, l.next_id) {
1541
+				if (_sctp_con_del_id_locked(h, e)==0){
1542
+					/* unlocked, need to lock again and restart the list */
1543
+					goto again;
1544
+				}
1545
+			}
1546
+		UNLOCK_SCTP_ID_H(h);
1547
+	}
1548
+}
1549
+
1550
+
1551
+
1529 1552
 /** using id, get the corresponding sctp assoc & socket. 
1530 1553
  *  @param id - ser unique assoc id
1531 1554
  *  @param si  - result parameter, filled with the socket info on success
... ...
@@ -1859,6 +1882,8 @@ error:
1859 1859
 
1860 1860
 
1861 1861
 
1862
+#else /* SCTP_CONN_REUSE */
1863
+void sctp_con_tracking_flush() {}
1862 1864
 #endif /* SCTP_CONN_REUSE */
1863 1865
 
1864 1866
 
... ...
@@ -2070,7 +2095,8 @@ static int sctp_handle_assoc_change(struct socket_info* si,
2070 2070
 			atomic_inc(sctp_conn_no);
2071 2071
 #ifdef SCTP_CONN_REUSE
2072 2072
 			/* new connection, track it */
2073
-			sctp_con_track(assoc_id, si, su, SCTP_CON_UP_SEEN);
2073
+			if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
2074
+					sctp_con_track(assoc_id, si, su, SCTP_CON_UP_SEEN);
2074 2075
 #if 0
2075 2076
 again:
2076 2077
 			id=atomic_add(sctp_id, 1);
... ...
@@ -2102,7 +2128,8 @@ again:
2102 2102
 			atomic_dec(sctp_conn_no);
2103 2103
 #ifdef SCTP_CONN_REUSE
2104 2104
 			/* connection down*/
2105
-			sctp_con_track(assoc_id, si, su, SCTP_CON_DOWN_SEEN);
2105
+			if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
2106
+				sctp_con_track(assoc_id, si, su, SCTP_CON_DOWN_SEEN);
2106 2107
 #if 0
2107 2108
 			if (unlikely(sctp_con_del_assoc(assoc_id, si)!=0))
2108 2109
 				WARN("sctp con: tried to remove inexistent connection\n");
... ...
@@ -2388,7 +2415,7 @@ int sctp_rcv_loop()
2388 2388
 		/* update the local config */
2389 2389
 		cfg_update();
2390 2390
 #ifdef SCTP_CONN_REUSE
2391
-		if (likely(sinfo)){
2391
+		if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking) && sinfo)){
2392 2392
 			ri.proto_reserved1 = sctp_con_track(sinfo->sinfo_assoc_id,
2393 2393
 												ri.bind_address, 
2394 2394
 												&ri.src_su,
... ...
@@ -2464,7 +2491,8 @@ static int sctp_msg_send_raw(struct dest_info* dst, char* buf, unsigned len,
2464 2464
 	/* if dst->id is set it means we want to send on association with
2465 2465
 	   ser id dst->id if still opened and only if closed use dst->to */
2466 2466
 	assoc_id=0;
2467
-	if (cfg_get(sctp, sctp_cfg, assoc_reuse) && (dst->id) &&
2467
+	if ((dst->id) && cfg_get(sctp, sctp_cfg, assoc_reuse) &&
2468
+			cfg_get(sctp, sctp_cfg, assoc_tracking) &&
2468 2469
 			(assoc_id=sctp_con_get_assoc(dst->id, &si, &to, 0))){
2469 2470
 		DBG("sctp: sending on sctp assoc_id %d (ser id %d)\n",
2470 2471
 				assoc_id, dst->id);
... ...
@@ -2500,10 +2528,12 @@ static int sctp_msg_send_raw(struct dest_info* dst, char* buf, unsigned len,
2500 2500
 	}else{
2501 2501
 #ifdef SCTP_ADDR_HASH
2502 2502
 		/* update timeout for the assoc identified  by (dst->to, dst->si) */
2503
-		tmp_id=sctp_con_addr_get_id_assoc(&dst->to, dst->send_sock,
2504
-											&tmp_assoc_id, 0);
2505
-		DBG("sctp send: timeout updated ser id %d, sctp assoc_id %d\n",
2506
-				tmp_id, tmp_assoc_id);
2503
+		if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking))){
2504
+			tmp_id=sctp_con_addr_get_id_assoc(&dst->to, dst->send_sock,
2505
+												&tmp_assoc_id, 0);
2506
+			DBG("sctp send: timeout updated ser id %d, sctp assoc_id %d\n",
2507
+					tmp_id, tmp_assoc_id);
2508
+		}
2507 2509
 #endif /* SCTP_ADDR_HASH */
2508 2510
 		tolen=sockaddru_len(dst->to);
2509 2511
 		msg.msg_name=&dst->to.s;
... ...
@@ -2606,7 +2636,10 @@ void sctp_get_info(struct sctp_gen_info* i)
2606 2606
 	if (i){
2607 2607
 		i->sctp_connections_no=atomic_get(sctp_conn_no);
2608 2608
 #ifdef SCTP_CONN_REUSE
2609
-		i->sctp_tracked_no=atomic_get(sctp_conn_tracked);
2609
+		if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
2610
+			i->sctp_tracked_no=atomic_get(sctp_conn_tracked);
2611
+		else
2612
+			i->sctp_tracked_no=-1;
2610 2613
 #else /* SCTP_CONN_REUSE */
2611 2614
 		i->sctp_tracked_no=-1;
2612 2615
 #endif /* SCTP_CONN_REUSE */
... ...
@@ -50,4 +50,6 @@ void destroy_sctp();
50 50
 
51 51
 int sctp_setsockopt(int s, int level, int optname,
52 52
 					void* optval, socklen_t optlen, char* err_prefix);
53
+
54
+void sctp_con_tracking_flush();
53 55
 #endif /* _sctp_server_h */