Просмотр исходного кода

allow to use dscp for traffic prioritization

Signed-off-by: David Hanisch <hanisch@strato.de>
Reviewed-by: Jan Friesse <jfriesse@redhat.com>
David Hanisch 6 месяцев назад
Родитель
Сommit
5678836caf
12 измененных файлов с 131 добавлено и 1 удалено
  1. 2 0
      configure.ac
  2. 1 0
      exec/cfg.c
  3. 57 1
      exec/coroparse.c
  4. 1 0
      exec/main.c
  5. 2 0
      exec/totemconfig.c
  6. 6 0
      exec/totemknet.c
  7. 15 0
      exec/totemudp.c
  8. 13 0
      exec/totemudpu.c
  9. 16 0
      exec/util.c
  10. 2 0
      exec/util.h
  11. 2 0
      include/corosync/totem/totem.h
  12. 14 0
      man/corosync.conf.5

+ 2 - 0
configure.ac

@@ -202,6 +202,8 @@ AC_CHECK_LIB([knet],[knet_handle_crypto_set_config],
 	     [AC_DEFINE_UNQUOTED([HAVE_KNET_CRYPTO_RECONF], 1, [have knet crypto reconfig support])])
 	     [AC_DEFINE_UNQUOTED([HAVE_KNET_CRYPTO_RECONF], 1, [have knet crypto reconfig support])])
 AC_CHECK_LIB([knet],[knet_handle_get_onwire_ver],
 AC_CHECK_LIB([knet],[knet_handle_get_onwire_ver],
 	     [AC_DEFINE_UNQUOTED([HAVE_KNET_ONWIRE_VER], 1, [have knet onwire versioning])])
 	     [AC_DEFINE_UNQUOTED([HAVE_KNET_ONWIRE_VER], 1, [have knet onwire versioning])])
+AC_CHECK_LIB([knet],[knet_handle_setprio_dscp],
+	     [AC_DEFINE_UNQUOTED([HAVE_KNET_SETPRIO_DSCP], 1, [have knet dscp traffic prioritization])])
 LIBS="$OLDLIBS"
 LIBS="$OLDLIBS"
 
 
 # Checks for library functions.
 # Checks for library functions.

+ 1 - 0
exec/cfg.c

@@ -632,6 +632,7 @@ static void remove_ro_entries(icmap_map_t temp_map)
 	delete_and_notify_if_changed(temp_map, "totem.version");
 	delete_and_notify_if_changed(temp_map, "totem.version");
 	delete_and_notify_if_changed(temp_map, "totem.threads");
 	delete_and_notify_if_changed(temp_map, "totem.threads");
 	delete_and_notify_if_changed(temp_map, "totem.ip_version");
 	delete_and_notify_if_changed(temp_map, "totem.ip_version");
+	delete_and_notify_if_changed(temp_map, "totem.ip_dscp");
 	delete_and_notify_if_changed(temp_map, "totem.netmtu");
 	delete_and_notify_if_changed(temp_map, "totem.netmtu");
 	delete_and_notify_if_changed(temp_map, "totem.interface.bindnetaddr");
 	delete_and_notify_if_changed(temp_map, "totem.interface.bindnetaddr");
 	delete_and_notify_if_changed(temp_map, "totem.interface.mcastaddr");
 	delete_and_notify_if_changed(temp_map, "totem.interface.mcastaddr");

+ 57 - 1
exec/coroparse.c

@@ -568,6 +568,41 @@ static int str_to_ull(const char *str, unsigned long long int *res)
 	return (0);
 	return (0);
 }
 }
 
 
+static int get_dscp_value(char *str, int *dscp) {
+	struct dscp_name {const char *name; int dscp;} names[] = {
+		{"cs0", 0}, {"cs1", 8}, {"cs2", 16}, {"cs3", 24},
+		{"cs4", 32}, {"cs5", 40}, {"cs6", 48}, {"cs7", 56},
+		{"af11", 10}, {"af12", 12}, {"af13", 14}, {"af21", 18},
+		{"af22", 20}, {"af23", 22}, {"af31", 26}, {"af32", 28},
+		{"af33", 30}, {"af41", 34}, {"af42", 36}, {"af43", 38},
+		{"ef", 46}, {NULL, 0}
+	};
+	struct dscp_name *n;
+	long val;
+	char *end;
+
+	/*
+	 * allow dscp symbolical names according to
+	 * https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml
+	 */
+	for (n = names; n->name; n++) {
+		if (strcmp(str, n->name) == 0) {
+			*dscp = n->dscp;
+			return 0;
+		}
+	}
+
+	/* allow dscp as number (decimal, hex, octal) */
+	errno = 0;
+	val = strtol(str, &end, 0);
+	if (errno == 0 && *end == '\0' && val >= 0 && val <= 63) {
+		*dscp = val;
+		return 0;
+	}
+
+	return -1;
+}
+
 static int handle_crypto_model(const char *val, const char **error_string)
 static int handle_crypto_model(const char *val, const char **error_string)
 {
 {
 
 
@@ -610,7 +645,7 @@ static int main_config_parser_cb(const char *path,
 	struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
 	struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
 	struct key_value_list_item *kv_item;
 	struct key_value_list_item *kv_item;
 	struct qb_list_head *iter, *tmp_iter;
 	struct qb_list_head *iter, *tmp_iter;
-	int uid, gid;
+	int uid, gid, dscp;
 	cs_error_t cs_err;
 	cs_error_t cs_err;
 	const char *path_prefix;
 	const char *path_prefix;
 
 
@@ -845,6 +880,16 @@ static int main_config_parser_cb(const char *path,
 				}
 				}
 			}
 			}
 
 
