Up to [cvs.NetBSD.org] / src / tests / net / if_wg
Request diff between arbitrary revisions
Keyword substitution: kv
Default branch: MAIN
Pull up following revision(s) (requested by riastradh in ticket #934): sys/net/if_wg.c: revision 1.117 sys/net/if_wg.c: revision 1.118 sys/net/if_wg.c: revision 1.119 sys/net/if_wg.c: revision 1.80 sys/net/if_wg.c: revision 1.81 tests/net/if_wg/t_misc.sh: revision 1.13 sys/net/if_wg.c: revision 1.82 sys/net/if_wg.c: revision 1.130 tests/net/if_wg/t_misc.sh: revision 1.14 sys/net/if_wg.c: revision 1.83 sys/net/if_wg.c: revision 1.131 tests/net/if_wg/t_misc.sh: revision 1.15 sys/net/if_wg.c: revision 1.84 sys/net/if_wg.c: revision 1.132 tests/net/if_wg/t_misc.sh: revision 1.16 sys/net/if_wg.c: revision 1.85 sys/net/if_wg.c: revision 1.86 tests/net/if_wg/t_basic.sh: revision 1.5 sys/net/if_wg.c: revision 1.87 tests/net/if_wg/t_basic.sh: revision 1.6 sys/net/if_wg.c: revision 1.88 sys/net/if_wg.c: revision 1.89 sys/net/if_wg.c: revision 1.100 sys/net/if_wg.c: revision 1.101 sys/net/if_wg.c: revision 1.102 sys/net/if_wg.c: revision 1.103 sys/net/if_wg.c: revision 1.104 sys/net/if_wg.c: revision 1.105 sys/net/if_wg.c: revision 1.106 sys/net/if_wg.c: revision 1.107 sys/net/if_wg.c: revision 1.108 sys/net/if_wg.c: revision 1.109 sys/net/if_wg.c: revision 1.120 sys/net/if_wg.c: revision 1.121 sys/net/if_wg.c: revision 1.122 sys/net/if_wg.c: revision 1.123 sys/net/if_wg.c: revision 1.124 sys/net/if_wg.c: revision 1.75 sys/net/if_wg.c: revision 1.77 sys/net/if_wg.c: revision 1.125 sys/net/if_wg.c: revision 1.126 sys/net/if_wg.c: revision 1.79 sys/net/if_wg.c: revision 1.127 sys/net/if_wg.c: revision 1.128 sys/net/if_wg.c: revision 1.129 sys/net/if_wg.c: revision 1.90 sys/net/if_wg.c: revision 1.91 sys/net/if_wg.c: revision 1.92 sys/net/if_wg.c: revision 1.93 sys/net/if_wg.c: revision 1.94 sys/net/if_wg.c: revision 1.95 sys/net/if_wg.c: revision 1.96 sys/net/if_wg.c: revision 1.97 sys/net/if_wg.c: revision 1.98 sys/net/if_wg.c: revision 1.99 sys/net/if_wg.c: revision 1.110 sys/net/if_wg.c: revision 1.111 sys/net/if_wg.c: revision 1.112 sys/net/if_wg.c: revision 1.113 sys/net/if_wg.c: revision 1.114 sys/net/if_wg.c: revision 1.115 sys/net/if_wg.c: revision 1.116 fix simple mis-matched function prototype and definitions. most of these are like, eg void foo(int[2]); with either of these void foo(int*) { ... } void foo(int[]) { ... } in some cases (such as stat or utimes* calls found in our header files), we now match standard definition from opengroup. found by GCC 12. sys: Drop redundant NULL check before m_freem(9) m_freem(9) safely has accepted NULL argument at least since 4.2BSD: https://www.tuhs.org/cgi-bin/utree.pl?file=4.2BSD/usr/src/sys/sys/uipc_mbuf.c Compile-tested on amd64/ALL. Suggested by knakahara@ Add a wg_debug variable to split between debug/trace/dump messages Add more debugging in packet validation If any of the WG_DEBUG_XXX symbols happens to be defined (say, from a stray rump Makefile...) then we now must have WG_DEBUG also defined, so if it wasn't, make it so. While the previous change fixed the broken build, it wasn't the best way, as defining any of the WG_DEBUG_XXX symbols then effectively defined all of them - making them as seperate entities, pointless. So, rearrange the way things are done a little to avoid doing that. Add packet dump debugging fix size limit calculation in dump and NULL checks use hexdump... Fix 32 bit (32 bit size_t) WG_DEBUG builds - use %zu rather than %lu to print size_t values. There's a new WG_DEBUG_XXX ( XXX==PACKET ) to deal with now. That needs WG_DEBUG defined as well, if set. Make the debug (WG_DEBUG) func gethexdump() always return a valid pointer, never NULL, so it doesn't need to be tested before being printed, which was being done sometimes, but not always. Add more debugging from Taylor wg(4): Allow modunload before any interface creation. The workqueue and pktq are both lazily created, for annoying module initialization order reasons, so they may not have been created by the time of modunload. PR kern/58470 Limit the size of the packet, and print ... if it is bigger. (from kre@) wg(4): Rework some details of internal session state machine. This way: - There is a clear transition between when a session is being set up, and when it is exposed to the data rx path (wg_handle_msg_data): atomic_store_release to set wgs->wgs_state to INIT_PASSIVE or ESTABLISHED. (The transition INIT_PASSIVE -> ESTABLISHED is immaterial to the data rx path, so that's just atomic_store_relaxed. Similarly the transition to DESTROYING.) - There is a clear transition between when a session is being set up, and when it is exposed to the data tx path (wg_output): atomic_store_release to set wgp->wgp_session_stable to it. - Every path that reinitializes a session must go through wg_destroy_session via wg_put_index_session first. This avoids races between session reuse and the data rx/tx paths. - Add a log message at the time of every state transition. Prompted by: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Fix logic to ensure session initiation is underway. Previously, wg_task_send_init_message would call wg_send_handshake_msg_init if either: (a) the stable session is UNKNOWN, meaning a session has not yet been established, either by us or by the peer (but it could be in progress); or (b) the stable session is not UNKNOWN but the unstable session is _not_ INIT_ACTIVE, meaning there is an established session and we are not currently initiating a new session. If wg_output (or wgintr) found no established session while there was already a session being initiated, we may only enter wg_task_send_init_message after the session is already established, and trigger spurious reinitiation. Instead, create a separate flag to indicate whether it is mandatory to rekey because limits have passed. Then create a session only if: (a) the stable session is not ESTABLISHED, or (b) the mandatory rekey flag is not set, and clear the mandatory rekey flag. While here, arrange to do rekey-after-time on tx, not on callout. If there's no data to tx, we shouldn't reinitiate a session -- we should stay quiet on the network. PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Use callout_halt, not callout_stop. It's possible that callout_stop might work here, but let's simplify reasoning about it -- the timers in question only take the peer intr lock, so it's safe to wait for them while holding the peer lock in the handshake worker thread. We may have to undo the task bit but that will take a bit more analysis to determine. Prompted by (but probably won't fix anything in): PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Omit needless pserialize_perform on transition to DESTROYING. A session can still be used when it is in the DESTROYING state, so there's no need to wait for users to drain here -- that's the whole point of a separate DESTROYING state. It is only the transition from DESTROYING back to UNKNOWN, after the session has been unpublished so no new users can begin, that requires waiting for all users to drain, and we already do that in wg_destroy_session. Prompted by (but won't fix anything in, because this is just a performance optimization): PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Expand cookie secret to 32 bytes. This is only relevant for denial of service mitigation, so it's not that big a deal, and the spec doesn't say anything about the size, but let's make it the standard key size. PR kern/58479: experimental wg(4) uses 32-bit cookie secret, not 32-byte cookie secret wg(4): Mark wgp_pending volatile to reflect its usage. Prompted by (but won't fix any part of): PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Fix session destruction. Schedule destruction as soon as the session is created, to ensure key erasure within 2*reject-after-time seconds. Previously, we would schedule destruction of the previous session 1 second after the next one has been established. Combined with a failure to update the state machine on keepalive packets, this led to temporary deadlock scenarios. To keep it simple, there's just one callout which runs every reject-after-time seconds and erases keys in sessions older than reject-after-time, so if a session is established the moment after it runs, the keys might not be erased until (2-eps)*reject-after-time seconds. PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Reject rx on sessions older than reject-after-time sec. Prompted by (but won't fix anything in): PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): On rx of valid ciphertext, make sure to update state machine. Previously, we also required the plaintext to be a plausible-looking IP packet before updating the state machine. But keepalive packets are empty -- and if the peer initiated the session to rekey after last tx but had no more data to tx, it will send a keepalive to finish session initiation. If we didn't update the state machine in that case, we would stay in INIT_PASSIVE state unable to tx on the session, which would make things hang. So make sure to always update the state machine once we have accepted a packet as genuine, even if it's genuine garbage on the inside. PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Make sure to update endpoint on keepalive packets too. Prompted by: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. tests/net/if_wg/t_misc: Tweak timeouts in wg_handshake_timeout. Most of the timers in wg(4) have only 1sec resolution, which might be rounded in either direction, so make sure there's a 2sec buffer on either side of the event we care about (the point at which wg(4) decides to stop retrying handshake). Won't fix any bugs, but might make the tests slightly less flaky. PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions tests/net/if_wg/t_misc: Elaborate in wg_rekey debug messages. Helpful for following the test log when things go wrong. PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Tests should pass now. PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Use 32-bit for times handled in rx/tx paths. The rx and tx paths require unlocked access to wgs_time_established (to decide whether it's time to rekey) and wgs_time_last_data_sent (to decide whether we need to reply to incoming data with a keepalive packet), so do it with atomic_load/store_*. On 32-bit platforms, we may not be able to do that on time_t. However, since sessions only last for a few minutes before reject-after-time kicks in and they are erased, 32 bits is plenty to record the durations that we need to record here, so this shouldn't introduce any new bugs even on hosts that exceed 136 years of uptime. Prompted by: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Make time_uptime32 work in netbsd<=10. This is the low 32 bits of time_uptime. Will simplify pullups to 10 for: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Fix quotation in comment. Prompted by: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Process all altq'd packets when deleting peer. Can't just drop them because we can only go through all packets on an interface at a time, for all peers -- so we'd either have to drop all peers' packets, or requeue the packets for other peers. Probably not worth the trouble, so let's just wait for all the packets currently queued up to go through first. This requires reordering teardown so that we wg_destroy_all_peers, and thus wg_purge_pending_packets, _before_ we wg_if_detach, because wg_if_detach -> if_detach destroys the lock that IFQ_DEQUEUE uses. PR kern/58477: experimental wg(4) ALTQ support is probably buggy wg(4): Tidy up error branches. No functional change intended, except to add some log messages in failure cases. Cleanup after: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Be more consistent about #ifdef INET/INET6. PR kern/58478: experimental wg(4) probably doesn't build with INET6-only wg(4): Parenthesize macro expansions properly. PR kern/58480: experimental wg(4) sliding window logic has oopsie wg(4): Delete temporary hacks to dump keys and packets. No longer useful for: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Explain why gethexdump/puthexdump is there, and tidy. This way I will not be tempted to replace it by in-line calls to libkern hexdump. PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Put force_rekey state in the session, not the peer. That way, there is a time when one thread has exclusive access to the state, in wg_destroy_session under the peer lock, when we can clear the state without racing against the data tx path. This will work more reliably than the atomic_swap_uint I used before. Noted by kre@. PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Sprinkle static on fixed-size array parameters. Let's make the static size declarations useful. No functional change intended. wg(4): Queue pending packet in FIFO order, not LIFO order. Sometimes the session takes a seconds to establish, for whatever reason. It is better if the pending packet, which we queue up to send as soon as we get the responder's handshake response, is the most recent packet, rather than the first packet. That way, we don't wind up with a weird multi-second-delayed ping, followed by a bunch of dropped, followed by normal ping timings, or wind up sending the first TCP SYN instead of the most recent, or what have you. Senders need to be prepared to retransmit anyway if packets are dropped. PR kern/58508: experimental wg(4) queues LIFO, not FIFO, pending first handshake wg(4): Sprinkle comments into wg_swap_sessions. No functional change intended. Prompted by: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): No need for atomic access to wgs_time_established in tx/rx. This is stable while the session is visible to the tx/rx paths -- it is initialized before the session is exposed to tx/rx, and doesn't change until the session is no longer used by any tx/rx path and has been recycled. When I sprinkled atomic access to wgs_time_established in if_wg.c rev. 1.104, it was a vestige of an uncommitted draft that did the transition from INIT_PASSIVE to ESTABLISHED in the tx path itself, in an attempt to enable prompter tx on the new session as soon as it is established. This turned out to be unnecessary, so I reverted most of it, but forgot that wgs_time_established no longer needed atomic treatment. We could go back to using time_t and time_uptime, now that there's no need to do atomic loads and stores on these quantities. But there's no point in 64-bit arithmetic when the time differences are all guaranteed bounded by a few minutes, so keeping it 32-bit is probably a slight performance improvement on 32-bit systems. (In contrast, wgs_time_last_data_sent is both written and read in the tx path, which may run in parallel on multiple CPUs, so it still requires the atomic treatment.) Tidying up for: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Fix memory ordering in detach. PR kern/58510: experimental wg(4) lacks memory ordering between wg_count_dec and module unload wg(4): Fix typo in comment recently added. Comment added in the service of: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Omit needless atomic_load. wgs_local_index is only ever written to while only one thread has access to it and it is not in the thmap -- before it is published in wg_get_session_index, and after it is unpublished in wg_destroy_session. So no need for atomic_load -- it is stable if we observe it in thmap_get result. (Of course this is only for an assertion, which if tripped obviously indicates a violation of our assumptions. But if that happens, well, in the worst case we'll see a weird assertion message claiming that the index is not equal to itself, which from which we can conclude there must have been a concurrent update, which is good enough to help diagnose that problem without any atomic_load.) Tidying some of the changes for: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Sprinkle comments on internal sliding window API. Post-fix tidying for: PR kern/58480: experimental wg(4) sliding window logic has oopsie wg(4): Deduplicate session establishment actions. The actions to (a) record the last handshake time, (b) clear some handshake state, (c) transmit first data if queued, or (if initiator) keepalive, and (d) begin destroying the old session, were formerly duplicated between wg_handle_msg_resp (for when we're the initiator) and wg_task_establish_session (for when we're the responder). Instead, let's factor this out into wg_swap_session so there's only one copy of the logic. This requires moving wg_update_endpoint_if_necessary a little earlier in wg_handle_msg_resp -- which should be done anyway so that the endpoint is updated _before_ the session is published for the data tx path to use. Other than moving wg_update_endpoint_if_necessary a little earlier, no functional change intended. Post-fix tidying for: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Read wgs_state atomically in wg_get_stable_session. As noted in the comment above, it may concurrently transition from ESTABLISHED to DESTROYING. Post-fix tidying for: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Force rekey on tx if session is older than reject-after-time. One more corner case for: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Add missing barriers around wgp_pending access. PR kern/58520: experimental wg(4) lacks barriers around access to packet pending initiation wg(4): Trigger session initiation in wgintr, not in wg_output. We have to look up the session in wgintr anyway, for wg_send_data_msg. By triggering session initiation in wgintr instead of wg_output, we can skip the stable session lookup and reference in wg_output -- simpler that way. Post-fix tidying for: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Queue packet for post-handshake retransmit if limits are hit. PR kern/58521: experimental wg(4) may drop packet after minutes of quiet wg(4): When a session is established, send first packet directly. Like we would do with the keepalive packet, if we had to send that instead -- no need to defer it to the pktq. Keep it simple. Post-fix tidying for: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Sprinkle volatile on variables requiring atomic access. No functional change intended, since the relevant access is always done with atomic_* when it might race with concurrent access -- and really this should be _Atomic or something. But for now our atomic_ops(9) API is still spelled with volatile, so we'll use that. Post-fix tidying for: PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. wg(4): Make a rule for who wins when both peers send INIT at once. The rule is that the peer with the numerically smaller public key hash, in little-endian, takes priority iff the low order bit of H(peer A pubkey) ^ H(peer B pubkey) ^ H(posix minutes as le64) is 0, and the peer with the lexicographically larger public key takes priority iff the low-order bit is 1. Another case of: PR kern/56252: wg(4) state machine has race conditions PR kern/58463: if_wg does not work when idle. This one is, as far as I can tell, simply a deadlock in the protocol of the whitepaper -- until both sides give up on the handshake and one of them (but not both) later decides to try sending data again. (But not related to our t_misc:wg_rekey test, as far as I can tell, and I haven't put enough thought into how to reliably trigger this race to write a new automatic test for it.) wg(4): Add Internet Archive links for the versions cited. No functional change. tests/net/if_wg/t_misc: Add some diagnostics. PR kern/55729: net/if_wg/t_misc:wg_rekey test case fails wg(4): Test truncated UDP input from the network. This triggers double-free in the IPv6 udp6_input path -- but, confusingly, not the IPv4 udp_input path, even though the overudp_cb interface ought to be the same: /* udp_input -- no further use of m if return is -1 */ if ((n = udp4_realinput(&src, &dst, &m, iphlen)) == -1) { UDP_STATINC(UDP_STAT_HDROPS); return; } /* udp6_input -- m_freem if return is not 0 */ if (udp6_realinput(AF_INET6, &src, &dst, &m, off) == 0) { ... } bad: m_freem(m); return IPPROTO_DONE; The subroutines udp4_realinput and udp6_realinput pass through the return value of overudp_cb in essentially the same way: /* udp4_realinput */ if (inp->inp_overudp_cb != NULL) { int ret; ret = inp->inp_overudp_cb(mp, off, inp->inp_socket, sintosa(src), inp->inp_overudp_arg); switch (ret) { case -1: /* Error, m was freed */ rcvcnt = -1; goto bad; ... bad: return rcvcnt; /* udp6_realinput */ if (inp->inp_overudp_cb != NULL) { int ret; ret = inp->inp_overudp_cb(mp, off, inp->inp_socket, sin6tosa(src), inp->inp_overudp_arg); switch (ret) { case -1: /* Error, m was freed */ rcvcnt = -1; goto bad; ... bad: return rcvcnt; PR kern/58688: userland panic of kernel via wg(4) wg(4): Fix wg_overudp_cb drop paths to null out *mp as caller needs. PR kern/58688: userland panic of kernel via wg(4)
wg(4): Fix wg_overudp_cb drop paths to null out *mp as caller needs. PR kern/58688: userland panic of kernel via wg(4)
wg(4): Test truncated UDP input from the network. This triggers double-free in the IPv6 udp6_input path -- but, confusingly, not the IPv4 udp_input path, even though the overudp_cb interface ought to be the same: /* udp_input -- no further use of m if return is -1 */ if ((n = udp4_realinput(&src, &dst, &m, iphlen)) == -1) { UDP_STATINC(UDP_STAT_HDROPS); return; } /* udp6_input -- m_freem if return is not 0 */ if (udp6_realinput(AF_INET6, &src, &dst, &m, off) == 0) { ... } bad: m_freem(m); return IPPROTO_DONE; The subroutines udp4_realinput and udp6_realinput pass through the return value of overudp_cb in essentially the same way: /* udp4_realinput */ if (inp->inp_overudp_cb != NULL) { int ret; ret = inp->inp_overudp_cb(mp, off, inp->inp_socket, sintosa(src), inp->inp_overudp_arg); switch (ret) { case -1: /* Error, m was freed */ rcvcnt = -1; goto bad; ... bad: return rcvcnt; /* udp6_realinput */ if (inp->inp_overudp_cb != NULL) { int ret; ret = inp->inp_overudp_cb(mp, off, inp->inp_socket, sin6tosa(src), inp->inp_overudp_arg); switch (ret) { case -1: /* Error, m was freed */ rcvcnt = -1; goto bad; ... bad: return rcvcnt; PR kern/58688: userland panic of kernel via wg(4)
Revert previous, 11th time failed after commit. Problem must be elsewhere.
Bump tentative flag timeout (-w) from 10 to 20 seconds. Changes this test from failing roughly half the time to working 100% over 10 tests on evbmips er4.
wg: Fix tests by sprinkling ifconfig -w 10 So protocols have time to finish setup.
Clarify wg(4)'s relation to WireGuard, pending further discussion. Still planning to replace wgconfig(8) and wg-keygen(8) by one wg(8) tool compatible with wireguard-tools; update wg(4) for the minor changes from the 2018-06-30 spec to the 2020-06-01 spec; &c. This just clarifies the current state of affairs as it exists in the development tree for now. Mark the man page EXPERIMENTAL for extra clarity.