Quellcode durchsuchen

qnet: Migrate to new votequorum API

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Jan Friesse vor 10 Jahren
Ursprung
Commit
afa22646f9

+ 6 - 4
qdevices/corosync-qdevice-net.c

@@ -578,18 +578,20 @@ qdevice_net_msg_received_node_list_reply(struct qdevice_net_instance *instance,
 		return (-1);
 		return (-1);
 	}
 	}
 
 
-	if (!msg->vote_set || !msg->seq_number_set) {
+	if (!msg->seq_number_set) {
 		qdevice_net_log(LOG_ERR, "Received node list reply message without "
 		qdevice_net_log(LOG_ERR, "Received node list reply message without "
 		    "required options. Disconnecting from server");
 		    "required options. Disconnecting from server");
+
+		return (-1);
 	}
 	}
 
 
 	/*
 	/*
 	 * TODO API
 	 * TODO API
 	 */
 	 */
-	qdevice_net_log(LOG_INFO, "Received node list reply seq=%"PRIu32", vote=%u",
-	    msg->seq_number, msg->vote);
+	qdevice_net_log(LOG_INFO, "Received node list reply seq=%"PRIu32", vote_set=%u, vote=%u",
+	    msg->seq_number, msg->vote_set, (msg->vote_set ? msg->vote : 0));
 
 
-	if (qdevice_net_cast_vote_timer_update(instance, msg->vote) != 0) {
+	if (msg->vote_set && qdevice_net_cast_vote_timer_update(instance, msg->vote) != 0) {
 		return (-1);
 		return (-1);
 	}
 	}
 
 

+ 23 - 10
qdevices/corosync-qnetd.c

@@ -631,6 +631,7 @@ qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnet
 	struct send_buffer_list_entry *send_buffer;
 	struct send_buffer_list_entry *send_buffer;
 	enum tlv_reply_error_code reply_error_code;
 	enum tlv_reply_error_code reply_error_code;
 	enum tlv_vote result_vote;
 	enum tlv_vote result_vote;
+	int add_result_vote;
 
 
 	reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
 	reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
 
 
@@ -674,6 +675,8 @@ qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnet
 		return (0);
 		return (0);
 	}
 	}
 
 
+	add_result_vote = 1;
+
 	switch (msg->node_list_type) {
 	switch (msg->node_list_type) {
 	case TLV_NODE_LIST_TYPE_INITIAL_CONFIG:
 	case TLV_NODE_LIST_TYPE_INITIAL_CONFIG:
 	case TLV_NODE_LIST_TYPE_CHANGED_CONFIG:
 	case TLV_NODE_LIST_TYPE_CHANGED_CONFIG:
@@ -696,8 +699,12 @@ qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnet
 			return (0);
 			return (0);
 		}
 		}
 
 
