corosync  3.1.5
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;
87  struct totem_ip_address member;
88  int fd;
89  int active;
90 };
91 
94 
96 
98 
100 
101  void *context;
102 
104  void *context,
105  const void *msg,
106  unsigned int msg_len,
107  const struct sockaddr_storage *system_from);
108 
110  void *context,
111  const struct totem_ip_address *iface_address,
112  unsigned int ring_no);
113 
115 
116  /*
117  * Function and data used to log messages
118  */
120 
122 
124 
126 
128 
130 
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 
141 
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 
173 
175 
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 struct totemudpu_member *find_member_by_sockaddr(
448  const void *udpu_context,
449  const struct sockaddr *sa)
450 {
451  struct qb_list_head *list;
452  struct totemudpu_member *member;
453  struct totemudpu_member *res_member;
454  const struct totemudpu_instance *instance = (const struct totemudpu_instance *)udpu_context;
455 
456  res_member = NULL;
457 
458  qb_list_for_each(list, &(instance->member_list)) {
459  member = qb_list_entry (list,
460  struct totemudpu_member,
461  list);
462 
463  if (totemip_sa_equal(&member->member, sa)) {
464  res_member = member;
465  break ;
466  }
467  }
468 
469  return (res_member);
470 }
471 
472 
473 static int net_deliver_fn (
474  int fd,
475  int revents,
476  void *data)
477 {
478  struct totemudpu_instance *instance = (struct totemudpu_instance *)data;
479  struct msghdr msg_recv;
480  struct iovec *iovec;
481  struct sockaddr_storage system_from;
482  int bytes_received;
483  int truncated_packet;
484 
485  iovec = &instance->totemudpu_iov_recv;
486 
487  /*
488  * Receive datagram
489  */
490  msg_recv.msg_name = &system_from;
491  msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
492  msg_recv.msg_iov = iovec;
493  msg_recv.msg_iovlen = 1;
494 #ifdef HAVE_MSGHDR_CONTROL
495  msg_recv.msg_control = 0;
496 #endif
497 #ifdef HAVE_MSGHDR_CONTROLLEN
498  msg_recv.msg_controllen = 0;
499 #endif
500 #ifdef HAVE_MSGHDR_FLAGS
501  msg_recv.msg_flags = 0;
502 #endif
503 #ifdef HAVE_MSGHDR_ACCRIGHTS
504  msg_recv.msg_accrights = NULL;
505 #endif
506 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
507  msg_recv.msg_accrightslen = 0;
508 #endif
509 
510  bytes_received = recvmsg (fd, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
511  if (bytes_received == -1) {
512  return (0);
513  } else {
514  instance->stats_recv += bytes_received;
515  }
516 
517  truncated_packet = 0;
518 
519 #ifdef HAVE_MSGHDR_FLAGS
520  if (msg_recv.msg_flags & MSG_TRUNC) {
521  truncated_packet = 1;
522  }
523 #else
524  /*
525  * We don't have MSGHDR_FLAGS, but we can (hopefully) safely make assumption that
526  * if bytes_received == UDP_RECEIVE_FRAME_SIZE_MAX then packet is truncated
527  */
528  if (bytes_received == UDP_RECEIVE_FRAME_SIZE_MAX) {
529  truncated_packet = 1;
530  }
531 #endif
532 
533  if (truncated_packet) {
535  "Received too big message. This may be because something bad is happening"
536  "on the network (attack?), or you tried join more nodes than corosync is"
537  "compiled with (%u) or bug in the code (bad estimation of "
538  "the UDP_RECEIVE_FRAME_SIZE_MAX). Dropping packet.", PROCESSOR_COUNT_MAX);
539  return (0);
540  }
541 
542  if (instance->totem_config->block_unlisted_ips &&
543  find_member_by_sockaddr(instance, (const struct sockaddr *)&system_from) == NULL) {
544  log_printf(instance->totemudpu_log_level_debug, "Packet rejected from %s",
545  totemip_sa_print((const struct sockaddr *)&system_from));
546 
547  return (0);
548  }
549 
550  iovec->iov_len = bytes_received;
551 
552  /*
553  * Handle incoming message
554  */
555  instance->totemudpu_deliver_fn (
556  instance->context,
557  iovec->iov_base,
558  iovec->iov_len,
559  &system_from);
560 
561  iovec->iov_len = UDP_RECEIVE_FRAME_SIZE_MAX;
562  return (0);
563 }
564 
565 static int netif_determine (
566  struct totemudpu_instance *instance,
567  struct totem_ip_address *bindnet,
568  struct totem_ip_address *bound_to,
569  int *interface_up,
570  int *interface_num)
571 {
572  int res;
573 
574  res = totemip_iface_check (bindnet, bound_to,
575  interface_up, interface_num,
576  instance->totem_config->clear_node_high_bit);
577 
578 
579  return (res);
580 }
581 
582 
583 /*
584  * If the interface is up, the sockets for totem are built. If the interface is down
585  * this function is requeued in the timer list to retry building the sockets later.
586  */
587 static void timer_function_netif_check_timeout (
588  void *data)
589 {
590  struct totemudpu_instance *instance = (struct totemudpu_instance *)data;
591  int interface_up;
592  int interface_num;
593 
594  /*
595  * Build sockets for every interface
596  */
597  netif_determine (instance,
598  &instance->totem_interface->bindnet,
599  &instance->totem_interface->boundto,
600  &interface_up, &interface_num);
601  /*
602  * If the network interface isn't back up and we are already
603  * in loopback mode, add timer to check again and return
604  */
605  if ((instance->netif_bind_state == BIND_STATE_LOOPBACK &&
606  interface_up == 0) ||
607 
608  (instance->my_memb_entries == 1 &&
609  instance->netif_bind_state == BIND_STATE_REGULAR &&
610  interface_up == 1)) {
611 
612  qb_loop_timer_add (instance->totemudpu_poll_handle,
613  QB_LOOP_MED,
614  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
615  (void *)instance,
616  timer_function_netif_check_timeout,
617  &instance->timer_netif_check_timeout);
618 
619  /*
620  * Add a timer to check for a downed regular interface
621  */
622  return;
623  }
624 
625  if (instance->token_socket > 0) {
626  qb_loop_poll_del (instance->totemudpu_poll_handle,
627  instance->token_socket);
628  close (instance->token_socket);
629  instance->token_socket = -1;
630  }
631 
632  if (interface_up == 0) {
633  if (instance->netif_bind_state == BIND_STATE_UNBOUND) {
635  "One of your ip addresses are now bound to localhost. "
636  "Corosync would not work correctly.");
638  }
639 
640  /*
641  * Interface is not up
642  */
644 
645  /*
646  * Add a timer to retry building interfaces and request memb_gather_enter
647  */
648  qb_loop_timer_add (instance->totemudpu_poll_handle,
649  QB_LOOP_MED,
650  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
651  (void *)instance,
652  timer_function_netif_check_timeout,
653  &instance->timer_netif_check_timeout);
654  } else {
655  /*
656  * Interface is up
657  */
659  }
660  /*
661  * Create and bind the multicast and unicast sockets
662  */
663  totemudpu_build_sockets (instance,
664  &instance->totem_interface->bindnet,
665  &instance->totem_interface->boundto);
666 
667  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
668  qb_loop_poll_add (instance->totemudpu_poll_handle,
669  QB_LOOP_MED,
670  instance->token_socket,
671  POLLIN, instance, net_deliver_fn);
672  }
673 
674  totemip_copy (&instance->my_id, &instance->totem_interface->boundto);
675 
676  /*
677  * This reports changes in the interface to the user and totemsrp
678  */
679  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
680  if (instance->netif_state_report & NETIF_STATE_REPORT_UP) {
682  "The network interface [%s] is now up.",
683  totemip_print (&instance->totem_interface->boundto));
685  instance->totemudpu_iface_change_fn (instance->context, &instance->my_id, 0);
686  }
687  /*
688  * Add a timer to check for interface going down in single membership
689  */
690  if (instance->my_memb_entries == 1) {
691  qb_loop_timer_add (instance->totemudpu_poll_handle,
692  QB_LOOP_MED,
693  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
694  (void *)instance,
695  timer_function_netif_check_timeout,
696  &instance->timer_netif_check_timeout);
697  }
698 
699  } else {
702  "The network interface is down.");
703  instance->totemudpu_iface_change_fn (instance->context, &instance->my_id, 0);
704  }
706 
707  }
708 }
709 
710 /* Set the socket priority to INTERACTIVE to ensure
711  that our messages don't get queued behind anything else */
712 static void totemudpu_traffic_control_set(struct totemudpu_instance *instance, int sock)
713 {
714 #ifdef SO_PRIORITY
715  int prio = 6; /* TC_PRIO_INTERACTIVE */
716 
717  if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(int))) {
718  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
719  "Could not set traffic priority");
720  }
721 #endif
722 }
723 
724 static int totemudpu_build_sockets_ip (
725  struct totemudpu_instance *instance,
726  struct totem_ip_address *bindnet_address,
727  struct totem_ip_address *bound_to,
728  int interface_num)
729 {
730  struct sockaddr_storage sockaddr;
731  int addrlen;
732  int res;
733  unsigned int recvbuf_size;
734  unsigned int optlen = sizeof (recvbuf_size);
735  unsigned int retries = 0;
736 
737  /*
738  * Setup unicast socket
739  */
740  instance->token_socket = socket (bindnet_address->family, SOCK_DGRAM, 0);
741  if (instance->token_socket == -1) {
742  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
743  "socket() failed");
744  return (-1);
745  }
746 
747  totemip_nosigpipe (instance->token_socket);
748  res = fcntl (instance->token_socket, F_SETFL, O_NONBLOCK);
749  if (res == -1) {
750  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
751  "Could not set non-blocking operation on token socket");
752  return (-1);
753  }
754 
755  /*
756  * Bind to unicast socket used for token send/receives
757  * This has the side effect of binding to the correct interface
758  */
759  totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &sockaddr, &addrlen);
760  while (1) {
761  res = bind (instance->token_socket, (struct sockaddr *)&sockaddr, addrlen);
762  if (res == 0) {
763  break;
764  }
765  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
766  "bind token socket failed");
767  if (++retries > BIND_MAX_RETRIES) {
768  break;
769  }
770 
771  /*
772  * Wait for a while
773  */
774  (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
775  }
776 
777  if (res == -1) {
778  return (-1);
779  }
780 
781  /*
782  * the token_socket can receive many messages. Allow a large number
783  * of receive messages on this socket
784  */
785  recvbuf_size = MCAST_SOCKET_BUFFER_SIZE;
786  res = setsockopt (instance->token_socket, SOL_SOCKET, SO_RCVBUF,
787  &recvbuf_size, optlen);
788  if (res == -1) {
789  LOGSYS_PERROR (errno, instance->totemudpu_log_level_notice,
790  "Could not set recvbuf size");
791  }
792 
793  return 0;
794 }
795 
796 int totemudpu_nodestatus_get (void *udpu_context, unsigned int nodeid,
797  struct totem_node_status *node_status)
798 {
799  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
800  struct qb_list_head *list;
801  struct totemudpu_member *member;
802 
803  qb_list_for_each(list, &(instance->member_list)) {
804  member = qb_list_entry (list,
805  struct totemudpu_member,
806  list);
807 
808  if (member->member.nodeid == nodeid) {
809  node_status->nodeid = nodeid;
810  /* reachable is filled in by totemsrp */
811  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
812  node_status->link_status[0].enabled = 1;
813  } else {
814  node_status->link_status[0].enabled = 0;
815  }
816  node_status->link_status[0].connected = node_status->reachable;
817  node_status->link_status[0].mtu = instance->totem_config->net_mtu;
818  strncpy(node_status->link_status[0].src_ipaddr, totemip_print(&member->member), KNET_MAX_HOST_LEN-1);
819  }
820  }
821  return (0);
822 }
823 
825  void *net_context,
826  char ***status,
827  unsigned int *iface_count)
828 {
829  static char *statuses[INTERFACE_MAX] = {(char*)"OK"};
830 
831  if (status) {
832  *status = statuses;
833  }
834  *iface_count = 1;
835 
836  return (0);
837 }
838 
839 
840 static int totemudpu_build_local_sockets(
841  struct totemudpu_instance *instance)
842 {
843  int i;
844  unsigned int sendbuf_size;
845  unsigned int recvbuf_size;
846  unsigned int optlen = sizeof (sendbuf_size);
847  int res;
848 
849  /*
850  * Create local multicast loop socket
851  */
852  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, instance->local_loop_sock) == -1) {
853  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
854  "socket() failed");
855  return (-1);
856  }
857 
858  for (i = 0; i < 2; i++) {
859  totemip_nosigpipe (instance->local_loop_sock[i]);
860  res = fcntl (instance->local_loop_sock[i], F_SETFL, O_NONBLOCK);
861  if (res == -1) {
862  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
863  "Could not set non-blocking operation on multicast socket");
864  return (-1);
865  }
866  }
867 
868  recvbuf_size = MCAST_SOCKET_BUFFER_SIZE;
869  sendbuf_size = MCAST_SOCKET_BUFFER_SIZE;
870 
871  res = setsockopt (instance->local_loop_sock[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, optlen);
872  if (res == -1) {
873  LOGSYS_PERROR (errno, instance->totemudpu_log_level_debug,
874  "Unable to set SO_RCVBUF size on UDP local mcast loop socket");
875  return (-1);
876  }
877  res = setsockopt (instance->local_loop_sock[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, optlen);
878  if (res == -1) {
879  LOGSYS_PERROR (errno, instance->totemudpu_log_level_debug,
880  "Unable to set SO_SNDBUF size on UDP local mcast loop socket");
881  return (-1);
882  }
883 
884  res = getsockopt (instance->local_loop_sock[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
885  if (res == 0) {
887  "Local receive multicast loop socket recv buffer size (%d bytes).", recvbuf_size);
888  }
889 
890  res = getsockopt (instance->local_loop_sock[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
891  if (res == 0) {
893  "Local transmit multicast loop socket send buffer size (%d bytes).", sendbuf_size);
894  }
895 
896  return (0);
897 }
898 
899 static int totemudpu_build_sockets (
900  struct totemudpu_instance *instance,
901  struct totem_ip_address *bindnet_address,
902  struct totem_ip_address *bound_to)
903 {
904  int interface_num;
905  int interface_up;
906  int res;
907 
908  /*
909  * Determine the ip address bound to and the interface name
910  */
911  res = netif_determine (instance,
912  bindnet_address,
913  bound_to,
914  &interface_up,
915  &interface_num);
916 
917  if (res == -1) {
918  return (-1);
919  }
920 
921  totemip_copy(&instance->my_id, bound_to);
922 
923  res = totemudpu_build_sockets_ip (instance,
924  bindnet_address, bound_to, interface_num);
925 
926  if (res == -1) {
927  /* if we get here, corosync won't work anyway, so better leaving than faking to work */
928  LOGSYS_PERROR (errno, instance->totemudpu_log_level_error,
929  "Unable to create sockets, exiting");
930  exit(EXIT_FAILURE);
931  }
932 
933  /* We only send out of the token socket */
934  totemudpu_traffic_control_set(instance, instance->token_socket);
935 
936  /*
937  * Rebind all members to new ips
938  */
940 
941  return res;
942 }
943 
944 /*
945  * Totem Network interface
946  * depends on poll abstraction, POSIX, IPV4
947  */
948 
949 /*
950  * Create an instance
951  */
953  qb_loop_t *poll_handle,
954  void **udpu_context,
955  struct totem_config *totem_config,
956  totemsrp_stats_t *stats,
957  void *context,
958 
959  void (*deliver_fn) (
960  void *context,
961  const void *msg,
962  unsigned int msg_len,
963  const struct sockaddr_storage *system_from),
964 
965  void (*iface_change_fn) (
966  void *context,
967  const struct totem_ip_address *iface_address,
968  unsigned int ring_no),
969 
970  void (*mtu_changed) (
971  void *context,
972  int net_mtu),
973 
974  void (*target_set_completed) (
975  void *context))
976 {
977  struct totemudpu_instance *instance;
978 
979  instance = malloc (sizeof (struct totemudpu_instance));
980  if (instance == NULL) {
981  return (-1);
982  }
983 
984  totemudpu_instance_initialize (instance);
985 
986  instance->totem_config = totem_config;
987  instance->stats = stats;
988 
989  /*
990  * Configure logging
991  */
992  instance->totemudpu_log_level_security = 1; //totem_config->totem_logging_configuration.log_level_security;
999 
1000  /*
1001  * Initialize local variables for totemudpu
1002  */
1003  instance->totem_interface = &totem_config->interfaces[0];
1004  memset (instance->iov_buffer, 0, UDP_RECEIVE_FRAME_SIZE_MAX);
1005 
1006  instance->totemudpu_poll_handle = poll_handle;
1007 
1008  instance->totem_interface->bindnet.nodeid = instance->totem_config->node_id;
1009 
1010  instance->context = context;
1011  instance->totemudpu_deliver_fn = deliver_fn;
1012 
1013  instance->totemudpu_iface_change_fn = iface_change_fn;
1014 
1015  instance->totemudpu_target_set_completed = target_set_completed;
1016 
1017  /*
1018  * Create static local mcast sockets
1019  */
1020  if (totemudpu_build_local_sockets(instance) == -1) {
1021  free(instance);
1022  return (-1);
1023  }
1024 
1025  qb_loop_poll_add (
1026  instance->totemudpu_poll_handle,
1027  QB_LOOP_MED,
1028  instance->local_loop_sock[0],
1029  POLLIN, instance, net_deliver_fn);
1030 
1031  /*
1032  * RRP layer isn't ready to receive message because it hasn't
1033  * initialized yet. Add short timer to check the interfaces.
1034  */
1035  qb_loop_timer_add (instance->totemudpu_poll_handle,
1036  QB_LOOP_MED,
1037  100*QB_TIME_NS_IN_MSEC,
1038  (void *)instance,
1039  timer_function_netif_check_timeout,
1040  &instance->timer_netif_check_timeout);
1041 
1042  totemudpu_start_merge_detect_timeout((void*)instance);
1043 
1044  *udpu_context = instance;
1045  return (0);
1046 }
1047 
1049 {
1050  return malloc (FRAME_SIZE_MAX);
1051 }
1052 
1054 {
1055  return free (ptr);
1056 }
1057 
1059  void *udpu_context,
1060  int processor_count)
1061 {
1062  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1063  int res = 0;
1064 
1065  instance->my_memb_entries = processor_count;
1066  qb_loop_timer_del (instance->totemudpu_poll_handle,
1067  instance->timer_netif_check_timeout);
1068  if (processor_count == 1) {
1069  qb_loop_timer_add (instance->totemudpu_poll_handle,
1070  QB_LOOP_MED,
1071  instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
1072  (void *)instance,
1073  timer_function_netif_check_timeout,
1074  &instance->timer_netif_check_timeout);
1075  }
1076 
1077  return (res);
1078 }
1079 
1081 {
1082  int res = 0;
1083 
1084  return (res);
1085 }
1086 
1088 {
1089  int res = 0;
1090 
1091  return (res);
1092 }
1093 
1095  void *udpu_context,
1096  const void *msg,
1097  unsigned int msg_len)
1098 {
1099  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1100  int res = 0;
1101 
1102  ucast_sendmsg (instance, &instance->token_target, msg, msg_len);
1103 
1104  return (res);
1105 }
1107  void *udpu_context,
1108  const void *msg,
1109  unsigned int msg_len)
1110 {
1111  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1112  int res = 0;
1113 
1114  mcast_sendmsg (instance, msg, msg_len, 0);
1115 
1116  return (res);
1117 }
1118 
1120  void *udpu_context,
1121  const void *msg,
1122  unsigned int msg_len)
1123 {
1124  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1125  int res = 0;
1126 
1127  mcast_sendmsg (instance, msg, msg_len, 1);
1128 
1129  return (res);
1130 }
1131 
1133 {
1134  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1135  int res = 0;
1136 
1137  timer_function_netif_check_timeout (instance);
1138 
1139  return (res);
1140 }
1141 
1143 {
1145 }
1146 
1147 
1149  void *udpu_context,
1150  unsigned int nodeid)
1151 {
1152 
1153  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1154  struct qb_list_head *list;
1155  struct totemudpu_member *member;
1156  int res = 0;
1157 
1158  qb_list_for_each(list, &(instance->member_list)) {
1159  member = qb_list_entry (list,
1160  struct totemudpu_member,
1161  list);
1162 
1163  if (member->member.nodeid == nodeid) {
1164  memcpy (&instance->token_target, &member->member,
1165  sizeof (struct totem_ip_address));
1166 
1167  instance->totemudpu_target_set_completed (instance->context);
1168  break;
1169  }
1170  }
1171  return (res);
1172 }
1173 
1175  void *udpu_context)
1176 {
1177  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1178  unsigned int res;
1179  struct sockaddr_storage system_from;
1180  struct msghdr msg_recv;
1181  struct pollfd ufd;
1182  int nfds, i;
1183  int msg_processed = 0;
1184  int sock;
1185 
1186  /*
1187  * Receive datagram
1188  */
1189  msg_recv.msg_name = &system_from;
1190  msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
1191  msg_recv.msg_iov = &instance->totemudpu_iov_recv;
1192  msg_recv.msg_iovlen = 1;
1193 #ifdef HAVE_MSGHDR_CONTROL
1194  msg_recv.msg_control = 0;
1195 #endif
1196 #ifdef HAVE_MSGHDR_CONTROLLEN
1197  msg_recv.msg_controllen = 0;
1198 #endif
1199 #ifdef HAVE_MSGHDR_FLAGS
1200  msg_recv.msg_flags = 0;
1201 #endif
1202 #ifdef HAVE_MSGHDR_ACCRIGHTS
1203  msg_recv.msg_accrights = NULL;
1204 #endif
1205 #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
1206  msg_recv.msg_accrightslen = 0;
1207 #endif
1208 
1209  for (i = 0; i < 2; i++) {
1210  sock = -1;
1211  if (i == 0) {
1212  if (instance->netif_bind_state == BIND_STATE_REGULAR) {
1213  sock = instance->token_socket;
1214  } else {
1215  continue;
1216  }
1217  }
1218  if (i == 1) {
1219  sock = instance->local_loop_sock[0];
1220  }
1221  assert(sock != -1);
1222 
1223  do {
1224  ufd.fd = sock;
1225  ufd.events = POLLIN;
1226  nfds = poll (&ufd, 1, 0);
1227  if (nfds == 1 && ufd.revents & POLLIN) {
1228  res = recvmsg (sock, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
1229  if (res != -1) {
1230  msg_processed = 1;
1231  } else {
1232  msg_processed = -1;
1233  }
1234  }
1235  } while (nfds == 1);
1236  }
1237 
1238  return (msg_processed);
1239 }
1240 
1241 static int totemudpu_create_sending_socket(
1242  void *udpu_context,
1243  const struct totem_ip_address *member)
1244 {
1245  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1246  int fd;
1247  int res;
1248  unsigned int sendbuf_size;
1249  unsigned int optlen = sizeof (sendbuf_size);
1250  struct sockaddr_storage sockaddr;
1251  int addrlen;
1252 
1253  fd = socket (member->family, SOCK_DGRAM, 0);
1254  if (fd == -1) {
1255  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
1256  "Could not create socket for new member");
1257  return (-1);
1258  }
1259  totemip_nosigpipe (fd);
1260  res = fcntl (fd, F_SETFL, O_NONBLOCK);
1261  if (res == -1) {
1262  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
1263  "Could not set non-blocking operation on token socket");
1264  goto error_close_fd;
1265  }
1266 
1267  /*
1268  * These sockets are used to send multicast messages, so their buffers
1269  * should be large
1270  */
1271  sendbuf_size = MCAST_SOCKET_BUFFER_SIZE;
1272  res = setsockopt (fd, SOL_SOCKET, SO_SNDBUF,
1273  &sendbuf_size, optlen);
1274  if (res == -1) {
1275  LOGSYS_PERROR (errno, instance->totemudpu_log_level_notice,
1276  "Could not set sendbuf size");
1277  /*
1278  * Fail in setting sendbuf size is not fatal -> don't exit
1279  */
1280  }
1281 
1282  /*
1283  * Bind to sending interface
1284  */
1285  totemip_totemip_to_sockaddr_convert(&instance->my_id, 0, &sockaddr, &addrlen);
1286  res = bind (fd, (struct sockaddr *)&sockaddr, addrlen);
1287  if (res == -1) {
1288  LOGSYS_PERROR (errno, instance->totemudpu_log_level_warning,
1289  "bind token socket failed");
1290  goto error_close_fd;
1291  }
1292 
1293  return (fd);
1294 
1295 error_close_fd:
1296  close(fd);
1297  return (-1);
1298 }
1299 
1300 int totemudpu_iface_set (void *net_context,
1301  const struct totem_ip_address *local_addr,
1302  unsigned short ip_port,
1303  unsigned int iface_no)
1304 {
1305  /* Not supported */
1306  return (-1);
1307 }
1308 
1310  void *udpu_context,
1311  const struct totem_ip_address *local,
1312  const struct totem_ip_address *member,
1313  int ring_no)
1314 {
1315  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1316 
1317  struct totemudpu_member *new_member;
1318 
1319  new_member = malloc (sizeof (struct totemudpu_member));
1320  if (new_member == NULL) {
1321  return (-1);
1322  }
1323 
1324  memset(new_member, 0, sizeof(*new_member));
1325 
1326  log_printf (LOGSYS_LEVEL_NOTICE, "adding new UDPU member {%s}",
1328  qb_list_init (&new_member->list);
1329  qb_list_add_tail (&new_member->list, &instance->member_list);
1330  memcpy (&new_member->member, member, sizeof (struct totem_ip_address));
1331  new_member->fd = totemudpu_create_sending_socket(udpu_context, member);
1332  new_member->active = 1;
1333 
1334  return (0);
1335 }
1336 
1338  void *udpu_context,
1339  const struct totem_ip_address *token_target,
1340  int ring_no)
1341 {
1342  int found = 0;
1343  struct qb_list_head *list;
1344  struct totemudpu_member *member;
1345 
1346  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1347 
1348  /*
1349  * Find the member to remove and close its socket
1350  */
1351  qb_list_for_each(list, &(instance->member_list)) {
1352  member = qb_list_entry (list,
1353  struct totemudpu_member,
1354  list);
1355 
1356  if (totemip_compare (token_target, &member->member)==0) {
1358  "removing UDPU member {%s}",
1359  totemip_print(&member->member));
1360 
1361  if (member->fd > 0) {
1363  "Closing socket to: {%s}",
1364  totemip_print(&member->member));
1365  qb_loop_poll_del (instance->totemudpu_poll_handle,
1366  member->fd);
1367  close (member->fd);
1368  }
1369  found = 1;
1370  break;
1371  }
1372  }
1373 
1374  /*
1375  * Delete the member from the list
1376  */
1377  if (found) {
1378  qb_list_del (list);
1379  }
1380 
1381  instance = NULL;
1382  return (0);
1383 }
1384 
1386  void *udpu_context)
1387 {
1388  struct qb_list_head *list;
1389  struct totemudpu_member *member;
1390 
1391  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1392 
1393  qb_list_for_each(list, &(instance->member_list)) {
1394  member = qb_list_entry (list,
1395  struct totemudpu_member,
1396  list);
1397 
1398  if (member->fd > 0) {
1399  close (member->fd);
1400  }
1401 
1402  member->fd = totemudpu_create_sending_socket(udpu_context, &member->member);
1403  }
1404 
1405  return (0);
1406 }
1407 
1408 
1409 static void timer_function_merge_detect_timeout (
1410  void *data)
1411 {
1412  struct totemudpu_instance *instance = (struct totemudpu_instance *)data;
1413 
1414  if (instance->merge_detect_messages_sent_before_timeout == 0) {
1415  instance->send_merge_detect_message = 1;
1416  }
1417 
1419 
1420  totemudpu_start_merge_detect_timeout(instance);
1421 }
1422 
1423 static void totemudpu_start_merge_detect_timeout(
1424  void *udpu_context)
1425 {
1426  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1427 
1428  qb_loop_timer_add(instance->totemudpu_poll_handle,
1429  QB_LOOP_MED,
1430  instance->totem_config->merge_timeout * 2 * QB_TIME_NS_IN_MSEC,
1431  (void *)instance,
1432  timer_function_merge_detect_timeout,
1433  &instance->timer_merge_detect_timeout);
1434 
1435 }
1436 
1437 static void totemudpu_stop_merge_detect_timeout(
1438  void *udpu_context)
1439 {
1440  struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
1441 
1442  qb_loop_timer_del(instance->totemudpu_poll_handle,
1443  instance->timer_merge_detect_timeout);
1444 }
1445 
1447  void *udpu_context,
1448  struct totem_config *totem_config)
1449 {
1450  /* Not supported */
1451  return (-1);
1452 }
#define INTERFACE_MAX
Definition: coroapi.h:88
unsigned int nodeid
Definition: coroapi.h:0
#define PROCESSOR_COUNT_MAX
Definition: coroapi.h:96
@ COROSYNC_DONE_FATAL_ERR
Definition: exec/util.h:55
#define LOGSYS_LEVEL_NOTICE
Definition: logsys.h:74
#define LOGSYS_LEVEL_DEBUG
Definition: logsys.h:76
unsigned int node_id
Definition: totem.h:167
struct totem_logging_configuration totem_logging_configuration
Definition: totem.h:207
unsigned int downcheck_timeout
Definition: totem.h:199
struct totem_interface * interfaces
Definition: totem.h:165
unsigned int clear_node_high_bit
Definition: totem.h:168
unsigned int merge_timeout
Definition: totem.h:197
unsigned int net_mtu
Definition: totem.h:209
unsigned int block_unlisted_ips
Definition: totem.h:245
struct totem_ip_address boundto
Definition: totem.h:84
uint16_t ip_port
Definition: totem.h:87
struct totem_ip_address bindnet
Definition: totem.h:83
The totem_ip_address struct.
Definition: coroapi.h:111
unsigned int nodeid
Definition: coroapi.h:112
unsigned short family
Definition: coroapi.h:113
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:101
uint8_t reachable
Definition: totem.h:265
unsigned int nodeid
Definition: totem.h:264
struct knet_link_status link_status[KNET_MAX_LINK]
Definition: totem.h:271
struct totem_config * totem_config
Definition: totemudpu.c:168
int local_loop_sock[2]
Definition: totemudpu.c:176
qb_loop_t * totemudpu_poll_handle
Definition: totemudpu.c:93
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
void(* totemudpu_deliver_fn)(void *context, const void *msg, unsigned int msg_len, const struct sockaddr_storage *system_from)
Definition: totemudpu.c:103
struct totem_ip_address my_id
Definition: totemudpu.c:160
int totemudpu_log_level_notice
Definition: totemudpu.c:125
qb_loop_timer_handle timer_netif_check_timeout
Definition: totemudpu.c:164
qb_loop_timer_handle timer_merge_detect_timeout
Definition: totemudpu.c:178
unsigned int my_memb_entries
Definition: totemudpu.c:166
int totemudpu_log_level_security
Definition: totemudpu.c:119
struct totem_ip_address token_target
Definition: totemudpu.c:172
unsigned int merge_detect_messages_sent_before_timeout
Definition: totemudpu.c:182
int send_merge_detect_message
Definition: totemudpu.c:180
struct timeval stats_tv_start
Definition: totemudpu.c:158
totemsrp_stats_t * stats
Definition: totemudpu.c:170
int totemudpu_log_level_warning
Definition: totemudpu.c:123
char iov_buffer[UDP_RECEIVE_FRAME_SIZE_MAX]
Definition: totemudpu.c:142
struct iovec totemudpu_iov_recv
Definition: totemudpu.c:144
struct totem_interface * totem_interface
Definition: totemudpu.c:95
int totemudpu_log_level_debug
Definition: totemudpu.c:127
int totemudpu_log_level_error
Definition: totemudpu.c:121
void(* totemudpu_target_set_completed)(void *context)
Definition: totemudpu.c:114
struct qb_list_head member_list
Definition: totemudpu.c:146
void(*) void udpu_context)
Definition: totemudpu.c:138
void(* totemudpu_iface_change_fn)(void *context, const struct totem_ip_address *iface_address, unsigned int ring_no)
Definition: totemudpu.c:109
struct totem_ip_address member
Definition: totemudpu.c:87
struct qb_list_head list
Definition: totemudpu.c:86
struct totemudpu_instance * instance
Definition: totemudpu.c:188
const void * msg
Definition: totemknet.c:190
unsigned int msg_len
Definition: totemknet.c:191
typedef __attribute__
#define FRAME_SIZE_MAX
Definition: totem.h:52
#define BIND_RETRIES_INTERVAL
Definition: totem.h:71
#define BIND_MAX_RETRIES
Definition: totem.h:70
#define UDP_RECEIVE_FRAME_SIZE_MAX
Definition: totem.h:62
int totemip_sa_equal(const struct totem_ip_address *totem_ip, const struct sockaddr *sa)
Definition: totemip.c:95
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:529
#define totemip_nosigpipe(s)
Definition: totemip.h:56
void totemip_copy(struct totem_ip_address *addr1, const struct totem_ip_address *addr2)
Definition: totemip.c:123
size_t totemip_udpip_header_size(int family)
Definition: totemip.c:608
int totemip_compare(const void *a, const void *b)
Definition: totemip.c:150
int totemip_totemip_to_sockaddr_convert(struct totem_ip_address *ip_addr, uint16_t port, struct sockaddr_storage *saddr, int *addrlen)
Definition: totemip.c:264
const char * totemip_sa_print(const struct sockaddr *sa)
Definition: totemip.c:234
const char * totemip_print(const struct totem_ip_address *addr)
Definition: totemip.c:256
struct srp_addr system_from
Definition: totemsrp.c:1
void totemudpu_buffer_release(void *ptr)
Definition: totemudpu.c:1053
int totemudpu_ifaces_get(void *net_context, char ***status, unsigned int *iface_count)
Definition: totemudpu.c:824
#define NETIF_STATE_REPORT_UP
Definition: totemudpu.c:78
#define log_printf(level, format, args...)
Definition: totemudpu.c:227
int totemudpu_send_flush(void *udpu_context)
Definition: totemudpu.c:1087
int totemudpu_token_target_set(void *udpu_context, unsigned int nodeid)
Definition: totemudpu.c:1148
#define BIND_STATE_LOOPBACK
Definition: totemudpu.c:83
#define NETIF_STATE_REPORT_DOWN
Definition: totemudpu.c:79
int totemudpu_member_list_rebind_ip(void *udpu_context)
Definition: totemudpu.c:1385
int totemudpu_recv_mcast_empty(void *udpu_context)
Definition: totemudpu.c:1174
int totemudpu_processor_count_set(void *udpu_context, int processor_count)
Definition: totemudpu.c:1058
int totemudpu_token_send(void *udpu_context, const void *msg, unsigned int msg_len)
Definition: totemudpu.c:1094
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:1300
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:952
int totemudpu_crypto_set(void *udpu_context, const char *cipher_type, const char *hash_type)
Definition: totemudpu.c:244
#define MCAST_SOCKET_BUFFER_SIZE
Definition: totemudpu.c:77
int totemudpu_recv_flush(void *udpu_context)
Definition: totemudpu.c:1080
int totemudpu_mcast_noflush_send(void *udpu_context, const void *msg, unsigned int msg_len)
Definition: totemudpu.c:1119
int totemudpu_member_remove(void *udpu_context, const struct totem_ip_address *token_target, int ring_no)
Definition: totemudpu.c:1337
int totemudpu_finalize(void *udpu_context)
Definition: totemudpu.c:423
#define MSG_NOSIGNAL
Definition: totemudpu.c:74
int totemudpu_mcast_flush_send(void *udpu_context, const void *msg, unsigned int msg_len)
Definition: totemudpu.c:1106
int totemudpu_iface_check(void *udpu_context)
Definition: totemudpu.c:1132
void * totemudpu_buffer_alloc(void)
Definition: totemudpu.c:1048
int totemudpu_reconfigure(void *udpu_context, struct totem_config *totem_config)
Definition: totemudpu.c:1446
#define LOGSYS_PERROR(err_num, level, fmt, args...)
Definition: totemudpu.c:234
#define BIND_STATE_UNBOUND
Definition: totemudpu.c:81
#define BIND_STATE_REGULAR
Definition: totemudpu.c:82
void totemudpu_net_mtu_adjust(void *udpu_context, struct totem_config *totem_config)
Definition: totemudpu.c:1142
int totemudpu_nodestatus_get(void *udpu_context, unsigned int nodeid, struct totem_node_status *node_status)
Definition: totemudpu.c:796
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:1309