]> git.proxmox.com Git - mirror_kronosnet.git/blob - libknet/links.c
[logging] fix log target of recently added API calls
[mirror_kronosnet.git] / libknet / links.c
1 /*
2 * Copyright (C) 2012-2019 Red Hat, Inc. All rights reserved.
3 *
4 * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
5 * Federico Simoncelli <fsimon@kronosnet.org>
6 *
7 * This software licensed under GPL-2.0+, LGPL-2.0+
8 */
9
10 #include "config.h"
11
12 #include <errno.h>
13 #include <netdb.h>
14 #include <string.h>
15 #include <pthread.h>
16
17 #include "internals.h"
18 #include "logging.h"
19 #include "links.h"
20 #include "transports.h"
21 #include "host.h"
22 #include "threads_common.h"
23 #include "links_acl.h"
24
25 int _link_updown(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
26 unsigned int enabled, unsigned int connected)
27 {
28 struct knet_link *link = &knet_h->host_index[host_id]->link[link_id];
29
30 if ((link->status.enabled == enabled) &&
31 (link->status.connected == connected))
32 return 0;
33
34 link->status.enabled = enabled;
35 link->status.connected = connected;
36
37 _host_dstcache_update_async(knet_h, knet_h->host_index[host_id]);
38
39 if ((link->status.dynconnected) &&
40 (!link->status.connected))
41 link->status.dynconnected = 0;
42
43 if (connected) {
44 time(&link->status.stats.last_up_times[link->status.stats.last_up_time_index]);
45 link->status.stats.up_count++;
46 if (++link->status.stats.last_up_time_index > MAX_LINK_EVENTS) {
47 link->status.stats.last_up_time_index = 0;
48 }
49 } else {
50 time(&link->status.stats.last_down_times[link->status.stats.last_down_time_index]);
51 link->status.stats.down_count++;
52 if (++link->status.stats.last_down_time_index > MAX_LINK_EVENTS) {
53 link->status.stats.last_down_time_index = 0;
54 }
55 }
56 return 0;
57 }
58
59 void _link_clear_stats(knet_handle_t knet_h)
60 {
61 struct knet_host *host;
62 struct knet_link *link;
63 uint32_t host_id;
64 uint8_t link_id;
65
66 for (host_id = 0; host_id < KNET_MAX_HOST; host_id++) {
67 host = knet_h->host_index[host_id];
68 if (!host) {
69 continue;
70 }
71 for (link_id = 0; link_id < KNET_MAX_LINK; link_id++) {
72 link = &host->link[link_id];
73 memset(&link->status.stats, 0, sizeof(struct knet_link_stats));
74 }
75 }
76 }
77
78 int knet_link_set_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
79 uint8_t transport,
80 struct sockaddr_storage *src_addr,
81 struct sockaddr_storage *dst_addr,
82 uint64_t flags)
83 {
84 int savederrno = 0, err = 0, i;
85 struct knet_host *host;
86 struct knet_link *link;
87
88 if (!knet_h) {
89 errno = EINVAL;
90 return -1;
91 }
92
93 if (link_id >= KNET_MAX_LINK) {
94 errno = EINVAL;
95 return -1;
96 }
97
98 if (!src_addr) {
99 errno = EINVAL;
100 return -1;
101 }
102
103 if (dst_addr && (src_addr->ss_family != dst_addr->ss_family)) {
104 log_err(knet_h, KNET_SUB_LINK, "Source address family does not match destination address family");
105 errno = EINVAL;
106 return -1;
107 }
108
109 if (transport >= KNET_MAX_TRANSPORTS) {
110 errno = EINVAL;
111 return -1;
112 }
113
114 savederrno = get_global_wrlock(knet_h);
115 if (savederrno) {
116 log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
117 strerror(savederrno));
118 errno = savederrno;
119 return -1;
120 }
121
122 if (transport == KNET_TRANSPORT_LOOPBACK && knet_h->host_id != host_id) {
123 log_err(knet_h, KNET_SUB_LINK, "Cannot create loopback link to remote node");
124 err = -1;
125 savederrno = EINVAL;
126 goto exit_unlock;
127 }
128
129 if (knet_h->host_id == host_id && knet_h->has_loop_link) {
130 log_err(knet_h, KNET_SUB_LINK, "Cannot create more than 1 link when loopback is active");
131 err = -1;
132 savederrno = EINVAL;
133 goto exit_unlock;
134 }
135
136 host = knet_h->host_index[host_id];
137 if (!host) {
138 err = -1;
139 savederrno = EINVAL;
140 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
141 host_id, strerror(savederrno));
142 goto exit_unlock;
143 }
144
145 if (transport == KNET_TRANSPORT_LOOPBACK && knet_h->host_id == host_id) {
146 for (i=0; i<KNET_MAX_LINK; i++) {
147 if (host->link[i].configured) {
148 log_err(knet_h, KNET_SUB_LINK, "Cannot add loopback link when other links are already configured.");
149 err = -1;
150 savederrno = EINVAL;
151 goto exit_unlock;
152 }
153 }
154 }
155
156 link = &host->link[link_id];
157
158 if (link->configured != 0) {
159 err =-1;
160 savederrno = EBUSY;
161 log_err(knet_h, KNET_SUB_LINK, "Host %u link %u is currently configured: %s",
162 host_id, link_id, strerror(savederrno));
163 goto exit_unlock;
164 }
165
166 if (link->status.enabled != 0) {
167 err =-1;
168 savederrno = EBUSY;
169 log_err(knet_h, KNET_SUB_LINK, "Host %u link %u is currently in use: %s",
170 host_id, link_id, strerror(savederrno));
171 goto exit_unlock;
172 }
173
174 memmove(&link->src_addr, src_addr, sizeof(struct sockaddr_storage));
175
176 err = knet_addrtostr(src_addr, sizeof(struct sockaddr_storage),
177 link->status.src_ipaddr, KNET_MAX_HOST_LEN,
178 link->status.src_port, KNET_MAX_PORT_LEN);
179 if (err) {
180 if (err == EAI_SYSTEM) {
181 savederrno = errno;
182 log_warn(knet_h, KNET_SUB_LINK,
183 "Unable to resolve host: %u link: %u source addr/port: %s",
184 host_id, link_id, strerror(savederrno));
185 } else {
186 savederrno = EINVAL;
187 log_warn(knet_h, KNET_SUB_LINK,
188 "Unable to resolve host: %u link: %u source addr/port: %s",
189 host_id, link_id, gai_strerror(err));
190 }
191 err = -1;
192 goto exit_unlock;
193 }
194
195 if (!dst_addr) {
196 link->dynamic = KNET_LINK_DYNIP;
197 } else {
198
199 link->dynamic = KNET_LINK_STATIC;
200
201 memmove(&link->dst_addr, dst_addr, sizeof(struct sockaddr_storage));
202 err = knet_addrtostr(dst_addr, sizeof(struct sockaddr_storage),
203 link->status.dst_ipaddr, KNET_MAX_HOST_LEN,
204 link->status.dst_port, KNET_MAX_PORT_LEN);
205 if (err) {
206 if (err == EAI_SYSTEM) {
207 savederrno = errno;
208 log_warn(knet_h, KNET_SUB_LINK,
209 "Unable to resolve host: %u link: %u destination addr/port: %s",
210 host_id, link_id, strerror(savederrno));
211 } else {
212 savederrno = EINVAL;
213 log_warn(knet_h, KNET_SUB_LINK,
214 "Unable to resolve host: %u link: %u destination addr/port: %s",
215 host_id, link_id, gai_strerror(err));
216 }
217 err = -1;
218 goto exit_unlock;
219 }
220 }
221
222 link->pong_count = KNET_LINK_DEFAULT_PONG_COUNT;
223 link->has_valid_mtu = 0;
224 link->ping_interval = KNET_LINK_DEFAULT_PING_INTERVAL * 1000; /* microseconds */
225 link->pong_timeout = KNET_LINK_DEFAULT_PING_TIMEOUT * 1000; /* microseconds */
226 link->pong_timeout_backoff = KNET_LINK_PONG_TIMEOUT_BACKOFF;
227 link->pong_timeout_adj = link->pong_timeout * link->pong_timeout_backoff; /* microseconds */
228 link->latency_fix = KNET_LINK_DEFAULT_PING_PRECISION;
229 link->latency_exp = KNET_LINK_DEFAULT_PING_PRECISION - \
230 ((link->ping_interval * KNET_LINK_DEFAULT_PING_PRECISION) / 8000000);
231 link->flags = flags;
232
233 if (transport_link_set_config(knet_h, link, transport) < 0) {
234 savederrno = errno;
235 err = -1;
236 goto exit_unlock;
237 }
238
239 /*
240 * we can only configure default access lists if we know both endpoints
241 * and the protocol uses GENERIC_ACL, otherwise the protocol has
242 * to setup their own access lists above in transport_link_set_config.
243 */
244 if ((transport_get_acl_type(knet_h, transport) == USE_GENERIC_ACL) &&
245 (link->dynamic == KNET_LINK_STATIC)) {
246 log_debug(knet_h, KNET_SUB_LINK, "Configuring default access lists for host: %u link: %u socket: %d",
247 host_id, link_id, link->outsock);
248 if ((check_add(knet_h, link->outsock, transport, -1,
249 &link->dst_addr, &link->dst_addr,
250 CHECK_TYPE_ADDRESS, CHECK_ACCEPT) < 0) && (errno != EEXIST)) {
251 log_warn(knet_h, KNET_SUB_LINK, "Failed to configure default access lists for host: %u link: %u", host_id, link_id);
252 savederrno = errno;
253 err = -1;
254 goto exit_unlock;
255 }
256 }
257
258 link->configured = 1;
259 log_debug(knet_h, KNET_SUB_LINK, "host: %u link: %u is configured",
260 host_id, link_id);
261
262 if (transport == KNET_TRANSPORT_LOOPBACK) {
263 knet_h->has_loop_link = 1;
264 knet_h->loop_link = link_id;
265 host->status.reachable = 1;
266 link->status.mtu = KNET_PMTUD_SIZE_V6;
267 } else {
268 link->status.mtu = KNET_PMTUD_MIN_MTU_V4 - KNET_HEADER_ALL_SIZE - knet_h->sec_header_size;
269 link->has_valid_mtu = 1;
270 }
271
272 exit_unlock:
273 pthread_rwlock_unlock(&knet_h->global_rwlock);
274 errno = err ? savederrno : 0;
275 return err;
276 }
277
278 int knet_link_get_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
279 uint8_t *transport,
280 struct sockaddr_storage *src_addr,
281 struct sockaddr_storage *dst_addr,
282 uint8_t *dynamic,
283 uint64_t *flags)
284 {
285 int savederrno = 0, err = 0;
286 struct knet_host *host;
287 struct knet_link *link;
288
289 if (!knet_h) {
290 errno = EINVAL;
291 return -1;
292 }
293
294 if (link_id >= KNET_MAX_LINK) {
295 errno = EINVAL;
296 return -1;
297 }
298
299 if (!src_addr) {
300 errno = EINVAL;
301 return -1;
302 }
303
304 if (!dynamic) {
305 errno = EINVAL;
306 return -1;
307 }
308
309 if (!transport) {
310 errno = EINVAL;
311 return -1;
312 }
313
314 if (!flags) {
315 errno = EINVAL;
316 return -1;
317 }
318
319 savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
320 if (savederrno) {
321 log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
322 strerror(savederrno));
323 errno = savederrno;
324 return -1;
325 }
326
327 host = knet_h->host_index[host_id];
328 if (!host) {
329 err = -1;
330 savederrno = EINVAL;
331 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
332 host_id, strerror(savederrno));
333 goto exit_unlock;
334 }
335
336 link = &host->link[link_id];
337
338 if (!link->configured) {
339 err = -1;
340 savederrno = EINVAL;
341 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
342 host_id, link_id, strerror(savederrno));
343 goto exit_unlock;
344 }
345
346 if ((link->dynamic == KNET_LINK_STATIC) && (!dst_addr)) {
347 savederrno = EINVAL;
348 err = -1;
349 goto exit_unlock;
350 }
351
352 memmove(src_addr, &link->src_addr, sizeof(struct sockaddr_storage));
353
354 *transport = link->transport;
355 *flags = link->flags;
356
357 if (link->dynamic == KNET_LINK_STATIC) {
358 *dynamic = 0;
359 memmove(dst_addr, &link->dst_addr, sizeof(struct sockaddr_storage));
360 } else {
361 *dynamic = 1;
362 }
363
364 exit_unlock:
365 pthread_rwlock_unlock(&knet_h->global_rwlock);
366 errno = err ? savederrno : 0;
367 return err;
368 }
369
370 int knet_link_clear_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id)
371 {
372 int savederrno = 0, err = 0;
373 struct knet_host *host;
374 struct knet_link *link;
375 int sock;
376 uint8_t transport;
377
378 if (!knet_h) {
379 errno = EINVAL;
380 return -1;
381 }
382
383 if (link_id >= KNET_MAX_LINK) {
384 errno = EINVAL;
385 return -1;
386 }
387
388 savederrno = get_global_wrlock(knet_h);
389 if (savederrno) {
390 log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
391 strerror(savederrno));
392 errno = savederrno;
393 return -1;
394 }
395
396 host = knet_h->host_index[host_id];
397 if (!host) {
398 err = -1;
399 savederrno = EINVAL;
400 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
401 host_id, strerror(savederrno));
402 goto exit_unlock;
403 }
404
405 link = &host->link[link_id];
406
407 if (link->configured != 1) {
408 err = -1;
409 savederrno = EINVAL;
410 log_err(knet_h, KNET_SUB_LINK, "Host %u link %u is not configured: %s",
411 host_id, link_id, strerror(savederrno));
412 goto exit_unlock;
413 }
414
415 if (link->status.enabled != 0) {
416 err = -1;
417 savederrno = EBUSY;
418 log_err(knet_h, KNET_SUB_LINK, "Host %u link %u is currently in use: %s",
419 host_id, link_id, strerror(savederrno));
420 goto exit_unlock;
421 }
422
423 /*
424 * remove well known access lists here.
425 * After the transport has done clearing the config,
426 * then we can remove any leftover access lists if the link
427 * is no longer in use.
428 */
429 if ((transport_get_acl_type(knet_h, link->transport) == USE_GENERIC_ACL) &&
430 (link->dynamic == KNET_LINK_STATIC)) {
431 if ((check_rm(knet_h, link->outsock, link->transport,
432 &link->dst_addr, &link->dst_addr,
433 CHECK_TYPE_ADDRESS, CHECK_ACCEPT) < 0) && (errno != ENOENT)) {
434 err = -1;
435 savederrno = errno;
436 log_err(knet_h, KNET_SUB_LINK, "Host %u link %u: unable to remove default access list",
437 host_id, link_id);
438 goto exit_unlock;
439 }
440 }
441
442 /*
443 * cache it for later as we don't know if the transport
444 * will clear link info during clear_config.
445 */
446 sock = link->outsock;
447 transport = link->transport;
448
449 if ((transport_link_clear_config(knet_h, link) < 0) &&
450 (errno != EBUSY)) {
451 savederrno = errno;
452 err = -1;
453 goto exit_unlock;
454 }
455
456 /*
457 * remove any other access lists when the socket is no
458 * longer in use by the transport.
459 */
460 if ((transport_get_acl_type(knet_h, link->transport) == USE_GENERIC_ACL) &&
461 (knet_h->knet_transport_fd_tracker[sock].transport == KNET_MAX_TRANSPORTS)) {
462 check_rmall(knet_h, sock, transport);
463 }
464
465 memset(link, 0, sizeof(struct knet_link));
466 link->link_id = link_id;
467
468 if (knet_h->has_loop_link && host_id == knet_h->host_id && link_id == knet_h->loop_link) {
469 knet_h->has_loop_link = 0;
470 if (host->active_link_entries == 0) {
471 host->status.reachable = 0;
472 }
473 }
474
475 log_debug(knet_h, KNET_SUB_LINK, "host: %u link: %u config has been wiped",
476 host_id, link_id);
477
478 exit_unlock:
479 pthread_rwlock_unlock(&knet_h->global_rwlock);
480 errno = err ? savederrno : 0;
481 return err;
482 }
483
484 int knet_link_set_enable(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
485 unsigned int enabled)
486 {
487 int savederrno = 0, err = 0;
488 struct knet_host *host;
489 struct knet_link *link;
490
491 if (!knet_h) {
492 errno = EINVAL;
493 return -1;
494 }
495
496 if (link_id >= KNET_MAX_LINK) {
497 errno = EINVAL;
498 return -1;
499 }
500
501 if (enabled > 1) {
502 errno = EINVAL;
503 return -1;
504 }
505
506 savederrno = get_global_wrlock(knet_h);
507 if (savederrno) {
508 log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
509 strerror(savederrno));
510 errno = savederrno;
511 return -1;
512 }
513
514 host = knet_h->host_index[host_id];
515 if (!host) {
516 err = -1;
517 savederrno = EINVAL;
518 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
519 host_id, strerror(savederrno));
520 goto exit_unlock;
521 }
522
523 link = &host->link[link_id];
524
525 if (!link->configured) {
526 err = -1;
527 savederrno = EINVAL;
528 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
529 host_id, link_id, strerror(savederrno));
530 goto exit_unlock;
531 }
532
533 if (link->status.enabled == enabled) {
534 err = 0;
535 goto exit_unlock;
536 }
537
538 err = _link_updown(knet_h, host_id, link_id, enabled, link->status.connected);
539 savederrno = errno;
540
541 if (enabled) {
542 goto exit_unlock;
543 }
544
545 log_debug(knet_h, KNET_SUB_LINK, "host: %u link: %u is disabled",
546 host_id, link_id);
547
548 exit_unlock:
549 pthread_rwlock_unlock(&knet_h->global_rwlock);
550 errno = err ? savederrno : 0;
551 return err;
552 }
553
554 int knet_link_get_enable(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
555 unsigned int *enabled)
556 {
557 int savederrno = 0, err = 0;
558 struct knet_host *host;
559 struct knet_link *link;
560
561 if (!knet_h) {
562 errno = EINVAL;
563 return -1;
564 }
565
566 if (link_id >= KNET_MAX_LINK) {
567 errno = EINVAL;
568 return -1;
569 }
570
571 if (!enabled) {
572 errno = EINVAL;
573 return -1;
574 }
575
576 savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
577 if (savederrno) {
578 log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
579 strerror(savederrno));
580 errno = savederrno;
581 return -1;
582 }
583
584 host = knet_h->host_index[host_id];
585 if (!host) {
586 err = -1;
587 savederrno = EINVAL;
588 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
589 host_id, strerror(savederrno));
590 goto exit_unlock;
591 }
592
593 link = &host->link[link_id];
594
595 if (!link->configured) {
596 err = -1;
597 savederrno = EINVAL;
598 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
599 host_id, link_id, strerror(savederrno));
600 goto exit_unlock;
601 }
602
603 *enabled = link->status.enabled;
604
605 exit_unlock:
606 pthread_rwlock_unlock(&knet_h->global_rwlock);
607 errno = err ? savederrno : 0;
608 return err;
609 }
610
611 int knet_link_set_pong_count(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
612 uint8_t pong_count)
613 {
614 int savederrno = 0, err = 0;
615 struct knet_host *host;
616 struct knet_link *link;
617
618 if (!knet_h) {
619 errno = EINVAL;
620 return -1;
621 }
622
623 if (link_id >= KNET_MAX_LINK) {
624 errno = EINVAL;
625 return -1;
626 }
627
628 if (pong_count < 1) {
629 errno = EINVAL;
630 return -1;
631 }
632
633 savederrno = get_global_wrlock(knet_h);
634 if (savederrno) {
635 log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
636 strerror(savederrno));
637 errno = savederrno;
638 return -1;
639 }
640
641 host = knet_h->host_index[host_id];
642 if (!host) {
643 err = -1;
644 savederrno = EINVAL;
645 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
646 host_id, strerror(savederrno));
647 goto exit_unlock;
648 }
649
650 link = &host->link[link_id];
651
652 if (!link->configured) {
653 err = -1;
654 savederrno = EINVAL;
655 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
656 host_id, link_id, strerror(savederrno));
657 goto exit_unlock;
658 }
659
660 link->pong_count = pong_count;
661
662 log_debug(knet_h, KNET_SUB_LINK,
663 "host: %u link: %u pong count update: %u",
664 host_id, link_id, link->pong_count);
665
666 exit_unlock:
667 pthread_rwlock_unlock(&knet_h->global_rwlock);
668 errno = err ? savederrno : 0;
669 return err;
670 }
671
672 int knet_link_get_pong_count(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
673 uint8_t *pong_count)
674 {
675 int savederrno = 0, err = 0;
676 struct knet_host *host;
677 struct knet_link *link;
678
679 if (!knet_h) {
680 errno = EINVAL;
681 return -1;
682 }
683
684 if (link_id >= KNET_MAX_LINK) {
685 errno = EINVAL;
686 return -1;
687 }
688
689 if (!pong_count) {
690 errno = EINVAL;
691 return -1;
692 }
693
694 savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
695 if (savederrno) {
696 log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
697 strerror(savederrno));
698 errno = savederrno;
699 return -1;
700 }
701
702 host = knet_h->host_index[host_id];
703 if (!host) {
704 err = -1;
705 savederrno = EINVAL;
706 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
707 host_id, strerror(savederrno));
708 goto exit_unlock;
709 }
710
711 link = &host->link[link_id];
712
713 if (!link->configured) {
714 err = -1;
715 savederrno = EINVAL;
716 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
717 host_id, link_id, strerror(savederrno));
718 goto exit_unlock;
719 }
720
721 *pong_count = link->pong_count;
722
723 exit_unlock:
724 pthread_rwlock_unlock(&knet_h->global_rwlock);
725 errno = err ? savederrno : 0;
726 return err;
727 }
728
729 int knet_link_set_ping_timers(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
730 time_t interval, time_t timeout, unsigned int precision)
731 {
732 int savederrno = 0, err = 0;
733 struct knet_host *host;
734 struct knet_link *link;
735
736 if (!knet_h) {
737 errno = EINVAL;
738 return -1;
739 }
740
741 if (link_id >= KNET_MAX_LINK) {
742 errno = EINVAL;
743 return -1;
744 }
745
746 if (!interval) {
747 errno = EINVAL;
748 return -1;
749 }
750
751 if (!timeout) {
752 errno = ENOSYS;
753 return -1;
754 }
755
756 if (!precision) {
757 errno = EINVAL;
758 return -1;
759 }
760
761 savederrno = get_global_wrlock(knet_h);
762 if (savederrno) {
763 log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
764 strerror(savederrno));
765 errno = savederrno;
766 return -1;
767 }
768
769 host = knet_h->host_index[host_id];
770 if (!host) {
771 err = -1;
772 savederrno = EINVAL;
773 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
774 host_id, strerror(savederrno));
775 goto exit_unlock;
776 }
777
778 link = &host->link[link_id];
779
780 if (!link->configured) {
781 err = -1;
782 savederrno = EINVAL;
783 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
784 host_id, link_id, strerror(savederrno));
785 goto exit_unlock;
786 }
787
788 link->ping_interval = interval * 1000; /* microseconds */
789 link->pong_timeout = timeout * 1000; /* microseconds */
790 link->latency_fix = precision;
791 link->latency_exp = precision - \
792 ((link->ping_interval * precision) / 8000000);
793
794 log_debug(knet_h, KNET_SUB_LINK,
795 "host: %u link: %u timeout update - interval: %llu timeout: %llu precision: %u",
796 host_id, link_id, link->ping_interval, link->pong_timeout, precision);
797
798 exit_unlock:
799 pthread_rwlock_unlock(&knet_h->global_rwlock);
800 errno = err ? savederrno : 0;
801 return err;
802 }
803
804 int knet_link_get_ping_timers(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
805 time_t *interval, time_t *timeout, unsigned int *precision)
806 {
807 int savederrno = 0, err = 0;
808 struct knet_host *host;
809 struct knet_link *link;
810
811 if (!knet_h) {
812 errno = EINVAL;
813 return -1;
814 }
815
816 if (link_id >= KNET_MAX_LINK) {
817 errno = EINVAL;
818 return -1;
819 }
820
821 if (!interval) {
822 errno = EINVAL;
823 return -1;
824 }
825
826 if (!timeout) {
827 errno = EINVAL;
828 return -1;
829 }
830
831 if (!precision) {
832 errno = EINVAL;
833 return -1;
834 }
835
836 savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
837 if (savederrno) {
838 log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
839 strerror(savederrno));
840 errno = savederrno;
841 return -1;
842 }
843
844 host = knet_h->host_index[host_id];
845 if (!host) {
846 err = -1;
847 savederrno = EINVAL;
848 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
849 host_id, strerror(savederrno));
850 goto exit_unlock;
851 }
852
853 link = &host->link[link_id];
854
855 if (!link->configured) {
856 err = -1;
857 savederrno = EINVAL;
858 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
859 host_id, link_id, strerror(savederrno));
860 goto exit_unlock;
861 }
862
863 *interval = link->ping_interval / 1000; /* microseconds */
864 *timeout = link->pong_timeout / 1000;
865 *precision = link->latency_fix;
866
867 exit_unlock:
868 pthread_rwlock_unlock(&knet_h->global_rwlock);
869 errno = err ? savederrno : 0;
870 return err;
871 }
872
873 int knet_link_set_priority(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
874 uint8_t priority)
875 {
876 int savederrno = 0, err = 0;
877 struct knet_host *host;
878 struct knet_link *link;
879 uint8_t old_priority;
880
881 if (!knet_h) {
882 errno = EINVAL;
883 return -1;
884 }
885
886 if (link_id >= KNET_MAX_LINK) {
887 errno = EINVAL;
888 return -1;
889 }
890
891 savederrno = get_global_wrlock(knet_h);
892 if (savederrno) {
893 log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
894 strerror(savederrno));
895 errno = savederrno;
896 return -1;
897 }
898
899 host = knet_h->host_index[host_id];
900 if (!host) {
901 err = -1;
902 savederrno = EINVAL;
903 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
904 host_id, strerror(savederrno));
905 goto exit_unlock;
906 }
907
908 link = &host->link[link_id];
909
910 if (!link->configured) {
911 err = -1;
912 savederrno = EINVAL;
913 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
914 host_id, link_id, strerror(savederrno));
915 goto exit_unlock;
916 }
917
918 old_priority = link->priority;
919
920 if (link->priority == priority) {
921 err = 0;
922 goto exit_unlock;
923 }
924
925 link->priority = priority;
926
927 if (_host_dstcache_update_sync(knet_h, host)) {
928 savederrno = errno;
929 log_debug(knet_h, KNET_SUB_LINK,
930 "Unable to update link priority (host: %u link: %u priority: %u): %s",
931 host_id, link_id, link->priority, strerror(savederrno));
932 link->priority = old_priority;
933 err = -1;
934 goto exit_unlock;
935 }
936
937 log_debug(knet_h, KNET_SUB_LINK,
938 "host: %u link: %u priority set to: %u",
939 host_id, link_id, link->priority);
940
941 exit_unlock:
942 pthread_rwlock_unlock(&knet_h->global_rwlock);
943 errno = err ? savederrno : 0;
944 return err;
945 }
946
947 int knet_link_get_priority(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
948 uint8_t *priority)
949 {
950 int savederrno = 0, err = 0;
951 struct knet_host *host;
952 struct knet_link *link;
953
954 if (!knet_h) {
955 errno = EINVAL;
956 return -1;
957 }
958
959 if (link_id >= KNET_MAX_LINK) {
960 errno = EINVAL;
961 return -1;
962 }
963
964 if (!priority) {
965 errno = EINVAL;
966 return -1;
967 }
968
969 savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
970 if (savederrno) {
971 log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
972 strerror(savederrno));
973 errno = savederrno;
974 return -1;
975 }
976
977 host = knet_h->host_index[host_id];
978 if (!host) {
979 err = -1;
980 savederrno = EINVAL;
981 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
982 host_id, strerror(savederrno));
983 goto exit_unlock;
984 }
985
986 link = &host->link[link_id];
987
988 if (!link->configured) {
989 err = -1;
990 savederrno = EINVAL;
991 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
992 host_id, link_id, strerror(savederrno));
993 goto exit_unlock;
994 }
995
996 *priority = link->priority;
997
998 exit_unlock:
999 pthread_rwlock_unlock(&knet_h->global_rwlock);
1000 errno = err ? savederrno : 0;
1001 return err;
1002 }
1003
1004 int knet_link_get_link_list(knet_handle_t knet_h, knet_node_id_t host_id,
1005 uint8_t *link_ids, size_t *link_ids_entries)
1006 {
1007 int savederrno = 0, err = 0, i, count = 0;
1008 struct knet_host *host;
1009 struct knet_link *link;
1010
1011 if (!knet_h) {
1012 errno = EINVAL;
1013 return -1;
1014 }
1015
1016 if (!link_ids) {
1017 errno = EINVAL;
1018 return -1;
1019 }
1020
1021 if (!link_ids_entries) {
1022 errno = EINVAL;
1023 return -1;
1024 }
1025
1026 savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
1027 if (savederrno) {
1028 log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
1029 strerror(savederrno));
1030 errno = savederrno;
1031 return -1;
1032 }
1033
1034 host = knet_h->host_index[host_id];
1035 if (!host) {
1036 err = -1;
1037 savederrno = EINVAL;
1038 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
1039 host_id, strerror(savederrno));
1040 goto exit_unlock;
1041 }
1042
1043 for (i = 0; i < KNET_MAX_LINK; i++) {
1044 link = &host->link[i];
1045 if (!link->configured) {
1046 continue;
1047 }
1048 link_ids[count] = i;
1049 count++;
1050 }
1051
1052 *link_ids_entries = count;
1053
1054 exit_unlock:
1055 pthread_rwlock_unlock(&knet_h->global_rwlock);
1056 errno = err ? savederrno : 0;
1057 return err;
1058 }
1059
1060 int knet_link_get_status(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
1061 struct knet_link_status *status, size_t struct_size)
1062 {
1063 int savederrno = 0, err = 0;
1064 struct knet_host *host;
1065 struct knet_link *link;
1066
1067 if (!knet_h) {
1068 errno = EINVAL;
1069 return -1;
1070 }
1071
1072 if (link_id >= KNET_MAX_LINK) {
1073 errno = EINVAL;
1074 return -1;
1075 }
1076
1077 if (!status) {
1078 errno = EINVAL;
1079 return -1;
1080 }
1081
1082 savederrno = get_global_wrlock(knet_h);
1083 if (savederrno) {
1084 log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
1085 strerror(savederrno));
1086 errno = savederrno;
1087 return -1;
1088 }
1089
1090 host = knet_h->host_index[host_id];
1091 if (!host) {
1092 err = -1;
1093 savederrno = EINVAL;
1094 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
1095 host_id, strerror(savederrno));
1096 goto exit_unlock;
1097 }
1098
1099 link = &host->link[link_id];
1100
1101 if (!link->configured) {
1102 err = -1;
1103 savederrno = EINVAL;
1104 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
1105 host_id, link_id, strerror(savederrno));
1106 goto exit_unlock;
1107 }
1108
1109 memmove(status, &link->status, struct_size);
1110
1111 /* Calculate totals - no point in doing this on-the-fly */
1112 status->stats.rx_total_packets =
1113 status->stats.rx_data_packets +
1114 status->stats.rx_ping_packets +
1115 status->stats.rx_pong_packets +
1116 status->stats.rx_pmtu_packets;
1117 status->stats.tx_total_packets =
1118 status->stats.tx_data_packets +
1119 status->stats.tx_ping_packets +
1120 status->stats.tx_pong_packets +
1121 status->stats.tx_pmtu_packets;
1122 status->stats.rx_total_bytes =
1123 status->stats.rx_data_bytes +
1124 status->stats.rx_ping_bytes +
1125 status->stats.rx_pong_bytes +
1126 status->stats.rx_pmtu_bytes;
1127 status->stats.tx_total_bytes =
1128 status->stats.tx_data_bytes +
1129 status->stats.tx_ping_bytes +
1130 status->stats.tx_pong_bytes +
1131 status->stats.tx_pmtu_bytes;
1132 status->stats.tx_total_errors =
1133 status->stats.tx_data_errors +
1134 status->stats.tx_ping_errors +
1135 status->stats.tx_pong_errors +
1136 status->stats.tx_pmtu_errors;
1137 status->stats.tx_total_retries =
1138 status->stats.tx_data_retries +
1139 status->stats.tx_ping_retries +
1140 status->stats.tx_pong_retries +
1141 status->stats.tx_pmtu_retries;
1142
1143 /* Tell the caller our full size in case they have an old version */
1144 status->size = sizeof(struct knet_link_status);
1145
1146 exit_unlock:
1147 pthread_rwlock_unlock(&knet_h->global_rwlock);
1148 errno = err ? savederrno : 0;
1149 return err;
1150 }
1151
1152 int knet_link_add_acl(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
1153 struct sockaddr_storage *ss1,
1154 struct sockaddr_storage *ss2,
1155 check_type_t type, check_acceptreject_t acceptreject)
1156 {
1157 int savederrno = 0, err = 0;
1158 struct knet_host *host;
1159 struct knet_link *link;
1160
1161 if (!knet_h) {
1162 errno = EINVAL;
1163 return -1;
1164 }
1165
1166 if (!ss1) {
1167 errno = EINVAL;
1168 return -1;
1169 }
1170
1171 if ((type != CHECK_TYPE_ADDRESS) &&
1172 (type != CHECK_TYPE_MASK) &&
1173 (type != CHECK_TYPE_RANGE)) {
1174 errno = EINVAL;
1175 return -1;
1176 }
1177
1178 if ((acceptreject != CHECK_ACCEPT) &&
1179 (acceptreject != CHECK_REJECT)) {
1180 errno = EINVAL;
1181 return -1;
1182 }
1183
1184 if ((type != CHECK_TYPE_ADDRESS) && (!ss2)) {
1185 errno = EINVAL;
1186 return -1;
1187 }
1188
1189 if ((type == CHECK_TYPE_RANGE) &&
1190 (ss1->ss_family != ss2->ss_family)) {
1191 errno = EINVAL;
1192 return -1;
1193 }
1194
1195 if (link_id >= KNET_MAX_LINK) {
1196 errno = EINVAL;
1197 return -1;
1198 }
1199
1200 savederrno = get_global_wrlock(knet_h);
1201 if (savederrno) {
1202 log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
1203 strerror(savederrno));
1204 errno = savederrno;
1205 return -1;
1206 }
1207
1208 host = knet_h->host_index[host_id];
1209 if (!host) {
1210 err = -1;
1211 savederrno = EINVAL;
1212 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
1213 host_id, strerror(savederrno));
1214 goto exit_unlock;
1215 }
1216
1217 link = &host->link[link_id];
1218
1219 if (!link->configured) {
1220 err = -1;
1221 savederrno = EINVAL;
1222 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
1223 host_id, link_id, strerror(savederrno));
1224 goto exit_unlock;
1225 }
1226
1227 if (link->dynamic != KNET_LINK_DYNIP) {
1228 err = -1;
1229 savederrno = EINVAL;
1230 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is a point to point connection: %s",
1231 host_id, link_id, strerror(savederrno));
1232 goto exit_unlock;
1233 }
1234
1235 err = check_add(knet_h, transport_link_get_acl_fd(knet_h, link), link->transport, -1,
1236 ss1, ss2, type, acceptreject);
1237 savederrno = errno;
1238
1239 exit_unlock:
1240 pthread_rwlock_unlock(&knet_h->global_rwlock);
1241
1242 errno = savederrno;
1243 return err;
1244 }
1245
1246 int knet_link_insert_acl(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
1247 int index,
1248 struct sockaddr_storage *ss1,
1249 struct sockaddr_storage *ss2,
1250 check_type_t type, check_acceptreject_t acceptreject)
1251 {
1252 int savederrno = 0, err = 0;
1253 struct knet_host *host;
1254 struct knet_link *link;
1255
1256 if (!knet_h) {
1257 errno = EINVAL;
1258 return -1;
1259 }
1260
1261 if (!ss1) {
1262 errno = EINVAL;
1263 return -1;
1264 }
1265
1266 if ((type != CHECK_TYPE_ADDRESS) &&
1267 (type != CHECK_TYPE_MASK) &&
1268 (type != CHECK_TYPE_RANGE)) {
1269 errno = EINVAL;
1270 return -1;
1271 }
1272
1273 if ((acceptreject != CHECK_ACCEPT) &&
1274 (acceptreject != CHECK_REJECT)) {
1275 errno = EINVAL;
1276 return -1;
1277 }
1278
1279 if ((type != CHECK_TYPE_ADDRESS) && (!ss2)) {
1280 errno = EINVAL;
1281 return -1;
1282 }
1283
1284 if ((type == CHECK_TYPE_RANGE) &&
1285 (ss1->ss_family != ss2->ss_family)) {
1286 errno = EINVAL;
1287 return -1;
1288 }
1289
1290 if (link_id >= KNET_MAX_LINK) {
1291 errno = EINVAL;
1292 return -1;
1293 }
1294
1295 savederrno = get_global_wrlock(knet_h);
1296 if (savederrno) {
1297 log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
1298 strerror(savederrno));
1299 errno = savederrno;
1300 return -1;
1301 }
1302
1303 host = knet_h->host_index[host_id];
1304 if (!host) {
1305 err = -1;
1306 savederrno = EINVAL;
1307 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
1308 host_id, strerror(savederrno));
1309 goto exit_unlock;
1310 }
1311
1312 link = &host->link[link_id];
1313
1314 if (!link->configured) {
1315 err = -1;
1316 savederrno = EINVAL;
1317 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
1318 host_id, link_id, strerror(savederrno));
1319 goto exit_unlock;
1320 }
1321
1322 if (link->dynamic != KNET_LINK_DYNIP) {
1323 err = -1;
1324 savederrno = EINVAL;
1325 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is a point to point connection: %s",
1326 host_id, link_id, strerror(savederrno));
1327 goto exit_unlock;
1328 }
1329
1330 err = check_add(knet_h, transport_link_get_acl_fd(knet_h, link), link->transport, index,
1331 ss1, ss2, type, acceptreject);
1332 savederrno = errno;
1333
1334 exit_unlock:
1335 pthread_rwlock_unlock(&knet_h->global_rwlock);
1336
1337 errno = savederrno;
1338 return err;
1339 }
1340
1341 int knet_link_rm_acl(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
1342 struct sockaddr_storage *ss1,
1343 struct sockaddr_storage *ss2,
1344 check_type_t type, check_acceptreject_t acceptreject)
1345 {
1346 int savederrno = 0, err = 0;
1347 struct knet_host *host;
1348 struct knet_link *link;
1349
1350 if (!knet_h) {
1351 errno = EINVAL;
1352 return -1;
1353 }
1354
1355 if (!ss1) {
1356 errno = EINVAL;
1357 return -1;
1358 }
1359
1360 if ((type != CHECK_TYPE_ADDRESS) &&
1361 (type != CHECK_TYPE_MASK) &&
1362 (type != CHECK_TYPE_RANGE)) {
1363 errno = EINVAL;
1364 return -1;
1365 }
1366
1367 if ((acceptreject != CHECK_ACCEPT) &&
1368 (acceptreject != CHECK_REJECT)) {
1369 errno = EINVAL;
1370 return -1;
1371 }
1372
1373 if ((type != CHECK_TYPE_ADDRESS) && (!ss2)) {
1374 errno = EINVAL;
1375 return -1;
1376 }
1377
1378 if ((type == CHECK_TYPE_RANGE) &&
1379 (ss1->ss_family != ss2->ss_family)) {
1380 errno = EINVAL;
1381 return -1;
1382 }
1383
1384 if (link_id >= KNET_MAX_LINK) {
1385 errno = EINVAL;
1386 return -1;
1387 }
1388
1389 savederrno = get_global_wrlock(knet_h);
1390 if (savederrno) {
1391 log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
1392 strerror(savederrno));
1393 errno = savederrno;
1394 return -1;
1395 }
1396
1397 host = knet_h->host_index[host_id];
1398 if (!host) {
1399 err = -1;
1400 savederrno = EINVAL;
1401 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
1402 host_id, strerror(savederrno));
1403 goto exit_unlock;
1404 }
1405
1406 link = &host->link[link_id];
1407
1408 if (!link->configured) {
1409 err = -1;
1410 savederrno = EINVAL;
1411 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
1412 host_id, link_id, strerror(savederrno));
1413 goto exit_unlock;
1414 }
1415
1416 if (link->dynamic != KNET_LINK_DYNIP) {
1417 err = -1;
1418 savederrno = EINVAL;
1419 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is a point to point connection: %s",
1420 host_id, link_id, strerror(savederrno));
1421 goto exit_unlock;
1422 }
1423
1424 err = check_rm(knet_h, transport_link_get_acl_fd(knet_h, link), link->transport,
1425 ss1, ss2, type, acceptreject);
1426 savederrno = errno;
1427
1428 exit_unlock:
1429 pthread_rwlock_unlock(&knet_h->global_rwlock);
1430
1431 errno = savederrno;
1432 return err;
1433 }
1434
1435 int knet_link_clear_acl(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id)
1436 {
1437 int savederrno = 0, err = 0;
1438 struct knet_host *host;
1439 struct knet_link *link;
1440
1441 if (!knet_h) {
1442 errno = EINVAL;
1443 return -1;
1444 }
1445
1446 if (link_id >= KNET_MAX_LINK) {
1447 errno = EINVAL;
1448 return -1;
1449 }
1450
1451 savederrno = get_global_wrlock(knet_h);
1452 if (savederrno) {
1453 log_err(knet_h, KNET_SUB_LINK, "Unable to get write lock: %s",
1454 strerror(savederrno));
1455 errno = savederrno;
1456 return -1;
1457 }
1458
1459 host = knet_h->host_index[host_id];
1460 if (!host) {
1461 err = -1;
1462 savederrno = EINVAL;
1463 log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
1464 host_id, strerror(savederrno));
1465 goto exit_unlock;
1466 }
1467
1468 link = &host->link[link_id];
1469
1470 if (!link->configured) {
1471 err = -1;
1472 savederrno = EINVAL;
1473 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
1474 host_id, link_id, strerror(savederrno));
1475 goto exit_unlock;
1476 }
1477
1478 if (link->dynamic != KNET_LINK_DYNIP) {
1479 err = -1;
1480 savederrno = EINVAL;
1481 log_err(knet_h, KNET_SUB_LINK, "host %u link %u is a point to point connection: %s",
1482 host_id, link_id, strerror(savederrno));
1483 goto exit_unlock;
1484 }
1485
1486 check_rmall(knet_h, transport_link_get_acl_fd(knet_h, link), link->transport);
1487
1488 exit_unlock:
1489 pthread_rwlock_unlock(&knet_h->global_rwlock);
1490
1491 errno = savederrno;
1492 return err;
1493 }