Re: ssh(1), getrrsetbyname(3), SSHFP and DNSSEC

2020-07-17 Thread Peter J. Philipp
On Fri, Jul 17, 2020 at 11:45:22PM +0200, Jesper Wallin wrote:
> Thoughts?
> 
> 
> Yours,
> Jesper Wallin

I found this very interesting.  Too bad you didn't quote any RFC's that
support this behaviour because RFC 4033 says you shouldn't set the AD bit
in a query, RFC 4035 says something similar, but then digging some further
in RFC 6840 (internet standard) it says in section 5.7:

5.7.  Setting the AD Bit on Queries

   The semantics of the Authentic Data (AD) bit in the query were
   previously undefined.  Section 4.6 of [RFC4035] instructed resolvers
   to always clear the AD bit when composing queries.

   This document defines setting the AD bit in a query as a signal
   indicating that the requester understands and is interested in the
   value of the AD bit in the response.  This allows a requester to
   indicate that it understands the AD bit without also requesting
   DNSSEC data via the DO bit.

I just wanted to add this as a thought supporting your patch.

Best Regards,
-peter



dhclient.conf - correct typo

2020-07-17 Thread Larry Hynes
seonds -> seconds

Index: sbin/dhclient/dhclient.conf.5
===
RCS file: /cvs/src/sbin/dhclient/dhclient.conf.5,v
retrieving revision 1.50
diff -u -p -r1.50 dhclient.conf.5
--- sbin/dhclient/dhclient.conf.5   10 Feb 2020 13:18:20 -  1.50
+++ sbin/dhclient/dhclient.conf.5   17 Jul 2020 21:40:44 -
@@ -89,7 +89,7 @@ Sets the number of seconds to wait for a
 If no lease is received the first valid lease in
 .Xr dhclient.leases 5
 will be used.
-The default is 30 seonds.
+The default is 30 seconds.
 .El
 .Sh DHCP OPTION DECLARATIONS
 .Bl -tag -width Ds



Re: xhci(4) isoc: fix bogus handling of chained TRBs

2020-07-17 Thread sc . dying
hi,

On 2020/07/15 21:28, sc.dy...@gmail.com wrote:
> hi,
> 
> The patch works well on Intel PCH xhci, but not on AMD Bolton xHCI.
> I'll investigate this problem.

Bolton xHCI sometimes raises following events.
(I added printf Completion Code.)

#246 cc 13 remain 0 type 5 origlen 2048 frlengths[6] 2048
#247 cc 1 remain 0 type 1 origlen 1024 frlengths[6] 3072

It seems this behavior violates the spec. 4.10.1.1.
When the remain of 1. TRB is 0, CC should be SUCCESS, not SHORT_PKT,
and HC should not raise interrupt.
The problem is how many length 2. TRB transferred.
If real CC of 1. TRB = SUCCESS, we should add 2. TRB length to frlengths.
If SHORT_PKT, we should keep frlengths as is.
Actually with the latter assumption I can see video smoothly w/o errors.

I changed your patch to skip adding to frlengths and actlen
if previous TRB is processed AND remain == 0.


