corosync  2.4.5
totemconfig.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002-2005 MontaVista Software, Inc.
3  * Copyright (c) 2006-2013 Red Hat, Inc.
4  *
5  * All rights reserved.
6  *
7  * Author: Steven Dake (sdake@redhat.com)
8  * Jan Friesse (jfriesse@redhat.com)
9  *
10  * This software licensed under BSD license, the text of which follows:
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * - Redistributions of source code must retain the above copyright notice,
16  * this list of conditions and the following disclaimer.
17  * - Redistributions in binary form must reproduce the above copyright notice,
18  * this list of conditions and the following disclaimer in the documentation
19  * and/or other materials provided with the distribution.
20  * - Neither the name of the MontaVista Software, Inc. nor the names of its
21  * contributors may be used to endorse or promote products derived from this
22  * software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34  * THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #include <config.h>
38 
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <unistd.h>
44 #include <sys/socket.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #include <sys/param.h>
51 
52 #include <corosync/swab.h>
53 #include <corosync/list.h>
54 #include <qb/qbdefs.h>
55 #include <corosync/totem/totem.h>
56 #include <corosync/config.h>
57 #include <corosync/logsys.h>
58 #include <corosync/icmap.h>
59 
60 #include "util.h"
61 #include "totemconfig.h"
62 
63 #define TOKEN_RETRANSMITS_BEFORE_LOSS_CONST 4
64 #define TOKEN_TIMEOUT 1000
65 #define TOKEN_COEFFICIENT 650
66 #define JOIN_TIMEOUT 50
67 #define MERGE_TIMEOUT 200
68 #define DOWNCHECK_TIMEOUT 1000
69 #define FAIL_TO_RECV_CONST 2500
70 #define SEQNO_UNCHANGED_CONST 30
71 #define MINIMUM_TIMEOUT (int)(1000/HZ)*3
72 #define MAX_NETWORK_DELAY 50
73 #define WINDOW_SIZE 50
74 #define MAX_MESSAGES 17
75 #define MISS_COUNT_CONST 5
76 #define RRP_PROBLEM_COUNT_TIMEOUT 2000
77 #define RRP_PROBLEM_COUNT_THRESHOLD_DEFAULT 10
78 #define RRP_PROBLEM_COUNT_THRESHOLD_MIN 2
79 #define RRP_AUTORECOVERY_CHECK_TIMEOUT 1000
80 #define BLOCK_UNLISTED_IPS 1
81 
82 #define DEFAULT_PORT 5405
83 
84 static char error_string_response[768];
85 
86 static void add_totem_config_notification(struct totem_config *totem_config);
87 
88 
89 /* All the volatile parameters are uint32s, luckily */
90 static uint32_t *totem_get_param_by_name(struct totem_config *totem_config, const char *param_name)
91 {
92  if (strcmp(param_name, "totem.token") == 0)
93  return &totem_config->token_timeout;
94  if (strcmp(param_name, "totem.token_retransmit") == 0)
95  return &totem_config->token_retransmit_timeout;
96  if (strcmp(param_name, "totem.hold") == 0)
97  return &totem_config->token_hold_timeout;
98  if (strcmp(param_name, "totem.token_retransmits_before_loss_const") == 0)
99  return &totem_config->token_retransmits_before_loss_const;
100  if (strcmp(param_name, "totem.join") == 0)
101  return &totem_config->join_timeout;
102  if (strcmp(param_name, "totem.send_join") == 0)
103  return &totem_config->send_join_timeout;
104  if (strcmp(param_name, "totem.consensus") == 0)
105  return &totem_config->consensus_timeout;
106  if (strcmp(param_name, "totem.merge") == 0)
107  return &totem_config->merge_timeout;
108  if (strcmp(param_name, "totem.downcheck") == 0)
109  return &totem_config->downcheck_timeout;
110  if (strcmp(param_name, "totem.fail_recv_const") == 0)
111  return &totem_config->fail_to_recv_const;
112  if (strcmp(param_name, "totem.seqno_unchanged_const") == 0)
113  return &totem_config->seqno_unchanged_const;
114  if (strcmp(param_name, "totem.rrp_token_expired_timeout") == 0)
115  return &totem_config->rrp_token_expired_timeout;
116  if (strcmp(param_name, "totem.rrp_problem_count_timeout") == 0)
117  return &totem_config->rrp_problem_count_timeout;
118  if (strcmp(param_name, "totem.rrp_problem_count_threshold") == 0)
119  return &totem_config->rrp_problem_count_threshold;
120  if (strcmp(param_name, "totem.rrp_problem_count_mcast_threshold") == 0)
121  return &totem_config->rrp_problem_count_mcast_threshold;
122  if (strcmp(param_name, "totem.rrp_autorecovery_check_timeout") == 0)
123  return &totem_config->rrp_autorecovery_check_timeout;
124  if (strcmp(param_name, "totem.heartbeat_failures_allowed") == 0)
125  return &totem_config->heartbeat_failures_allowed;
126  if (strcmp(param_name, "totem.max_network_delay") == 0)
127  return &totem_config->max_network_delay;
128  if (strcmp(param_name, "totem.window_size") == 0)
129  return &totem_config->window_size;
130  if (strcmp(param_name, "totem.max_messages") == 0)
131  return &totem_config->max_messages;
132  if (strcmp(param_name, "totem.miss_count_const") == 0)
133  return &totem_config->miss_count_const;
134  if (strcmp(param_name, "totem.block_unlisted_ips") == 0)
135  return &totem_config->block_unlisted_ips;
136 
137  return NULL;
138 }
139 
140 /*
141  * Read key_name from icmap. If key is not found or key_name == delete_key or if allow_zero is false
142  * and readed value is zero, default value is used and stored into totem_config.
143  */
144 static void totem_volatile_config_set_value (struct totem_config *totem_config,
145  const char *key_name, const char *deleted_key, unsigned int default_value,
146  int allow_zero_value)
147 {
148  char runtime_key_name[ICMAP_KEYNAME_MAXLEN];
149 
150  if (icmap_get_uint32(key_name, totem_get_param_by_name(totem_config, key_name)) != CS_OK ||
151  (deleted_key != NULL && strcmp(deleted_key, key_name) == 0) ||
152  (!allow_zero_value && *totem_get_param_by_name(totem_config, key_name) == 0)) {
153  *totem_get_param_by_name(totem_config, key_name) = default_value;
154  }
155 
156  /*
157  * Store totem_config value to cmap runtime section
158  */
159  if (strlen("runtime.config.") + strlen(key_name) >= ICMAP_KEYNAME_MAXLEN) {
160  /*
161  * This shouldn't happen
162  */
163  return ;
164  }
165 
166  strcpy(runtime_key_name, "runtime.config.");
167  strcat(runtime_key_name, key_name);
168 
169  icmap_set_uint32(runtime_key_name, *totem_get_param_by_name(totem_config, key_name));
170 }
171 
172 /*
173  * Read string value stored in key_name from icmap, use it as a boolean (yes/no) type, convert it
174  * to integer value (1/0) and store into totem_config.
175  *
176  * If key is not found or key_name == delete_key default value is used
177  * and stored into totem_config.
178  */
179 static void totem_volatile_config_set_boolean_value (struct totem_config *totem_config,
180  const char *key_name, const char *deleted_key, unsigned int default_value)
181 {
182  char runtime_key_name[ICMAP_KEYNAME_MAXLEN];
183  char *str;
184  int val;
185 
186  str = NULL;
187  val = default_value;
188 
189  if ((deleted_key != NULL && strcmp(deleted_key, key_name) == 0) ||
190  (icmap_get_string(key_name, &str) != CS_OK)) {
191  /*
192  * Do nothing. str is NULL (icmap_get_string ether not called or
193  * not changed str).
194  */
195  } else {
196  if (strcmp(str, "yes") == 0) {
197  val = 1;
198  } else if (strcmp(str, "no") == 0) {
199  val = 0;
200  }
201  free(str);
202  }
203 
204  /*
205  * Store totem_config value to cmap runtime section
206  */
207  if (strlen("runtime.config.") + strlen(key_name) >= ICMAP_KEYNAME_MAXLEN) {
208  /*
209  * This shouldn't happen
210  */
211  return ;
212  }
213 
214  strcpy(runtime_key_name, "runtime.config.");
215  strcat(runtime_key_name, key_name);
216 
217  *totem_get_param_by_name(totem_config, key_name) = val;
218 
219  icmap_set_uint32(runtime_key_name, val);
220 }
221 
222 /*
223  * Read and validate config values from cmap and store them into totem_config. If key doesn't exists,
224  * default value is stored. deleted_key is name of key beeing processed by delete operation
225  * from cmap. It is considered as non existing even if it can be read. Can be NULL.
226  */
227 static void totem_volatile_config_read (struct totem_config *totem_config, const char *deleted_key)
228 {
229  uint32_t u32;
230 
231  totem_volatile_config_set_value(totem_config, "totem.token_retransmits_before_loss_const", deleted_key,
233 
234  totem_volatile_config_set_value(totem_config, "totem.token", deleted_key, TOKEN_TIMEOUT, 0);
235 
236  if (totem_config->interface_count > 0 && totem_config->interfaces[0].member_count > 2) {
237  u32 = TOKEN_COEFFICIENT;
238  icmap_get_uint32("totem.token_coefficient", &u32);
239  totem_config->token_timeout += (totem_config->interfaces[0].member_count - 2) * u32;
240 
241  /*
242  * Store totem_config value to cmap runtime section
243  */
244  icmap_set_uint32("runtime.config.totem.token", totem_config->token_timeout);
245  }
246 
247  totem_volatile_config_set_value(totem_config, "totem.max_network_delay", deleted_key, MAX_NETWORK_DELAY, 0);
248 
249  totem_volatile_config_set_value(totem_config, "totem.window_size", deleted_key, WINDOW_SIZE, 0);
250 
251  totem_volatile_config_set_value(totem_config, "totem.max_messages", deleted_key, MAX_MESSAGES, 0);
252 
253  totem_volatile_config_set_value(totem_config, "totem.miss_count_const", deleted_key, MISS_COUNT_CONST, 0);
254 
255  totem_volatile_config_set_value(totem_config, "totem.token_retransmit", deleted_key,
256  (int)(totem_config->token_timeout / (totem_config->token_retransmits_before_loss_const + 0.2)), 0);
257 
258  totem_volatile_config_set_value(totem_config, "totem.hold", deleted_key,
259  (int)(totem_config->token_retransmit_timeout * 0.8 - (1000/HZ)), 0);
260 
261  totem_volatile_config_set_value(totem_config, "totem.join", deleted_key, JOIN_TIMEOUT, 0);
262 
263  totem_volatile_config_set_value(totem_config, "totem.consensus", deleted_key,
264  (int)(float)(1.2 * totem_config->token_timeout), 0);
265 
266  totem_volatile_config_set_value(totem_config, "totem.merge", deleted_key, MERGE_TIMEOUT, 0);
267 
268  totem_volatile_config_set_value(totem_config, "totem.downcheck", deleted_key, DOWNCHECK_TIMEOUT, 0);
269 
270  totem_volatile_config_set_value(totem_config, "totem.fail_recv_const", deleted_key, FAIL_TO_RECV_CONST, 0);
271 
272  totem_volatile_config_set_value(totem_config, "totem.seqno_unchanged_const", deleted_key,
274 
275  totem_volatile_config_set_value(totem_config, "totem.send_join", deleted_key, 0, 1);
276 
277  totem_volatile_config_set_value(totem_config, "totem.rrp_problem_count_timeout", deleted_key,
279 
280  totem_volatile_config_set_value(totem_config, "totem.rrp_problem_count_threshold", deleted_key,
282 
283  totem_volatile_config_set_value(totem_config, "totem.rrp_problem_count_mcast_threshold", deleted_key,
284  totem_config->rrp_problem_count_threshold * 10, 0);
285 
286  totem_volatile_config_set_value(totem_config, "totem.rrp_token_expired_timeout", deleted_key,
287  totem_config->token_retransmit_timeout, 0);
288 
289  totem_volatile_config_set_value(totem_config, "totem.rrp_autorecovery_check_timeout", deleted_key,
291 
292  totem_volatile_config_set_value(totem_config, "totem.heartbeat_failures_allowed", deleted_key, 0, 1);
293 
294  totem_volatile_config_set_boolean_value(totem_config, "totem.block_unlisted_ips", deleted_key,
296 }
297 
298 static int totem_volatile_config_validate (
299  struct totem_config *totem_config,
300  const char **error_string)
301 {
302  static char local_error_reason[512];
303  const char *error_reason = local_error_reason;
304 
305  if (totem_config->max_network_delay < MINIMUM_TIMEOUT) {
306  snprintf (local_error_reason, sizeof(local_error_reason),
307  "The max_network_delay parameter (%d ms) may not be less than (%d ms).",
308  totem_config->max_network_delay, MINIMUM_TIMEOUT);
309  goto parse_error;
310  }
311 
312  if (totem_config->token_timeout < MINIMUM_TIMEOUT) {
313  snprintf (local_error_reason, sizeof(local_error_reason),
314  "The token timeout parameter (%d ms) may not be less than (%d ms).",
315  totem_config->token_timeout, MINIMUM_TIMEOUT);
316  goto parse_error;
317  }
318 
319  if (totem_config->token_retransmit_timeout < MINIMUM_TIMEOUT) {
320  snprintf (local_error_reason, sizeof(local_error_reason),
321  "The token retransmit timeout parameter (%d ms) may not be less than (%d ms).",
323  goto parse_error;
324  }
325 
326  if (totem_config->token_hold_timeout < MINIMUM_TIMEOUT) {
327  snprintf (local_error_reason, sizeof(local_error_reason),
328  "The token hold timeout parameter (%d ms) may not be less than (%d ms).",
329  totem_config->token_hold_timeout, MINIMUM_TIMEOUT);
330  goto parse_error;
331  }
332 
333  if (totem_config->join_timeout < MINIMUM_TIMEOUT) {
334  snprintf (local_error_reason, sizeof(local_error_reason),
335  "The join timeout parameter (%d ms) may not be less than (%d ms).",
336  totem_config->join_timeout, MINIMUM_TIMEOUT);
337  goto parse_error;
338  }
339 
340  if (totem_config->consensus_timeout < MINIMUM_TIMEOUT) {
341  snprintf (local_error_reason, sizeof(local_error_reason),
342  "The consensus timeout parameter (%d ms) may not be less than (%d ms).",
343  totem_config->consensus_timeout, MINIMUM_TIMEOUT);
344  goto parse_error;
345  }
346 
347  if (totem_config->consensus_timeout < totem_config->join_timeout) {
348  snprintf (local_error_reason, sizeof(local_error_reason),
349  "The consensus timeout parameter (%d ms) may not be less than join timeout (%d ms).",
350  totem_config->consensus_timeout, totem_config->join_timeout);
351  goto parse_error;
352  }
353 
354  if (totem_config->merge_timeout < MINIMUM_TIMEOUT) {
355  snprintf (local_error_reason, sizeof(local_error_reason),
356  "The merge timeout parameter (%d ms) may not be less than (%d ms).",
357  totem_config->merge_timeout, MINIMUM_TIMEOUT);
358  goto parse_error;
359  }
360 
361  if (totem_config->downcheck_timeout < MINIMUM_TIMEOUT) {
362  snprintf (local_error_reason, sizeof(local_error_reason),
363  "The downcheck timeout parameter (%d ms) may not be less than (%d ms).",
364  totem_config->downcheck_timeout, MINIMUM_TIMEOUT);
365  goto parse_error;
366  }
367 
368  if (totem_config->rrp_problem_count_timeout < MINIMUM_TIMEOUT) {
369  snprintf (local_error_reason, sizeof(local_error_reason),
370  "The RRP problem count timeout parameter (%d ms) may not be less than (%d ms).",
372  goto parse_error;
373  }
374 
376  snprintf (local_error_reason, sizeof(local_error_reason),
377  "The RRP problem count threshold (%d problem count) may not be less than (%d problem count).",
379  goto parse_error;
380  }
382  snprintf (local_error_reason, sizeof(local_error_reason),
383  "The RRP multicast problem count threshold (%d problem count) may not be less than (%d problem count).",
385  goto parse_error;
386  }
387 
388  if (totem_config->rrp_token_expired_timeout < MINIMUM_TIMEOUT) {
389  snprintf (local_error_reason, sizeof(local_error_reason),
390  "The RRP token expired timeout parameter (%d ms) may not be less than (%d ms).",
392  goto parse_error;
393  }
394 
395  return 0;
396 
397 parse_error:
398  snprintf (error_string_response, sizeof(error_string_response),
399  "parse error in config: %s\n", error_reason);
400  *error_string = error_string_response;
401  return (-1);
402 
403 }
404 
405 static int totem_get_crypto(struct totem_config *totem_config)
406 {
407  char *str;
408  const char *tmp_cipher;
409  const char *tmp_hash;
410 
411  tmp_hash = "sha1";
412  tmp_cipher = "aes256";
413 
414  if (icmap_get_string("totem.secauth", &str) == CS_OK) {
415  if (strcmp (str, "off") == 0) {
416  tmp_hash = "none";
417  tmp_cipher = "none";
418  }
419  free(str);
420  }
421 
422  if (icmap_get_string("totem.crypto_cipher", &str) == CS_OK) {
423  if (strcmp(str, "none") == 0) {
424  tmp_cipher = "none";
425  }
426  if (strcmp(str, "aes256") == 0) {
427  tmp_cipher = "aes256";
428  }
429  if (strcmp(str, "aes192") == 0) {
430  tmp_cipher = "aes192";
431  }
432  if (strcmp(str, "aes128") == 0) {
433  tmp_cipher = "aes128";
434  }
435  if (strcmp(str, "3des") == 0) {
436  tmp_cipher = "3des";
437  }
438  free(str);
439  }
440 
441  if (icmap_get_string("totem.crypto_hash", &str) == CS_OK) {
442  if (strcmp(str, "none") == 0) {
443  tmp_hash = "none";
444  }
445  if (strcmp(str, "md5") == 0) {
446  tmp_hash = "md5";
447  }
448  if (strcmp(str, "sha1") == 0) {
449  tmp_hash = "sha1";
450  }
451  if (strcmp(str, "sha256") == 0) {
452  tmp_hash = "sha256";
453  }
454  if (strcmp(str, "sha384") == 0) {
455  tmp_hash = "sha384";
456  }
457  if (strcmp(str, "sha512") == 0) {
458  tmp_hash = "sha512";
459  }
460  free(str);
461  }
462 
463  if ((strcmp(tmp_cipher, "none") != 0) &&
464  (strcmp(tmp_hash, "none") == 0)) {
465  return -1;
466  }
467 
468  free(totem_config->crypto_cipher_type);
469  free(totem_config->crypto_hash_type);
470 
471  totem_config->crypto_cipher_type = strdup(tmp_cipher);
472  totem_config->crypto_hash_type = strdup(tmp_hash);
473 
474  return 0;
475 }
476 
477 static int totem_config_get_ip_version(void)
478 {
479  int res;
480  char *str;
481 
482  res = AF_INET;
483  if (icmap_get_string("totem.ip_version", &str) == CS_OK) {
484  if (strcmp(str, "ipv4") == 0) {
485  res = AF_INET;
486  }
487  if (strcmp(str, "ipv6") == 0) {
488  res = AF_INET6;
489  }
490  free(str);
491  }
492 
493  return (res);
494 }
495 
496 static uint16_t generate_cluster_id (const char *cluster_name)
497 {
498  int i;
499  int value = 0;
500 
501  for (i = 0; i < strlen(cluster_name); i++) {
502  value <<= 1;
503  value += cluster_name[i];
504  }
505 
506  return (value & 0xFFFF);
507 }
508 
509 static int get_cluster_mcast_addr (
510  const char *cluster_name,
511  unsigned int ringnumber,
512  int ip_version,
513  struct totem_ip_address *res)
514 {
515  uint16_t clusterid;
516  char addr[INET6_ADDRSTRLEN + 1];
517  int err;
518 
519  if (cluster_name == NULL) {
520  return (-1);
521  }
522 
523  clusterid = generate_cluster_id(cluster_name) + ringnumber;
524  memset (res, 0, sizeof(*res));
525 
526  switch (ip_version) {
527  case AF_INET:
528  snprintf(addr, sizeof(addr), "239.192.%d.%d", clusterid >> 8, clusterid % 0xFF);
529  break;
530  case AF_INET6:
531  snprintf(addr, sizeof(addr), "ff15::%x", clusterid);
532  break;
533  default:
534  /*
535  * Unknown family
536  */
537  return (-1);
538  }
539 
540  err = totemip_parse (res, addr, ip_version);
541 
542  return (err);
543 }
544 
545 static unsigned int generate_nodeid_for_duplicate_test(
546  struct totem_config *totem_config,
547  char *addr)
548 {
549  unsigned int nodeid;
550  struct totem_ip_address totemip;
551 
552  /* AF_INET hard-coded here because auto-generated nodeids
553  are only for IPv4 */
554  if (totemip_parse(&totemip, addr, AF_INET) != 0)
555  return -1;
556 
557  memcpy (&nodeid, &totemip.addr, sizeof (unsigned int));
558 
559 #if __BYTE_ORDER == __LITTLE_ENDIAN
560  nodeid = swab32 (nodeid);
561 #endif
562 
563  if (totem_config->clear_node_high_bit) {
564  nodeid &= 0x7FFFFFFF;
565  }
566  return nodeid;
567 }
568 
569 static int check_for_duplicate_nodeids(
570  struct totem_config *totem_config,
571  const char **error_string)
572 {
573  icmap_iter_t iter;
574  icmap_iter_t subiter;
575  const char *iter_key;
576  int res = 0;
577  int retval = 0;
578  char tmp_key[ICMAP_KEYNAME_MAXLEN];
579  char *ring0_addr=NULL;
580  char *ring0_addr1=NULL;
581  unsigned int node_pos;
582  unsigned int node_pos1;
583  unsigned int nodeid;
584  unsigned int nodeid1;
585  int autogenerated;
586 
587  iter = icmap_iter_init("nodelist.node.");
588  while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
589  res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos, tmp_key);
590  if (res != 2) {
591  continue;
592  }
593 
594  if (strcmp(tmp_key, "ring0_addr") != 0) {
595  continue;
596  }
597 
598  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.nodeid", node_pos);
599  autogenerated = 0;
600  if (icmap_get_uint32(tmp_key, &nodeid) != CS_OK) {
601 
602  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.ring0_addr", node_pos);
603  if (icmap_get_string(tmp_key, &ring0_addr) != CS_OK) {
604  continue;
605  }
606 
607  /* Generate nodeid so we can check that auto-generated nodeids don't clash either */
608  nodeid = generate_nodeid_for_duplicate_test(totem_config, ring0_addr);
609  if (nodeid == -1) {
610  continue;
611  }
612  autogenerated = 1;
613  }
614 
615  node_pos1 = 0;
616  subiter = icmap_iter_init("nodelist.node.");
617  while (((iter_key = icmap_iter_next(subiter, NULL, NULL)) != NULL) && (node_pos1 < node_pos)) {
618  res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos1, tmp_key);
619  if ((res != 2) || (node_pos1 >= node_pos)) {
620  continue;
621  }
622 
623  if (strcmp(tmp_key, "ring0_addr") != 0) {
624  continue;
625  }
626 
627  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.nodeid", node_pos1);
628  if (icmap_get_uint32(tmp_key, &nodeid1) != CS_OK) {
629 
630  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.ring0_addr", node_pos1);
631  if (icmap_get_string(tmp_key, &ring0_addr1) != CS_OK) {
632  continue;
633  }
634  nodeid1 = generate_nodeid_for_duplicate_test(totem_config, ring0_addr1);
635  if (nodeid1 == -1) {
636  continue;
637  }
638  }
639 
640  if (nodeid == nodeid1) {
641  retval = -1;
642  snprintf (error_string_response, sizeof(error_string_response),
643  "Nodeid %u%s%s%s appears twice in corosync.conf", nodeid,
644  autogenerated?"(autogenerated from ":"",
645  autogenerated?ring0_addr:"",
646  autogenerated?")":"");
647  log_printf (LOGSYS_LEVEL_ERROR, error_string_response);
648  *error_string = error_string_response;
649  break;
650  }
651  }
652  icmap_iter_finalize(subiter);
653  }
654  icmap_iter_finalize(iter);
655  return retval;
656 }
657 
658 
659 static int find_local_node_in_nodelist(struct totem_config *totem_config)
660 {
661  icmap_iter_t iter;
662  const char *iter_key;
663  int res = 0;
664  unsigned int node_pos;
665  int local_node_pos = -1;
666  struct totem_ip_address bind_addr;
667  int interface_up, interface_num;
668  char tmp_key[ICMAP_KEYNAME_MAXLEN];
669  char *node_addr_str;
670  struct totem_ip_address node_addr;
671 
672  res = totemip_iface_check(&totem_config->interfaces[0].bindnet,
673  &bind_addr, &interface_up, &interface_num,
674  totem_config->clear_node_high_bit);
675  if (res == -1) {
676  return (-1);
677  }
678 
679  iter = icmap_iter_init("nodelist.node.");
680  while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
681  res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos, tmp_key);
682  if (res != 2) {
683  continue;
684  }
685 
686  if (strcmp(tmp_key, "ring0_addr") != 0) {
687  continue;
688  }
689 
690  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.ring0_addr", node_pos);
691  if (icmap_get_string(tmp_key, &node_addr_str) != CS_OK) {
692  continue;
693  }
694 
695  res = totemip_parse (&node_addr, node_addr_str, totem_config->ip_version);
696  free(node_addr_str);
697  if (res == -1) {
698  continue ;
699  }
700 
701  if (totemip_equal(&bind_addr, &node_addr)) {
702  local_node_pos = node_pos;
703  }
704  }
705  icmap_iter_finalize(iter);
706 
707  return (local_node_pos);
708 }
709 
710 /*
711  * Compute difference between two set of totem interface arrays. set1 and set2
712  * are changed so for same ring, ip existing in both set1 and set2 are cleared
713  * (set to 0), and ips which are only in set1 or set2 remains untouched.
714  * totempg_node_add/remove is called.
715  */
716 static void compute_interfaces_diff(int interface_count,
717  struct totem_interface *set1,
718  struct totem_interface *set2)
719 {
720  int ring_no, set1_pos, set2_pos;
721  struct totem_ip_address empty_ip_address;
722 
723  memset(&empty_ip_address, 0, sizeof(empty_ip_address));
724 
725  for (ring_no = 0; ring_no < interface_count; ring_no++) {
726  for (set1_pos = 0; set1_pos < set1[ring_no].member_count; set1_pos++) {
727  for (set2_pos = 0; set2_pos < set2[ring_no].member_count; set2_pos++) {
728  /*
729  * For current ring_no remove all set1 items existing
730  * in set2
731  */
732  if (memcmp(&set1[ring_no].member_list[set1_pos],
733  &set2[ring_no].member_list[set2_pos],
734  sizeof(struct totem_ip_address)) == 0) {
735  memset(&set1[ring_no].member_list[set1_pos], 0,
736  sizeof(struct totem_ip_address));
737  memset(&set2[ring_no].member_list[set2_pos], 0,
738  sizeof(struct totem_ip_address));
739  }
740  }
741  }
742  }
743 
744  for (ring_no = 0; ring_no < interface_count; ring_no++) {
745  for (set1_pos = 0; set1_pos < set1[ring_no].member_count; set1_pos++) {
746  /*
747  * All items which remained in set1 doesn't exists in set2 any longer so
748  * node has to be removed.
749  */
750  if (memcmp(&set1[ring_no].member_list[set1_pos], &empty_ip_address, sizeof(empty_ip_address)) != 0) {
752  "removing dynamic member %s for ring %u",
753  totemip_print(&set1[ring_no].member_list[set1_pos]),
754  ring_no);
755 
756  totempg_member_remove(&set1[ring_no].member_list[set1_pos], ring_no);
757  }
758  }
759  for (set2_pos = 0; set2_pos < set2[ring_no].member_count; set2_pos++) {
760  /*
761  * All items which remained in set2 doesn't existed in set1 so this is no node
762  * and has to be added.
763  */
764  if (memcmp(&set2[ring_no].member_list[set2_pos], &empty_ip_address, sizeof(empty_ip_address)) != 0) {
766  "adding dynamic member %s for ring %u",
767  totemip_print(&set2[ring_no].member_list[set2_pos]),
768  ring_no);
769 
770  totempg_member_add(&set2[ring_no].member_list[set2_pos], ring_no);
771  }
772  }
773  }
774 }
775 
776 static void put_nodelist_members_to_config(struct totem_config *totem_config, int reload)
777 {
778  icmap_iter_t iter, iter2;
779  const char *iter_key, *iter_key2;
780  int res = 0;
781  unsigned int node_pos;
782  char tmp_key[ICMAP_KEYNAME_MAXLEN];
783  char tmp_key2[ICMAP_KEYNAME_MAXLEN];
784  char *node_addr_str;
785  int member_count;
786  unsigned int ringnumber = 0;
787  int i, j;
788  struct totem_interface *orig_interfaces = NULL;
789  struct totem_interface *new_interfaces = NULL;
790 
791  if (reload) {
792  /*
793  * We need to compute diff only for reload. Also for initial configuration
794  * not all totem structures are initialized so corosync will crash during
795  * member_add/remove
796  */
797  orig_interfaces = malloc (sizeof (struct totem_interface) * INTERFACE_MAX);
798  assert(orig_interfaces != NULL);
799  new_interfaces = malloc (sizeof (struct totem_interface) * INTERFACE_MAX);
800  assert(new_interfaces != NULL);
801 
802  memcpy(orig_interfaces, totem_config->interfaces, sizeof (struct totem_interface) * INTERFACE_MAX);
803  }
804 
805  /* Clear out nodelist so we can put the new one in if needed */
806  for (i = 0; i < totem_config->interface_count; i++) {
807  for (j = 0; j < PROCESSOR_COUNT_MAX; j++) {
808  memset(&totem_config->interfaces[i].member_list[j], 0, sizeof(struct totem_ip_address));
809  }
810  totem_config->interfaces[i].member_count = 0;
811  }
812 
813  iter = icmap_iter_init("nodelist.node.");
814  while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
815  res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos, tmp_key);
816  if (res != 2) {
817  continue;
818  }
819 
820  if (strcmp(tmp_key, "ring0_addr") != 0) {
821  continue;
822  }
823 
824  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.", node_pos);
825  iter2 = icmap_iter_init(tmp_key);
826  while ((iter_key2 = icmap_iter_next(iter2, NULL, NULL)) != NULL) {
827  res = sscanf(iter_key2, "nodelist.node.%u.ring%u%s", &node_pos, &ringnumber, tmp_key2);
828  if (res != 3 || strcmp(tmp_key2, "_addr") != 0) {
829  continue;
830  }
831 
832  if (icmap_get_string(iter_key2, &node_addr_str) != CS_OK) {
833  continue;
834  }
835 
836  member_count = totem_config->interfaces[ringnumber].member_count;
837 
838  res = totemip_parse(&totem_config->interfaces[ringnumber].member_list[member_count],
839  node_addr_str, totem_config->ip_version);
840  if (res != -1) {
841  totem_config->interfaces[ringnumber].member_count++;
842  }
843  free(node_addr_str);
844  }
845 
846  icmap_iter_finalize(iter2);
847  }
848 
849  icmap_iter_finalize(iter);
850 
851  if (reload) {
852  memcpy(new_interfaces, totem_config->interfaces, sizeof (struct totem_interface) * INTERFACE_MAX);
853 
854  compute_interfaces_diff(totem_config->interface_count, orig_interfaces, new_interfaces);
855 
856  free(new_interfaces);
857  free(orig_interfaces);
858  }
859 }
860 
861 static void nodelist_dynamic_notify(
862  int32_t event,
863  const char *key_name,
864  struct icmap_notify_value new_val,
865  struct icmap_notify_value old_val,
866  void *user_data)
867 {
868  int res;
869  unsigned int ring_no;
870  unsigned int member_no;
871  char tmp_str[ICMAP_KEYNAME_MAXLEN];
872  uint8_t reloading;
873  struct totem_config *totem_config = (struct totem_config *)user_data;
874 
875  /*
876  * If a full reload is in progress then don't do anything until it's done and
877  * can reconfigure it all atomically
878  */
879  if (icmap_get_uint8("config.totemconfig_reload_in_progress", &reloading) == CS_OK && reloading) {
880  return ;
881  }
882 
883  res = sscanf(key_name, "nodelist.node.%u.ring%u%s", &member_no, &ring_no, tmp_str);
884  if (res != 3)
885  return ;
886 
887  if (strcmp(tmp_str, "_addr") != 0) {
888  return;
889  }
890 
891  put_nodelist_members_to_config(totem_config, 1);
892 }
893 
894 
895 /*
896  * Tries to find node (node_pos) in config nodelist which address matches any
897  * local interface. Address can be stored in ring0_addr or if ipaddr_key_prefix is not NULL
898  * key with prefix ipaddr_key is used (there can be multiuple of them)
899  * This function differs * from find_local_node_in_nodelist because it doesn't need bindnetaddr,
900  * but doesn't work when bind addr is network address (so IP must be exact
901  * match).
902  *
903  * Returns 1 on success (address was found, node_pos is then correctly set) or 0 on failure.
904  */
905 int totem_config_find_local_addr_in_nodelist(const char *ipaddr_key_prefix, unsigned int *node_pos)
906 {
907  struct list_head addrs;
908  struct totem_ip_if_address *if_addr;
909  icmap_iter_t iter, iter2;
910  const char *iter_key, *iter_key2;
911  struct list_head *list;
912  const char *ipaddr_key;
913  int ip_version;
914  struct totem_ip_address node_addr;
915  char *node_addr_str;
916  int node_found = 0;
917  int res = 0;
918  char tmp_key[ICMAP_KEYNAME_MAXLEN];
919 
920  if (totemip_getifaddrs(&addrs) == -1) {
921  return 0;
922  }
923 
924  ip_version = totem_config_get_ip_version();
925 
926  iter = icmap_iter_init("nodelist.node.");
927 
928  while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
929  res = sscanf(iter_key, "nodelist.node.%u.%s", node_pos, tmp_key);
930  if (res != 2) {
931  continue;
932  }
933 
934  if (strcmp(tmp_key, "ring0_addr") != 0) {
935  continue;
936  }
937 
938  if (icmap_get_string(iter_key, &node_addr_str) != CS_OK) {
939  continue ;
940  }
941 
942  free(node_addr_str);
943 
944  /*
945  * ring0_addr found -> let's iterate thru ipaddr_key_prefix
946  */
947  snprintf(tmp_key, sizeof(tmp_key), "nodelist.node.%u.%s", *node_pos,
948  (ipaddr_key_prefix != NULL ? ipaddr_key_prefix : "ring0_addr"));
949 
950  iter2 = icmap_iter_init(tmp_key);
951  while ((iter_key2 = icmap_iter_next(iter2, NULL, NULL)) != NULL) {
952  /*
953  * ring0_addr must be exact match, not prefix
954  */
955  ipaddr_key = (ipaddr_key_prefix != NULL ? iter_key2 : tmp_key);
956  if (icmap_get_string(ipaddr_key, &node_addr_str) != CS_OK) {
957  continue ;
958  }
959 
960  if (totemip_parse(&node_addr, node_addr_str, ip_version) == -1) {
961  free(node_addr_str);
962  continue ;
963  }
964  free(node_addr_str);
965 
966  /*
967  * Try to match ip with if_addrs
968  */
969  node_found = 0;
970  for (list = addrs.next; list != &addrs; list = list->next) {
971  if_addr = list_entry(list, struct totem_ip_if_address, list);
972 
973  if (totemip_equal(&node_addr, &if_addr->ip_addr)) {
974  node_found = 1;
975  break;
976  }
977  }
978 
979  if (node_found) {
980  break ;
981  }
982  }
983 
984  icmap_iter_finalize(iter2);
985 
986  if (node_found) {
987  break ;
988  }
989  }
990 
991  icmap_iter_finalize(iter);
992  totemip_freeifaddrs(&addrs);
993 
994  return (node_found);
995 }
996 
997 static void config_convert_nodelist_to_interface(struct totem_config *totem_config)
998 {
999  int res = 0;
1000  unsigned int node_pos;
1001  char tmp_key[ICMAP_KEYNAME_MAXLEN];
1002  char tmp_key2[ICMAP_KEYNAME_MAXLEN];
1003  char *node_addr_str;
1004  unsigned int ringnumber = 0;
1005  icmap_iter_t iter;
1006  const char *iter_key;
1007 
1008  if (totem_config_find_local_addr_in_nodelist(NULL, &node_pos)) {
1009  /*
1010  * We found node, so create interface section
1011  */
1012  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.", node_pos);
1013  iter = icmap_iter_init(tmp_key);
1014  while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
1015  res = sscanf(iter_key, "nodelist.node.%u.ring%u%s", &node_pos, &ringnumber, tmp_key2);
1016  if (res != 3 || strcmp(tmp_key2, "_addr") != 0) {
1017  continue ;
1018  }
1019 
1020  if (icmap_get_string(iter_key, &node_addr_str) != CS_OK) {
1021  continue;
1022  }
1023 
1024  snprintf(tmp_key2, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr", ringnumber);
1025  icmap_set_string(tmp_key2, node_addr_str);
1026  free(node_addr_str);
1027  }
1028  icmap_iter_finalize(iter);
1029  }
1030 }
1031 
1032 
1033 extern int totem_config_read (
1034  struct totem_config *totem_config,
1035  const char **error_string,
1036  uint64_t *warnings)
1037 {
1038  int res = 0;
1039  char *str, *ring0_addr_str;
1040  unsigned int ringnumber = 0;
1041  int member_count = 0;
1042  icmap_iter_t iter, member_iter;
1043  const char *iter_key;
1044  const char *member_iter_key;
1045  char ringnumber_key[ICMAP_KEYNAME_MAXLEN];
1046  char tmp_key[ICMAP_KEYNAME_MAXLEN];
1047  uint8_t u8;
1048  uint16_t u16;
1049  char *cluster_name = NULL;
1050  int i;
1051  int local_node_pos;
1052  int nodeid_set;
1053 
1054  *warnings = 0;
1055 
1056  memset (totem_config, 0, sizeof (struct totem_config));
1057  totem_config->interfaces = malloc (sizeof (struct totem_interface) * INTERFACE_MAX);
1058  if (totem_config->interfaces == 0) {
1059  *error_string = "Out of memory trying to allocate ethernet interface storage area";
1060  return -1;
1061  }
1062 
1063  memset (totem_config->interfaces, 0,
1064  sizeof (struct totem_interface) * INTERFACE_MAX);
1065 
1066  strcpy (totem_config->rrp_mode, "none");
1067 
1068  icmap_get_uint32("totem.version", (uint32_t *)&totem_config->version);
1069 
1070  if (totem_get_crypto(totem_config) != 0) {
1071  *error_string = "crypto_cipher requires crypto_hash with value other than none";
1072  return -1;
1073  }
1074 
1075  if (icmap_get_string("totem.rrp_mode", &str) == CS_OK) {
1076  if (strlen(str) >= TOTEM_RRP_MODE_BYTES) {
1077  *error_string = "totem.rrp_mode is too long";
1078  free(str);
1079 
1080  return -1;
1081  }
1082  strcpy (totem_config->rrp_mode, str);
1083  free(str);
1084  }
1085 
1086  icmap_get_uint32("totem.nodeid", &totem_config->node_id);
1087 
1088  totem_config->clear_node_high_bit = 0;
1089  if (icmap_get_string("totem.clear_node_high_bit", &str) == CS_OK) {
1090  if (strcmp (str, "yes") == 0) {
1091  totem_config->clear_node_high_bit = 1;
1092  }
1093  free(str);
1094  }
1095 
1096  icmap_get_uint32("totem.threads", &totem_config->threads);
1097 
1098  icmap_get_uint32("totem.netmtu", &totem_config->net_mtu);
1099 
1100  if (icmap_get_string("totem.cluster_name", &cluster_name) != CS_OK) {
1101  cluster_name = NULL;
1102  }
1103 
1104  totem_config->ip_version = totem_config_get_ip_version();
1105 
1106  if (icmap_get_string("totem.interface.0.bindnetaddr", &str) != CS_OK) {
1107  /*
1108  * We were not able to find ring 0 bindnet addr. Try to use nodelist informations
1109  */
1110  config_convert_nodelist_to_interface(totem_config);
1111  } else {
1112  if (icmap_get_string("nodelist.node.0.ring0_addr", &ring0_addr_str) == CS_OK) {
1113  /*
1114  * Both bindnetaddr and ring0_addr are set.
1115  * Log warning information, and use nodelist instead
1116  */
1118 
1119  config_convert_nodelist_to_interface(totem_config);
1120 
1121  free(ring0_addr_str);
1122  }
1123 
1124  free(str);
1125  }
1126 
1127  /*
1128  * Broadcast option is global but set in interface section,
1129  * so reset before processing interfaces.
1130  */
1131  totem_config->broadcast_use = 0;
1132 
1133  iter = icmap_iter_init("totem.interface.");
1134  while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
1135  res = sscanf(iter_key, "totem.interface.%[^.].%s", ringnumber_key, tmp_key);
1136  if (res != 2) {
1137  continue;
1138  }
1139 
1140  if (strcmp(tmp_key, "bindnetaddr") != 0) {
1141  continue;
1142  }
1143 
1144  member_count = 0;
1145 
1146  ringnumber = atoi(ringnumber_key);
1147 
1148  if (ringnumber >= INTERFACE_MAX) {
1149  free(cluster_name);
1150 
1151  snprintf (error_string_response, sizeof(error_string_response),
1152  "parse error in config: interface ring number %u is bigger than allowed maximum %u\n",
1153  ringnumber, INTERFACE_MAX - 1);
1154 
1155  *error_string = error_string_response;
1156  return -1;
1157  }
1158 
1159  /*
1160  * Get the bind net address
1161  */
1162  if (icmap_get_string(iter_key, &str) == CS_OK) {
1163  res = totemip_parse (&totem_config->interfaces[ringnumber].bindnet, str,
1164  totem_config->ip_version);
1165  free(str);
1166  }
1167 
1168  /*
1169  * Get interface multicast address
1170  */
1171  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr", ringnumber);
1172  if (icmap_get_string(tmp_key, &str) == CS_OK) {
1173  res = totemip_parse (&totem_config->interfaces[ringnumber].mcast_addr, str, totem_config->ip_version);
1174  free(str);
1175  } else {
1176  /*
1177  * User not specified address -> autogenerate one from cluster_name key
1178  * (if available). Return code is intentionally ignored, because
1179  * udpu doesn't need mcastaddr and validity of mcastaddr for udp is
1180  * checked later anyway.
1181  */
1182  (void)get_cluster_mcast_addr (cluster_name,
1183  ringnumber,
1184  totem_config->ip_version,
1185  &totem_config->interfaces[ringnumber].mcast_addr);
1186  }
1187 
1188  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast", ringnumber);
1189  if (icmap_get_string(tmp_key, &str) == CS_OK) {
1190  if (strcmp (str, "yes") == 0) {
1191  totem_config->broadcast_use = 1;
1192  }
1193  free(str);
1194  }
1195 
1196  /*
1197  * Get mcast port
1198  */
1199  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport", ringnumber);
1200  if (icmap_get_uint16(tmp_key, &totem_config->interfaces[ringnumber].ip_port) != CS_OK) {
1201  if (totem_config->broadcast_use) {
1202  totem_config->interfaces[ringnumber].ip_port = DEFAULT_PORT + (2 * ringnumber);
1203  } else {
1204  totem_config->interfaces[ringnumber].ip_port = DEFAULT_PORT;
1205  }
1206  }
1207 
1208  /*
1209  * Get the TTL
1210  */
1211  totem_config->interfaces[ringnumber].ttl = 1;
1212 
1213  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl", ringnumber);
1214 
1215  if (icmap_get_uint8(tmp_key, &u8) == CS_OK) {
1216  totem_config->interfaces[ringnumber].ttl = u8;
1217  }
1218 
1219  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.", ringnumber);
1220  member_iter = icmap_iter_init(tmp_key);
1221  while ((member_iter_key = icmap_iter_next(member_iter, NULL, NULL)) != NULL) {
1222  if (member_count == 0) {
1223  if (icmap_get_string("nodelist.node.0.ring0_addr", &str) == CS_OK) {
1224  free(str);
1226  break;
1227  } else {
1229  }
1230  }
1231 
1232  if (icmap_get_string(member_iter_key, &str) == CS_OK) {
1233  res = totemip_parse (&totem_config->interfaces[ringnumber].member_list[member_count++],
1234  str, totem_config->ip_version);
1235  }
1236  }
1237  icmap_iter_finalize(member_iter);
1238 
1239  totem_config->interfaces[ringnumber].member_count = member_count;
1240  totem_config->interface_count++;
1241  }
1242  icmap_iter_finalize(iter);
1243 
1244  /*
1245  * Use broadcast is global, so if set, make sure to fill mcast addr correctly
1246  */
1247  if (totem_config->broadcast_use) {
1248  for (ringnumber = 0; ringnumber < totem_config->interface_count; ringnumber++) {
1249  totemip_parse (&totem_config->interfaces[ringnumber].mcast_addr,
1250  "255.255.255.255", 0);
1251  }
1252  }
1253 
1254  /*
1255  * Store automatically generated items back to icmap
1256  */
1257  for (i = 0; i < totem_config->interface_count; i++) {
1258  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr", i);
1259  if (icmap_get_string(tmp_key, &str) == CS_OK) {
1260  free(str);
1261  } else {
1262  str = (char *)totemip_print(&totem_config->interfaces[i].mcast_addr);
1263  icmap_set_string(tmp_key, str);
1264  }
1265 
1266  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport", i);
1267  if (icmap_get_uint16(tmp_key, &u16) != CS_OK) {
1268  icmap_set_uint16(tmp_key, totem_config->interfaces[i].ip_port);
1269  }
1270  }
1271 
1272  totem_config->transport_number = TOTEM_TRANSPORT_UDP;
1273  if (icmap_get_string("totem.transport", &str) == CS_OK) {
1274  if (strcmp (str, "udpu") == 0) {
1275  totem_config->transport_number = TOTEM_TRANSPORT_UDPU;
1276  }
1277 
1278  if (strcmp (str, "iba") == 0) {
1279  totem_config->transport_number = TOTEM_TRANSPORT_RDMA;
1280  }
1281  free(str);
1282  }
1283 
1284  free(cluster_name);
1285 
1286  /*
1287  * Check existence of nodelist
1288  */
1289  if (icmap_get_string("nodelist.node.0.ring0_addr", &str) == CS_OK) {
1290  free(str);
1291  /*
1292  * find local node
1293  */
1294  local_node_pos = find_local_node_in_nodelist(totem_config);
1295  if (local_node_pos != -1) {
1296  icmap_set_uint32("nodelist.local_node_pos", local_node_pos);
1297 
1298  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.nodeid", local_node_pos);
1299 
1300  nodeid_set = (totem_config->node_id != 0);
1301  if (icmap_get_uint32(tmp_key, &totem_config->node_id) == CS_OK && nodeid_set) {
1303  }
1304 
1305  /*
1306  * Make localnode ring0_addr read only, so we can be sure that local
1307  * node never changes. If rebinding to other IP would be in future
1308  * supported, this must be changed and handled properly!
1309  */
1310  snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.ring0_addr", local_node_pos);
1311  icmap_set_ro_access(tmp_key, 0, 1);
1312  icmap_set_ro_access("nodelist.local_node_pos", 0, 1);
1313  }
1314 
1315  put_nodelist_members_to_config(totem_config, 0);
1316  }
1317 
1318  /*
1319  * Get things that might change in the future (and can depend on totem_config->interfaces);
1320  */
1321  totem_volatile_config_read(totem_config, NULL);
1322 
1323  icmap_set_uint8("config.totemconfig_reload_in_progress", 0);
1324 
1325  add_totem_config_notification(totem_config);
1326 
1327  return 0;
1328 }
1329 
1330 
1332  struct totem_config *totem_config,
1333  const char **error_string)
1334 {
1335  static char local_error_reason[512];
1336  char parse_error[512];
1337  const char *error_reason = local_error_reason;
1338  int i, j;
1339  unsigned int interface_max = INTERFACE_MAX;
1340  unsigned int port1, port2;
1341 
1342  if (totem_config->interface_count == 0) {
1343  error_reason = "No interfaces defined";
1344  goto parse_error;
1345  }
1346 
1347  for (i = 0; i < totem_config->interface_count; i++) {
1348  /*
1349  * Some error checking of parsed data to make sure its valid
1350  */
1351 
1352  struct totem_ip_address null_addr;
1353  memset (&null_addr, 0, sizeof (struct totem_ip_address));
1354 
1355  if ((totem_config->transport_number == 0) &&
1356  memcmp (&totem_config->interfaces[i].mcast_addr, &null_addr,
1357  sizeof (struct totem_ip_address)) == 0) {
1358  error_reason = "No multicast address specified";
1359  goto parse_error;
1360  }
1361 
1362  if (totem_config->interfaces[i].ip_port == 0) {
1363  error_reason = "No multicast port specified";
1364  goto parse_error;
1365  }
1366 
1367  if (totem_config->interfaces[i].ttl > 255) {
1368  error_reason = "Invalid TTL (should be 0..255)";
1369  goto parse_error;
1370  }
1371  if (totem_config->transport_number != TOTEM_TRANSPORT_UDP &&
1372  totem_config->interfaces[i].ttl != 1) {
1373  error_reason = "Can only set ttl on multicast transport types";
1374  goto parse_error;
1375  }
1376 
1377  if (totem_config->interfaces[i].mcast_addr.family == AF_INET6 &&
1378  totem_config->node_id == 0) {
1379 
1380  error_reason = "An IPV6 network requires that a node ID be specified.";
1381  goto parse_error;
1382  }
1383 
1384  if (totem_config->broadcast_use == 0 && totem_config->transport_number == TOTEM_TRANSPORT_UDP) {
1385  if (totem_config->interfaces[i].mcast_addr.family != totem_config->interfaces[i].bindnet.family) {
1386  error_reason = "Multicast address family does not match bind address family";
1387  goto parse_error;
1388  }
1389 
1390  if (totemip_is_mcast (&totem_config->interfaces[i].mcast_addr) != 0) {
1391  error_reason = "mcastaddr is not a correct multicast address.";
1392  goto parse_error;
1393  }
1394  }
1395 
1396  if (totem_config->interfaces[0].bindnet.family != totem_config->interfaces[i].bindnet.family) {
1397  error_reason = "Not all bind address belong to the same IP family";
1398  goto parse_error;
1399  }
1400 
1401  /*
1402  * Ensure mcast address/port differs
1403  */
1404  if (totem_config->transport_number == TOTEM_TRANSPORT_UDP) {
1405  for (j = i + 1; j < totem_config->interface_count; j++) {
1406  port1 = totem_config->interfaces[i].ip_port;
1407  port2 = totem_config->interfaces[j].ip_port;
1408  if (totemip_equal(&totem_config->interfaces[i].mcast_addr,
1409  &totem_config->interfaces[j].mcast_addr) &&
1410  (((port1 > port2 ? port1 : port2) - (port1 < port2 ? port1 : port2)) <= 1)) {
1411  error_reason = "Interfaces multicast address/port pair must differ";
1412  goto parse_error;
1413  }
1414  }
1415  }
1416  }
1417 
1418  if (totem_config->version != 2) {
1419  error_reason = "This totem parser can only parse version 2 configurations.";
1420  goto parse_error;
1421  }
1422 
1423  if (totem_volatile_config_validate(totem_config, error_string) == -1) {
1424  return (-1);
1425  }
1426 
1427  if (check_for_duplicate_nodeids(totem_config, error_string) == -1) {
1428  return (-1);
1429  }
1430 
1431  /*
1432  * RRP values validation
1433  */
1434  if (strcmp (totem_config->rrp_mode, "none") &&
1435  strcmp (totem_config->rrp_mode, "active") &&
1436  strcmp (totem_config->rrp_mode, "passive")) {
1437  snprintf (local_error_reason, sizeof(local_error_reason),
1438  "The RRP mode \"%s\" specified is invalid. It must be none, active, or passive.\n", totem_config->rrp_mode);
1439  goto parse_error;
1440  }
1441 
1442  if (strcmp (totem_config->rrp_mode, "none") == 0) {
1443  interface_max = 1;
1444  }
1445  if (interface_max < totem_config->interface_count) {
1446  snprintf (parse_error, sizeof(parse_error),
1447  "%d is too many configured interfaces for the rrp_mode setting %s.",
1448  totem_config->interface_count,
1449  totem_config->rrp_mode);
1450  error_reason = parse_error;
1451  goto parse_error;
1452  }
1453 
1454  if (totem_config->net_mtu == 0) {
1455  totem_config->net_mtu = 1500;
1456  }
1457 
1458  return 0;
1459 
1460 parse_error:
1461  snprintf (error_string_response, sizeof(error_string_response),
1462  "parse error in config: %s\n", error_reason);
1463  *error_string = error_string_response;
1464  return (-1);
1465 
1466 }
1467 
1468 static int read_keyfile (
1469  const char *key_location,
1470  struct totem_config *totem_config,
1471  const char **error_string)
1472 {
1473  int fd;
1474  int res;
1475  ssize_t expected_key_len = sizeof (totem_config->private_key);
1476  int saved_errno;
1477  char error_str[100];
1478  const char *error_ptr;
1479 
1480  fd = open (key_location, O_RDONLY);
1481  if (fd == -1) {
1482  error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
1483  snprintf (error_string_response, sizeof(error_string_response),
1484  "Could not open %s: %s\n",
1485  key_location, error_ptr);
1486  goto parse_error;
1487  }
1488 
1489  res = read (fd, totem_config->private_key, expected_key_len);
1490  saved_errno = errno;
1491  close (fd);
1492 
1493  if (res == -1) {
1494  error_ptr = qb_strerror_r (saved_errno, error_str, sizeof(error_str));
1495  snprintf (error_string_response, sizeof(error_string_response),
1496  "Could not read %s: %s\n",
1497  key_location, error_ptr);
1498  goto parse_error;
1499  }
1500 
1501  totem_config->private_key_len = expected_key_len;
1502 
1503  if (res != expected_key_len) {
1504  snprintf (error_string_response, sizeof(error_string_response),
1505  "Could only read %d bits of 1024 bits from %s.\n",
1506  res * 8, key_location);
1507  goto parse_error;
1508  }
1509 
1510  return 0;
1511 
1512 parse_error:
1513  *error_string = error_string_response;
1514  return (-1);
1515 }
1516 
1518  struct totem_config *totem_config,
1519  const char **error_string)
1520 {
1521  int got_key = 0;
1522  char *key_location = NULL;
1523  int res;
1524  size_t key_len;
1525 
1526  memset (totem_config->private_key, 0, 128);
1527  totem_config->private_key_len = 128;
1528 
1529  if (strcmp(totem_config->crypto_cipher_type, "none") == 0 &&
1530  strcmp(totem_config->crypto_hash_type, "none") == 0) {
1531  return (0);
1532  }
1533 
1534  /* cmap may store the location of the key file */
1535  if (icmap_get_string("totem.keyfile", &key_location) == CS_OK) {
1536  res = read_keyfile(key_location, totem_config, error_string);
1537  free(key_location);
1538  if (res) {
1539  goto key_error;
1540  }
1541  got_key = 1;
1542  } else { /* Or the key itself may be in the cmap */
1543  if (icmap_get("totem.key", NULL, &key_len, NULL) == CS_OK) {
1544  if (key_len > sizeof (totem_config->private_key)) {
1545  sprintf(error_string_response, "key is too long");
1546  goto key_error;
1547  }
1548  if (icmap_get("totem.key", totem_config->private_key, &key_len, NULL) == CS_OK) {
1549  totem_config->private_key_len = key_len;
1550  got_key = 1;
1551  } else {
1552  sprintf(error_string_response, "can't store private key");
1553  goto key_error;
1554  }
1555  }
1556  }
1557 
1558  /* In desperation we read the default filename */
1559  if (!got_key) {
1560  const char *filename = getenv("COROSYNC_TOTEM_AUTHKEY_FILE");
1561  if (!filename)
1562  filename = COROSYSCONFDIR "/authkey";
1563  res = read_keyfile(filename, totem_config, error_string);
1564  if (res)
1565  goto key_error;
1566 
1567  }
1568 
1569  return (0);
1570 
1571 key_error:
1572  *error_string = error_string_response;
1573  return (-1);
1574 
1575 }
1576 
1577 static void debug_dump_totem_config(const struct totem_config *totem_config)
1578 {
1579 
1580  log_printf(LOGSYS_LEVEL_DEBUG, "Token Timeout (%d ms) retransmit timeout (%d ms)",
1581  totem_config->token_timeout, totem_config->token_retransmit_timeout);
1582  log_printf(LOGSYS_LEVEL_DEBUG, "token hold (%d ms) retransmits before loss (%d retrans)",
1583  totem_config->token_hold_timeout, totem_config->token_retransmits_before_loss_const);
1584  log_printf(LOGSYS_LEVEL_DEBUG, "join (%d ms) send_join (%d ms) consensus (%d ms) merge (%d ms)",
1585  totem_config->join_timeout, totem_config->send_join_timeout, totem_config->consensus_timeout,
1586  totem_config->merge_timeout);
1587  log_printf(LOGSYS_LEVEL_DEBUG, "downcheck (%d ms) fail to recv const (%d msgs)",
1588  totem_config->downcheck_timeout, totem_config->fail_to_recv_const);
1590  "seqno unchanged const (%d rotations) Maximum network MTU %d",
1591  totem_config->seqno_unchanged_const, totem_config->net_mtu);
1593  "window size per rotation (%d messages) maximum messages per rotation (%d messages)",
1594  totem_config->window_size, totem_config->max_messages);
1595  log_printf(LOGSYS_LEVEL_DEBUG, "missed count const (%d messages)", totem_config->miss_count_const);
1596  log_printf(LOGSYS_LEVEL_DEBUG, "RRP token expired timeout (%d ms)",
1597  totem_config->rrp_token_expired_timeout);
1598  log_printf(LOGSYS_LEVEL_DEBUG, "RRP token problem counter (%d ms)",
1599  totem_config->rrp_problem_count_timeout);
1600  log_printf(LOGSYS_LEVEL_DEBUG, "RRP threshold (%d problem count)",
1601  totem_config->rrp_problem_count_threshold);
1602  log_printf(LOGSYS_LEVEL_DEBUG, "RRP multicast threshold (%d problem count)",
1603  totem_config->rrp_problem_count_mcast_threshold);
1604  log_printf(LOGSYS_LEVEL_DEBUG, "RRP automatic recovery check timeout (%d ms)",
1605  totem_config->rrp_autorecovery_check_timeout);
1606  log_printf(LOGSYS_LEVEL_DEBUG, "RRP mode set to %s.",
1607  totem_config->rrp_mode);
1608  log_printf(LOGSYS_LEVEL_DEBUG, "heartbeat_failures_allowed (%d)",
1609  totem_config->heartbeat_failures_allowed);
1610  log_printf(LOGSYS_LEVEL_DEBUG, "max_network_delay (%d ms)", totem_config->max_network_delay);
1611 }
1612 
1613 static void totem_change_notify(
1614  int32_t event,
1615  const char *key_name,
1616  struct icmap_notify_value new_val,
1617  struct icmap_notify_value old_val,
1618  void *user_data)
1619 {
1620  struct totem_config *totem_config = (struct totem_config *)user_data;
1621  uint32_t *param;
1622  uint8_t reloading;
1623  const char *deleted_key = NULL;
1624  const char *error_string;
1625 
1626  /*
1627  * If a full reload is in progress then don't do anything until it's done and
1628  * can reconfigure it all atomically
1629  */
1630  if (icmap_get_uint8("config.reload_in_progress", &reloading) == CS_OK && reloading)
1631  return;
1632 
1633  param = totem_get_param_by_name((struct totem_config *)user_data, key_name);
1634  /*
1635  * Process change only if changed key is found in totem_config (-> param is not NULL)
1636  * or for special key token_coefficient. token_coefficient key is not stored in
1637  * totem_config, but it is used for computation of token timeout.
1638  */
1639  if (!param && strcmp(key_name, "totem.token_coefficient") != 0)
1640  return;
1641 
1642  /*
1643  * Values other than UINT32 are not supported, or needed (yet)
1644  */
1645  switch (event) {
1646  case ICMAP_TRACK_DELETE:
1647  deleted_key = key_name;
1648  break;
1649  case ICMAP_TRACK_ADD:
1650  case ICMAP_TRACK_MODIFY:
1651  deleted_key = NULL;
1652  break;
1653  default:
1654  break;
1655  }
1656 
1657  totem_volatile_config_read (totem_config, deleted_key);
1658  log_printf(LOGSYS_LEVEL_DEBUG, "Totem related config key changed. Dumping actual totem config.");
1659  debug_dump_totem_config(totem_config);
1660  if (totem_volatile_config_validate(totem_config, &error_string) == -1) {
1661  log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
1662  /*
1663  * TODO: Consider corosync exit and/or load defaults for volatile
1664  * values. For now, log error seems to be enough
1665  */
1666  }
1667 }
1668 
1669 static void totem_reload_notify(
1670  int32_t event,
1671  const char *key_name,
1672  struct icmap_notify_value new_val,
1673  struct icmap_notify_value old_val,
1674  void *user_data)
1675 {
1676  struct totem_config *totem_config = (struct totem_config *)user_data;
1677  uint32_t local_node_pos;
1678  const char *error_string;
1679 
1680  /* Reload has completed */
1681  if (*(uint8_t *)new_val.data == 0) {
1682  put_nodelist_members_to_config (totem_config, 1);
1683  totem_volatile_config_read (totem_config, NULL);
1684  log_printf(LOGSYS_LEVEL_DEBUG, "Configuration reloaded. Dumping actual totem config.");
1685  debug_dump_totem_config(totem_config);
1686  if (totem_volatile_config_validate(totem_config, &error_string) == -1) {
1687  log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
1688  /*
1689  * TODO: Consider corosync exit and/or load defaults for volatile
1690  * values. For now, log error seems to be enough
1691  */
1692  }
1693 
1694  /* Reinstate the local_node_pos */
1695  local_node_pos = find_local_node_in_nodelist(totem_config);
1696  if (local_node_pos != -1) {
1697  icmap_set_uint32("nodelist.local_node_pos", local_node_pos);
1698  }
1699 
1700  icmap_set_uint8("config.totemconfig_reload_in_progress", 0);
1701  } else {
1702  icmap_set_uint8("config.totemconfig_reload_in_progress", 1);
1703  }
1704 }
1705 
1706 static void add_totem_config_notification(struct totem_config *totem_config)
1707 {
1709 
1710  icmap_track_add("totem.",
1712  totem_change_notify,
1713  totem_config,
1714  &icmap_track);
1715 
1716  icmap_track_add("config.reload_in_progress",
1718  totem_reload_notify,
1719  totem_config,
1720  &icmap_track);
1721 
1722  icmap_track_add("nodelist.node.",
1724  nodelist_dynamic_notify,
1725  (void *)totem_config,
1726  &icmap_track);
1727 }
unsigned int clear_node_high_bit
Definition: totem.h:120
unsigned short family
Definition: coroapi.h:113
#define BLOCK_UNLISTED_IPS
Definition: totemconfig.c:80
const char * icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
Return next item in iterator iter.
Definition: icmap.c:1103
#define RRP_PROBLEM_COUNT_TIMEOUT
Definition: totemconfig.c:76
uint32_t value
struct totem_interface * interfaces
Definition: totem.h:117
unsigned int interface_count
Definition: totem.h:118
struct list_head * next
Definition: list.h:47
The totem_ip_address struct.
Definition: coroapi.h:111
#define DEFAULT_PORT
Definition: totemconfig.c:82
const char * totemip_print(const struct totem_ip_address *addr)
Definition: totemip.c:263
void icmap_iter_finalize(icmap_iter_t iter)
Finalize iterator.
Definition: icmap.c:1124
totem_transport_t transport_number
Definition: totem.h:188
int totemip_parse(struct totem_ip_address *totemip, const char *addr, int family)
Definition: totemip.c:312
#define DOWNCHECK_TIMEOUT
Definition: totemconfig.c:68
unsigned int token_hold_timeout
Definition: totem.h:136
int member_count
Definition: totem.h:73
struct totem_ip_address member_list[PROCESSOR_COUNT_MAX]
Definition: totem.h:74
unsigned char private_key[TOTEM_PRIVATE_KEY_LEN]
Definition: totem.h:125
char rrp_mode[TOTEM_RRP_MODE_BYTES]
Definition: totem.h:164
unsigned char addr[TOTEMIP_ADDRLEN]
Definition: coroapi.h:77
#define COROSYSCONFDIR
Definition: config.h:11
unsigned int rrp_problem_count_timeout
Definition: totem.h:156
cs_error_t icmap_set_string(const char *key_name, const char *value)
Definition: icmap.c:641
int totemip_is_mcast(struct totem_ip_address *addr)
Definition: totemip.c:141
#define RRP_AUTORECOVERY_CHECK_TIMEOUT
Definition: totemconfig.c:79
unsigned int downcheck_timeout
Definition: totem.h:148
unsigned int private_key_len
Definition: totem.h:127
Definition: list.h:46
#define SEQNO_UNCHANGED_CONST
Definition: totemconfig.c:70
unsigned int max_network_delay
Definition: totem.h:174
#define log_printf(level, format, args...)
Definition: logsys.h:320
unsigned int heartbeat_failures_allowed
Definition: totem.h:172
unsigned int send_join_timeout
Definition: totem.h:142
unsigned int window_size
Definition: totem.h:176
unsigned int rrp_problem_count_threshold
Definition: totem.h:158
#define ICMAP_TRACK_DELETE
Definition: icmap.h:77
#define INTERFACE_MAX
Definition: coroapi.h:88
#define RRP_PROBLEM_COUNT_THRESHOLD_MIN
Definition: totemconfig.c:78
#define ICMAP_KEYNAME_MAXLEN
Maximum length of key in icmap.
Definition: icmap.h:48
unsigned int block_unlisted_ips
Definition: totem.h:194
#define MINIMUM_TIMEOUT
Definition: totemconfig.c:71
cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8)
Definition: icmap.c:842
uint16_t ttl
Definition: totem.h:72
unsigned int node_id
Definition: totem.h:119
int totem_config_keyread(struct totem_config *totem_config, const char **error_string)
Definition: totemconfig.c:1517
#define ICMAP_TRACK_MODIFY
Definition: icmap.h:78
unsigned int token_retransmits_before_loss_const
Definition: totem.h:138
int totemip_iface_check(struct totem_ip_address *bindnet, struct totem_ip_address *boundto, int *interface_up, int *interface_num, int mask_high_bit)
Definition: totemip.c:454
#define FAIL_TO_RECV_CONST
Definition: totemconfig.c:69
cs_error_t icmap_set_uint32(const char *key_name, uint32_t value)
Definition: icmap.c:611
unsigned int seqno_unchanged_const
Definition: totem.h:152
void * user_data
Definition: sam.c:127
unsigned int miss_count_const
Definition: totem.h:190
unsigned int join_timeout
Definition: totem.h:140
int totem_config_validate(struct totem_config *totem_config, const char **error_string)
Definition: totemconfig.c:1331
const void * data
Definition: icmap.h:94
#define TOTEM_CONFIG_BINDNETADDR_NODELIST_SET
Definition: totemconfig.h:49
#define ICMAP_TRACK_ADD
Definition: icmap.h:76
int totem_config_find_local_addr_in_nodelist(const char *ipaddr_key_prefix, unsigned int *node_pos)
Definition: totemconfig.c:905
char * crypto_hash_type
Definition: totem.h:186
struct totem_ip_address mcast_addr
Definition: totem.h:70
#define LOGSYS_LEVEL_ERROR
Definition: logsys.h:70
Linked list API.
unsigned int rrp_autorecovery_check_timeout
Definition: totem.h:162
cs_error_t icmap_get(const char *key_name, void *value, size_t *value_len, icmap_value_types_t *type)
Retrieve value of key key_name and store it in user preallocated value pointer.
Definition: icmap.c:739
#define LOGSYS_LEVEL_DEBUG
Definition: logsys.h:74
cs_error_t icmap_set_uint16(const char *key_name, uint16_t value)
Definition: icmap.c:599
unsigned int fail_to_recv_const
Definition: totem.h:150
#define TOKEN_COEFFICIENT
Definition: totemconfig.c:65
int totempg_member_remove(const struct totem_ip_address *member, int ring_no)
Definition: totempg.c:1520
#define TOTEM_CONFIG_WARNING_MEMBERS_DEPRECATED
Definition: totemconfig.h:47
cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32)
Definition: icmap.c:866
uint8_t param
#define TOTEM_CONFIG_WARNING_MEMBERS_IGNORED
Definition: totemconfig.h:46
uint16_t ip_port
Definition: totem.h:71
void totemip_freeifaddrs(struct list_head *addrs)
Definition: totemip.c:438
#define swab32(x)
The swab32 macro.
Definition: swab.h:51
#define WINDOW_SIZE
Definition: totemconfig.c:73
int version
Definition: totem.h:112
unsigned int net_mtu
Definition: totem.h:168
#define MAX_NETWORK_DELAY
Definition: totemconfig.c:72
#define TOKEN_TIMEOUT
Definition: totemconfig.c:64
int ip_version
Definition: totem.h:192
#define MERGE_TIMEOUT
Definition: totemconfig.c:67
unsigned int token_timeout
Definition: totem.h:132
#define JOIN_TIMEOUT
Definition: totemconfig.c:66
unsigned int consensus_timeout
Definition: totem.h:144
int totemip_getifaddrs(struct list_head *addrs)
Definition: totemip.c:370
#define PROCESSOR_COUNT_MAX
Definition: coroapi.h:96
#define TOKEN_RETRANSMITS_BEFORE_LOSS_CONST
Definition: totemconfig.c:63
#define MISS_COUNT_CONST
Definition: totemconfig.c:75
unsigned int broadcast_use
Definition: totem.h:182
unsigned int rrp_problem_count_mcast_threshold
Definition: totem.h:160
cs_error_t icmap_get_string(const char *key_name, char **str)
Shortcut for icmap_get for string type.
Definition: icmap.c:896
#define list_entry(ptr, type, member)
Definition: list.h:84
cs_error_t icmap_set_uint8(const char *key_name, uint8_t value)
Definition: icmap.c:587
unsigned int max_messages
Definition: totem.h:178
char * crypto_cipher_type
Definition: totem.h:184
cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access)
Set read-only access for given key (key_name) or prefix, If prefix is set.
Definition: icmap.c:1233
unsigned int merge_timeout
Definition: totem.h:146
unsigned int token_retransmit_timeout
Definition: totem.h:134
struct totem_ip_address bindnet
Definition: totem.h:68
unsigned int nodeid
Definition: coroapi.h:75
icmap_iter_t icmap_iter_init(const char *prefix)
Initialize iterator with given prefix.
Definition: icmap.c:1097
int totemip_equal(const struct totem_ip_address *addr1, const struct totem_ip_address *addr2)
Definition: totemip.c:71
struct totem_ip_address ip_addr
Definition: totemip.h:72
cs_error_t icmap_get_uint16(const char *key_name, uint16_t *u16)
Definition: icmap.c:854
#define TOTEM_CONFIG_WARNING_TOTEM_NODEID_IGNORED
Definition: totemconfig.h:48
#define MAX_MESSAGES
Definition: totemconfig.c:74
unsigned int rrp_token_expired_timeout
Definition: totem.h:154
unsigned int threads
Definition: totem.h:170
qb_map_iter_t * icmap_iter_t
Itterator type.
Definition: icmap.h:123
Structure passed as new_value and old_value in change callback.
Definition: icmap.h:91
cs_error_t icmap_track_add(const char *key_name, int32_t track_type, icmap_notify_fn_t notify_fn, void *user_data, icmap_track_t *icmap_track)
Add tracking function for given key_name.
Definition: icmap.c:1167
int totem_config_read(struct totem_config *totem_config, const char **error_string, uint64_t *warnings)
Definition: totemconfig.c:1033
#define ICMAP_TRACK_PREFIX
Whole prefix is tracked, instead of key only (so "totem." tracking means that "totem.nodeid", "totem.version", ...
Definition: icmap.h:85
#define RRP_PROBLEM_COUNT_THRESHOLD_DEFAULT
Definition: totemconfig.c:77
int totempg_member_add(const struct totem_ip_address *member, int ring_no)
Definition: totempg.c:1513