corosync  3.0.1
totemudpu.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2005 MontaVista Software, Inc.
3  * Copyright (c) 2006-2018 Red Hat, Inc.
4  *
5  * All rights reserved.
6  *
7  * Author: Steven Dake (sdake@redhat.com)
8 
9  * This software licensed under BSD license, the text of which follows:
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are met:
13  *
14  * - Redistributions of source code must retain the above copyright notice,
15  * this list of conditions and the following disclaimer.
16  * - Redistributions in binary form must reproduce the above copyright notice,
17  * this list of conditions and the following disclaimer in the documentation
18  * and/or other materials provided with the distribution.
19  * - Neither the name of the MontaVista Software, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived from this
21  * software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33  * THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include <config.h>
37 
38 #include <assert.h>
39 #include <sys/mman.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <sys/socket.h>
43 #include <netdb.h>
44 #include <sys/un.h>
45 #include <sys/ioctl.h>
46 #include <sys/param.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
49 #include <unistd.h>
50 #include <fcntl.h>
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <errno.h>
54 #include <sched.h>
55 #include <time.h>
56 #include <sys/time.h>
57 #include <sys/poll.h>
58 #include <sys/uio.h>
59 #include <limits.h>
60 
61 #include <qb/qblist.h>
62 #include <qb/qbdefs.h>
63 #include <qb/qbloop.h>
64 
65 #include <corosync/sq.h>
66 #include <corosync/swab.h>
67 #define LOGSYS_UTILS_ONLY 1
68 #include <corosync/logsys.h>
69 #include "totemudpu.h"
70 
71 #include "util.h"
72 
73 #ifndef MSG_NOSIGNAL
74 #define MSG_NOSIGNAL 0
75 #endif
76 
77 #define MCAST_SOCKET_BUFFER_SIZE (TRANSMITS_ALLOWED * UDP_RECEIVE_FRAME_SIZE_MAX)
78 #define NETIF_STATE_REPORT_UP 1
79 #define NETIF_STATE_REPORT_DOWN 2
80 
81 #define BIND_STATE_UNBOUND 0
82 #define BIND_STATE_REGULAR 1
83 #define BIND_STATE_LOOPBACK 2
84 
86  struct qb_list_head list;
88  int fd;
89  int active;
90 };
91 
94 
96 
98 
100 
101  void *context;
102 
103  void (*totemudpu_deliver_fn) (
104  void *context,
105  const void *msg,
106  unsigned int msg_len,
107  const struct sockaddr_storage *system_from);
108 
109  void (*totemudpu_iface_change_fn) (
110  void *context,
111  const struct totem_ip_address *iface_address,
112  unsigned int ring_no);
113 
114  void (*totemudpu_target_set_completed) (void *context);
115 
116  /*
117  * Function and data used to log messages
118  */
120 
122 
124 
126 
128 
130 
131  void (*totemudpu_log_printf) (
132  int level,
133  int subsys,
134  const char *function,
135  const char *file,
136  int line,
137  const char *format,
138  ...)__attribute__((format(printf, 6, 7)));
139 
140  void *udpu_context;
141 
142  char iov_buffer[UDP_RECEIVE_FRAME_SIZE_MAX];
143 
144  struct iovec totemudpu_iov_recv;
145 
146  struct qb_list_head member_list;
147 
149 
151 
153 
155 
157 
158  struct timeval stats_tv_start;
159 
160  struct totem_ip_address my_id;
161 
162  int firstrun;
163 
164  qb_loop_timer_handle timer_netif_check_timeout;
165 
166  unsigned int my_memb_entries;
167 
169 
171 
172  struct totem_ip_address token_target;
173 
175 
176  int local_loop_sock[2];
177 
178  qb_loop_timer_handle timer_merge_detect_timeout;
179 
181 
183 };
184 
185 struct work_item {
186  const void *msg;
187  unsigned int msg_len;
189 };
190 
191 static int totemudpu_build_sockets (
192  struct totemudpu_instance *instance,
193  struct totem_ip_address *bindnet_address,
194  struct totem_ip_address *bound_to);
195 
196 static int totemudpu_create_sending_socket(
197  void *udpu_context,
198  const struct totem_ip_address *member);
199 
201  void *udpu_context);
202 
203 static void totemudpu_start_merge_detect_timeout(
204  void *udpu_context);
205 
206 static void totemudpu_stop_merge_detect_timeout(
207  void *udpu_context);
208 
209 static void totemudpu_instance_initialize (struct totemudpu_instance *instance)
210 {
211  memset (instance, 0, sizeof (struct totemudpu_instance));
212 
214 
215  instance->totemudpu_iov_recv.iov_base = instance->iov_buffer;
216 
217  instance->totemudpu_iov_recv.iov_len = UDP_RECEIVE_FRAME_SIZE_MAX; //sizeof (instance->iov_buffer);
218 
219  /*
220  * There is always atleast 1 processor
221  */
222  instance->my_memb_entries = 1;
223 
224  qb_list_init (&instance->member_list);
225 }
226 
227 #define log_printf(level, format, args...) \
228 do { \
229  instance->totemudpu_log_printf ( \
230  level, instance->totemudpu_subsys_id, \
231  __FUNCTION__, __FILE__, __LINE__, \
232  (const char *)format, ##args); \
233 } while (0);
234 #define LOGSYS_PERROR(err_num, level, fmt, args...) \
235 do { \
236  char _error_str[LOGSYS_MAX_PERROR_MSG_LEN]; \
237  const char *_error_ptr = qb_strerror_r(err_num, _error_str, sizeof(_error_str)); \
238  instance->totemudpu_log_printf ( \
239  level, instance->totemudpu_subsys_id, \
240  __FUNCTION__, __FILE__, __LINE__, \
241  fmt ": %s (%d)", ##args, _error_ptr, err_num); \
242  } while(0)
243 
245  void *udpu_context,
246  const char *cipher_type,
247  const char *hash_type)
248 {
249 
250  return (0);
251 }
252 
253 
254 static inline void ucast_sendmsg (
255  struct totemudpu_instance *instance,
256  struct totem_ip_address *system_to,
257  const void *msg,
258  unsigned int msg_len)
259 {
260  struct msghdr msg_ucast;
261  int res = 0;
262  struct sockaddr_storage sockaddr;
263  struct iovec iovec;
264  int addrlen;
265  int send_sock;
266 
267  iovec.iov_base = (void *)msg;
268  iovec.iov_len = msg_len;
269 
270  /*
271  * Build unicast message
272  */
274  instance->totem_interface->ip_port, &sockaddr, &addrlen);
275  memset(&msg_ucast, 0, sizeof(msg_ucast));
276  msg_ucast.msg_name = &sockaddr;
277  msg_ucast.msg_namelen = addrlen;
278  msg_ucast.msg_iov = (void *)&iovec;
279  msg_ucast.msg_iovlen = 1;
280 #ifdef HAVE_MSGHDR_CONTROL
281  msg_ucast.msg_control = 0;
282 #endif
283 #ifdef HAVE_MSGHDR_CONTROLLEN
284  msg_ucast.msg_controllen = 0;
285 #endif
286 #ifdef HAVE_MSGHDR_FLAGS
287  msg_ucast.msg_flags = 0;
288 #endif
289 #ifdef HAVE_MSGHDR_ACCRIGHTS
290  msg_ucast.msg_accrights = NULL;
291 #endif
292 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
293  msg_ucast.msg_accrightslen = 0;
294 #endif
295 
296  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
297  send_sock = instance->token_socket;
298  } else {
299  send_sock = instance->local_loop_sock[1];
300  msg_ucast.msg_name = NULL;
301  msg_ucast.msg_namelen = 0;
302  }
303 
304 
305  /*
306  * Transmit unicast message
307  * An error here is recovered by totemsrp
308  */
309  res = sendmsg (send_sock, &msg_ucast, MSG_NOSIGNAL);
310  if (res < 0) {
311  LOGSYS_PERROR (errno, instance->totemudpu_log_level_debug,
312  "sendmsg(ucast) failed (non-critical)");
313  }
314 }
315 
316 static inline void mcast_sendmsg (
317  struct totemudpu_instance *instance,
318  const void *msg,
319  unsigned int msg_len,
320  int only_active)
321 {
322  struct msghdr msg_mcast;
323  int res = 0;
324  struct iovec iovec;
325  struct sockaddr_storage sockaddr;
326  int addrlen;
327  struct qb_list_head *list;
328  struct totemudpu_member *member;
329 
330  iovec.iov_base = (void *)msg;
331  iovec.iov_len = msg_len;
332 
333  memset(&msg_mcast, 0, sizeof(msg_mcast));
334  /*
335  * Build multicast message
336  */
337  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
338  qb_list_for_each(list, &(instance->member_list)) {
339  member = qb_list_entry (list,
340  struct totemudpu_member,
341  list);
342  /*
343  * Do not send multicast message if message is not "flush", member
344  * is inactive and timeout for sending merge message didn't expired.
345  */
346  if (only_active && !member->active && !instance->send_merge_detect_message)
347  continue ;
348 
350  instance->totem_interface->ip_port, &sockaddr, &addrlen);
351  msg_mcast.msg_name = &sockaddr;
352  msg_mcast.msg_namelen = addrlen;
353  msg_mcast.msg_iov = (void *)&iovec;
354  msg_mcast.msg_iovlen = 1;
355  #ifdef HAVE_MSGHDR_CONTROL
356  msg_mcast.msg_control = 0;
357  #endif
358  #ifdef HAVE_MSGHDR_CONTROLLEN
359  msg_mcast.msg_controllen = 0;
360  #endif
361  #ifdef HAVE_MSGHDR_FLAGS
362  msg_mcast.msg_flags = 0;
363  #endif
364  #ifdef HAVE_MSGHDR_ACCRIGHTS
365  msg_mcast.msg_accrights = NULL;
366  #endif
367  #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
368  msg_mcast.msg_accrightslen = 0;
369  #endif
370 
371  /*
372  * Transmit multicast message
373  * An error here is recovered by totemsrp
374  */
375  res = sendmsg (member->fd, &msg_mcast, MSG_NOSIGNAL);
376  if (res < 0) {
377  LOGSYS_PERROR (errno, instance->totemudpu_log_level_debug,
378  "sendmsg(mcast) failed (non-critical)");
379  }
380  }
381 
382  if (!only_active || instance->send_merge_detect_message) {
383  /*
384  * Current message was sent to all nodes
385  */
387  instance->send_merge_detect_message = 0;
388  }
389  } else {
390  /*
391  * Transmit multicast message to local unix mcast loop
392  * An error here is recovered by totemsrp
393  */
394  msg_mcast.msg_name = NULL;
395  msg_mcast.msg_namelen = 0;
396  msg_mcast.msg_iov = (void *)&iovec;
397  msg_mcast.msg_iovlen = 1;
398  #ifdef HAVE_MSGHDR_CONTROL
399  msg_mcast.msg_control = 0;
400  #endif
401  #ifdef HAVE_MSGHDR_CONTROLLEN
402  msg_mcast.msg_controllen = 0;
403  #endif
404  #ifdef HAVE_MSGHDR_FLAGS
405  msg_mcast.msg_flags = 0;
406  #endif
407  #ifdef HAVE_MSGHDR_ACCRIGHTS
408  msg_mcast.msg_accrights = NULL;
409  #endif
410  #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
411  msg_mcast.msg_accrightslen = 0;
412  #endif
413 
414  res = sendmsg (instance->local_loop_sock[1], &msg_mcast,
415  MSG_NOSIGNAL);
416  if (res < 0) {
417  LOGSYS_PERROR (errno, instance->totemudpu_log_level_debug,
418  "sendmsg(local mcast loop) failed (non-critical)");
419  }
420  }
421 }
422 
424  void *udpu_context)
425 {
426  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
427  int res = 0;
428 
429  if (instance->token_socket > 0) {
430  qb_loop_poll_del (instance->totemudpu_poll_handle,
431  instance->token_socket);
432  close (instance->token_socket);
433  }
434 
435  if (instance->local_loop_sock[0] > 0) {
436  qb_loop_poll_del (instance->totemudpu_poll_handle,
437  instance->local_loop_sock[0]);
438  close (instance->local_loop_sock[0]);
439  close (instance->local_loop_sock[1]);
440  }
441 
442  totemudpu_stop_merge_detect_timeout(instance);
443 
444  return (res);
445 }
446 
447 static int net_deliver_fn (
448  int fd,
449  int revents,
450  void *data)
451 {
452  struct totemudpu_instance *instance = (struct totemudpu_instance *)data;
453  struct msghdr msg_recv;
454  struct iovec *iovec;
455  struct sockaddr_storage system_from;
456  int bytes_received;
457  int truncated_packet;
458 
459  iovec = &instance->totemudpu_iov_recv;
460 
461  /*
462  * Receive datagram
463  */
464  msg_recv.msg_name = &system_from;
465  msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
466  msg_recv.msg_iov = iovec;
467  msg_recv.msg_iovlen = 1;
468 #ifdef HAVE_MSGHDR_CONTROL
469  msg_recv.msg_control = 0;
470 #endif
471 #ifdef HAVE_MSGHDR_CONTROLLEN
472  msg_recv.msg_controllen = 0;
473 #endif
474 #ifdef HAVE_MSGHDR_FLAGS
475  msg_recv.msg_flags = 0;
476 #endif
477 #ifdef HAVE_MSGHDR_ACCRIGHTS
478  msg_recv.msg_accrights = NULL;
479 #endif
480 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
481  msg_recv.msg_accrightslen = 0;
482 #endif
483 
484  bytes_received = recvmsg (fd, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
485  if (bytes_received == -1) {
486  return (0);
487  } else {
488  instance->stats_recv += bytes_received;
489  }
490 
491  truncated_packet = 0;
492 
493 #ifdef HAVE_MSGHDR_FLAGS
494  if (msg_recv.msg_flags & MSG_TRUNC) {
495  truncated_packet = 1;
496  }
497 #else
498  /*
499  * We don't have MSGHDR_FLAGS, but we can (hopefully) safely make assumption that
500  * if bytes_received == UDP_RECEIVE_FRAME_SIZE_MAX then packet is truncated
501  */
502  if (bytes_received == UDP_RECEIVE_FRAME_SIZE_MAX) {
503  truncated_packet = 1;
504  }
505 #endif
506 
507  if (truncated_packet) {
509  "Received too big message. This may be because something bad is happening"
510  "on the network (attack?), or you tried join more nodes than corosync is"
511  "compiled with (%u) or bug in the code (bad estimation of "
512  "the UDP_RECEIVE_FRAME_SIZE_MAX). Dropping packet.", PROCESSOR_COUNT_MAX);
513  return (0);
514  }
515 
516  iovec->iov_len = bytes_received;
517 
518  /*
519  * Handle incoming message
520  */
521  instance->totemudpu_deliver_fn (
522  instance->context,
523  iovec->iov_base,
524  iovec->iov_len,
525  &system_from);
526 
527  iovec->iov_len = UDP_RECEIVE_FRAME_SIZE_MAX;
528  return (0);
529 }
530 
531 static int netif_determine (
532  struct totemudpu_instance *instance,
533  struct totem_ip_address *bindnet,
534  struct totem_ip_address *bound_to,
535  int *interface_up,
536  int *interface_num)
537 {
538  int res;
539 
540  res = totemip_iface_check (bindnet, bound_to,
541  interface_up, interface_num,
542  instance->totem_config->clear_node_high_bit);
543 
544 
545  return (res);
546 }
547 
548 
549 /*
550  * If the interface is up, the sockets for totem are built. If the interface is down
551  * this function is requeued in the timer list to retry building the sockets later.
552  */
553 static void timer_function_netif_check_timeout (
554  void *data)
555 {
556  struct totemudpu_instance *instance = (struct totemudpu_instance *)data;
557  int interface_up;
558  int interface_num;
559 
560  /*
561  * Build sockets for every interface
562  */
563  netif_determine (instance,
564  &instance->totem_interface->bindnet,
565  &instance->totem_interface->boundto,
566  &interface_up, &interface_num);
567  /*
568  * If the network interface isn't back up and we are already
569  * in loopback mode, add timer to check again and return
570  */
571  if ((instance->netif_bind_state == BIND_STATE_LOOPBACK &&
572  interface_up == 0) ||
573 
574  (instance->my_memb_entries == 1 &&
575  instance->netif_bind_state == BIND_STATE_REGULAR &&
576  interface_up == 1)) {
577 
578  qb_loop_timer_add (instance->totemudpu_poll_handle,
579  QB_LOOP_MED,
580  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
581  (void *)instance,
582  timer_function_netif_check_timeout,
583  &instance->timer_netif_check_timeout);
584 
585  /*
586  * Add a timer to check for a downed regular interface
587  */
588  return;
589  }
590 
591  if (instance->token_socket > 0) {
592  qb_loop_poll_del (instance->totemudpu_poll_handle,
593  instance->token_socket);
594  close (instance->token_socket);
595  instance->token_socket = -1;
596  }
597 
598  if (interface_up == 0) {
599  if (instance->netif_bind_state == BIND_STATE_UNBOUND) {
601  "One of your ip addresses are now bound to localhost. "
602  "Corosync would not work correctly.");
604  }
605 
606  /*
607  * Interface is not up
608  */
610 
611  /*
612  * Add a timer to retry building interfaces and request memb_gather_enter
613  */
614  qb_loop_timer_add (instance->totemudpu_poll_handle,
615  QB_LOOP_MED,
616  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
617  (void *)instance,
618  timer_function_netif_check_timeout,
619  &instance->timer_netif_check_timeout);
620  } else {
621  /*
622  * Interface is up
623  */
625  }
626  /*
627  * Create and bind the multicast and unicast sockets
628  */
629  totemudpu_build_sockets (instance,
630  &instance->totem_interface->bindnet,
631  &instance->totem_interface->boundto);
632 
633  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
634  qb_loop_poll_add (instance->totemudpu_poll_handle,
635  QB_LOOP_MED,
636  instance->token_socket,
637  POLLIN, instance, net_deliver_fn);
638  }
639 
640  totemip_copy (&instance->my_id, &instance->totem_interface->boundto);
641 
642  /*
643  * This reports changes in the interface to the user and totemsrp
644  */
645  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
646  if (instance->netif_state_report & NETIF_STATE_REPORT_UP) {
648  "The network interface [%s] is now up.",
649  totemip_print (&instance->totem_interface->boundto));
651  instance->totemudpu_iface_change_fn (instance->context, &instance->my_id, 0);
652  }
653  /*
654  * Add a timer to check for interface going down in single membership
655  */
656  if (instance->my_memb_entries == 1) {
657  qb_loop_timer_add (instance->totemudpu_poll_handle,
658  QB_LOOP_MED,
659  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
660  (void *)instance,
661  timer_function_netif_check_timeout,
662  &instance->timer_netif_check_timeout);
663  }
664 
665  } else {
668  "The network interface is down.");
669  instance->totemudpu_iface_change_fn (instance->context, &instance->my_id, 0);
670  }
672 
673  }
674 }
675 
676 /* Set the socket priority to INTERACTIVE to ensure
677  that our messages don't get queued behind anything else */
678 static void totemudpu_traffic_control_set(struct totemudpu_instance *instance, int sock)
679 {
680 #ifdef SO_PRIORITY
681  int prio = 6; /* TC_PRIO_INTERACTIVE */
682 
683  if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(int))) {
684  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
685  "Could not set traffic priority");
686  }
687 #endif
688 }
689 
690 static int totemudpu_build_sockets_ip (
691  struct totemudpu_instance *instance,
692  struct totem_ip_address *bindnet_address,
693  struct totem_ip_address *bound_to,
694  int interface_num)
695 {
696  struct sockaddr_storage sockaddr;
697  int addrlen;
698  int res;
699  unsigned int recvbuf_size;
700  unsigned int optlen = sizeof (recvbuf_size);
701  unsigned int retries = 0;
702 
703  /*
704  * Setup unicast socket
705  */
706  instance->token_socket = socket (bindnet_address->family, SOCK_DGRAM, 0);
707  if (instance->token_socket == -1) {
708  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
709  "socket() failed");
710  return (-1);
711  }
712 
713  totemip_nosigpipe (instance->token_socket);
714  res = fcntl (instance->token_socket, F_SETFL, O_NONBLOCK);
715  if (res == -1) {
716  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
717  "Could not set non-blocking operation on token socket");
718  return (-1);
719  }
720 
721  /*
722  * Bind to unicast socket used for token send/receives
723  * This has the side effect of binding to the correct interface
724  */
725  totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &sockaddr, &addrlen);
726  while (1) {
727  res = bind (instance->token_socket, (struct sockaddr *)&sockaddr, addrlen);
728  if (res == 0) {
729  break;
730  }
731  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
732  "bind token socket failed");
733  if (++retries > BIND_MAX_RETRIES) {
734  break;
735  }
736 
737  /*
738  * Wait for a while
739  */
740  (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
741  }
742 
743  if (res == -1) {
744  return (-1);
745  }
746 
747  /*
748  * the token_socket can receive many messages. Allow a large number
749  * of receive messages on this socket
750  */
751  recvbuf_size = MCAST_SOCKET_BUFFER_SIZE;
752  res = setsockopt (instance->token_socket, SOL_SOCKET, SO_RCVBUF,
753  &recvbuf_size, optlen);
754  if (res == -1) {
755  LOGSYS_PERROR (errno, instance->totemudpu_log_level_notice,
756  "Could not set recvbuf size");
757  }
758 
759  return 0;
760 }
761 
763  void *net_context,
764  char ***status,
765  unsigned int *iface_count)
766 {
767  static char *statuses[INTERFACE_MAX] = {(char*)"OK"};
768 
769  if (status) {
770  *status = statuses;
771  }
772  *iface_count = 1;
773 
774  return (0);
775 }
776 
777 
778 static int totemudpu_build_local_sockets(
779  struct totemudpu_instance *instance)
780 {
781  int i;
782  unsigned int sendbuf_size;
783  unsigned int recvbuf_size;
784  unsigned int optlen = sizeof (sendbuf_size);
785  int res;
786 
787  /*
788  * Create local multicast loop socket
789  */
790  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, instance->local_loop_sock) == -1) {
791  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
792  "socket() failed");
793  return (-1);
794  }
795 
796  for (i = 0; i < 2; i++) {
797  totemip_nosigpipe (instance->local_loop_sock[i]);
798  res = fcntl (instance->local_loop_sock[i], F_SETFL, O_NONBLOCK);
799  if (res == -1) {
800  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
801  "Could not set non-blocking operation on multicast socket");
802  return (-1);
803  }
804  }
805 
806  recvbuf_size = MCAST_SOCKET_BUFFER_SIZE;
807  sendbuf_size = MCAST_SOCKET_BUFFER_SIZE;
808 
809  res = setsockopt (instance->local_loop_sock[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, optlen);
810  if (res == -1) {
811  LOGSYS_PERROR (errno, instance->totemudpu_log_level_debug,
812  "Unable to set SO_RCVBUF size on UDP local mcast loop socket");
813  return (-1);
814  }
815  res = setsockopt (instance->local_loop_sock[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, optlen);
816  if (res == -1) {
817  LOGSYS_PERROR (errno, instance->totemudpu_log_level_debug,
818  "Unable to set SO_SNDBUF size on UDP local mcast loop socket");
819  return (-1);
820  }
821 
822  res = getsockopt (instance->local_loop_sock[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
823  if (res == 0) {
825  "Local receive multicast loop socket recv buffer size (%d bytes).", recvbuf_size);
826  }
827 
828  res = getsockopt (instance->local_loop_sock[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
829  if (res == 0) {
831  "Local transmit multicast loop socket send buffer size (%d bytes).", sendbuf_size);
832  }
833 
834  return (0);
835 }
836 
837 static int totemudpu_build_sockets (
838  struct totemudpu_instance *instance,
839  struct totem_ip_address *bindnet_address,
840  struct totem_ip_address *bound_to)
841 {
842  int interface_num;
843  int interface_up;
844  int res;
845 
846  /*
847  * Determine the ip address bound to and the interface name
848  */
849  res = netif_determine (instance,
850  bindnet_address,
851  bound_to,
852  &interface_up,
853  &interface_num);
854 
855  if (res == -1) {
856  return (-1);
857  }
858 
859  totemip_copy(&instance->my_id, bound_to);
860 
861  res = totemudpu_build_sockets_ip (instance,
862  bindnet_address, bound_to, interface_num);
863 
864  if (res == -1) {
865  /* if we get here, corosync won't work anyway, so better leaving than faking to work */
866  LOGSYS_PERROR (errno, instance->totemudpu_log_level_error,
867  "Unable to create sockets, exiting");
868  exit(EXIT_FAILURE);
869  }
870 
871  /* We only send out of the token socket */
872  totemudpu_traffic_control_set(instance, instance->token_socket);
873 
874  /*
875  * Rebind all members to new ips
876  */
878 
879  return res;
880 }
881 
882 /*
883  * Totem Network interface
884  * depends on poll abstraction, POSIX, IPV4
885  */
886 
887 /*
888  * Create an instance
889  */
891  qb_loop_t *poll_handle,
892  void **udpu_context,
893  struct totem_config *totem_config,
894  totemsrp_stats_t *stats,
895  void *context,
896 
897  void (*deliver_fn) (
898  void *context,
899  const void *msg,
900  unsigned int msg_len,
901  const struct sockaddr_storage *system_from),
902 
903  void (*iface_change_fn) (
904  void *context,
905  const struct totem_ip_address *iface_address,
906  unsigned int ring_no),
907 
908  void (*mtu_changed) (
909  void *context,
910  int net_mtu),
911 
912  void (*target_set_completed) (
913  void *context))
914 {
915  struct totemudpu_instance *instance;
916 
917  instance = malloc (sizeof (struct totemudpu_instance));
918  if (instance == NULL) {
919  return (-1);
920  }
921 
922  totemudpu_instance_initialize (instance);
923 
924  instance->totem_config = totem_config;
925  instance->stats = stats;
926 
927  /*
928  * Configure logging
929  */
930  instance->totemudpu_log_level_security = 1; //totem_config->totem_logging_configuration.log_level_security;
937 
938  /*
939  * Initialize local variables for totemudpu
940  */
941  instance->totem_interface = &totem_config->interfaces[0];
942  memset (instance->iov_buffer, 0, UDP_RECEIVE_FRAME_SIZE_MAX);
943 
944  instance->totemudpu_poll_handle = poll_handle;
945 
946  instance->totem_interface->bindnet.nodeid = instance->totem_config->node_id;
947 
948  instance->context = context;
949  instance->totemudpu_deliver_fn = deliver_fn;
950 
951  instance->totemudpu_iface_change_fn = iface_change_fn;
952 
953  instance->totemudpu_target_set_completed = target_set_completed;
954 
955  /*
956  * Create static local mcast sockets
957  */
958  if (totemudpu_build_local_sockets(instance) == -1) {
959  free(instance);
960  return (-1);
961  }
962 
963  qb_loop_poll_add (
964  instance->totemudpu_poll_handle,
965  QB_LOOP_MED,
966  instance->local_loop_sock[0],
967  POLLIN, instance, net_deliver_fn);
968 
969  /*
970  * RRP layer isn't ready to receive message because it hasn't
971  * initialized yet. Add short timer to check the interfaces.
972  */
973  qb_loop_timer_add (instance->totemudpu_poll_handle,
974  QB_LOOP_MED,
975  100*QB_TIME_NS_IN_MSEC,
976  (void *)instance,
977  timer_function_netif_check_timeout,
978  &instance->timer_netif_check_timeout);
979 
980  totemudpu_start_merge_detect_timeout((void*)instance);
981 
982  *udpu_context = instance;
983  return (0);
984 }
985 
987 {
988  return malloc (FRAME_SIZE_MAX);
989 }
990 
991 void totemudpu_buffer_release (void *ptr)
992 {
993  return free (ptr);
994 }
995 
997  void *udpu_context,
998  int processor_count)
999 {
1000  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1001  int res = 0;
1002 
1003  instance->my_memb_entries = processor_count;
1004  qb_loop_timer_del (instance->totemudpu_poll_handle,
1005  instance->timer_netif_check_timeout);
1006  if (processor_count == 1) {
1007  qb_loop_timer_add (instance->totemudpu_poll_handle,
1008  QB_LOOP_MED,
1009  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
1010  (void *)instance,
1011  timer_function_netif_check_timeout,
1012  &instance->timer_netif_check_timeout);
1013  }
1014 
1015  return (res);
1016 }
1017 
1018 int totemudpu_recv_flush (void *udpu_context)
1019 {
1020  int res = 0;
1021 
1022  return (res);
1023 }
1024 
1025 int totemudpu_send_flush (void *udpu_context)
1026 {
1027  int res = 0;
1028 
1029  return (res);
1030 }
1031 
1033  void *udpu_context,
1034  const void *msg,
1035  unsigned int msg_len)
1036 {
1037  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1038  int res = 0;
1039 
1040  ucast_sendmsg (instance, &instance->token_target, msg, msg_len);
1041 
1042  return (res);
1043 }
1045  void *udpu_context,
1046  const void *msg,
1047  unsigned int msg_len)
1048 {
1049  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1050  int res = 0;
1051 
1052  mcast_sendmsg (instance, msg, msg_len, 0);
1053 
1054  return (res);
1055 }
1056 
1058  void *udpu_context,
1059  const void *msg,
1060  unsigned int msg_len)
1061 {
1062  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1063  int res = 0;
1064 
1065  mcast_sendmsg (instance, msg, msg_len, 1);
1066 
1067  return (res);
1068 }
1069 
1070 extern int totemudpu_iface_check (void *udpu_context)
1071 {
1072  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1073  int res = 0;
1074 
1075  timer_function_netif_check_timeout (instance);
1076 
1077  return (res);
1078 }
1079 
1080 extern void totemudpu_net_mtu_adjust (void *udpu_context, struct totem_config *totem_config)
1081 {
1082  totem_config->net_mtu -= totemip_udpip_header_size(totem_config->interfaces[0].bindnet.family);
1083 }
1084 
1085 
1087  void *udpu_context,
1088  unsigned int nodeid)
1089 {
1090 
1091  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1092  struct qb_list_head *list;
1093  struct totemudpu_member *member;
1094  int res = 0;
1095 
1096  qb_list_for_each(list, &(instance->member_list)) {
1097  member = qb_list_entry (list,
1098  struct totemudpu_member,
1099  list);
1100 
1101  if (member->member.nodeid == nodeid) {
1102  memcpy (&instance->token_target, &member->member,
1103  sizeof (struct totem_ip_address));
1104 
1105  instance->totemudpu_target_set_completed (instance->context);
1106  break;
1107  }
1108  }
1109  return (res);
1110 }
1111 
1113  void *udpu_context)
1114 {
1115  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1116  unsigned int res;
1117  struct sockaddr_storage system_from;
1118  struct msghdr msg_recv;
1119  struct pollfd ufd;
1120  int nfds, i;
1121  int msg_processed = 0;
1122  int sock;
1123 
1124  /*
1125  * Receive datagram
1126  */
1127  msg_recv.msg_name = &system_from;
1128  msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
1129  msg_recv.msg_iov = &instance->totemudpu_iov_recv;
1130  msg_recv.msg_iovlen = 1;
1131 #ifdef HAVE_MSGHDR_CONTROL
1132  msg_recv.msg_control = 0;
1133 #endif
1134 #ifdef HAVE_MSGHDR_CONTROLLEN
1135  msg_recv.msg_controllen = 0;
1136 #endif
1137 #ifdef HAVE_MSGHDR_FLAGS
1138  msg_recv.msg_flags = 0;
1139 #endif
1140 #ifdef HAVE_MSGHDR_ACCRIGHTS
1141  msg_recv.msg_accrights = NULL;
1142 #endif
1143 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
1144  msg_recv.msg_accrightslen = 0;
1145 #endif
1146 
1147  for (i = 0; i < 2; i++) {
1148  sock = -1;
1149  if (i == 0) {
1150  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
1151  sock = instance->token_socket;
1152  } else {
1153  continue;
1154  }
1155  }
1156  if (i == 1) {
1157  sock = instance->local_loop_sock[0];
1158  }
1159  assert(sock != -1);
1160 
1161  do {
1162  ufd.fd = sock;
1163  ufd.events = POLLIN;
1164  nfds = poll (&ufd, 1, 0);
1165  if (nfds == 1 && ufd.revents & POLLIN) {
1166  res = recvmsg (sock, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
1167  if (res != -1) {
1168  msg_processed = 1;
1169  } else {
1170  msg_processed = -1;
1171  }
1172  }
1173  } while (nfds == 1);
1174  }
1175 
1176  return (msg_processed);
1177 }
1178 
1179 static int totemudpu_create_sending_socket(
1180  void *udpu_context,
1181  const struct totem_ip_address *member)
1182 {
1183  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1184  int fd;
1185  int res;
1186  unsigned int sendbuf_size;
1187  unsigned int optlen = sizeof (sendbuf_size);
1188  struct sockaddr_storage sockaddr;
1189  int addrlen;
1190 
1191  fd = socket (member->family, SOCK_DGRAM, 0);
1192  if (fd == -1) {
1193  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
1194  "Could not create socket for new member");
1195  return (-1);
1196  }
1197  totemip_nosigpipe (fd);
1198  res = fcntl (fd, F_SETFL, O_NONBLOCK);
1199  if (res == -1) {
1200  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
1201  "Could not set non-blocking operation on token socket");
1202  goto error_close_fd;
1203  }
1204 
1205  /*
1206  * These sockets are used to send multicast messages, so their buffers
1207  * should be large
1208  */
1209  sendbuf_size = MCAST_SOCKET_BUFFER_SIZE;
1210  res = setsockopt (fd, SOL_SOCKET, SO_SNDBUF,
1211  &sendbuf_size, optlen);
1212  if (res == -1) {
1213  LOGSYS_PERROR (errno, instance->totemudpu_log_level_notice,
1214  "Could not set sendbuf size");
1215  /*
1216  * Fail in setting sendbuf size is not fatal -> don't exit
1217  */
1218  }
1219 
1220  /*
1221  * Bind to sending interface
1222  */
1223  totemip_totemip_to_sockaddr_convert(&instance->my_id, 0, &sockaddr, &addrlen);
1224  res = bind (fd, (struct sockaddr *)&sockaddr, addrlen);
1225  if (res == -1) {
1226  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
1227  "bind token socket failed");
1228  goto error_close_fd;
1229  }
1230 
1231  return (fd);
1232 
1233 error_close_fd:
1234  close(fd);
1235  return (-1);
1236 }
1237 
1238 int totemudpu_iface_set (void *net_context,
1239  const struct totem_ip_address *local_addr,
1240  unsigned short ip_port,
1241  unsigned int iface_no)
1242 {
1243  /* Not supported */
1244  return (-1);
1245 }
1246 
1248  void *udpu_context,
1249  const struct totem_ip_address *local,
1250  const struct totem_ip_address *member,
1251  int ring_no)
1252 {
1253  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1254 
1255  struct totemudpu_member *new_member;
1256 
1257  new_member = malloc (sizeof (struct totemudpu_member));
1258  if (new_member == NULL) {
1259  return (-1);
1260  }
1261 
1262  memset(new_member, 0, sizeof(*new_member));
1263 
1264  log_printf (LOGSYS_LEVEL_NOTICE, "adding new UDPU member {%s}",
1265  totemip_print(member));
1266  qb_list_init (&new_member->list);
1267  qb_list_add_tail (&new_member->list, &instance->member_list);
1268  memcpy (&new_member->member, member, sizeof (struct totem_ip_address));
1269  new_member->fd = totemudpu_create_sending_socket(udpu_context, member);
1270  new_member->active = 1;
1271 
1272  return (0);
1273 }
1274 
1276  void *udpu_context,
1277  const struct totem_ip_address *token_target,
1278  int ring_no)
1279 {
1280  int found = 0;
1281  struct qb_list_head *list;
1282  struct totemudpu_member *member;
1283 
1284  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1285 
1286  /*
1287  * Find the member to remove and close its socket
1288  */
1289  qb_list_for_each(list, &(instance->member_list)) {
1290  member = qb_list_entry (list,
1291  struct totemudpu_member,
1292  list);
1293 
1294  if (totemip_compare (token_target, &member->member)==0) {
1296  "removing UDPU member {%s}",
1297  totemip_print(&member->member));
1298 
1299  if (member->fd > 0) {
1301  "Closing socket to: {%s}",
1302  totemip_print(&member->member));
1303  qb_loop_poll_del (instance->totemudpu_poll_handle,
1304  member->fd);
1305  close (member->fd);
1306  }
1307  found = 1;
1308  break;
1309  }
1310  }
1311 
1312  /*
1313  * Delete the member from the list
1314  */
1315  if (found) {
1316  qb_list_del (list);
1317  }
1318 
1319  instance = NULL;
1320  return (0);
1321 }
1322 
1324  void *udpu_context)
1325 {
1326  struct qb_list_head *list;
1327  struct totemudpu_member *member;
1328 
1329  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1330 
1331  qb_list_for_each(list, &(instance->member_list)) {
1332  member = qb_list_entry (list,
1333  struct totemudpu_member,
1334  list);
1335 
1336  if (member->fd > 0) {
1337  close (member->fd);
1338  }
1339 
1340  member->fd = totemudpu_create_sending_socket(udpu_context, &member->member);
1341  }
1342 
1343  return (0);
1344 }
1345 
1346 
1347 static void timer_function_merge_detect_timeout (
1348  void *data)
1349 {
1350  struct totemudpu_instance *instance = (struct totemudpu_instance *)data;
1351 
1352  if (instance->merge_detect_messages_sent_before_timeout == 0) {
1353  instance->send_merge_detect_message = 1;
1354  }
1355 
1357 
1358  totemudpu_start_merge_detect_timeout(instance);
1359 }
1360 
1361 static void totemudpu_start_merge_detect_timeout(
1362  void *udpu_context)
1363 {
1364  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1365 
1366  qb_loop_timer_add(instance->totemudpu_poll_handle,
1367  QB_LOOP_MED,
1368  instance->totem_config->merge_timeout * 2 * QB_TIME_NS_IN_MSEC,
1369  (void *)instance,
1370  timer_function_merge_detect_timeout,
1371  &instance->timer_merge_detect_timeout);
1372 
1373 }
1374 
1375 static void totemudpu_stop_merge_detect_timeout(
1376  void *udpu_context)
1377 {
1378  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1379 
1380  qb_loop_timer_del(instance->totemudpu_poll_handle,
1381  instance->timer_merge_detect_timeout);
1382 }
1383 
1385  void *udpu_context,
1386  struct totem_config *totem_config)
1387 {
1388  /* Not supported */
1389  return (-1);
1390 }
unsigned int clear_node_high_bit
Definition: totem.h:161
unsigned short family
Definition: coroapi.h:113
#define BIND_STATE_UNBOUND
Definition: totemudpu.c:81
#define NETIF_STATE_REPORT_UP
Definition: totemudpu.c:78
struct totem_config * totem_config
Definition: totemudpu.c:168
struct totem_ip_address member
Definition: totemudpu.c:87
unsigned int my_memb_entries
Definition: totemudpu.c:166
#define BIND_MAX_RETRIES
Definition: totem.h:69
struct totem_interface * interfaces
Definition: totem.h:158
void(* totemudpu_iface_change_fn)(void *context, const struct totem_ip_address *iface_address, unsigned int ring_no)
Definition: totemudpu.c:109
The totem_ip_address struct.
Definition: coroapi.h:111
void(*) void udpu_context)
Definition: totemudpu.c:138
struct qb_list_head member_list
Definition: totemudpu.c:146
const char * totemip_print(const struct totem_ip_address *addr)
Definition: totemip.c:237
struct totem_ip_address my_id
Definition: totemudpu.c:160
struct totemudpu_instance * instance
Definition: totemudpu.c:188
int totemudpu_iface_set(void *net_context, const struct totem_ip_address *local_addr, unsigned short ip_port, unsigned int iface_no)
Definition: totemudpu.c:1238
#define NETIF_STATE_REPORT_DOWN
Definition: totemudpu.c:79
int totemip_compare(const void *a, const void *b)
Definition: totemip.c:131
#define log_printf(level, format, args...)
Definition: totemudpu.c:227
int totemudpu_processor_count_set(void *udpu_context, int processor_count)
Definition: totemudpu.c:996
int totemudpu_log_level_security
Definition: totemudpu.c:119
void totemip_copy(struct totem_ip_address *addr1, const struct totem_ip_address *addr2)
Definition: totemip.c:96
int totemudpu_member_remove(void *udpu_context, const struct totem_ip_address *token_target, int ring_no)
Definition: totemudpu.c:1275
unsigned int downcheck_timeout
Definition: totem.h:192
qb_loop_timer_handle timer_merge_detect_timeout
Definition: totemudpu.c:178
int send_merge_detect_message
Definition: totemudpu.c:180
#define totemip_nosigpipe(s)
Definition: totemip.h:56
int totemudpu_log_level_warning
Definition: totemudpu.c:123
int totemudpu_log_level_debug
Definition: totemudpu.c:127
struct iovec totemudpu_iov_recv
Definition: totemudpu.c:144
#define INTERFACE_MAX
Definition: coroapi.h:88
unsigned int node_id
Definition: totem.h:160
#define BIND_STATE_REGULAR
Definition: totemudpu.c:82
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:510
#define UDP_RECEIVE_FRAME_SIZE_MAX
Definition: totem.h:61
void totemudpu_buffer_release(void *ptr)
Definition: totemudpu.c:991
void * totemudpu_buffer_alloc(void)
Definition: totemudpu.c:986
unsigned int merge_detect_messages_sent_before_timeout
Definition: totemudpu.c:182
qb_loop_t * totemudpu_poll_handle
Definition: totemudpu.c:93
int totemudpu_mcast_noflush_send(void *udpu_context, const void *msg, unsigned int msg_len)
Definition: totemudpu.c:1057
unsigned int nodeid
Definition: coroapi.h:112
totemsrp_stats_t * stats
Definition: totemudpu.c:170
int local_loop_sock[2]
Definition: totemudpu.c:176
#define BIND_RETRIES_INTERVAL
Definition: totem.h:70
struct totem_ip_address token_target
Definition: totemudpu.c:172
int totemudpu_crypto_set(void *udpu_context, const char *cipher_type, const char *hash_type)
Definition: totemudpu.c:244
#define LOGSYS_LEVEL_DEBUG
Definition: logsys.h:76
struct totem_interface * totem_interface
Definition: totemudpu.c:95
int totemudpu_token_send(void *udpu_context, const void *msg, unsigned int msg_len)
Definition: totemudpu.c:1032
struct totem_ip_address boundto
Definition: totem.h:83
typedef __attribute__
size_t totemip_udpip_header_size(int family)
Definition: totemip.c:589
struct qb_list_head list
Definition: totemudpu.c:86
void(* log_printf)(int level, int subsys, const char *function_name, const char *file_name, int file_line, const char *format,...) __attribute__((format(printf
Definition: totem.h:99
uint16_t ip_port
Definition: totem.h:85
qb_loop_timer_handle timer_netif_check_timeout
Definition: totemudpu.c:164
void(* totemudpu_target_set_completed)(void *context)
Definition: totemudpu.c:114
#define BIND_STATE_LOOPBACK
Definition: totemudpu.c:83
unsigned int net_mtu
Definition: totem.h:202
#define MCAST_SOCKET_BUFFER_SIZE
Definition: totemudpu.c:77
#define PROCESSOR_COUNT_MAX
Definition: coroapi.h:96
int totemudpu_ifaces_get(void *net_context, char ***status, unsigned int *iface_count)
Definition: totemudpu.c:762
char iov_buffer[UDP_RECEIVE_FRAME_SIZE_MAX]
Definition: totemudpu.c:142
int totemudpu_token_target_set(void *udpu_context, unsigned int nodeid)
Definition: totemudpu.c:1086
#define FRAME_SIZE_MAX
Definition: totem.h:52
int totemudpu_initialize(qb_loop_t *poll_handle, void **udpu_context, struct totem_config *totem_config, totemsrp_stats_t *stats, void *context, void(*deliver_fn)(void *context, const void *msg, unsigned int msg_len, const struct sockaddr_storage *system_from), void(*iface_change_fn)(void *context, const struct totem_ip_address *iface_address, unsigned int ring_no), void(*mtu_changed)(void *context, int net_mtu), void(*target_set_completed)(void *context))
Create an instance.
Definition: totemudpu.c:890
int totemip_totemip_to_sockaddr_convert(struct totem_ip_address *ip_addr, uint16_t port, struct sockaddr_storage *saddr, int *addrlen)
Definition: totemip.c:245
struct totem_logging_configuration totem_logging_configuration
Definition: totem.h:200
#define LOGSYS_LEVEL_NOTICE
Definition: logsys.h:74
int totemudpu_recv_mcast_empty(void *udpu_context)
Definition: totemudpu.c:1112
struct srp_addr system_from
Definition: totemsrp.c:261
int totemudpu_log_level_error
Definition: totemudpu.c:121
int totemudpu_member_add(void *udpu_context, const struct totem_ip_address *local, const struct totem_ip_address *member, int ring_no)
Definition: totemudpu.c:1247
unsigned int merge_timeout
Definition: totem.h:190
int totemudpu_reconfigure(void *udpu_context, struct totem_config *totem_config)
Definition: totemudpu.c:1384
void totemudpu_net_mtu_adjust(void *udpu_context, struct totem_config *totem_config)
Definition: totemudpu.c:1080
struct totem_ip_address bindnet
Definition: totem.h:82
unsigned int nodeid
Definition: coroapi.h:75
#define MSG_NOSIGNAL
Definition: totemudpu.c:74
void(* totemudpu_deliver_fn)(void *context, const void *msg, unsigned int msg_len, const struct sockaddr_storage *system_from)
Definition: totemudpu.c:103
int totemudpu_mcast_flush_send(void *udpu_context, const void *msg, unsigned int msg_len)
Definition: totemudpu.c:1044
int totemudpu_send_flush(void *udpu_context)
Definition: totemudpu.c:1025
int totemudpu_finalize(void *udpu_context)
Definition: totemudpu.c:423
int totemudpu_recv_flush(void *udpu_context)
Definition: totemudpu.c:1018
#define LOGSYS_PERROR(err_num, level, fmt, args...)
Definition: totemudpu.c:234
int totemudpu_member_list_rebind_ip(void *udpu_context)
Definition: totemudpu.c:1323
void(* totemudpu_log_printf)(int level, int subsys, const char *function, const char *file, int line, const char *format,...) __attribute__((format(printf
Definition: totemudpu.c:131
int totemudpu_iface_check(void *udpu_context)
Definition: totemudpu.c:1070
int totemudpu_log_level_notice
Definition: totemudpu.c:125