Parcourir la source

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 il y a 16 ans
Parent
commit
709fb80638
4 fichiers modifiés avec 113 ajouts et 15 suppressions
  1. 66 5
      sctp_options.c
  2. 3 1
      sctp_options.h
  3. 42 9
      sctp_server.c
  4. 2 0
      sctp_server.h

+ 66 - 5
sctp_options.c

@@ -48,6 +48,7 @@ struct cfg_group_sctp sctp_default_cfg;
 
 
 static int set_autoclose(void* cfg_h, str* gname, str* name, void** val);
+static int set_assoc_tracking(void* cfg_h, str* gname, str* name, void** val);
 static int set_assoc_reuse(void* cfg_h, str* gname, str* name, void** val);
 static int set_srto_initial(void* cfg_h, str* gname, str* name, void** val);
 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[] = {
 		"milliseconds before aborting a send" },
 	{ "send_retries", CFG_VAR_INT| CFG_ATOMIC, 0, MAX_SCTP_SEND_RETRIES, 0, 0,
 		"re-send attempts on failure" },
+	{ "assoc_tracking", CFG_VAR_INT| CFG_ATOMIC, 0, 1, set_assoc_tracking, 0,
+		"connection/association tracking (see also assoc_reuse)" },
 	{ "assoc_reuse", CFG_VAR_INT| CFG_ATOMIC, 0, 1, set_assoc_reuse, 0,
-		"connection/association reuse (for now used only for replies)" },
+		"connection/association reuse (for now used only for replies)"
+		", depends on assoc_tracking being set"},
 	{ "srto_initial", CFG_VAR_INT| CFG_ATOMIC, 0, 1<<30, set_srto_initial, 0,
 		"initial value of the retr. timeout, used in RTO calculations,"
 			" in msecs" },
@@ -124,8 +128,10 @@ void init_sctp_options()
 	sctp_default_cfg.send_ttl=DEFAULT_SCTP_SEND_TTL;   /* in milliseconds */
 	sctp_default_cfg.send_retries=DEFAULT_SCTP_SEND_RETRIES;
 #ifdef SCTP_CONN_REUSE
+	sctp_default_cfg.assoc_tracking=1; /* on by default */
 	sctp_default_cfg.assoc_reuse=1; /* on by default */
 #else
+	sctp_default_cfg.assoc_tracking=0;
 	sctp_default_cfg.assoc_reuse=0;
 #endif /* SCTP_CONN_REUSE */
 #endif
@@ -148,13 +154,27 @@ void sctp_options_check()
 	W_OPT_NSCTP(autoclose);
 	W_OPT_NSCTP(send_ttl);
 	W_OPT_NSCTP(send_retries);
-#else
+	W_OPT_NSCTP(assoc_tracking);
+	W_OPT_NSCTP(assoc_reuse);
+#else /* USE_SCTP */
 	if (sctp_default_cfg.send_retries>MAX_SCTP_SEND_RETRIES) {
 		WARN("sctp: sctp_send_retries too high (%d), setting it to %d\n",
 				sctp_default_cfg.send_retries, MAX_SCTP_SEND_RETRIES);
 		sctp_default_cfg.send_retries=MAX_SCTP_SEND_RETRIES;
 	}
-#endif
+#ifndef CONN_REUSE
+	if (sctp_default_cfg.assoc_tracking || sctp_default_cfg.assoc_reuse){
+		WARN("sctp_options: assoc_tracking and assoc_reuse support cannnot"
+				" be enabled (CONN_REUSE support not compiled-in)\n");
+		sctp_default_cfg.assoc_tracking=0;
+		sctp_default_cfg.assoc_reuse=0;
+	}
+#else /* CONN_REUSE */
+	if (sctp_default_cfg.assoc_reuse && sctp_default_cfg.assoc_tracking==0){
+		sctp_default_cfg.assoc_tracking=1;
+	}
+#endif /* CONN_REUSE */
+#endif /* USE_SCTP */
 }
 
 
@@ -218,14 +238,55 @@ static int set_autoclose(void* cfg_h, str* gname, str* name, void** val)
 
 
 
