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 78
 		"milliseconds before aborting a send" },
78 79
 	{ "send_retries", CFG_VAR_INT| CFG_ATOMIC, 0, MAX_SCTP_SEND_RETRIES, 0, 0,
79 80
 		"re-send attempts on failure" },
81
+	{ "assoc_tracking", CFG_VAR_INT| CFG_ATOMIC, 0, 1, set_assoc_tracking, 0,
82
+		"connection/association tracking (see also assoc_reuse)" },
80 83
 	{ "assoc_reuse", CFG_VAR_INT| CFG_ATOMIC, 0, 1, set_assoc_reuse, 0,
81
-		"connection/association reuse (for now used only for replies)" },
84
+		"connection/association reuse (for now used only for replies)"
85
+		", depends on assoc_tracking being set"},
82 86
 	{ "srto_initial", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_srto_initial, 0,
83 87
 		"initial value of the retr. timeout, used in RTO calculations,"
84 88
 			" in msecs" },
... ...
@@ -124,8 +128,10 @@ void init_sctp_options()
124 128
 	sctp_default_cfg.send_ttl=DEFAULT_SCTP_SEND_TTL;   /* in milliseconds */
125 129
 	sctp_default_cfg.send_retries=DEFAULT_SCTP_SEND_RETRIES;
126 130
 #ifdef SCTP_CONN_REUSE
131
+	sctp_default_cfg.assoc_tracking=1; /* on by default */
127 132
 	sctp_default_cfg.assoc_reuse=1; /* on by default */
128 133
 #else
134
+	sctp_default_cfg.assoc_tracking=0;
129 135
 	sctp_default_cfg.assoc_reuse=0;
130 136
 #endif /* SCTP_CONN_REUSE */
131 137
 #endif
... ...
@@ -148,13 +154,27 @@ void sctp_options_check()
148 154
 	W_OPT_NSCTP(autoclose);
149 155
 	W_OPT_NSCTP(send_ttl);
150 156
 	W_OPT_NSCTP(send_retries);
151
-#else
157
+	W_OPT_NSCTP(assoc_tracking);
158
+	W_OPT_NSCTP(assoc_reuse);
159
+#else /* USE_SCTP */
152 160
 	if (sctp_default_cfg.send_retries>MAX_SCTP_SEND_RETRIES) {
153 161
 		WARN("sctp: sctp_send_retries too high (%d), setting it to %d\n",
154 162
 				sctp_default_cfg.send_retries, MAX_SCTP_SEND_RETRIES);
155 163
 		sctp_default_cfg.send_retries=MAX_SCTP_SEND_RETRIES;
156 164
 	}
157
-#endif
165
+#ifndef CONN_REUSE
166
+	if (sctp_default_cfg.assoc_tracking || sctp_default_cfg.assoc_reuse){
167
+		WARN("sctp_options: assoc_tracking and assoc_reuse support cannnot"
168
+				" be enabled (CONN_REUSE support not compiled-in)\n");
169
+		sctp_default_cfg.assoc_tracking=0;
170
+		sctp_default_cfg.assoc_reuse=0;
171
+	}
172
+#else /* CONN_REUSE */
173
+	if (sctp_default_cfg.assoc_reuse && sctp_default_cfg.assoc_tracking==0){
174
+		sctp_default_cfg.assoc_tracking=1;
175
+	}
176
+#endif /* CONN_REUSE */
177
+#endif /* USE_SCTP */
158 178
 }
159 179
 
160 180
 
... ...
@@ -218,14 +238,55 @@ static int set_autoclose(void* cfg_h, str* gname, str* name, void** val)
218 238
 
219 239
 
220 240
 
241
+static int set_assoc_tracking(void* cfg_h, str* gname, str* name, void** val)
242
+{
243
+	int optval;
244
+	
245
+	optval=(int)(long)(*val);
246
+#ifndef SCTP_CONN_REUSE
247
+	if (optval!=0){
248
+		ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
249
+		return -1;
250
+	}
251
+#else /* SCTP_CONN_REUSE */
252
+	if (optval==0){
253
+		/* turn tracking off */
254
+		/* check if assoc_reuse is off */
255
+		if (cfg_get(sctp, cfg_h, assoc_reuse)!=0){
256
+			ERR("cannot turn sctp assoc_tracking off while assoc_reuse is"
257
+					" still on, please turn assoc_reuse off first\n");
258
+			return -1;
259
+		}
260
+		sctp_con_tracking_flush();
261
+	}else if (optval==1 && cfg_get(sctp, cfg_h, assoc_reuse)==0){
262
+		/* turning from off to on, make sure we flush the tracked list
263
+		   again, just incase the off flush was racing with a new connection*/
264
+		sctp_con_tracking_flush();
265
+	}
266
+#endif /* SCTP_CONN_REUSE */
267
+	return 0;
268
+}
269
+
270
+
271
+
221 272
 static int set_assoc_reuse(void* cfg_h, str* gname, str* name, void** val)
