Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 7 Mar 2018 10:54:10 +0000 (UTC)
From:      Eitan Adler <eadler@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r330576 - in stable/11/sys: dev/iwm dev/otus dev/usb/wlan net80211
Message-ID:  <201803071054.w27AsAPs037775@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: eadler
Date: Wed Mar  7 10:54:10 2018
New Revision: 330576
URL: https://svnweb.freebsd.org/changeset/base/330576

Log:
  Revert MFC of r330463 r330462 r330454 r330452 r330451:
  
  These commits have KPI/KBI considerations (or are a result of those that
  do). I did not properly take into account these concerns when merging to
  a kbi-stable branch.
  
  Requested by:	jhb
  Pointyhat to:	eadler

Modified:
  stable/11/sys/dev/iwm/if_iwm.c
  stable/11/sys/dev/otus/if_otus.c
  stable/11/sys/dev/usb/wlan/if_rsu.c
  stable/11/sys/net80211/ieee80211_freebsd.h
  stable/11/sys/net80211/ieee80211_ht.c
  stable/11/sys/net80211/ieee80211_input.c
  stable/11/sys/net80211/ieee80211_output.c
  stable/11/sys/net80211/ieee80211_proto.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/iwm/if_iwm.c
==============================================================================
--- stable/11/sys/dev/iwm/if_iwm.c	Wed Mar  7 10:47:27 2018	(r330575)
+++ stable/11/sys/dev/iwm/if_iwm.c	Wed Mar  7 10:54:10 2018	(r330576)
@@ -3260,13 +3260,8 @@ iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *
 	}
 
 	/* rssi is in 1/2db units */
-	rxs.c_rssi = rssi * 2;
-	rxs.c_nf = sc->sc_noise;
-	if (ieee80211_add_rx_params(m, &rxs) == 0) {
-		if (ni)
-			ieee80211_free_node(ni);
-		goto fail;
-	}
+	rxs.rssi = rssi * 2;
+	rxs.nf = sc->sc_noise;
 
 	if (ieee80211_radiotap_active_vap(vap)) {
 		struct iwm_rx_radiotap_header *tap = &sc->sc_rxtap;
@@ -3303,18 +3298,17 @@ iwm_mvm_rx_rx_mpdu(struct iwm_softc *sc, struct mbuf *
 	IWM_UNLOCK(sc);
 	if (ni != NULL) {
 		IWM_DPRINTF(sc, IWM_DEBUG_RECV, "input m %p\n", m);
-		ieee80211_input_mimo(ni, m);
+		ieee80211_input_mimo(ni, m, &rxs);
 		ieee80211_free_node(ni);
 	} else {
 		IWM_DPRINTF(sc, IWM_DEBUG_RECV, "inputall m %p\n", m);
-		ieee80211_input_mimo_all(ic, m);
+		ieee80211_input_mimo_all(ic, m, &rxs);
 	}
 	IWM_LOCK(sc);
 
 	return TRUE;
 
-fail:
-	counter_u64_add(ic->ic_ierrors, 1);
+fail:	counter_u64_add(ic->ic_ierrors, 1);
 	return FALSE;
 }
 

Modified: stable/11/sys/dev/otus/if_otus.c
==============================================================================
--- stable/11/sys/dev/otus/if_otus.c	Wed Mar  7 10:47:27 2018	(r330575)
+++ stable/11/sys/dev/otus/if_otus.c	Wed Mar  7 10:54:10 2018	(r330576)
@@ -1710,13 +1710,10 @@ otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, in
 	/* Add RSSI/NF to this mbuf */
 	bzero(&rxs, sizeof(rxs));
 	rxs.r_flags = IEEE80211_R_NF | IEEE80211_R_RSSI;
-	rxs.c_nf = sc->sc_nf[0];	/* XXX chain 0 != combined rssi/nf */
-	rxs.c_rssi = tail->rssi;
+	rxs.nf = sc->sc_nf[0];	/* XXX chain 0 != combined rssi/nf */
+	rxs.rssi = tail->rssi;
 	/* XXX TODO: add MIMO RSSI/NF as well */
-	if (ieee80211_add_rx_params(m, &rxs) == 0) {
-		counter_u64_add(ic->ic_ierrors, 1);
-		return;
-	}
+	ieee80211_add_rx_params(m, &rxs);
 
 	/* XXX make a method */
 	STAILQ_INSERT_TAIL(&rxq->mq_head, m, m_stailqpkt);
@@ -1829,10 +1826,10 @@ tr_setup:
 			if (ni != NULL) {
 				if (ni->ni_flags & IEEE80211_NODE_HT)
 					m->m_flags |= M_AMPDU;
-				(void)ieee80211_input_mimo(ni, m);
+				(void)ieee80211_input_mimo(ni, m, NULL);
 				ieee80211_free_node(ni);
 			} else
-				(void)ieee80211_input_mimo_all(ic, m);
+				(void)ieee80211_input_mimo_all(ic, m, NULL);
 		}
 #ifdef	IEEE80211_SUPPORT_SUPERG
 		ieee80211_ff_age_all(ic, 100);