+		reply_error_code = qnetd_algorithm_membership_node_list_received(client,
+		    msg->seq_number, &msg->ring_id, &msg->nodes, &result_vote);
+		break;
+	case TLV_NODE_LIST_TYPE_QUORUM:
 		if (!msg->quorate_set) {
 		if (!msg->quorate_set) {
-			qnetd_log(LOG_ERR, "Received node list message without quorate set. "
+			qnetd_log(LOG_ERR, "Received quorum list message without quorate set. "
 			    "Sending error reply.");
 			    "Sending error reply.");
 
 
 			if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
 			if (qnetd_client_send_err(client, msg->seq_number_set, msg->seq_number,
@@ -707,10 +714,9 @@ qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnet
 
 
 			return (0);
 			return (0);
 		}
 		}
-
-		reply_error_code = qnetd_algorithm_membership_node_list_received(client,
-		    msg->seq_number, msg->config_version_set, msg->config_version,
-		    &msg->ring_id, msg->quorate, &msg->nodes, &result_vote);
+		reply_error_code = qnetd_algorithm_quorum_node_list_received(client,
+		    msg->seq_number,msg->quorate, &msg->nodes);
+		add_result_vote = 0;
 		break;
 		break;
 	default:
 	default:
 		errx(1, "qnetd_client_msg_received_node_list fatal error. "
 		errx(1, "qnetd_client_msg_received_node_list fatal error. "
@@ -753,6 +759,15 @@ qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnet
 			return (-1);
 			return (-1);
 		}
 		}
 		break;
 		break;
+	case TLV_NODE_LIST_TYPE_QUORUM:
+		node_list_free(&client->last_quorum_node_list);
+		if (node_list_clone(&client->last_quorum_node_list, &msg->nodes) == -1) {
+			qnetd_log(LOG_ERR, "Can't alloc quorum node list clone. "
+			    "Disconnecting client connection.");
+
+			return (-1);
+		}
+		break;
 	default:
 	default:
 		errx(1, "qnetd_client_msg_received_node_list fatal error. "
 		errx(1, "qnetd_client_msg_received_node_list fatal error. "
 		    "Unhandled node_list_type");
 		    "Unhandled node_list_type");
@@ -767,7 +782,8 @@ qnetd_client_msg_received_node_list(struct qnetd_instance *instance, struct qnet
 		return (-1);
 		return (-1);
 	}
 	}
 
 
-	if (msg_create_node_list_reply(&send_buffer->buffer, msg->seq_number, result_vote) == -1) {
+	if (msg_create_node_list_reply(&send_buffer->buffer, msg->seq_number, add_result_vote,
+	    result_vote) == -1) {
 		qnetd_log(LOG_ERR, "Can't alloc node list reply msg. "
 		qnetd_log(LOG_ERR, "Can't alloc node list reply msg. "
 		    "Disconnecting client connection.");
 		    "Disconnecting client connection.");
 
 
@@ -884,7 +900,6 @@ qnetd_client_msg_received_vote_info_reply(struct qnetd_instance *instance,
 {
 {
 	int res;
 	int res;
 	enum tlv_reply_error_code reply_error_code;
 	enum tlv_reply_error_code reply_error_code;
-	enum tlv_vote result_vote;
 
 
 	reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
 	reply_error_code = TLV_REPLY_ERROR_CODE_NO_ERROR;
 
 
@@ -916,9 +931,7 @@ qnetd_client_msg_received_vote_info_reply(struct qnetd_instance *instance,
 		return (0);
 		return (0);
 	}
 	}
 
 
-	reply_error_code = qnetd_algorithm_membership_node_list_received(client,
-	    msg->seq_number, msg->config_version_set, msg->config_version,
-	    &msg->ring_id, msg->quorate, &msg->nodes, &result_vote);
+	reply_error_code = qnetd_algorithm_vote_info_reply_received(client, msg->seq_number);
 
 
 	if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
 	if (reply_error_code != TLV_REPLY_ERROR_CODE_NO_ERROR) {
 		qnetd_log(LOG_ERR, "Algorithm returned error code. "
 		qnetd_log(LOG_ERR, "Algorithm returned error code. "

+ 5 - 3
qdevices/msg.c

@@ -565,7 +565,7 @@ small_buf_err:
 
 
 size_t
 size_t
 msg_create_node_list_reply(struct dynar *msg, uint32_t msg_seq_number,
 msg_create_node_list_reply(struct dynar *msg, uint32_t msg_seq_number,
-    enum tlv_vote vote)
+    int add_result_vote, enum tlv_vote vote)
 {
 {
 
 
 	dynar_clean(msg);
 	dynar_clean(msg);
@@ -577,8 +577,10 @@ msg_create_node_list_reply(struct dynar *msg, uint32_t msg_seq_number,
 		goto small_buf_err;
 		goto small_buf_err;
 	}
 	}
 
 
-	if (tlv_add_vote(msg, vote) == -1) {
-		goto small_buf_err;
+	if (add_result_vote) {
+		if (tlv_add_vote(msg, vote) == -1) {
+			goto small_buf_err;
+		}
 	}
 	}
 
 
 	msg_set_len(msg, dynar_size(msg) - (MSG_TYPE_LENGTH + MSG_LENGTH_LENGTH));
 	msg_set_len(msg, dynar_size(msg) - (MSG_TYPE_LENGTH + MSG_LENGTH_LENGTH));

+ 1 - 1
qdevices/msg.h

@@ -159,7 +159,7 @@ extern size_t		msg_create_node_list(struct dynar *msg,
     const struct node_list *nodes);
     const struct node_list *nodes);
 
 
 extern size_t		msg_create_node_list_reply(struct dynar *msg, uint32_t msg_seq_number,
 extern size_t		msg_create_node_list_reply(struct dynar *msg, uint32_t msg_seq_number,
-    enum tlv_vote vote);
+    int add_result_vote, enum tlv_vote vote);
 
 
 extern size_t		msg_create_ask_for_vote(struct dynar *msg, uint32_t msg_seq_number);
 extern size_t		msg_create_ask_for_vote(struct dynar *msg, uint32_t msg_seq_number);
 
 

+ 58 - 6
qdevices/qdevice-net-send.c

@@ -173,6 +173,8 @@ qdevice_net_send_config_node_list(struct qdevice_net_instance *instance, int ini
 		return (-1);
 		return (-1);
 	}
 	}
 
 
+	node_list_free(&nlist);
+
 	send_buffer_list_put(&instance->send_buffer_list, send_buffer);
 	send_buffer_list_put(&instance->send_buffer_list, send_buffer);
 
 
 	return (0);
 	return (0);
@@ -180,7 +182,57 @@ qdevice_net_send_config_node_list(struct qdevice_net_instance *instance, int ini
 
 
 int
 int
 qdevice_net_send_membership_node_list(struct qdevice_net_instance *instance,
 qdevice_net_send_membership_node_list(struct qdevice_net_instance *instance,
-    enum tlv_quorate quorate, const struct tlv_ring_id *ring_id,
+    const struct tlv_ring_id *ring_id,
+    uint32_t node_list_entries, uint32_t node_list[])
+{
+	struct node_list nlist;
+	struct send_buffer_list_entry *send_buffer;
+	uint32_t i;
+
+	node_list_init(&nlist);
+
+	for (i = 0; i < node_list_entries; i++) {
+		if (node_list_add(&nlist, node_list[i], 0, TLV_NODE_STATE_NOT_SET) == NULL) {
+			qdevice_net_log(LOG_ERR, "Can't allocate membership node list.");
+
+			node_list_free(&nlist);
+
+			return (-1);
+		}
+	}
+
+	send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
+	if (send_buffer == NULL) {
+		qdevice_net_log(LOG_ERR, "Can't allocate send list buffer for membership "
+		    "node list msg");
+
+		node_list_free(&nlist);
+
+		return (-1);
+	}
+
+	instance->last_msg_seq_num++;
+
+	if (msg_create_node_list(&send_buffer->buffer, instance->last_msg_seq_num,
+	    TLV_NODE_LIST_TYPE_MEMBERSHIP,
+	    1, ring_id, 0, 0, 0, 0, &nlist) == 0) {
+		qdevice_net_log(LOG_ERR, "Can't allocate send buffer for membership list msg");
+
+		node_list_free(&nlist);
+
+		return (-1);
+	}
+
+	node_list_free(&nlist);
+
+	send_buffer_list_put(&instance->send_buffer_list, send_buffer);
+
+	return (0);
+}
+
+int
+qdevice_net_send_quorum_node_list(struct qdevice_net_instance *instance,
+    enum tlv_quorate quorate,
     uint32_t node_list_entries, votequorum_node_t node_list[])
     uint32_t node_list_entries, votequorum_node_t node_list[])
 {
 {
 	struct node_list nlist;
 	struct node_list nlist;
@@ -196,7 +248,7 @@ qdevice_net_send_membership_node_list(struct qdevice_net_instance *instance,
 
 
 		if (node_list_add(&nlist, node_list[i].nodeid, 0,
 		if (node_list_add(&nlist, node_list[i].nodeid, 0,
 		    qdevice_net_votequorum_node_state_to_tlv(node_list[i].state)) == NULL) {
 		    qdevice_net_votequorum_node_state_to_tlv(node_list[i].state)) == NULL) {
-			qdevice_net_log(LOG_ERR, "Can't allocate membership node list.");
+			qdevice_net_log(LOG_ERR, "Can't allocate quorum node list.");
 
 
 			node_list_free(&nlist);
 			node_list_free(&nlist);
 
 
@@ -206,7 +258,7 @@ qdevice_net_send_membership_node_list(struct qdevice_net_instance *instance,
 
 
 	send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
 	send_buffer = send_buffer_list_get_new(&instance->send_buffer_list);
 	if (send_buffer == NULL) {
 	if (send_buffer == NULL) {
-		qdevice_net_log(LOG_ERR, "Can't allocate send list buffer for config "
+		qdevice_net_log(LOG_ERR, "Can't allocate send list buffer for quorum "
 		    "node list msg");
 		    "node list msg");
 
 
 		node_list_free(&nlist);
 		node_list_free(&nlist);
@@ -217,9 +269,9 @@ qdevice_net_send_membership_node_list(struct qdevice_net_instance *instance,
 	instance->last_msg_seq_num++;
 	instance->last_msg_seq_num++;
 
 
 	if (msg_create_node_list(&send_buffer->buffer, instance->last_msg_seq_num,
 	if (msg_create_node_list(&send_buffer->buffer, instance->last_msg_seq_num,
-	    TLV_NODE_LIST_TYPE_MEMBERSHIP,
-	    1, ring_id, 0, 0, 1, quorate, &nlist) == 0) {
-		qdevice_net_log(LOG_ERR, "Can't allocate send buffer for config list msg");
+	    TLV_NODE_LIST_TYPE_QUORUM,
+	    0, NULL, 0, 0, 1, quorate, &nlist) == 0) {
+		qdevice_net_log(LOG_ERR, "Can't allocate send buffer for quorum list msg");
 
 
 		node_list_free(&nlist);
 		node_list_free(&nlist);
 
 

+ 5 - 2
qdevices/qdevice-net-send.h

@@ -54,8 +54,11 @@ extern int		qdevice_net_send_config_node_list(struct qdevice_net_instance *insta
     int initial);
     int initial);
 
 
 extern int		qdevice_net_send_membership_node_list(
 extern int		qdevice_net_send_membership_node_list(
-    struct qdevice_net_instance *instance,
-    enum tlv_quorate quorate, const struct tlv_ring_id *ring_id,
+    struct qdevice_net_instance *instance, const struct tlv_ring_id *ring_id,
+    uint32_t node_list_entries, uint32_t node_list[]);
+
+extern int		qdevice_net_send_quorum_node_list(
+    struct qdevice_net_instance *instance, enum tlv_quorate quorate,
     uint32_t node_list_entries, votequorum_node_t node_list[]);
     uint32_t node_list_entries, votequorum_node_t node_list[]);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 78 - 4
qdevices/qdevice-net-votequorum.c

@@ -74,6 +74,78 @@ qdevice_net_votequorum_ring_id_to_tlv(struct tlv_ring_id *tlv_rid,
 	tlv_rid->seq = votequorum_rid->seq;
 	tlv_rid->seq = votequorum_rid->seq;
 }
 }
 
 
+static void
+qdevice_net_votequorum_quorum_notify_callback(votequorum_handle_t votequorum_handle,
+    uint64_t context, uint32_t quorate,
+    uint32_t node_list_entries, votequorum_node_t node_list[])
+{
+	struct qdevice_net_instance *instance;
+	uint32_t u32;
+
+	if (votequorum_context_get(votequorum_handle, (void **)&instance) != CS_OK) {
+		errx(1, "Fatal error. Can't get votequorum context");
+	}
+
+	if (qdevice_net_send_quorum_node_list(instance,
+	    (quorate ? TLV_QUORATE_QUORATE : TLV_QUORATE_INQUORATE),
+	    node_list_entries, node_list) != 0) {
+		/*
+		 * Fatal error -> schedule disconnect
+		 */
+		instance->schedule_disconnect = 1;
+	}
+
+	qdevice_net_log(LOG_DEBUG, "Votequorum quorum notify callback:");
+	qdevice_net_log(LOG_DEBUG, "  Quorate = %u", quorate);
+
+	qdevice_net_log(LOG_DEBUG, "  Node list (size = %"PRIu32"):", node_list_entries);
+	for (u32 = 0; u32 < node_list_entries; u32++) {
+		qdevice_net_log(LOG_DEBUG, "    %"PRIu32" nodeid = %"PRIu32", state = %"PRIu32,
+		    u32, node_list[u32].nodeid, node_list[u32].state);
+	}
+}
+
+static void
+qdevice_net_votequorum_node_list_notify_callback(votequorum_handle_t votequorum_handle,
+    uint64_t context, votequorum_ring_id_t votequorum_ring_id,
+    uint32_t node_list_entries, uint32_t node_list[])
+{
+	struct qdevice_net_instance *instance;
+	struct tlv_ring_id tlv_rid;
+	uint32_t u32;
+
+	if (votequorum_context_get(votequorum_handle, (void **)&instance) != CS_OK) {
+		errx(1, "Fatal error. Can't get votequorum context");
+	}
+
+	qdevice_net_votequorum_ring_id_to_tlv(&tlv_rid, &votequorum_ring_id);
+
+	if (qdevice_net_send_membership_node_list(instance,
+	    &tlv_rid, node_list_entries, node_list) != 0) {
+		/*
+		 * Fatal error -> schedule disconnect
+		 */
+		instance->schedule_disconnect = 1;
+	}
+
+	memcpy(&instance->last_received_votequorum_ring_id, &votequorum_ring_id, sizeof(votequorum_ring_id));
+
+	if (qdevice_net_cast_vote_timer_update(instance, TLV_VOTE_WAIT_FOR_REPLY) != 0) {
+		errx(1, "qdevice_net_votequorum_notify_callback fatal error. "
+		    "Can't update cast vote timer vote");
+	}
+
+	qdevice_net_log(LOG_DEBUG, "Votequorum nodelist notify callback:");
+	qdevice_net_log(LOG_DEBUG, "  Ring_id = (%"PRIx32".%"PRIx64")",
+	    votequorum_ring_id.nodeid, votequorum_ring_id.seq);
+
+	qdevice_net_log(LOG_DEBUG, "  Node list (size = %"PRIu32"):", node_list_entries);
+	for (u32 = 0; u32 < node_list_entries; u32++) {
+		qdevice_net_log(LOG_DEBUG, "    %"PRIu32" nodeid = %"PRIu32,
+		    u32, node_list[u32]);
+	}
+}
+
 //static void
 //static void
 //qdevice_net_votequorum_notify_callback(votequorum_handle_t votequorum_handle,
 //qdevice_net_votequorum_notify_callback(votequorum_handle_t votequorum_handle,
 //    uint64_t context, uint32_t quorate,
 //    uint64_t context, uint32_t quorate,
@@ -127,10 +199,12 @@ qdevice_net_votequorum_init(struct qdevice_net_instance *instance)
 	int fd;
 	int fd;
 
 
 	memset(&votequorum_callbacks, 0, sizeof(votequorum_callbacks));
 	memset(&votequorum_callbacks, 0, sizeof(votequorum_callbacks));
-/*
- *	TODO:
- *	votequorum_callbacks.votequorum_notify_fn = qdevice_net_votequorum_notify_callback;
- */
+
+	votequorum_callbacks.votequorum_quorum_notify_fn =
+	    qdevice_net_votequorum_quorum_notify_callback;
+
+	votequorum_callbacks.votequorum_nodelist_notify_fn =
+	    qdevice_net_votequorum_node_list_notify_callback;
 
 
 	no_retries = 0;
 	no_retries = 0;
 
 

+ 17 - 13
qdevices/qnetd-algo-2nodelms.c

@@ -142,8 +142,7 @@ qnetd_algo_2nodelms_config_node_list_received(struct qnetd_client *client,
 
 
 enum tlv_reply_error_code
 enum tlv_reply_error_code
 qnetd_algo_2nodelms_membership_node_list_received(struct qnetd_client *client,
 qnetd_algo_2nodelms_membership_node_list_received(struct qnetd_client *client,
-    uint32_t msg_seq_num, int config_version_set, uint64_t config_version,
-    const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+    uint32_t msg_seq_num, const struct tlv_ring_id *ring_id,
     const struct node_list *nodes, enum tlv_vote *result_vote)
     const struct node_list *nodes, enum tlv_vote *result_vote)
 {
 {
 	struct node_list_entry *node_info;
 	struct node_list_entry *node_info;
@@ -174,11 +173,9 @@ qnetd_algo_2nodelms_membership_node_list_received(struct qnetd_client *client,
 
 
 	/* If both nodes are present, then we're OK. return a vote */
 	/* If both nodes are present, then we're OK. return a vote */
 	TAILQ_FOREACH(node_info, nodes, entries) {
 	TAILQ_FOREACH(node_info, nodes, entries) {
-		if (node_info->node_state == TLV_NODE_STATE_MEMBER) {
-			node_count++;
-			if (node_info->node_id < low_node_id) {
-				low_node_id = node_info->node_id;
-			}
+		node_count++;
+		if (node_info->node_id < low_node_id) {
+			low_node_id = node_info->node_id;
 		}
 		}
 	}
 	}
 
 
@@ -197,12 +194,10 @@ qnetd_algo_2nodelms_membership_node_list_received(struct qnetd_client *client,
 			continue; /* We've seen our membership list */
 			continue; /* We've seen our membership list */
 		}
 		}
 		TAILQ_FOREACH(node_info, &other_client->last_membership_node_list, entries) {
 		TAILQ_FOREACH(node_info, &other_client->last_membership_node_list, entries) {
-			if (node_info->node_state == TLV_NODE_STATE_MEMBER) {
-				node_count++;
-				qnetd_log(LOG_DEBUG, "algo-2nodelms: seen nodeid %d on client %p (ring ID %" PRIu64 ")", node_info->node_id, other_client, other_info->ring_id.seq);
-				if (node_info->node_id < low_node_id) {
-					low_node_id = node_info->node_id;
-				}
+			node_count++;
+			qnetd_log(LOG_DEBUG, "algo-2nodelms: seen nodeid %d on client %p (ring ID %" PRIu64 ")", node_info->node_id, other_client, other_info->ring_id.seq);
+			if (node_info->node_id < low_node_id) {
+				low_node_id = node_info->node_id;
 			}
 			}
 		}
 		}
 	}
 	}
@@ -229,6 +224,14 @@ qnetd_algo_2nodelms_membership_node_list_received(struct qnetd_client *client,
 	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
 	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
 }
 }
 
 
+enum tlv_reply_error_code
+qnetd_algo_2nodelms_quorum_node_list_received(struct qnetd_client *client,
+    uint32_t msg_seq_num, enum tlv_quorate quorate, const struct node_list *nodes)
+{
+
+	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
+}
+
 /*
 /*
  * Called after client disconnect. Client structure is still existing (and it's part
  * Called after client disconnect. Client structure is still existing (and it's part
  * of a client->cluster), but it is destroyed (and removed from cluster) right after
  * of a client->cluster), but it is destroyed (and removed from cluster) right after
@@ -283,6 +286,7 @@ static struct qnetd_algorithm qnetd_algo_2nodelms = {
 	.init                          = qnetd_algo_2nodelms_client_init,
 	.init                          = qnetd_algo_2nodelms_client_init,
 	.config_node_list_received     = qnetd_algo_2nodelms_config_node_list_received,
 	.config_node_list_received     = qnetd_algo_2nodelms_config_node_list_received,
 	.membership_node_list_received = qnetd_algo_2nodelms_membership_node_list_received,
 	.membership_node_list_received = qnetd_algo_2nodelms_membership_node_list_received,
+	.quorum_node_list_received     = qnetd_algo_2nodelms_quorum_node_list_received,
 	.client_disconnect             = qnetd_algo_2nodelms_client_disconnect,
 	.client_disconnect             = qnetd_algo_2nodelms_client_disconnect,
 	.ask_for_vote_received         = qnetd_algo_2nodelms_ask_for_vote_received,
 	.ask_for_vote_received         = qnetd_algo_2nodelms_ask_for_vote_received,
 	.vote_info_reply_received      = qnetd_algo_2nodelms_vote_info_reply_received,
 	.vote_info_reply_received      = qnetd_algo_2nodelms_vote_info_reply_received,

+ 6 - 2
qdevices/qnetd-algo-2nodelms.h

@@ -49,10 +49,14 @@ extern enum tlv_reply_error_code	qnetd_algo_2nodelms_config_node_list_received(
     enum tlv_vote *result_vote);
     enum tlv_vote *result_vote);
 
 
 extern enum tlv_reply_error_code	qnetd_algo_2nodelms_membership_node_list_received(
 extern enum tlv_reply_error_code	qnetd_algo_2nodelms_membership_node_list_received(
-    struct qnetd_client *client, uint32_t msg_seq_num, int config_version_set,
-    uint64_t config_version, const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+    struct qnetd_client *client, uint32_t msg_seq_num,
+    const struct tlv_ring_id *ring_id,
     const struct node_list *nodes, enum tlv_vote *result_vote);
     const struct node_list *nodes, enum tlv_vote *result_vote);
 
 
+extern enum tlv_reply_error_code	qnetd_algo_2nodelms_quorum_node_list_received(
+    struct qnetd_client *client, uint32_t msg_seq_num,
+    enum tlv_quorate quorate, const struct node_list *nodes);
+
 extern void				qnetd_algo_2nodelms_client_disconnect(
 extern void				qnetd_algo_2nodelms_client_disconnect(
     struct qnetd_client *client, int server_going_down);
     struct qnetd_client *client, int server_going_down);
 
 

+ 10 - 2
qdevices/qnetd-algo-ffsplit.c

@@ -73,8 +73,7 @@ qnetd_algo_ffsplit_config_node_list_received(struct qnetd_client *client,
 
 
 enum tlv_reply_error_code
 enum tlv_reply_error_code
 qnetd_algo_ffsplit_membership_node_list_received(struct qnetd_client *client,
 qnetd_algo_ffsplit_membership_node_list_received(struct qnetd_client *client,
-    uint32_t msg_seq_num, int config_version_set, uint64_t config_version,
-    const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+    uint32_t msg_seq_num, const struct tlv_ring_id *ring_id,
     const struct node_list *nodes, enum tlv_vote *result_vote)
     const struct node_list *nodes, enum tlv_vote *result_vote)
 {
 {
 
 
@@ -83,6 +82,14 @@ qnetd_algo_ffsplit_membership_node_list_received(struct qnetd_client *client,
 	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
 	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
 }
 }
 
 
+enum tlv_reply_error_code
+qnetd_algo_ffsplit_quorum_node_list_received(struct qnetd_client *client,
+    uint32_t msg_seq_num, enum tlv_quorate quorate, const struct node_list *nodes)
+{
+
+	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
+}
+
 void
 void
 qnetd_algo_ffsplit_client_disconnect(struct qnetd_client *client, int server_going_down)
 qnetd_algo_ffsplit_client_disconnect(struct qnetd_client *client, int server_going_down)
 {
 {
@@ -110,6 +117,7 @@ static struct qnetd_algorithm qnetd_algo_ffsplit = {
 	.init                          = qnetd_algo_ffsplit_client_init,
 	.init                          = qnetd_algo_ffsplit_client_init,
 	.config_node_list_received     = qnetd_algo_ffsplit_config_node_list_received,
 	.config_node_list_received     = qnetd_algo_ffsplit_config_node_list_received,
 	.membership_node_list_received = qnetd_algo_ffsplit_membership_node_list_received,
 	.membership_node_list_received = qnetd_algo_ffsplit_membership_node_list_received,
+	.quorum_node_list_received     = qnetd_algo_ffsplit_quorum_node_list_received,
 	.client_disconnect             = qnetd_algo_ffsplit_client_disconnect,
 	.client_disconnect             = qnetd_algo_ffsplit_client_disconnect,
 	.ask_for_vote_received         = qnetd_algo_ffsplit_ask_for_vote_received,
 	.ask_for_vote_received         = qnetd_algo_ffsplit_ask_for_vote_received,
 	.vote_info_reply_received      = qnetd_algo_ffsplit_vote_info_reply_received,
 	.vote_info_reply_received      = qnetd_algo_ffsplit_vote_info_reply_received,

+ 6 - 2
qdevices/qnetd-algo-ffsplit.h

@@ -49,10 +49,14 @@ extern enum tlv_reply_error_code	qnetd_algo_ffsplit_config_node_list_received(
     enum tlv_vote *result_vote);
     enum tlv_vote *result_vote);
 
 
 extern enum tlv_reply_error_code	qnetd_algo_ffsplit_membership_node_list_received(
 extern enum tlv_reply_error_code	qnetd_algo_ffsplit_membership_node_list_received(
-    struct qnetd_client *client, uint32_t msg_seq_num, int config_version_set,
-    uint64_t config_version, const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+    struct qnetd_client *client, uint32_t msg_seq_num,
+    const struct tlv_ring_id *ring_id,
     const struct node_list *nodes, enum tlv_vote *result_vote);
     const struct node_list *nodes, enum tlv_vote *result_vote);
 
 
+extern enum tlv_reply_error_code	qnetd_algo_ffsplit_quorum_node_list_received(
+    struct qnetd_client *client, uint32_t msg_seq_num,
+    enum tlv_quorate quorate, const struct node_list *nodes);
+
 extern void				qnetd_algo_ffsplit_client_disconnect(
 extern void				qnetd_algo_ffsplit_client_disconnect(
     struct qnetd_client *client, int server_going_down);
     struct qnetd_client *client, int server_going_down);
 
 

+ 13 - 2
qdevices/qnetd-algo-lms.c

@@ -168,6 +168,9 @@ static int ring_ids_match(struct qnetd_client *client, const struct tlv_ring_id
 		 * we need to wait until they have all caught up before making a decision
 		 * we need to wait until they have all caught up before making a decision
 		 */
 		 */
 		TAILQ_FOREACH(node_info, &client->last_membership_node_list, entries) {
 		TAILQ_FOREACH(node_info, &client->last_membership_node_list, entries) {
+			/*
+			 * TODO: last_membership_node_list state is always set to NOT_SET
+			 */
 			if (node_info->node_state == TLV_NODE_STATE_MEMBER && node_info->node_id == other_client->node_id) {
 			if (node_info->node_state == TLV_NODE_STATE_MEMBER && node_info->node_id == other_client->node_id) {
 				in_our_partition = 1;
 				in_our_partition = 1;
 			}
 			}
@@ -354,8 +357,7 @@ qnetd_algo_lms_config_node_list_received(struct qnetd_client *client,
 
 
 enum tlv_reply_error_code
 enum tlv_reply_error_code
 qnetd_algo_lms_membership_node_list_received(struct qnetd_client *client,
 qnetd_algo_lms_membership_node_list_received(struct qnetd_client *client,
-    uint32_t msg_seq_num, int config_version_set, uint64_t config_version,
-    const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+    uint32_t msg_seq_num, const struct tlv_ring_id *ring_id,
     const struct node_list *nodes, enum tlv_vote *result_vote)
     const struct node_list *nodes, enum tlv_vote *result_vote)
 {
 {
 	struct qnetd_algo_lms_info *info = client->algorithm_data;
 	struct qnetd_algo_lms_info *info = client->algorithm_data;
@@ -367,6 +369,14 @@ qnetd_algo_lms_membership_node_list_received(struct qnetd_client *client,
 	return do_lms_algorithm(client, result_vote);
 	return do_lms_algorithm(client, result_vote);
 }
 }
 
 
+enum tlv_reply_error_code
+qnetd_algo_lms_quorum_node_list_received(struct qnetd_client *client,
+    uint32_t msg_seq_num, enum tlv_quorate quorate, const struct node_list *nodes)
+{
+
+	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
+}
+
 /*
 /*
  * Called after client disconnect. Client structure is still existing (and it's part
  * Called after client disconnect. Client structure is still existing (and it's part
  * of a client->cluster), but it is destroyed (and removed from cluster) right after
  * of a client->cluster), but it is destroyed (and removed from cluster) right after
@@ -412,6 +422,7 @@ static struct qnetd_algorithm qnetd_algo_lms = {
 	.init                          = qnetd_algo_lms_client_init,
 	.init                          = qnetd_algo_lms_client_init,
 	.config_node_list_received     = qnetd_algo_lms_config_node_list_received,
 	.config_node_list_received     = qnetd_algo_lms_config_node_list_received,
 	.membership_node_list_received = qnetd_algo_lms_membership_node_list_received,
 	.membership_node_list_received = qnetd_algo_lms_membership_node_list_received,
+	.quorum_node_list_received     = qnetd_algo_lms_quorum_node_list_received,
 	.client_disconnect             = qnetd_algo_lms_client_disconnect,
 	.client_disconnect             = qnetd_algo_lms_client_disconnect,
 	.ask_for_vote_received         = qnetd_algo_lms_ask_for_vote_received,
 	.ask_for_vote_received         = qnetd_algo_lms_ask_for_vote_received,
 	.vote_info_reply_received      = qnetd_algo_lms_vote_info_reply_received,
 	.vote_info_reply_received      = qnetd_algo_lms_vote_info_reply_received,

+ 6 - 2
qdevices/qnetd-algo-lms.h

@@ -49,10 +49,14 @@ extern enum tlv_reply_error_code	qnetd_algo_lms_config_node_list_received(
     enum tlv_vote *result_vote);
     enum tlv_vote *result_vote);
 
 
 extern enum tlv_reply_error_code	qnetd_algo_lms_membership_node_list_received(
 extern enum tlv_reply_error_code	qnetd_algo_lms_membership_node_list_received(
-    struct qnetd_client *client, uint32_t msg_seq_num, int config_version_set,
-    uint64_t config_version, const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+    struct qnetd_client *client, uint32_t msg_seq_num,
+    const struct tlv_ring_id *ring_id,
     const struct node_list *nodes, enum tlv_vote *result_vote);
     const struct node_list *nodes, enum tlv_vote *result_vote);
 
 
+extern enum tlv_reply_error_code	qnetd_algo_lms_quorum_node_list_received(
+    struct qnetd_client *client, uint32_t msg_seq_num,
+    enum tlv_quorate quorate, const struct node_list *nodes);
+
 extern void				qnetd_algo_lms_client_disconnect(
 extern void				qnetd_algo_lms_client_disconnect(
     struct qnetd_client *client, int server_going_down);
     struct qnetd_client *client, int server_going_down);
 
 

+ 30 - 10
qdevices/qnetd-algo-test.c

@@ -167,9 +167,8 @@ qnetd_algo_test_config_node_list_received(struct qnetd_client *client,
 /*
 /*
  * Called after client sent membership node list.
  * Called after client sent membership node list.
  * All client fields are already set. Nodes is actual node list.
  * All client fields are already set. Nodes is actual node list.
- * msg_seq_num is 32-bit number set by client. If client sent config file version,
- * config_version_set is set to 1 and config_version contains valid config file version.
- * ring_id and quorate are copied from client votequorum callback.
+ * msg_seq_num is 32-bit number set by client.
+ * ring_id is copied from client votequorum callback.
  *
  *
  * Function has to return result_vote. This can be one of ack/nack, ask_later (client
  * Function has to return result_vote. This can be one of ack/nack, ask_later (client
  * should ask later for a vote) or wait_for_reply (client should wait for reply).
  * should ask later for a vote) or wait_for_reply (client should wait for reply).
@@ -180,8 +179,7 @@ qnetd_algo_test_config_node_list_received(struct qnetd_client *client,
 
 
 enum tlv_reply_error_code
 enum tlv_reply_error_code
 qnetd_algo_test_membership_node_list_received(struct qnetd_client *client,
 qnetd_algo_test_membership_node_list_received(struct qnetd_client *client,
-    uint32_t msg_seq_num, int config_version_set, uint64_t config_version,
-    const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+    uint32_t msg_seq_num, const struct tlv_ring_id *ring_id,
     const struct node_list *nodes, enum tlv_vote *result_vote)
     const struct node_list *nodes, enum tlv_vote *result_vote)
 {
 {
 
 
@@ -190,13 +188,8 @@ qnetd_algo_test_membership_node_list_received(struct qnetd_client *client,
 
 
 	qnetd_log(LOG_INFO, "algo-test:   msg seq num %"PRIu32, msg_seq_num);
 	qnetd_log(LOG_INFO, "algo-test:   msg seq num %"PRIu32, msg_seq_num);
 
 
-	if (config_version_set) {
-		qnetd_log(LOG_INFO, "algo-test:   config version = %"PRIu64, config_version);
-	}
-
 	qnetd_log(LOG_INFO, "algo-test:   ring id = (%"PRIx32".%"PRIx64")",
 	qnetd_log(LOG_INFO, "algo-test:   ring id = (%"PRIx32".%"PRIx64")",
 	    ring_id->node_id, ring_id->seq);
 	    ring_id->node_id, ring_id->seq);
-	qnetd_log(LOG_INFO, "algo-test:   quorate = %u", quorate);
 
 
 	qnetd_algo_dump_node_list(client, nodes);
 	qnetd_algo_dump_node_list(client, nodes);
 
 
@@ -205,6 +198,32 @@ qnetd_algo_test_membership_node_list_received(struct qnetd_client *client,
 	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
 	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
 }
 }
 
 
+/*
+ * Called after client sent quorum node list.
+ * All client fields are already set. Nodes is actual node list.
+ * msg_seq_num is 32-bit number set by client.
+ * quorate is copied from client votequorum callback.
+ * Function is just informative. If client vote is required to change, it's possible
+ * to use qnetd_client_send_vote_info.
+ *
+ * Return TLV_REPLY_ERROR_CODE_NO_ERROR on success, different TLV_REPLY_ERROR_CODE_*
+ * on failure (error is send back to client)
+ */
+enum tlv_reply_error_code
+qnetd_algo_test_quorum_node_list_received(struct qnetd_client *client,
+    uint32_t msg_seq_num, enum tlv_quorate quorate, const struct node_list *nodes)
+{
+	qnetd_log(LOG_INFO, "algo-test: Client %p (cluster %s, node_id %"PRIx32") "
+	    "sent quorum node list.", client, client->cluster_name, client->node_id);
+
+	qnetd_log(LOG_INFO, "algo-test:   msg seq num %"PRIu32, msg_seq_num);
+	qnetd_log(LOG_INFO, "algo-test:   quorate = %u", quorate);
+
+	qnetd_algo_dump_node_list(client, nodes);
+
+	return (TLV_REPLY_ERROR_CODE_NO_ERROR);
+}
+
 /*
 /*
  * Called after client disconnect. Client structure is still existing (and it's part
  * Called after client disconnect. Client structure is still existing (and it's part
  * of a client->cluster), but it is destroyed (and removed from cluster) right after
  * of a client->cluster), but it is destroyed (and removed from cluster) right after
@@ -254,6 +273,7 @@ static struct qnetd_algorithm qnetd_algo_test = {
 	.init                          = qnetd_algo_test_client_init,
 	.init                          = qnetd_algo_test_client_init,
 	.config_node_list_received     = qnetd_algo_test_config_node_list_received,
 	.config_node_list_received     = qnetd_algo_test_config_node_list_received,
 	.membership_node_list_received = qnetd_algo_test_membership_node_list_received,
 	.membership_node_list_received = qnetd_algo_test_membership_node_list_received,
+	.quorum_node_list_received     = qnetd_algo_test_quorum_node_list_received,
 	.client_disconnect             = qnetd_algo_test_client_disconnect,
 	.client_disconnect             = qnetd_algo_test_client_disconnect,
 	.ask_for_vote_received         = qnetd_algo_test_ask_for_vote_received,
 	.ask_for_vote_received         = qnetd_algo_test_ask_for_vote_received,
 	.vote_info_reply_received      = qnetd_algo_test_vote_info_reply_received,
 	.vote_info_reply_received      = qnetd_algo_test_vote_info_reply_received,

+ 6 - 2
qdevices/qnetd-algo-test.h

@@ -49,10 +49,14 @@ extern enum tlv_reply_error_code	qnetd_algo_test_config_node_list_received(
     enum tlv_vote *result_vote);
     enum tlv_vote *result_vote);
 
 
 extern enum tlv_reply_error_code	qnetd_algo_test_membership_node_list_received(
 extern enum tlv_reply_error_code	qnetd_algo_test_membership_node_list_received(
-    struct qnetd_client *client, uint32_t msg_seq_num, int config_version_set,
-    uint64_t config_version, const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+    struct qnetd_client *client, uint32_t msg_seq_num,
+    const struct tlv_ring_id *ring_id,
     const struct node_list *nodes, enum tlv_vote *result_vote);
     const struct node_list *nodes, enum tlv_vote *result_vote);
 
 
+extern enum tlv_reply_error_code	qnetd_algo_test_quorum_node_list_received(
+    struct qnetd_client *client, uint32_t msg_seq_num,
+    enum tlv_quorate quorate, const struct node_list *nodes);
+
 extern void				qnetd_algo_test_client_disconnect(
 extern void				qnetd_algo_test_client_disconnect(
     struct qnetd_client *client, int server_going_down);
     struct qnetd_client *client, int server_going_down);
 
 

+ 20 - 3
qdevices/qnetd-algorithm.c

@@ -77,8 +77,7 @@ qnetd_algorithm_config_node_list_received(struct qnetd_client *client,
 
 
 enum tlv_reply_error_code
 enum tlv_reply_error_code
 qnetd_algorithm_membership_node_list_received(struct qnetd_client *client,
 qnetd_algorithm_membership_node_list_received(struct qnetd_client *client,
-    uint32_t msg_seq_num, int config_version_set, uint64_t config_version,
-    const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+    uint32_t msg_seq_num, const struct tlv_ring_id *ring_id,
     const struct node_list *nodes, enum tlv_vote *result_vote)
     const struct node_list *nodes, enum tlv_vote *result_vote)
 {
 {
 
 
@@ -92,7 +91,25 @@ qnetd_algorithm_membership_node_list_received(struct qnetd_client *client,
 
 
 	return qnetd_algorithm[client->decision_algorithm]->membership_node_list_received(
 	return qnetd_algorithm[client->decision_algorithm]->membership_node_list_received(
 		client, msg_seq_num,
 		client, msg_seq_num,
-		config_version_set, config_version, ring_id, quorate, nodes, result_vote);
+		ring_id, nodes, result_vote);
+}
+
+enum tlv_reply_error_code
+qnetd_algorithm_quorum_node_list_received(struct qnetd_client *client,
+    uint32_t msg_seq_num, enum tlv_quorate quorate,
+    const struct node_list *nodes)
+{
+
+	if (client->decision_algorithm >= MAX_QNETD_ALGORITHMS ||
+	    qnetd_algorithm[client->decision_algorithm] == NULL) {
+
+		errx(1, "qnetd_algorithm_quorum_node_list_received unhandled "
+		    "decision algorithm");
+		return (TLV_REPLY_ERROR_CODE_INTERNAL_ERROR);
+	}
+
+	return qnetd_algorithm[client->decision_algorithm]->quorum_node_list_received(
+		client, msg_seq_num, quorate, nodes);
 }
 }
 
 
 void
 void

+ 11 - 5
qdevices/qnetd-algorithm.h

@@ -53,10 +53,13 @@ extern enum tlv_reply_error_code	qnetd_algorithm_config_node_list_received(
     enum tlv_vote *result_vote);
     enum tlv_vote *result_vote);
 
 
 extern enum tlv_reply_error_code	qnetd_algorithm_membership_node_list_received(
 extern enum tlv_reply_error_code	qnetd_algorithm_membership_node_list_received(
-    struct qnetd_client *client, uint32_t msg_seq_num, int config_version_set,
-    uint64_t config_version, const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+    struct qnetd_client *client, uint32_t msg_seq_num, const struct tlv_ring_id *ring_id,
     const struct node_list *nodes, enum tlv_vote *result_vote);
     const struct node_list *nodes, enum tlv_vote *result_vote);
 
 
+extern enum tlv_reply_error_code	qnetd_algorithm_quorum_node_list_received(
+    struct qnetd_client *client, uint32_t msg_seq_num, enum tlv_quorate quorate,
+    const struct node_list *nodes);
+
 extern void				qnetd_algorithm_client_disconnect(
 extern void				qnetd_algorithm_client_disconnect(
     struct qnetd_client *client, int server_going_down);
     struct qnetd_client *client, int server_going_down);
 
 
@@ -72,11 +75,14 @@ struct qnetd_algorithm {
 	void (*client_disconnect)(struct qnetd_client *client, int server_going_down);
 	void (*client_disconnect)(struct qnetd_client *client, int server_going_down);
 
 
 	enum tlv_reply_error_code (*membership_node_list_received)(
 	enum tlv_reply_error_code (*membership_node_list_received)(
-		struct qnetd_client *client,
-		uint32_t msg_seq_num, int config_version_set, uint64_t config_version,
-		const struct tlv_ring_id *ring_id, enum tlv_quorate quorate,
+		struct qnetd_client *client, uint32_t msg_seq_num,
+		const struct tlv_ring_id *ring_id,
 		const struct node_list *nodes, enum tlv_vote *result_vote);
 		const struct node_list *nodes, enum tlv_vote *result_vote);
 
 
+	enum tlv_reply_error_code (*quorum_node_list_received)(
+		struct qnetd_client *client, uint32_t msg_seq_num, enum tlv_quorate quorate,
+		const struct node_list *nodes);
+
 	enum tlv_reply_error_code (*config_node_list_received)(
 	enum tlv_reply_error_code (*config_node_list_received)(
 		struct qnetd_client *client,
 		struct qnetd_client *client,
 		uint32_t msg_seq_num, int config_version_set, uint64_t config_version,
 		uint32_t msg_seq_num, int config_version_set, uint64_t config_version,

+ 2 - 0
qdevices/qnetd-client.c

@@ -50,6 +50,7 @@ qnetd_client_init(struct qnetd_client *client, PRFileDesc *sock, PRNetAddr *addr
 	send_buffer_list_init(&client->send_buffer_list, max_send_buffers, max_send_size);
 	send_buffer_list_init(&client->send_buffer_list, max_send_buffers, max_send_size);
 	node_list_init(&client->configuration_node_list);
 	node_list_init(&client->configuration_node_list);
 	node_list_init(&client->last_membership_node_list);
 	node_list_init(&client->last_membership_node_list);
+	node_list_init(&client->last_quorum_node_list);
 }
 }
 
 
 void
 void
@@ -57,6 +58,7 @@ qnetd_client_destroy(struct qnetd_client *client)
 {
 {
 
 
 	free(client->cluster_name);
 	free(client->cluster_name);
+	node_list_free(&client->last_quorum_node_list);
 	node_list_free(&client->last_membership_node_list);
 	node_list_free(&client->last_membership_node_list);
 	node_list_free(&client->configuration_node_list);
 	node_list_free(&client->configuration_node_list);
 	send_buffer_list_free(&client->send_buffer_list);
 	send_buffer_list_free(&client->send_buffer_list);

+ 1 - 0
qdevices/qnetd-client.h

@@ -71,6 +71,7 @@ struct qnetd_client {
 	void *algorithm_data;
 	void *algorithm_data;
 	struct node_list configuration_node_list;
 	struct node_list configuration_node_list;
 	struct node_list last_membership_node_list;
 	struct node_list last_membership_node_list;
+	struct node_list last_quorum_node_list;
 	struct qnetd_cluster *cluster;
 	struct qnetd_cluster *cluster;
 	TAILQ_ENTRY(qnetd_client) entries;
 	TAILQ_ENTRY(qnetd_client) entries;
 	TAILQ_ENTRY(qnetd_client) cluster_entries;
 	TAILQ_ENTRY(qnetd_client) cluster_entries;

+ 2 - 1
qdevices/tlv.c

@@ -844,7 +844,8 @@ tlv_iter_decode_node_list_type(struct tlv_iterator *tlv_iter,
 
 
 	if (tmp_node_list_type != TLV_NODE_LIST_TYPE_INITIAL_CONFIG &&
 	if (tmp_node_list_type != TLV_NODE_LIST_TYPE_INITIAL_CONFIG &&
 	    tmp_node_list_type != TLV_NODE_LIST_TYPE_CHANGED_CONFIG &&
 	    tmp_node_list_type != TLV_NODE_LIST_TYPE_CHANGED_CONFIG &&
-	    tmp_node_list_type != TLV_NODE_LIST_TYPE_MEMBERSHIP) {
+	    tmp_node_list_type != TLV_NODE_LIST_TYPE_MEMBERSHIP &&
+	    tmp_node_list_type != TLV_NODE_LIST_TYPE_QUORUM) {
 		return (-4);
 		return (-4);
 	}
 	}
 
 

+ 1 - 0
qdevices/tlv.h

@@ -116,6 +116,7 @@ enum tlv_node_list_type {
 	TLV_NODE_LIST_TYPE_INITIAL_CONFIG = 0,
 	TLV_NODE_LIST_TYPE_INITIAL_CONFIG = 0,
 	TLV_NODE_LIST_TYPE_CHANGED_CONFIG = 1,
 	TLV_NODE_LIST_TYPE_CHANGED_CONFIG = 1,
 	TLV_NODE_LIST_TYPE_MEMBERSHIP = 2,
 	TLV_NODE_LIST_TYPE_MEMBERSHIP = 2,
+	TLV_NODE_LIST_TYPE_QUORUM = 3,
 };
 };
 
 
 enum tlv_vote {
 enum tlv_vote {