1    	/*
2    	 * Copyright (C) 2015-2025 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 LGPL-2.0+
8    	 */
9    	
10   	#include "config.h"
11   	
12   	#include <unistd.h>
13   	#include <string.h>
14   	#include <errno.h>
15   	#include <pthread.h>
16   	
17   	#include "crypto.h"
18   	#include "links.h"
19   	#include "host.h"
20   	#include "logging.h"
21   	#include "transports.h"
22   	#include "threads_common.h"
23   	#include "threads_pmtud.h"
24   	
25   	static int _calculate_manual_mtu(knet_handle_t knet_h, struct knet_link *dst_link)
26   	{
27   		size_t ipproto_overhead_len;	/* onwire packet overhead (protocol based) */
28   	
29   		switch (dst_link->dst_addr.ss_family) {
30   			case AF_INET6:
31   				ipproto_overhead_len = KNET_PMTUD_OVERHEAD_V6 + dst_link->proto_overhead;
32   				break;
33   			case AF_INET:
34   				ipproto_overhead_len = KNET_PMTUD_OVERHEAD_V4 + dst_link->proto_overhead;
35   				break;
36   			default:
37   				log_debug(knet_h, KNET_SUB_PMTUD, "unknown protocol");
38   				return 0;
39   				break;
40   		}
41   	
42   		dst_link->status.mtu = calc_max_data_outlen(knet_h, knet_h->manual_mtu - ipproto_overhead_len);
43   	
44   		return 1;
45   	}
46   	
47   	static int _handle_check_link_pmtud(knet_handle_t knet_h, struct knet_host *dst_host, struct knet_link *dst_link)
48   	{
49   		int err, ret, savederrno, mutex_retry_limit, failsafe, use_kernel_mtu, warn_once;
50   		uint32_t kernel_mtu;		/* record kernel_mtu from EMSGSIZE */
51   		size_t onwire_len;   		/* current packet onwire size */
52   		size_t ipproto_overhead_len;	/* onwire packet overhead (protocol based) */
53   		size_t max_mtu_len;		/* max mtu for protocol */
54   		size_t data_len;		/* how much data we can send in the packet
55   						 * generally would be onwire_len - ipproto_overhead_len
56   						 * needs to be adjusted for crypto
57   						 */
58   		size_t app_mtu_len;		/* real data that we can send onwire */
59   		ssize_t len;			/* len of what we were able to sendto onwire */
60   	
61   		struct timespec ts, pmtud_crypto_start_ts, pmtud_crypto_stop_ts;
62   		unsigned long long pong_timeout_adj_tmp, timediff;
63   		int pmtud_crypto_reduce = 1;
64   		unsigned char *outbuf = (unsigned char *)knet_h->pmtudbuf;
65   	
66   		warn_once = 0;
67   	
68   		mutex_retry_limit = 0;
69   		failsafe = 0;
70   	
71   		knet_h->pmtudbuf->khp_pmtud_link = dst_link->link_id;
72   	
(1) Event switch: Switch case value "10".
73   		switch (dst_link->dst_addr.ss_family) {
(2) Event switch_case: Reached case "10".
74   			case AF_INET6:
75   				max_mtu_len = KNET_PMTUD_SIZE_V6;
76   				ipproto_overhead_len = KNET_PMTUD_OVERHEAD_V6 + dst_link->proto_overhead;
(3) Event break: Breaking from switch.
77   				break;
78   			case AF_INET:
79   				max_mtu_len = KNET_PMTUD_SIZE_V4;
80   				ipproto_overhead_len = KNET_PMTUD_OVERHEAD_V4 + dst_link->proto_overhead;
81   				break;
82   			default:
83   				log_debug(knet_h, KNET_SUB_PMTUD, "PMTUD aborted, unknown protocol");
84   				return -1;
85   				break;
(4) Event switch_end: Reached end of switch.
86   		}
87   	
88   		dst_link->last_bad_mtu = 0;
89   		dst_link->last_good_mtu = dst_link->last_ping_size + ipproto_overhead_len;
90   	
91   		/*
92   		 * discovery starts from the top because kernel will
93   		 * refuse to send packets > current iface mtu.
94   		 * this saves us some time and network bw.
95   		 */ 
96   		onwire_len = max_mtu_len;
97   	
(49) Event label: Reached label "restart".
(94) Event label: Reached label "restart".
98   	restart:
99   	
100  		/*
101  		 * prevent a race when interface mtu is changed _exactly_ during
102  		 * the discovery process and it's complex to detect. Easier
103  		 * to wait the next loop.
104  		 * 30 is not an arbitrary value. To bisect from 576 to 128000 doesn't
105  		 * take more than 18/19 steps.
106  		 */
107  	
(5) Event cond_false: Condition "failsafe == 30", taking false branch.
(50) Event cond_false: Condition "failsafe == 30", taking false branch.
(95) Event cond_false: Condition "failsafe == 30", taking false branch.
108  		if (failsafe == 30) {
109  			log_err(knet_h, KNET_SUB_PMTUD,
110  				"Aborting PMTUD process: Too many attempts. MTU might have changed during discovery.");
111  			return -1;
(6) Event else_branch: Reached else branch.
(51) Event else_branch: Reached else branch.
(96) Event else_branch: Reached else branch.
112  		} else {
113  			failsafe++;
114  		}
115  	
116  		/*
117  		 * common to all packets
118  		 */
119  	
120  		/*
121  		 * calculate the application MTU based on current onwire_len minus ipproto_overhead_len
122  		 */
123  	
124  		app_mtu_len = calc_max_data_outlen(knet_h, onwire_len - ipproto_overhead_len);
125  	
126  		/*
127  		 * recalculate onwire len back that might be different based
128  		 * on data padding from crypto layer.
129  		 */
130  	
131  		onwire_len = calc_data_outlen(knet_h, app_mtu_len + KNET_HEADER_ALL_SIZE) + ipproto_overhead_len;
132  	
133  		/*
134  		 * calculate the size of what we need to send to sendto(2).
135  		 * see also onwire.c for packet format explanation.
136  		 */
137  		data_len = app_mtu_len + knet_h->sec_hash_size + knet_h->sec_salt_size + KNET_HEADER_ALL_SIZE;
138  	
(7) Event cond_true: Condition "knet_h->crypto_in_use_config", taking true branch.
(52) Event cond_true: Condition "knet_h->crypto_in_use_config", taking true branch.
(97) Event cond_true: Condition "knet_h->crypto_in_use_config", taking true branch.
139  		if (knet_h->crypto_in_use_config) {
(8) Event cond_false: Condition "data_len < knet_h->sec_hash_size + knet_h->sec_salt_size + 1", taking false branch.
(53) Event cond_false: Condition "data_len < knet_h->sec_hash_size + knet_h->sec_salt_size + 1", taking false branch.
(98) Event cond_false: Condition "data_len < knet_h->sec_hash_size + knet_h->sec_salt_size + 1", taking false branch.
140  			if (data_len < (knet_h->sec_hash_size + knet_h->sec_salt_size) + 1) {
141  				log_debug(knet_h, KNET_SUB_PMTUD, "Aborting PMTUD process: link mtu smaller than crypto header detected (link might have been disconnected)");
142  				return -1;
(9) Event if_end: End of if statement.
(54) Event if_end: End of if statement.
(99) Event if_end: End of if statement.
143  			}
144  	
145  			knet_h->pmtudbuf->khp_pmtud_size = onwire_len;
146  	
(10) Event cond_false: Condition "crypto_encrypt_and_sign(knet_h, (unsigned char const *)knet_h->pmtudbuf, data_len - (knet_h->sec_hash_size + knet_h->sec_salt_size), knet_h->pmtudbuf_crypt, (ssize_t *)&data_len) < 0", taking false branch.
(55) Event cond_false: Condition "crypto_encrypt_and_sign(knet_h, (unsigned char const *)knet_h->pmtudbuf, data_len - (knet_h->sec_hash_size + knet_h->sec_salt_size), knet_h->pmtudbuf_crypt, (ssize_t *)&data_len) < 0", taking false branch.
(100) Event cond_false: Condition "crypto_encrypt_and_sign(knet_h, (unsigned char const *)knet_h->pmtudbuf, data_len - (knet_h->sec_hash_size + knet_h->sec_salt_size), knet_h->pmtudbuf_crypt, (ssize_t *)&data_len) < 0", taking false branch.
147  			if (crypto_encrypt_and_sign(knet_h,
148  						    (const unsigned char *)knet_h->pmtudbuf,
149  						    data_len - (knet_h->sec_hash_size + knet_h->sec_salt_size),
150  						    knet_h->pmtudbuf_crypt,
151  						    (ssize_t *)&data_len) < 0) {
152  				log_debug(knet_h, KNET_SUB_PMTUD, "Unable to crypto pmtud packet");
153  				return -1;
(11) Event if_end: End of if statement.
(56) Event if_end: End of if statement.
(101) Event if_end: End of if statement.
154  			}
155  	
156  			outbuf = knet_h->pmtudbuf_crypt;
(12) Event cond_false: Condition "pthread_mutex_lock(&knet_h->handle_stats_mutex) < 0", taking false branch.
(57) Event cond_false: Condition "pthread_mutex_lock(&knet_h->handle_stats_mutex) < 0", taking false branch.
(102) Event cond_false: Condition "pthread_mutex_lock(&knet_h->handle_stats_mutex) < 0", taking false branch.
157  			if (pthread_mutex_lock(&knet_h->handle_stats_mutex) < 0) {
158  				log_err(knet_h, KNET_SUB_PMTUD, "Unable to get mutex lock");
159  				return -1;
(13) Event if_end: End of if statement.
(58) Event if_end: End of if statement.
(103) Event if_end: End of if statement.
160  			}
161  			knet_h->stats_extra.tx_crypt_pmtu_packets++;
162  			pthread_mutex_unlock(&knet_h->handle_stats_mutex);
(14) Event if_fallthrough: Falling through to end of if statement.
(59) Event if_fallthrough: Falling through to end of if statement.
(104) Event if_fallthrough: Falling through to end of if statement.
163  		} else {
164  			knet_h->pmtudbuf->khp_pmtud_size = onwire_len;
(15) Event if_end: End of if statement.
(60) Event if_end: End of if statement.
(105) Event if_end: End of if statement.
165  		}
166  	
167  		/* link has gone down, aborting pmtud */
(16) Event cond_false: Condition "dst_link->status.connected != 1", taking false branch.
(61) Event cond_false: Condition "dst_link->status.connected != 1", taking false branch.
(106) Event cond_false: Condition "dst_link->status.connected != 1", taking false branch.
168  		if (dst_link->status.connected != 1) {
169  			log_debug(knet_h, KNET_SUB_PMTUD, "PMTUD detected host (%u) link (%u) has been disconnected", dst_host->host_id, dst_link->link_id);
170  			return -1;
(17) Event if_end: End of if statement.
(62) Event if_end: End of if statement.
(107) Event if_end: End of if statement.
171  		}
172  	
(18) Event cond_false: Condition "dst_link->transport_connected != 1", taking false branch.
(63) Event cond_false: Condition "dst_link->transport_connected != 1", taking false branch.
(108) Event cond_false: Condition "dst_link->transport_connected != 1", taking false branch.
173  		if (dst_link->transport_connected != 1) {
174  			log_debug(knet_h, KNET_SUB_PMTUD, "PMTUD detected host (%u) link (%u) has been disconnected", dst_host->host_id, dst_link->link_id);
175  			return -1;
(19) Event if_end: End of if statement.
(64) Event if_end: End of if statement.
(109) Event if_end: End of if statement.
176  		}
177  	
(20) Event cond_false: Condition "pthread_mutex_lock(&knet_h->pmtud_mutex) != 0", taking false branch.
(65) Event cond_false: Condition "pthread_mutex_lock(&knet_h->pmtud_mutex) != 0", taking false branch.
(110) Event cond_false: Condition "pthread_mutex_lock(&knet_h->pmtud_mutex) != 0", taking false branch.
178  		if (pthread_mutex_lock(&knet_h->pmtud_mutex) != 0) {
179  			log_debug(knet_h, KNET_SUB_PMTUD, "Unable to get mutex lock");
180  			return -1;
(21) Event if_end: End of if statement.
(66) Event if_end: End of if statement.
(111) Event if_end: End of if statement.
181  		}
182  	
(22) Event cond_false: Condition "knet_h->pmtud_abort", taking false branch.
(67) Event cond_false: Condition "knet_h->pmtud_abort", taking false branch.
(112) Event cond_false: Condition "knet_h->pmtud_abort", taking false branch.
183  		if (knet_h->pmtud_abort) {
184  			pthread_mutex_unlock(&knet_h->pmtud_mutex);
185  			errno = EDEADLK;
186  			return -1;
(23) Event if_end: End of if statement.
(68) Event if_end: End of if statement.
(113) Event if_end: End of if statement.
187  		}
188  	
189  		savederrno = pthread_mutex_lock(&knet_h->tx_mutex);
(24) Event cond_false: Condition "savederrno", taking false branch.
(69) Event cond_false: Condition "savederrno", taking false branch.
(114) Event cond_false: Condition "savederrno", taking false branch.
190  		if (savederrno) {
191  			pthread_mutex_unlock(&knet_h->pmtud_mutex);
192  			log_err(knet_h, KNET_SUB_PMTUD, "Unable to get TX mutex lock: %s", strerror(savederrno));
193  			return -1;
(25) Event if_end: End of if statement.
(70) Event if_end: End of if statement.
(115) Event if_end: End of if statement.
194  		}
195  	
(159) Event lock_acquire: Example 1: Calling "pthread_mutex_lock" acquires lock "knet_link.link_stats_mutex".
Also see events: [missing_lock][example_access]
196  		savederrno = pthread_mutex_lock(&dst_link->link_stats_mutex);
(26) Event cond_false: Condition "savederrno", taking false branch.
(71) Event cond_false: Condition "savederrno", taking false branch.
(116) Event cond_false: Condition "savederrno", taking false branch.
197  		if (savederrno) {
198  			pthread_mutex_unlock(&knet_h->pmtud_mutex);
199  			pthread_mutex_unlock(&knet_h->tx_mutex);
200  			log_err(knet_h, KNET_SUB_PMTUD, "Unable to get stats mutex lock for host %u link %u: %s",
201  				dst_host->host_id, dst_link->link_id, strerror(savederrno));
202  			return -1;
(27) Event if_end: End of if statement.
(72) Event if_end: End of if statement.
(117) Event if_end: End of if statement.
203  		}
204  	
205  	retry:
(28) Event cond_true: Condition "transport_get_connection_oriented(knet_h, dst_link->transport) == 0", taking true branch.
(73) Event cond_true: Condition "transport_get_connection_oriented(knet_h, dst_link->transport) == 0", taking true branch.
(118) Event cond_true: Condition "transport_get_connection_oriented(knet_h, dst_link->transport) == 0", taking true branch.
206  		if (transport_get_connection_oriented(knet_h, dst_link->transport) == TRANSPORT_PROTO_NOT_CONNECTION_ORIENTED) {
207  			len = sendto(dst_link->outsock, outbuf, data_len, MSG_DONTWAIT | MSG_NOSIGNAL,
208  				     (struct sockaddr *) &dst_link->dst_addr,
209  				     knet_h->knet_transport_fd_tracker[dst_link->outsock].sockaddr_len);
(29) Event if_fallthrough: Falling through to end of if statement.
(74) Event if_fallthrough: Falling through to end of if statement.
(119) Event if_fallthrough: Falling through to end of if statement.
210  		} else {
211  			len = sendto(dst_link->outsock, outbuf, data_len, MSG_DONTWAIT | MSG_NOSIGNAL, NULL, 0);
(30) Event if_end: End of if statement.
(75) Event if_end: End of if statement.
(120) Event if_end: End of if statement.
212  		}
213  		savederrno = errno;
214  	
215  		/*
216  		 * we cannot hold a lock on kmtu_mutex between resetting
217  		 * knet_h->kernel_mtu here and below where it's used.
218  		 * use_kernel_mtu tells us if the knet_h->kernel_mtu was
219  		 * set to 0 and we can trust its value later.
220  		 */
221  		use_kernel_mtu = 0;
222  	
(31) Event cond_true: Condition "pthread_mutex_lock(&knet_h->kmtu_mutex) == 0", taking true branch.
(76) Event cond_true: Condition "pthread_mutex_lock(&knet_h->kmtu_mutex) == 0", taking true branch.
(121) Event cond_true: Condition "pthread_mutex_lock(&knet_h->kmtu_mutex) == 0", taking true branch.
223  		if (pthread_mutex_lock(&knet_h->kmtu_mutex) == 0) {
224  			use_kernel_mtu = 1;
225  			knet_h->kernel_mtu = 0;
226  			pthread_mutex_unlock(&knet_h->kmtu_mutex);
227  		}
228  	
229  		kernel_mtu = 0;
230  	
231  		err = transport_tx_sock_error(knet_h, dst_link->transport, dst_link->outsock, KNET_SUB_PMTUD, len, savederrno);
(32) Event switch: Switch case value "0".
(77) Event switch: Switch case value "0".
(122) Event switch: Switch case value "0".
232  		switch(err) {
233  			case -1: /* unrecoverable error */
234  				log_debug(knet_h, KNET_SUB_PMTUD, "Unable to send pmtu packet (sendto): %d %s", savederrno, strerror(savederrno));
235  				pthread_mutex_unlock(&knet_h->tx_mutex);
236  				pthread_mutex_unlock(&knet_h->pmtud_mutex);
237  				dst_link->status.stats.tx_pmtu_errors++;
238  				pthread_mutex_unlock(&dst_link->link_stats_mutex);
239  				return -1;
(33) Event switch_case: Reached case "0".
(78) Event switch_case: Reached case "0".
(123) Event switch_case: Reached case "0".
240  			case 0: /* ignore error and continue */
(34) Event break: Breaking from switch.
(79) Event break: Breaking from switch.
(124) Event break: Breaking from switch.
241  				break;
242  			case 1: /* retry to send those same data */
243  				dst_link->status.stats.tx_pmtu_retries++;
244  				goto retry;
245  				break;
(35) Event switch_end: Reached end of switch.
(80) Event switch_end: Reached end of switch.
(125) Event switch_end: Reached end of switch.
246  		}
247  	
248  		pthread_mutex_unlock(&knet_h->tx_mutex);
249  	
(36) Event cond_true: Condition "len != (ssize_t)data_len", taking true branch.
(81) Event cond_true: Condition "len != (ssize_t)data_len", taking true branch.
(126) Event cond_false: Condition "len != (ssize_t)data_len", taking false branch.
250  		if (len != (ssize_t )data_len) {
251  			pthread_mutex_unlock(&dst_link->link_stats_mutex);
(37) Event cond_true: Condition "savederrno == 90", taking true branch.
(82) Event cond_true: Condition "savederrno == 90", taking true branch.
252  			if (savederrno == EMSGSIZE || savederrno == EPERM) {
253  				/*
254  				 * we cannot hold a lock on kmtu_mutex between resetting
255  				 * knet_h->kernel_mtu and here.
256  				 * use_kernel_mtu tells us if the knet_h->kernel_mtu was
257  				 * set to 0 previously and we can trust its value now.
258  				 */
(38) Event cond_true: Condition "use_kernel_mtu", taking true branch.
(83) Event cond_true: Condition "use_kernel_mtu", taking true branch.
259  				if (use_kernel_mtu) {
260  					use_kernel_mtu = 0;
(39) Event cond_true: Condition "pthread_mutex_lock(&knet_h->kmtu_mutex) == 0", taking true branch.
(84) Event cond_true: Condition "pthread_mutex_lock(&knet_h->kmtu_mutex) == 0", taking true branch.
261  					if (pthread_mutex_lock(&knet_h->kmtu_mutex) == 0) {
262  						kernel_mtu = knet_h->kernel_mtu;
263  						pthread_mutex_unlock(&knet_h->kmtu_mutex);
264  					}
265  				}
(40) Event cond_false: Condition "kernel_mtu > 0", taking false branch.
(85) Event cond_false: Condition "kernel_mtu > 0", taking false branch.
266  				if (kernel_mtu > 0) {
267  					dst_link->last_bad_mtu = kernel_mtu + 1;
(41) Event else_branch: Reached else branch.
(86) Event else_branch: Reached else branch.
268  				} else {
269  					dst_link->last_bad_mtu = onwire_len;
270  				}
(42) Event if_fallthrough: Falling through to end of if statement.
(87) Event if_fallthrough: Falling through to end of if statement.
271  			} else {
272  				log_debug(knet_h, KNET_SUB_PMTUD, "Unable to send pmtu packet len: %zu err: %s", onwire_len, strerror(savederrno));
(43) Event if_end: End of if statement.
(88) Event if_end: End of if statement.
273  			}
274  	
(44) Event if_fallthrough: Falling through to end of if statement.
(89) Event if_fallthrough: Falling through to end of if statement.
(127) Event else_branch: Reached else branch.
275  		} else {
276  			dst_link->last_sent_mtu = onwire_len;
(160) Event example_access: Example 1 (cont.): "knet_link.last_recv_mtu" is written to with lock "knet_link.link_stats_mutex" held.
Also see events: [missing_lock][lock_acquire]
277  			dst_link->last_recv_mtu = 0;
278  			dst_link->status.stats.tx_pmtu_packets++;
279  			dst_link->status.stats.tx_pmtu_bytes += data_len;
280  			pthread_mutex_unlock(&dst_link->link_stats_mutex);
281  	
(128) Event cond_false: Condition "clock_gettime(0, &ts) < 0", taking false branch.
282  			if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
283  				log_debug(knet_h, KNET_SUB_PMTUD, "Unable to get current time: %s", strerror(errno));
284  				pthread_mutex_unlock(&knet_h->pmtud_mutex);
285  				return -1;
(129) Event if_end: End of if statement.
286  			}
287  	
288  			/*
289  			 * non fatal, we can wait the next round to reduce the
290  			 * multiplier
291  			 */
(130) Event cond_false: Condition "clock_gettime(1, &pmtud_crypto_start_ts) < 0", taking false branch.
292  			if (clock_gettime(CLOCK_MONOTONIC, &pmtud_crypto_start_ts) < 0) {
293  				log_debug(knet_h, KNET_SUB_PMTUD, "Unable to get current time: %s", strerror(errno));
294  				pmtud_crypto_reduce = 0;
(131) Event if_end: End of if statement.
295  			}
296  	
297  			/*
298  			 * set PMTUd reply timeout to match pong_timeout on a given link
299  			 *
300  			 * math: internally pong_timeout is expressed in microseconds, while
301  			 *       the public API exports milliseconds. So careful with the 0's here.
302  			 * the loop is necessary because we are grabbing the current time just above
303  			 * and add values to it that could overflow into seconds.
304  			 */ 
305  	
(132) Event cond_false: Condition "pthread_mutex_lock(&knet_h->backoff_mutex)", taking false branch.
306  			if (pthread_mutex_lock(&knet_h->backoff_mutex)) {
307  				log_debug(knet_h, KNET_SUB_PMTUD, "Unable to get backoff_mutex");
308  				pthread_mutex_unlock(&knet_h->pmtud_mutex);
309  				return -1;
(133) Event if_end: End of if statement.
310  			}
311  	
(134) Event cond_true: Condition "knet_h->crypto_in_use_config", taking true branch.
312  			if (knet_h->crypto_in_use_config) {
313  				/*
314  				 * crypto, under pressure, is a royal PITA
315  				 */
316  				pong_timeout_adj_tmp = dst_link->pong_timeout_adj * dst_link->pmtud_crypto_timeout_multiplier;
(135) Event if_fallthrough: Falling through to end of if statement.
317  			} else {
318  				pong_timeout_adj_tmp = dst_link->pong_timeout_adj;
(136) Event if_end: End of if statement.
319  			}
320  	
321  			ts.tv_sec += pong_timeout_adj_tmp / 1000000;
322  			ts.tv_nsec += (((pong_timeout_adj_tmp) % 1000000) * 1000);
(137) Event cond_true: Condition "ts.tv_nsec > 1000000000", taking true branch.
(139) Event loop_begin: Jumped back to beginning of loop.
(140) Event cond_false: Condition "ts.tv_nsec > 1000000000", taking false branch.
323  			while (ts.tv_nsec > 1000000000) {
324  				ts.tv_sec += 1;
325  				ts.tv_nsec -= 1000000000;
(138) Event loop: Jumping back to the beginning of the loop.
(141) Event loop_end: Reached end of loop.
326  			}
327  	
328  			pthread_mutex_unlock(&knet_h->backoff_mutex);
329  	
330  			knet_h->pmtud_waiting = 1;
331  	
332  			ret = pthread_cond_timedwait(&knet_h->pmtud_cond, &knet_h->pmtud_mutex, &ts);
333  	
334  			knet_h->pmtud_waiting = 0;
335  	
(142) Event cond_false: Condition "knet_h->pmtud_abort", taking false branch.
336  			if (knet_h->pmtud_abort) {
337  				pthread_mutex_unlock(&knet_h->pmtud_mutex);
338  				errno = EDEADLK;
339  				return -1;
(143) Event if_end: End of if statement.
340  			}
341  	
342  			/*
343  			 * we cannot use shutdown_in_progress in here because
344  			 * we already hold the read lock
345  			 */
(144) Event cond_false: Condition "knet_h->fini_in_progress", taking false branch.
346  			if (knet_h->fini_in_progress) {
347  				pthread_mutex_unlock(&knet_h->pmtud_mutex);
348  				log_debug(knet_h, KNET_SUB_PMTUD, "PMTUD aborted. shutdown in progress");
349  				return -1;
(145) Event if_end: End of if statement.
350  			}
351  	
(146) Event cond_false: Condition "ret", taking false branch.
352  			if (ret) {
353  				if (ret == ETIMEDOUT) {
354  					if ((knet_h->crypto_in_use_config) && (dst_link->pmtud_crypto_timeout_multiplier < KNET_LINK_PMTUD_CRYPTO_TIMEOUT_MULTIPLIER_MAX)) {
355  						dst_link->pmtud_crypto_timeout_multiplier = dst_link->pmtud_crypto_timeout_multiplier * 2;
356  						pmtud_crypto_reduce = 0;
357  						log_debug(knet_h, KNET_SUB_PMTUD,
358  								"Increasing PMTUd response timeout multiplier to (%u) for host %u link: %u",
359  								dst_link->pmtud_crypto_timeout_multiplier,
360  								dst_host->host_id,
361  								dst_link->link_id);
362  						pthread_mutex_unlock(&knet_h->pmtud_mutex);
363  						goto restart;
364  					}
365  					if (!warn_once) {
366  						log_warn(knet_h, KNET_SUB_PMTUD,
367  								"possible MTU misconfiguration detected. "
368  								"kernel is reporting MTU: %u bytes for "
369  								"host %u link %u but the other node is "
370  								"not acknowledging packets of this size. ",
371  								dst_link->last_sent_mtu,
372  								dst_host->host_id,
373  								dst_link->link_id);
374  						log_warn(knet_h, KNET_SUB_PMTUD,
375  								"This can be caused by this node interface MTU "
376  								"too big or a network device that does not "
377  								"support or has been misconfigured to manage MTU "
378  								"of this size, or packet loss. knet will continue "
379  								"to run but performances might be affected.");
380  						warn_once = 1;
381  					}
382  				} else {
383  					pthread_mutex_unlock(&knet_h->pmtud_mutex);
384  					if (mutex_retry_limit == 3) {
385  						log_debug(knet_h, KNET_SUB_PMTUD, "PMTUD aborted, unable to get mutex lock");
386  						return -1;
387  					}
388  					mutex_retry_limit++;
389  					goto restart;
390  				}
(147) Event if_end: End of if statement.
391  			}
392  	
(148) Event cond_true: Condition "knet_h->crypto_in_use_config", taking true branch.
(149) Event cond_true: Condition "pmtud_crypto_reduce == 1", taking true branch.
(150) Event cond_true: Condition "dst_link->pmtud_crypto_timeout_multiplier > 2", taking true branch.
393  			if ((knet_h->crypto_in_use_config) && (pmtud_crypto_reduce == 1) &&
394  			    (dst_link->pmtud_crypto_timeout_multiplier > KNET_LINK_PMTUD_CRYPTO_TIMEOUT_MULTIPLIER_MIN)) {
(151) Event cond_true: Condition "!clock_gettime(1, &pmtud_crypto_stop_ts)", taking true branch.
395  				if (!clock_gettime(CLOCK_MONOTONIC, &pmtud_crypto_stop_ts)) {
(152) Event cond_true: Condition "pmtud_crypto_stop_ts.tv_sec > pmtud_crypto_start_ts.tv_sec", taking true branch.
(153) Event if_fallthrough: Falling through to end of if statement.
(154) Event if_end: End of if statement.
396  					timespec_diff(pmtud_crypto_start_ts, pmtud_crypto_stop_ts, &timediff);
(155) Event cond_true: Condition "pong_timeout_adj_tmp * 1000 / 2 > timediff", taking true branch.
397  					if (((pong_timeout_adj_tmp * 1000) / 2) > timediff) {
398  						dst_link->pmtud_crypto_timeout_multiplier = dst_link->pmtud_crypto_timeout_multiplier / 2;
399  						log_debug(knet_h, KNET_SUB_PMTUD,
400  								"Decreasing PMTUd response timeout multiplier to (%u) for host %u link: %u",
401  								dst_link->pmtud_crypto_timeout_multiplier,
402  								dst_host->host_id,
403  								dst_link->link_id);
404  					}
(156) Event if_fallthrough: Falling through to end of if statement.
405  				} else {
406  					log_debug(knet_h, KNET_SUB_PMTUD, "Unable to get current time: %s", strerror(errno));
(157) Event if_end: End of if statement.
407  				}
408  			}
409  	
(158) Event missing_lock: Accessing "dst_link->last_recv_mtu" without holding lock "knet_link.link_stats_mutex". Elsewhere, "knet_link.last_recv_mtu" is written to with "knet_link.link_stats_mutex" held 1 out of 1 times.
Also see events: [lock_acquire][example_access]
410  			if ((dst_link->last_recv_mtu != onwire_len) || (ret)) {
411  				dst_link->last_bad_mtu = onwire_len;
412  			} else {
413  				int found_mtu = 0;
414  	
415  				if (knet_h->sec_block_size) {
416  					if ((onwire_len + knet_h->sec_block_size >= max_mtu_len) ||
417  					   ((dst_link->last_bad_mtu) && (dst_link->last_bad_mtu <= (onwire_len + knet_h->sec_block_size)))) {
418  						found_mtu = 1;
419  					}
420  				} else {
421  					if ((onwire_len == max_mtu_len) ||
422  					    ((dst_link->last_bad_mtu) && (dst_link->last_bad_mtu == (onwire_len + 1))) ||
423  					     (dst_link->last_bad_mtu == dst_link->last_good_mtu)) {
424  						found_mtu = 1;
425  					}
426  				}
427  	
428  				if (found_mtu) {
429  					/*
430  					 * account for IP overhead, knet headers and crypto in PMTU calculation
431  					 */
432  					dst_link->status.mtu = calc_max_data_outlen(knet_h, onwire_len - ipproto_overhead_len);
433  					pthread_mutex_unlock(&knet_h->pmtud_mutex);
434  					return 0;
435  				}
436  	
437  				dst_link->last_good_mtu = onwire_len;
438  			}
(45) Event if_end: End of if statement.
(90) Event if_end: End of if statement.
439  		}
440  	
(46) Event cond_false: Condition "kernel_mtu", taking false branch.
(91) Event cond_false: Condition "kernel_mtu", taking false branch.
441  		if (kernel_mtu) {
442  			onwire_len = kernel_mtu;
(47) Event else_branch: Reached else branch.
(92) Event else_branch: Reached else branch.
443  		} else {
444  			onwire_len = (dst_link->last_good_mtu + dst_link->last_bad_mtu) / 2;
445  		}
446  	
447  		pthread_mutex_unlock(&knet_h->pmtud_mutex);
448  	
(48) Event goto: Jumping to label "restart".
(93) Event goto: Jumping to label "restart".
449  		goto restart;
450  	}
451  	
452  	static int _handle_check_pmtud(knet_handle_t knet_h, struct knet_host *dst_host, struct knet_link *dst_link, int force_run)
453  	{
454  		uint8_t saved_valid_pmtud;
455  		unsigned int saved_pmtud;
456  		struct timespec clock_now;
457  		unsigned long long diff_pmtud, interval;
458  	
459  		if (clock_gettime(CLOCK_MONOTONIC, &clock_now) != 0) {
460  			log_debug(knet_h, KNET_SUB_PMTUD, "Unable to get monotonic clock");
461  			return 0;
462  		}
463  	
464  		if (!force_run) {
465  			interval = knet_h->pmtud_interval * 1000000000llu; /* nanoseconds */
466  	
467  			timespec_diff(dst_link->pmtud_last, clock_now, &diff_pmtud);
468  	
469  			if (diff_pmtud < interval) {
470  				return dst_link->has_valid_mtu;
471  			}
472  		}
473  	
474  		/*
475  		 * status.proto_overhead should include all IP/(UDP|SCTP)/knet headers
476  		 *
477  		 * please note that it is not the same as link->proto_overhead that
478  		 * includes only either UDP or SCTP (at the moment) overhead.
479  		 */
480  		switch (dst_link->dst_addr.ss_family) {
481  			case AF_INET6:
482  				dst_link->status.proto_overhead = KNET_PMTUD_OVERHEAD_V6 + dst_link->proto_overhead + KNET_HEADER_ALL_SIZE + knet_h->sec_hash_size + knet_h->sec_salt_size;
483  				break;
484  			case AF_INET:
485  				dst_link->status.proto_overhead = KNET_PMTUD_OVERHEAD_V4 + dst_link->proto_overhead + KNET_HEADER_ALL_SIZE + knet_h->sec_hash_size + knet_h->sec_salt_size;
486  				break;
487  		}
488  	
489  		saved_pmtud = dst_link->status.mtu;
490  		saved_valid_pmtud = dst_link->has_valid_mtu;
491  	
492  		log_debug(knet_h, KNET_SUB_PMTUD, "Starting PMTUD for host: %u link: %u", dst_host->host_id, dst_link->link_id);
493  	
494  		errno = 0;
495  		if (_handle_check_link_pmtud(knet_h, dst_host, dst_link) < 0) {
496  			if (errno == EDEADLK) {
497  				log_debug(knet_h, KNET_SUB_PMTUD, "PMTUD for host: %u link: %u has been rescheduled", dst_host->host_id, dst_link->link_id);
498  				dst_link->status.mtu = saved_pmtud;
499  				dst_link->has_valid_mtu = saved_valid_pmtud;
500  				errno = EDEADLK;
501  				return dst_link->has_valid_mtu;
502  			}
503  			dst_link->has_valid_mtu = 0;
504  		} else {
505  			if (dst_link->status.mtu < calc_min_mtu(knet_h)) {
506  				log_info(knet_h, KNET_SUB_PMTUD,
507  					 "Invalid MTU detected for host: %u link: %u mtu: %u",
508  					 dst_host->host_id, dst_link->link_id, dst_link->status.mtu);
509  				dst_link->has_valid_mtu = 0;
510  			} else {
511  				dst_link->has_valid_mtu = 1;
512  			}
513  			if (dst_link->has_valid_mtu) {
514  				if ((saved_pmtud) && (saved_pmtud != dst_link->status.mtu)) {
515  					log_info(knet_h, KNET_SUB_PMTUD, "PMTUD link change for host: %u link: %u from %u to %u",
516  						 dst_host->host_id, dst_link->link_id, saved_pmtud, dst_link->status.mtu);
517  				}
518  				log_debug(knet_h, KNET_SUB_PMTUD, "PMTUD completed for host: %u link: %u current link mtu: %u",
519  					  dst_host->host_id, dst_link->link_id, dst_link->status.mtu);
520  	
521  				/*
522  				 * set pmtud_last, if we can, after we are done with the PMTUd process
523  				 * because it can take a very long time.
524  				 */
525  				dst_link->pmtud_last = clock_now;
526  				if (!clock_gettime(CLOCK_MONOTONIC, &clock_now)) {
527  					dst_link->pmtud_last = clock_now;
528  				}
529  			}
530  		}
531  	
532  		if (saved_valid_pmtud != dst_link->has_valid_mtu) {
533  			_host_dstcache_update_async(knet_h, dst_host);
534  		}
535  	
536  		return dst_link->has_valid_mtu;
537  	}
538  	
539  	void *_handle_pmtud_link_thread(void *data)
540  	{
541  		knet_handle_t knet_h = (knet_handle_t) data;
542  		struct knet_host *dst_host;
543  		struct knet_link *dst_link;
544  		int link_idx;
545  		unsigned int have_mtu;
546  		unsigned int lower_mtu;
547  		int link_has_mtu;
548  		int force_run = 0;
549  	
550  		set_thread_status(knet_h, KNET_THREAD_PMTUD, KNET_THREAD_STARTED);
551  	
552  		knet_h->data_mtu = calc_min_mtu(knet_h);
553  	
554  		/* preparing pmtu buffer */
555  		knet_h->pmtudbuf->kh_version = KNET_HEADER_VERSION;
556  		knet_h->pmtudbuf->kh_type = KNET_HEADER_TYPE_PMTUD;
557  		knet_h->pmtudbuf->kh_node = htons(knet_h->host_id);
558  	
559  		while (!shutdown_in_progress(knet_h)) {
560  			usleep(KNET_THREADS_TIMERES);
561  	
562  			if (pthread_mutex_lock(&knet_h->pmtud_mutex) != 0) {
563  				log_debug(knet_h, KNET_SUB_PMTUD, "Unable to get mutex lock");
564  				continue;
565  			}
566  			knet_h->pmtud_abort = 0;
567  			knet_h->pmtud_running = 1;
568  			force_run = knet_h->pmtud_forcerun;
569  			knet_h->pmtud_forcerun = 0;
570  			pthread_mutex_unlock(&knet_h->pmtud_mutex);
571  	
572  			if (force_run) {
573  				log_debug(knet_h, KNET_SUB_PMTUD, "PMTUd request to rerun has been received");
574  			}
575  	
576  			if (pthread_rwlock_rdlock(&knet_h->global_rwlock) != 0) {
577  				log_debug(knet_h, KNET_SUB_PMTUD, "Unable to get read lock");
578  				continue;
579  			}
580  	
581  			lower_mtu = KNET_PMTUD_SIZE_V4;
582  			have_mtu = 0;
583  	
584  			for (dst_host = knet_h->host_head; dst_host != NULL; dst_host = dst_host->next) {
585  				for (link_idx = 0; link_idx < KNET_MAX_LINK; link_idx++) {
586  					dst_link = &dst_host->link[link_idx];
587  	
588  					if ((dst_link->status.enabled != 1) ||
589  					    (dst_link->status.connected != 1) ||
590  					    (dst_host->link[link_idx].transport == KNET_TRANSPORT_LOOPBACK) ||
591  					    (!dst_link->last_ping_size) ||
592  					    ((dst_link->dynamic == KNET_LINK_DYNIP) &&
593  					     (dst_link->status.dynconnected != 1)))
594  						continue;
595  	
596  					if (!knet_h->manual_mtu) {
597  						link_has_mtu = _handle_check_pmtud(knet_h, dst_host, dst_link, force_run);
598  						if (errno == EDEADLK) {
599  							goto out_unlock;
600  						}
601  						if (link_has_mtu) {
602  							have_mtu = 1;
603  							if (dst_link->status.mtu < lower_mtu) {
604  								lower_mtu = dst_link->status.mtu;
605  							}
606  						}
607  					} else {
608  						link_has_mtu = _calculate_manual_mtu(knet_h, dst_link);
609  						if (link_has_mtu) {
610  							have_mtu = 1;
611  							if (dst_link->status.mtu < lower_mtu) {
612  								lower_mtu = dst_link->status.mtu;
613  							}
614  						}
615  					}
616  				}
617  			}
618  	
619  			if (have_mtu) {
620  				if (knet_h->data_mtu != lower_mtu) {
621  					knet_h->data_mtu = lower_mtu;
622  					log_info(knet_h, KNET_SUB_PMTUD, "Global data MTU changed to: %u", knet_h->data_mtu);
623  	
624  					if (knet_h->pmtud_notify_fn) {
625  						knet_h->pmtud_notify_fn(knet_h->pmtud_notify_fn_private_data,
626  									knet_h->data_mtu);
627  					}
628  				}
629  			}
630  	out_unlock:
631  			pthread_rwlock_unlock(&knet_h->global_rwlock);
632  			if (pthread_mutex_lock(&knet_h->pmtud_mutex) != 0) {
633  				log_debug(knet_h, KNET_SUB_PMTUD, "Unable to get mutex lock");
634  			} else {
635  				knet_h->pmtud_running = 0;
636  				pthread_mutex_unlock(&knet_h->pmtud_mutex);
637  			}
638  		}
639  	
640  		set_thread_status(knet_h, KNET_THREAD_PMTUD, KNET_THREAD_STOPPED);
641  	
642  		return NULL;
643  	}
644  	
645  	int knet_handle_pmtud_getfreq(knet_handle_t knet_h, unsigned int *interval)
646  	{
647  		int savederrno = 0;
648  	
649  		if (!_is_valid_handle(knet_h)) {
650  			return -1;
651  		}
652  	
653  		if (!interval) {
654  			errno = EINVAL;
655  			return -1;
656  		}
657  	
658  		savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
659  		if (savederrno) {
660  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to get read lock: %s",
661  				strerror(savederrno));
662  			errno = savederrno;
663  			return -1;
664  		}
665  	
666  		*interval = knet_h->pmtud_interval;
667  	
668  		pthread_rwlock_unlock(&knet_h->global_rwlock);
669  	
670  		errno = 0;
671  		return 0;
672  	}
673  	
674  	int knet_handle_pmtud_setfreq(knet_handle_t knet_h, unsigned int interval)
675  	{
676  		int savederrno = 0;
677  	
678  		if (!_is_valid_handle(knet_h)) {
679  			return -1;
680  		}
681  	
682  		if ((!interval) || (interval > 86400)) {
683  			errno = EINVAL;
684  			return -1;
685  		}
686  	
687  		savederrno = get_global_wrlock(knet_h);
688  		if (savederrno) {
689  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to get write lock: %s",
690  				strerror(savederrno));
691  			errno = savederrno;
692  			return -1;
693  		}
694  	
695  		knet_h->pmtud_interval = interval;
696  		log_debug(knet_h, KNET_SUB_HANDLE, "PMTUd interval set to: %u seconds", interval);
697  	
698  		pthread_rwlock_unlock(&knet_h->global_rwlock);
699  	
700  		errno = 0;
701  		return 0;
702  	}
703  	
704  	int knet_handle_enable_pmtud_notify(knet_handle_t knet_h,
705  					    void *pmtud_notify_fn_private_data,
706  					    void (*pmtud_notify_fn) (
707  							void *private_data,
708  							unsigned int data_mtu))
709  	{
710  		int savederrno = 0;
711  	
712  		if (!_is_valid_handle(knet_h)) {
713  			return -1;
714  		}
715  	
716  		savederrno = get_global_wrlock(knet_h);
717  		if (savederrno) {
718  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to get write lock: %s",
719  				strerror(savederrno));
720  			errno = savederrno;
721  			return -1;
722  		}
723  	
724  		knet_h->pmtud_notify_fn_private_data = pmtud_notify_fn_private_data;
725  		knet_h->pmtud_notify_fn = pmtud_notify_fn;
726  		if (knet_h->pmtud_notify_fn) {
727  			log_debug(knet_h, KNET_SUB_HANDLE, "pmtud_notify_fn enabled");
728  		} else {
729  			log_debug(knet_h, KNET_SUB_HANDLE, "pmtud_notify_fn disabled");
730  		}
731  	
732  		pthread_rwlock_unlock(&knet_h->global_rwlock);
733  	
734  		errno = 0;
735  		return 0;
736  	}
737  	
738  	int knet_handle_pmtud_set(knet_handle_t knet_h,
739  				  unsigned int iface_mtu)
740  	{
741  		int savederrno = 0;
742  	
743  		if (!_is_valid_handle(knet_h)) {
744  			return -1;
745  		}
746  	
747  		if (iface_mtu > KNET_PMTUD_SIZE_V4) {
748  			errno = EINVAL;
749  			return -1;
750  		}
751  	
752  		savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
753  		if (savederrno) {
754  			log_err(knet_h, KNET_SUB_PMTUD, "Unable to get read lock: %s",
755  				strerror(savederrno));
756  			errno = savederrno;
757  			return -1;
758  		}
759  	
760  		log_info(knet_h, KNET_SUB_PMTUD, "MTU manually set to: %u", iface_mtu);
761  	
762  		knet_h->manual_mtu = iface_mtu;
763  	
764  		force_pmtud_run(knet_h, KNET_SUB_PMTUD, 0, 0);
765  	
766  		pthread_rwlock_unlock(&knet_h->global_rwlock);
767  	
768  		errno = 0;
769  		return 0;
770  	}
771  	
772  	int knet_handle_pmtud_get(knet_handle_t knet_h,
773  				  unsigned int *data_mtu)
774  	{
775  		int savederrno = 0;
776  	
777  		if (!_is_valid_handle(knet_h)) {
778  			return -1;
779  		}
780  	
781  		if (!data_mtu) {
782  			errno = EINVAL;
783  			return -1;
784  		}
785  	
786  		savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
787  		if (savederrno) {
788  			log_err(knet_h, KNET_SUB_HANDLE, "Unable to get read lock: %s",
789  				strerror(savederrno));
790  			errno = savederrno;
791  			return -1;
792  		}
793  	
794  		*data_mtu = knet_h->data_mtu;
795  	
796  		pthread_rwlock_unlock(&knet_h->global_rwlock);
797  	
798  		errno = 0;
799  		return 0;
800  	}
801