Modified: stable/11/sys/dev/usb/wlan/if_rsu.c
==============================================================================
--- stable/11/sys/dev/usb/wlan/if_rsu.c	Wed Mar  7 10:47:27 2018	(r330575)
+++ stable/11/sys/dev/usb/wlan/if_rsu.c	Wed Mar  7 10:54:10 2018	(r330576)
@@ -1546,14 +1546,12 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, i
 	rxs.c_ieee = le32toh(bss->config.dsconfig);
 	rxs.c_freq = ieee80211_ieee2mhz(rxs.c_ieee, IEEE80211_CHAN_2GHZ);
 	/* This is a number from 0..100; so let's just divide it down a bit */
-	rxs.c_rssi = le32toh(bss->rssi) / 2;
-	rxs.c_nf = -96;
-	if (ieee80211_add_rx_params(m, &rxs) == 0)
-		return;
+	rxs.rssi = le32toh(bss->rssi) / 2;
+	rxs.nf = -96;
 
 	/* XXX avoid a LOR */
 	RSU_UNLOCK(sc);
-	ieee80211_input_mimo_all(ic, m);
+	ieee80211_input_mimo_all(ic, m, &rxs);
 	RSU_LOCK(sc);
 }
 

Modified: stable/11/sys/net80211/ieee80211_freebsd.h
==============================================================================
--- stable/11/sys/net80211/ieee80211_freebsd.h	Wed Mar  7 10:47:27 2018	(r330575)
+++ stable/11/sys/net80211/ieee80211_freebsd.h	Wed Mar  7 10:54:10 2018	(r330576)
@@ -620,82 +620,33 @@ int	ieee80211_add_xmit_params(struct mbuf *m,
 int	ieee80211_get_xmit_params(struct mbuf *m,
 	    struct ieee80211_bpf_params *);
 
-/*
- * Note: this is fine for 3x3 (and 4x4) 11n HT40;
- * but getting EVM information for VHT80, VHT160
- * will involve more than 6 EVM pilots.
- */
-#define	IEEE80211_MAX_CHAINS		4
+#define	IEEE80211_MAX_CHAINS		3
 #define	IEEE80211_MAX_EVM_PILOTS	6
 
-#define	IEEE80211_R_NF		0x00000001	/* global NF value valid */
-#define	IEEE80211_R_RSSI	0x00000002	/* global RSSI value valid */
-#define	IEEE80211_R_C_CHAIN	0x00000004	/* RX chain count valid */
-#define	IEEE80211_R_C_NF	0x00000008	/* per-chain NF value valid */
-#define	IEEE80211_R_C_RSSI	0x00000010	/* per-chain RSSI value valid */
-#define	IEEE80211_R_C_EVM	0x00000020	/* per-chain EVM valid */
-#define	IEEE80211_R_C_HT40	0x00000040	/* RX'ed packet is 40mhz, pilots 4,5 valid */
-#define	IEEE80211_R_FREQ	0x00000080	/* Freq value populated, MHz */
-#define	IEEE80211_R_IEEE	0x00000100	/* IEEE value populated */
-#define	IEEE80211_R_BAND	0x00000200	/* Frequency band populated */
-#define	IEEE80211_R_TSF32	0x00004000	/* 32 bit TSF */
-#define	IEEE80211_R_TSF64	0x00008000	/* 64 bit TSF */
-#define	IEEE80211_R_TSF_START	0x00010000	/* TSF is sampled at start of frame */
-#define	IEEE80211_R_TSF_END	0x00020000	/* TSF is sampled at end of frame */
+#define	IEEE80211_R_NF		0x0000001	/* global NF value valid */
+#define	IEEE80211_R_RSSI	0x0000002	/* global RSSI value valid */
+#define	IEEE80211_R_C_CHAIN	0x0000004	/* RX chain count valid */
+#define	IEEE80211_R_C_NF	0x0000008	/* per-chain NF value valid */
+#define	IEEE80211_R_C_RSSI	0x0000010	/* per-chain RSSI value valid */
+#define	IEEE80211_R_C_EVM	0x0000020	/* per-chain EVM valid */
+#define	IEEE80211_R_C_HT40	0x0000040	/* RX'ed packet is 40mhz, pilots 4,5 valid */
+#define	IEEE80211_R_FREQ	0x0000080	/* Freq value populated, MHz */
+#define	IEEE80211_R_IEEE	0x0000100	/* IEEE value populated */
+#define	IEEE80211_R_BAND	0x0000200	/* Frequency band populated */
 
-/* RX packet flags - describe the kind of frame */
-#define	IEEE80211_RX_F_STBC		0x00000001
-#define	IEEE80211_RX_F_LDPC		0x00000002
-#define	IEEE80211_RX_F_AMSDU		0x00000004 /* This is the start of an decap AMSDU list */
-#define	IEEE80211_RX_F_AMSDU_MORE	0x00000008 /* This is another decap AMSDU frame in the batch */
-#define	IEEE80211_RX_F_AMPDU		0x00000010 /* This is the start of an decap AMPDU list */
-#define	IEEE80211_RX_F_AMPDU_MORE	0x00000020 /* This is another decap AMPDU frame in the batch */
-
-/* Channel width */
-#define	IEEE80211_RX_FW_20MHZ		1
-#define	IEEE80211_RX_FW_40MHZ		2
-#define	IEEE80211_RX_FW_80MHZ		3
-
-/* PHY type */
-#define	IEEE80211_RX_FP_11B		1
-#define	IEEE80211_RX_FP_11G		2
-#define	IEEE80211_RX_FP_11A		3
-#define	IEEE80211_RX_FP_11NA		4
-#define	IEEE80211_RX_FP_11NG		5
-
 struct ieee80211_rx_stats {
 	uint32_t r_flags;		/* IEEE80211_R_* flags */
-	uint32_t c_pktflags;		/* IEEE80211_RX_F_* flags */
-
-	uint64_t c_rx_tsf;		/* 32 or 64 bit TSF */
-
-	/* All DWORD aligned */
-	int16_t c_nf_ctl[IEEE80211_MAX_CHAINS];	/* per-chain NF */
-	int16_t c_nf_ext[IEEE80211_MAX_CHAINS];	/* per-chain NF */
-	int16_t c_rssi_ctl[IEEE80211_MAX_CHAINS];	/* per-chain RSSI */
-	int16_t c_rssi_ext[IEEE80211_MAX_CHAINS];	/* per-chain RSSI */
-
-	/* 32 bits */
-	uint8_t c_nf;			/* global NF */
-	uint8_t c_rssi;			/* global RSSI */
 	uint8_t c_chain;		/* number of RX chains involved */
-	uint8_t c_rate;			/* legacy + 11n rate code */
-
-	/* 32 bits */
-	uint16_t c_freq;		/* Frequency, MHz */
-	uint8_t c_ieee;			/* Channel */
-	uint8_t c_width;		/* channel width, FW flags above */
-
-	/* Force alignment to DWORD */
-	union {
-		uint8_t evm[IEEE80211_MAX_CHAINS][IEEE80211_MAX_EVM_PILOTS];
-		    /* per-chain, per-pilot EVM values */
-		uint32_t __aln[8];
-	} evm;
-
-	/* 32 bits */
-	uint8_t c_phytype;		/* PHY type, FW flags above */
-	uint8_t c_pad2[3];
+	int16_t	c_nf_ctl[IEEE80211_MAX_CHAINS];	/* per-chain NF */
+	int16_t	c_nf_ext[IEEE80211_MAX_CHAINS];	/* per-chain NF */
+	int16_t	c_rssi_ctl[IEEE80211_MAX_CHAINS];	/* per-chain RSSI */
+	int16_t	c_rssi_ext[IEEE80211_MAX_CHAINS];	/* per-chain RSSI */
+	uint8_t nf;			/* global NF */
+	uint8_t rssi;			/* global RSSI */
+	uint8_t evm[IEEE80211_MAX_CHAINS][IEEE80211_MAX_EVM_PILOTS];
+					/* per-chain, per-pilot EVM values */
+	uint16_t c_freq;
+	uint8_t c_ieee;
 };
 
 struct ieee80211_rx_params {

Modified: stable/11/sys/net80211/ieee80211_ht.c
==============================================================================
--- stable/11/sys/net80211/ieee80211_ht.c	Wed Mar  7 10:47:27 2018	(r330575)
+++ stable/11/sys/net80211/ieee80211_ht.c	Wed Mar  7 10:54:10 2018	(r330576)
@@ -586,7 +586,7 @@ ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni
 	rap->rxa_flags |=  IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND;
 
 	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni,
-	    "%s: tid=%d, start=%d, wnd=%d, flags=0x%08x",
+	    "%s: tid=%d, start=%d, wnd=%d, flags=0x%08x\n",
 	    __func__,
 	    tid,
 	    seq,

Modified: stable/11/sys/net80211/ieee80211_input.c
==============================================================================
--- stable/11/sys/net80211/ieee80211_input.c	Wed Mar  7 10:47:27 2018	(r330575)
+++ stable/11/sys/net80211/ieee80211_input.c	Wed Mar  7 10:54:10 2018	(r330576)
@@ -83,20 +83,24 @@ ieee80211_process_mimo(struct ieee80211_node *ni, stru
 }
 
 int
-ieee80211_input_mimo(struct ieee80211_node *ni, struct mbuf *m)
+ieee80211_input_mimo(struct ieee80211_node *ni, struct mbuf *m,
+    struct ieee80211_rx_stats *rx)
 {
 	struct ieee80211_rx_stats rxs;
 
-	/* try to read stats from mbuf */
-	bzero(&rxs, sizeof(rxs));
-	if (ieee80211_get_rx_params(m, &rxs) != 0)
-		return (-1);
+	if (rx) {
+		memcpy(&rxs, rx, sizeof(*rx));
+	} else {
+		/* try to read from mbuf */
+		bzero(&rxs, sizeof(rxs));
+		ieee80211_get_rx_params(m, &rxs);
+	}
 
 	/* XXX should assert IEEE80211_R_NF and IEEE80211_R_RSSI are set */
 	ieee80211_process_mimo(ni, &rxs);
 
 	//return ieee80211_input(ni, m, rx->rssi, rx->nf);
-	return ni->ni_vap->iv_input(ni, m, &rxs, rxs.c_rssi, rxs.c_nf);
+	return ni->ni_vap->iv_input(ni, m, &rxs, rxs.rssi, rxs.nf);
 }
 
 int
@@ -105,23 +109,29 @@ ieee80211_input_all(struct ieee80211com *ic, struct mb
 	struct ieee80211_rx_stats rx;
 
 	rx.r_flags = IEEE80211_R_NF | IEEE80211_R_RSSI;
-	rx.c_nf = nf;
-	rx.c_rssi = rssi;
-
-	if (!ieee80211_add_rx_params(m, &rx))
-		return (-1);
-
-	return ieee80211_input_mimo_all(ic, m);
+	rx.nf = nf;
+	rx.rssi = rssi;
+	return ieee80211_input_mimo_all(ic, m, &rx);
 }
 
 int
-ieee80211_input_mimo_all(struct ieee80211com *ic, struct mbuf *m)
+ieee80211_input_mimo_all(struct ieee80211com *ic, struct mbuf *m,
+    struct ieee80211_rx_stats *rx)
 {
+	struct ieee80211_rx_stats rxs;
 	struct ieee80211vap *vap;
 	int type = -1;
 
 	m->m_flags |= M_BCAST;		/* NB: mark for bpf tap'ing */
 
+	if (rx) {
+		memcpy(&rxs, rx, sizeof(*rx));
+	} else {
+		/* try to read from mbuf */
+		bzero(&rxs, sizeof(rxs));
+		ieee80211_get_rx_params(m, &rxs);
+	}
+
 	/* XXX locking */
 	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
 		struct ieee80211_node *ni;
@@ -142,7 +152,6 @@ ieee80211_input_mimo_all(struct ieee80211com *ic, stru
 			/*
 			 * Packet contents are changed by ieee80211_decap
 			 * so do a deep copy of the packet.
-			 * NB: tags are copied too.
 			 */
 			mcopy = m_dup(m, M_NOWAIT);
 			if (mcopy == NULL) {
@@ -154,7 +163,7 @@ ieee80211_input_mimo_all(struct ieee80211com *ic, stru
 			m = NULL;
 		}
 		ni = ieee80211_ref_node(vap->iv_bss);
-		type = ieee80211_input_mimo(ni, mcopy);
+		type = ieee80211_input_mimo(ni, mcopy, &rxs);
 		ieee80211_free_node(ni);
 	}
 	if (m != NULL)			/* no vaps, reclaim mbuf */

Modified: stable/11/sys/net80211/ieee80211_output.c
==============================================================================
--- stable/11/sys/net80211/ieee80211_output.c	Wed Mar  7 10:47:27 2018	(r330575)
+++ stable/11/sys/net80211/ieee80211_output.c	Wed Mar  7 10:54:10 2018	(r330576)
@@ -2074,7 +2074,6 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
-	struct ieee80211_node *bss;
 	const struct ieee80211_txparam *tp;
 	struct ieee80211_bpf_params params;
 	const struct ieee80211_rateset *rs;
@@ -2082,13 +2081,10 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
 	uint8_t *frm;
 	int ret;
 
-	bss = ieee80211_ref_node(vap->iv_bss);
-
 	if (vap->iv_state == IEEE80211_S_CAC) {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni,
 		    "block %s frame in CAC state", "probe request");
 		vap->iv_stats.is_tx_badstate++;
-		ieee80211_free_node(bss);
 		return EIO;		/* XXX */
 	}
 
@@ -2110,7 +2106,6 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
 	 *	[tlv] supported rates
 	 *	[tlv] RSN (optional)
 	 *	[tlv] extended supported rates
-	 *	[tlv] HT cap (optional)
 	 *	[tlv] WPA (optional)
 	 *	[tlv] user-specified ie's
 	 */
@@ -2118,8 +2113,6 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
 		 ic->ic_headroom + sizeof(struct ieee80211_frame),
 	       	 2 + IEEE80211_NWID_LEN
 	       + 2 + IEEE80211_RATE_SIZE
-	       + sizeof(struct ieee80211_ie_htcap)
-	       + sizeof(struct ieee80211_ie_htinfo)
 	       + sizeof(struct ieee80211_ie_wpa)
 	       + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
 	       + sizeof(struct ieee80211_ie_wpa)
@@ -2129,7 +2122,6 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
 	if (m == NULL) {
 		vap->iv_stats.is_tx_nobuf++;
 		ieee80211_free_node(ni);
-		ieee80211_free_node(bss);
 		return ENOMEM;
 	}
 
@@ -2138,27 +2130,6 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
 	frm = ieee80211_add_rates(frm, rs);
 	frm = ieee80211_add_rsn(frm, vap);
 	frm = ieee80211_add_xrates(frm, rs);
-
-	/*
-	 * Note: we can't use bss; we don't have one yet.
-	 *
-	 * So, we should announce our capabilities
-	 * in this channel mode (2g/5g), not the
-	 * channel details itself.
-	 */
-	if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
-	    (vap->iv_flags_ht & IEEE80211_FHT_HT)) {
-		struct ieee80211_channel *c;
-
-		/*
-		 * Get the HT channel that we should try upgrading to.
-		 * If we can do 40MHz then this'll upgrade it appropriately.
-		 */
-		c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan,
-		    vap->iv_flags_ht);
-		frm = ieee80211_add_htcap_ch(frm, vap, c);
-	}
-
 	frm = ieee80211_add_wpa(frm, vap);
 	if (vap->iv_appie_probereq != NULL)
 		frm = add_appie(frm, vap->iv_appie_probereq);
@@ -2170,7 +2141,6 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
 	if (m == NULL) {
 		/* NB: cannot happen */
 		ieee80211_free_node(ni);
-		ieee80211_free_node(bss);
 		return ENOMEM;
 	}
 
@@ -2187,11 +2157,8 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
 	IEEE80211_NODE_STAT(ni, tx_mgmt);
 
 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS,
-	    "send probe req on channel %u bssid %s sa %6D da %6D ssid \"%.*s\"\n",
-	    ieee80211_chan2ieee(ic, ic->ic_curchan),
-	    ether_sprintf(bssid),
-	    sa, ":",
-	    da, ":",
+	    "send probe req on channel %u bssid %s ssid \"%.*s\"\n",
+	    ieee80211_chan2ieee(ic, ic->ic_curchan), ether_sprintf(bssid),
 	    ssidlen, ssid);
 
 	memset(&params, 0, sizeof(params));
