corosync 3.1.10
totemudp.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 <pthread.h>
40#include <sys/mman.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <sys/socket.h>
44#include <netdb.h>
45#include <sys/un.h>
46#include <sys/ioctl.h>
47#include <sys/param.h>
48#include <netinet/in.h>
49#include <arpa/inet.h>
50#include <unistd.h>
51#include <fcntl.h>
52#include <stdlib.h>
53#include <stdio.h>
54#include <errno.h>
55#include <sched.h>
56#include <time.h>
57#include <sys/time.h>
58#include <sys/poll.h>
59#include <sys/uio.h>
60#include <limits.h>
61
62#include <corosync/sq.h>
63#include <corosync/swab.h>
64#include <qb/qbdefs.h>
65#include <qb/qbloop.h>
66#define LOGSYS_UTILS_ONLY 1
67#include <corosync/logsys.h>
68#include "totemudp.h"
69
70#include "util.h"
71
72#ifndef MSG_NOSIGNAL
73#define MSG_NOSIGNAL 0
74#endif
75
76#define MCAST_SOCKET_BUFFER_SIZE (TRANSMITS_ALLOWED * FRAME_SIZE_MAX)
77#define NETIF_STATE_REPORT_UP 1
78#define NETIF_STATE_REPORT_DOWN 2
79
80#define BIND_STATE_UNBOUND 0
81#define BIND_STATE_REGULAR 1
82#define BIND_STATE_LOOPBACK 2
83
85 struct qb_list_head list;
87};
88
92 int token;
93 /*
94 * Socket used for local multicast delivery. We don't rely on multicast
95 * loop and rather this UNIX DGRAM socket is used. Socket is created by
96 * socketpair call and they are used in same way as pipe (so [0] is read
97 * end and [1] is write end)
98 */
100};
101
104
106
108
110
111 void *context;
112
114 void *context,
115 const void *msg,
116 unsigned int msg_len,
117 const struct sockaddr_storage *system_from);
118
120 void *context,
121 const struct totem_ip_address *iface_address,
122 unsigned int ring_no);
123
125
126 /*
127 * Function and data used to log messages
128 */
130
132
134
136
138
140
142 int level,
143 int subsys,
144 const char *function,
145 const char *file,
146 int line,
147 const char *format,
148 ...)__attribute__((format(printf, 6, 7)));
149
151
152 struct qb_list_head member_list;
153
155
157
158 struct iovec totemudp_iov_recv;
159
161
163
165
167
169
171
173
175
176 struct timeval stats_tv_start;
177
179
181
182 qb_loop_timer_handle timer_netif_check_timeout;
183
184 unsigned int my_memb_entries;
185
187
189
191
193};
194
195struct work_item {
196 const void *msg;
197 unsigned int msg_len;
199};
200
201static int totemudp_build_sockets (
202 struct totemudp_instance *instance,
203 struct totem_ip_address *bindnet_address,
204 struct totem_ip_address *mcastaddress,
205 struct totemudp_socket *sockets,
206 struct totem_ip_address *bound_to);
207
208static struct totem_ip_address localhost;
209
210static void totemudp_instance_initialize (struct totemudp_instance *instance)
211{
212 memset (instance, 0, sizeof (struct totemudp_instance));
213
215
216 instance->totemudp_iov_recv.iov_base = instance->iov_buffer;
217
218 instance->totemudp_iov_recv.iov_len = UDP_RECEIVE_FRAME_SIZE_MAX + 1; //sizeof (instance->iov_buffer) + 1;
219 instance->totemudp_iov_recv_flush.iov_base = instance->iov_buffer_flush;
220
221 instance->totemudp_iov_recv_flush.iov_len = UDP_RECEIVE_FRAME_SIZE_MAX + 1; //sizeof (instance->iov_buffer) + 1;
222
223 /*
224 * There is always atleast 1 processor
225 */
226 instance->my_memb_entries = 1;
227
228 qb_list_init (&instance->member_list);
229}
230
231#define log_printf(level, format, args...) \
232do { \
233 instance->totemudp_log_printf ( \
234 level, instance->totemudp_subsys_id, \
235 __FUNCTION__, __FILE__, __LINE__, \
236 (const char *)format, ##args); \
237} while (0);
238
239#define LOGSYS_PERROR(err_num, level, fmt, args...) \
240do { \
241 char _error_str[LOGSYS_MAX_PERROR_MSG_LEN]; \
242 const char *_error_ptr = qb_strerror_r(err_num, _error_str, sizeof(_error_str)); \
243 instance->totemudp_log_printf ( \
244 level, instance->totemudp_subsys_id, \
245 __FUNCTION__, __FILE__, __LINE__, \
246 fmt ": %s (%d)\n", ##args, _error_ptr, err_num); \
247 } while(0)
248
250 void *udp_context,
251 const char *cipher_type,
252 const char *hash_type)
253{
254
255 return (0);
256}
257
258
259static inline void ucast_sendmsg (
260 struct totemudp_instance *instance,
261 struct totem_ip_address *system_to,
262 const void *msg,
263 unsigned int msg_len)
264{
265 struct msghdr msg_ucast;
266 int res = 0;
267 struct sockaddr_storage sockaddr;
268 struct iovec iovec;
269 int addrlen;
270
271 iovec.iov_base = (void*)msg;
272 iovec.iov_len = msg_len;
273
274 /*
275 * Build unicast message
276 */
277 memset(&msg_ucast, 0, sizeof(msg_ucast));
279 instance->totem_interface->ip_port, &sockaddr, &addrlen);
280 msg_ucast.msg_name = &sockaddr;
281 msg_ucast.msg_namelen = addrlen;
282 msg_ucast.msg_iov = (void *)&iovec;
283 msg_ucast.msg_iovlen = 1;
284
285 /*
286 * Transmit unicast message
287 * An error here is recovered by totemsrp
288 */
289 res = sendmsg (instance->totemudp_sockets.mcast_send, &msg_ucast,
291 if (res < 0) {
292 LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
293 "sendmsg(ucast) failed (non-critical)");
294 }
295}
296
297static inline void mcast_sendmsg (
298 struct totemudp_instance *instance,
299 const void *msg,
300 unsigned int msg_len)
301{
302 struct msghdr msg_mcast;
303 int res = 0;
304 struct iovec iovec;
305 struct sockaddr_storage sockaddr;
306 int addrlen;
307
308 iovec.iov_base = (void *)msg;
309 iovec.iov_len = msg_len;
310
311 /*
312 * Build multicast message
313 */
315 instance->totem_interface->ip_port, &sockaddr, &addrlen);
316 memset(&msg_mcast, 0, sizeof(msg_mcast));
317 msg_mcast.msg_name = &sockaddr;
318 msg_mcast.msg_namelen = addrlen;
319 msg_mcast.msg_iov = (void *)&iovec;
320 msg_mcast.msg_iovlen = 1;
321
322 /*
323 * Transmit multicast message
324 * An error here is recovered by totemsrp
325 */
326 res = sendmsg (instance->totemudp_sockets.mcast_send, &msg_mcast,
328 if (res < 0) {
329 LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
330 "sendmsg(mcast) failed (non-critical)");
332 } else {
333 instance->stats->continuous_sendmsg_failures = 0;
334 }
335
336 /*
337 * Transmit multicast message to local unix mcast loop
338 * An error here is recovered by totemsrp
339 */
340 msg_mcast.msg_name = NULL;
341 msg_mcast.msg_namelen = 0;
342
343 res = sendmsg (instance->totemudp_sockets.local_mcast_loop[1], &msg_mcast,
345 if (res < 0) {
346 LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
347 "sendmsg(local mcast loop) failed (non-critical)");
348 }
349}
350
351
353 void *udp_context)
354{
355 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
356 int res = 0;
357
358 if (instance->totemudp_sockets.mcast_recv > 0) {
359 qb_loop_poll_del (instance->totemudp_poll_handle,
360 instance->totemudp_sockets.mcast_recv);
361 close (instance->totemudp_sockets.mcast_recv);
362 }
363 if (instance->totemudp_sockets.mcast_send > 0) {
364 close (instance->totemudp_sockets.mcast_send);
365 }
366 if (instance->totemudp_sockets.local_mcast_loop[0] > 0) {
367 qb_loop_poll_del (instance->totemudp_poll_handle,
369 close (instance->totemudp_sockets.local_mcast_loop[0]);
370 close (instance->totemudp_sockets.local_mcast_loop[1]);
371 }
372 if (instance->totemudp_sockets.token > 0) {
373 qb_loop_poll_del (instance->totemudp_poll_handle,
374 instance->totemudp_sockets.token);
375 close (instance->totemudp_sockets.token);
376 }
377
378 return (res);
379}
380
381/*
382 * Only designed to work with a message with one iov
383 */
384
385static int net_deliver_fn (
386 int fd,
387 int revents,
388 void *data)
389{
390 struct totemudp_instance *instance = (struct totemudp_instance *)data;
391 struct msghdr msg_recv;
392 struct iovec *iovec;
393 struct sockaddr_storage system_from;
394 int bytes_received;
395
396 if (instance->flushing == 1) {
397 iovec = &instance->totemudp_iov_recv_flush;
398 } else {
399 iovec = &instance->totemudp_iov_recv;
400 }
401
402 /*
403 * Receive datagram
404 */
405 memset(&msg_recv, 0, sizeof(msg_recv));
406 msg_recv.msg_name = &system_from;
407 msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
408 msg_recv.msg_iov = iovec;
409 msg_recv.msg_iovlen = 1;
410
411 bytes_received = recvmsg (fd, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
412 if (bytes_received == -1) {
413 return (0);
414 } else {
415 instance->stats_recv += bytes_received;
416 }
417
418 if (bytes_received >= UDP_RECEIVE_FRAME_SIZE_MAX + 1) {
419 /*
420 * Maximum packet size should be UDP_RECEIVE_FRAME_SIZE_MAX.
421 * If received packet is UDP_RECEIVE_FRAME_SIZE_MAX + 1 it means packet was truncated
422 * (iov_buffer size and iov_len are intentionally set to UDP_RECEIVE_FRAME_SIZE_MAX + 1).
423 */
425 "Received too big message. This may be because something bad is happening "
426 "on the network (attack?), or you tried join more nodes than corosync is "
427 "compiled with (%u) or bug in the code (bad estimation of "
428 "the UDP_RECEIVE_FRAME_SIZE_MAX). Dropping packet.", PROCESSOR_COUNT_MAX);
429 return (0);
430 }
431
432 iovec->iov_len = bytes_received;
433
434 /*
435 * Handle incoming message
436 */
437 instance->totemudp_deliver_fn (
438 instance->context,
439 iovec->iov_base,
440 iovec->iov_len,
441 &system_from);
442
443 iovec->iov_len = UDP_RECEIVE_FRAME_SIZE_MAX + 1;
444 return (0);
445}
446
447static int netif_determine (
448 struct totemudp_instance *instance,
449 struct totem_ip_address *bindnet,
450 struct totem_ip_address *bound_to,
451 int *interface_up,
452 int *interface_num)
453{
454 int res;
455
456 res = totemip_iface_check (bindnet, bound_to,
457 interface_up, interface_num,
459
460
461 return (res);
462}
463
464
465/*
466 * If the interface is up, the sockets for totem are built. If the interface is down
467 * this function is requeued in the timer list to retry building the sockets later.
468 */
469static void timer_function_netif_check_timeout (
470 void *data)
471{
472 struct totemudp_instance *instance = (struct totemudp_instance *)data;
473 int interface_up;
474 int interface_num;
475 struct totem_ip_address *bind_address;
476
477 /*
478 * Build sockets for every interface
479 */
480 netif_determine (instance,
481 &instance->totem_interface->bindnet,
482 &instance->totem_interface->boundto,
483 &interface_up, &interface_num);
484 /*
485 * If the network interface isn't back up and we are already
486 * in loopback mode, add timer to check again and return
487 */
488 if ((instance->netif_bind_state == BIND_STATE_LOOPBACK &&
489 interface_up == 0) ||
490
491 (instance->my_memb_entries == 1 &&
493 interface_up == 1)) {
494
495 qb_loop_timer_add (instance->totemudp_poll_handle,
496 QB_LOOP_MED,
497 instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
498 (void *)instance,
499 timer_function_netif_check_timeout,
500 &instance->timer_netif_check_timeout);
501
502 /*
503 * Add a timer to check for a downed regular interface
504 */
505 return;
506 }
507
508 if (instance->totemudp_sockets.mcast_recv > 0) {
509 qb_loop_poll_del (instance->totemudp_poll_handle,
510 instance->totemudp_sockets.mcast_recv);
511 close (instance->totemudp_sockets.mcast_recv);
512 }
513 if (instance->totemudp_sockets.mcast_send > 0) {
514 close (instance->totemudp_sockets.mcast_send);
515 }
516 if (instance->totemudp_sockets.local_mcast_loop[0] > 0) {
517 qb_loop_poll_del (instance->totemudp_poll_handle,
519 close (instance->totemudp_sockets.local_mcast_loop[0]);
520 close (instance->totemudp_sockets.local_mcast_loop[1]);
521 }
522 if (instance->totemudp_sockets.token > 0) {
523 qb_loop_poll_del (instance->totemudp_poll_handle,
524 instance->totemudp_sockets.token);
525 close (instance->totemudp_sockets.token);
526 }
527
528 if (interface_up == 0) {
529 /*
530 * Interface is not up
531 */
533 bind_address = &localhost;
534
535 /*
536 * Add a timer to retry building interfaces and request memb_gather_enter
537 */
538 qb_loop_timer_add (instance->totemudp_poll_handle,
539 QB_LOOP_MED,
540 instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
541 (void *)instance,
542 timer_function_netif_check_timeout,
543 &instance->timer_netif_check_timeout);
544 } else {
545 /*
546 * Interface is up
547 */
549 bind_address = &instance->totem_interface->bindnet;
550 }
551 /*
552 * Create and bind the multicast and unicast sockets
553 */
554 (void)totemudp_build_sockets (instance,
555 &instance->mcast_address,
556 bind_address,
557 &instance->totemudp_sockets,
558 &instance->totem_interface->boundto);
559
560 qb_loop_poll_add (
561 instance->totemudp_poll_handle,
562 QB_LOOP_MED,
564 POLLIN, instance, net_deliver_fn);
565
566 qb_loop_poll_add (
567 instance->totemudp_poll_handle,
568 QB_LOOP_MED,
570 POLLIN, instance, net_deliver_fn);
571
572 qb_loop_poll_add (
573 instance->totemudp_poll_handle,
574 QB_LOOP_MED,
575 instance->totemudp_sockets.token,
576 POLLIN, instance, net_deliver_fn);
577
578 totemip_copy (&instance->my_id, &instance->totem_interface->boundto);
579
580 /*
581 * This reports changes in the interface to the user and totemsrp
582 */
583 if (instance->netif_bind_state == BIND_STATE_REGULAR) {
586 "The network interface [%s] is now up.",
589 instance->totemudp_iface_change_fn (instance->context, &instance->my_id, 0);
590 }
591 /*
592 * Add a timer to check for interface going down in single membership
593 */
594 if (instance->my_memb_entries == 1) {
595 qb_loop_timer_add (instance->totemudp_poll_handle,
596 QB_LOOP_MED,
597 instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
598 (void *)instance,
599 timer_function_netif_check_timeout,
600 &instance->timer_netif_check_timeout);
601 }
602
603 } else {
606 "The network interface is down.");
607 instance->totemudp_iface_change_fn (instance->context, &instance->my_id, 0);
608 }
610
611 }
612}
613
614/* Set the socket priority to INTERACTIVE to ensure
615 that our messages don't get queued behind anything else */
616static void totemudp_traffic_control_set(struct totemudp_instance *instance, int sock)
617{
618#ifdef SO_PRIORITY
619 int prio = 6; /* TC_PRIO_INTERACTIVE */
620
621 if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(int))) {
622 LOGSYS_PERROR (errno, instance->totemudp_log_level_warning, "Could not set traffic priority");
623 }
624#endif
625}
626
627static int totemudp_build_sockets_ip (
628 struct totemudp_instance *instance,
629 struct totem_ip_address *mcast_address,
630 struct totem_ip_address *bindnet_address,
631 struct totemudp_socket *sockets,
632 struct totem_ip_address *bound_to,
633 int interface_num)
634{
635 struct sockaddr_storage sockaddr;
636 struct ipv6_mreq mreq6;
637 struct ip_mreq mreq;
638 struct sockaddr_storage mcast_ss, boundto_ss;
639 struct sockaddr_in6 *mcast_sin6 = (struct sockaddr_in6 *)&mcast_ss;
640 struct sockaddr_in *mcast_sin = (struct sockaddr_in *)&mcast_ss;
641 struct sockaddr_in *boundto_sin = (struct sockaddr_in *)&boundto_ss;
642 unsigned int sendbuf_size;
643 unsigned int recvbuf_size;
644 unsigned int optlen = sizeof (sendbuf_size);
645 unsigned int retries;
646 int addrlen;
647 int res;
648 int flag;
649 uint8_t sflag;
650 int i;
651
652 /*
653 * Create multicast recv socket
654 */
655 sockets->mcast_recv = socket (bindnet_address->family, SOCK_DGRAM, 0);
656 if (sockets->mcast_recv == -1) {
658 "socket() failed");
659 return (-1);
660 }
661
662 totemip_nosigpipe (sockets->mcast_recv);
663 res = fcntl (sockets->mcast_recv, F_SETFL, O_NONBLOCK);
664 if (res == -1) {
666 "Could not set non-blocking operation on multicast socket");
667 return (-1);
668 }
669
670 /*
671 * Force reuse
672 */
673 flag = 1;
674 if ( setsockopt(sockets->mcast_recv, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
676 "setsockopt(SO_REUSEADDR) failed");
677 return (-1);
678 }
679
680 /*
681 * Create local multicast loop socket
682 */
683 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets->local_mcast_loop) == -1) {
685 "socket() failed");
686 return (-1);
687 }
688
689 for (i = 0; i < 2; i++) {
691 res = fcntl (sockets->local_mcast_loop[i], F_SETFL, O_NONBLOCK);
692 if (res == -1) {
694 "Could not set non-blocking operation on multicast socket");
695 return (-1);
696 }
697 }
698
699
700
701 /*
702 * Setup mcast send socket
703 */
704 sockets->mcast_send = socket (bindnet_address->family, SOCK_DGRAM, 0);
705 if (sockets->mcast_send == -1) {
707 "socket() failed");
708 return (-1);
709 }
710
711 totemip_nosigpipe (sockets->mcast_send);
712 res = fcntl (sockets->mcast_send, F_SETFL, O_NONBLOCK);
713 if (res == -1) {
715 "Could not set non-blocking operation on multicast socket");
716 return (-1);
717 }
718
719 /*
720 * Force reuse
721 */
722 flag = 1;
723 if ( setsockopt(sockets->mcast_send, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
725 "setsockopt(SO_REUSEADDR) failed");
726 return (-1);
727 }
728
729 res = set_socket_dscp(sockets->mcast_send,
730 instance->totem_config->ip_dscp);
731 if (res == -1) {
733 "Could not set IP_TOS bits");
734 return (-1);
735 }
736
738 &sockaddr, &addrlen);
739
740 retries = 0;
741 while (1) {
742 res = bind (sockets->mcast_send, (struct sockaddr *)&sockaddr, addrlen);
743 if (res == 0) {
744 break;
745 }
747 "Unable to bind the socket to send multicast packets");
748 if (++retries > BIND_MAX_RETRIES) {
749 break;
750 }
751
752 /*
753 * Wait for a while
754 */
755 (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
756 }
757 if (res == -1) {
758 return (-1);
759 }
760
761 /*
762 * Setup unicast socket
763 */
764 sockets->token = socket (bindnet_address->family, SOCK_DGRAM, 0);
765 if (sockets->token == -1) {
767 "socket() failed");
768 return (-1);
769 }
770
771 totemip_nosigpipe (sockets->token);
772 res = fcntl (sockets->token, F_SETFL, O_NONBLOCK);
773 if (res == -1) {
775 "Could not set non-blocking operation on token socket");
776 return (-1);
777 }
778
779 /*
780 * Force reuse
781 */
782 flag = 1;
783 if ( setsockopt(sockets->token, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
785 "setsockopt(SO_REUSEADDR) failed");
786 return (-1);
787 }
788
789 res = set_socket_dscp(sockets->token, instance->totem_config->ip_dscp);
790 if (res == -1) {
792 "Could not set IP_TOS bits");
793 return (-1);
794 }
795
796 /*
797 * Bind to unicast socket used for token send/receives
798 * This has the side effect of binding to the correct interface
799 */
800 totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &sockaddr, &addrlen);
801
802 retries = 0;
803 while (1) {
804 res = bind (sockets->token, (struct sockaddr *)&sockaddr, addrlen);
805 if (res == 0) {
806 break;
807 }
809 "Unable to bind UDP unicast socket");
810 if (++retries > BIND_MAX_RETRIES) {
811 break;
812 }
813
814 /*
815 * Wait for a while
816 */
817 (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
818 }
819 if (res == -1) {
820 return (-1);
821 }
822
823 recvbuf_size = MCAST_SOCKET_BUFFER_SIZE;
824 sendbuf_size = MCAST_SOCKET_BUFFER_SIZE;
825 /*
826 * Set buffer sizes to avoid overruns
827 */
828 res = setsockopt (sockets->mcast_recv, SOL_SOCKET, SO_RCVBUF, &recvbuf_size, optlen);
829 if (res == -1) {
830 LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
831 "Unable to set SO_RCVBUF size on UDP mcast socket");
832 return (-1);
833 }
834 res = setsockopt (sockets->mcast_send, SOL_SOCKET, SO_SNDBUF, &sendbuf_size, optlen);
835 if (res == -1) {
836 LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
837 "Unable to set SO_SNDBUF size on UDP mcast socket");
838 return (-1);
839 }
840 res = setsockopt (sockets->local_mcast_loop[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, optlen);
841 if (res == -1) {
842 LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
843 "Unable to set SO_RCVBUF size on UDP local mcast loop socket");
844 return (-1);
845 }
846 res = setsockopt (sockets->local_mcast_loop[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, optlen);
847 if (res == -1) {
848 LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
849 "Unable to set SO_SNDBUF size on UDP local mcast loop socket");
850 return (-1);
851 }
852
853 res = getsockopt (sockets->mcast_recv, SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
854 if (res == 0) {
856 "Receive multicast socket recv buffer size (%d bytes).", recvbuf_size);
857 }
858
859 res = getsockopt (sockets->mcast_send, SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
860 if (res == 0) {
862 "Transmit multicast socket send buffer size (%d bytes).", sendbuf_size);
863 }
864
865 res = getsockopt (sockets->local_mcast_loop[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
866 if (res == 0) {
868 "Local receive multicast loop socket recv buffer size (%d bytes).", recvbuf_size);
869 }
870
871 res = getsockopt (sockets->local_mcast_loop[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
872 if (res == 0) {
874 "Local transmit multicast loop socket send buffer size (%d bytes).", sendbuf_size);
875 }
876
877
878 /*
879 * Join group membership on socket
880 */
881 totemip_totemip_to_sockaddr_convert(mcast_address, instance->totem_interface->ip_port, &mcast_ss, &addrlen);
882 totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &boundto_ss, &addrlen);
883
884 if (instance->totem_config->broadcast_use == 1) {
885 unsigned int broadcast = 1;
886
887 if ((setsockopt(sockets->mcast_recv, SOL_SOCKET,
888 SO_BROADCAST, &broadcast, sizeof (broadcast))) == -1) {
890 "setting broadcast option failed");
891 return (-1);
892 }
893 if ((setsockopt(sockets->mcast_send, SOL_SOCKET,
894 SO_BROADCAST, &broadcast, sizeof (broadcast))) == -1) {
896 "setting broadcast option failed");
897 return (-1);
898 }
899 } else {
900 switch (bindnet_address->family) {
901 case AF_INET:
902 memset(&mreq, 0, sizeof(mreq));
903 mreq.imr_multiaddr.s_addr = mcast_sin->sin_addr.s_addr;
904 mreq.imr_interface.s_addr = boundto_sin->sin_addr.s_addr;
905 res = setsockopt (sockets->mcast_recv, IPPROTO_IP, IP_ADD_MEMBERSHIP,
906 &mreq, sizeof (mreq));
907 if (res == -1) {
909 "join ipv4 multicast group failed");
910 return (-1);
911 }
912 break;
913 case AF_INET6:
914 memset(&mreq6, 0, sizeof(mreq6));
915 memcpy(&mreq6.ipv6mr_multiaddr, &mcast_sin6->sin6_addr, sizeof(struct in6_addr));
916 mreq6.ipv6mr_interface = interface_num;
917
918 res = setsockopt (sockets->mcast_recv, IPPROTO_IPV6, IPV6_JOIN_GROUP,
919 &mreq6, sizeof (mreq6));
920 if (res == -1) {
922 "join ipv6 multicast group failed");
923 return (-1);
924 }
925 break;
926 }
927 }
928
929 /*
930 * Turn off multicast loopback
931 */
932
933 flag = 0;
934 switch ( bindnet_address->family ) {
935 case AF_INET:
936 sflag = 0;
937 res = setsockopt (sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_LOOP,
938 &sflag, sizeof (sflag));
939 break;
940 case AF_INET6:
941 res = setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
942 &flag, sizeof (flag));
943 }
944 if (res == -1) {
946 "Unable to turn off multicast loopback");
947 return (-1);
948 }
949
950 /*
951 * Set multicast packets TTL
952 */
953 flag = instance->totem_interface->ttl;
954 if (bindnet_address->family == AF_INET6) {
955 res = setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
956 &flag, sizeof (flag));
957 if (res == -1) {
959 "set mcast v6 TTL failed");
960 return (-1);
961 }
962 } else {
963 sflag = flag;
964 res = setsockopt(sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_TTL,
965 &sflag, sizeof(sflag));
966 if (res == -1) {
968 "set mcast v4 TTL failed");
969 return (-1);
970 }
971 }
972
973 /*
974 * Bind to a specific interface for multicast send and receive
975 */
976 switch ( bindnet_address->family ) {
977 case AF_INET:
978 if (setsockopt (sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_IF,
979 &boundto_sin->sin_addr, sizeof (boundto_sin->sin_addr)) < 0) {
981 "cannot select interface for multicast packets (send)");
982 return (-1);
983 }
984 if (setsockopt (sockets->mcast_recv, IPPROTO_IP, IP_MULTICAST_IF,
985 &boundto_sin->sin_addr, sizeof (boundto_sin->sin_addr)) < 0) {
987 "cannot select interface for multicast packets (recv)");
988 return (-1);
989 }
990 break;
991 case AF_INET6:
992 if (setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_IF,
993 &interface_num, sizeof (interface_num)) < 0) {
995 "cannot select interface for multicast packets (send v6)");
996 return (-1);
997 }
998 if (setsockopt (sockets->mcast_recv, IPPROTO_IPV6, IPV6_MULTICAST_IF,
999 &interface_num, sizeof (interface_num)) < 0) {
1000 LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1001 "cannot select interface for multicast packets (recv v6)");
1002 return (-1);
1003 }
1004 break;
1005 }
1006
1007 /*
1008 * Bind to multicast socket used for multicast receives
1009 * This needs to happen after all of the multicast setsockopt() calls
1010 * as the kernel seems to only put them into effect (for IPV6) when bind()
1011 * is called.
1012 */
1014 instance->totem_interface->ip_port, &sockaddr, &addrlen);
1015
1016 retries = 0;
1017 while (1) {
1018 res = bind (sockets->mcast_recv, (struct sockaddr *)&sockaddr, addrlen);
1019 if (res == 0) {
1020 break;
1021 }
1022 LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
1023 "Unable to bind the socket to receive multicast packets");
1024 if (++retries > BIND_MAX_RETRIES) {
1025 break;
1026 }
1027
1028 /*
1029 * Wait for a while
1030 */
1031 (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
1032 }
1033
1034 if (res == -1) {
1035 return (-1);
1036 }
1037 return 0;
1038}
1039
1040static int totemudp_build_sockets (
1041 struct totemudp_instance *instance,
1042 struct totem_ip_address *mcast_address,
1043 struct totem_ip_address *bindnet_address,
1044 struct totemudp_socket *sockets,
1045 struct totem_ip_address *bound_to)
1046{
1047 int interface_num;
1048 int interface_up;
1049 int res;
1050
1051 /*
1052 * Determine the ip address bound to and the interface name
1053 */
1054 res = netif_determine (instance,
1055 bindnet_address,
1056 bound_to,
1057 &interface_up,
1058 &interface_num);
1059
1060 if (res == -1) {
1061 return (-1);
1062 }
1063
1064 totemip_copy(&instance->my_id, bound_to);
1065
1066 res = totemudp_build_sockets_ip (instance, mcast_address,
1067 bindnet_address, sockets, bound_to, interface_num);
1068
1069 if (res == -1) {
1070 /* if we get here, corosync won't work anyway, so better leaving than faking to work */
1071 LOGSYS_PERROR (errno, instance->totemudp_log_level_error,
1072 "Unable to create sockets, exiting");
1073 exit(EXIT_FAILURE);
1074 }
1075
1076 /* We only send out of the token socket */
1077 totemudp_traffic_control_set(instance, sockets->token);
1078 return res;
1079}
1080
1081/*
1082 * Totem Network interface
1083 * depends on poll abstraction, POSIX, IPV4
1084 */
1085
1086/*
1087 * Create an instance
1088 */
1090 qb_loop_t *poll_handle,
1091 void **udp_context,
1092 struct totem_config *totem_config,
1093 totemsrp_stats_t *stats,
1094
1095 void *context,
1096
1097 int (*deliver_fn) (
1098 void *context,
1099 const void *msg,
1100 unsigned int msg_len,
1101 const struct sockaddr_storage *system_from),
1102
1103 int (*iface_change_fn) (
1104 void *context,
1105 const struct totem_ip_address *iface_address,
1106 unsigned int ring_no),
1107
1108 void (*mtu_changed) (
1109 void *context,
1110 int net_mtu),
1111
1112 void (*target_set_completed) (
1113 void *context))
1114{
1115 struct totemudp_instance *instance;
1116
1117 instance = malloc (sizeof (struct totemudp_instance));
1118 if (instance == NULL) {
1119 return (-1);
1120 }
1121
1122 totemudp_instance_initialize (instance);
1123
1124 instance->totem_config = totem_config;
1125 instance->stats = stats;
1126
1127 /*
1128 * Configure logging
1129 */
1130 instance->totemudp_log_level_security = 1; //totem_config->totem_logging_configuration.log_level_security;
1137
1138 /*
1139 * Initialize local variables for totemudp
1140 */
1141 instance->totem_interface = &totem_config->interfaces[0];
1142 totemip_copy (&instance->mcast_address, &instance->totem_interface->mcast_addr);
1143 memset (instance->iov_buffer, 0, UDP_RECEIVE_FRAME_SIZE_MAX + 1);
1144 memset (instance->iov_buffer_flush, 0, UDP_RECEIVE_FRAME_SIZE_MAX + 1);
1145
1146 instance->totemudp_poll_handle = poll_handle;
1147
1148 instance->totem_interface->bindnet.nodeid = instance->totem_config->node_id;
1149
1150 instance->context = context;
1151 instance->totemudp_deliver_fn = deliver_fn;
1152
1153 instance->totemudp_iface_change_fn = iface_change_fn;
1154
1155 instance->totemudp_target_set_completed = target_set_completed;
1156
1157 totemip_localhost (instance->mcast_address.family, &localhost);
1158 localhost.nodeid = instance->totem_config->node_id;
1159
1160 /*
1161 * RRP layer isn't ready to receive message because it hasn't
1162 * initialized yet. Add short timer to check the interfaces.
1163 */
1164 qb_loop_timer_add (instance->totemudp_poll_handle,
1165 QB_LOOP_MED,
1166 100*QB_TIME_NS_IN_MSEC,
1167 (void *)instance,
1168 timer_function_netif_check_timeout,
1169 &instance->timer_netif_check_timeout);
1170
1171 *udp_context = instance;
1172 return (0);
1173}
1174
1176{
1177 return malloc (FRAME_SIZE_MAX);
1178}
1179
1181{
1182 return free (ptr);
1183}
1184
1186 void *udp_context,
1187 int processor_count)
1188{
1189 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1190 int res = 0;
1191
1192 instance->my_memb_entries = processor_count;
1193 qb_loop_timer_del (instance->totemudp_poll_handle,
1194 instance->timer_netif_check_timeout);
1195 if (processor_count == 1) {
1196 qb_loop_timer_add (instance->totemudp_poll_handle,
1197 QB_LOOP_MED,
1198 instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
1199 (void *)instance,
1200 timer_function_netif_check_timeout,
1201 &instance->timer_netif_check_timeout);
1202 }
1203
1204 return (res);
1205}
1206
1208{
1209 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1210 struct pollfd ufd;
1211 int nfds;
1212 int res = 0;
1213 int i;
1214 int sock;
1215
1216 instance->flushing = 1;
1217
1218 for (i = 0; i < 2; i++) {
1219 sock = -1;
1220 if (i == 0) {
1221 sock = instance->totemudp_sockets.mcast_recv;
1222 }
1223 if (i == 1) {
1224 sock = instance->totemudp_sockets.local_mcast_loop[0];
1225 }
1226 assert(sock != -1);
1227
1228 do {
1229 ufd.fd = sock;
1230 ufd.events = POLLIN;
1231 nfds = poll (&ufd, 1, 0);
1232 if (nfds == 1 && ufd.revents & POLLIN) {
1233 net_deliver_fn (sock, ufd.revents, instance);
1234 }
1235 } while (nfds == 1);
1236 }
1237
1238 instance->flushing = 0;
1239
1240 return (res);
1241}
1242
1243int totemudp_send_flush (void *udp_context)
1244{
1245 return 0;
1246}
1247
1249 void *udp_context,
1250 const void *msg,
1251 unsigned int msg_len)
1252{
1253 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1254 int res = 0;
1255
1256 ucast_sendmsg (instance, &instance->token_target, msg, msg_len);
1257
1258 return (res);
1259}
1261 void *udp_context,
1262 const void *msg,
1263 unsigned int msg_len)
1264{
1265 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1266 int res = 0;
1267
1268 mcast_sendmsg (instance, msg, msg_len);
1269
1270 return (res);
1271}
1272
1274 void *udp_context,
1275 const void *msg,
1276 unsigned int msg_len)
1277{
1278 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1279 int res = 0;
1280
1281 mcast_sendmsg (instance, msg, msg_len);
1282
1283 return (res);
1284}
1285
1287{
1288 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1289 int res = 0;
1290
1291 timer_function_netif_check_timeout (instance);
1292
1293 return (res);
1294}
1295
1297 struct totem_node_status *node_status)
1298{
1299 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1300 struct qb_list_head *list;
1301 struct totemudp_member *member;
1302
1303 qb_list_for_each(list, &(instance->member_list)) {
1304 member = qb_list_entry (list,
1305 struct totemudp_member,
1306 list);
1307
1308 if (member->member.nodeid == nodeid) {
1309 node_status->nodeid = nodeid;
1310 /* reachable is filled in by totemsrp */
1311 node_status->link_status[0].enabled = 1;
1312 if (instance->netif_bind_state == BIND_STATE_REGULAR) {
1313 node_status->link_status[0].enabled = 1;
1314 } else {
1315 node_status->link_status[0].enabled = 0;
1316 }
1317 node_status->link_status[0].connected = node_status->reachable;
1318 node_status->link_status[0].mtu = instance->totem_config->net_mtu;
1319 strncpy(node_status->link_status[0].src_ipaddr, totemip_print(&member->member), KNET_MAX_HOST_LEN-1);
1320 }
1321 }
1322 return (0);
1323}
1324
1326 void *net_context,
1327 char ***status,
1328 unsigned int *iface_count)
1329{
1330 static char *statuses[INTERFACE_MAX] = {(char*)"OK"};
1331
1332 if (status) {
1333 *status = statuses;
1334 }
1335 *iface_count = 1;
1336
1337 return (0);
1338}
1339
1344
1346 void *udp_context,
1347 unsigned int nodeid)
1348{
1349 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1350 struct qb_list_head *list;
1351 struct totemudp_member *member;
1352 int res = 0;
1353
1354 qb_list_for_each(list, &(instance->member_list)) {
1355 member = qb_list_entry (list,
1356 struct totemudp_member,
1357 list);
1358
1359 if (member->member.nodeid == nodeid) {
1360 memcpy (&instance->token_target, &member->member,
1361 sizeof (struct totem_ip_address));
1362
1363 instance->totemudp_target_set_completed (instance->context);
1364 break;
1365 }
1366 }
1367 return (res);
1368}
1369
1371 void *udp_context)
1372{
1373 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1374 unsigned int res;
1375 struct sockaddr_storage system_from;
1376 struct msghdr msg_recv;
1377 struct pollfd ufd;
1378 int nfds;
1379 int msg_processed = 0;
1380 int i;
1381 int sock;
1382
1383 /*
1384 * Receive datagram
1385 */
1386 memset(&msg_recv, 0, sizeof(msg_recv));
1387 msg_recv.msg_name = &system_from;
1388 msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
1389 msg_recv.msg_iov = &instance->totemudp_iov_recv_flush;
1390 msg_recv.msg_iovlen = 1;
1391
1392 for (i = 0; i < 2; i++) {
1393 sock = -1;
1394 if (i == 0) {
1395 sock = instance->totemudp_sockets.mcast_recv;
1396 }
1397 if (i == 1) {
1398 sock = instance->totemudp_sockets.local_mcast_loop[0];
1399 }
1400 assert(sock != -1);
1401
1402 do {
1403 ufd.fd = sock;
1404 ufd.events = POLLIN;
1405 nfds = poll (&ufd, 1, 0);
1406 if (nfds == 1 && ufd.revents & POLLIN) {
1407 res = recvmsg (sock, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
1408 if (res != -1) {
1409 msg_processed = 1;
1410 } else {
1411 msg_processed = -1;
1412 }
1413 }
1414 } while (nfds == 1);
1415 }
1416
1417 return (msg_processed);
1418}
1419
1420
1422 void *udp_context,
1423 const struct totem_ip_address *local,
1424 const struct totem_ip_address *member,
1425 int ring_no)
1426{
1427 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1428
1429 struct totemudp_member *new_member;
1430
1431 new_member = malloc (sizeof (struct totemudp_member));
1432 if (new_member == NULL) {
1433 return (-1);
1434 }
1435
1436 memset(new_member, 0, sizeof(*new_member));
1437
1438 qb_list_init (&new_member->list);
1439 qb_list_add_tail (&new_member->list, &instance->member_list);
1440 memcpy (&new_member->member, member, sizeof (struct totem_ip_address));
1441
1442 return (0);
1443}
1444
1446 void *udp_context,
1447 const struct totem_ip_address *token_target,
1448 int ring_no)
1449{
1450 int found = 0;
1451 struct qb_list_head *list;
1452 struct totemudp_member *member;
1453 struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
1454
1455 /*
1456 * Find the member to remove and close its socket
1457 */
1458 qb_list_for_each(list, &(instance->member_list)) {
1459 member = qb_list_entry (list,
1460 struct totemudp_member,
1461 list);
1462
1463 if (totemip_compare (token_target, &member->member)==0) {
1464 found = 1;
1465 break;
1466 }
1467 }
1468
1469 /*
1470 * Delete the member from the list
1471 */
1472 if (found) {
1473 qb_list_del (list);
1474 }
1475
1476 return (0);
1477}
1478
1479int totemudp_iface_set (void *net_context,
1480 const struct totem_ip_address *local_addr,
1481 unsigned short ip_port,
1482 unsigned int iface_no)
1483{
1484 /* Not supported */
1485 return (-1);
1486}
1487
1489 void *udp_context,
1490 struct totem_config *totem_config)
1491{
1492 /* Not supported */
1493 return (-1);
1494}
#define INTERFACE_MAX
Definition coroapi.h:88
unsigned int nodeid
Definition coroapi.h:0
#define PROCESSOR_COUNT_MAX
Definition coroapi.h:96
unsigned int node_id
Definition totem.h:167
unsigned int broadcast_use
Definition totem.h:222
struct totem_logging_configuration totem_logging_configuration
Definition totem.h:208
unsigned int downcheck_timeout
Definition totem.h:200
struct totem_interface * interfaces
Definition totem.h:165
unsigned int clear_node_high_bit
Definition totem.h:168
unsigned char ip_dscp
Definition totem.h:250
unsigned int net_mtu
Definition totem.h:210
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
uint16_t ttl
Definition totem.h:88
struct totem_ip_address mcast_addr
Definition totem.h:85
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:270
unsigned int nodeid
Definition totem.h:269
struct knet_link_status link_status[KNET_MAX_LINK]
Definition totem.h:276
uint32_t continuous_sendmsg_failures
Definition totemstats.h:79
qb_loop_timer_handle timer_netif_check_timeout
Definition totemudp.c:182
struct totem_ip_address mcast_address
Definition totemudp.c:164
struct qb_list_head member_list
Definition totemudp.c:152
qb_loop_t * totemudp_poll_handle
Definition totemudp.c:103
int totemudp_log_level_security
Definition totemudp.c:129
struct totem_ip_address my_id
Definition totemudp.c:178
struct totem_interface * totem_interface
Definition totemudp.c:105
struct iovec totemudp_iov_recv_flush
Definition totemudp.c:160
int totemudp_log_level_notice
Definition totemudp.c:135
void(* totemudp_log_printf)(int level, int subsys, const char *function, const char *file, int line, const char *format,...) __attribute__((format(printf
Definition totemudp.c:141
unsigned int my_memb_entries
Definition totemudp.c:184
int totemudp_log_level_debug
Definition totemudp.c:137
struct totem_config * totem_config
Definition totemudp.c:188
int totemudp_log_level_warning
Definition totemudp.c:133
struct totem_ip_address token_target
Definition totemudp.c:192
void(* totemudp_target_set_completed)(void *context)
Definition totemudp.c:124
char iov_buffer[UDP_RECEIVE_FRAME_SIZE_MAX+1]
Definition totemudp.c:154
int(* totemudp_iface_change_fn)(void *context, const struct totem_ip_address *iface_address, unsigned int ring_no)
Definition totemudp.c:119
struct iovec totemudp_iov_recv
Definition totemudp.c:158
totemsrp_stats_t * stats
Definition totemudp.c:190
struct totemudp_socket totemudp_sockets
Definition totemudp.c:162
struct timeval stats_tv_start
Definition totemudp.c:176
int(* totemudp_deliver_fn)(void *context, const void *msg, unsigned int msg_len, const struct sockaddr_storage *system_from)
Definition totemudp.c:113
char iov_buffer_flush[UDP_RECEIVE_FRAME_SIZE_MAX+1]
Definition totemudp.c:156
void void * udp_context
Definition totemudp.c:150
int totemudp_log_level_error
Definition totemudp.c:131
struct totem_ip_address member
Definition totemudp.c:86
struct qb_list_head list
Definition totemudp.c:85
int local_mcast_loop[2]
Definition totemudp.c:99
const void * msg
Definition totemknet.c:191
unsigned int msg_len
Definition totemknet.c:192
struct totemknet_instance * instance
Definition totemknet.c:193
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_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_print(const struct totem_ip_address *addr)
Definition totemip.c:256
int totemip_localhost(int family, struct totem_ip_address *localhost)
Definition totemip.c:202
#define MSG_NOSIGNAL
Definition totemknet.c:82
struct srp_addr system_from
Definition totemsrp.c:1
int totemudp_iface_set(void *net_context, const struct totem_ip_address *local_addr, unsigned short ip_port, unsigned int iface_no)
Definition totemudp.c:1479
#define NETIF_STATE_REPORT_UP
Definition totemudp.c:77
void totemudp_net_mtu_adjust(void *udp_context, struct totem_config *totem_config)
Definition totemudp.c:1340
#define log_printf(level, format, args...)
Definition totemudp.c:231
void * totemudp_buffer_alloc(void)
Definition totemudp.c:1175
int totemudp_send_flush(void *udp_context)
Definition totemudp.c:1243
int totemudp_iface_check(void *udp_context)
Definition totemudp.c:1286
int totemudp_recv_flush(void *udp_context)
Definition totemudp.c:1207
#define BIND_STATE_LOOPBACK
Definition totemudp.c:82
#define NETIF_STATE_REPORT_DOWN
Definition totemudp.c:78
int totemudp_nodestatus_get(void *udp_context, unsigned int nodeid, struct totem_node_status *node_status)
Definition totemudp.c:1296
int totemudp_token_target_set(void *udp_context, unsigned int nodeid)
Definition totemudp.c:1345
int totemudp_ifaces_get(void *net_context, char ***status, unsigned int *iface_count)
Definition totemudp.c:1325
int totemudp_reconfigure(void *udp_context, struct totem_config *totem_config)
Definition totemudp.c:1488
#define MCAST_SOCKET_BUFFER_SIZE
Definition totemudp.c:76
int totemudp_mcast_flush_send(void *udp_context, const void *msg, unsigned int msg_len)
Definition totemudp.c:1260
int totemudp_finalize(void *udp_context)
Definition totemudp.c:352
int totemudp_recv_mcast_empty(void *udp_context)
Definition totemudp.c:1370
int totemudp_crypto_set(void *udp_context, const char *cipher_type, const char *hash_type)
Definition totemudp.c:249
#define LOGSYS_PERROR(err_num, level, fmt, args...)
Definition totemudp.c:239
int totemudp_processor_count_set(void *udp_context, int processor_count)
Definition totemudp.c:1185
int totemudp_token_send(void *udp_context, const void *msg, unsigned int msg_len)
Definition totemudp.c:1248
#define BIND_STATE_REGULAR
Definition totemudp.c:81
int totemudp_mcast_noflush_send(void *udp_context, const void *msg, unsigned int msg_len)
Definition totemudp.c:1273
int totemudp_member_add(void *udp_context, const struct totem_ip_address *local, const struct totem_ip_address *member, int ring_no)
Definition totemudp.c:1421
void totemudp_buffer_release(void *ptr)
Definition totemudp.c:1180
int totemudp_initialize(qb_loop_t *poll_handle, void **udp_context, struct totem_config *totem_config, totemsrp_stats_t *stats, void *context, int(*deliver_fn)(void *context, const void *msg, unsigned int msg_len, const struct sockaddr_storage *system_from), int(*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 totemudp.c:1089
int totemudp_member_remove(void *udp_context, const struct totem_ip_address *token_target, int ring_no)
Definition totemudp.c:1445
int set_socket_dscp(int socket, unsigned char dscp)
Definition util.c:358