+			if (strcmp(path, "totem.ip_dscp") == 0) {
+				if (get_dscp_value(value, &dscp) != 0) {
+					goto str_to_dscp_error;
+				}
+				if ((cs_err = icmap_set_uint8_r(config_map, path, dscp)) != CS_OK) {
+					goto icmap_set_error;
+				}
+				add_as_string = 0;
+			}
+
 			break;
 			break;
 
 
 		case MAIN_CP_CB_DATA_STATE_SYSTEM:
 		case MAIN_CP_CB_DATA_STATE_SYSTEM:
@@ -1615,6 +1660,17 @@ str_to_ull_error:
 
 
 	return (0);
 	return (0);
 
 
+str_to_dscp_error:
+	if (snprintf(formated_err, sizeof(formated_err),
+	    "Value of key \"%s\" is expected to be number (0..63) or symbolical dscp value, "
+	    "but \"%s\" was given", key_name, value) >= sizeof(formated_err)) {
+		*error_string = "Can't format parser error message";
+	} else {
+		*error_string = formated_err;
+	}
+
+	return (0);
+
 icmap_set_error:
 icmap_set_error:
 	if (snprintf(formated_err, sizeof(formated_err),
 	if (snprintf(formated_err, sizeof(formated_err),
 	    "Can't store key \"%s\" into icmap, returned error is %s",
 	    "Can't store key \"%s\" into icmap, returned error is %s",

+ 1 - 0
exec/main.c

@@ -1065,6 +1065,7 @@ static void set_icmap_ro_keys_flag (void)
 	icmap_set_ro_access("totem.key", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.key", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.secauth", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.secauth", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.ip_version", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.ip_version", CS_FALSE, CS_TRUE);
+	icmap_set_ro_access("totem.ip_dscp", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.transport", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.transport", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.cluster_name", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.cluster_name", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.netmtu", CS_FALSE, CS_TRUE);
 	icmap_set_ro_access("totem.netmtu", CS_FALSE, CS_TRUE);

+ 2 - 0
exec/totemconfig.c

@@ -1912,6 +1912,8 @@ extern int totem_config_read (
 			       "255.255.255.255", TOTEM_IP_VERSION_4);
 			       "255.255.255.255", TOTEM_IP_VERSION_4);
 	}
 	}
 
 
+	totem_config->ip_dscp = 0;
+	(void)icmap_get_uint8("totem.ip_dscp", &totem_config->ip_dscp);
 
 
 	/*
 	/*
 	 * Store automatically generated items back to icmap only for UDP
 	 * Store automatically generated items back to icmap only for UDP

+ 6 - 0
exec/totemknet.c

@@ -1322,6 +1322,12 @@ int totemknet_initialize (
 	if (res) {
 	if (res) {
 		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_pmtud_set failed");
 		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_pmtud_set failed");
 	}
 	}
+#ifdef HAVE_KNET_SETPRIO_DSCP
+	res = knet_handle_setprio_dscp(instance->knet_handle, instance->totem_config->ip_dscp);
+	if (res) {
+		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_setprio_dscp failed");
+	}
+#endif
 	res = knet_handle_enable_filter(instance->knet_handle, instance, dst_host_filter_callback_fn);
 	res = knet_handle_enable_filter(instance->knet_handle, instance, dst_host_filter_callback_fn);
 	if (res) {
 	if (res) {
 		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_filter failed");
 		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_filter failed");

+ 15 - 0
exec/totemudp.c

@@ -783,6 +783,14 @@ static int totemudp_build_sockets_ip (
 		return (-1);
 		return (-1);
 	}
 	}
 
 
+	res = set_socket_dscp(sockets->mcast_send,
+		instance->totem_config->ip_dscp);
+	if (res == -1) {
+		LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
+			"Could not set IP_TOS bits");
+		return (-1);
+	}
+
 	totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port - 1,
 	totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port - 1,
 		&sockaddr, &addrlen);
 		&sockaddr, &addrlen);
 
 
@@ -835,6 +843,13 @@ static int totemudp_build_sockets_ip (
 		return (-1);
 		return (-1);
 	}
 	}
 
 
+	res = set_socket_dscp(sockets->token, instance->totem_config->ip_dscp);
+	if (res == -1) {
+		LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
+			"Could not set IP_TOS bits");
+		return (-1);
+	}
+
 	/*
 	/*
 	 * Bind to unicast socket used for token send/receives
 	 * Bind to unicast socket used for token send/receives
 	 * This has the side effect of binding to the correct interface
 	 * This has the side effect of binding to the correct interface

+ 13 - 0
exec/totemudpu.c

@@ -791,6 +791,13 @@ static int totemudpu_build_sockets_ip (
 			"Could not set recvbuf size");
 			"Could not set recvbuf size");
 	}
 	}
 
 
+	res = set_socket_dscp(instance->token_socket,
+		instance->totem_config->ip_dscp);
+	if (res == -1) {
+		LOGSYS_PERROR (errno, instance->totemudpu_log_level_notice,
+			"Could not set IP_TOS bits");
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1280,6 +1287,12 @@ static int totemudpu_create_sending_socket(
 		 */
 		 */
 	}
 	}
 
 
+	res = set_socket_dscp(fd, instance->totem_config->ip_dscp);
+	if (res == -1) {
+		LOGSYS_PERROR (errno, instance->totemudpu_log_level_notice,
+			"Could not set IP_TOS bits");
+	}
+
 	/*
 	/*
 	 * Bind to sending interface
 	 * Bind to sending interface
 	 */
 	 */

+ 16 - 0
exec/util.c

@@ -42,6 +42,7 @@
 #include <errno.h>
 #include <errno.h>
 #include <sys/time.h>
 #include <sys/time.h>
 #include <assert.h>
 #include <assert.h>
+#include <sys/socket.h>
 
 
 #include <libknet.h>
 #include <libknet.h>
 
 
@@ -352,3 +353,18 @@ int util_is_valid_knet_compress_model(const char *val,
 
 
 	return (model_found);
 	return (model_found);
 }
 }