@@ -2206,7 +2173,6 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
 	params.ibp_power = ni->ni_txpower;
 	ret = ieee80211_raw_output(vap, ni, m, &params);
 	IEEE80211_TX_UNLOCK(ic);
-	ieee80211_free_node(bss);
 	return (ret);
 }
 

Modified: stable/11/sys/net80211/ieee80211_proto.h
==============================================================================
--- stable/11/sys/net80211/ieee80211_proto.h	Wed Mar  7 10:47:27 2018	(r330575)
+++ stable/11/sys/net80211/ieee80211_proto.h	Wed Mar  7 10:54:10 2018	(r330576)
@@ -83,8 +83,10 @@ void	ieee80211_syncflag_ext(struct ieee80211vap *, int
 	((ni)->ni_vap->iv_input(ni, m, NULL, rssi, nf))
 int	ieee80211_input_all(struct ieee80211com *, struct mbuf *, int, int);
 
-int	ieee80211_input_mimo(struct ieee80211_node *, struct mbuf *);
-int	ieee80211_input_mimo_all(struct ieee80211com *, struct mbuf *);
+int	ieee80211_input_mimo(struct ieee80211_node *, struct mbuf *,
+	    struct ieee80211_rx_stats *);
+int	ieee80211_input_mimo_all(struct ieee80211com *, struct mbuf *,
+	    struct ieee80211_rx_stats *);
 
 struct ieee80211_bpf_params;
 int	ieee80211_mgmt_output(struct ieee80211_node *, struct mbuf *, int,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803071054.w27AsAPs037775>