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

defect 981
big endian and little endian in the same network causes infinite loop. This
patch fixes that problem for the totem layer only. Other components are not
resolved.


git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@922 fd59a12c-fef9-0310-b244-a6a79926bd2f

Steven Dake 20 лет назад
Родитель
Сommit
d248cfb8ae
5 измененных файлов с 97 добавлено и 68 удалено
  1. 20 23
      exec/swab.h
  2. 1 1
      exec/totemconfig.c
  3. 8 0
      exec/totemip.c
  4. 1 0
      exec/totemip.h
  5. 67 44
      exec/totemsrp.c

+ 20 - 23
exec/swab.h

@@ -36,12 +36,9 @@
 #include <sys/socket.h>
 #include <netdb.h>
 #include <sys/un.h>
-#include <sys/sysinfo.h>
 #include <sys/ioctl.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <linux/if.h>
-#include <linux/sockios.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdlib.h>
@@ -55,31 +52,31 @@
 
 #define swab16(x) \
 ({ \
-	__u16 __x = (x); \
-		((__u16)( \
-		(((__u16)(__x) & (__u16)0x00ffU) << 8) | \
-		(((__u16)(__x) & (__u16)0xff00U) >> 8) )); \
+	uint16_t __x = (x); \
+		((uint16_t)( \
+		(((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
+		(((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
 })
 
 #define swab32(x) \
 ({ \
-	__u32 __x = (x); \
-		((__u32)( \
-		(((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \
-		(((__u32)(__x) & (__u32)0x0000ff00UL) <<  8) | \
-		(((__u32)(__x) & (__u32)0x00ff0000UL) >>  8) | \
-		(((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \
+	uint32_t __x = (x); \
+		((uint32_t)( \
+		(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
+		(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
+		(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
+		(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
 })
 #define swab64(x) \
 ({ \
-	__u64 __x = (x); \
-		((__u64)( \
-		(__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
-		(__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
-		(__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
-		(__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) <<  8) | \
-		(__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >>  8) | \
-		(__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
-		(__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
-		(__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
+	uint64_t __x = (x); \
+		((uint64_t)( \
+		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
+		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
+		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
+		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) <<  8) | \
+		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >>  8) | \
+		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
+		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
+		(uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
 })

+ 1 - 1
exec/totemconfig.c

@@ -61,7 +61,7 @@
 #define CONSENSUS_TIMEOUT			200
 #define MERGE_TIMEOUT				200
 #define DOWNCHECK_TIMEOUT			1000
-#define FAIL_TO_RECV_CONST			10
+#define FAIL_TO_RECV_CONST			50
 #define	SEQNO_UNCHANGED_CONST			30
 #define MINIMUM_TIMEOUT				(int)(1000/HZ)*3
 #define MAX_NETWORK_DELAY			50 /*In milliseconds*/

+ 8 - 0
exec/totemip.c

@@ -51,6 +51,7 @@
 #include <linux/rtnetlink.h>
 
 #include "totemip.h"
+#include "swab.h"
 
 #define LOCALHOST_IPV4 "127.0.0.1"
 #define LOCALHOST_IPV6 "::1"
@@ -86,6 +87,13 @@ void totemip_copy(struct totem_ip_address *addr1, struct totem_ip_address *addr2
 	memcpy(addr1, addr2, sizeof(struct totem_ip_address));
 }
 
+void totemip_copy_endian_convert(struct totem_ip_address *addr1, struct totem_ip_address *addr2)
+{
+	addr1->nodeid = swab32(addr2->nodeid);
+	addr1->family = swab16(addr2->family);
+	memcpy(addr1->addr, addr2->addr, TOTEMIP_ADDRLEN);
+}
+
 /* For sorting etc. params are void * for qsort's benefit */
 int totemip_compare(const void *a, const void *b)
 {

+ 1 - 0
exec/totemip.h

@@ -51,6 +51,7 @@ struct totem_ip_address
 extern int totemip_equal(struct totem_ip_address *addr1, struct totem_ip_address *addr2);
 extern int totemip_compare(const void *a, const void *b);
 extern void totemip_copy(struct totem_ip_address *addr1, struct totem_ip_address *addr2);
+extern void totemip_copy_endian_convert(struct totem_ip_address *addr1, struct totem_ip_address *addr2);
 int totemip_localhost(int family, struct totem_ip_address *localhost);
 extern int totemip_localhost_check(struct totem_ip_address *addr);
 extern const char *totemip_print(struct totem_ip_address *addr);

+ 67 - 44
exec/totemsrp.c

@@ -526,6 +526,9 @@ static void orf_token_endian_convert (struct orf_token *in, struct orf_token *ou
 static void memb_commit_token_endian_convert (struct memb_commit_token *in, struct memb_commit_token *out);
 static void memb_join_endian_convert (struct memb_join *in, struct memb_join *out);
 static void mcast_endian_convert (struct mcast *in, struct mcast *out);
+static void memb_merge_detect_endian_convert (
+	struct memb_merge_detect *in,
+	struct memb_merge_detect *out);
 static void timer_function_orf_token_timeout (void *data);
 static void timer_function_heartbeat_timeout (void *data);
 static void timer_function_token_retransmit_timeout (void *data);
@@ -2686,8 +2689,7 @@ static int message_handler_orf_token (
 {
 	char token_storage[1500];
 	char token_convert[1500];
-	struct orf_token *token;
-	struct orf_token *token_ref = (struct orf_token *)msg;
+	struct orf_token *token = NULL;
 	int transmits_allowed;
 	int forward_token;
 	int mcasted;
@@ -2713,20 +2715,12 @@ if (random()%100 < 10) {
 }
 #endif
 
-	/*
-	 * Handle merge detection timeout
-	 */
-	if (token_ref->seq == instance->my_last_seq) {
-		start_merge_detect_timeout (instance);
-		instance->my_seq_unchanged += 1;
-	} else {
-		cancel_merge_detect_timeout (instance);
-		cancel_token_hold_retransmit_timeout (instance);
-		instance->my_seq_unchanged = 0;
+	if (endian_conversion_needed) {
+		orf_token_endian_convert ((struct orf_token *)msg,
+			(struct orf_token *)token_convert);
+		msg = (struct orf_token *)token_convert;
 	}
 
-	instance->my_last_seq = token_ref->seq;
-
 	/*
 	 * Make copy of token and retransmit list in case we have
 	 * to flush incoming messages from the kernel queue
@@ -2736,11 +2730,21 @@ if (random()%100 < 10) {
 	memcpy (&token->rtr_list[0], msg + sizeof (struct orf_token),
 		sizeof (struct rtr_item) * RETRANSMIT_ENTRIES_MAX);
 
-	if (endian_conversion_needed) {
-		orf_token_endian_convert (token, (struct orf_token *)token_convert);
-		token = (struct orf_token *)token_convert;
+
+	/*
+	 * Handle merge detection timeout
+	 */
+	if (token->seq == instance->my_last_seq) {
+		start_merge_detect_timeout (instance);
+		instance->my_seq_unchanged += 1;
+	} else {
+		cancel_merge_detect_timeout (instance);
+		cancel_token_hold_retransmit_timeout (instance);
+		instance->my_seq_unchanged = 0;
 	}
 
+	instance->my_last_seq = token->seq;
+
 	totemrrp_recv_flush (instance->totemrrp_handle);
 
 	/*
@@ -2830,7 +2834,6 @@ if (random()%100 < 10) {
 
 		if (sq_lt_compare (instance->last_released + MISSING_MCAST_WINDOW, token->seq + TRANSMITS_ALLOWED)) {
 			transmits_allowed = 0;
-printf ("zero \n");
 		}
 		mcasted = orf_token_mcast (instance, token, transmits_allowed, system_from);
 		if (sq_lt_compare (instance->my_aru, token->aru) ||
@@ -2983,6 +2986,7 @@ static void messages_deliver_to_app (
 	struct mcast *mcast;
 	unsigned int range = 0;
 	unsigned int my_high_delivered_stored = 0;
+	struct totem_ip_address msg_source;
 
 	instance->totemsrp_log_printf (instance->totemsrp_log_level_debug,
 		"Delivering %x to %x\n", instance->my_high_delivered,
@@ -3050,13 +3054,19 @@ static void messages_deliver_to_app (
 			"Delivering MCAST message with seq %x to pending delivery queue\n",
 			mcast->seq);
 
+		if (mcast->header.endian_detector == ENDIAN_LOCAL) {
+			totemip_copy (&msg_source, &mcast->source);
+		} else {
+			totemip_copy_endian_convert (&msg_source, &mcast->source);
+		}
+
 		/*
 		 * Message is locally originated multicast
 		 */
 	 	if (sort_queue_item_p->iov_len > 1 &&
 			sort_queue_item_p->iovec[0].iov_len == sizeof (struct mcast)) {
 			instance->totemsrp_deliver_fn (
-				&mcast->source,
+				&msg_source,
 				&sort_queue_item_p->iovec[1],
 				sort_queue_item_p->iov_len - 1,
 				mcast->header.endian_detector != ENDIAN_LOCAL);
@@ -3065,7 +3075,7 @@ static void messages_deliver_to_app (
 			sort_queue_item_p->iovec[0].iov_base += sizeof (struct mcast);
 
 			instance->totemsrp_deliver_fn (
-				&mcast->source,
+				&msg_source,
 				sort_queue_item_p->iovec,
 				sort_queue_item_p->iov_len,
 				mcast->header.endian_detector != ENDIAN_LOCAL);
@@ -3220,6 +3230,10 @@ static int message_handler_memb_merge_detect (
 {
 	struct memb_merge_detect *memb_merge_detect = (struct memb_merge_detect *)msg;
 
+	if (endian_conversion_needed) {
+		memb_merge_detect_endian_convert (msg, msg);
+	}
+
 	/*
 	 * do nothing if this is a merge detect from this configuration
 	 */
@@ -3341,12 +3355,10 @@ static void memb_join_endian_convert (struct memb_join *in, struct memb_join *ou
 	out->failed_list_entries = swab32 (in->failed_list_entries);
 	out->ring_seq = swab64 (in->ring_seq);
 	for (i = 0; i < out->proc_list_entries; i++) {
-		totemip_copy(&out->proc_list[i], &in->proc_list[i]);
-		out->proc_list[i].family = swab16(out->proc_list[i].family);
+		totemip_copy_endian_convert(&out->proc_list[i], &in->proc_list[i]);
 	}
 	for (i = 0; i < out->failed_list_entries; i++) {
-		totemip_copy(&out->failed_list[i], &in->failed_list[i]);
-		out->failed_list[i].family = swab16(out->failed_list[i].family);
+		totemip_copy_endian_convert(&out->failed_list[i], &in->failed_list[i]);
 	}
 }
 
@@ -3358,24 +3370,27 @@ static void memb_commit_token_endian_convert (struct memb_commit_token *in, stru
 	out->header.endian_detector = ENDIAN_LOCAL;
 	out->header.nodeid = swab32 (in->header.nodeid);
 	out->token_seq = swab32 (in->token_seq);
-	totemip_copy(&out->ring_id.rep, &in->ring_id.rep);
+	totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
 	out->ring_id.seq = swab64 (in->ring_id.seq);
 	out->retrans_flg = swab32 (in->retrans_flg);
 	out->memb_index = swab32 (in->memb_index);
 	out->addr_entries = swab32 (in->addr_entries);
 	for (i = 0; i < out->addr_entries; i++) {
-		totemip_copy(&out->addr[i], &in->addr[i]);
-		out->addr[i].family = swab16(in->addr[i].family);
-
-		totemip_copy(&out->memb_list[i].ring_id.rep,
-			     &in->memb_list[i].ring_id.rep);
-		out->memb_list[i].ring_id.rep.family = swab16(in->memb_list[i].ring_id.rep.family);
+		totemip_copy_endian_convert(&out->addr[i], &in->addr[i]);
 
-		out->memb_list[i].ring_id.seq =
-			swab64 (in->memb_list[i].ring_id.seq);
-		out->memb_list[i].aru = swab32 (in->memb_list[i].aru);
-		out->memb_list[i].high_delivered = swab32 (in->memb_list[i].high_delivered);
-		out->memb_list[i].received_flg = swab32 (in->memb_list[i].received_flg);
+		/*
+		 * Only convert the memb entry if it has been set
+		 */
+		if (in->memb_list[i].ring_id.rep.family != 0) {
+			totemip_copy_endian_convert(&out->memb_list[i].ring_id.rep,
+				     &in->memb_list[i].ring_id.rep);
+	
+			out->memb_list[i].ring_id.seq =
+				swab64 (in->memb_list[i].ring_id.seq);
+			out->memb_list[i].aru = swab32 (in->memb_list[i].aru);
+			out->memb_list[i].high_delivered = swab32 (in->memb_list[i].high_delivered);
+			out->memb_list[i].received_flg = swab32 (in->memb_list[i].received_flg);
+		}
 	}
 }
 
@@ -3389,16 +3404,14 @@ static void orf_token_endian_convert (struct orf_token *in, struct orf_token *ou
 	out->seq = swab32 (in->seq);
 	out->token_seq = swab32 (in->token_seq);
 	out->aru = swab32 (in->aru);
-	totemip_copy(&out->ring_id.rep, &in->ring_id.rep);
-	out->ring_id.rep.family = swab16(in->ring_id.rep.family);
-
+	totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
+	totemip_copy_endian_convert(&out->aru_addr, &in->aru_addr);
 	out->ring_id.seq = swab64 (in->ring_id.seq);
 	out->fcc = swab32 (in->fcc);
 	out->retrans_flg = swab32 (in->retrans_flg);
 	out->rtr_list_entries = swab32 (in->rtr_list_entries);
 	for (i = 0; i < out->rtr_list_entries; i++) {
-		totemip_copy(&out->rtr_list[i].ring_id.rep, &in->rtr_list[i].ring_id.rep);
-		out->rtr_list[i].ring_id.rep.family = swab16(in->rtr_list[i].ring_id.rep.family);
+		totemip_copy_endian_convert(&out->rtr_list[i].ring_id.rep, &in->rtr_list[i].ring_id.rep);
 		out->rtr_list[i].ring_id.seq = swab64 (in->rtr_list[i].ring_id.seq);
 		out->rtr_list[i].seq = swab32 (in->rtr_list[i].seq);
 	}
@@ -3410,13 +3423,23 @@ static void mcast_endian_convert (struct mcast *in, struct mcast *out)
 	out->header.endian_detector = ENDIAN_LOCAL;
 	out->header.nodeid = swab32 (in->header.nodeid);
 	out->seq = swab32 (in->seq);
-	totemip_copy(&out->ring_id.rep, &in->ring_id.rep);
-	out->ring_id.rep.family = swab16(in->ring_id.rep.family);
+	totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
+	totemip_copy_endian_convert(&out->source, &in->source);
 	out->ring_id.seq = swab64 (in->ring_id.seq);
-	out->source = in->source;
 	out->guarantee = in->guarantee;
 }
 
+static void memb_merge_detect_endian_convert (
+	struct memb_merge_detect *in,
+	struct memb_merge_detect *out)
+{
+	out->header.type = in->header.type;
+	out->header.endian_detector = ENDIAN_LOCAL;
+	out->header.nodeid = swab32 (in->header.nodeid);
+	totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
+	out->ring_id.seq = swab64 (in->ring_id.seq);
+}
+
 static int message_handler_memb_join (
 	struct totemsrp_instance *instance,
 	struct totem_ip_address *system_from,