소스 검색

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 년 전
부모
커밋
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,