+static int set_assoc_tracking(void* cfg_h, str* gname, str* name, void** val)
+{
+	int optval;
+	
+	optval=(int)(long)(*val);
+#ifndef SCTP_CONN_REUSE
+	if (optval!=0){
+		ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
+		return -1;
+	}
+#else /* SCTP_CONN_REUSE */
+	if (optval==0){
+		/* turn tracking off */
+		/* check if assoc_reuse is off */
+		if (cfg_get(sctp, cfg_h, assoc_reuse)!=0){
+			ERR("cannot turn sctp assoc_tracking off while assoc_reuse is"
+					" still on, please turn assoc_reuse off first\n");
+			return -1;
+		}
+		sctp_con_tracking_flush();
+	}else if (optval==1 && cfg_get(sctp, cfg_h, assoc_reuse)==0){
+		/* turning from off to on, make sure we flush the tracked list
+		   again, just incase the off flush was racing with a new connection*/
+		sctp_con_tracking_flush();
+	}
+#endif /* SCTP_CONN_REUSE */
+	return 0;
+}
+
+
+
 static int set_assoc_reuse(void* cfg_h, str* gname, str* name, void** val)
 {
+	int optval;
+	
+	optval=(int)(long)(*val);
 #ifndef SCTP_CONN_REUSE
-	if ((int)(long)(*val)!=0){
+	if (optval!=0){
 		ERR("no SCTP_CONN_REUSE support, please recompile with it enabled\n");
 		return -1;
 	}
-#endif /* SCTP_AUTOCLOSE */
+#else /* SCTP_CONN_REUSE */
+	if (optval==1 && cfg_get(sctp, cfg_h, assoc_tracking)==0){
+		/* conn reuse on, but assoc_tracking off => not possible */
+		ERR("cannot turn sctp assoc_reuse on while assoc_tracking is"
+					" off, please turn assoc_tracking on first\n");
+		return -1;
+	}
+#endif /* SCTP_CONN_REUSE */
 	return 0;
 }
 

+ 3 - 1
sctp_options.h

@@ -45,7 +45,9 @@ struct cfg_group_sctp{
 	unsigned int autoclose; /* in seconds */
 	unsigned int send_ttl; /* in milliseconds */
 	unsigned int send_retries;
-	int assoc_reuse; /* reuse the request connection for sending the reply*/
+	int assoc_tracking; /* track associations */
+	int assoc_reuse; /* reuse the request connection for sending the reply,
+					    depends on assoc_tracking */
 	unsigned int srto_initial; /** initial retr. timeout */
 	unsigned int srto_max;     /** max retr. timeout */
 	unsigned int srto_min;     /** min retr. timeout */

+ 42 - 9
sctp_server.c

@@ -1526,6 +1526,29 @@ inline static int _sctp_con_del_addr_locked(unsigned h,
 
 
 
+/** delete all tracked associations entries.
+ */
+void sctp_con_tracking_flush()
+{
+	unsigned h;
+	struct sctp_con_elem* e;
+	struct sctp_con_elem* tmp;
+	
+	for (h=0; h<SCTP_ID_HASH_SIZE; h++){
+again:
+		LOCK_SCTP_ID_H(h);
+			clist_foreach_safe(&sctp_con_id_hash[h], e, tmp, l.next_id) {
+				if (_sctp_con_del_id_locked(h, e)==0){
+					/* unlocked, need to lock again and restart the list */
+					goto again;
+				}
+			}
+		UNLOCK_SCTP_ID_H(h);
+	}
+}
+
+
+
 /** using id, get the corresponding sctp assoc & socket. 
  *  @param id - ser unique assoc id
  *  @param si  - result parameter, filled with the socket info on success
@@ -1859,6 +1882,8 @@ error:
 
 
 
+#else /* SCTP_CONN_REUSE */
+void sctp_con_tracking_flush() {}
 #endif /* SCTP_CONN_REUSE */
 
 
@@ -2070,7 +2095,8 @@ static int sctp_handle_assoc_change(struct socket_info* si,
 			atomic_inc(sctp_conn_no);
 #ifdef SCTP_CONN_REUSE
 			/* new connection, track it */
-			sctp_con_track(assoc_id, si, su, SCTP_CON_UP_SEEN);
+			if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
+					sctp_con_track(assoc_id, si, su, SCTP_CON_UP_SEEN);
 #if 0
 again:
 			id=atomic_add(sctp_id, 1);
@@ -2102,7 +2128,8 @@ again:
 			atomic_dec(sctp_conn_no);
 #ifdef SCTP_CONN_REUSE
 			/* connection down*/
-			sctp_con_track(assoc_id, si, su, SCTP_CON_DOWN_SEEN);
+			if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
+				sctp_con_track(assoc_id, si, su, SCTP_CON_DOWN_SEEN);
 #if 0
 			if (unlikely(sctp_con_del_assoc(assoc_id, si)!=0))
 				WARN("sctp con: tried to remove inexistent connection\n");
@@ -2388,7 +2415,7 @@ int sctp_rcv_loop()
 		/* update the local config */
 		cfg_update();
 #ifdef SCTP_CONN_REUSE
-		if (likely(sinfo)){
+		if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking) && sinfo)){
 			ri.proto_reserved1 = sctp_con_track(sinfo->sinfo_assoc_id,
 												ri.bind_address, 
 												&ri.src_su,
@@ -2464,7 +2491,8 @@ static int sctp_msg_send_raw(struct dest_info* dst, char* buf, unsigned len,
 	/* if dst->id is set it means we want to send on association with
 	   ser id dst->id if still opened and only if closed use dst->to */
 	assoc_id=0;
-	if (cfg_get(sctp, sctp_cfg, assoc_reuse) && (dst->id) &&
+	if ((dst->id) && cfg_get(sctp, sctp_cfg, assoc_reuse) &&
+			cfg_get(sctp, sctp_cfg, assoc_tracking) &&
 			(assoc_id=sctp_con_get_assoc(dst->id, &si, &to, 0))){
 		DBG("sctp: sending on sctp assoc_id %d (ser id %d)\n",
 				assoc_id, dst->id);
@@ -2500,10 +2528,12 @@ static int sctp_msg_send_raw(struct dest_info* dst, char* buf, unsigned len,
 	}else{
 #ifdef SCTP_ADDR_HASH
 		/* update timeout for the assoc identified  by (dst->to, dst->si) */
-		tmp_id=sctp_con_addr_get_id_assoc(&dst->to, dst->send_sock,
-											&tmp_assoc_id, 0);
-		DBG("sctp send: timeout updated ser id %d, sctp assoc_id %d\n",
-				tmp_id, tmp_assoc_id);
+		if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking))){
+			tmp_id=sctp_con_addr_get_id_assoc(&dst->to, dst->send_sock,
+												&tmp_assoc_id, 0);
+			DBG("sctp send: timeout updated ser id %d, sctp assoc_id %d\n",
+					tmp_id, tmp_assoc_id);
+		}
 #endif /* SCTP_ADDR_HASH */
 		tolen=sockaddru_len(dst->to);
 		msg.msg_name=&dst->to.s;
@@ -2606,7 +2636,10 @@ void sctp_get_info(struct sctp_gen_info* i)
 	if (i){
 		i->sctp_connections_no=atomic_get(sctp_conn_no);
 #ifdef SCTP_CONN_REUSE
-		i->sctp_tracked_no=atomic_get(sctp_conn_tracked);
+		if (likely(cfg_get(sctp, sctp_cfg, assoc_tracking)))
+			i->sctp_tracked_no=atomic_get(sctp_conn_tracked);
+		else
+			i->sctp_tracked_no=-1;
 #else /* SCTP_CONN_REUSE */
 		i->sctp_tracked_no=-1;
 #endif /* SCTP_CONN_REUSE */

+ 2 - 0
sctp_server.h

@@ -50,4 +50,6 @@ void destroy_sctp();
 
 int sctp_setsockopt(int s, int level, int optname,
 					void* optval, socklen_t optlen, char* err_prefix);
+
+void sctp_con_tracking_flush();
 #endif /* _sctp_server_h */