Re: fread optimization
+#define MINIMUM(a, b) (((a) (b)) ? (a) : (b)) you don't want to use the MIN from sys/param.h? many files in libc already do. (though admittedly fvwrite.c defines its own, but that seems like a bug.) I guess you haven't observed the commits of the last week... I am certain you know sys/param.h creates much namespace pollution on all systems. This is largely unavoidable since this is a poorly specified legacy header. Recently I went through efforts to limit the pollution, and to limit pulling in the pollution. The base system now uses POSIX limits.h rather than sys/param.h, wherever possible. Simultaneously, sys/param.h has been wittled down to not expose many symbols which are CSRGisms or only used by _KERNEL code. sys/param.h is still fully supported and usable, but the base is completely refactored to use the better practice (for cleanliness, but also as a demonstration of good practice moving forward). So in the base, only 185 includes of sys/param.h exist. This is to support uses of the following by programs in the base: 1 ALIGNBYTES 1 ALIGNED_POINTER 1 MID_MACHINE(our own infection...) 1 NOFILE_MAX 2 BSD 2 PAGE_SHIFT 2 PZERO 3 MACHINE_ARCH (our own infection...) 3 isclr 4 MACHINE(our own infection...) 4 clrbit 4 powerof2 5 dbtob 7 btodb 8 NODEV 11 ALIGN 11 setbit 12 MAX 12 isset 13 nitems (our own infection...) 14 MIN 22 MAXCOMLEN 23 roundup 28 MAXBSIZE 38 DEV_BSIZE The inclusion of sys/param.h via netdb.h and arpa/nameser.h has been terminated, and the ports tree was repaired (simpler than originally thought. 10 programs?) The most scary impact is that BSD will no longer be defined in some enviroments which picked it up via netdb.h or arpa/nameser.h, so we'll have to keep an eye out for such failures. Finally, this brings us back to MIN() and MAX(), in your original question. There were quite a few uses of this. To avoid the namespace poisoning I replaced all uses with local #define's of MINIMUM() and MAXIMUM(), and will revisit looking for other solutions later...
Re: fread optimization
On Wed, Jan 21, 2015 at 5:42 PM, enh e...@google.com wrote: On Wed, Jan 21, 2015 at 3:04 AM, Martin Pieuchot mpieuc...@nolizard.org wrote: Hello Elliott, On 20/01/15(Tue) 16:15, enh wrote: that patch wasn't setting the _flags right on error or eof. Thanks! Below is a version of your diff with some tweaks to match the recent changes done in -current. In your original post you've shown some test numbers. Does it mean that you have a test program for fread(3)? If so do you think it would fit as test in OpenBSD's regress framework? we have over a thousand C library tests and a small number of benchmarks in bionic/tests and bionic/benchmarks in the Android tree, all BSD-licensed. (though this only amounts to 42% coverage.) I'd suggest you to check the setup of your mail client, apparently it eats all the tabs and makes impossible to apply your diffs correctly :) afaik, there's nothing to can do to stop gmail eating tabs. Check out devio.us if you need a shell account, to send diffs to OpenBSD. Index: fread.c === RCS file: /home/ncvs/src/lib/libc/stdio/fread.c,v retrieving revision 1.13 diff -u -p -r1.13 fread.c --- fread.c 8 Dec 2014 20:40:53 - 1.13 +++ fread.c 21 Jan 2015 10:54:56 - @@ -37,18 +37,19 @@ #include errno.h #include local.h +#define MINIMUM(a, b) (((a) (b)) ? (a) : (b)) you don't want to use the MIN from sys/param.h? many files in libc already do. (though admittedly fvwrite.c defines its own, but that seems like a bug.) #define MUL_NO_OVERFLOW(1UL (sizeof(size_t) * 4)) size_t fread(void *buf, size_t size, size_t count, FILE *fp) { - size_t resid; - char *p; - int r; + size_t desired_total; size_t total; + char *dst; /* -* Extension: Catch integer overflow +* Extension: Catch integer overflow. */ if ((size = MUL_NO_OVERFLOW || count = MUL_NO_OVERFLOW) size 0 SIZE_MAX / size count) { @@ -57,47 +58,79 @@ fread(void *buf, size_t size, size_t cou return (0); } + desired_total = count * size; + total = desired_total; + /* * ANSI and SUSv2 require a return value of 0 if size or count are 0. */ - if ((resid = count * size) == 0) + if (total == 0) return (0); + FLOCKFILE(fp); _SET_ORIENTATION(fp, -1); + + /* XXX: how can this ever happen?! */ if (fp-_r 0) fp-_r = 0; - total = resid; - p = buf; - if ((fp-_flags __SNBF) != 0) { + + /* +* Ensure _bf._size is valid. +*/ + if (fp-_bf._base == NULL) + __smakebuf(fp); + + dst = buf; + + while (total 0) { /* -* We know if we're unbuffered that our buffer is empty, so -* we can just read directly. This is much faster than the -* loop below which will perform a series of one byte reads. +* Copy data out of the buffer. */ - while (resid 0 (r = (*fp-_read)(fp-_cookie, p, resid)) 0) { - p += r; - resid -= r; - } - FUNLOCKFILE(fp); - return ((total - resid) / size); + size_t buffered_bytes = MINIMUM(fp-_r, total); + + memcpy(dst, fp-_p, buffered_bytes); + fp-_p += buffered_bytes; + fp-_r -= buffered_bytes; + dst += buffered_bytes; + total -= buffered_bytes; + + /* +* Are we done? +*/ + if (total == 0) + goto out; + + /* +* Do we have so much more to read that we should +* avoid copying it through the buffer? +*/ + if (total (size_t) fp-_bf._size) + break; + + /* +* Less than a buffer to go, so refill the buffer and +* go around the loop again. +*/ + if (__srefill(fp)) + goto out; } - while (resid (r = fp-_r)) { - (void)memcpy((void *)p, (void *)fp-_p, (size_t)r); - fp-_p += r; - /* fp-_r = 0 ... done in __srefill */ - p += r; - resid -= r; - if (__srefill(fp)) { - /* no more input: return partial result */ - FUNLOCKFILE(fp); - return ((total - resid) / size); + /* +* Read directly into the caller's buffer. +*/ + while (total 0) { + ssize_t bytes_read =
Re: fread optimization
On Wed, Jan 21, 2015 at 12:04, Martin Pieuchot wrote: Hello Elliott, On 20/01/15(Tue) 16:15, enh wrote: that patch wasn't setting the _flags right on error or eof. Thanks! Below is a version of your diff with some tweaks to match the recent changes done in -current. fwiw, I think this is a good diff, but maybe for 5.8 and not 5.7. It will take a while for me to be certain this is functionally equivalent.
if_media.c: #include net/if_var.h
Hi, if_media.c needs net/if_var.h. This fixes the build with IFMEDIA_DEBUG. Regards, Fabian Index: sys/net/if_media.c === RCS file: /cvs/src/sys/net/if_media.c,v retrieving revision 1.24 diff -u -p -r1.24 if_media.c --- sys/net/if_media.c 9 Dec 2014 07:05:06 - 1.24 +++ sys/net/if_media.c 21 Jan 2015 22:18:29 - @@ -84,6 +84,7 @@ #include sys/malloc.h #include net/if.h +#include net/if_var.h #include net/if_media.h #include net/netisr.h
mail(1) -r argument with mailbox
This makes mail(1) reject -r when not sending a message as it already does for -s, -c, and -b. I was going to write a patch to take -r with a mailbox but realized I could set from interactively so nobody would want that. -- Martin Index: main.c === RCS file: /cvs/src/usr.bin/mail/main.c,v retrieving revision 1.28 diff -u -p -r1.28 main.c --- main.c 20 Jan 2015 16:59:07 - 1.28 +++ main.c 21 Jan 2015 22:57:51 - @@ -185,8 +185,10 @@ main(int argc, char **argv) /* * Check for inconsistent arguments. */ - if (to == NULL (subject != NULL || cc != NULL || bcc != NULL)) - errx(1, You must specify direct recipients with -s, -c, or -b); + if (to == NULL (subject != NULL || cc != NULL || bcc != NULL || + fromaddr != NULL)) + errx(1, You must specify direct recipients with -s, -c, -b, + or -r); /* * Block SIGINT except where we install an explicit handler for it. */
Re: enable jumbos on newer re(4) devices
On 21 Jan 2015, at 23:49, Brad Smith b...@comstyle.com wrote: On 01/21/15 06:51, Jim Smith wrote: hi all, the below diff enables support for jumbo frames on some newer re(4) devices. i've tested it on 8186D/8111D and 8186E/8111E chips, which are both able to do 9k jumbos. it seems to provide a significant speed-up on simple file transfer tests. most of the important parts were taken from the freebsd re(4) driver. feedback welcome, hope this helps someone. I had started looking into adding support for jumbos to re(4) but what I have so far does not work; no crashing but the interface does not receive any packets. What you posted still needs some work. I'll see if I can get back to it soon-ish but I have put it aside as it was not intended to be a priority for the next release. thats not very constructive feedback, especially if you dont have to time to tweak the code. if you could explain what needs work, maybe jim could have a go at it. he's already spent the time to get it this far, and he said feedback is welcome. dlg
Re: Fewer malloc() memcpy() in USB land
On Fri, Jan 9, 2015 at 2:07 PM, Martin Pieuchot mpieuc...@nolizard.org wrote: On 09/01/15(Fri) 12:36, David Higgs wrote: On Fri, Jan 9, 2015 at 9:00 AM, Martin Pieuchot mpieuc...@nolizard.org wrote: As pointed out by David Higgs, uhidev report functions do a lot of memory allocations and copies between buffers. This is not uncommon in USB land due to way DMA buffers are handled. One way to reduce the number of copies is to submit a transfer with the USBD_NO_COPY flag. Without it the kernel does two to three copies: (stack/driver array --) malloc'ed array -- DMA reacheable array This is not limited to uhidev functions. That's also done for every transfer sent through an interrupt pipe or for every control request with data. I'd like to slowly change the stack such that USBD_NO_COPY becomes the default behavior. This would first reduces the number of buffer copies and then allow umass(4) to directly use the DMA reachable buffers provided by the SCSI stack, which should *at least* reduce the CPU usage when using USB drives. Here's a diff about uhidev(4) to illustrate the changes I'm talking about. Comments, ok? See inline. Reviewed to the best of my ability/eyesight via variable-width webmail. [...] + + if (id 0) + len++; + + buf = usbd_alloc_buffer(xfer, len); + if (buf == NULL) + return (-1); You forgot to free xfer in this error path. Indeed! @@ -586,6 +585,7 @@ usbd_status usbd_clear_endpoint_stall_async(struct usbd_pipe *pipe) { struct usbd_device *dev = pipe-device; + struct usbd_xfer *xfer; usb_device_request_t req; usbd_status err; @@ -596,7 +596,12 @@ usbd_clear_endpoint_stall_async(struct u USETW(req.wValue, UF_ENDPOINT_HALT); USETW(req.wIndex, pipe-endpoint-edesc-bEndpointAddress); USETW(req.wLength, 0); - err = usbd_do_request_async(dev, req, 0, 0, 0); + + xfer = usbd_alloc_xfer(dev); + if (xfer == NULL) + return (USBD_NOMEM); + + err = usbd_request_async(xfer, req, NULL, NULL); Missing xfer cleanup here too, I think. Here it's fine, as soon as you call usbd_request_async() the xfer will be freed. Updated diff below. The updated diff appears to works for me and I don't see any further issues upon review. No behavior changes when applied to a snapshot + HEAD kernel as of this evening. Tested via repeated sysctl reads of upd(4) sensor info and a few device detach/attach events. --david
Re: fread optimization
Hello Elliott, On 20/01/15(Tue) 16:15, enh wrote: that patch wasn't setting the _flags right on error or eof. Thanks! Below is a version of your diff with some tweaks to match the recent changes done in -current. In your original post you've shown some test numbers. Does it mean that you have a test program for fread(3)? If so do you think it would fit as test in OpenBSD's regress framework? I'd suggest you to check the setup of your mail client, apparently it eats all the tabs and makes impossible to apply your diffs correctly :) Index: fread.c === RCS file: /home/ncvs/src/lib/libc/stdio/fread.c,v retrieving revision 1.13 diff -u -p -r1.13 fread.c --- fread.c 8 Dec 2014 20:40:53 - 1.13 +++ fread.c 21 Jan 2015 10:54:56 - @@ -37,18 +37,19 @@ #include errno.h #include local.h +#define MINIMUM(a, b) (((a) (b)) ? (a) : (b)) + #define MUL_NO_OVERFLOW(1UL (sizeof(size_t) * 4)) size_t fread(void *buf, size_t size, size_t count, FILE *fp) { - size_t resid; - char *p; - int r; + size_t desired_total; size_t total; + char *dst; /* -* Extension: Catch integer overflow +* Extension: Catch integer overflow. */ if ((size = MUL_NO_OVERFLOW || count = MUL_NO_OVERFLOW) size 0 SIZE_MAX / size count) { @@ -57,47 +58,79 @@ fread(void *buf, size_t size, size_t cou return (0); } + desired_total = count * size; + total = desired_total; + /* * ANSI and SUSv2 require a return value of 0 if size or count are 0. */ - if ((resid = count * size) == 0) + if (total == 0) return (0); + FLOCKFILE(fp); _SET_ORIENTATION(fp, -1); + + /* XXX: how can this ever happen?! */ if (fp-_r 0) fp-_r = 0; - total = resid; - p = buf; - if ((fp-_flags __SNBF) != 0) { + + /* +* Ensure _bf._size is valid. +*/ + if (fp-_bf._base == NULL) + __smakebuf(fp); + + dst = buf; + + while (total 0) { /* -* We know if we're unbuffered that our buffer is empty, so -* we can just read directly. This is much faster than the -* loop below which will perform a series of one byte reads. +* Copy data out of the buffer. */ - while (resid 0 (r = (*fp-_read)(fp-_cookie, p, resid)) 0) { - p += r; - resid -= r; - } - FUNLOCKFILE(fp); - return ((total - resid) / size); + size_t buffered_bytes = MINIMUM(fp-_r, total); + + memcpy(dst, fp-_p, buffered_bytes); + fp-_p += buffered_bytes; + fp-_r -= buffered_bytes; + dst += buffered_bytes; + total -= buffered_bytes; + + /* +* Are we done? +*/ + if (total == 0) + goto out; + + /* +* Do we have so much more to read that we should +* avoid copying it through the buffer? +*/ + if (total (size_t) fp-_bf._size) + break; + + /* +* Less than a buffer to go, so refill the buffer and +* go around the loop again. +*/ + if (__srefill(fp)) + goto out; } - while (resid (r = fp-_r)) { - (void)memcpy((void *)p, (void *)fp-_p, (size_t)r); - fp-_p += r; - /* fp-_r = 0 ... done in __srefill */ - p += r; - resid -= r; - if (__srefill(fp)) { - /* no more input: return partial result */ - FUNLOCKFILE(fp); - return ((total - resid) / size); + /* +* Read directly into the caller's buffer. +*/ + while (total 0) { + ssize_t bytes_read = (*fp-_read)(fp-_cookie, dst, total); + + if (bytes_read = 0) { + fp-_flags = (fp-_r == 0) ? __SEOF : __SERR; + break; } + dst += bytes_read; + total -= bytes_read; } - (void)memcpy((void *)p, (void *)fp-_p, resid); - fp-_r -= resid; - fp-_p += resid; + +out: FUNLOCKFILE(fp); - return (count); + return ((desired_total - total) / size); }
enable jumbos on newer re(4) devices
hi all, the below diff enables support for jumbo frames on some newer re(4) devices. i've tested it on 8186D/8111D and 8186E/8111E chips, which are both able to do 9k jumbos. it seems to provide a significant speed-up on simple file transfer tests. most of the important parts were taken from the freebsd re(4) driver. feedback welcome, hope this helps someone. cheers, jim Index: re.c === RCS file: /cvs/src/sys/dev/ic/re.c,v retrieving revision 1.173 diff -u -r1.173 re.c --- re.c21 Jan 2015 10:00:42 - 1.173 +++ re.c21 Jan 2015 11:10:31 - @@ -171,6 +171,8 @@ intre_ifmedia_upd(struct ifnet *); void re_ifmedia_sts(struct ifnet *, struct ifmediareq *); +void re_set_jumbo(struct rl_softc *); + void re_eeprom_putbyte(struct rl_softc *, int); void re_eeprom_getword(struct rl_softc *, int, u_int16_t *); void re_read_eeprom(struct rl_softc *, caddr_t, int, int); @@ -206,6 +208,10 @@ CSR_WRITE_1(sc, RL_EECMD, \ CSR_READ_1(sc, RL_EECMD) ~x) +#define RL_FRAMELEN(mtu) \ + (mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + \ + ETHER_VLAN_ENCAP_LEN) + static const struct re_revision { u_int32_t re_chipid; const char *re_name; @@ -1022,8 +1028,10 @@ /* Create DMA maps for RX buffers */ for (i = 0; i RL_RX_DESC_CNT; i++) { - error = bus_dmamap_create(sc-sc_dmat, MCLBYTES, 1, MCLBYTES, - 0, 0, sc-rl_ldata.rl_rxsoft[i].rxs_dmamap); + error = bus_dmamap_create(sc-sc_dmat, + RL_FRAMELEN(sc-rl_max_mtu), 1, + RL_FRAMELEN(sc-rl_max_mtu), 0, 0, + sc-rl_ldata.rl_rxsoft[i].rxs_dmamap); if (error) { printf(%s: can't create DMA map for RX\n, sc-sc_dev.dv_xname); @@ -1038,8 +1046,7 @@ ifp-if_ioctl = re_ioctl; ifp-if_start = re_start; ifp-if_watchdog = re_watchdog; - if ((sc-rl_flags RL_FLAG_JUMBOV2) == 0) - ifp-if_hardmtu = sc-rl_max_mtu; + ifp-if_hardmtu = sc-rl_max_mtu; IFQ_SET_MAXLEN(ifp-if_snd, RL_TX_QLEN); IFQ_SET_READY(ifp-if_snd); @@ -1159,7 +1166,7 @@ u_int32_t cmdstat; int error, idx; - m = MCLGETI(NULL, M_DONTWAIT, NULL, MCLBYTES); + m = MCLGETI(NULL, M_DONTWAIT, NULL, RL_FRAMELEN(sc-rl_max_mtu)); if (!m) return (ENOBUFS); @@ -1168,7 +1175,7 @@ * alignment so that the frame payload is * longword aligned on strict alignment archs. */ - m-m_len = m-m_pkthdr.len = RE_RX_DESC_BUFLEN; + m-m_len = m-m_pkthdr.len = RL_FRAMELEN(sc-rl_max_mtu); m-m_data += RE_ETHER_ALIGN; idx = sc-rl_ldata.rl_rx_prodidx; @@ -1274,7 +1281,7 @@ { struct mbuf *m; struct ifnet*ifp; - int i, total_len, rx = 0; + int i, total_len, rxerr, rx = 0; struct rl_desc *cur_rx; struct rl_rxsoft *rxs; u_int32_t rxstat, rxvlan; @@ -1306,8 +1313,12 @@ BUS_DMASYNC_POSTREAD); bus_dmamap_unload(sc-sc_dmat, rxs-rxs_dmamap); - if (!(rxstat RL_RDESC_STAT_EOF)) { - m-m_len = RE_RX_DESC_BUFLEN; + if ((sc-rl_flags RL_FLAG_JUMBOV2) != 0 + (rxstat (RL_RDESC_STAT_SOF | RL_RDESC_STAT_EOF)) != + (RL_RDESC_STAT_SOF | RL_RDESC_STAT_EOF)) { + continue; + } else if (!(rxstat RL_RDESC_STAT_EOF)) { + m-m_len = RL_FRAMELEN(sc-rl_max_mtu); if (sc-rl_head == NULL) sc-rl_head = sc-rl_tail = m; else { @@ -1341,24 +1352,31 @@ * if total_len 2^13-1, both _RXERRSUM and _GIANT will be * set, but if CRC is clear, it will still be a valid frame. */ - if (rxstat RL_RDESC_STAT_RXERRSUM !(total_len 8191 - (rxstat RL_RDESC_STAT_ERRS) == RL_RDESC_STAT_GIANT)) { - ifp-if_ierrors++; - /* -* If this is part of a multi-fragment packet, -* discard all the pieces. -*/ - if (sc-rl_head != NULL) { - m_freem(sc-rl_head); - sc-rl_head = sc-rl_tail = NULL; + if ((rxstat RL_RDESC_STAT_RXERRSUM) != 0) { + rxerr = 1; + if (rxstat RL_RDESC_STAT_RXERRSUM !(total_len 8191 + (rxstat RL_RDESC_STAT_ERRS) == RL_RDESC_STAT_GIANT)) { + rxerr
Re: cdce(4) and MBIM
Hi Ingo, sorry to disappoint you, but that won't work. First of all, if_cdce.c doesn't do NCM encoding and second, even if it did this still wouldn't work because it just describes how data packets are encapsulated. But to talk to an MBIM device, you need a different set of control messages (e.g. to set the PIN, to tell the device to connect to the network, etc.) I'm currently working on an MBIM driver for OpenBSD, but it will take some more time until it's ready for sending out patches. Gerhard On Tue, 20 Jan 2015 23:31:17 +0100 Ingo Feinerer feine...@logic.at wrote: Has anyone experiences with USB devices (e.g. UMTS modem) offering Mobile Broadband Interface Model (MBIM) interfaces? According to www.usb.org/developers/docs/devclass_docs/MBIM10Errata1_073013.zip MBIM is comparable to NCM (The largest deviation from NCM 1.0 is that devices transfer raw IP packets instead of packets with 802.3 headers.) which is supported by cdce(4). By hardcoding vendor and device ID in sys/dev/usb/if_cdce.c I managed to have a modem with MBIM interface attach via cdce: cdce0 at uhub0 port 4 configuration 1 interface 0 MediaTek Inc Product rev 2.00/3.00 addr 2 cdce0: address XX:XX:XX:XX:XX:XX ifconfig appears to work as well cdce0: flags=8802BROADCAST,SIMPLEX,MULTICAST mtu 1500 lladdr XX:XX:XX:XX:XX:XX priority: 0 but dhclient gets no response. /var/log/messages contains cdce0: watchdog timeout cdce0: usb error on tx: TIMEOUT Any ideas? Best regards, Ingo
Re: Use rtdeletemsg()
On 19/01/15(Mon) 09:35, Todd C. Miller wrote: On Mon, 19 Jan 2015 11:49:53 +0100, Martin Pieuchot wrote: Instead of rerolling rtrequest1(RTM_DELETE...) code in various places, simply use rtdeletemsg() which also notify userland that the route entry is going away. Since rtdeletemsg() may call rtfree() doesn't this mean that we can end up calling rtfree() twice? Or is rt-rt_refcnt never going to be zero in this case? It is indeed confusing. I tried to check every cases but in the end I think that it might be better to decouple the removal from the routing table and the rtfree(). Updated diff below does that. Another advantage I can see to this approach is to be more strict about the reference counter on a per-rt basic. Index: net/route.c === RCS file: /home/ncvs/src/sys/net/route.c,v retrieving revision 1.200 diff -u -p -r1.200 route.c --- net/route.c 18 Jan 2015 14:51:43 - 1.200 +++ net/route.c 21 Jan 2015 12:17:21 - @@ -544,11 +544,6 @@ rtdeletemsg(struct rtentry *rt, u_int ta rt_missmsg(RTM_DELETE, info, info.rti_flags, ifp, error, tableid); - /* Adjust the refcount */ - if (error == 0 rt-rt_refcnt = 0) { - rt-rt_refcnt++; - rtfree(rt); - } return (error); } @@ -556,11 +551,19 @@ int rtflushclone1(struct radix_node *rn, void *arg, u_int id) { struct rtentry *rt, *parent; + int error; rt = (struct rtentry *)rn; parent = (struct rtentry *)arg; - if ((rt-rt_flags RTF_CLONED) != 0 rt-rt_parent == parent) - rtdeletemsg(rt, id); + if ((rt-rt_flags RTF_CLONED) != 0 rt-rt_parent == parent) { + error = rtdeletemsg(rt, id); + + /* Adjust the refcount */ + if (error == 0 rt-rt_refcnt = 0) { + rt-rt_refcnt++; + rtfree(rt); + } + } return 0; } @@ -1632,8 +1635,17 @@ rt_if_remove_rtdelete(struct radix_node if (rt-rt_ifp == ifp) { int cloning = (rt-rt_flags RTF_CLONING); - if (rtdeletemsg(rt, id) == 0 cloning) - return (EAGAIN); + if (rtdeletemsg(rt, id) == 0) { + + /* Adjust the refcount */ + if (rt-rt_refcnt = 0) { + rt-rt_refcnt++; + rtfree(rt); + } + + if (cloning) + return (EAGAIN); + } } /* Index: netinet/if_ether.c === RCS file: /home/ncvs/src/sys/netinet/if_ether.c,v retrieving revision 1.141 diff -u -p -r1.141 if_ether.c --- netinet/if_ether.c 13 Jan 2015 12:16:18 - 1.141 +++ netinet/if_ether.c 21 Jan 2015 12:17:21 - @@ -789,6 +789,7 @@ arptfree(struct llinfo_arp *la) struct rtentry *rt = la-la_rt; struct sockaddr_dl *sdl; u_int tid = 0; + int error; if (rt == NULL) panic(arptfree); @@ -803,7 +804,13 @@ arptfree(struct llinfo_arp *la) if (rt-rt_ifp) tid = rt-rt_ifp-if_rdomain; - rtdeletemsg(rt, tid); + error = rtdeletemsg(rt, tid); + + /* Adjust the refcount */ + if (error == 0 rt-rt_refcnt = 0) { + rt-rt_refcnt++; + rtfree(rt); + } } /* Index: netinet/ip_icmp.c === RCS file: /home/ncvs/src/sys/netinet/ip_icmp.c,v retrieving revision 1.129 diff -u -p -r1.129 ip_icmp.c --- netinet/ip_icmp.c 22 Dec 2014 11:05:53 - 1.129 +++ netinet/ip_icmp.c 21 Jan 2015 12:17:21 - @@ -1031,20 +1031,12 @@ icmp_mtudisc_timeout(struct rtentry *rt, (RTF_DYNAMIC | RTF_HOST)) { void *(*ctlfunc)(int, struct sockaddr *, u_int, void *); struct sockaddr_in sa; - struct rt_addrinfo info; int s; - memset(info, 0, sizeof(info)); - info.rti_info[RTAX_DST] = rt_key(rt); - info.rti_info[RTAX_NETMASK] = rt_mask(rt); - info.rti_info[RTAX_GATEWAY] = rt-rt_gateway; - info.rti_flags = rt-rt_flags; - sa = *(struct sockaddr_in *)rt_key(rt); s = splsoftnet(); - rtrequest1(RTM_DELETE, info, rt-rt_priority, NULL, - r-rtt_tableid); + rtdeletemsg(rt, r-rtt_tableid); /* Notify TCP layer of increased Path MTU estimate */ ctlfunc = inetsw[ip_protox[IPPROTO_TCP]].pr_ctlinput; @@ -1083,18 +1075,10 @@ icmp_redirect_timeout(struct rtentry *rt if ((rt-rt_flags (RTF_DYNAMIC | RTF_HOST)) == (RTF_DYNAMIC | RTF_HOST)) { - struct rt_addrinfo