+
+int
+set_socket_dscp(int socket, unsigned char dscp)
+{
+	int res = 0;
+	int tos;
+
+	if (dscp) {
+		/* dscp is the upper 6 bits of TOS IP header field, RFC 2474 */
+		tos = (dscp & 0x3f) << 2;
+		res = setsockopt(socket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
+	}
+
+	return res;
+}

+ 2 - 0
exec/util.h

@@ -95,4 +95,6 @@ extern int util_is_valid_knet_compress_model(const char *val,
 	const char **list_str, int machine_parseable_str,
 	const char **list_str, int machine_parseable_str,
 	const char *error_string_prefix, const char **error_string);
 	const char *error_string_prefix, const char **error_string);
 
 
+int set_socket_dscp(int socket, unsigned char dscp);
+
 #endif /* UTIL_H_DEFINED */
 #endif /* UTIL_H_DEFINED */

+ 2 - 0
include/corosync/totem/totem.h

@@ -247,6 +247,8 @@ struct totem_config {
 
 
 	unsigned int cancel_token_hold_on_retransmit;
 	unsigned int cancel_token_hold_on_retransmit;
 
 
+	unsigned char ip_dscp;
+
 	void (*totem_memb_ring_id_create_or_load) (
 	void (*totem_memb_ring_id_create_or_load) (
 	    struct memb_ring_id *memb_ring_id,
 	    struct memb_ring_id *memb_ring_id,
 	    unsigned int nodeid);
 	    unsigned int nodeid);

+ 14 - 0
man/corosync.conf.5

@@ -372,6 +372,20 @@ for UDP transport.
 The KNET transport supports IPv4 and IPv6 addresses concurrently,
 The KNET transport supports IPv4 and IPv6 addresses concurrently,
 provided they are consistent on each link.
 provided they are consistent on each link.
 
 
+.TP
+ip_dscp
+This specifies the dscp (differentiated services code point) value to be
+used in the IP header's type of service (TOS) field according to RFC 2474.
+Allowed values are 0-63 and symbolic dscp names cs0, cs1, cs2, cs3, cs4, cs5,
+cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42,
+af43 and ef.
+Value 0 disables the dscp support. Use of TOS field then depends on the
+used transport.
+If ip_dscp is set to a value not equal to zero, and an appropriate
+socket option (IP_TOS) is available, the value is put into the upper
+six bits of the TOS header field.
+
+.PP
 Within the
 Within the
 .B totem
 .B totem
 directive, there are several configuration options which are used to control
 directive, there are several configuration options which are used to control