222 273
 {
274
+	int optval;
275
+	
276
+	optval=(int)(long)(*val);
223 277
 #ifndef SCTP_CONN_REUSE
224
-	if ((int)(long)(*val)!=0){
278
+	if (optval!=0){
225 279
 		ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
226 280
 		return -1;
227 281
 	}
228
-#endif /* SCTP_AUTOCLOSE */
282
+#else /* SCTP_CONN_REUSE */
283
+	if (optval==1 && cfg_get(sctp, cfg_h, assoc_tracking)==0){
284
+		/* conn reuse on, but assoc_tracking off => not possible */
285
+		ERR("cannot turn sctp assoc_reuse on while assoc_tracking is"
286
+					" off, please turn assoc_tracking on first\n");
287
+		return -1;
288
+	}
289
+#endif /* SCTP_CONN_REUSE */
229 290
 	return 0;
230 291
 }
231 292
 
... ...
@@ -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 1882
 
1860 1883
 
1861 1884
 
1885
+#else /* SCTP_CONN_REUSE */
1886
+void sctp_con_tracking_flush() {}
1862 1887
 #endif /* SCTP_CONN_REUSE */
1863 1888
 
1864 1889
 
... ...
@@ -2070,7 +2095,8 @@ static int sctp_handle_assoc_change(struct socket_info* si,
2070 2095
 			atomic_inc(sctp_conn_no);
2071 2096
 #ifdef SCTP_CONN_REUSE
2072 2097
 			/* new connection, track it */
2073
-			sctp_con_track(assoc_id, si, su, SCTP_CON_UP_SEEN);
2098
+			if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
2099
+					sctp_con_track(assoc_id, si, su, SCTP_CON_UP_SEEN);
2074 2100
 #if 0
2075 2101
 again:
2076 2102
 			id=atomic_add(sctp_id, 1);
... ...
@@ -2102,7 +2128,8 @@ again:
2102 2128
 			atomic_dec(sctp_conn_no);
2103 2129
 #ifdef SCTP_CONN_REUSE
2104 2130
 			/* connection down*/
2105
-			sctp_con_track(assoc_id, si, su, SCTP_CON_DOWN_SEEN);
2131
+			if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
2132
+				sctp_con_track(assoc_id, si, su, SCTP_CON_DOWN_SEEN);
2106 2133
 #if 0
2107 2134
 			if (unlikely(sctp_con_del_assoc(assoc_id, si)!=0))
2108 2135
 				WARN("sctp con: tried to remove inexistent connection\n");
... ...
@@ -2388,7 +2415,7 @@ int sctp_rcv_loop()
2388 2415
 		/* update the local config */
2389 2416
 		cfg_update();
2390 2417
 #ifdef SCTP_CONN_REUSE
2391
-		if (likely(sinfo)){
2418
+		if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking) && sinfo)){
2392 2419
 			ri.proto_reserved1 = sctp_con_track(sinfo->sinfo_assoc_id,
2393 2420
 												ri.bind_address, 
2394 2421
 												&ri.src_su,
... ...
@@ -2464,7 +2491,8 @@ static int sctp_msg_send_raw(struct dest_info* dst, char* buf, unsigned len,
2464 2491
 	/* if dst->id is set it means we want to send on association with
2465 2492
 	   ser id dst->id if still opened and only if closed use dst->to */
2466 2493
 	assoc_id=0;
2467
-	if (cfg_get(sctp, sctp_cfg, assoc_reuse) && (dst->id) &&
2494
+	if ((dst->id) && cfg_get(sctp, sctp_cfg, assoc_reuse) &&
2495
+			cfg_get(sctp, sctp_cfg, assoc_tracking) &&
2468 2496
 			(assoc_id=sctp_con_get_assoc(dst->id, &si, &to, 0))){
2469 2497
 		DBG("sctp: sending on sctp assoc_id %d (ser id %d)\n",
2470 2498
 				assoc_id, dst->id);
... ...
@@ -2500,10 +2528,12 @@ static int sctp_msg_send_raw(struct dest_info* dst, char* buf, unsigned len,
2500 2528
 	}else{
2501 2529
 #ifdef SCTP_ADDR_HASH
2502 2530
 		/* 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);
2531
+		if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking))){
2532
+			tmp_id=sctp_con_addr_get_id_assoc(&dst->to, dst->send_sock,
2533
+												&tmp_assoc_id, 0);
2534
+			DBG("sctp send: timeout updated ser id %d, sctp assoc_id %d\n",
2535
+					tmp_id, tmp_assoc_id);
2536
+		}
2507 2537
 #endif /* SCTP_ADDR_HASH */
2508 2538
 		tolen=sockaddru_len(dst->to);
2509 2539
 		msg.msg_name=&dst->to.s;
... ...
@@ -2606,7 +2636,10 @@ void sctp_get_info(struct sctp_gen_info* i)
2606 2636
 	if (i){
2607 2637
 		i->sctp_connections_no=atomic_get(sctp_conn_no);
2608 2638
 #ifdef SCTP_CONN_REUSE
2609
-		i->sctp_tracked_no=atomic_get(sctp_conn_tracked);
2639
+		if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
2640
+			i->sctp_tracked_no=atomic_get(sctp_conn_tracked);
2641
+		else
2642
+			i->sctp_tracked_no=-1;
2610 2643
 #else /* SCTP_CONN_REUSE */
2611 2644
 		i->sctp_tracked_no=-1;
2612 2645
 #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 */