totemudp.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419
  1. /*
  2. * Copyright (c) 2005 MontaVista Software, Inc.
  3. * Copyright (c) 2006-2012 Red Hat, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. * Author: Steven Dake (sdake@redhat.com)
  8. * This software licensed under BSD license, the text of which follows:
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  32. * THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include <config.h>
  35. #include <assert.h>
  36. #include <pthread.h>
  37. #include <sys/mman.h>
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <sys/socket.h>
  41. #include <netdb.h>
  42. #include <sys/un.h>
  43. #include <sys/ioctl.h>
  44. #include <sys/param.h>
  45. #include <netinet/in.h>
  46. #include <arpa/inet.h>
  47. #include <unistd.h>
  48. #include <fcntl.h>
  49. #include <stdlib.h>
  50. #include <stdio.h>
  51. #include <errno.h>
  52. #include <sched.h>
  53. #include <time.h>
  54. #include <sys/time.h>
  55. #include <sys/poll.h>
  56. #include <sys/uio.h>
  57. #include <limits.h>
  58. #include <corosync/sq.h>
  59. #include <corosync/swab.h>
  60. #include <qb/qbdefs.h>
  61. #include <qb/qbloop.h>
  62. #define LOGSYS_UTILS_ONLY 1
  63. #include <corosync/logsys.h>
  64. #include "totemudp.h"
  65. #include "util.h"
  66. #ifndef MSG_NOSIGNAL
  67. #define MSG_NOSIGNAL 0
  68. #endif
  69. #define MCAST_SOCKET_BUFFER_SIZE (TRANSMITS_ALLOWED * FRAME_SIZE_MAX)
  70. #define NETIF_STATE_REPORT_UP 1
  71. #define NETIF_STATE_REPORT_DOWN 2
  72. #define BIND_STATE_UNBOUND 0
  73. #define BIND_STATE_REGULAR 1
  74. #define BIND_STATE_LOOPBACK 2
  75. #define MESSAGE_TYPE_MEMB_JOIN 3
  76. struct totemudp_socket {
  77. int mcast_recv;
  78. int mcast_send;
  79. int token;
  80. /*
  81. * Socket used for local multicast delivery. We don't rely on multicast
  82. * loop and rather this UNIX DGRAM socket is used. Socket is created by
  83. * socketpair call and they are used in same way as pipe (so [0] is read
  84. * end and [1] is write end)
  85. */
  86. int local_mcast_loop[2];
  87. };
  88. struct totemudp_instance {
  89. qb_loop_t *totemudp_poll_handle;
  90. struct totem_interface *totem_interface;
  91. int netif_state_report;
  92. int netif_bind_state;
  93. void *context;
  94. void (*totemudp_deliver_fn) (
  95. void *context,
  96. const void *msg,
  97. unsigned int msg_len);
  98. void (*totemudp_iface_change_fn) (
  99. void *context,
  100. const struct totem_ip_address *iface_address,
  101. unsigned int ring_no);
  102. void (*totemudp_target_set_completed) (void *context);
  103. /*
  104. * Function and data used to log messages
  105. */
  106. int totemudp_log_level_security;
  107. int totemudp_log_level_error;
  108. int totemudp_log_level_warning;
  109. int totemudp_log_level_notice;
  110. int totemudp_log_level_debug;
  111. int totemudp_subsys_id;
  112. void (*totemudp_log_printf) (
  113. int level,
  114. int subsys,
  115. const char *function,
  116. const char *file,
  117. int line,
  118. const char *format,
  119. ...)__attribute__((format(printf, 6, 7)));
  120. void *udp_context;
  121. char iov_buffer[FRAME_SIZE_MAX];
  122. char iov_buffer_flush[FRAME_SIZE_MAX];
  123. struct iovec totemudp_iov_recv;
  124. struct iovec totemudp_iov_recv_flush;
  125. struct totemudp_socket totemudp_sockets;
  126. struct totem_ip_address mcast_address;
  127. int stats_sent;
  128. int stats_recv;
  129. int stats_delv;
  130. int stats_remcasts;
  131. int stats_orf_token;
  132. struct timeval stats_tv_start;
  133. struct totem_ip_address my_id;
  134. int firstrun;
  135. qb_loop_timer_handle timer_netif_check_timeout;
  136. unsigned int my_memb_entries;
  137. int flushing;
  138. struct totem_config *totem_config;
  139. totemsrp_stats_t *stats;
  140. struct totem_ip_address token_target;
  141. };
  142. struct work_item {
  143. const void *msg;
  144. unsigned int msg_len;
  145. struct totemudp_instance *instance;
  146. };
  147. static int totemudp_build_sockets (
  148. struct totemudp_instance *instance,
  149. struct totem_ip_address *bindnet_address,
  150. struct totem_ip_address *mcastaddress,
  151. struct totemudp_socket *sockets,
  152. struct totem_ip_address *bound_to);
  153. static struct totem_ip_address localhost;
  154. static void totemudp_instance_initialize (struct totemudp_instance *instance)
  155. {
  156. memset (instance, 0, sizeof (struct totemudp_instance));
  157. instance->netif_state_report = NETIF_STATE_REPORT_UP | NETIF_STATE_REPORT_DOWN;
  158. instance->totemudp_iov_recv.iov_base = instance->iov_buffer;
  159. instance->totemudp_iov_recv.iov_len = FRAME_SIZE_MAX; //sizeof (instance->iov_buffer);
  160. instance->totemudp_iov_recv_flush.iov_base = instance->iov_buffer_flush;
  161. instance->totemudp_iov_recv_flush.iov_len = FRAME_SIZE_MAX; //sizeof (instance->iov_buffer);
  162. /*
  163. * There is always atleast 1 processor
  164. */
  165. instance->my_memb_entries = 1;
  166. }
  167. #define log_printf(level, format, args...) \
  168. do { \
  169. instance->totemudp_log_printf ( \
  170. level, instance->totemudp_subsys_id, \
  171. __FUNCTION__, __FILE__, __LINE__, \
  172. (const char *)format, ##args); \
  173. } while (0);
  174. #define LOGSYS_PERROR(err_num, level, fmt, args...) \
  175. do { \
  176. char _error_str[LOGSYS_MAX_PERROR_MSG_LEN]; \
  177. const char *_error_ptr = qb_strerror_r(err_num, _error_str, sizeof(_error_str)); \
  178. instance->totemudp_log_printf ( \
  179. level, instance->totemudp_subsys_id, \
  180. __FUNCTION__, __FILE__, __LINE__, \
  181. fmt ": %s (%d)\n", ##args, _error_ptr, err_num); \
  182. } while(0)
  183. int totemudp_crypto_set (
  184. void *udp_context,
  185. const char *cipher_type,
  186. const char *hash_type)
  187. {
  188. return (0);
  189. }
  190. static inline void ucast_sendmsg (
  191. struct totemudp_instance *instance,
  192. struct totem_ip_address *system_to,
  193. const void *msg,
  194. unsigned int msg_len)
  195. {
  196. struct msghdr msg_ucast;
  197. int res = 0;
  198. struct sockaddr_storage sockaddr;
  199. struct iovec iovec;
  200. int addrlen;
  201. iovec.iov_base = (void*)msg;
  202. iovec.iov_len = msg_len;
  203. /*
  204. * Build unicast message
  205. */
  206. memset(&msg_ucast, 0, sizeof(msg_ucast));
  207. totemip_totemip_to_sockaddr_convert(system_to,
  208. instance->totem_interface->ip_port, &sockaddr, &addrlen);
  209. msg_ucast.msg_name = &sockaddr;
  210. msg_ucast.msg_namelen = addrlen;
  211. msg_ucast.msg_iov = (void *)&iovec;
  212. msg_ucast.msg_iovlen = 1;
  213. #ifdef HAVE_MSGHDR_CONTROL
  214. msg_ucast.msg_control = 0;
  215. #endif
  216. #ifdef HAVE_MSGHDR_CONTROLLEN
  217. msg_ucast.msg_controllen = 0;
  218. #endif
  219. #ifdef HAVE_MSGHDR_FLAGS
  220. msg_ucast.msg_flags = 0;
  221. #endif
  222. #ifdef HAVE_MSGHDR_ACCRIGHTS
  223. msg_ucast.msg_accrights = NULL;
  224. #endif
  225. #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
  226. msg_ucast.msg_accrightslen = 0;
  227. #endif
  228. /*
  229. * Transmit unicast message
  230. * An error here is recovered by totemsrp
  231. */
  232. res = sendmsg (instance->totemudp_sockets.mcast_send, &msg_ucast,
  233. MSG_NOSIGNAL);
  234. if (res < 0) {
  235. LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
  236. "sendmsg(ucast) failed (non-critical)");
  237. }
  238. }
  239. static inline void mcast_sendmsg (
  240. struct totemudp_instance *instance,
  241. const void *msg,
  242. unsigned int msg_len)
  243. {
  244. struct msghdr msg_mcast;
  245. int res = 0;
  246. struct iovec iovec;
  247. struct sockaddr_storage sockaddr;
  248. int addrlen;
  249. iovec.iov_base = (void *)msg;
  250. iovec.iov_len = msg_len;
  251. /*
  252. * Build multicast message
  253. */
  254. totemip_totemip_to_sockaddr_convert(&instance->mcast_address,
  255. instance->totem_interface->ip_port, &sockaddr, &addrlen);
  256. memset(&msg_mcast, 0, sizeof(msg_mcast));
  257. msg_mcast.msg_name = &sockaddr;
  258. msg_mcast.msg_namelen = addrlen;
  259. msg_mcast.msg_iov = (void *)&iovec;
  260. msg_mcast.msg_iovlen = 1;
  261. #ifdef HAVE_MSGHDR_CONTROL
  262. msg_mcast.msg_control = 0;
  263. #endif
  264. #ifdef HAVE_MSGHDR_CONTROLLEN
  265. msg_mcast.msg_controllen = 0;
  266. #endif
  267. #ifdef HAVE_MSGHDR_FLAGS
  268. msg_mcast.msg_flags = 0;
  269. #endif
  270. #ifdef HAVE_MSGHDR_ACCRIGHTS
  271. msg_mcast.msg_accrights = NULL;
  272. #endif
  273. #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
  274. msg_mcast.msg_accrightslen = 0;
  275. #endif
  276. /*
  277. * Transmit multicast message
  278. * An error here is recovered by totemsrp
  279. */
  280. res = sendmsg (instance->totemudp_sockets.mcast_send, &msg_mcast,
  281. MSG_NOSIGNAL);
  282. if (res < 0) {
  283. LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
  284. "sendmsg(mcast) failed (non-critical)");
  285. instance->stats->continuous_sendmsg_failures++;
  286. } else {
  287. instance->stats->continuous_sendmsg_failures = 0;
  288. }
  289. /*
  290. * Transmit multicast message to local unix mcast loop
  291. * An error here is recovered by totemsrp
  292. */
  293. msg_mcast.msg_name = NULL;
  294. msg_mcast.msg_namelen = 0;
  295. res = sendmsg (instance->totemudp_sockets.local_mcast_loop[1], &msg_mcast,
  296. MSG_NOSIGNAL);
  297. if (res < 0) {
  298. LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
  299. "sendmsg(local mcast loop) failed (non-critical)");
  300. }
  301. }
  302. int totemudp_finalize (
  303. void *udp_context)
  304. {
  305. struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
  306. int res = 0;
  307. if (instance->totemudp_sockets.mcast_recv > 0) {
  308. qb_loop_poll_del (instance->totemudp_poll_handle,
  309. instance->totemudp_sockets.mcast_recv);
  310. close (instance->totemudp_sockets.mcast_recv);
  311. }
  312. if (instance->totemudp_sockets.mcast_send > 0) {
  313. close (instance->totemudp_sockets.mcast_send);
  314. }
  315. if (instance->totemudp_sockets.local_mcast_loop[0] > 0) {
  316. qb_loop_poll_del (instance->totemudp_poll_handle,
  317. instance->totemudp_sockets.local_mcast_loop[0]);
  318. close (instance->totemudp_sockets.local_mcast_loop[0]);
  319. close (instance->totemudp_sockets.local_mcast_loop[1]);
  320. }
  321. if (instance->totemudp_sockets.token > 0) {
  322. qb_loop_poll_del (instance->totemudp_poll_handle,
  323. instance->totemudp_sockets.token);
  324. close (instance->totemudp_sockets.token);
  325. }
  326. return (res);
  327. }
  328. /*
  329. * Only designed to work with a message with one iov
  330. */
  331. static int net_deliver_fn (
  332. int fd,
  333. int revents,
  334. void *data)
  335. {
  336. struct totemudp_instance *instance = (struct totemudp_instance *)data;
  337. struct msghdr msg_recv;
  338. struct iovec *iovec;
  339. struct sockaddr_storage system_from;
  340. int bytes_received;
  341. char *message_type;
  342. if (instance->flushing == 1) {
  343. iovec = &instance->totemudp_iov_recv_flush;
  344. } else {
  345. iovec = &instance->totemudp_iov_recv;
  346. }
  347. /*
  348. * Receive datagram
  349. */
  350. msg_recv.msg_name = &system_from;
  351. msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
  352. msg_recv.msg_iov = iovec;
  353. msg_recv.msg_iovlen = 1;
  354. #ifdef HAVE_MSGHDR_CONTROL
  355. msg_recv.msg_control = 0;
  356. #endif
  357. #ifdef HAVE_MSGHDR_CONTROLLEN
  358. msg_recv.msg_controllen = 0;
  359. #endif
  360. #ifdef HAVE_MSGHDR_FLAGS
  361. msg_recv.msg_flags = 0;
  362. #endif
  363. #ifdef HAVE_MSGHDR_ACCRIGHTS
  364. msg_recv.msg_accrights = NULL;
  365. #endif
  366. #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
  367. msg_recv.msg_accrightslen = 0;
  368. #endif
  369. bytes_received = recvmsg (fd, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
  370. if (bytes_received == -1) {
  371. return (0);
  372. } else {
  373. instance->stats_recv += bytes_received;
  374. }
  375. iovec->iov_len = bytes_received;
  376. /*
  377. * Drop all non-mcast messages (more specifically join
  378. * messages should be dropped)
  379. */
  380. message_type = (char *)iovec->iov_base;
  381. if (instance->flushing == 1 && *message_type == MESSAGE_TYPE_MEMB_JOIN) {
  382. log_printf(instance->totemudp_log_level_warning, "JOIN or LEAVE message was thrown away during flush operation.");
  383. iovec->iov_len = FRAME_SIZE_MAX;
  384. return (0);
  385. }
  386. /*
  387. * Handle incoming message
  388. */
  389. instance->totemudp_deliver_fn (
  390. instance->context,
  391. iovec->iov_base,
  392. iovec->iov_len);
  393. iovec->iov_len = FRAME_SIZE_MAX;
  394. return (0);
  395. }
  396. static int netif_determine (
  397. struct totemudp_instance *instance,
  398. struct totem_ip_address *bindnet,
  399. struct totem_ip_address *bound_to,
  400. int *interface_up,
  401. int *interface_num)
  402. {
  403. int res;
  404. res = totemip_iface_check (bindnet, bound_to,
  405. interface_up, interface_num,
  406. instance->totem_config->clear_node_high_bit);
  407. return (res);
  408. }
  409. /*
  410. * If the interface is up, the sockets for totem are built. If the interface is down
  411. * this function is requeued in the timer list to retry building the sockets later.
  412. */
  413. static void timer_function_netif_check_timeout (
  414. void *data)
  415. {
  416. struct totemudp_instance *instance = (struct totemudp_instance *)data;
  417. int interface_up;
  418. int interface_num;
  419. struct totem_ip_address *bind_address;
  420. /*
  421. * Build sockets for every interface
  422. */
  423. netif_determine (instance,
  424. &instance->totem_interface->bindnet,
  425. &instance->totem_interface->boundto,
  426. &interface_up, &interface_num);
  427. /*
  428. * If the network interface isn't back up and we are already
  429. * in loopback mode, add timer to check again and return
  430. */
  431. if ((instance->netif_bind_state == BIND_STATE_LOOPBACK &&
  432. interface_up == 0) ||
  433. (instance->my_memb_entries == 1 &&
  434. instance->netif_bind_state == BIND_STATE_REGULAR &&
  435. interface_up == 1)) {
  436. qb_loop_timer_add (instance->totemudp_poll_handle,
  437. QB_LOOP_MED,
  438. instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
  439. (void *)instance,
  440. timer_function_netif_check_timeout,
  441. &instance->timer_netif_check_timeout);
  442. /*
  443. * Add a timer to check for a downed regular interface
  444. */
  445. return;
  446. }
  447. if (instance->totemudp_sockets.mcast_recv > 0) {
  448. qb_loop_poll_del (instance->totemudp_poll_handle,
  449. instance->totemudp_sockets.mcast_recv);
  450. close (instance->totemudp_sockets.mcast_recv);
  451. }
  452. if (instance->totemudp_sockets.mcast_send > 0) {
  453. close (instance->totemudp_sockets.mcast_send);
  454. }
  455. if (instance->totemudp_sockets.local_mcast_loop[0] > 0) {
  456. qb_loop_poll_del (instance->totemudp_poll_handle,
  457. instance->totemudp_sockets.local_mcast_loop[0]);
  458. close (instance->totemudp_sockets.local_mcast_loop[0]);
  459. close (instance->totemudp_sockets.local_mcast_loop[1]);
  460. }
  461. if (instance->totemudp_sockets.token > 0) {
  462. qb_loop_poll_del (instance->totemudp_poll_handle,
  463. instance->totemudp_sockets.token);
  464. close (instance->totemudp_sockets.token);
  465. }
  466. if (interface_up == 0) {
  467. /*
  468. * Interface is not up
  469. */
  470. instance->netif_bind_state = BIND_STATE_LOOPBACK;
  471. bind_address = &localhost;
  472. /*
  473. * Add a timer to retry building interfaces and request memb_gather_enter
  474. */
  475. qb_loop_timer_add (instance->totemudp_poll_handle,
  476. QB_LOOP_MED,
  477. instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
  478. (void *)instance,
  479. timer_function_netif_check_timeout,
  480. &instance->timer_netif_check_timeout);
  481. } else {
  482. /*
  483. * Interface is up
  484. */
  485. instance->netif_bind_state = BIND_STATE_REGULAR;
  486. bind_address = &instance->totem_interface->bindnet;
  487. }
  488. /*
  489. * Create and bind the multicast and unicast sockets
  490. */
  491. (void)totemudp_build_sockets (instance,
  492. &instance->mcast_address,
  493. bind_address,
  494. &instance->totemudp_sockets,
  495. &instance->totem_interface->boundto);
  496. qb_loop_poll_add (
  497. instance->totemudp_poll_handle,
  498. QB_LOOP_MED,
  499. instance->totemudp_sockets.mcast_recv,
  500. POLLIN, instance, net_deliver_fn);
  501. qb_loop_poll_add (
  502. instance->totemudp_poll_handle,
  503. QB_LOOP_MED,
  504. instance->totemudp_sockets.local_mcast_loop[0],
  505. POLLIN, instance, net_deliver_fn);
  506. qb_loop_poll_add (
  507. instance->totemudp_poll_handle,
  508. QB_LOOP_MED,
  509. instance->totemudp_sockets.token,
  510. POLLIN, instance, net_deliver_fn);
  511. totemip_copy (&instance->my_id, &instance->totem_interface->boundto);
  512. /*
  513. * This reports changes in the interface to the user and totemsrp
  514. */
  515. if (instance->netif_bind_state == BIND_STATE_REGULAR) {
  516. if (instance->netif_state_report & NETIF_STATE_REPORT_UP) {
  517. log_printf (instance->totemudp_log_level_notice,
  518. "The network interface [%s] is now up.",
  519. totemip_print (&instance->totem_interface->boundto));
  520. instance->netif_state_report = NETIF_STATE_REPORT_DOWN;
  521. instance->totemudp_iface_change_fn (instance->context, &instance->my_id, 0);
  522. }
  523. /*
  524. * Add a timer to check for interface going down in single membership
  525. */
  526. if (instance->my_memb_entries == 1) {
  527. qb_loop_timer_add (instance->totemudp_poll_handle,
  528. QB_LOOP_MED,
  529. instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
  530. (void *)instance,
  531. timer_function_netif_check_timeout,
  532. &instance->timer_netif_check_timeout);
  533. }
  534. } else {
  535. if (instance->netif_state_report & NETIF_STATE_REPORT_DOWN) {
  536. log_printf (instance->totemudp_log_level_notice,
  537. "The network interface is down.");
  538. instance->totemudp_iface_change_fn (instance->context, &instance->my_id, 0);
  539. }
  540. instance->netif_state_report = NETIF_STATE_REPORT_UP;
  541. }
  542. }
  543. /* Set the socket priority to INTERACTIVE to ensure
  544. that our messages don't get queued behind anything else */
  545. static void totemudp_traffic_control_set(struct totemudp_instance *instance, int sock)
  546. {
  547. #ifdef SO_PRIORITY
  548. int prio = 6; /* TC_PRIO_INTERACTIVE */
  549. if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(int))) {
  550. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning, "Could not set traffic priority");
  551. }
  552. #endif
  553. }
  554. static int totemudp_build_sockets_ip (
  555. struct totemudp_instance *instance,
  556. struct totem_ip_address *mcast_address,
  557. struct totem_ip_address *bindnet_address,
  558. struct totemudp_socket *sockets,
  559. struct totem_ip_address *bound_to,
  560. int interface_num)
  561. {
  562. struct sockaddr_storage sockaddr;
  563. struct ipv6_mreq mreq6;
  564. struct ip_mreq mreq;
  565. struct sockaddr_storage mcast_ss, boundto_ss;
  566. struct sockaddr_in6 *mcast_sin6 = (struct sockaddr_in6 *)&mcast_ss;
  567. struct sockaddr_in *mcast_sin = (struct sockaddr_in *)&mcast_ss;
  568. struct sockaddr_in *boundto_sin = (struct sockaddr_in *)&boundto_ss;
  569. unsigned int sendbuf_size;
  570. unsigned int recvbuf_size;
  571. unsigned int optlen = sizeof (sendbuf_size);
  572. unsigned int retries;
  573. int addrlen;
  574. int res;
  575. int flag;
  576. uint8_t sflag;
  577. int i;
  578. /*
  579. * Create multicast recv socket
  580. */
  581. sockets->mcast_recv = socket (bindnet_address->family, SOCK_DGRAM, 0);
  582. if (sockets->mcast_recv == -1) {
  583. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  584. "socket() failed");
  585. return (-1);
  586. }
  587. totemip_nosigpipe (sockets->mcast_recv);
  588. res = fcntl (sockets->mcast_recv, F_SETFL, O_NONBLOCK);
  589. if (res == -1) {
  590. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  591. "Could not set non-blocking operation on multicast socket");
  592. return (-1);
  593. }
  594. /*
  595. * Force reuse
  596. */
  597. flag = 1;
  598. if ( setsockopt(sockets->mcast_recv, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
  599. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  600. "setsockopt(SO_REUSEADDR) failed");
  601. return (-1);
  602. }
  603. /*
  604. * Create local multicast loop socket
  605. */
  606. if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets->local_mcast_loop) == -1) {
  607. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  608. "socket() failed");
  609. return (-1);
  610. }
  611. for (i = 0; i < 2; i++) {
  612. totemip_nosigpipe (sockets->local_mcast_loop[i]);
  613. res = fcntl (sockets->local_mcast_loop[i], F_SETFL, O_NONBLOCK);
  614. if (res == -1) {
  615. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  616. "Could not set non-blocking operation on multicast socket");
  617. return (-1);
  618. }
  619. }
  620. /*
  621. * Setup mcast send socket
  622. */
  623. sockets->mcast_send = socket (bindnet_address->family, SOCK_DGRAM, 0);
  624. if (sockets->mcast_send == -1) {
  625. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  626. "socket() failed");
  627. return (-1);
  628. }
  629. totemip_nosigpipe (sockets->mcast_send);
  630. res = fcntl (sockets->mcast_send, F_SETFL, O_NONBLOCK);
  631. if (res == -1) {
  632. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  633. "Could not set non-blocking operation on multicast socket");
  634. return (-1);
  635. }
  636. /*
  637. * Force reuse
  638. */
  639. flag = 1;
  640. if ( setsockopt(sockets->mcast_send, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
  641. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  642. "setsockopt(SO_REUSEADDR) failed");
  643. return (-1);
  644. }
  645. totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port - 1,
  646. &sockaddr, &addrlen);
  647. retries = 0;
  648. while (1) {
  649. res = bind (sockets->mcast_send, (struct sockaddr *)&sockaddr, addrlen);
  650. if (res == 0) {
  651. break;
  652. }
  653. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  654. "Unable to bind the socket to send multicast packets");
  655. if (++retries > BIND_MAX_RETRIES) {
  656. break;
  657. }
  658. /*
  659. * Wait for a while
  660. */
  661. (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
  662. }
  663. if (res == -1) {
  664. return (-1);
  665. }
  666. /*
  667. * Setup unicast socket
  668. */
  669. sockets->token = socket (bindnet_address->family, SOCK_DGRAM, 0);
  670. if (sockets->token == -1) {
  671. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  672. "socket() failed");
  673. return (-1);
  674. }
  675. totemip_nosigpipe (sockets->token);
  676. res = fcntl (sockets->token, F_SETFL, O_NONBLOCK);
  677. if (res == -1) {
  678. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  679. "Could not set non-blocking operation on token socket");
  680. return (-1);
  681. }
  682. /*
  683. * Force reuse
  684. */
  685. flag = 1;
  686. if ( setsockopt(sockets->token, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
  687. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  688. "setsockopt(SO_REUSEADDR) failed");
  689. return (-1);
  690. }
  691. /*
  692. * Bind to unicast socket used for token send/receives
  693. * This has the side effect of binding to the correct interface
  694. */
  695. totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &sockaddr, &addrlen);
  696. retries = 0;
  697. while (1) {
  698. res = bind (sockets->token, (struct sockaddr *)&sockaddr, addrlen);
  699. if (res == 0) {
  700. break;
  701. }
  702. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  703. "Unable to bind UDP unicast socket");
  704. if (++retries > BIND_MAX_RETRIES) {
  705. break;
  706. }
  707. /*
  708. * Wait for a while
  709. */
  710. (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
  711. }
  712. if (res == -1) {
  713. return (-1);
  714. }
  715. recvbuf_size = MCAST_SOCKET_BUFFER_SIZE;
  716. sendbuf_size = MCAST_SOCKET_BUFFER_SIZE;
  717. /*
  718. * Set buffer sizes to avoid overruns
  719. */
  720. res = setsockopt (sockets->mcast_recv, SOL_SOCKET, SO_RCVBUF, &recvbuf_size, optlen);
  721. if (res == -1) {
  722. LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
  723. "Unable to set SO_RCVBUF size on UDP mcast socket");
  724. return (-1);
  725. }
  726. res = setsockopt (sockets->mcast_send, SOL_SOCKET, SO_SNDBUF, &sendbuf_size, optlen);
  727. if (res == -1) {
  728. LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
  729. "Unable to set SO_SNDBUF size on UDP mcast socket");
  730. return (-1);
  731. }
  732. res = setsockopt (sockets->local_mcast_loop[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, optlen);
  733. if (res == -1) {
  734. LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
  735. "Unable to set SO_RCVBUF size on UDP local mcast loop socket");
  736. return (-1);
  737. }
  738. res = setsockopt (sockets->local_mcast_loop[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, optlen);
  739. if (res == -1) {
  740. LOGSYS_PERROR (errno, instance->totemudp_log_level_debug,
  741. "Unable to set SO_SNDBUF size on UDP local mcast loop socket");
  742. return (-1);
  743. }
  744. res = getsockopt (sockets->mcast_recv, SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
  745. if (res == 0) {
  746. log_printf (instance->totemudp_log_level_debug,
  747. "Receive multicast socket recv buffer size (%d bytes).", recvbuf_size);
  748. }
  749. res = getsockopt (sockets->mcast_send, SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
  750. if (res == 0) {
  751. log_printf (instance->totemudp_log_level_debug,
  752. "Transmit multicast socket send buffer size (%d bytes).", sendbuf_size);
  753. }
  754. res = getsockopt (sockets->local_mcast_loop[0], SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
  755. if (res == 0) {
  756. log_printf (instance->totemudp_log_level_debug,
  757. "Local receive multicast loop socket recv buffer size (%d bytes).", recvbuf_size);
  758. }
  759. res = getsockopt (sockets->local_mcast_loop[1], SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
  760. if (res == 0) {
  761. log_printf (instance->totemudp_log_level_debug,
  762. "Local transmit multicast loop socket send buffer size (%d bytes).", sendbuf_size);
  763. }
  764. /*
  765. * Join group membership on socket
  766. */
  767. totemip_totemip_to_sockaddr_convert(mcast_address, instance->totem_interface->ip_port, &mcast_ss, &addrlen);
  768. totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &boundto_ss, &addrlen);
  769. if (instance->totem_config->broadcast_use == 1) {
  770. unsigned int broadcast = 1;
  771. if ((setsockopt(sockets->mcast_recv, SOL_SOCKET,
  772. SO_BROADCAST, &broadcast, sizeof (broadcast))) == -1) {
  773. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  774. "setting broadcast option failed");
  775. return (-1);
  776. }
  777. if ((setsockopt(sockets->mcast_send, SOL_SOCKET,
  778. SO_BROADCAST, &broadcast, sizeof (broadcast))) == -1) {
  779. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  780. "setting broadcast option failed");
  781. return (-1);
  782. }
  783. } else {
  784. switch (bindnet_address->family) {
  785. case AF_INET:
  786. memset(&mreq, 0, sizeof(mreq));
  787. mreq.imr_multiaddr.s_addr = mcast_sin->sin_addr.s_addr;
  788. mreq.imr_interface.s_addr = boundto_sin->sin_addr.s_addr;
  789. res = setsockopt (sockets->mcast_recv, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  790. &mreq, sizeof (mreq));
  791. if (res == -1) {
  792. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  793. "join ipv4 multicast group failed");
  794. return (-1);
  795. }
  796. break;
  797. case AF_INET6:
  798. memset(&mreq6, 0, sizeof(mreq6));
  799. memcpy(&mreq6.ipv6mr_multiaddr, &mcast_sin6->sin6_addr, sizeof(struct in6_addr));
  800. mreq6.ipv6mr_interface = interface_num;
  801. res = setsockopt (sockets->mcast_recv, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  802. &mreq6, sizeof (mreq6));
  803. if (res == -1) {
  804. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  805. "join ipv6 multicast group failed");
  806. return (-1);
  807. }
  808. break;
  809. }
  810. }
  811. /*
  812. * Turn off multicast loopback
  813. */
  814. flag = 0;
  815. switch ( bindnet_address->family ) {
  816. case AF_INET:
  817. sflag = 0;
  818. res = setsockopt (sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_LOOP,
  819. &sflag, sizeof (sflag));
  820. break;
  821. case AF_INET6:
  822. res = setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
  823. &flag, sizeof (flag));
  824. }
  825. if (res == -1) {
  826. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  827. "Unable to turn off multicast loopback");
  828. return (-1);
  829. }
  830. /*
  831. * Set multicast packets TTL
  832. */
  833. flag = instance->totem_interface->ttl;
  834. if (bindnet_address->family == AF_INET6) {
  835. res = setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
  836. &flag, sizeof (flag));
  837. if (res == -1) {
  838. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  839. "set mcast v6 TTL failed");
  840. return (-1);
  841. }
  842. } else {
  843. sflag = flag;
  844. res = setsockopt(sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_TTL,
  845. &sflag, sizeof(sflag));
  846. if (res == -1) {
  847. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  848. "set mcast v4 TTL failed");
  849. return (-1);
  850. }
  851. }
  852. /*
  853. * Bind to a specific interface for multicast send and receive
  854. */
  855. switch ( bindnet_address->family ) {
  856. case AF_INET:
  857. if (setsockopt (sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_IF,
  858. &boundto_sin->sin_addr, sizeof (boundto_sin->sin_addr)) < 0) {
  859. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  860. "cannot select interface for multicast packets (send)");
  861. return (-1);
  862. }
  863. if (setsockopt (sockets->mcast_recv, IPPROTO_IP, IP_MULTICAST_IF,
  864. &boundto_sin->sin_addr, sizeof (boundto_sin->sin_addr)) < 0) {
  865. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  866. "cannot select interface for multicast packets (recv)");
  867. return (-1);
  868. }
  869. break;
  870. case AF_INET6:
  871. if (setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_IF,
  872. &interface_num, sizeof (interface_num)) < 0) {
  873. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  874. "cannot select interface for multicast packets (send v6)");
  875. return (-1);
  876. }
  877. if (setsockopt (sockets->mcast_recv, IPPROTO_IPV6, IPV6_MULTICAST_IF,
  878. &interface_num, sizeof (interface_num)) < 0) {
  879. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  880. "cannot select interface for multicast packets (recv v6)");
  881. return (-1);
  882. }
  883. break;
  884. }
  885. /*
  886. * Bind to multicast socket used for multicast receives
  887. * This needs to happen after all of the multicast setsockopt() calls
  888. * as the kernel seems to only put them into effect (for IPV6) when bind()
  889. * is called.
  890. */
  891. totemip_totemip_to_sockaddr_convert(mcast_address,
  892. instance->totem_interface->ip_port, &sockaddr, &addrlen);
  893. retries = 0;
  894. while (1) {
  895. res = bind (sockets->mcast_recv, (struct sockaddr *)&sockaddr, addrlen);
  896. if (res == 0) {
  897. break;
  898. }
  899. LOGSYS_PERROR (errno, instance->totemudp_log_level_warning,
  900. "Unable to bind the socket to receive multicast packets");
  901. if (++retries > BIND_MAX_RETRIES) {
  902. break;
  903. }
  904. /*
  905. * Wait for a while
  906. */
  907. (void)poll(NULL, 0, BIND_RETRIES_INTERVAL * retries);
  908. }
  909. if (res == -1) {
  910. return (-1);
  911. }
  912. return 0;
  913. }
  914. static int totemudp_build_sockets (
  915. struct totemudp_instance *instance,
  916. struct totem_ip_address *mcast_address,
  917. struct totem_ip_address *bindnet_address,
  918. struct totemudp_socket *sockets,
  919. struct totem_ip_address *bound_to)
  920. {
  921. int interface_num;
  922. int interface_up;
  923. int res;
  924. /*
  925. * Determine the ip address bound to and the interface name
  926. */
  927. res = netif_determine (instance,
  928. bindnet_address,
  929. bound_to,
  930. &interface_up,
  931. &interface_num);
  932. if (res == -1) {
  933. return (-1);
  934. }
  935. totemip_copy(&instance->my_id, bound_to);
  936. res = totemudp_build_sockets_ip (instance, mcast_address,
  937. bindnet_address, sockets, bound_to, interface_num);
  938. if (res == -1) {
  939. /* if we get here, corosync won't work anyway, so better leaving than faking to work */
  940. LOGSYS_PERROR (errno, instance->totemudp_log_level_error,
  941. "Unable to create sockets, exiting");
  942. exit(EXIT_FAILURE);
  943. }
  944. /* We only send out of the token socket */
  945. totemudp_traffic_control_set(instance, sockets->token);
  946. return res;
  947. }
  948. /*
  949. * Totem Network interface
  950. * depends on poll abstraction, POSIX, IPV4
  951. */
  952. /*
  953. * Create an instance
  954. */
  955. int totemudp_initialize (
  956. qb_loop_t *poll_handle,
  957. void **udp_context,
  958. struct totem_config *totem_config,
  959. totemsrp_stats_t *stats,
  960. void *context,
  961. void (*deliver_fn) (
  962. void *context,
  963. const void *msg,
  964. unsigned int msg_len),
  965. void (*iface_change_fn) (
  966. void *context,
  967. const struct totem_ip_address *iface_address,
  968. unsigned int ring_no),
  969. void (*mtu_changed) (
  970. void *context,
  971. int net_mtu),
  972. void (*target_set_completed) (
  973. void *context))
  974. {
  975. struct totemudp_instance *instance;
  976. instance = malloc (sizeof (struct totemudp_instance));
  977. if (instance == NULL) {
  978. return (-1);
  979. }
  980. totemudp_instance_initialize (instance);
  981. instance->totem_config = totem_config;
  982. instance->stats = stats;
  983. /*
  984. * Configure logging
  985. */
  986. instance->totemudp_log_level_security = 1; //totem_config->totem_logging_configuration.log_level_security;
  987. instance->totemudp_log_level_error = totem_config->totem_logging_configuration.log_level_error;
  988. instance->totemudp_log_level_warning = totem_config->totem_logging_configuration.log_level_warning;
  989. instance->totemudp_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
  990. instance->totemudp_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
  991. instance->totemudp_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
  992. instance->totemudp_log_printf = totem_config->totem_logging_configuration.log_printf;
  993. /*
  994. * Initialize local variables for totemudp
  995. */
  996. instance->totem_interface = &totem_config->interfaces[0];
  997. totemip_copy (&instance->mcast_address, &instance->totem_interface->mcast_addr);
  998. memset (instance->iov_buffer, 0, FRAME_SIZE_MAX);
  999. instance->totemudp_poll_handle = poll_handle;
  1000. instance->totem_interface->bindnet.nodeid = instance->totem_config->node_id;
  1001. instance->context = context;
  1002. instance->totemudp_deliver_fn = deliver_fn;
  1003. instance->totemudp_iface_change_fn = iface_change_fn;
  1004. instance->totemudp_target_set_completed = target_set_completed;
  1005. totemip_localhost (instance->mcast_address.family, &localhost);
  1006. localhost.nodeid = instance->totem_config->node_id;
  1007. /*
  1008. * RRP layer isn't ready to receive message because it hasn't
  1009. * initialized yet. Add short timer to check the interfaces.
  1010. */
  1011. qb_loop_timer_add (instance->totemudp_poll_handle,
  1012. QB_LOOP_MED,
  1013. 100*QB_TIME_NS_IN_MSEC,
  1014. (void *)instance,
  1015. timer_function_netif_check_timeout,
  1016. &instance->timer_netif_check_timeout);
  1017. *udp_context = instance;
  1018. return (0);
  1019. }
  1020. void *totemudp_buffer_alloc (void)
  1021. {
  1022. return malloc (FRAME_SIZE_MAX);
  1023. }
  1024. void totemudp_buffer_release (void *ptr)
  1025. {
  1026. return free (ptr);
  1027. }
  1028. int totemudp_processor_count_set (
  1029. void *udp_context,
  1030. int processor_count)
  1031. {
  1032. struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
  1033. int res = 0;
  1034. instance->my_memb_entries = processor_count;
  1035. qb_loop_timer_del (instance->totemudp_poll_handle,
  1036. instance->timer_netif_check_timeout);
  1037. if (processor_count == 1) {
  1038. qb_loop_timer_add (instance->totemudp_poll_handle,
  1039. QB_LOOP_MED,
  1040. instance->totem_config->downcheck_timeout*QB_TIME_NS_IN_MSEC,
  1041. (void *)instance,
  1042. timer_function_netif_check_timeout,
  1043. &instance->timer_netif_check_timeout);
  1044. }
  1045. return (res);
  1046. }
  1047. int totemudp_recv_flush (void *udp_context)
  1048. {
  1049. struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
  1050. struct pollfd ufd;
  1051. int nfds;
  1052. int res = 0;
  1053. int i;
  1054. int sock;
  1055. instance->flushing = 1;
  1056. for (i = 0; i < 2; i++) {
  1057. sock = -1;
  1058. if (i == 0) {
  1059. sock = instance->totemudp_sockets.mcast_recv;
  1060. }
  1061. if (i == 1) {
  1062. sock = instance->totemudp_sockets.local_mcast_loop[0];
  1063. }
  1064. assert(sock != -1);
  1065. do {
  1066. ufd.fd = sock;
  1067. ufd.events = POLLIN;
  1068. nfds = poll (&ufd, 1, 0);
  1069. if (nfds == 1 && ufd.revents & POLLIN) {
  1070. net_deliver_fn (sock, ufd.revents, instance);
  1071. }
  1072. } while (nfds == 1);
  1073. }
  1074. instance->flushing = 0;
  1075. return (res);
  1076. }
  1077. int totemudp_send_flush (void *udp_context)
  1078. {
  1079. return 0;
  1080. }
  1081. int totemudp_token_send (
  1082. void *udp_context,
  1083. const void *msg,
  1084. unsigned int msg_len)
  1085. {
  1086. struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
  1087. int res = 0;
  1088. ucast_sendmsg (instance, &instance->token_target, msg, msg_len);
  1089. return (res);
  1090. }
  1091. int totemudp_mcast_flush_send (
  1092. void *udp_context,
  1093. const void *msg,
  1094. unsigned int msg_len)
  1095. {
  1096. struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
  1097. int res = 0;
  1098. mcast_sendmsg (instance, msg, msg_len);
  1099. return (res);
  1100. }
  1101. int totemudp_mcast_noflush_send (
  1102. void *udp_context,
  1103. const void *msg,
  1104. unsigned int msg_len)
  1105. {
  1106. struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
  1107. int res = 0;
  1108. mcast_sendmsg (instance, msg, msg_len);
  1109. return (res);
  1110. }
  1111. extern int totemudp_iface_check (void *udp_context)
  1112. {
  1113. struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
  1114. int res = 0;
  1115. timer_function_netif_check_timeout (instance);
  1116. return (res);
  1117. }
  1118. int totemudp_ifaces_get (
  1119. void *net_context,
  1120. char ***status,
  1121. unsigned int *iface_count)
  1122. {
  1123. static char *statuses[INTERFACE_MAX] = {(char*)"OK"};
  1124. if (status) {
  1125. *status = statuses;
  1126. }
  1127. *iface_count = 1;
  1128. return (0);
  1129. }
  1130. extern void totemudp_net_mtu_adjust (void *udp_context, struct totem_config *totem_config)
  1131. {
  1132. totem_config->net_mtu -= totemip_udpip_header_size(totem_config->interfaces[0].bindnet.family);
  1133. }
  1134. int totemudp_token_target_set (
  1135. void *udp_context,
  1136. const struct totem_ip_address *token_target)
  1137. {
  1138. struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
  1139. int res = 0;
  1140. memcpy (&instance->token_target, token_target,
  1141. sizeof (struct totem_ip_address));
  1142. instance->totemudp_target_set_completed (instance->context);
  1143. return (res);
  1144. }
  1145. extern int totemudp_recv_mcast_empty (
  1146. void *udp_context)
  1147. {
  1148. struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
  1149. unsigned int res;
  1150. struct sockaddr_storage system_from;
  1151. struct msghdr msg_recv;
  1152. struct pollfd ufd;
  1153. int nfds;
  1154. int msg_processed = 0;
  1155. int i;
  1156. int sock;
  1157. /*
  1158. * Receive datagram
  1159. */
  1160. msg_recv.msg_name = &system_from;
  1161. msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
  1162. msg_recv.msg_iov = &instance->totemudp_iov_recv_flush;
  1163. msg_recv.msg_iovlen = 1;
  1164. #ifdef HAVE_MSGHDR_CONTROL
  1165. msg_recv.msg_control = 0;
  1166. #endif
  1167. #ifdef HAVE_MSGHDR_CONTROLLEN
  1168. msg_recv.msg_controllen = 0;
  1169. #endif
  1170. #ifdef HAVE_MSGHDR_FLAGS
  1171. msg_recv.msg_flags = 0;
  1172. #endif
  1173. #ifdef HAVE_MSGHDR_ACCRIGHTS
  1174. msg_recv.msg_accrights = NULL;
  1175. #endif
  1176. #ifdef HAVE_MSGHDR_ACCRIGHTSLEN
  1177. msg_recv.msg_accrightslen = 0;
  1178. #endif
  1179. for (i = 0; i < 2; i++) {
  1180. sock = -1;
  1181. if (i == 0) {
  1182. sock = instance->totemudp_sockets.mcast_recv;
  1183. }
  1184. if (i == 1) {
  1185. sock = instance->totemudp_sockets.local_mcast_loop[0];
  1186. }
  1187. assert(sock != -1);
  1188. do {
  1189. ufd.fd = sock;
  1190. ufd.events = POLLIN;
  1191. nfds = poll (&ufd, 1, 0);
  1192. if (nfds == 1 && ufd.revents & POLLIN) {
  1193. res = recvmsg (sock, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
  1194. if (res != -1) {
  1195. msg_processed = 1;
  1196. } else {
  1197. msg_processed = -1;
  1198. }
  1199. }
  1200. } while (nfds == 1);
  1201. }
  1202. return (msg_processed);
  1203. }
  1204. int totemudp_iface_set (void *net_context,
  1205. const struct totem_ip_address *local_addr,
  1206. unsigned short ip_port,
  1207. unsigned int iface_no)
  1208. {
  1209. /* Not supported */
  1210. return (-1);
  1211. }