--- sys/dev/usb/xhci.c.orig Sun Apr  5 10:12:37 2020
+++ sys/dev/usb/xhci.c  Fri Jul 17 23:30:30 2020
@@ -931,7 +931,7 @@ xhci_event_xfer_isoc(struct usbd_xfer *xfer, struct xh
 {
struct usbd_xfer *skipxfer;
struct xhci_xfer *xx = (struct xhci_xfer *)xfer;
-   int trb0_idx, frame_idx = 0;
+   int trb0_idx, frame_idx = 0, prev_trb_processed = 0;
 
KASSERT(xx->index >= 0);
trb0_idx =
@@ -945,6 +945,7 @@ xhci_event_xfer_isoc(struct usbd_xfer *xfer, struct xh
if (trb0_idx++ == (xp->ring.ntrb - 1))
trb0_idx = 0;
}
+   xp->ring.trb_processed[trb_idx] = 1;
 
/*
 * If we queued two TRBs for a frame and this is the second TRB,
@@ -958,15 +959,19 @@ xhci_event_xfer_isoc(struct usbd_xfer *xfer, struct xh
trb0_idx = xp->ring.ntrb - 2;
else
trb0_idx = trb_idx - 1;
-   if (xfer->frlengths[frame_idx] == 0) {
+   prev_trb_processed = xp->ring.trb_processed[trb0_idx];
+   if (prev_trb_processed == 0) {
xfer->frlengths[frame_idx] = XHCI_TRB_LEN(letoh32(
xp->ring.trbs[trb0_idx].trb_status));
}
}
 
-   xfer->frlengths[frame_idx] +=
-   XHCI_TRB_LEN(letoh32(xp->ring.trbs[trb_idx].trb_status)) - remain;
-   xfer->actlen += xfer->frlengths[frame_idx];
+   if (!(prev_trb_processed != 0 && remain == 0)) {
+   xfer->frlengths[frame_idx] +=
+   XHCI_TRB_LEN(letoh32(xp->ring.trbs[trb_idx].trb_status)) -
+   remain;
+   xfer->actlen += xfer->frlengths[frame_idx];
+   }
 
if (xx->index != trb_idx)
return (1);
@@ -1696,6 +1701,9 @@ xhci_ring_alloc(struct xhci_softc *sc, struct xhci_rin
 
ring->ntrb = ntrb;
 
+   ring->trb_processed = malloc(ring->ntrb * sizeof(*ring->trb_processed),
+   M_DEVBUF, M_NOWAIT);
+
xhci_ring_reset(sc, ring);
 
return (0);
@@ -1704,6 +1712,8 @@ xhci_ring_alloc(struct xhci_softc *sc, struct xhci_rin
 void
 xhci_ring_free(struct xhci_softc *sc, struct xhci_ring *ring)
 {
+   free(ring->trb_processed, M_DEVBUF,
+   ring->ntrb * sizeof(*ring->trb_processed));
usbd_dma_contig_free(&sc->sc_bus, &ring->dma);
 }
 
@@ -1715,6 +1725,8 @@ xhci_ring_reset(struct xhci_softc *sc, struct xhci_rin
size = ring->ntrb * sizeof(struct xhci_trb);
 
memset(ring->trbs, 0, size);
+   memset(ring->trb_processed, 0,
+   ring->ntrb * sizeof(*ring->trb_processed));
 
ring->index = 0;
ring->toggle = XHCI_TRB_CYCLE;
@@ -1799,6 +1811,8 @@ xhci_ring_produce(struct xhci_softc *sc, struct xhci_r
ring->index = 0;
ring->toggle ^= 1;
}
+
+   ring->trb_processed[(trb - &ring->trbs[0])] = 0;
 
return (trb);
 }



Re: ssh(1), getrrsetbyname(3), SSHFP and DNSSEC

2020-07-17 Thread Jeremy C. Reed
On Fri, 17 Jul 2020, Jeremy C. Reed wrote:

> > To get a response with the AD flag set, the request itself also needs
> > to have the AD flag set.

I re-read your post again and see you already clarified this.



Re: ssh(1), getrrsetbyname(3), SSHFP and DNSSEC

2020-07-17 Thread Jeremy C. Reed
On Fri, 17 Jul 2020, Jesper Wallin wrote:

> To get a response with the AD flag set, the request itself also needs
> to have the AD flag set.

...

> -#define RES_DEFAULT(RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
> +#define RES_DEFAULT(RES_RECURSE | RES_DEFNAMES | RES_DNSRCH | RES_USE_AD)

Can you share some examples of "needs" AD flag set in 
combination with DO flag? It's not required to set the AD 
flag when the DO flag is already set. You can set the DO flag without AD 
flag also set and get AD flag set in the response. (As a brief 
explanation, if the validator already authenticated it, when setting the 
AD flag without the DO flag in the query, the validator can send back 
the AD without the RRSIG records.)

(I don't have any argument with adding the feature and enabling it, but 
I am curious what specific example caused you to require it.)



Re: Add ability to set control values with video(1)

2020-07-17 Thread Laurence Tratt
On Mon, Jul 13, 2020 at 07:39:41PM +0100, Laurence Tratt wrote:

> video(1) allows users to adjust controls such as brightness, saturation
> (etc.) depending on the input device in question. These values persist even
> after video(1) has quit, allowing you to e.g. increase the brightness of a
> webcam before connecting to a video call. However, the only way to adjust
> values is to hold down keys in the GUI, which is slow, error prone, and
> can't easily be scripted.
> 
> This patch adds a "-c" option to video(1) which either takes the special
> value "reset" or a "control=value" pair. For example:
> 
>   $ video -c reset
> 
> resets all the controls to their default values. Assuming the input device
> in question supports brightness one can set that as follows:
> 
>   $ video -c brightness=200
> 
> Note that the available controls, and their min/max values, will vary from
> device to device.
> 
> To keep the patch simple, only one "-c" option can be passed to video(1) at
> a time. Note that passing this option causes video(1) to quit before
> displaying video (in identical fashion to "-q") which makes it useful for
> scripting purposes.

The attached patch reworks things a bit. First, it now works with
white_balance_temperature, which (at least on my C920) requires mmap_init to
be called first. Second, the previous patch sometimes set controls to
surprising values because it called what is (in effect) a "change control by
X" function. This patch now renames the "old" function to "dev_inc_ctrl" and
introduces a new "dev_set_ctrl_abs". This then provides an obvious
opportunity to simplify the reset function.

With this patch I can do things like:

  $ video -c white_balance_temperature=6500
  $ video -c brightness=200
  $ video && video -c reset && video

and see changes being made as appropriate.


Laurie



Index: video.1
===
RCS file: /cvs/xenocara/app/video/video.1,v
retrieving revision 1.15
diff -u -r1.15 video.1
--- video.1 17 Jul 2020 07:51:23 -  1.15
+++ video.1 17 Jul 2020 21:44:49 -
@@ -27,6 +27,7 @@
 .Bk -words
 .Op Fl \&gqRv
 .Op Fl a Ar adaptor
+.Op Fl c Ar reset | control=value
 .Op Fl e Ar encoding
 .Op Fl f Ar file
 .Op Fl i Ar input
@@ -81,6 +82,15 @@
 adaptor to use.
 The default is 0, the first adaptor reported by
 .Xr X 7 .
+.It Fl c Ar reset | control=value
+Set control value (e.g. brightness) and exit. The special name
+.Ql reset
+resets all values to their default. The available controls can be found
+with
+.Fl q
+and the default values with
+.Fl c Ar reset
+.Fl v .
 .It Fl e Ar encoding
 Lowercase FOURCC name of video encoding to use.
 Valid arguments are
Index: video.c
===
RCS file: /cvs/xenocara/app/video/video.c,v
retrieving revision 1.31
diff -u -r1.31 video.c
--- video.c 17 Jul 2020 07:51:23 -  1.31
+++ video.c 17 Jul 2020 21:44:49 -
@@ -192,7 +192,10 @@
 #define M_IN_FILE  0x4
 #define M_OUT_FILE 0x8
 #define M_QUERY0x10
+#define M_RESET0x20
+#define M_SET_CTRL 0x40
int  mode;
+   char*set_ctrl_str;
int  verbose;
 };
 
@@ -212,10 +215,12 @@
 void dev_dump_info(struct video *);
 void dev_dump_query(struct video *);
 int dev_init(struct video *);
-void dev_set_ctrl(struct video *, int, int);
+void dev_inc_ctrl(struct video *, int, int);
+void dev_set_ctrl_abs(struct video *vid, int, int);
 void dev_set_ctrl_auto_white_balance(struct video *, int);
 void dev_reset_ctrls(struct video *);
 
+int parse_ctrl(struct video *, int *, int *);
 int parse_size(struct video *);
 int choose_size(struct video *);
 int choose_enc(struct video *);
@@ -241,9 +246,9 @@
 usage(void)
 {
fprintf(stderr, "usage: %s [-gqRv] "
-   "[-a adaptor] [-e encoding] [-f file] [-i input] [-O output]\n"
-   "   %*s [-o output] [-r rate] [-s size]\n", __progname,
-   (int)strlen(__progname), "");
+   "[-a adaptor] [-c reset|control=value] [-e encoding] [-f file]\n"
+   "   %*s [-i input] [-O output] [-o output] [-r rate] [-s 
size]\n",
+   __progname, (int)strlen(__progname), "");
 }
 
 int
@@ -657,46 +662,46 @@
switch (str) {
case 'A':
if (vid->mode & M_IN_DEV)
-   dev_set_ctrl(vid, CTRL_SHARPNESS, 1);
+   dev_inc_ctrl(vid, CTRL_SHARPNESS, 1);
break;
case 'a':
if (vid->mode & M_IN_DEV)
-   dev_set_ctrl(vid, CTRL_SHARPNESS, -1);
+   dev_inc_ctrl(vid, CTRL_SHARPNESS, -1);
break;
case 'B':
if (vid-

ssh(1), getrrsetbyname(3), SSHFP and DNSSEC

2020-07-17 Thread Jesper Wallin
Hi all,

I recently decided to add SSHFP records for my servers, since I never
memorize or write down my key fingerprints.  I learned that if I
want ssh(1) to trust these records, DNSSEC needs to be enabled for my
zone.  To validate these records, ssh(1) is using getrrsetbyname(3),
which checks if the AD (Authentic Data) flag is set in the response.

To get a response with the AD flag set, the request itself also needs
to have the AD flag set.  It turns out that getrrsetbyname(3) doesn't
set this and will therefore never get a validated response, unless the
resolver is configured to always send it, no matter what the client
requested.

It seems like unwind(8) behaves this way but it also responds with the
RRSIG records, which is extra overhead and ignored by getrrsetbyname(3).

This was mentioned a few years ago [0] and the solution suggested was
to add the RES_USE_DNSSEC to _res.options, which also makes the resolver
respond with the extra RRSIG records.

Instead, by only setting the AD flag, both the request and the response
has the same size as without the flag set.  The patch below will add
RES_USE_AD as an option to _res.options and set it by default.
This is also the default behaviour in dig(1), which I understand is a
bit different, but that sure added some confusion while debugging this.

This let you run unbound(8) or any other validating resolver on your
local network and getrrsetbyname(3) will trust it.  Do read the CAVEATS
in the manual of getrrsetbyname(3) though.

As a side note, I noticed that the default value of _res.options was the
same value as RES_DEFAULT, so I changed it to RES_DEFAULT instead, for
the sake of consistency.

Thoughts?


Yours,
Jesper Wallin

[0] https://marc.info/?t=14998384322&r=1&w=2


Index: include/resolv.h
===
RCS file: /cvs/src/include/resolv.h,v
retrieving revision 1.22
diff -u -p -r1.22 resolv.h
--- include/resolv.h14 Jan 2019 06:23:06 -  1.22
+++ include/resolv.h17 Jul 2020 21:25:30 -
@@ -191,8 +191,9 @@ struct __res_state_ext {
 /* DNSSEC extensions: use higher bit to avoid conflict with ISC use */
 #defineRES_USE_DNSSEC  0x2000  /* use DNSSEC using OK bit in 
OPT */
 #defineRES_USE_CD  0x1000  /* set Checking Disabled flag */
+#defineRES_USE_AD  0x8000  /* set Authentic Data flag */
 
-#define RES_DEFAULT(RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
+#define RES_DEFAULT(RES_RECURSE | RES_DEFNAMES | RES_DNSRCH | RES_USE_AD)
 
 /*
  * Resolver "pfcode" values.  Used by dig.
Index: lib/libc/asr/asr.c
===
RCS file: /cvs/src/lib/libc/asr/asr.c,v
retrieving revision 1.64
diff -u -p -r1.64 asr.c
--- lib/libc/asr/asr.c  6 Jul 2020 13:33:05 -   1.64
+++ lib/libc/asr/asr.c  17 Jul 2020 21:25:30 -
@@ -511,7 +511,7 @@ asr_ctx_create(void)
if ((ac = calloc(1, sizeof(*ac))) == NULL)
return (NULL);
 
-   ac->ac_options = RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
+   ac->ac_options = RES_DEFAULT;
ac->ac_refcount = 1;
ac->ac_ndots = 1;
ac->ac_family[0] = AF_INET;
Index: lib/libc/asr/res_mkquery.c
===
RCS file: /cvs/src/lib/libc/asr/res_mkquery.c,v
retrieving revision 1.13
diff -u -p -r1.13 res_mkquery.c
--- lib/libc/asr/res_mkquery.c  14 Jan 2019 06:49:42 -  1.13
+++ lib/libc/asr/res_mkquery.c  17 Jul 2020 21:25:30 -
@@ -62,6 +62,8 @@ res_mkquery(int op, const char *dname, i
h.flags |= RD_MASK;
if (ac->ac_options & RES_USE_CD)
h.flags |= CD_MASK;
+   if (ac->ac_options & RES_USE_AD)
+   h.flags |= AD_MASK;
h.qdcount = 1;
if (ac->ac_options & (RES_USE_EDNS0 | RES_USE_DNSSEC))
h.arcount = 1;
Index: lib/libc/asr/res_send_async.c
===
RCS file: /cvs/src/lib/libc/asr/res_send_async.c,v
retrieving revision 1.39
diff -u -p -r1.39 res_send_async.c
--- lib/libc/asr/res_send_async.c   28 Sep 2019 11:21:07 -  1.39
+++ lib/libc/asr/res_send_async.c   17 Jul 2020 21:25:30 -
@@ -378,6 +378,8 @@ setup_query(struct asr_query *as, const 
h.flags |= RD_MASK;
if (as->as_ctx->ac_options & RES_USE_CD)
h.flags |= CD_MASK;
+   if (as->as_ctx->ac_options & RES_USE_AD)
+   h.flags |= AD_MASK;
h.qdcount = 1;
if (as->as_ctx->ac_options & (RES_USE_EDNS0 | RES_USE_DNSSEC))
h.arcount = 1;
Index: lib/libc/net/res_init.3
===
RCS file: /cvs/src/lib/libc/net/res_init.3,v
retrieving revision 1.4
diff -u -p -r1.4 res_init.3
--- lib/libc/net/res_init.3 25 Apr 2020 21:06:17 -  1.4
+++ lib/libc/net/res_init.3 17 Jul 2020 21:25:30 -00

Re: timekeep: fixing large skews on amd64 with RDTSCP

2020-07-17 Thread Philip Guenther
On Thu, Jul 16, 2020 at 4:55 PM Scott Cheloha 
wrote:

> > On Jul 16, 2020, at 19:36, Theo de Raadt  wrote:
> >
> >> Note the third sentence.
> >>
> >> Given that, I reason that a serializing instruction before *and* after
> >> the RDTSC should freeze it in place.
> >
> > I haven't seen anyone read it that way.
>
> They say that instructions after RDTSC can run before it because
> it isn't a serializing instruction.
>
> Do we want that?
>
> And then, consider this bit of programming advice.  Also from the
> ISA reference (Vol. 2B 4-547):
>
> > If software requires RDTSC to be executed prior to execution of any
> > subsequent instruction (including any memory accesses), it can
> > execute the sequence LFENCE immediately after RDTSC.
>
> What other reading is possible given this documentation?
>
> What is your interpretation?  Am I missing something?
>

If you're trying to time a sequence of instructions via rdtsc, then you
have to put an lfence after the first rdtsc (so that the sequence being
timed doesn't get lifted to before it completes) and an lfence before the
second rdtsc (so that the sequence is actually complete before the second
one).  In this case, is it a problem if instructions after the rdtsc that
are not dependent on its result may be started before it's actually
complete?  If not, then there's no reason to bracket that side.


Philip Guenther


Re: net80211: skip input block ack window gaps faster

2020-07-17 Thread Uwe Werler
> Next version.
> 
> One problem with the previous patch was that it effectively limited the
> size of the BA window to the arbitrarily chosen limit of 16. We should not
> drop frames which arrive out of order but still fall within the BA window.
> 
> With this version, we allow the entire block ack window (usually 64 frames)
> to fill up beyond the missing frame at the head, and only then bypass the
> gap timeout handler and skip over the missing frame directly. I can still
> trigger this shortcut with tcpbench, and still see the timeout run sometimes.
> Direct skip should be faster than having to wait for the timeout to run,
> and missing just one out of 64 frames is a common case in my testing.
> 
> Also, I am not quite sure if calling if_input() from a timeout is such a
> good idea. Any opinions about that? This patch still lets the gap timeout
> handler clear the leading gap but avoids flushing buffered frames there.
> The peer will now need to send another frame to flush the buffer, but now
> if_input() will be called from network interrupt context only. Which is
> probably a good thing?
> 
> This code still seems to recover well enough from occasional packet loss,
> which is what this is all about. If you are on a really bad link, none
> of this will help anyway.
> 
> diff refs/heads/master refs/heads/ba-gap
> blob - 098aa9bce19481ce09676ce3c4fc0040f14c9b93
> blob + 4f41b568311bf29e131a3f4802e0a238ba940fe0
> --- sys/net80211/ieee80211_input.c
> +++ sys/net80211/ieee80211_input.c
> @@ -67,6 +67,7 @@ voidieee80211_input_ba(struct ieee80211com *, 
> struct 
>   struct mbuf_list *);
>  void ieee80211_input_ba_flush(struct ieee80211com *, struct ieee80211_node *,
>   struct ieee80211_rx_ba *, struct mbuf_list *);
> +int  ieee80211_input_ba_gap_skip(struct ieee80211_rx_ba *);
>  void ieee80211_input_ba_gap_timeout(void *arg);
>  void ieee80211_ba_move_window(struct ieee80211com *,
>   struct ieee80211_node *, u_int8_t, u_int16_t, struct mbuf_list *);
> @@ -837,10 +838,29 @@ ieee80211_input_ba(struct ieee80211com *ic, struct mbu
>   rxi->rxi_flags |= IEEE80211_RXI_AMPDU_DONE;
>   ba->ba_buf[idx].rxi = *rxi;
>  
> - if (ba->ba_buf[ba->ba_head].m == NULL)
> - timeout_add_msec(&ba->ba_gap_to, IEEE80211_BA_GAP_TIMEOUT);
> - else if (timeout_pending(&ba->ba_gap_to))
> - timeout_del(&ba->ba_gap_to);
> + if (ba->ba_buf[ba->ba_head].m == NULL) {
> + if (ba->ba_gapwait < (ba->ba_winsize - 1)) {
> + if (ba->ba_gapwait == 0) {
> + timeout_add_msec(&ba->ba_gap_to,
> + IEEE80211_BA_GAP_TIMEOUT);
> + }
> + ba->ba_gapwait++;
> + } else {
> + /*
> +  * A full BA window worth of frames is now waiting.
> +  * Skip the missing frame at the head of the window.
> +  */
> + int skipped = ieee80211_input_ba_gap_skip(ba);
> + ic->ic_stats.is_ht_rx_ba_frame_lost += skipped;
> + ba->ba_gapwait = 0;
> + if (timeout_pending(&ba->ba_gap_to))
> + timeout_del(&ba->ba_gap_to);
> + }
> + } else {
> + ba->ba_gapwait = 0;
> + if (timeout_pending(&ba->ba_gap_to))
> + timeout_del(&ba->ba_gap_to);
> + }
>  
>   ieee80211_input_ba_flush(ic, ni, ba, ml);
>  }
> @@ -908,10 +928,26 @@ ieee80211_input_ba_flush(struct ieee80211com *ic, stru
>   * A leading gap will occur if a particular A-MPDU subframe never arrives
>   * or if a bug in the sender causes sequence numbers to jump forward by > 1.
>   */
> +int
> +ieee80211_input_ba_gap_skip(struct ieee80211_rx_ba *ba)
> +{
> + int skipped = 0;
> +
> + while (skipped < ba->ba_winsize && ba->ba_buf[ba->ba_head].m == NULL) {
> + /* move window forward */
> + ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;
> + ba->ba_winstart = (ba->ba_winstart + 1) & 0xfff;
> + skipped++;
> + }
> + if (skipped > 0)
> + ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;
> +
> + return skipped;
> +}
> +
>  void
>  ieee80211_input_ba_gap_timeout(void *arg)
>  {
> - struct mbuf_list ml = MBUF_LIST_INITIALIZER();
>   struct ieee80211_rx_ba *ba = arg;
>   struct ieee80211_node *ni = ba->ba_ni;
>   struct ieee80211com *ic = ni->ni_ic;
> @@ -921,20 +957,9 @@ ieee80211_input_ba_gap_timeout(void *arg)
>  
>   s = splnet();
>  
> - skipped = 0;
> - while (skipped < ba->ba_winsize && ba->ba_buf[ba->ba_head].m == NULL) {
> - /* move window forward */
> - ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;
> - ba->ba_winstart = (ba->ba_winstart + 1) & 0xfff;
> - skipped++;
> -  

Re: net80211: skip input block ack window gaps faster

2020-07-17 Thread Stefan Sperling
On Fri, Jul 17, 2020 at 03:59:38PM +0200, Stefan Sperling wrote:
> While measuring Tx performance at a fixed Tx rate with iwm(4) I observed
> unexpected dips in throughput measured by tcpbench. These dips coincided
> with one or more gap timeouts shown in 'netstat -W iwm0', such as:
>   77 input block ack window gaps timed out
> Which means lost frames on the receive side were stalling subsequent frames
> and thus slowing tcpbench down.
> 
> I decided to disable the gap timeout entirely to see what would happen if
> those missing frames were immediately skipped rather than waiting for them.
> The result was stable throughput according to tcpbench.
> 
> I then wrote the patch below which keeps the gap timeout intact (it is needed
> in case the peer stops sending anything) but skips missing frames at the head
> of the Rx block window once a certain amount of frames have queued up. This
> heuristics avoids having to wait for the timeout to fire in order to get
> frames flowing again if we lose one of more frames during Rx traffic bursts.
> 
> I have picked a threshold of 16 outstanding frames based on local testing.
> I have no idea if this is a good threshold for everyone. It would help to
> get some feedback from tests in other RF environments and other types of 
> access points. Any regressions?

Next version.

One problem with the previous patch was that it effectively limited the
size of the BA window to the arbitrarily chosen limit of 16. We should not
drop frames which arrive out of order but still fall within the BA window.

With this version, we allow the entire block ack window (usually 64 frames)
to fill up beyond the missing frame at the head, and only then bypass the
gap timeout handler and skip over the missing frame directly. I can still
trigger this shortcut with tcpbench, and still see the timeout run sometimes.
Direct skip should be faster than having to wait for the timeout to run,
and missing just one out of 64 frames is a common case in my testing.

Also, I am not quite sure if calling if_input() from a timeout is such a
good idea. Any opinions about that? This patch still lets the gap timeout
handler clear the leading gap but avoids flushing buffered frames there.
The peer will now need to send another frame to flush the buffer, but now
if_input() will be called from network interrupt context only. Which is
probably a good thing?

This code still seems to recover well enough from occasional packet loss,
which is what this is all about. If you are on a really bad link, none
of this will help anyway.

diff refs/heads/master refs/heads/ba-gap
blob - 098aa9bce19481ce09676ce3c4fc0040f14c9b93
blob + 4f41b568311bf29e131a3f4802e0a238ba940fe0
--- sys/net80211/ieee80211_input.c
+++ sys/net80211/ieee80211_input.c
@@ -67,6 +67,7 @@ void  ieee80211_input_ba(struct ieee80211com *, struct 
struct mbuf_list *);
 void   ieee80211_input_ba_flush(struct ieee80211com *, struct ieee80211_node *,
struct ieee80211_rx_ba *, struct mbuf_list *);
+intieee80211_input_ba_gap_skip(struct ieee80211_rx_ba *);
 void   ieee80211_input_ba_gap_timeout(void *arg);
 void   ieee80211_ba_move_window(struct ieee80211com *,
struct ieee80211_node *, u_int8_t, u_int16_t, struct mbuf_list *);
@@ -837,10 +838,29 @@ ieee80211_input_ba(struct ieee80211com *ic, struct mbu
rxi->rxi_flags |= IEEE80211_RXI_AMPDU_DONE;
ba->ba_buf[idx].rxi = *rxi;
 
-   if (ba->ba_buf[ba->ba_head].m == NULL)
-   timeout_add_msec(&ba->ba_gap_to, IEEE80211_BA_GAP_TIMEOUT);
-   else if (timeout_pending(&ba->ba_gap_to))
-   timeout_del(&ba->ba_gap_to);
+   if (ba->ba_buf[ba->ba_head].m == NULL) {
+   if (ba->ba_gapwait < (ba->ba_winsize - 1)) {
+   if (ba->ba_gapwait == 0) {
+   timeout_add_msec(&ba->ba_gap_to,
+   IEEE80211_BA_GAP_TIMEOUT);
+   }
+   ba->ba_gapwait++;
+   } else {
+   /*
+* A full BA window worth of frames is now waiting.
+* Skip the missing frame at the head of the window.
+*/
+   int skipped = ieee80211_input_ba_gap_skip(ba);
+   ic->ic_stats.is_ht_rx_ba_frame_lost += skipped;
+   ba->ba_gapwait = 0;
+   if (timeout_pending(&ba->ba_gap_to))
+   timeout_del(&ba->ba_gap_to);
+   }
+   } else {
+   ba->ba_gapwait = 0;
+   if (timeout_pending(&ba->ba_gap_to))
+   timeout_del(&ba->ba_gap_to);
+   }
 
ieee80211_input_ba_flush(ic, ni, ba, ml);
 }
@@ -908,10 +928,26 @@ ieee80211_input_ba_flush(struct ieee80211com *ic, stru
  * A leading gap will occur if a particular A-MPDU subframe never arrives
  * or if a bug in the sender causes sequence numb

pipex(4): document global data locks

2020-07-17 Thread Vitaliy Makkoveev
Subj. Also add NET_ASSERT_LOCKED() to pipex_{link,unlink,rele}_session()
to be sure they called under NET_LOCK().

Index: sys/net/pipex.c
===
RCS file: /cvs/src/sys/net/pipex.c,v
retrieving revision 1.120
diff -u -p -r1.120 pipex.c
--- sys/net/pipex.c 17 Jul 2020 08:57:27 -  1.120
+++ sys/net/pipex.c 17 Jul 2020 14:01:10 -
@@ -83,19 +83,24 @@ struct pool pipex_session_pool;
 struct pool mppe_key_pool;
 
 /*
- * static/global variables
+ * Global data
+ * Locks used to protect global data
+ *   A   atomic operation
+ *   I   immutable after creation
+ *   N   net lock
  */
-intpipex_enable = 0;
+
+intpipex_enable = 0;   /* [N] */
 struct pipex_hash_head
-pipex_session_list,/* master session list 
*/
-pipex_close_wait_list, /* expired session list */
-pipex_peer_addr_hashtable[PIPEX_HASH_SIZE],/* peer's address hash 
*/
-pipex_id_hashtable[PIPEX_HASH_SIZE];   /* peer id hash */
+pipex_session_list,/* [N] master session 
list */
+pipex_close_wait_list, /* [N] expired session list */
+pipex_peer_addr_hashtable[PIPEX_HASH_SIZE],/* [N] peer's address 
hash */
+pipex_id_hashtable[PIPEX_HASH_SIZE];   /* [N] peer id hash */
 
-struct radix_node_head *pipex_rd_head4 = NULL;
-struct radix_node_head *pipex_rd_head6 = NULL;
+struct radix_node_head *pipex_rd_head4 = NULL; /* [N] */
+struct radix_node_head *pipex_rd_head6 = NULL; /* [N] */
 struct timeout pipex_timer_ch; /* callout timer context */
-int pipex_prune = 1;   /* walk list every seconds */
+int pipex_prune = 1;   /* [I] walk list every seconds */
 
 /* pipex traffic queue */
 struct mbuf_queue pipexinq = MBUF_QUEUE_INITIALIZER(IFQ_MAXLEN, IPL_NET);
@@ -105,7 +110,7 @@ struct mbuf_queue pipexoutq = MBUF_QUEUE
 #define ph_ppp_proto ether_vtag
 
 #ifdef PIPEX_DEBUG
-int pipex_debug = 0;   /* systcl net.inet.ip.pipex_debug */
+int pipex_debug = 0;   /* [A] systcl net.inet.ip.pipex_debug */
 #endif
 
 /* PPP compression == MPPE is assumed, so don't answer CCP Reset-Request. */
@@ -419,6 +424,8 @@ pipex_init_session(struct pipex_session 
 void
 pipex_rele_session(struct pipex_session *session)
 {
+   NET_ASSERT_LOCKED();
+
if (session->mppe_recv.old_session_keys)
pool_put(&mppe_key_pool, session->mppe_recv.old_session_keys);
pool_put(&pipex_session_pool, session);
@@ -430,6 +437,8 @@ pipex_link_session(struct pipex_session 
 {
struct pipex_hash_head *chain;
 
+   NET_ASSERT_LOCKED();
+
if (!iface->pipexmode)
return (ENXIO);
if (pipex_lookup_by_session_id(session->protocol,
@@ -463,6 +472,8 @@ pipex_link_session(struct pipex_session 
 void
 pipex_unlink_session(struct pipex_session *session)
 {
+   NET_ASSERT_LOCKED();
+
session->ifindex = 0;
 
LIST_REMOVE(session, id_chain);



net80211: skip input block ack window gaps faster

2020-07-17 Thread Stefan Sperling
While measuring Tx performance at a fixed Tx rate with iwm(4) I observed
unexpected dips in throughput measured by tcpbench. These dips coincided
with one or more gap timeouts shown in 'netstat -W iwm0', such as:
77 input block ack window gaps timed out
Which means lost frames on the receive side were stalling subsequent frames
and thus slowing tcpbench down.

I decided to disable the gap timeout entirely to see what would happen if
those missing frames were immediately skipped rather than waiting for them.
The result was stable throughput according to tcpbench.

I then wrote the patch below which keeps the gap timeout intact (it is needed
in case the peer stops sending anything) but skips missing frames at the head
of the Rx block window once a certain amount of frames have queued up. This
heuristics avoids having to wait for the timeout to fire in order to get
frames flowing again if we lose one of more frames during Rx traffic bursts.

I have picked a threshold of 16 outstanding frames based on local testing.
I have no idea if this is a good threshold for everyone. It would help to
get some feedback from tests in other RF environments and other types of 
access points. Any regressions?

diff e27fc20afa168944a7605737ac45330f21645404 /usr/src
blob - 098aa9bce19481ce09676ce3c4fc0040f14c9b93
file + sys/net80211/ieee80211_input.c
--- sys/net80211/ieee80211_input.c
+++ sys/net80211/ieee80211_input.c
@@ -67,6 +67,7 @@ void  ieee80211_input_ba(struct ieee80211com *, struct 
struct mbuf_list *);
 void   ieee80211_input_ba_flush(struct ieee80211com *, struct ieee80211_node *,
struct ieee80211_rx_ba *, struct mbuf_list *);
+intieee80211_input_ba_gap_skip(struct ieee80211_rx_ba *);
 void   ieee80211_input_ba_gap_timeout(void *arg);
 void   ieee80211_ba_move_window(struct ieee80211com *,
struct ieee80211_node *, u_int8_t, u_int16_t, struct mbuf_list *);
@@ -837,10 +838,24 @@ ieee80211_input_ba(struct ieee80211com *ic, struct mbu
rxi->rxi_flags |= IEEE80211_RXI_AMPDU_DONE;
ba->ba_buf[idx].rxi = *rxi;
 
-   if (ba->ba_buf[ba->ba_head].m == NULL)
-   timeout_add_msec(&ba->ba_gap_to, IEEE80211_BA_GAP_TIMEOUT);
-   else if (timeout_pending(&ba->ba_gap_to))
-   timeout_del(&ba->ba_gap_to);
+   if (ba->ba_buf[ba->ba_head].m == NULL) {
+   if (ba->ba_gapwait < IEEE80211_BA_MAX_GAPWAIT) {
+   if (ba->ba_gapwait == 0)
+   timeout_add_msec(&ba->ba_gap_to,
+   IEEE80211_BA_GAP_TIMEOUT);
+   ba->ba_gapwait++;
+   } else {
+   int skipped = ieee80211_input_ba_gap_skip(ba);
+   ic->ic_stats.is_ht_rx_ba_frame_lost += skipped;
+   ba->ba_gapwait = 0;
+   if (timeout_pending(&ba->ba_gap_to))
+   timeout_del(&ba->ba_gap_to);
+   }
+   } else {
+   ba->ba_gapwait = 0;
+   if (timeout_pending(&ba->ba_gap_to))
+   timeout_del(&ba->ba_gap_to);
+   }
 
ieee80211_input_ba_flush(ic, ni, ba, ml);
 }
@@ -902,6 +917,23 @@ ieee80211_input_ba_flush(struct ieee80211com *ic, stru
ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;
 }
 
+int
+ieee80211_input_ba_gap_skip(struct ieee80211_rx_ba *ba)
+{
+   int skipped = 0;
+
+   while (skipped < ba->ba_winsize && ba->ba_buf[ba->ba_head].m == NULL) {
+   /* move window forward */
+   ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;
+   ba->ba_winstart = (ba->ba_winstart + 1) & 0xfff;
+   skipped++;
+   }
+   if (skipped > 0)
+   ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;
+
+   return skipped;
+}
+
 /* 
  * Forcibly move the BA window forward to remove a leading gap which has
  * been causing frames to linger in the reordering buffer for too long.
@@ -921,17 +953,8 @@ ieee80211_input_ba_gap_timeout(void *arg)
 
s = splnet();
 
-   skipped = 0;
-   while (skipped < ba->ba_winsize && ba->ba_buf[ba->ba_head].m == NULL) {
-   /* move window forward */
-   ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;
-   ba->ba_winstart = (ba->ba_winstart + 1) & 0xfff;
-   skipped++;
-   ic->ic_stats.is_ht_rx_ba_frame_lost++;
-   }
-   if (skipped > 0)
-   ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;
-
+   skipped = ieee80211_input_ba_gap_skip(ba);
+   ic->ic_stats.is_ht_rx_ba_frame_lost += skipped;
ieee80211_input_ba_flush(ic, ni, ba, &ml);
if_input(&ic->ic_if, &ml);
 
@@ -2716,6 +2739,7 @@ ieee80211_recv_addba_req(struct ieee80211com *ic, stru
ba->ba_token = token;
timeout_set(&ba->ba_to, ieee80211_rx_ba_timeout, ba);
timeout_

ppp{ac,x}(4): document locks

2020-07-17 Thread Vitaliy Makkoveev
Subj.

Index: sys/net/if_pppx.c
===
RCS file: /cvs/src/sys/net/if_pppx.c,v
retrieving revision 1.97
diff -u -p -r1.97 if_pppx.c
--- sys/net/if_pppx.c   17 Jul 2020 08:57:27 -  1.97
+++ sys/net/if_pppx.c   17 Jul 2020 13:51:14 -
@@ -115,9 +115,16 @@ int pppxdebug = 0;
 
 struct pppx_if;
 
+/*
+ * Locks used to protect struct members and global data
+ *   I   immutable after creation
+ *   K   kernel lock
+ *   N   net lock
+ */
+
 struct pppx_dev {
-   LIST_ENTRY(pppx_dev)pxd_entry;
-   int pxd_unit;
+   LIST_ENTRY(pppx_dev)pxd_entry;  /* [K] */
+   int pxd_unit;   /* [I] */
 
/* kq shizz */
struct selinfo  pxd_rsel;
@@ -127,34 +134,36 @@ struct pppx_dev {
 
/* queue of packets for userland to service - protected by splnet */
struct mbuf_queue   pxd_svcq;
-   int pxd_waiting;
-   LIST_HEAD(,pppx_if) pxd_pxis;
+   int pxd_waiting;/* [N] */
+   LIST_HEAD(,pppx_if) pxd_pxis;   /* [N] */
 };
 
-LIST_HEAD(, pppx_dev)  pppx_devs = LIST_HEAD_INITIALIZER(pppx_devs);
+LIST_HEAD(, pppx_dev)  pppx_devs =
+   LIST_HEAD_INITIALIZER(pppx_devs); /* [K] */
 struct poolpppx_if_pl;
 
 struct pppx_dev*pppx_dev_lookup(dev_t);
 struct pppx_dev*pppx_dev2pxd(dev_t);
 
 struct pppx_if_key {
-   int pxik_session_id;
-   int pxik_protocol;
+   int pxik_session_id;/* [I] */
+   int pxik_protocol;  /* [I] */
 };
 
 struct pppx_if {
-   struct pppx_if_key  pxi_key; /* must be first in the struct */
+   struct pppx_if_key  pxi_key;/* [I] must be first
+   in the struct */
 
-   RBT_ENTRY(pppx_if)  pxi_entry;
-   LIST_ENTRY(pppx_if) pxi_list;
+   RBT_ENTRY(pppx_if)  pxi_entry;  /* [N] */
+   LIST_ENTRY(pppx_if) pxi_list;   /* [N] */
 
-   int pxi_ready;
+   int pxi_ready;  /* [N] */
 
-   int pxi_unit;
+   int pxi_unit;   /* [I] */
struct ifnetpxi_if;
-   struct pppx_dev *pxi_dev;
-   struct pipex_session*pxi_session;
-   struct pipex_iface_context  pxi_ifcontext;
+   struct pppx_dev *pxi_dev;   /* [I] */
+   struct pipex_session*pxi_session;   /* [I] */
+   struct pipex_iface_context  pxi_ifcontext;  /* [N] */
 };
 
 static inline int
@@ -163,7 +172,7 @@ pppx_if_cmp(const struct pppx_if *a, con
return memcmp(&a->pxi_key, &b->pxi_key, sizeof(a->pxi_key));
 }
 
-RBT_HEAD(pppx_ifs, pppx_if)pppx_ifs = RBT_INITIALIZER(&pppx_ifs);
+RBT_HEAD(pppx_ifs, pppx_if) pppx_ifs = RBT_INITIALIZER(&pppx_ifs); /* [N] */
 RBT_PROTOTYPE(pppx_ifs, pppx_if, pxi_entry, pppx_if_cmp);
 
 intpppx_if_next_unit(void);
@@ -995,12 +1004,19 @@ RBT_GENERATE(pppx_ifs, pppx_if, pxi_entr
 
 #include 
 
+/*
+ * Locks used to protect struct members and global data
+ *   I   immutable after creation
+ *   K   kernel lock
+ *   N   net lock
+ */
+
 struct pppac_softc {
struct ifnetsc_if;
-   unsigned intsc_dead;
-   dev_t   sc_dev;
+   unsigned intsc_dead;/* [N] */
+   dev_t   sc_dev; /* [I] */
LIST_ENTRY(pppac_softc)
-   sc_entry;
+   sc_entry;   /* [K] */
 
struct mutexsc_rsel_mtx;
struct selinfo  sc_rsel;
@@ -1014,7 +1030,7 @@ struct pppac_softc {
sc_mq;
 };
 
-LIST_HEAD(pppac_list, pppac_softc);
+LIST_HEAD(pppac_list, pppac_softc);/* [K] */
 
 static voidfilt_pppac_rdetach(struct knote *);
 static int filt_pppac_read(struct knote *, long);



pipex_iface_fini() release multicast session under NET_LOCK()

2020-07-17 Thread Vitaliy Makkoveev
We are going to lock the whole pipex(4) by NET_LOCK(). So move
`multicast_session' freeing undet NET_LOCK() too.

Index: sys/net/pipex.c
===
RCS file: /cvs/src/sys/net/pipex.c,v
retrieving revision 1.120
diff -u -p -r1.120 pipex.c
--- sys/net/pipex.c 17 Jul 2020 08:57:27 -  1.120
+++ sys/net/pipex.c 17 Jul 2020 13:23:16 -
@@ -192,8 +192,8 @@ pipex_iface_stop(struct pipex_iface_cont
 void
 pipex_iface_fini(struct pipex_iface_context *pipex_iface)
 {
-   pool_put(&pipex_session_pool, pipex_iface->multicast_session);
NET_LOCK();
+   pool_put(&pipex_session_pool, pipex_iface->multicast_session);
pipex_iface_stop(pipex_iface);
NET_UNLOCK();
 }



Re: Add missing `IFXF_CLONED' to pseudo-interfaces

2020-07-17 Thread Vitaliy Makkoveev
ping?

> On 10 Jul 2020, at 14:59, Vitaliy Makkoveev  wrote:
> 
> Some pseudo interfaces have missing `IFXF_CLONED' flag. Diff below fixes
> this.
> 
> Index: sys/net/if_ppp.c
> ===
> RCS file: /cvs/src/sys/net/if_ppp.c,v
> retrieving revision 1.114
> diff -u -p -r1.114 if_ppp.c
> --- sys/net/if_ppp.c  24 Jun 2020 22:03:42 -  1.114
> +++ sys/net/if_ppp.c  10 Jul 2020 11:57:39 -
> @@ -220,6 +220,7 @@ ppp_clone_create(struct if_clone *ifc, i
>   sc->sc_if.if_output = pppoutput;
>   sc->sc_if.if_start = ppp_ifstart;
>   sc->sc_if.if_rtrequest = p2p_rtrequest;
> + sc->sc_if.if_xflags = IFXF_CLONED;
>   IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN);
>   mq_init(&sc->sc_inq, IFQ_MAXLEN, IPL_NET);
>   ppp_pkt_list_init(&sc->sc_rawq, IFQ_MAXLEN);
> Index: sys/net/if_pppoe.c
> ===
> RCS file: /cvs/src/sys/net/if_pppoe.c,v
> retrieving revision 1.68
> diff -u -p -r1.68 if_pppoe.c
> --- sys/net/if_pppoe.c16 Jun 2019 00:10:37 -  1.68
> +++ sys/net/if_pppoe.c10 Jul 2020 11:57:39 -
> @@ -210,6 +210,7 @@ pppoe_clone_create(struct if_clone *ifc,
>   sc->sc_sppp.pp_if.if_ioctl = pppoe_ioctl;
>   sc->sc_sppp.pp_if.if_start = pppoe_start;
>   sc->sc_sppp.pp_if.if_rtrequest = p2p_rtrequest;
> + sc->sc_sppp.pp_if.if_xflags = IFXF_CLONED;
>   sc->sc_sppp.pp_tls = pppoe_tls;
>   sc->sc_sppp.pp_tlf = pppoe_tlf;
>   IFQ_SET_MAXLEN(&sc->sc_sppp.pp_if.if_snd, IFQ_MAXLEN);
> Index: sys/net/if_switch.c
> ===
> RCS file: /cvs/src/sys/net/if_switch.c,v
> retrieving revision 1.30
> diff -u -p -r1.30 if_switch.c
> --- sys/net/if_switch.c   6 Nov 2019 03:51:26 -   1.30
> +++ sys/net/if_switch.c   10 Jul 2020 11:57:39 -
> @@ -159,6 +159,7 @@ switch_clone_create(struct if_clone *ifc
>   ifp->if_start = NULL;
>   ifp->if_type = IFT_BRIDGE;
>   ifp->if_hdrlen = ETHER_HDR_LEN;
> + ifp->if_xflags = IFXF_CLONED;
>   TAILQ_INIT(&sc->sc_swpo_list);
> 
>   sc->sc_unit = unit;
> Index: sys/net/if_trunk.c
> ===
> RCS file: /cvs/src/sys/net/if_trunk.c,v
> retrieving revision 1.146
> diff -u -p -r1.146 if_trunk.c
> --- sys/net/if_trunk.c17 Jun 2020 06:45:22 -  1.146
> +++ sys/net/if_trunk.c10 Jul 2020 11:57:39 -
> @@ -184,6 +184,7 @@ trunk_clone_create(struct if_clone *ifc,
>   ifp->if_ioctl = trunk_ioctl;
>   ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
>   ifp->if_capabilities = trunk_capabilities(tr);
> + ifp->if_xflags = IFXF_CLONED;
> 
>   snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
>   ifc->ifc_name, unit);
> Index: sys/net/if_tun.c
> ===
> RCS file: /cvs/src/sys/net/if_tun.c,v
> retrieving revision 1.222
> diff -u -p -r1.222 if_tun.c
> --- sys/net/if_tun.c  13 May 2020 00:48:06 -  1.222
> +++ sys/net/if_tun.c  10 Jul 2020 11:57:39 -
> @@ -236,6 +236,7 @@ tun_create(struct if_clone *ifc, int uni
>   ifp->if_hardmtu = TUNMRU;
>   ifp->if_link_state = LINK_STATE_DOWN;
>   IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
> + ifp->if_xflags = IFXF_CLONED;
> 
>   if_counters_alloc(ifp);
> 
> Index: sys/net/if_vether.c
> ===
> RCS file: /cvs/src/sys/net/if_vether.c,v
> retrieving revision 1.30
> diff -u -p -r1.30 if_vether.c
> --- sys/net/if_vether.c   9 Jan 2018 15:24:24 -   1.30
> +++ sys/net/if_vether.c   10 Jul 2020 11:57:39 -
> @@ -88,6 +88,7 @@ vether_clone_create(struct if_clone *ifc
> 
>   ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN;
>   ifp->if_capabilities = IFCAP_VLAN_MTU;
> + ifp->if_xflags = IFXF_CLONED;
> 
>   ifmedia_init(&sc->sc_media, 0, vether_media_change,
>   vether_media_status);
> Index: sys/net/if_vxlan.c
> ===
> RCS file: /cvs/src/sys/net/if_vxlan.c,v
> retrieving revision 1.77
> diff -u -p -r1.77 if_vxlan.c
> --- sys/net/if_vxlan.c12 Apr 2020 11:56:52 -  1.77
> +++ sys/net/if_vxlan.c10 Jul 2020 11:57:39 -
> @@ -155,6 +155,7 @@ vxlan_clone_create(struct if_clone *ifc,
> 
>   ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN;
>   ifp->if_capabilities = IFCAP_VLAN_MTU;
> + ifp->if_xflags = IFXF_CLONED;
> 
>   ifmedia_init(&sc->sc_media, 0, vxlan_media_change,
>   vxlan_media_status);



iwn: fix off-by-one in antenna calibration for iwn5000

2020-07-17 Thread Holger Mikolon
I came across this by reading the code if_iwn.c and DPRINTFs on
a kernel with IWN_DEBUG.

IWN_LSB() returns an index starting with 1, however the arrays used
later on (noise and gain in iwn5000_set_gains()) start with 0. The
current code accounts for this difference when setting the antenna
gain by accessing cmd.gain[i - 1]. However the noise array is accessed
with noise[i], the chainmask is as well checked against i and more
importantly the overall for() loop iterates wrongly over the antennas by
always starting with i=2 (the third antenna). One consequence is, that
gain calibration never happens in case of only two antennas.

Secondly, the final DPRINTF in iwn5000_set_gains() assumes a two-antenna
setup. In my case three antennas are connected. I don't know if there
are iwn setups with one antenna, but the DPRINTF wouldn't make sense
there at all. Hence I propose to move this DPRINTF up where it makes
more sense (and adjust it to the new place).

My diff below fixes the said off-by-one and DPRINTF. Additionally
it adds another DPRINTF which I felt useful while debugging and
it extends a comment - those additions may be skipped of course.

Here is few details of my laptop (cvs updated and kernel built today):

$ dmesg | grep iwn0
iwn0 at pci2 dev 0 function 0 "Intel WiFi Link 5300" rev 0x00: msi, MIMO 3T3R, 
MoW, address 00:21:6a:56:2b:36

$ sysctl hw | grep -e machine -e model -e vendor -e product
hw.machine=amd64
hw.model=Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz
hw.vendor=Dell Inc.
hw.product=Studio 1555

Let me know if you need a full dmesg or anything else.

Regards
Holger


Index: if_iwn.c
===
RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.234
diff -u -p -u -r1.234 if_iwn.c
--- if_iwn.c10 Jul 2020 13:22:20 -  1.234
+++ if_iwn.c17 Jul 2020 10:44:14 -
@@ -4596,22 +4596,27 @@ iwn5000_set_gains(struct iwn_softc *sc)
cmd.code = sc->noise_gain;
cmd.ngroups = 1;
cmd.isvalid = 1;
-   /* Get first available RX antenna as referential. */
-   ant = IWN_LSB(sc->rxchainmask);
+   /* Get first available RX antenna as referential.
+* IWN_LSB() return values start with 1, but
+* antenna gain array cmd.gain[] and noise array
+* calib->noise[] start with 0. */
+   ant = IWN_LSB(sc->rxchainmask) - 1;
+
/* Set differential gains for other antennas. */
for (i = ant + 1; i < 3; i++) {
if (sc->chainmask & (1 << i)) {
/* The delta is relative to antenna "ant". */
delta = ((int32_t)calib->noise[ant] -
(int32_t)calib->noise[i]) / div;
+   DPRINTF(("Ant[%d] vs. Ant[%d]: delta %d\n", ant, i, 
delta));
/* Limit to [-4.5dB,+4.5dB]. */
-   cmd.gain[i - 1] = MIN(abs(delta), 3);
+   cmd.gain[i] = MIN(abs(delta), 3);
if (delta < 0)
-   cmd.gain[i - 1] |= 1 << 2;  /* sign bit */
+   cmd.gain[i] |= 1 << 2;  /* sign bit */
+   DPRINTF(("Setting differential gains for antenna %d: 
%x\n",
+   i, cmd.gain[i]));
}
}
-   DPRINTF(("setting differential gains: %x/%x (%x)\n",
-   cmd.gain[0], cmd.gain[1], sc->chainmask));
return iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 1);
 }
 



Re: wsfontload(8): display number of characters in a loaded font

2020-07-17 Thread Stuart Henderson
Seems useful. While it's not especially likely anyone is parsing the output 
of this, just in case they are it's usually more admin-friendly to add a 
new column at the end unless there's a good reason not to.


--
 Sent from a phone, apologies for poor formatting.
On 16 July 2020 21:29:50 Frederic Cambus  wrote:


Hi tech@,

Here is a diff to add a new column to wsfontload -l output, which
reports the number of characters contained in a loaded font.

It's especially useful with user loaded fonts as they can contain more
than 256 characters.

Below is the current output of wsfontload -l, without the diff:

# Name Encoding  W  H
0 Boldface  ibm  8 16
1 Spleen 6x12   iso  6 12
2 Spleen 8x16   iso  8 16
3 Spleen 12x24  iso 12 24
4 Spleen 16x32  iso 16 32
5 Spleen 32x64  iso 32 64

And now with the diff:

# Name EncodingChars  W  H
0 Boldface  ibm  254  8 16
1 Spleen 6x12   iso   96  6 12
2 Spleen 8x16   iso  224  8 16
3 Spleen 12x24  iso  224 12 24
4 Spleen 16x32  iso  224 16 32
5 Spleen 32x64  iso  224 32 64

Comments? OK?

Index: usr.sbin/wsfontload/wsfontload.c
===
RCS file: /cvs/src/usr.sbin/wsfontload/wsfontload.c,v
retrieving revision 1.21
diff -u -p -r1.21 wsfontload.c
--- usr.sbin/wsfontload/wsfontload.c 28 Jun 2019 13:32:51 - 1.21
+++ usr.sbin/wsfontload/wsfontload.c 16 Jul 2020 16:11:18 -
@@ -141,7 +141,8 @@ main(int argc, char *argv[])

 if (list) {
 i = 0;
- p = " # Name Encoding  W  H";
+ p = " # Name Encoding" \
+"Chars  W  H";
 do {
 f.index = i;
 res = ioctl(wsfd, WSDISPLAYIO_LSFONT, &f);
@@ -151,10 +152,11 @@ main(int argc, char *argv[])
 puts(p);
 p = NULL;
 }
- printf("%2d %-32s %8s %2d %2d\n",
+ printf("%2d %-32s %8s %8d %2d %2d\n",
f.index, f.name,
encodings[f.encoding].name,
-f.fontwidth, f.fontheight);
+f.numchars, f.fontwidth,
+f.fontheight);
 }
 }
 i++;




Avoid realloc

2020-07-17 Thread Gerhard Roth
Recently a stat(2) call was added to load_server_config() of ssh to
avoid reallocs. However, a buffer of 'st_size' length might be too
short to hold the null terminator of the string.

Add one more byte to the size, if it is sure that we can't overflow.


Gerhard



Index: usr.bin/ssh/servconf.c
===
RCS file: /cvs/src/usr.bin/ssh/servconf.c,v
retrieving revision 1.367
diff -u -p -u -p -r1.367 servconf.c
--- usr.bin/ssh/servconf.c  5 Jul 2020 23:59:45 -   1.367
+++ usr.bin/ssh/servconf.c  17 Jul 2020 09:27:08 -
@@ -2339,7 +2339,8 @@ load_server_config(const char *filename,
sshbuf_reset(conf);
/* grow buffer, so realloc is avoided for large config files */
if (fstat(fileno(f), &st) == 0 && st.st_size > 0 &&
-(r = sshbuf_allocate(conf, st.st_size)) != 0)
+   st.st_size < LONG_MAX &&
+   (r = sshbuf_allocate(conf, st.st_size + 1)) != 0)
fatal("%s: allocate failed: %s", __func__, ssh_err(r));
while (getline(&line, &linesize, f) != -1) {
lineno++;



Re: Add missing `IFXF_CLONED' to pseudo-interfaces

2020-07-17 Thread Vitaliy Makkoveev
anyone?

On Fri, Jul 10, 2020 at 02:59:55PM +0300, Vitaliy Makkoveev wrote:
> Some pseudo interfaces have missing `IFXF_CLONED' flag. Diff below fixes
> this.
> 
> Index: sys/net/if_ppp.c
> ===
> RCS file: /cvs/src/sys/net/if_ppp.c,v
> retrieving revision 1.114
> diff -u -p -r1.114 if_ppp.c
> --- sys/net/if_ppp.c  24 Jun 2020 22:03:42 -  1.114
> +++ sys/net/if_ppp.c  10 Jul 2020 11:57:39 -
> @@ -220,6 +220,7 @@ ppp_clone_create(struct if_clone *ifc, i
>   sc->sc_if.if_output = pppoutput;
>   sc->sc_if.if_start = ppp_ifstart;
>   sc->sc_if.if_rtrequest = p2p_rtrequest;
> + sc->sc_if.if_xflags = IFXF_CLONED;
>   IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN);
>   mq_init(&sc->sc_inq, IFQ_MAXLEN, IPL_NET);
>   ppp_pkt_list_init(&sc->sc_rawq, IFQ_MAXLEN);
> Index: sys/net/if_pppoe.c
> ===
> RCS file: /cvs/src/sys/net/if_pppoe.c,v
> retrieving revision 1.68
> diff -u -p -r1.68 if_pppoe.c
> --- sys/net/if_pppoe.c16 Jun 2019 00:10:37 -  1.68
> +++ sys/net/if_pppoe.c10 Jul 2020 11:57:39 -
> @@ -210,6 +210,7 @@ pppoe_clone_create(struct if_clone *ifc,
>   sc->sc_sppp.pp_if.if_ioctl = pppoe_ioctl;
>   sc->sc_sppp.pp_if.if_start = pppoe_start;
>   sc->sc_sppp.pp_if.if_rtrequest = p2p_rtrequest;
> + sc->sc_sppp.pp_if.if_xflags = IFXF_CLONED;
>   sc->sc_sppp.pp_tls = pppoe_tls;
>   sc->sc_sppp.pp_tlf = pppoe_tlf;
>   IFQ_SET_MAXLEN(&sc->sc_sppp.pp_if.if_snd, IFQ_MAXLEN);
> Index: sys/net/if_switch.c
> ===
> RCS file: /cvs/src/sys/net/if_switch.c,v
> retrieving revision 1.30
> diff -u -p -r1.30 if_switch.c
> --- sys/net/if_switch.c   6 Nov 2019 03:51:26 -   1.30
> +++ sys/net/if_switch.c   10 Jul 2020 11:57:39 -
> @@ -159,6 +159,7 @@ switch_clone_create(struct if_clone *ifc
>   ifp->if_start = NULL;
>   ifp->if_type = IFT_BRIDGE;
>   ifp->if_hdrlen = ETHER_HDR_LEN;
> + ifp->if_xflags = IFXF_CLONED;
>   TAILQ_INIT(&sc->sc_swpo_list);
>  
>   sc->sc_unit = unit;
> Index: sys/net/if_trunk.c
> ===
> RCS file: /cvs/src/sys/net/if_trunk.c,v
> retrieving revision 1.146
> diff -u -p -r1.146 if_trunk.c
> --- sys/net/if_trunk.c17 Jun 2020 06:45:22 -  1.146
> +++ sys/net/if_trunk.c10 Jul 2020 11:57:39 -
> @@ -184,6 +184,7 @@ trunk_clone_create(struct if_clone *ifc,
>   ifp->if_ioctl = trunk_ioctl;
>   ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
>   ifp->if_capabilities = trunk_capabilities(tr);
> + ifp->if_xflags = IFXF_CLONED;
>  
>   snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
>   ifc->ifc_name, unit);
> Index: sys/net/if_tun.c
> ===
> RCS file: /cvs/src/sys/net/if_tun.c,v
> retrieving revision 1.222
> diff -u -p -r1.222 if_tun.c
> --- sys/net/if_tun.c  13 May 2020 00:48:06 -  1.222
> +++ sys/net/if_tun.c  10 Jul 2020 11:57:39 -
> @@ -236,6 +236,7 @@ tun_create(struct if_clone *ifc, int uni
>   ifp->if_hardmtu = TUNMRU;
>   ifp->if_link_state = LINK_STATE_DOWN;
>   IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
> + ifp->if_xflags = IFXF_CLONED;
>  
>   if_counters_alloc(ifp);
>  
> Index: sys/net/if_vether.c
> ===
> RCS file: /cvs/src/sys/net/if_vether.c,v
> retrieving revision 1.30
> diff -u -p -r1.30 if_vether.c
> --- sys/net/if_vether.c   9 Jan 2018 15:24:24 -   1.30
> +++ sys/net/if_vether.c   10 Jul 2020 11:57:39 -
> @@ -88,6 +88,7 @@ vether_clone_create(struct if_clone *ifc
>  
>   ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN;
>   ifp->if_capabilities = IFCAP_VLAN_MTU;
> + ifp->if_xflags = IFXF_CLONED;
>  
>   ifmedia_init(&sc->sc_media, 0, vether_media_change,
>   vether_media_status);
> Index: sys/net/if_vxlan.c
> ===
> RCS file: /cvs/src/sys/net/if_vxlan.c,v
> retrieving revision 1.77
> diff -u -p -r1.77 if_vxlan.c
> --- sys/net/if_vxlan.c12 Apr 2020 11:56:52 -  1.77
> +++ sys/net/if_vxlan.c10 Jul 2020 11:57:39 -
> @@ -155,6 +155,7 @@ vxlan_clone_create(struct if_clone *ifc,
>  
>   ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN;
>   ifp->if_capabilities = IFCAP_VLAN_MTU;
> + ifp->if_xflags = IFXF_CLONED;
>  
>   ifmedia_init(&sc->sc_media, 0, vxlan_media_change,
>   vxlan_media_status);



faq/pf/carp: pfsync0 does not exist by default

2020-07-17 Thread Klemens Nanni
Without /etc/hostname.pfsync0 there will be no such interface upon boot.

Feedback? OK?

Index: faq/pf/carp.html
===
RCS file: /cvs/www/faq/pf/carp.html,v
retrieving revision 1.63
diff -u -p -r1.63 carp.html
--- faq/pf/carp.html28 May 2019 01:53:11 -  1.63
+++ faq/pf/carp.html13 Jul 2020 19:44:00 -
@@ -323,8 +323,6 @@ Since pfsync(4) is a virtual network int
 
 pfsyncN
 The name of the pfsync(4) interface.
-pfsync0 exists by default when using the GENERIC
-kernel.
 
 syncdev
 The name of the physical interface used to send pfsync updates out.



Re: random toeplitz seeds

2020-07-17 Thread David Gwynne
On Fri, Jun 26, 2020 at 07:55:43AM +0200, Theo Buehler wrote:
> This adds an stoeplitz_random_seed() function that generates a random
> Toeplitz key seed with an invertible matrix T. This is necessary and
> sufficient for the hash to spread out over all 65536 possible values.
> 
> While it is clear from T * (-1) == 0 that seeds with parity 0 are bad,
> I don't have a neat and clean proof for the fact that a seed with
> parity 1 always generates an invertible Toeplitz matrix. It's not hard
> to check, but rather tedious.
> 
> I'm unsure how to hook it up. I enabled random seeds by using the
> function in stoeplitz_init(), but that's just for illustration.

sorry, i didnt see this when you sent it out.

i can't say whether the maths is right or not, but i'm happy to trust
you on it. it's hooked up fine though, so ok by me.

dlg

> Index: sys/net/toeplitz.c
> ===
> RCS file: /var/cvs/src/sys/net/toeplitz.c,v
> retrieving revision 1.7
> diff -u -p -r1.7 toeplitz.c
> --- sys/net/toeplitz.c19 Jun 2020 08:48:15 -  1.7
> +++ sys/net/toeplitz.c25 Jun 2020 18:43:02 -
> @@ -69,9 +69,38 @@ static struct stoeplitz_cache  stoeplitz_
>  const struct stoeplitz_cache *const
>   stoeplitz_cache = &stoeplitz_syskey_cache; 
>  
> +/* parity of n16: count (mod 2) of ones in the binary representation. */
> +int
> +parity(uint16_t n16)
> +{
> + n16 = ((n16 & 0x) >> 1) ^ (n16 & 0x);
> + n16 = ((n16 & 0x) >> 2) ^ (n16 & 0x);
> + n16 = ((n16 & 0xf0f0) >> 4) ^ (n16 & 0x0f0f);
> + n16 = ((n16 & 0xff00) >> 8) ^ (n16 & 0x00ff);
> +
> + return (n16);
> +}
> +
> +/*
> + * The Toeplitz matrix obtained from a seed is invertible if and only if the
> + * parity of the seed is 1. Generate such a seed uniformly at random.
> + */
> +stoeplitz_key
> +stoeplitz_random_seed(void)
> +{
> + stoeplitz_key seed;
> +   
> + seed = arc4random() & UINT16_MAX;
> + if (parity(seed) == 0)
> + seed ^= 1;
> +
> + return (seed);
> +}
> +
>  void
>  stoeplitz_init(void)
>  {
> + stoeplitz_keyseed = stoeplitz_random_seed();
>   stoeplitz_cache_init(&stoeplitz_syskey_cache, stoeplitz_keyseed);
>  }
>  
> 



rge(4): support for Realtek RTL8125B

2020-07-17 Thread Kevin Lo
Hi,

The following diff adds Realtek RTL8125B support to rge(4) and uses
if_rxring to manage the number of filled slots on the rx ring.

Tested with the TP-LINK TL-NG421 adapter.

Index: share/man/man4/pci.4
===
RCS file: /cvs/src/share/man/man4/pci.4,v
retrieving revision 1.381
diff -u -p -u -p -r1.381 pci.4
--- share/man/man4/pci.419 Apr 2020 09:27:44 -  1.381
+++ share/man/man4/pci.417 Jul 2020 07:49:12 -
@@ -251,7 +251,7 @@ AMD PCnet-PCI 10/100 Ethernet device
 .It Xr re 4
 Realtek 8139C+/8169/816xS/811xS/8168/810xE 10/100/Gigabit Ethernet device
 .It Xr rge 4
-Realtek 8125 PCI Express 2.5Gb Ethernet device
+Realtek 8125/8125B PCI Express 2.5Gb Ethernet device
 .It Xr rl 4
 Realtek 8129/8139 10/100 Ethernet device
 .It Xr se 4
Index: share/man/man4/rge.4
===
RCS file: /cvs/src/share/man/man4/rge.4,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 rge.4
--- share/man/man4/rge.418 Nov 2019 22:09:59 -  1.2
+++ share/man/man4/rge.417 Jul 2020 07:49:12 -
@@ -1,6 +1,6 @@
 .\" $OpenBSD: rge.4,v 1.2 2019/11/18 22:09:59 jmc Exp $
 .\"
-.\" Copyright (c) 2019 Kevin Lo 
+.\" Copyright (c) 2019, 2020 Kevin Lo 
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
 .\" purpose with or without fee is hereby granted, provided that the above
@@ -19,18 +19,19 @@
 .Os
 .Sh NAME
 .Nm rge
-.Nd Realtek 8125 PCI Express 2.5Gb Ethernet device
+.Nd Realtek 8125/8125B PCI Express 2.5Gb Ethernet device
 .Sh SYNOPSIS
 .Cd "rge* at pci?"
 .Sh DESCRIPTION
 The
 .Nm
 driver provides support for PCI Express 2.5Gb Ethernet adapters based
-on the Realtek RTL8125 Ethernet controller, including the following:
+on the Realtek RTL8125 and RTL8125B Ethernet controllers,
+including the following:
 .Pp
 .Bl -bullet -offset indent -compact
 .It
-Realtek RTL8125 2.5GbE Adapter (2500baseT)
+Realtek 8125/8125B 2.5GbE Adapter (2500baseT)
 .It
 Rivet Networks Killer E3000 Adapter (2500baseT)
 .El
Index: sys/dev/pci/if_rge.c
===
RCS file: /cvs/src/sys/dev/pci/if_rge.c,v
retrieving revision 1.4
diff -u -p -u -p -r1.4 if_rge.c
--- sys/dev/pci/if_rge.c10 Jul 2020 13:26:38 -  1.4
+++ sys/dev/pci/if_rge.c17 Jul 2020 07:49:13 -
@@ -1,7 +1,7 @@
 /* $OpenBSD: if_rge.c,v 1.4 2020/07/10 13:26:38 patrick Exp $  */
 
 /*
- * Copyright (c) 2019 Kevin Lo 
+ * Copyright (c) 2019, 2020 Kevin Lo 
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -50,6 +50,13 @@
 
 #include 
 
+#ifdef RGE_DEBUG
+#define DPRINTF(x) do { if (rge_debug > 0) printf x; } while (0)
+int rge_debug = 0;
+#else
+#define DPRINTF(x)
+#endif
+
 intrge_match(struct device *, void *, void *);
 void   rge_attach(struct device *, struct device *, void *);
 intrge_intr(void *);
@@ -62,16 +69,22 @@ voidrge_stop(struct ifnet *);
 intrge_ifmedia_upd(struct ifnet *);
 void   rge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
 intrge_allocmem(struct rge_softc *);
-intrge_newbuf(struct rge_softc *, int);
+intrge_newbuf(struct rge_softc *);
 void   rge_discard_rxbuf(struct rge_softc *, int);
-intrge_rx_list_init(struct rge_softc *);
+void   rge_rx_list_init(struct rge_softc *);
 void   rge_tx_list_init(struct rge_softc *);
+void   rge_fill_rx_ring(struct rge_softc *);
 intrge_rxeof(struct rge_softc *);
 intrge_txeof(struct rge_softc *);
 void   rge_reset(struct rge_softc *);
 void   rge_iff(struct rge_softc *);
 void   rge_set_phy_power(struct rge_softc *, int);
 void   rge_phy_config(struct rge_softc *);
+void   rge_phy_config_mac_cfg2(struct rge_softc *);
+void   rge_phy_config_mac_cfg3(struct rge_softc *);
+void   rge_phy_config_mac_cfg4(struct rge_softc *);
+void   rge_phy_config_mac_cfg5(struct rge_softc *);
+void   rge_phy_config_mcu(struct rge_softc *, uint16_t);
 void   rge_set_macaddr(struct rge_softc *, const uint8_t *);
 void   rge_get_macaddr(struct rge_softc *, uint8_t *);
 void   rge_hw_init(struct rge_softc *);
@@ -79,6 +92,7 @@ void  rge_disable_phy_ocp_pwrsave(struct
 void   rge_patch_phy_mcu(struct rge_softc *, int);
 void   rge_add_media_types(struct rge_softc *);
 void   rge_config_imtype(struct rge_softc *, int);
+void   rge_disable_hw_im(struct rge_softc *);
 void   rge_disable_sim_im(struct rge_softc *);
 void   rge_setup_sim_im(struct rge_softc *);
 void   rge_setup_intr(struct rge_softc *, int);
@@ -88,6 +102,7 @@ uint32_t rge_read_csi(st