kqueue_scan() should not return EWOULDBLOCK
This fixes a recent regression in kqueue_scan() where the function can mistakenly return EWOULDBLOCK. Currently, kqueue_scan() does one more scan attempt after a timeout. Usually, this gives no new events and the function bails out through the following code. Note that it clears `error'. if (kq->kq_count == 0) { /* * Successive loops are only necessary if there are more * ready events to gather, so they don't need to block. */ if ((tsp != NULL && !timespecisset(tsp)) || scan->kqs_nevent != 0) { splx(s); error = 0; goto done; } However, there can be a last-minute event activation, in which case the function processes the event queue. Unfortunately, the error variable preserves its value EWOULDBLOCK/EAGAIN that gets returned to the caller. kevent(2), or select(2) or poll(2), is not supposed to return this error. The issue emerged in r1.146 of kern_event.c when the final copyout() was moved outside kqueue_scan(). The copyout()'s return value used to override the EWOULDBLOCK. The following patch fixes the regression by clearing `error' at the start of each scan round. The clearing could be done conditionally after kqueue_sleep(). However, that does not seem as robust. OK? Index: kern/kern_event.c === RCS file: src/sys/kern/kern_event.c,v retrieving revision 1.153 diff -u -p -r1.153 kern_event.c --- kern/kern_event.c 20 Dec 2020 12:54:05 - 1.153 +++ kern/kern_event.c 23 Dec 2020 07:10:24 - @@ -977,6 +977,8 @@ kqueue_scan(struct kqueue_scan_state *sc retry: KASSERT(nkev == 0); + error = 0; + if (kq->kq_state & KQ_DYING) { error = EBADF; goto done;
Wake on LAN support for rge(4)
Hi, This diff implements WoL support in rge(4). I can wakeup the machine with WoL after suspending it through `zzz` or powering off it through `halt -p`. Index: share/man/man4/rge.4 === RCS file: /cvs/src/share/man/man4/rge.4,v retrieving revision 1.4 diff -u -p -u -p -r1.4 rge.4 --- share/man/man4/rge.412 Oct 2020 02:11:10 - 1.4 +++ share/man/man4/rge.423 Dec 2020 04:33:26 - @@ -37,6 +37,15 @@ Rivet Networks Killer E3000 Adapter (250 .It TP-LINK TL-NG421 Adapter (2500baseT) .El +.Pp +The +.Nm +driver additionally supports Wake on LAN (WoL). +See +.Xr arp 8 +and +.Xr ifconfig 8 +for more details. .Sh SEE ALSO .Xr arp 4 , .Xr ifmedia 4 , Index: sys/dev/pci/if_rge.c === RCS file: /cvs/src/sys/dev/pci/if_rge.c,v retrieving revision 1.9 diff -u -p -u -p -r1.9 if_rge.c --- sys/dev/pci/if_rge.c12 Dec 2020 11:48:53 - 1.9 +++ sys/dev/pci/if_rge.c23 Dec 2020 04:33:27 - @@ -59,6 +59,7 @@ int rge_debug = 0; intrge_match(struct device *, void *, void *); void rge_attach(struct device *, struct device *, void *); +intrge_activate(struct device *, int); intrge_intr(void *); intrge_encap(struct rge_softc *, struct mbuf *, int); intrge_ioctl(struct ifnet *, u_long, caddr_t); @@ -111,6 +112,10 @@ intrge_get_link_status(struct rge_soft void rge_txstart(void *); void rge_tick(void *); void rge_link_state(struct rge_softc *); +#ifndef SMALL_KERNEL +intrge_wol(struct ifnet *, int); +void rge_wol_power(struct rge_softc *); +#endif static const struct { uint16_t reg; @@ -126,7 +131,7 @@ static const struct { }; struct cfattach rge_ca = { - sizeof(struct rge_softc), rge_match, rge_attach + sizeof(struct rge_softc), rge_match, rge_attach, NULL, rge_activate }; struct cfdriver rge_cd = { @@ -272,6 +277,11 @@ rge_attach(struct device *parent, struct ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; #endif +#ifndef SMALL_KERNEL + ifp->if_capabilities |= IFCAP_WOL; + ifp->if_wol = rge_wol; + rge_wol(ifp, 0); +#endif timeout_set(>sc_timeout, rge_tick, sc); task_set(>sc_task, rge_txstart, sc); @@ -288,6 +298,25 @@ rge_attach(struct device *parent, struct } int +rge_activate(struct device *self, int act) +{ + struct rge_softc *sc = (struct rge_softc *)self; + int rv = 0; + + switch (act) { + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); +#ifndef SMALL_KERNEL + rge_wol_power(sc); +#endif + default: + rv = config_activate_children(self, act); + break; + } + return (rv); +} + +int rge_intr(void *arg) { struct rge_softc *sc = arg; @@ -2025,6 +2054,7 @@ rge_hw_init(struct rge_softc *sc) /* Set PCIe uncorrectable error status. */ rge_write_csi(sc, 0x108, rge_read_csi(sc, 0x108) | 0x0010); + } void @@ -2391,3 +2421,48 @@ rge_link_state(struct rge_softc *sc) if_link_state_change(ifp); } } + +#ifndef SMALL_KERNEL +int +rge_wol(struct ifnet *ifp, int enable) +{ + struct rge_softc *sc = ifp->if_softc; + + if (enable) { + if (!(RGE_READ_1(sc, RGE_CFG1) & RGE_CFG1_PM_EN)) { + printf("%s: power management is disabled, " + "cannot do WOL\n", sc->sc_dev.dv_xname); + return (ENOTSUP); + } + + } + + rge_iff(sc); + + if (enable) + RGE_MAC_SETBIT(sc, 0xc0b6, 0x0001); + else + RGE_MAC_CLRBIT(sc, 0xc0b6, 0x0001); + + RGE_SETBIT_1(sc, RGE_EECMD, RGE_EECMD_WRITECFG); + RGE_CLRBIT_1(sc, RGE_CFG5, RGE_CFG5_WOL_LANWAKE | RGE_CFG5_WOL_UCAST | + RGE_CFG5_WOL_MCAST | RGE_CFG5_WOL_BCAST); + RGE_CLRBIT_1(sc, RGE_CFG3, RGE_CFG3_WOL_LINK | RGE_CFG3_WOL_MAGIC); + if (enable) + RGE_SETBIT_1(sc, RGE_CFG5, RGE_CFG5_WOL_LANWAKE); + RGE_CLRBIT_1(sc, RGE_EECMD, RGE_EECMD_WRITECFG); + + return (0); +} + +void +rge_wol_power(struct rge_softc *sc) +{ + /* Disable RXDV gate. */ + RGE_CLRBIT_1(sc, RGE_PPSW, 0x08); + DELAY(2000); + + RGE_SETBIT_1(sc, RGE_CFG1, RGE_CFG1_PM_EN); + RGE_SETBIT_1(sc, RGE_CFG2, RGE_CFG2_PMSTS_EN); +} +#endif Index: sys/dev/pci/if_rgereg.h === RCS file: /cvs/src/sys/dev/pci/if_rgereg.h,v retrieving revision 1.5 diff -u -p -u -p -r1.5 if_rgereg.h --- sys/dev/pci/if_rgereg.h 22 Nov 2020 14:06:22 - 1.5 +++ sys/dev/pci/if_rgereg.h 23 Dec 2020 04:33:27 - @@ -111,16 +111,24 @@ #define RGE_EECMD_WRITECFG 0xc0 /* Flags for
Re: uvmexp & per-CPU counters
> Date: Mon, 21 Dec 2020 16:46:32 -0300 > From: Martin Pieuchot > > During a page fault multiples counters are updated. They fall into two > categories "fault counters" and "global statistics" both of which are > currently represented by int-sized fields inside a global: `uvmexp'. > > Diff below makes use of the per-CPU counters_inc(9) API to make sure no > update is lost with an unlocked fault handler. I only converted the > fields touched by uvm_fault() to have a working solution and start a > discussion. > > - Should we keep a single enum for all fields inside `uvmexp' or do we > want to separate "statistics counters" which are mostly used sys/arch > from "fault counters" which are only used in uvm/uvm_fault.c? > > - The counter_add(9) API deals with uint64_t and currently uvmexp uses > int. Should we truncate or change the size of uvmexp fields or do > something else? > > Comments? I think this breaks "show uvmexp" in ddb. You fear that using atomic operations for these counters would lead to too much bus contention on systems with a large number of CPUs? > Index: kern/init_main.c > === > RCS file: /cvs/src/sys/kern/init_main.c,v > retrieving revision 1.302 > diff -u -p -r1.302 init_main.c > --- kern/init_main.c 7 Dec 2020 16:55:28 - 1.302 > +++ kern/init_main.c 21 Dec 2020 19:37:13 - > @@ -432,6 +432,7 @@ main(void *framep) > #endif > > mbcpuinit();/* enable per cpu mbuf data */ > + uvm_init_percpu(); > > /* init exec and emul */ > init_exec(); > Index: uvm/uvm_extern.h > === > RCS file: /cvs/src/sys/uvm/uvm_extern.h,v > retrieving revision 1.155 > diff -u -p -r1.155 uvm_extern.h > --- uvm/uvm_extern.h 1 Dec 2020 13:56:22 - 1.155 > +++ uvm/uvm_extern.h 21 Dec 2020 19:37:13 - > @@ -289,6 +289,7 @@ void uvm_vsunlock_device(struct proc > * > void *); > void uvm_pause(void); > void uvm_init(void); > +void uvm_init_percpu(void); > int uvm_io(vm_map_t, struct uio *, int); > > #define UVM_IO_FIXPROT 0x01 > Index: uvm/uvm_fault.c > === > RCS file: /cvs/src/sys/uvm/uvm_fault.c,v > retrieving revision 1.109 > diff -u -p -r1.109 uvm_fault.c > --- uvm/uvm_fault.c 8 Dec 2020 12:26:31 - 1.109 > +++ uvm/uvm_fault.c 21 Dec 2020 19:37:13 - > @@ -35,6 +35,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -271,7 +272,7 @@ uvmfault_anonget(struct uvm_faultinfo *u > int result; > > result = 0; /* XXX shut up gcc */ > - uvmexp.fltanget++; > + counters_inc(uvmexp_counters, flt_anget); > /* bump rusage counters */ > if (anon->an_page) > curproc->p_ru.ru_minflt++; > @@ -295,7 +296,7 @@ uvmfault_anonget(struct uvm_faultinfo *u > if ((pg->pg_flags & (PG_BUSY|PG_RELEASED)) == 0) > return (VM_PAGER_OK); > atomic_setbits_int(>pg_flags, PG_WANTED); > - uvmexp.fltpgwait++; > + counters_inc(uvmexp_counters, flt_pgwait); > > /* >* the last unlock must be an atomic unlock+wait on > @@ -310,7 +311,7 @@ uvmfault_anonget(struct uvm_faultinfo *u > > if (pg == NULL) { /* out of RAM. */ > uvmfault_unlockall(ufi, amap, NULL); > - uvmexp.fltnoram++; > + counters_inc(uvmexp_counters, flt_noram); > uvm_wait("flt_noram1"); > /* ready to relock and try again */ > } else { > @@ -325,7 +326,7 @@ uvmfault_anonget(struct uvm_faultinfo *u >* it is ok to read an_swslot here because >* we hold PG_BUSY on the page. >*/ > - uvmexp.pageins++; > + counters_inc(uvmexp_counters, pageins); > result = uvm_swap_get(pg, anon->an_swslot, > PGO_SYNCIO); > > @@ -369,7 +370,7 @@ uvmfault_anonget(struct uvm_faultinfo *u > uvm_anfree(anon); /* frees page for us */ > if (locked) > uvmfault_unlockall(ufi, amap, NULL); > - uvmexp.fltpgrele++; > + counters_inc(uvmexp_counters, flt_pgrele); > return (VM_PAGER_REFAULT); /* refault! */ > } > > @@ -426,7 +427,7 @@
Re: xhci zero length transfers 'leak' one transfer buffer count
> > Did you consider incrementing xx->ntrb instead? >That doesn't work either, because the status completion code needs >xx->ntrb to be correct for the data TD to be handled correctly. >Incrementing xx->ntrb means the number of TRBs for the data TD is >incorrect, since it includes the (optional) zero TD's TRB. > >In this case the zero TD allocates a TRB but doesn't do proper >accounting, and currently there's no place where this could be >accounted properly. > >In the end it's all software, so I guess the diff will simply have >to be bigger than just a one-liner. > > With the diff below the produced TRB isn't accounted which might > > lead > > to and off-by-one. Sorry, I missed this thread and had to re-grab the last mail from MARC. Can't we just take account of the zero trb separately? Index: dev/usb/xhci.c === RCS file: /cvs/src/sys/dev/usb/xhci.c,v retrieving revision 1.119 diff -u -p -u -p -r1.119 xhci.c --- dev/usb/xhci.c 31 Jul 2020 19:27:57 - 1.119 +++ dev/usb/xhci.c 22 Dec 2020 19:41:01 - @@ -1135,6 +1135,7 @@ xhci_xfer_done(struct usbd_xfer *xfer) i = (xp->ring.ntrb - 1); } xp->free_trbs += xx->ntrb; + xp->free_trbs += xx->zerotrb; xx->index = -1; xx->ntrb = 0; @@ -1842,6 +1843,7 @@ xhci_xfer_get_trb(struct xhci_softc *sc, switch (last) { case -1:/* This will be a zero-length TD. */ xp->pending_xfers[xp->ring.index] = NULL; + xx->zerotrb = 1; /* There can only be one zero TRB per xfer. */ break; case 0: /* This will be in a chain. */ xp->pending_xfers[xp->ring.index] = xfer; Index: dev/usb/xhcivar.h === RCS file: /cvs/src/sys/dev/usb/xhcivar.h,v retrieving revision 1.11 diff -u -p -u -p -r1.11 xhcivar.h --- dev/usb/xhcivar.h 6 Oct 2019 17:30:00 - 1.11 +++ dev/usb/xhcivar.h 22 Dec 2020 19:41:01 - @@ -40,6 +40,7 @@ struct xhci_xfer { struct usbd_xfer xfer; int index; /* Index of the last TRB */ size_t ntrb; /* Number of associated TRBs */ + size_t zerotrb; /* Is zero len TRB required? */ }; struct xhci_ring {
Re: Wireguard - VPN up after reboot
On Tue, 22 Dec 2020 09:50:04 + "Salvatore Cuzzilla" : > Hi Everyone, > > I'm happily using 'Wireguard' to setup few VPNs. > I store the required configuration within /etc/hostname.wg0 & I startup the > tunnel with 'doas sh > /etc/netstart wg0'. > > Everything is working like expected. > However, upon system reload the connectivity is lost. > The wg0 interface comes up but the tunnel stays in a sort of 'waiting' > state. > > The only way I figure out to bring it up is either re-launching 'doas sh > /etc/netstart wg0' or > pinging the tunnel default gateway. > > Is there any decent/clean way to avoid manual intervention? > > --- > :wq, > Salvatore. > I had the same issue, you must avoid using hostname for the remote address of the wireguard peer, because at this stage you can't resolve hostnames.
Re: Force knote state update in klist_invalidate()
On Mon, Dec 21, 2020 at 04:51:45PM -0300, Martin Pieuchot wrote: > On 21/12/20(Mon) 16:45, Visa Hankala wrote: > > There is a slight inconsistency in klist_invalidate(). If the knote is > > already in the event queue and has flag EV_ONESHOT, kqueue_scan() will > > not invoke the newly set f_event. In this case, the kevent(2) system > > call will return the knote's original event state that no longer > > reflects the state that is reachable through the file descriptor > > (the caller of klist_invalidate() has already revoked access to the > > file or device). > > I don't understand the problem. Why should filt_dead() be called? Is > it a race between two threads? Would you mind giving a scenario or some > code example? klist_invalidate() often is asynchronous relative to the thread that registered the knote, so yes, sort of a race is involved. filt_dead() sets the knote's event flags and data. Without the added call, filt_dead() might not be invoked and the knote's fields may retain old state that then gets reported to the caller of kqueue_scan(). In fact, this applies to any knote that has EV_ONESHOT set because the scan loop skips f_event when the flag is present. The kn->kn_fop->f_event(kn, 0) followed by knote_activate(kn) is actually similar to activation through knote(). > > > I think a proper fix is to invoke f_event manually to force the state > > update. > > > > OK? > > > > Index: kern/kern_event.c > > === > > RCS file: src/sys/kern/kern_event.c,v > > retrieving revision 1.153 > > diff -u -p -r1.153 kern_event.c > > --- kern/kern_event.c 20 Dec 2020 12:54:05 - 1.153 > > +++ kern/kern_event.c 21 Dec 2020 16:19:30 - > > @@ -1618,6 +1618,7 @@ klist_invalidate(struct klist *list) > > kn->kn_fop->f_detach(kn); > > if (kn->kn_fop->f_flags & FILTEROP_ISFD) { > > kn->kn_fop = _filtops; > > + kn->kn_fop->f_event(kn, 0); > > knote_activate(kn); > > s = splhigh(); > > knote_release(kn); > > >
Re: [diff] usr.sbin/smtpd: fix event handling upon exit
OK millert@ - todd
Re: Wireguard - VPN up after reboot
AFAIK, rc(8) should run netstart on boot. This is executed at /etc/rc:447. Can you post the contents of /etc/hostname.wg0 (of course redacting sensitive fields) ? Olivia On 22 December 2020 09:50:04 GMT, Salvatore Cuzzilla wrote: >Hi Everyone, > >I'm happily using 'Wireguard' to setup few VPNs. >I store the required configuration within /etc/hostname.wg0 & I startup the >tunnel with 'doas sh >/etc/netstart wg0'. > >Everything is working like expected. >However, upon system reload the connectivity is lost. >The wg0 interface comes up but the tunnel stays in a sort of 'waiting' >state. > >The only way I figure out to bring it up is either re-launching 'doas sh >/etc/netstart wg0' or >pinging the tunnel default gateway. > >Is there any decent/clean way to avoid manual intervention? > >--- >:wq, >Salvatore. > -- Sent from my Android device with K-9 Mail. Please excuse my brevity.
Re: IPv6 pf_test EACCES
On Mon, Dec 21, 2020 at 11:34:04PM +0100, Alexander Bluhm wrote: > Hi, > > A while ago we decided to pass EACCES to uerland if pf blocks a > packet. IPv6 still has the old EHOSTUNREACH code. > > Use the same errno for dropped IPv6 packets as in IPv4. > > ok? > looks good to me. OK sashan
Wireguard - VPN up after reboot
Hi Everyone, I'm happily using 'Wireguard' to setup few VPNs. I store the required configuration within /etc/hostname.wg0 & I startup the tunnel with 'doas sh /etc/netstart wg0'. Everything is working like expected. However, upon system reload the connectivity is lost. The wg0 interface comes up but the tunnel stays in a sort of 'waiting' state. The only way I figure out to bring it up is either re-launching 'doas sh /etc/netstart wg0' or pinging the tunnel default gateway. Is there any decent/clean way to avoid manual intervention? --- :wq, Salvatore.
Re: IPv6 pf_test EACCES
Yes please. OK florian On 21 December 2020 23:34:04 CET, Alexander Bluhm wrote: >Hi, > >A while ago we decided to pass EACCES to uerland if pf blocks a >packet. IPv6 still has the old EHOSTUNREACH code. > >Use the same errno for dropped IPv6 packets as in IPv4. > >ok? > >bluhm > >Index: netinet6/ip6_output.c >=== >RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v >retrieving revision 1.247 >diff -u -p -r1.247 ip6_output.c >--- netinet6/ip6_output.c 17 Jul 2020 15:21:36 - 1.247 >+++ netinet6/ip6_output.c 21 Dec 2020 22:27:24 - >@@ -616,7 +616,7 @@ reroute: > > #if NPF > 0 > if (pf_test(AF_INET6, PF_OUT, ifp, ) != PF_PASS) { >- error = EHOSTUNREACH; >+ error = EACCES; > m_freem(m); > goto done; > } >@@ -2773,7 +2773,7 @@ ip6_output_ipsec_send(struct tdb *tdb, s > if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL || > pf_test(AF_INET6, fwd ? PF_FWD : PF_OUT, encif, ) != PF_PASS) { > m_freem(m); >- return EHOSTUNREACH; >+ return EACCES; > } > if (m == NULL) > return 0; -- Sent from a mobile device. Please excuse poor formating.