Ver código fonte

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 meses atrás
pai
commit
5678836caf
12 arquivos alterados com 131 adições e 1 exclusões
  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_CHECK_LIB([knet],[knet_handle_get_onwire_ver],
 	     [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"
 
 # 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.threads");
 	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.interface.bindnetaddr");
 	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);
 }
 
+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)
 {
 
@@ -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 key_value_list_item *kv_item;
 	struct qb_list_head *iter, *tmp_iter;
-	int uid, gid;
+	int uid, gid, dscp;
 	cs_error_t cs_err;
 	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;
 
 		case MAIN_CP_CB_DATA_STATE_SYSTEM:
@@ -1615,6 +1660,17 @@ str_to_ull_error:
 
 	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:
 	if (snprintf(formated_err, sizeof(formated_err),
 	    "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.secauth", 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.cluster_name", 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);
 	}
 
+	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

+ 6 - 0
exec/totemknet.c

@@ -1322,6 +1322,12 @@ int totemknet_initialize (
 	if (res) {
 		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);
 	if (res) {
 		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);
 	}
 
+	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,
 		&sockaddr, &addrlen);
 
@@ -835,6 +843,13 @@ static int totemudp_build_sockets_ip (
 		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
 	 * 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");
 	}
 
+	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;
 }
 
@@ -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
 	 */

+ 16 - 0
exec/util.c

@@ -42,6 +42,7 @@
 #include <errno.h>
 #include <sys/time.h>
 #include <assert.h>
+#include <sys/socket.h>
 
 #include <libknet.h>
 
@@ -352,3 +353,18 @@ int util_is_valid_knet_compress_model(const char *val,
 
 	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 *error_string_prefix, const char **error_string);
 
+int set_socket_dscp(int socket, unsigned char dscp);
+
 #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 char ip_dscp;
+
 	void (*totem_memb_ring_id_create_or_load) (
 	    struct memb_ring_id *memb_ring_id,
 	    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,
 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
 .B totem
 directive, there are several configuration options which are used to control