From 75b706fde4cbf82bcd41a1cec319778aa0f8eb2d Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 9 Dec 2016 14:19:03 +0100 Subject: [PATCH] Update to FreeBSD head 2016-12-10 Git mirror commit 80c55f08a05ab3b26a73b226ccb56adc3122a55c. --- freebsd-org | 2 +- freebsd/bin/hostname/hostname.c | 22 +- freebsd/contrib/tcpdump/tcpdump.c | 47 ++ freebsd/lib/libc/db/btree/bt_close.c | 3 +- freebsd/lib/libc/include/libc_private.h | 1 + freebsd/lib/libc/net/getaddrinfo.c | 21 +- freebsd/lib/libc/net/linkaddr.c | 52 +- freebsd/lib/libc/net/name6.c | 21 +- freebsd/lib/libc/stdio/fgetln.c | 7 +- freebsd/lib/libipsec/pfkey.c | 1 + freebsd/lib/libipsec/pfkey_dump.c | 5 +- freebsd/lib/libmemstat/memstat_uma.c | 3 - freebsd/sbin/dhclient/clparse.c | 2 + freebsd/sbin/dhclient/dhclient.c | 15 + freebsd/sbin/dhclient/dhcpd.h | 2 + freebsd/sbin/dhclient/dispatch.c | 48 +- freebsd/sbin/dhclient/privsep.c | 8 + freebsd/sbin/dhclient/privsep.h | 3 +- freebsd/sbin/dhclient/tables.c | 1 + freebsd/sbin/ifconfig/af_inet.c | 2 +- freebsd/sbin/ifconfig/af_inet6.c | 2 +- freebsd/sbin/ifconfig/af_link.c | 25 +- freebsd/sbin/pfctl/parse.y | 78 +- freebsd/sbin/pfctl/pfctl.c | 2 +- freebsd/sbin/pfctl/pfctl_optimize.c | 4 +- freebsd/sbin/pfctl/pfctl_parser.c | 8 +- freebsd/sbin/sysctl/sysctl.c | 3 - freebsd/sys/arm/include/machine/cpufunc.h | 46 +- freebsd/sys/arm/xilinx/zy7_slcr.c | 5 +- freebsd/sys/cam/cam.h | 2 +- freebsd/sys/cam/cam_ccb.h | 6 + freebsd/sys/cam/cam_periph.h | 1 - freebsd/sys/cam/scsi/scsi_all.c | 123 ++- freebsd/sys/cam/scsi/scsi_all.h | 48 ++ freebsd/sys/crypto/sha1.h | 2 +- freebsd/sys/crypto/sha2/sha256.h | 11 +- freebsd/sys/crypto/sha2/sha384.h | 11 +- freebsd/sys/crypto/sha2/sha512.h | 11 +- freebsd/sys/crypto/sha2/sha512t.h | 22 +- freebsd/sys/crypto/siphash/siphash.h | 9 +- freebsd/sys/crypto/skein/skein_freebsd.h | 15 +- freebsd/sys/crypto/skein/skein_port.h | 10 + freebsd/sys/dev/bfe/if_bfe.c | 2 + freebsd/sys/dev/e1000/if_em.c | 44 +- freebsd/sys/dev/e1000/if_igb.c | 19 +- freebsd/sys/dev/e1000/if_lem.c | 175 +--- freebsd/sys/dev/mii/rgephy.c | 12 +- freebsd/sys/dev/mii/rgephyreg.h | 3 + freebsd/sys/dev/nvme/nvme.h | 38 +- freebsd/sys/dev/pci/pci.c | 180 +++- freebsd/sys/dev/pci/pcireg.h | 21 +- freebsd/sys/dev/pci/pcivar.h | 13 +- freebsd/sys/dev/re/if_re.c | 10 +- freebsd/sys/dev/rl/if_rlreg.h | 5 + freebsd/sys/dev/tsec/if_tsec.h | 7 +- freebsd/sys/dev/usb/controller/dwc_otg.c | 27 +- freebsd/sys/dev/usb/controller/dwc_otg.h | 7 + freebsd/sys/dev/usb/quirk/usb_quirk.c | 30 +- freebsd/sys/dev/usb/storage/umass.c | 2 +- freebsd/sys/dev/usb/usb_busdma.c | 14 +- freebsd/sys/dev/usb/usb_core.c | 14 + freebsd/sys/dev/usb/usb_core.h | 23 +- freebsd/sys/dev/usb/usb_dev.c | 6 +- freebsd/sys/dev/usb/usb_device.c | 61 +- freebsd/sys/dev/usb/usb_device.h | 5 +- freebsd/sys/dev/usb/usb_freebsd.h | 3 + freebsd/sys/dev/usb/usb_generic.c | 15 +- freebsd/sys/dev/usb/usb_hub.c | 8 +- freebsd/sys/dev/usb/usb_msctest.c | 8 +- freebsd/sys/dev/usb/usb_process.c | 25 +- freebsd/sys/dev/usb/usb_request.c | 21 +- freebsd/sys/dev/usb/usb_transfer.c | 76 +- freebsd/sys/dev/usb/usb_util.c | 4 +- freebsd/sys/dev/usb/usbdi.h | 57 +- freebsd/sys/i386/include/machine/md_var.h | 1 + freebsd/sys/kern/init_main.c | 42 +- freebsd/sys/kern/kern_condvar.c | 4 + freebsd/sys/kern/kern_linker.c | 38 +- freebsd/sys/kern/kern_mib.c | 22 +- freebsd/sys/kern/kern_synch.c | 10 +- freebsd/sys/kern/kern_sysctl.c | 2 +- freebsd/sys/kern/kern_time.c | 2 +- freebsd/sys/kern/kern_timeout.c | 4 +- freebsd/sys/kern/subr_bus.c | 74 +- freebsd/sys/kern/subr_hash.c | 2 +- freebsd/sys/kern/subr_pcpu.c | 2 +- freebsd/sys/kern/subr_prf.c | 6 +- freebsd/sys/kern/subr_sleepqueue.c | 6 +- freebsd/sys/kern/subr_taskqueue.c | 28 +- freebsd/sys/kern/subr_uio.c | 4 +- freebsd/sys/kern/sys_generic.c | 2 +- freebsd/sys/kern/sys_socket.c | 2 +- freebsd/sys/kern/uipc_accf.c | 2 +- freebsd/sys/kern/uipc_domain.c | 2 +- freebsd/sys/kern/uipc_mbuf.c | 6 +- freebsd/sys/kern/uipc_mbuf2.c | 2 +- freebsd/sys/kern/uipc_sockbuf.c | 2 +- freebsd/sys/kern/uipc_socket.c | 5 +- freebsd/sys/kern/uipc_syscalls.c | 310 ++----- freebsd/sys/kern/uipc_usrreq.c | 16 +- freebsd/sys/mips/include/machine/cpufunc.h | 10 +- freebsd/sys/mips/include/machine/cpuregs.h | 8 +- freebsd/sys/net/altq/altq_subr.c | 2 +- freebsd/sys/net/bpf_filter.c | 25 +- freebsd/sys/net/ethernet.h | 2 +- freebsd/sys/net/if.c | 2 +- freebsd/sys/net/if_arcsubr.c | 2 +- freebsd/sys/net/if_bridge.c | 88 +- freebsd/sys/net/if_fddisubr.c | 2 +- freebsd/sys/net/if_iso88025subr.c | 2 +- freebsd/sys/net/if_llatbl.c | 35 +- freebsd/sys/net/if_llatbl.h | 8 - freebsd/sys/net/if_loop.c | 5 + freebsd/sys/net/if_var.h | 10 +- freebsd/sys/net/pfkeyv2.h | 11 +- freebsd/sys/net/raw_usrreq.c | 2 +- freebsd/sys/net/route.c | 9 +- freebsd/sys/net/route_var.h | 2 + freebsd/sys/net/rtsock.c | 42 +- freebsd/sys/netinet/cc/cc.h | 1 + freebsd/sys/netinet/cc/cc_newreno.c | 29 +- freebsd/sys/netinet/if_ether.c | 128 +++ freebsd/sys/netinet/igmp.c | 8 +- freebsd/sys/netinet/in.c | 8 + freebsd/sys/netinet/in_pcb.c | 10 +- freebsd/sys/netinet/in_var.h | 2 + freebsd/sys/netinet/ip_fastfwd.c | 139 ++-- freebsd/sys/netinet/ip_icmp.c | 2 + freebsd/sys/netinet/ip_input.c | 2 +- freebsd/sys/netinet/ip_mroute.c | 8 +- freebsd/sys/netinet/ip_output.c | 13 +- freebsd/sys/netinet/raw_ip.c | 4 +- freebsd/sys/netinet/sctp_asconf.c | 54 +- freebsd/sys/netinet/sctp_asconf.h | 1 - freebsd/sys/netinet/sctp_bsd_addr.c | 11 +- freebsd/sys/netinet/sctp_bsd_addr.h | 1 - freebsd/sys/netinet/sctp_cc_functions.c | 77 +- freebsd/sys/netinet/sctp_constants.h | 5 +- freebsd/sys/netinet/sctp_crc32.c | 1 - freebsd/sys/netinet/sctp_crc32.h | 2 - freebsd/sys/netinet/sctp_header.h | 21 +- freebsd/sys/netinet/sctp_indata.c | 776 ++++++++---------- freebsd/sys/netinet/sctp_indata.h | 11 +- freebsd/sys/netinet/sctp_input.c | 136 ++- freebsd/sys/netinet/sctp_os_bsd.h | 1 - freebsd/sys/netinet/sctp_output.c | 390 ++++----- freebsd/sys/netinet/sctp_pcb.c | 147 ++-- freebsd/sys/netinet/sctp_pcb.h | 9 +- freebsd/sys/netinet/sctp_peeloff.h | 1 - freebsd/sys/netinet/sctp_structs.h | 28 +- freebsd/sys/netinet/sctp_sysctl.c | 3 - freebsd/sys/netinet/sctp_timer.c | 48 +- freebsd/sys/netinet/sctp_uio.h | 3 - freebsd/sys/netinet/sctp_usrreq.c | 142 +--- freebsd/sys/netinet/sctp_var.h | 6 +- freebsd/sys/netinet/sctputil.c | 185 ++--- freebsd/sys/netinet/sctputil.h | 5 - freebsd/sys/netinet/tcp_debug.c | 4 +- freebsd/sys/netinet/tcp_fsm.h | 3 +- freebsd/sys/netinet/tcp_hostcache.c | 56 +- freebsd/sys/netinet/tcp_hostcache.h | 28 +- freebsd/sys/netinet/tcp_input.c | 181 ++-- freebsd/sys/netinet/tcp_lro.c | 1 + freebsd/sys/netinet/tcp_output.c | 92 ++- freebsd/sys/netinet/tcp_seq.h | 7 +- freebsd/sys/netinet/tcp_subr.c | 50 +- freebsd/sys/netinet/tcp_syncache.c | 51 +- freebsd/sys/netinet/tcp_timer.c | 20 + freebsd/sys/netinet/tcp_timewait.c | 5 + freebsd/sys/netinet/tcp_usrreq.c | 53 +- freebsd/sys/netinet/tcp_var.h | 51 +- freebsd/sys/netinet/udp_usrreq.c | 11 +- freebsd/sys/netinet6/icmp6.c | 169 ++-- freebsd/sys/netinet6/in6.c | 19 +- freebsd/sys/netinet6/in6_ifattach.c | 25 +- freebsd/sys/netinet6/ip6_forward.c | 3 +- freebsd/sys/netinet6/ip6_input.c | 4 +- freebsd/sys/netinet6/ip6_mroute.c | 13 +- freebsd/sys/netinet6/ip6_output.c | 36 +- freebsd/sys/netinet6/nd6.c | 145 +++- freebsd/sys/netinet6/nd6.h | 29 +- freebsd/sys/netinet6/nd6_nbr.c | 43 +- freebsd/sys/netinet6/nd6_rtr.c | 372 ++++++--- freebsd/sys/netinet6/raw_ip6.c | 2 +- freebsd/sys/netinet6/sctp6_usrreq.c | 6 - freebsd/sys/netinet6/sctp6_var.h | 1 - freebsd/sys/netinet6/udp6_usrreq.c | 5 +- freebsd/sys/netpfil/ipfw/ip_fw2.c | 4 +- freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c | 11 +- freebsd/sys/netpfil/ipfw/ip_fw_pfil.c | 24 +- freebsd/sys/netpfil/ipfw/ip_fw_table.c | 52 +- .../sys/netpfil/ipfw/nat64/nat64_translate.c | 4 +- freebsd/sys/netpfil/pf/if_pflog.c | 2 +- freebsd/sys/netpfil/pf/if_pfsync.c | 9 +- freebsd/sys/netpfil/pf/pf.c | 65 +- freebsd/sys/netpfil/pf/pf_if.c | 2 +- freebsd/sys/netpfil/pf/pf_ioctl.c | 4 +- freebsd/sys/netpfil/pf/pf_norm.c | 2 +- freebsd/sys/opencrypto/crypto.c | 4 +- freebsd/sys/powerpc/include/machine/cpufunc.h | 2 +- freebsd/sys/powerpc/include/machine/spr.h | 5 + freebsd/sys/sys/buf.h | 31 +- freebsd/sys/sys/bufobj.h | 5 - freebsd/sys/sys/bus.h | 4 + freebsd/sys/sys/capsicum.h | 2 + freebsd/sys/sys/eventhandler.h | 7 + freebsd/sys/sys/filedesc.h | 28 + freebsd/sys/sys/linker.h | 1 + freebsd/sys/sys/mbuf.h | 8 +- freebsd/sys/sys/module.h | 2 +- freebsd/sys/sys/mount.h | 11 +- freebsd/sys/sys/proc.h | 1 + freebsd/sys/sys/sf_buf.h | 1 + freebsd/sys/sys/socket.h | 1 + freebsd/sys/sys/socketvar.h | 3 +- freebsd/sys/sys/sysctl.h | 1 + freebsd/sys/sys/sysproto.h | 2 +- freebsd/sys/sys/user.h | 3 +- freebsd/sys/sys/vmmeter.h | 40 +- freebsd/sys/sys/vnode.h | 13 +- freebsd/sys/vm/uma_core.c | 16 +- freebsd/usr.bin/netstat/mbuf.c | 3 + freebsd/usr.bin/netstat/route.c | 2 + freebsd/usr.bin/vmstat/vmstat.c | 14 +- libbsd.txt | 2 +- .../include/machine/rtems-bsd-kernel-space.h | 2 + rtemsbsd/include/rtems/bsd/sys/param.h | 2 +- 227 files changed, 3800 insertions(+), 3006 deletions(-) diff --git a/freebsd-org b/freebsd-org index 9fe7c416..80c55f08 160000 --- a/freebsd-org +++ b/freebsd-org @@ -1 +1 @@ -Subproject commit 9fe7c416e6abb28b1398fd3e5687099846800cfd +Subproject commit 80c55f08a05ab3b26a73b226ccb56adc3122a55c diff --git a/freebsd/bin/hostname/hostname.c b/freebsd/bin/hostname/hostname.c index 8e9fc975..61b5dbad 100644 --- a/freebsd/bin/hostname/hostname.c +++ b/freebsd/bin/hostname/hostname.c @@ -96,7 +96,7 @@ rtems_shell_cmd_t rtems_shell_HOSTNAME_Command = { int main(int argc, char *argv[]) { - int ch, sflag; + int ch, sflag, dflag; char *p, hostname[MAXHOSTNAMELEN]; #ifdef __rtems__ struct getopt_data getopt_data; @@ -107,10 +107,11 @@ main(int argc, char *argv[]) #endif /* __rtems__ */ sflag = 0; + dflag = 0; #ifndef __rtems__ - while ((ch = getopt(argc, argv, "fs")) != -1) + while ((ch = getopt(argc, argv, "fsd")) != -1) #else /* __rtems__ */ - while ((ch = getopt(argc, argv, "fms")) != -1) + while ((ch = getopt(argc, argv, "fdms")) != -1) #endif /* __rtems__ */ switch (ch) { case 'f': @@ -123,6 +124,9 @@ main(int argc, char *argv[]) case 's': sflag = 1; break; + case 'd': + dflag = 1; + break; #ifdef __rtems__ case 'm': mflag = 1; @@ -135,7 +139,7 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - if (argc > 1) + if (argc > 1 || (sflag && dflag)) usage(); if (*argv) { @@ -164,6 +168,10 @@ main(int argc, char *argv[]) p = strchr(hostname, '.'); if (p != NULL) *p = '\0'; + } else if (dflag) { + p = strchr(hostname, '.'); + if (p != NULL) + strcpy(hostname, ++p); } (void)printf("%s\n", hostname); } @@ -174,6 +182,10 @@ static void usage(void) { - (void)fprintf(stderr, "usage: hostname [-fms] [name-of-host]\n"); +#ifndef __rtems__ + (void)fprintf(stderr, "usage: hostname [-f] [-s | -d] [name-of-host]\n"); +#else /* __rtems__ */ + (void)fprintf(stderr, "usage: hostname [-f] [-m | -s | -d] [name-of-host]\n"); +#endif /* __rtems__ */ exit(1); } diff --git a/freebsd/contrib/tcpdump/tcpdump.c b/freebsd/contrib/tcpdump/tcpdump.c index 16914512..6a74ef70 100644 --- a/freebsd/contrib/tcpdump/tcpdump.c +++ b/freebsd/contrib/tcpdump/tcpdump.c @@ -40,6 +40,7 @@ static const char rcsid[] _U_ = /* $FreeBSD$ */ #ifdef __rtems__ +#define HAVE_GETOPT_LONG #define __need_getopt_newlib #include #define setpriority(a, b, c) @@ -84,6 +85,32 @@ extern int SIZE_BUF; #include #endif +#ifdef HAVE_LIBCRYPTO +#include +#endif + +#ifdef HAVE_GETOPT_LONG +#include +#else +#include "getopt_long.h" +#endif +/* Capsicum-specific code requires macros from , which will fail + * to compile if has already been included; including the headers + * in the opposite order works fine. + */ +#ifdef __FreeBSD__ +#include +#include +#include +#endif /* __FreeBSD__ */ +#ifdef HAVE_CASPER +#include +#include +#include +#include +#include +#include +#endif /* HAVE_CASPER */ #include #include #include @@ -1619,6 +1646,26 @@ main(int argc, char **argv) if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); +#ifdef HAVE_CASPER + if (RFileName == NULL && VFileName == NULL) { + static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF }; + + /* + * The various libpcap devices use a combination of + * read (bpf), ioctl (bpf, netmap), poll (netmap). + * Grant the relevant access rights, sorted by name. + */ + cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ); + if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 && + errno != ENOSYS) { + error("unable to limit pcap descriptor"); + } + if (cap_ioctls_limit(pcap_fileno(pd), cmds, + sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) { + error("unable to limit ioctls on pcap descriptor"); + } + } +#endif if (WFileName) { pcap_dumper_t *p; /* Do not exceed the default PATH_MAX for files. */ diff --git a/freebsd/lib/libc/db/btree/bt_close.c b/freebsd/lib/libc/db/btree/bt_close.c index 2034f6af..a8146e5a 100644 --- a/freebsd/lib/libc/db/btree/bt_close.c +++ b/freebsd/lib/libc/db/btree/bt_close.c @@ -136,7 +136,8 @@ __bt_sync(const DB *dbp, u_int flags) return (RET_ERROR); } - if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED)) + if (F_ISSET(t, B_INMEM | B_RDONLY) || + !F_ISSET(t, B_MODIFIED | B_METADIRTY)) return (RET_SUCCESS); if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR) diff --git a/freebsd/lib/libc/include/libc_private.h b/freebsd/lib/libc/include/libc_private.h index 9fe6ab01..053b221a 100644 --- a/freebsd/lib/libc/include/libc_private.h +++ b/freebsd/lib/libc/include/libc_private.h @@ -339,6 +339,7 @@ int __sys_openat(int, const char *, int, ...); int __sys_pselect(int, struct fd_set *, struct fd_set *, struct fd_set *, const struct timespec *, const __sigset_t *); +int __sys_ptrace(int, __pid_t, char *, int); int __sys_poll(struct pollfd *, unsigned, int); int __sys_ppoll(struct pollfd *, unsigned, const struct timespec *, const __sigset_t *); diff --git a/freebsd/lib/libc/net/getaddrinfo.c b/freebsd/lib/libc/net/getaddrinfo.c index 0fe1b5d8..18aed435 100644 --- a/freebsd/lib/libc/net/getaddrinfo.c +++ b/freebsd/lib/libc/net/getaddrinfo.c @@ -226,6 +226,7 @@ struct ai_order { struct policyqueue *aio_dstpolicy; struct addrinfo *aio_ai; int aio_matchlen; + int aio_initial_sequence; }; static const ns_src default_dns_files[] = { @@ -710,6 +711,7 @@ reorder(struct addrinfo *sentinel) aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr, &policyhead); set_source(&aio[i], &policyhead); + aio[i].aio_initial_sequence = i; } /* perform sorting. */ @@ -949,7 +951,7 @@ matchlen(struct sockaddr *src, struct sockaddr *dst) while (s < lim) if ((r = (*d++ ^ *s++)) != 0) { - while (r < addrlen * 8) { + while ((r & 0x80) == 0) { match++; r <<= 1; } @@ -1068,6 +1070,23 @@ comp_dst(const void *arg1, const void *arg2) } /* Rule 10: Otherwise, leave the order unchanged. */ + + /* + * Note that qsort is unstable; so, we can't return zero and + * expect the order to be unchanged. + * That also means we can't depend on the current position of + * dst2 being after dst1. We must enforce the initial order + * with an explicit compare on the original position. + * The qsort specification requires that "When the same objects + * (consisting of width bytes, irrespective of their current + * positions in the array) are passed more than once to the + * comparison function, the results shall be consistent with one + * another." + * In other words, If A < B, then we must also return B > A. + */ + if (dst2->aio_initial_sequence < dst1->aio_initial_sequence) + return(1); + return(-1); } diff --git a/freebsd/lib/libc/net/linkaddr.c b/freebsd/lib/libc/net/linkaddr.c index 1a2c3fd3..dbd363d8 100644 --- a/freebsd/lib/libc/net/linkaddr.c +++ b/freebsd/lib/libc/net/linkaddr.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -124,31 +125,46 @@ char * link_ntoa(const struct sockaddr_dl *sdl) { static char obuf[64]; - char *out = obuf; - int i; - u_char *in = (u_char *)LLADDR(sdl); - u_char *inlim = in + sdl->sdl_alen; - int firsttime = 1; + _Static_assert(sizeof(obuf) >= IFNAMSIZ + 20, "obuf is too small"); + char *out; + const u_char *in, *inlim; + int namelen, i, rem; - if (sdl->sdl_nlen) { - bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen); - out += sdl->sdl_nlen; - if (sdl->sdl_alen) + namelen = (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ; + + out = obuf; + rem = sizeof(obuf); + if (namelen > 0) { + bcopy(sdl->sdl_data, out, namelen); + out += namelen; + rem -= namelen; + if (sdl->sdl_alen > 0) { *out++ = ':'; + rem--; + } } - while (in < inlim) { - if (firsttime) - firsttime = 0; - else + + in = (const u_char *)sdl->sdl_data + sdl->sdl_nlen; + inlim = in + sdl->sdl_alen; + + while (in < inlim && rem > 1) { + if (in != (const u_char *)sdl->sdl_data + sdl->sdl_nlen) { *out++ = '.'; + rem--; + } i = *in++; if (i > 0xf) { - out[1] = hexlist[i & 0xf]; - i >>= 4; - out[0] = hexlist[i]; - out += 2; - } else + if (rem < 3) + break; + *out++ = hexlist[i >> 4]; + *out++ = hexlist[i & 0xf]; + rem -= 2; + } else { + if (rem < 2) + break; *out++ = hexlist[i]; + rem--; + } } *out = 0; return (obuf); diff --git a/freebsd/lib/libc/net/name6.c b/freebsd/lib/libc/net/name6.c index a106ad98..8b8ac79c 100644 --- a/freebsd/lib/libc/net/name6.c +++ b/freebsd/lib/libc/net/name6.c @@ -187,6 +187,7 @@ struct hp_order { #define aio_sa aio_un.aiou_sa int aio_matchlen; char *aio_h_addr; + int aio_initial_sequence; }; static struct hostent *_hpcopy(struct hostent *, int *); @@ -713,6 +714,7 @@ _hpreorder(struct hostent *hp) aio[i].aio_dstscope = gai_addr2scopetype(sa); aio[i].aio_dstpolicy = match_addrselectpolicy(sa, &policyhead); set_source(&aio[i], &policyhead); + aio[i].aio_initial_sequence = i; } /* perform sorting. */ @@ -930,7 +932,7 @@ matchlen(struct sockaddr *src, struct sockaddr *dst) while (s < lim) if ((r = (*d++ ^ *s++)) != 0) { - while (r < addrlen * 8) { + while ((r & 0x80) == 0) { match++; r <<= 1; } @@ -1047,6 +1049,23 @@ comp_dst(const void *arg1, const void *arg2) } /* Rule 10: Otherwise, leave the order unchanged. */ + + /* + * Note that qsort is unstable; so, we can't return zero and + * expect the order to be unchanged. + * That also means we can't depend on the current position of + * dst2 being after dst1. We must enforce the initial order + * with an explicit compare on the original position. + * The qsort specification requires that "When the same objects + * (consisting of width bytes, irrespective of their current + * positions in the array) are passed more than once to the + * comparison function, the results shall be consistent with one + * another." + * In other words, If A < B, then we must also return B > A. + */ + if (dst2->aio_initial_sequence < dst1->aio_initial_sequence) + return(1); + return(-1); } diff --git a/freebsd/lib/libc/stdio/fgetln.c b/freebsd/lib/libc/stdio/fgetln.c index 7d9f6a53..8d1235c5 100644 --- a/freebsd/lib/libc/stdio/fgetln.c +++ b/freebsd/lib/libc/stdio/fgetln.c @@ -143,8 +143,11 @@ fgetln(FILE *fp, size_t *lenp) (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, len - off); off = len; - if (__srefill(fp)) - break; /* EOF or error: return partial line */ + if (__srefill(fp)) { + if (__sfeof(fp)) + break; + goto error; + } if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) == NULL) continue; diff --git a/freebsd/lib/libipsec/pfkey.c b/freebsd/lib/libipsec/pfkey.c index abb0cee1..eeb07f82 100644 --- a/freebsd/lib/libipsec/pfkey.c +++ b/freebsd/lib/libipsec/pfkey.c @@ -1778,6 +1778,7 @@ pfkey_align(msg, mhp) case SADB_EXT_SPIRANGE: case SADB_X_EXT_POLICY: case SADB_X_EXT_SA2: + case SADB_X_EXT_SA_REPLAY: mhp[ext->sadb_ext_type] = (caddr_t)ext; break; case SADB_X_EXT_NAT_T_TYPE: diff --git a/freebsd/lib/libipsec/pfkey_dump.c b/freebsd/lib/libipsec/pfkey_dump.c index 7a5c2f21..7c6ff8d8 100644 --- a/freebsd/lib/libipsec/pfkey_dump.c +++ b/freebsd/lib/libipsec/pfkey_dump.c @@ -221,6 +221,7 @@ pfkey_sadump(m) struct sadb_key *m_auth, *m_enc; struct sadb_ident *m_sid, *m_did; struct sadb_sens *m_sens; + struct sadb_x_sa_replay *m_sa_replay; /* check pfkey message. */ if (pfkey_align(m, mhp)) { @@ -245,6 +246,7 @@ pfkey_sadump(m) m_sid = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_SRC]; m_did = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_DST]; m_sens = (struct sadb_sens *)mhp[SADB_EXT_SENSITIVITY]; + m_sa_replay = (struct sadb_x_sa_replay *)mhp[SADB_X_EXT_SA_REPLAY]; /* source address */ if (m_saddr == NULL) { @@ -308,7 +310,8 @@ pfkey_sadump(m) /* replay windoe size & flags */ printf("\tseq=0x%08x replay=%u flags=0x%08x ", m_sa2->sadb_x_sa2_sequence, - m_sa->sadb_sa_replay, + m_sa_replay ? (m_sa_replay->sadb_x_sa_replay_replay >> 3) : + m_sa->sadb_sa_replay, m_sa->sadb_sa_flags); /* state */ diff --git a/freebsd/lib/libmemstat/memstat_uma.c b/freebsd/lib/libmemstat/memstat_uma.c index 9c5e4024..299386c8 100644 --- a/freebsd/lib/libmemstat/memstat_uma.c +++ b/freebsd/lib/libmemstat/memstat_uma.c @@ -32,9 +32,6 @@ #include #include -#include -#include - #include #include diff --git a/freebsd/sbin/dhclient/clparse.c b/freebsd/sbin/dhclient/clparse.c index a65236fc..10df53b3 100644 --- a/freebsd/sbin/dhclient/clparse.c +++ b/freebsd/sbin/dhclient/clparse.c @@ -104,6 +104,8 @@ read_client_conf(void) [top_level_config.requested_option_count++] = DHO_HOST_NAME; top_level_config.requested_options [top_level_config.requested_option_count++] = DHO_DOMAIN_SEARCH; + top_level_config.requested_options + [top_level_config.requested_option_count++] = DHO_INTERFACE_MTU; if ((cfile = fopen(path_dhclient_conf, "r")) != NULL) { do { diff --git a/freebsd/sbin/dhclient/dhclient.c b/freebsd/sbin/dhclient/dhclient.c index c7b75c59..46ffaffc 100644 --- a/freebsd/sbin/dhclient/dhclient.c +++ b/freebsd/sbin/dhclient/dhclient.c @@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include "privsep.h" #include +#include #include @@ -134,6 +135,9 @@ int fork_privchld(int, int); ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) +/* Minimum MTU is 68 as per RFC791, p. 24 */ +#define MIN_MTU 68 + static time_t scripttime; int @@ -800,9 +804,20 @@ dhcpack(struct packet *packet) void bind_lease(struct interface_info *ip) { + struct option_data *opt; + /* Remember the medium. */ ip->client->new->medium = ip->client->medium; + opt = &ip->client->new->options[DHO_INTERFACE_MTU]; + if (opt->len == sizeof(u_int16_t)) { + u_int16_t mtu = be16dec(opt->data); + if (mtu < MIN_MTU) + warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU); + else + interface_set_mtu_unpriv(privfd, mtu); + } + /* Write out the new lease. */ write_client_lease(ip, ip->client->new, 0); diff --git a/freebsd/sbin/dhclient/dhcpd.h b/freebsd/sbin/dhclient/dhcpd.h index 852513a8..f2bc7738 100644 --- a/freebsd/sbin/dhclient/dhcpd.h +++ b/freebsd/sbin/dhclient/dhcpd.h @@ -319,6 +319,8 @@ void cancel_timeout(void (*)(void *), void *); void add_protocol(char *, int, void (*)(struct protocol *), void *); void remove_protocol(struct protocol *); int interface_link_status(char *); +void interface_set_mtu_unpriv(int, u_int16_t); +void interface_set_mtu_priv(char *, u_int16_t); /* hash.c */ struct hash_table *new_hash(void); diff --git a/freebsd/sbin/dhclient/dispatch.c b/freebsd/sbin/dhclient/dispatch.c index 4a68c62d..d37c9925 100644 --- a/freebsd/sbin/dhclient/dispatch.c +++ b/freebsd/sbin/dhclient/dispatch.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include "dhcpd.h" +#include "privsep.h" #include @@ -107,8 +108,8 @@ discover_interfaces(struct interface_info *iface) if (foo.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) continue; if (!iface->ifp) { - int len = IFNAMSIZ + ifa->ifa_addr->sa_len; - if ((tif = malloc(len)) == NULL) + if ((tif = calloc(1, sizeof(struct ifreq))) + == NULL) error("no space to remember ifp"); strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ); memcpy(&tif->ifr_addr, ifa->ifa_addr, @@ -503,3 +504,46 @@ interface_link_status(char *ifname) } return (1); } + +void +interface_set_mtu_unpriv(int privfd, u_int16_t mtu) +{ + struct imsg_hdr hdr; + struct buf *buf; + int errs = 0; + + hdr.code = IMSG_SET_INTERFACE_MTU; + hdr.len = sizeof(hdr) + + sizeof(u_int16_t); + + if ((buf = buf_open(hdr.len)) == NULL) + error("buf_open: %m"); + + errs += buf_add(buf, &hdr, sizeof(hdr)); + errs += buf_add(buf, &mtu, sizeof(mtu)); + if (errs) + error("buf_add: %m"); + + if (buf_close(privfd, buf) == -1) + error("buf_close: %m"); +} + +void +interface_set_mtu_priv(char *ifname, u_int16_t mtu) +{ + struct ifreq ifr; + int sock; + + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + error("Can't create socket"); + + memset(&ifr, 0, sizeof(ifr)); + + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + ifr.ifr_mtu = mtu; + + if (ioctl(sock, SIOCSIFMTU, &ifr) == -1) + warning("SIOCSIFMTU failed (%d): %s", mtu, + strerror(errno)); + close(sock); +} diff --git a/freebsd/sbin/dhclient/privsep.c b/freebsd/sbin/dhclient/privsep.c index aa1042fd..b1cf5106 100644 --- a/freebsd/sbin/dhclient/privsep.c +++ b/freebsd/sbin/dhclient/privsep.c @@ -113,6 +113,7 @@ dispatch_imsg(struct interface_info *ifi, int fd) struct client_lease lease; int ret, i, optlen; struct buf *buf; + u_int16_t mtu; buf_read(fd, &hdr, sizeof(hdr)); @@ -237,6 +238,13 @@ dispatch_imsg(struct interface_info *ifi, int fd) case IMSG_SEND_PACKET: send_packet_priv(ifi, &hdr, fd); break; + case IMSG_SET_INTERFACE_MTU: + if (hdr.len < sizeof(hdr) + sizeof(u_int16_t)) + error("corrupted message received"); + + buf_read(fd, &mtu, sizeof(u_int16_t)); + interface_set_mtu_priv(ifi->name, mtu); + break; default: error("received unknown message, code %d", hdr.code); } diff --git a/freebsd/sbin/dhclient/privsep.h b/freebsd/sbin/dhclient/privsep.h index d464da43..e1a7338f 100644 --- a/freebsd/sbin/dhclient/privsep.h +++ b/freebsd/sbin/dhclient/privsep.h @@ -36,7 +36,8 @@ enum imsg_code { IMSG_SCRIPT_WRITE_PARAMS, IMSG_SCRIPT_GO, IMSG_SCRIPT_GO_RET, - IMSG_SEND_PACKET + IMSG_SEND_PACKET, + IMSG_SET_INTERFACE_MTU, }; struct imsg_hdr { diff --git a/freebsd/sbin/dhclient/tables.c b/freebsd/sbin/dhclient/tables.c index d73022d1..6339898c 100644 --- a/freebsd/sbin/dhclient/tables.c +++ b/freebsd/sbin/dhclient/tables.c @@ -402,6 +402,7 @@ unsigned char dhcp_option_default_priority_list[] = { DHO_IRC_SERVER, DHO_STREETTALK_SERVER, DHO_STREETTALK_DA_SERVER, + DHO_DHCP_USER_CLASS_ID, DHO_DOMAIN_SEARCH, /* Presently-undefined options... */ diff --git a/freebsd/sbin/ifconfig/af_inet.c b/freebsd/sbin/ifconfig/af_inet.c index d464df52..040da216 100644 --- a/freebsd/sbin/ifconfig/af_inet.c +++ b/freebsd/sbin/ifconfig/af_inet.c @@ -100,7 +100,7 @@ in_status(int s __unused, const struct ifaddrs *ifa) sin = (struct sockaddr_in *)ifa->ifa_dstaddr; if (sin == NULL) sin = &null_sin; - printf(" --> %s ", inet_ntoa(sin->sin_addr)); + printf(" --> %s", inet_ntoa(sin->sin_addr)); } sin = (struct sockaddr_in *)ifa->ifa_netmask; diff --git a/freebsd/sbin/ifconfig/af_inet6.c b/freebsd/sbin/ifconfig/af_inet6.c index f743ee8f..d3d58ade 100644 --- a/freebsd/sbin/ifconfig/af_inet6.c +++ b/freebsd/sbin/ifconfig/af_inet6.c @@ -250,7 +250,7 @@ in6_status(int s __unused, const struct ifaddrs *ifa) if (error != 0) inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, sizeof(addr_buf)); - printf(" --> %s ", addr_buf); + printf(" --> %s", addr_buf); } } diff --git a/freebsd/sbin/ifconfig/af_link.c b/freebsd/sbin/ifconfig/af_link.c index 1c37496e..5fa2545d 100644 --- a/freebsd/sbin/ifconfig/af_link.c +++ b/freebsd/sbin/ifconfig/af_link.c @@ -102,13 +102,24 @@ link_getaddr(const char *addr, int which) if (which != ADDR) errx(1, "can't set link-level netmask or broadcast"); - if ((temp = malloc(strlen(addr) + 2)) == NULL) - errx(1, "malloc failed"); - temp[0] = ':'; - strcpy(temp + 1, addr); - sdl.sdl_len = sizeof(sdl); - link_addr(temp, &sdl); - free(temp); + if (!strcmp(addr, "random")) { + sdl.sdl_len = sizeof(sdl); + sdl.sdl_alen = ETHER_ADDR_LEN; + sdl.sdl_nlen = 0; + sdl.sdl_family = AF_LINK; + arc4random_buf(&sdl.sdl_data, ETHER_ADDR_LEN); + /* Non-multicast and claim it is locally administered. */ + sdl.sdl_data[0] &= 0xfc; + sdl.sdl_data[0] |= 0x02; + } else { + if ((temp = malloc(strlen(addr) + 2)) == NULL) + errx(1, "malloc failed"); + temp[0] = ':'; + strcpy(temp + 1, addr); + sdl.sdl_len = sizeof(sdl); + link_addr(temp, &sdl); + free(temp); + } if (sdl.sdl_alen > sizeof(sa->sa_data)) errx(1, "malformed link-level address"); sa->sa_family = AF_LINK; diff --git a/freebsd/sbin/pfctl/parse.y b/freebsd/sbin/pfctl/parse.y index 33edd3e5..9664aaf5 100644 --- a/freebsd/sbin/pfctl/parse.y +++ b/freebsd/sbin/pfctl/parse.y @@ -367,6 +367,8 @@ void decide_address_family(struct node_host *, sa_family_t *); void remove_invalid_hosts(struct node_host **, sa_family_t *); int invalid_redirect(struct node_host *, sa_family_t); u_int16_t parseicmpspec(char *, sa_family_t); +int kw_casecmp(const void *, const void *); +int map_tos(char *string, int *); static TAILQ_HEAD(loadanchorshead, loadanchors) loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead); @@ -2346,7 +2348,7 @@ pfrule : action dir logquick interface route af proto fromto memcpy(&r.rpool.key, $5.key, sizeof(struct pf_poolhashkey)); } - if (r.rt && r.rt != PF_FASTROUTE) { + if (r.rt) { decide_address_family($5.host, &r.af); remove_invalid_hosts(&$5.host, &r.af); if ($5.host == NULL) { @@ -3600,15 +3602,17 @@ icmp6type : STRING { ; tos : STRING { - if (!strcmp($1, "lowdelay")) - $$ = IPTOS_LOWDELAY; - else if (!strcmp($1, "throughput")) - $$ = IPTOS_THROUGHPUT; - else if (!strcmp($1, "reliability")) - $$ = IPTOS_RELIABILITY; - else if ($1[0] == '0' && $1[1] == 'x') - $$ = strtoul($1, NULL, 16); - else + int val; + char *end; + + if (map_tos($1, &val)) + $$ = val; + else if ($1[0] == '0' && $1[1] == 'x') { + errno = 0; + $$ = strtoul($1, &end, 16); + if (errno || *end != '\0') + $$ = 256; + } else $$ = 256; /* flag bad argument */ if ($$ < 0 || $$ > 255) { yyerror("illegal tos value %s", $1); @@ -4432,8 +4436,9 @@ route : /* empty */ { $$.pool_opts = 0; } | FASTROUTE { + /* backwards-compat */ $$.host = NULL; - $$.rt = PF_FASTROUTE; + $$.rt = 0; $$.pool_opts = 0; } | ROUTETO routespec pool_opts { @@ -6269,6 +6274,57 @@ pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans) return (0); } +int +kw_casecmp(const void *k, const void *e) +{ + return (strcasecmp(k, ((const struct keywords *)e)->k_name)); +} + +int +map_tos(char *s, int *val) +{ + /* DiffServ Codepoints and other TOS mappings */ + const struct keywords toswords[] = { + { "af11", IPTOS_DSCP_AF11 }, + { "af12", IPTOS_DSCP_AF12 }, + { "af13", IPTOS_DSCP_AF13 }, + { "af21", IPTOS_DSCP_AF21 }, + { "af22", IPTOS_DSCP_AF22 }, + { "af23", IPTOS_DSCP_AF23 }, + { "af31", IPTOS_DSCP_AF31 }, + { "af32", IPTOS_DSCP_AF32 }, + { "af33", IPTOS_DSCP_AF33 }, + { "af41", IPTOS_DSCP_AF41 }, + { "af42", IPTOS_DSCP_AF42 }, + { "af43", IPTOS_DSCP_AF43 }, + { "critical", IPTOS_PREC_CRITIC_ECP }, + { "cs0", IPTOS_DSCP_CS0 }, + { "cs1", IPTOS_DSCP_CS1 }, + { "cs2", IPTOS_DSCP_CS2 }, + { "cs3", IPTOS_DSCP_CS3 }, + { "cs4", IPTOS_DSCP_CS4 }, + { "cs5", IPTOS_DSCP_CS5 }, + { "cs6", IPTOS_DSCP_CS6 }, + { "cs7", IPTOS_DSCP_CS7 }, + { "ef", IPTOS_DSCP_EF }, + { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, + { "lowdelay", IPTOS_LOWDELAY }, + { "netcontrol", IPTOS_PREC_NETCONTROL }, + { "reliability", IPTOS_RELIABILITY }, + { "throughput", IPTOS_THROUGHPUT } + }; + const struct keywords *p; + + p = bsearch(s, toswords, sizeof(toswords)/sizeof(toswords[0]), + sizeof(toswords[0]), kw_casecmp); + + if (p) { + *val = p->k_val; + return (1); + } + return (0); +} + int rt_tableid_max(void) { diff --git a/freebsd/sbin/pfctl/pfctl.c b/freebsd/sbin/pfctl/pfctl.c index ab597068..f9efa090 100644 --- a/freebsd/sbin/pfctl/pfctl.c +++ b/freebsd/sbin/pfctl/pfctl.c @@ -1364,7 +1364,7 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) else snprintf(&path[len], MAXPATHLEN - len, "%s", r->anchor->name); - name = path; + name = r->anchor->name; } else name = r->anchor->path; } else diff --git a/freebsd/sbin/pfctl/pfctl_optimize.c b/freebsd/sbin/pfctl/pfctl_optimize.c index b8f44e8b..89cebe91 100644 --- a/freebsd/sbin/pfctl/pfctl_optimize.c +++ b/freebsd/sbin/pfctl/pfctl_optimize.c @@ -103,7 +103,7 @@ TAILQ_HEAD(superblocks, superblock); * Description of the PF rule structure. */ enum { - BARRIER, /* the presence of the field puts the rule in it's own block */ + BARRIER, /* the presence of the field puts the rule in its own block */ BREAK, /* the field may not differ between rules in a superblock */ NOMERGE, /* the field may not differ between rules when combined */ COMBINED, /* the field may itself be combined with other rules */ @@ -127,7 +127,7 @@ static struct pf_rule_field pf_rule_desc[] = { /* - * The presence of these fields in a rule put the rule in it's own + * The presence of these fields in a rule put the rule in its own * superblock. Thus it will not be optimized. It also prevents the * rule from being re-ordered at all. */ diff --git a/freebsd/sbin/pfctl/pfctl_parser.c b/freebsd/sbin/pfctl/pfctl_parser.c index 0ff7deec..cb49dc2a 100644 --- a/freebsd/sbin/pfctl/pfctl_parser.c +++ b/freebsd/sbin/pfctl/pfctl_parser.c @@ -790,12 +790,8 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) printf(" reply-to"); else if (r->rt == PF_DUPTO) printf(" dup-to"); - else if (r->rt == PF_FASTROUTE) - printf(" fastroute"); - if (r->rt != PF_FASTROUTE) { - printf(" "); - print_pool(&r->rpool, 0, 0, r->af, PF_PASS); - } + printf(" "); + print_pool(&r->rpool, 0, 0, r->af, PF_PASS); } if (r->af) { if (r->af == AF_INET) diff --git a/freebsd/sbin/sysctl/sysctl.c b/freebsd/sbin/sysctl/sysctl.c index fdbecd5f..03069a38 100644 --- a/freebsd/sbin/sysctl/sysctl.c +++ b/freebsd/sbin/sysctl/sysctl.c @@ -677,9 +677,6 @@ S_vmtotal(size_t l2, void *p) } #ifdef __amd64__ -#define efi_next_descriptor(ptr, size) \ - ((struct efi_md *)(((uint8_t *) ptr) + size)) - static int S_efi_map(size_t l2, void *p) { diff --git a/freebsd/sys/arm/include/machine/cpufunc.h b/freebsd/sys/arm/include/machine/cpufunc.h index 911fc14c..8a9a2a84 100644 --- a/freebsd/sys/arm/include/machine/cpufunc.h +++ b/freebsd/sys/arm/include/machine/cpufunc.h @@ -60,7 +60,7 @@ breakpoint(void) struct cpu_functions { /* CPU functions */ - +#if __ARM_ARCH < 6 void (*cf_cpwait) (void); /* MMU functions */ @@ -140,6 +140,7 @@ struct cpu_functions { void (*cf_idcache_inv_all) (void); void (*cf_idcache_wbinv_all) (void); void (*cf_idcache_wbinv_range) (vm_offset_t, vm_size_t); +#endif void (*cf_l2cache_wbinv_all) (void); void (*cf_l2cache_wbinv_range) (vm_offset_t, vm_size_t); void (*cf_l2cache_inv_range) (vm_offset_t, vm_size_t); @@ -148,13 +149,17 @@ struct cpu_functions { /* Other functions */ +#if __ARM_ARCH < 6 void (*cf_drain_writebuf) (void); +#endif void (*cf_sleep) (int mode); +#if __ARM_ARCH < 6 /* Soft functions */ void (*cf_context_switch) (void); +#endif void (*cf_setup) (void); }; @@ -164,10 +169,8 @@ extern u_int cputype; #if __ARM_ARCH < 6 #define cpu_cpwait() cpufuncs.cf_cpwait() -#endif #define cpu_control(c, e) cpufuncs.cf_control(c, e) -#if __ARM_ARCH < 6 #define cpu_setttb(t) cpufuncs.cf_setttb(t) #define cpu_tlb_flushID() cpufuncs.cf_tlb_flushID() @@ -186,6 +189,7 @@ extern u_int cputype; #define cpu_idcache_wbinv_all() cpufuncs.cf_idcache_wbinv_all() #define cpu_idcache_wbinv_range(a, s) cpufuncs.cf_idcache_wbinv_range((a), (s)) #endif + #define cpu_l2cache_wbinv_all() cpufuncs.cf_l2cache_wbinv_all() #define cpu_l2cache_wb_range(a, s) cpufuncs.cf_l2cache_wb_range((a), (s)) #define cpu_l2cache_inv_range(a, s) cpufuncs.cf_l2cache_inv_range((a), (s)) @@ -274,26 +278,12 @@ void sheeva_l2cache_wbinv_all (void); #if defined(CPU_MV_PJ4B) void armv6_idcache_wbinv_all (void); #endif -#if defined(CPU_MV_PJ4B) || defined(CPU_CORTEXA) || defined(CPU_KRAIT) -void armv7_setttb (u_int); -void armv7_tlb_flushID (void); -void armv7_tlb_flushID_SE (u_int); -void armv7_icache_sync_range (vm_offset_t, vm_size_t); -void armv7_idcache_wbinv_range (vm_offset_t, vm_size_t); -void armv7_idcache_inv_all (void); -void armv7_dcache_wbinv_all (void); +#if defined(CPU_CORTEXA8) || defined(CPU_CORTEXA_MP) || \ + defined(CPU_MV_PJ4B) || defined(CPU_KRAIT) void armv7_idcache_wbinv_all (void); -void armv7_dcache_wbinv_range (vm_offset_t, vm_size_t); -void armv7_dcache_inv_range (vm_offset_t, vm_size_t); -void armv7_dcache_wb_range (vm_offset_t, vm_size_t); void armv7_cpu_sleep (int); void armv7_setup (void); -void armv7_context_switch (void); void armv7_drain_writebuf (void); -void armv7_sev (void); -u_int armv7_auxctrl (u_int, u_int); - -void armadaxp_idcache_wbinv_all (void); void cortexa_setup (void); #endif @@ -303,26 +293,8 @@ void pj4bv7_setup (void); #endif #if defined(CPU_ARM1176) -void arm11_tlb_flushID (void); -void arm11_tlb_flushID_SE (u_int); -void arm11_tlb_flushD (void); -void arm11_tlb_flushD_SE (u_int va); - -void arm11_context_switch (void); - void arm11_drain_writebuf (void); -void armv6_dcache_wbinv_range (vm_offset_t, vm_size_t); -void armv6_dcache_inv_range (vm_offset_t, vm_size_t); -void armv6_dcache_wb_range (vm_offset_t, vm_size_t); - -void armv6_idcache_inv_all (void); - -void arm11x6_setttb (u_int); -void arm11x6_idcache_wbinv_all (void); -void arm11x6_dcache_wbinv_all (void); -void arm11x6_icache_sync_range (vm_offset_t, vm_size_t); -void arm11x6_idcache_wbinv_range (vm_offset_t, vm_size_t); void arm11x6_setup (void); void arm11x6_sleep (int); /* no ref. for errata */ #endif diff --git a/freebsd/sys/arm/xilinx/zy7_slcr.c b/freebsd/sys/arm/xilinx/zy7_slcr.c index 7ce502f9..dc6475c0 100644 --- a/freebsd/sys/arm/xilinx/zy7_slcr.c +++ b/freebsd/sys/arm/xilinx/zy7_slcr.c @@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$"); #include #ifndef __rtems__ -#include #include #include #endif /* __rtems__ */ @@ -639,8 +638,8 @@ zy7_slcr_attach(device_t dev) /* Derive PLL frequencies from PS_CLK. */ #ifndef __rtems__ node = ofw_bus_get_node(dev); - if (OF_getprop(node, "clock-frequency", &cell, sizeof(cell)) > 0) - ps_clk_frequency = fdt32_to_cpu(cell); + if (OF_getencprop(node, "clock-frequency", &cell, sizeof(cell)) > 0) + ps_clk_frequency = cell; else #endif /* __rtems__ */ ps_clk_frequency = ZYNQ_DEFAULT_PS_CLK_FREQUENCY; diff --git a/freebsd/sys/cam/cam.h b/freebsd/sys/cam/cam.h index 5eb0a776..23feb508 100644 --- a/freebsd/sys/cam/cam.h +++ b/freebsd/sys/cam/cam.h @@ -294,7 +294,7 @@ typedef enum { /* SIM ready to take more commands */ CAM_RELEASE_SIMQ = 0x100, - /* SIM has this command in it's queue */ + /* SIM has this command in its queue */ CAM_SIM_QUEUED = 0x200, /* Quality of service data is valid */ diff --git a/freebsd/sys/cam/cam_ccb.h b/freebsd/sys/cam/cam_ccb.h index e00b5bd3..d9b91f8d 100644 --- a/freebsd/sys/cam/cam_ccb.h +++ b/freebsd/sys/cam/cam_ccb.h @@ -757,6 +757,9 @@ struct ccb_scsiio { #define CAM_TAG_ACTION_NONE 0x00 u_int tag_id; /* tag id from initator (target mode) */ u_int init_id; /* initiator id of who selected */ +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + struct bio *bio; /* Associated bio */ +#endif #ifdef __rtems__ int readop; rtems_blkdev_sg_buffer *sg_current; @@ -1358,6 +1361,9 @@ cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries, csio->sense_len = sense_len; csio->cdb_len = cdb_len; csio->tag_action = tag_action; +#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING) + csio->bio = NULL; +#endif } static __inline void diff --git a/freebsd/sys/cam/cam_periph.h b/freebsd/sys/cam/cam_periph.h index e28d5b11..d5a74a51 100644 --- a/freebsd/sys/cam/cam_periph.h +++ b/freebsd/sys/cam/cam_periph.h @@ -166,7 +166,6 @@ void cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo); union ccb *cam_periph_getccb(struct cam_periph *periph, u_int32_t priority); -void cam_periph_ccbwait(union ccb *ccb); int cam_periph_runccb(union ccb *ccb, int (*error_routine)(union ccb *ccb, cam_flags camflags, diff --git a/freebsd/sys/cam/scsi/scsi_all.c b/freebsd/sys/cam/scsi/scsi_all.c index 0cb7118a..9e8924c5 100644 --- a/freebsd/sys/cam/scsi/scsi_all.c +++ b/freebsd/sys/cam/scsi/scsi_all.c @@ -1063,7 +1063,7 @@ static struct asc_table_entry asc_table[] = { { SST(0x00, 0x1C, SS_RDEF, /* XXX TBD */ "Verify operation in progress") }, /* DT B */ - { SST(0x00, 0x1D, SS_RDEF, /* XXX TBD */ + { SST(0x00, 0x1D, SS_NOP, "ATA pass through information available") }, /* DT R MAEBKV */ { SST(0x00, 0x1E, SS_RDEF, /* XXX TBD */ @@ -1072,7 +1072,7 @@ static struct asc_table_entry asc_table[] = { { SST(0x00, 0x1F, SS_RDEF, /* XXX TBD */ "Logical unit transitioning to another power condition") }, /* DT P B */ - { SST(0x00, 0x20, SS_RDEF, /* XXX TBD */ + { SST(0x00, 0x20, SS_NOP, "Extended copy information available") }, /* D */ { SST(0x00, 0x21, SS_RDEF, /* XXX TBD */ @@ -2338,7 +2338,7 @@ static struct asc_table_entry asc_table[] = { { SST(0x43, 0x00, SS_RDEF, "Message error") }, /* DTLPWROMAEBKVF */ - { SST(0x44, 0x00, SS_RDEF, + { SST(0x44, 0x00, SS_FATAL | EIO, "Internal target failure") }, /* DT P MAEBKVF */ { SST(0x44, 0x01, SS_RDEF, /* XXX TBD */ @@ -3199,10 +3199,10 @@ static struct asc_table_entry asc_table[] = { { SST(0x74, 0x6F, SS_RDEF, /* XXX TBD */ "External data encryption control error") }, /* DT R M E V */ - { SST(0x74, 0x71, SS_RDEF, /* XXX TBD */ + { SST(0x74, 0x71, SS_FATAL | EACCES, "Logical unit access not authorized") }, /* D */ - { SST(0x74, 0x79, SS_RDEF, /* XXX TBD */ + { SST(0x74, 0x79, SS_FATAL | EACCES, "Security conflict in translated device") } }; @@ -4661,6 +4661,53 @@ scsi_sense_progress_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, scsi_progress_sbuf(sb, progress_val); } +void +scsi_sense_ata_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, + u_int sense_len, uint8_t *cdb, int cdb_len, + struct scsi_inquiry_data *inq_data, + struct scsi_sense_desc_header *header) +{ + struct scsi_sense_ata_ret_desc *res; + + res = (struct scsi_sense_ata_ret_desc *)header; + + sbuf_printf(sb, "ATA status: %02x (%s%s%s%s%s%s%s%s), ", + res->status, + (res->status & 0x80) ? "BSY " : "", + (res->status & 0x40) ? "DRDY " : "", + (res->status & 0x20) ? "DF " : "", + (res->status & 0x10) ? "SERV " : "", + (res->status & 0x08) ? "DRQ " : "", + (res->status & 0x04) ? "CORR " : "", + (res->status & 0x02) ? "IDX " : "", + (res->status & 0x01) ? "ERR" : ""); + if (res->status & 1) { + sbuf_printf(sb, "error: %02x (%s%s%s%s%s%s%s%s), ", + res->error, + (res->error & 0x80) ? "ICRC " : "", + (res->error & 0x40) ? "UNC " : "", + (res->error & 0x20) ? "MC " : "", + (res->error & 0x10) ? "IDNF " : "", + (res->error & 0x08) ? "MCR " : "", + (res->error & 0x04) ? "ABRT " : "", + (res->error & 0x02) ? "NM " : "", + (res->error & 0x01) ? "ILI" : ""); + } + + if (res->flags & SSD_DESC_ATA_FLAG_EXTEND) { + sbuf_printf(sb, "count: %02x%02x, ", + res->count_15_8, res->count_7_0); + sbuf_printf(sb, "LBA: %02x%02x%02x%02x%02x%02x, ", + res->lba_47_40, res->lba_39_32, res->lba_31_24, + res->lba_23_16, res->lba_15_8, res->lba_7_0); + } else { + sbuf_printf(sb, "count: %02x, ", res->count_7_0); + sbuf_printf(sb, "LBA: %02x%02x%02x, ", + res->lba_23_16, res->lba_15_8, res->lba_7_0); + } + sbuf_printf(sb, "device: %02x, ", res->device); +} + /* * Generic sense descriptor printing routine. This is used when we have * not yet implemented a specific printing routine for this descriptor. @@ -4707,6 +4754,7 @@ struct scsi_sense_desc_printer { {SSD_DESC_FRU, scsi_sense_fru_sbuf}, {SSD_DESC_STREAM, scsi_sense_stream_sbuf}, {SSD_DESC_BLOCK, scsi_sense_block_sbuf}, + {SSD_DESC_ATA, scsi_sense_ata_sbuf}, {SSD_DESC_PROGRESS, scsi_sense_progress_sbuf} }; @@ -7913,6 +7961,32 @@ scsi_report_target_group(struct ccb_scsiio *csio, u_int32_t retries, scsi_ulto4b(alloc_len, scsi_cmd->length); } +void +scsi_report_timestamp(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, u_int8_t pdf, + void *buf, u_int32_t alloc_len, + u_int8_t sense_len, u_int32_t timeout) +{ + struct scsi_timestamp *scsi_cmd; + + cam_fill_csio(csio, + retries, + cbfcnp, + /*flags*/CAM_DIR_IN, + tag_action, + /*data_ptr*/(u_int8_t *)buf, + /*dxfer_len*/alloc_len, + sense_len, + sizeof(*scsi_cmd), + timeout); + scsi_cmd = (struct scsi_timestamp *)&csio->cdb_io.cdb_bytes; + bzero(scsi_cmd, sizeof(*scsi_cmd)); + scsi_cmd->opcode = MAINTENANCE_IN; + scsi_cmd->service_action = REPORT_TIMESTAMP | pdf; + scsi_ulto4b(alloc_len, scsi_cmd->length); +} + void scsi_set_target_group(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), @@ -7938,6 +8012,45 @@ scsi_set_target_group(struct ccb_scsiio *csio, u_int32_t retries, scsi_ulto4b(alloc_len, scsi_cmd->length); } +void +scsi_create_timestamp(uint8_t *timestamp_6b_buf, + uint64_t timestamp) +{ + uint8_t buf[8]; + scsi_u64to8b(timestamp, buf); + /* + * Using memcopy starting at buf[2] because the set timestamp parameters + * only has six bytes for the timestamp to fit into, and we don't have a + * scsi_u64to6b function. + */ + memcpy(timestamp_6b_buf, &buf[2], 6); +} + +void +scsi_set_timestamp(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + u_int8_t tag_action, void *buf, u_int32_t alloc_len, + u_int8_t sense_len, u_int32_t timeout) +{ + struct scsi_timestamp *scsi_cmd; + + cam_fill_csio(csio, + retries, + cbfcnp, + /*flags*/CAM_DIR_OUT, + tag_action, + /*data_ptr*/(u_int8_t *) buf, + /*dxfer_len*/alloc_len, + sense_len, + sizeof(*scsi_cmd), + timeout); + scsi_cmd = (struct scsi_timestamp *)&csio->cdb_io.cdb_bytes; + bzero(scsi_cmd, sizeof(*scsi_cmd)); + scsi_cmd->opcode = MAINTENANCE_OUT; + scsi_cmd->service_action = SET_TIMESTAMP; + scsi_ulto4b(alloc_len, scsi_cmd->length); +} + /* * Syncronize the media to the contents of the cache for * the given lba/count pair. Specifying 0/0 means sync diff --git a/freebsd/sys/cam/scsi/scsi_all.h b/freebsd/sys/cam/scsi/scsi_all.h index 1fd45405..9c1376cf 100644 --- a/freebsd/sys/cam/scsi/scsi_all.h +++ b/freebsd/sys/cam/scsi/scsi_all.h @@ -702,7 +702,9 @@ struct scsi_control_page { struct scsi_control_ext_page { uint8_t page_code; +#define SCEP_PAGE_CODE 0x0a uint8_t subpage_code; +#define SCEP_SUBPAGE_CODE 0x01 uint8_t page_length[2]; uint8_t flags; #define SCEP_TCMOS 0x04 /* Timestamp Changeable by */ @@ -2971,6 +2973,31 @@ struct scsi_target_group uint8_t control; }; +struct scsi_timestamp +{ + uint8_t opcode; + uint8_t service_action; + uint8_t reserved1[4]; + uint8_t length[4]; + uint8_t reserved2; + uint8_t control; +}; + +struct scsi_set_timestamp_parameters +{ + uint8_t reserved1[4]; + uint8_t timestamp[6]; + uint8_t reserved2[4]; +}; + +struct scsi_report_timestamp_parameter_data +{ + uint8_t length[2]; + uint8_t reserved1[2]; + uint8_t timestamp[6]; + uint8_t reserved2[2]; +}; + struct scsi_target_port_descriptor { uint8_t reserved[2]; uint8_t relative_target_port_identifier[2]; @@ -3682,6 +3709,10 @@ void scsi_sense_progress_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, u_int sense_len, uint8_t *cdb, int cdb_len, struct scsi_inquiry_data *inq_data, struct scsi_sense_desc_header *header); +void scsi_sense_ata_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, + u_int sense_len, uint8_t *cdb, int cdb_len, + struct scsi_inquiry_data *inq_data, + struct scsi_sense_desc_header *header); void scsi_sense_generic_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, u_int sense_len, uint8_t *cdb, int cdb_len, struct scsi_inquiry_data *inq_data, @@ -3962,12 +3993,29 @@ void scsi_report_target_group(struct ccb_scsiio *csio, u_int32_t retries, u_int32_t alloc_len, u_int8_t sense_len, u_int32_t timeout); +void scsi_report_timestamp(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, + union ccb *), u_int8_t tag_action, + u_int8_t pdf, + void *buf, + u_int32_t alloc_len, u_int8_t sense_len, + u_int32_t timeout); + void scsi_set_target_group(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, void *buf, u_int32_t alloc_len, u_int8_t sense_len, u_int32_t timeout); +void scsi_create_timestamp(uint8_t *timestamp_6b_buf, + uint64_t timestamp); + +void scsi_set_timestamp(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, + union ccb *), u_int8_t tag_action, + void *buf, u_int32_t alloc_len, + u_int8_t sense_len, u_int32_t timeout); + void scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, diff --git a/freebsd/sys/crypto/sha1.h b/freebsd/sys/crypto/sha1.h index d61709e2..c1bc1a3a 100644 --- a/freebsd/sys/crypto/sha1.h +++ b/freebsd/sys/crypto/sha1.h @@ -61,7 +61,7 @@ typedef struct sha1_ctxt SHA1_CTX; extern void sha1_init(struct sha1_ctxt *); extern void sha1_pad(struct sha1_ctxt *); extern void sha1_loop(struct sha1_ctxt *, const u_int8_t *, size_t); -extern void sha1_result(struct sha1_ctxt *, char[static SHA1_RESULTLEN]); +extern void sha1_result(struct sha1_ctxt *, char[__min_size(SHA1_RESULTLEN)]); /* compatibilty with other SHA1 source codes */ #define SHA1Init(x) sha1_init((x)) diff --git a/freebsd/sys/crypto/sha2/sha256.h b/freebsd/sys/crypto/sha2/sha256.h index 17aae7de..bd31a621 100644 --- a/freebsd/sys/crypto/sha2/sha256.h +++ b/freebsd/sys/crypto/sha2/sha256.h @@ -59,6 +59,12 @@ __BEGIN_DECLS #ifndef SHA256_End #define SHA256_End _libmd_SHA256_End #endif +#ifndef SHA256_Fd +#define SHA256_Fd _libmd_SHA256_Fd +#endif +#ifndef SHA256_FdChunk +#define SHA256_FdChunk _libmd_SHA256_FdChunk +#endif #ifndef SHA256_File #define SHA256_File _libmd_SHA256_File #endif @@ -78,10 +84,13 @@ __BEGIN_DECLS void SHA256_Init(SHA256_CTX *); void SHA256_Update(SHA256_CTX *, const void *, size_t); -void SHA256_Final(unsigned char [static SHA256_DIGEST_LENGTH], SHA256_CTX *); +void SHA256_Final(unsigned char [__min_size(SHA256_DIGEST_LENGTH)], + SHA256_CTX *); #ifndef _KERNEL char *SHA256_End(SHA256_CTX *, char *); char *SHA256_Data(const void *, unsigned int, char *); +char *SHA256_Fd(int, char *); +char *SHA256_FdChunk(int, char *, off_t, off_t); char *SHA256_File(const char *, char *); char *SHA256_FileChunk(const char *, char *, off_t, off_t); #endif diff --git a/freebsd/sys/crypto/sha2/sha384.h b/freebsd/sys/crypto/sha2/sha384.h index 63dd948b..01345592 100644 --- a/freebsd/sys/crypto/sha2/sha384.h +++ b/freebsd/sys/crypto/sha2/sha384.h @@ -58,6 +58,12 @@ __BEGIN_DECLS #ifndef SHA384_End #define SHA384_End _libmd_SHA384_End #endif +#ifndef SHA384_Fd +#define SHA384_Fd _libmd_SHA384_Fd +#endif +#ifndef SHA384_FdChunk +#define SHA384_FdChunk _libmd_SHA384_FdChunk +#endif #ifndef SHA384_File #define SHA384_File _libmd_SHA384_File #endif @@ -74,10 +80,13 @@ __BEGIN_DECLS void SHA384_Init(SHA384_CTX *); void SHA384_Update(SHA384_CTX *, const void *, size_t); -void SHA384_Final(unsigned char [static SHA384_DIGEST_LENGTH], SHA384_CTX *); +void SHA384_Final(unsigned char [__min_size(SHA384_DIGEST_LENGTH)], + SHA384_CTX *); #ifndef _KERNEL char *SHA384_End(SHA384_CTX *, char *); char *SHA384_Data(const void *, unsigned int, char *); +char *SHA384_Fd(int, char *); +char *SHA384_FdChunk(int, char *, off_t, off_t); char *SHA384_File(const char *, char *); char *SHA384_FileChunk(const char *, char *, off_t, off_t); #endif diff --git a/freebsd/sys/crypto/sha2/sha512.h b/freebsd/sys/crypto/sha2/sha512.h index b008aeae..8b3e17cc 100644 --- a/freebsd/sys/crypto/sha2/sha512.h +++ b/freebsd/sys/crypto/sha2/sha512.h @@ -58,6 +58,12 @@ __BEGIN_DECLS #ifndef SHA512_End #define SHA512_End _libmd_SHA512_End #endif +#ifndef SHA512_Fd +#define SHA512_Fd _libmd_SHA512_Fd +#endif +#ifndef SHA512_FdChunk +#define SHA512_FdChunk _libmd_SHA512_FdChunk +#endif #ifndef SHA512_File #define SHA512_File _libmd_SHA512_File #endif @@ -77,10 +83,13 @@ __BEGIN_DECLS void SHA512_Init(SHA512_CTX *); void SHA512_Update(SHA512_CTX *, const void *, size_t); -void SHA512_Final(unsigned char [static SHA512_DIGEST_LENGTH], SHA512_CTX *); +void SHA512_Final(unsigned char [__min_size(SHA512_DIGEST_LENGTH)], + SHA512_CTX *); #ifndef _KERNEL char *SHA512_End(SHA512_CTX *, char *); char *SHA512_Data(const void *, unsigned int, char *); +char *SHA512_Fd(int, char *); +char *SHA512_FdChunk(int, char *, off_t, off_t); char *SHA512_File(const char *, char *); char *SHA512_FileChunk(const char *, char *, off_t, off_t); #endif diff --git a/freebsd/sys/crypto/sha2/sha512t.h b/freebsd/sys/crypto/sha2/sha512t.h index 3f0c921f..1ae490f5 100644 --- a/freebsd/sys/crypto/sha2/sha512t.h +++ b/freebsd/sys/crypto/sha2/sha512t.h @@ -55,6 +55,12 @@ __BEGIN_DECLS #ifndef SHA512_224_End #define SHA512_224_End _libmd_SHA512_224_End #endif +#ifndef SHA512_224_Fd +#define SHA512_224_Fd _libmd_SHA512_224_Fd +#endif +#ifndef SHA512_224_FdChunk +#define SHA512_224_FdChunk _libmd_SHA512_224_FdChunk +#endif #ifndef SHA512_224_File #define SHA512_224_File _libmd_SHA512_224_File #endif @@ -84,6 +90,12 @@ __BEGIN_DECLS #ifndef SHA512_256_End #define SHA512_256_End _libmd_SHA512_256_End #endif +#ifndef SHA512_256_Fd +#define SHA512_256_Fd _libmd_SHA512_256_Fd +#endif +#ifndef SHA512_256_FdChunk +#define SHA512_256_FdChunk _libmd_SHA512_256_FdChunk +#endif #ifndef SHA512_256_File #define SHA512_256_File _libmd_SHA512_256_File #endif @@ -103,19 +115,25 @@ __BEGIN_DECLS void SHA512_224_Init(SHA512_CTX *); void SHA512_224_Update(SHA512_CTX *, const void *, size_t); -void SHA512_224_Final(unsigned char [static SHA512_224_DIGEST_LENGTH], SHA512_CTX *); +void SHA512_224_Final(unsigned char [__min_size(SHA512_224_DIGEST_LENGTH)], + SHA512_CTX *); #ifndef _KERNEL char *SHA512_224_End(SHA512_CTX *, char *); char *SHA512_224_Data(const void *, unsigned int, char *); +char *SHA512_224_Fd(int, char *); +char *SHA512_224_FdChunk(int, char *, off_t, off_t); char *SHA512_224_File(const char *, char *); char *SHA512_224_FileChunk(const char *, char *, off_t, off_t); #endif void SHA512_256_Init(SHA512_CTX *); void SHA512_256_Update(SHA512_CTX *, const void *, size_t); -void SHA512_256_Final(unsigned char [static SHA512_256_DIGEST_LENGTH], SHA512_CTX *); +void SHA512_256_Final(unsigned char [__min_size(SHA512_256_DIGEST_LENGTH)], + SHA512_CTX *); #ifndef _KERNEL char *SHA512_256_End(SHA512_CTX *, char *); char *SHA512_256_Data(const void *, unsigned int, char *); +char *SHA512_256_Fd(int, char *); +char *SHA512_256_FdChunk(int, char *, off_t, off_t); char *SHA512_256_File(const char *, char *); char *SHA512_256_FileChunk(const char *, char *, off_t, off_t); #endif diff --git a/freebsd/sys/crypto/siphash/siphash.h b/freebsd/sys/crypto/siphash/siphash.h index 8bbda4f3..235818b5 100644 --- a/freebsd/sys/crypto/siphash/siphash.h +++ b/freebsd/sys/crypto/siphash/siphash.h @@ -68,15 +68,16 @@ typedef struct _SIPHASH_CTX { #define SipHash24_Init(x) SipHash_InitX((x), 2, 4) #define SipHash48_Init(x) SipHash_InitX((x), 4, 8) void SipHash_InitX(SIPHASH_CTX *, int, int); -void SipHash_SetKey(SIPHASH_CTX *, const uint8_t[static SIPHASH_KEY_LENGTH]); +void SipHash_SetKey(SIPHASH_CTX *, + const uint8_t[__min_size(SIPHASH_KEY_LENGTH)]); void SipHash_Update(SIPHASH_CTX *, const void *, size_t); -void SipHash_Final(uint8_t[static SIPHASH_DIGEST_LENGTH], SIPHASH_CTX *); +void SipHash_Final(uint8_t[__min_size(SIPHASH_DIGEST_LENGTH)], SIPHASH_CTX *); uint64_t SipHash_End(SIPHASH_CTX *); #define SipHash24(x, y, z, i) SipHashX((x), 2, 4, (y), (z), (i)); #define SipHash48(x, y, z, i) SipHashX((x), 4, 8, (y), (z), (i)); -uint64_t SipHashX(SIPHASH_CTX *, int, int, const uint8_t[static SIPHASH_KEY_LENGTH], const void *, - size_t); +uint64_t SipHashX(SIPHASH_CTX *, int, int, + const uint8_t[__min_size(SIPHASH_KEY_LENGTH)], const void *, size_t); int SipHash24_TestVectors(void); diff --git a/freebsd/sys/crypto/skein/skein_freebsd.h b/freebsd/sys/crypto/skein/skein_freebsd.h index 935fa090..676b79bc 100644 --- a/freebsd/sys/crypto/skein/skein_freebsd.h +++ b/freebsd/sys/crypto/skein/skein_freebsd.h @@ -57,9 +57,12 @@ void SKEIN256_Update(SKEIN256_CTX *ctx, const void *in, size_t len); void SKEIN512_Update(SKEIN512_CTX *ctx, const void *in, size_t len); void SKEIN1024_Update(SKEIN1024_CTX *ctx, const void *in, size_t len); -void SKEIN256_Final(unsigned char digest[static SKEIN256_DIGEST_LENGTH], SKEIN256_CTX *ctx); -void SKEIN512_Final(unsigned char digest[static SKEIN512_DIGEST_LENGTH], SKEIN512_CTX *ctx); -void SKEIN1024_Final(unsigned char digest[static SKEIN1024_DIGEST_LENGTH], SKEIN1024_CTX *ctx); +void SKEIN256_Final(unsigned char digest[__min_size(SKEIN256_DIGEST_LENGTH)], + SKEIN256_CTX *ctx); +void SKEIN512_Final(unsigned char digest[__min_size(SKEIN512_DIGEST_LENGTH)], + SKEIN512_CTX *ctx); +void SKEIN1024_Final(unsigned char digest[__min_size(SKEIN1024_DIGEST_LENGTH)], + SKEIN1024_CTX *ctx); #ifndef _KERNEL char *SKEIN256_End(SKEIN256_CTX *, char *); @@ -68,6 +71,12 @@ char *SKEIN1024_End(SKEIN1024_CTX *, char *); char *SKEIN256_Data(const void *, unsigned int, char *); char *SKEIN512_Data(const void *, unsigned int, char *); char *SKEIN1024_Data(const void *, unsigned int, char *); +char *SKEIN256_Fd(int, char *); +char *SKEIN512_Fd(int, char *); +char *SKEIN1024_Fd(int, char *); +char *SKEIN256_FdChunk(int, char *, off_t, off_t); +char *SKEIN512_FdChunk(int, char *, off_t, off_t); +char *SKEIN1024_FdChunk(int, char *, off_t, off_t); char *SKEIN256_File(const char *, char *); char *SKEIN512_File(const char *, char *); char *SKEIN1024_File(const char *, char *); diff --git a/freebsd/sys/crypto/skein/skein_port.h b/freebsd/sys/crypto/skein/skein_port.h index 7025a516..ab320b29 100644 --- a/freebsd/sys/crypto/skein/skein_port.h +++ b/freebsd/sys/crypto/skein/skein_port.h @@ -137,6 +137,16 @@ void Skein_Get64_LSB_First(u64b_t *dst,const u08b_t *src,size_t wCnt) #define SKEIN512_End _libmd_SKEIN512_End #define SKEIN1024_End _libmd_SKEIN1024_End #endif +#ifndef SKEIN256_Fd +#define SKEIN256_Fd _libmd_SKEIN256_Fd +#define SKEIN512_Fd _libmd_SKEIN512_Fd +#define SKEIN1024_Fd _libmd_SKEIN1024_Fd +#endif +#ifndef SKEIN256_FdChunk +#define SKEIN256_FdChunk _libmd_SKEIN256_FdChunk +#define SKEIN512_FdChunk _libmd_SKEIN512_FdChunk +#define SKEIN1024_FdChunk _libmd_SKEIN1024_FdChunk +#endif #ifndef SKEIN256_File #define SKEIN256_File _libmd_SKEIN256_File #define SKEIN512_File _libmd_SKEIN512_File diff --git a/freebsd/sys/dev/bfe/if_bfe.c b/freebsd/sys/dev/bfe/if_bfe.c index c87dea13..a76bc7ee 100644 --- a/freebsd/sys/dev/bfe/if_bfe.c +++ b/freebsd/sys/dev/bfe/if_bfe.c @@ -795,6 +795,8 @@ bfe_list_newbuf(struct bfe_softc *sc, int c) int nsegs; m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); + if (m == NULL) + return (ENOBUFS); m->m_len = m->m_pkthdr.len = MCLBYTES; if (bus_dmamap_load_mbuf_sg(sc->bfe_rxmbuf_tag, sc->bfe_rx_sparemap, diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c index fa34dd62..d8c1e5a6 100644 --- a/freebsd/sys/dev/e1000/if_em.c +++ b/freebsd/sys/dev/e1000/if_em.c @@ -367,16 +367,10 @@ MODULE_DEPEND(em, netmap, 1, 1, 1); #define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000) #define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024) -#define M_TSO_LEN 66 #define MAX_INTS_PER_SEC 8000 #define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256)) -/* Allow common code without TSO */ -#ifndef CSUM_TSO -#define CSUM_TSO 0 -#endif - #define TSO_WORKAROUND 4 static SYSCTL_NODE(_hw, OID_AUTO, em, CTLFLAG_RD, 0, "EM driver parameters"); @@ -1399,15 +1393,9 @@ em_init_locked(struct adapter *adapter) if_clearhwassist(ifp); if (if_getcapenable(ifp) & IFCAP_TXCSUM) if_sethwassistbits(ifp, CSUM_TCP | CSUM_UDP, 0); - /* - ** There have proven to be problems with TSO when not - ** at full gigabit speed, so disable the assist automatically - ** when at lower speeds. -jfv - */ - if (if_getcapenable(ifp) & IFCAP_TSO4) { - if (adapter->link_speed == SPEED_1000) - if_sethwassistbits(ifp, CSUM_TSO, 0); - } + + if (if_getcapenable(ifp) & IFCAP_TSO4) + if_sethwassistbits(ifp, CSUM_TSO, 0); /* Configure for OS presence */ em_init_manageability(adapter); @@ -2415,6 +2403,18 @@ em_update_link_status(struct adapter *adapter) if (link_check && (adapter->link_active == 0)) { e1000_get_speed_and_duplex(hw, &adapter->link_speed, &adapter->link_duplex); + /* + ** There have proven to be problems with TSO when not + ** at full gigabit speed, so disable the assist automatically + ** when at lower speeds. -jfv + */ + if (adapter->link_speed != SPEED_1000) { + if_sethwassistbits(ifp, 0, CSUM_TSO); + if_setcapenablebit(ifp, 0, IFCAP_TSO4); + if_setcapabilitiesbit(ifp, 0, IFCAP_TSO4); + + } + /* Check if we must disable SPEED_MODE bit on PCI-E */ if ((adapter->link_speed != SPEED_1000) && ((hw->mac.type == e1000_82571) || @@ -5276,6 +5276,8 @@ em_get_wakeup(device_t dev) case e1000_ich10lan: case e1000_pchlan: case e1000_pch2lan: + case e1000_pch_lpt: + case e1000_pch_spt: apme_mask = E1000_WUC_APME; adapter->has_amt = TRUE; eeprom_data = E1000_READ_REG(&adapter->hw, E1000_WUC); @@ -5324,7 +5326,7 @@ em_enable_wakeup(device_t dev) { struct adapter *adapter = device_get_softc(dev); if_t ifp = adapter->ifp; - u32 pmc, ctrl, ctrl_ext, rctl; + u32 pmc, ctrl, ctrl_ext, rctl, wuc; u16 status; if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0)) @@ -5334,7 +5336,9 @@ em_enable_wakeup(device_t dev) ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3); E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); - E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN); + wuc = E1000_READ_REG(&adapter->hw, E1000_WUC); + wuc |= E1000_WUC_PME_EN; + E1000_WRITE_REG(&adapter->hw, E1000_WUC, wuc); if ((adapter->hw.mac.type == e1000_ich8lan) || (adapter->hw.mac.type == e1000_pchlan) || @@ -5365,8 +5369,10 @@ em_enable_wakeup(device_t dev) E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl); } - if ((adapter->hw.mac.type == e1000_pchlan) || - (adapter->hw.mac.type == e1000_pch2lan)) { + if ((adapter->hw.mac.type == e1000_pchlan) || + (adapter->hw.mac.type == e1000_pch2lan) || + (adapter->hw.mac.type == e1000_pch_lpt) || + (adapter->hw.mac.type == e1000_pch_spt)) { if (em_enable_phy_wakeup(adapter)) return; } else { diff --git a/freebsd/sys/dev/e1000/if_igb.c b/freebsd/sys/dev/e1000/if_igb.c index d683b85f..2e9c7259 100644 --- a/freebsd/sys/dev/e1000/if_igb.c +++ b/freebsd/sys/dev/e1000/if_igb.c @@ -592,11 +592,20 @@ igb_attach(device_t dev) error = EIO; goto err_late; } - /* Check its sanity */ - if (!igb_is_valid_ether_addr(adapter->hw.mac.addr)) { - device_printf(dev, "Invalid MAC address\n"); - error = EIO; - goto err_late; + + /* Check its sanity */ + if (!igb_is_valid_ether_addr(adapter->hw.mac.addr)) { + if (adapter->vf_ifp) { + u8 addr[ETHER_ADDR_LEN]; + arc4rand(&addr, sizeof(addr), 0); + addr[0] &= 0xFE; + addr[0] |= 0x02; + bcopy(addr, adapter->hw.mac.addr, sizeof(addr)); + } else { + device_printf(dev, "Invalid MAC address\n"); + error = EIO; + goto err_late; + } } /* Setup OS specific network interface */ diff --git a/freebsd/sys/dev/e1000/if_lem.c b/freebsd/sys/dev/e1000/if_lem.c index c46c3728..b3da1bdd 100644 --- a/freebsd/sys/dev/e1000/if_lem.c +++ b/freebsd/sys/dev/e1000/if_lem.c @@ -41,7 +41,6 @@ */ // #define BATCH_DISPATCH // #define NIC_SEND_COMBINING -// #define NIC_PARAVIRT /* enable virtio-like synchronization */ #include #include @@ -488,10 +487,6 @@ lem_attach(device_t dev) lem_add_rx_process_limit(adapter, "batch_enable", "driver rx batch", &adapter->batch_enable, 0); #endif /* BATCH_DISPATCH */ -#ifdef NIC_PARAVIRT - lem_add_rx_process_limit(adapter, "rx_retries", - "driver rx retries", &adapter->rx_retries, 0); -#endif /* NIC_PARAVIRT */ /* Sysctl for setting the interface flow control */ lem_set_flow_cntrl(adapter, "flow_control", @@ -550,51 +545,16 @@ lem_attach(device_t dev) */ adapter->hw.mac.report_tx_early = 1; -#ifdef NIC_PARAVIRT - device_printf(dev, "driver supports paravirt, subdev 0x%x\n", - adapter->hw.subsystem_device_id); - if (adapter->hw.subsystem_device_id == E1000_PARA_SUBDEV) { - uint64_t bus_addr; - - device_printf(dev, "paravirt support on dev %p\n", adapter); - tsize = 4096; // XXX one page for the csb - if (lem_dma_malloc(adapter, tsize, &adapter->csb_mem, BUS_DMA_NOWAIT)) { - device_printf(dev, "Unable to allocate csb memory\n"); - error = ENOMEM; - goto err_csb; - } - /* Setup the Base of the CSB */ - adapter->csb = (struct paravirt_csb *)adapter->csb_mem.dma_vaddr; - /* force the first kick */ - adapter->csb->host_need_txkick = 1; /* txring empty */ - adapter->csb->guest_need_rxkick = 1; /* no rx packets */ - bus_addr = adapter->csb_mem.dma_paddr; - lem_add_rx_process_limit(adapter, "csb_on", - "enable paravirt.", &adapter->csb->guest_csb_on, 0); - lem_add_rx_process_limit(adapter, "txc_lim", - "txc_lim", &adapter->csb->host_txcycles_lim, 1); - - /* some stats */ -#define PA_SC(name, var, val) \ - lem_add_rx_process_limit(adapter, name, name, var, val) - PA_SC("host_need_txkick",&adapter->csb->host_need_txkick, 1); - PA_SC("host_rxkick_at",&adapter->csb->host_rxkick_at, ~0); - PA_SC("guest_need_txkick",&adapter->csb->guest_need_txkick, 0); - PA_SC("guest_need_rxkick",&adapter->csb->guest_need_rxkick, 1); - PA_SC("tdt_reg_count",&adapter->tdt_reg_count, 0); - PA_SC("tdt_csb_count",&adapter->tdt_csb_count, 0); - PA_SC("tdt_int_count",&adapter->tdt_int_count, 0); - PA_SC("guest_need_kick_count",&adapter->guest_need_kick_count, 0); - /* tell the host where the block is */ - E1000_WRITE_REG(&adapter->hw, E1000_CSBAH, - (u32)(bus_addr >> 32)); - E1000_WRITE_REG(&adapter->hw, E1000_CSBAL, - (u32)bus_addr); - } -#endif /* NIC_PARAVIRT */ - - tsize = roundup2(adapter->num_tx_desc * sizeof(struct e1000_tx_desc), - EM_DBA_ALIGN); + /* + * It seems that the descriptor DMA engine on some PCI cards + * fetches memory past the end of the last descriptor in the + * ring. These reads are problematic when VT-d (DMAR) busdma + * is used. Allocate the scratch space to avoid getting + * faults from DMAR, by requesting scratch memory for one more + * descriptor. + */ + tsize = roundup2((adapter->num_tx_desc + 1) * + sizeof(struct e1000_tx_desc), EM_DBA_ALIGN); /* Allocate Transmit Descriptor ring */ if (lem_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) { @@ -605,8 +565,11 @@ lem_attach(device_t dev) adapter->tx_desc_base = (struct e1000_tx_desc *)adapter->txdma.dma_vaddr; - rsize = roundup2(adapter->num_rx_desc * sizeof(struct e1000_rx_desc), - EM_DBA_ALIGN); + /* + * See comment above txdma allocation for rationale behind +1. + */ + rsize = roundup2((adapter->num_rx_desc + 1) * + sizeof(struct e1000_rx_desc), EM_DBA_ALIGN); /* Allocate Receive Descriptor ring */ if (lem_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) { @@ -751,11 +714,6 @@ err_hw_init: err_rx_desc: lem_dma_free(adapter, &adapter->txdma); err_tx_desc: -#ifdef NIC_PARAVIRT - lem_dma_free(adapter, &adapter->csb_mem); -err_csb: -#endif /* NIC_PARAVIRT */ - err_pci: if (adapter->ifp != (void *)NULL) if_free(adapter->ifp); @@ -843,12 +801,6 @@ lem_detach(device_t dev) adapter->rx_desc_base = NULL; } -#ifdef NIC_PARAVIRT - if (adapter->csb) { - lem_dma_free(adapter, &adapter->csb_mem); - adapter->csb = NULL; - } -#endif /* NIC_PARAVIRT */ lem_release_hw_control(adapter); free(adapter->mta, M_DEVBUF); EM_TX_LOCK_DESTROY(adapter); @@ -958,16 +910,6 @@ lem_start_locked(if_t ifp) } if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); -#ifdef NIC_PARAVIRT - if (if_getdrvflags(ifp) & IFF_DRV_OACTIVE && adapter->csb && - adapter->csb->guest_csb_on && - !(adapter->csb->guest_need_txkick & 1)) { - adapter->csb->guest_need_txkick = 1; - adapter->guest_need_kick_count++; - // XXX memory barrier - lem_txeof(adapter); // XXX possibly clear IFF_DRV_OACTIVE - } -#endif /* NIC_PARAVIRT */ return; } @@ -1815,24 +1757,6 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp) bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); -#ifdef NIC_PARAVIRT - if (adapter->csb) { - adapter->csb->guest_tdt = i; - /* XXX memory barrier ? */ - if (adapter->csb->guest_csb_on && - !(adapter->csb->host_need_txkick & 1)) { - /* XXX maybe useless - * clean the ring. maybe do it before ? - * maybe a little bit of histeresys ? - */ - if (adapter->num_tx_desc_avail <= 64) {// XXX - lem_txeof(adapter); - } - return (0); - } - } -#endif /* NIC_PARAVIRT */ - #ifdef NIC_SEND_COMBINING if (adapter->sc_enable) { if (adapter->shadow_tdt & MIT_PENDING_INT) { @@ -2088,20 +2012,6 @@ lem_local_timer(void *arg) lem_smartspeed(adapter); -#ifdef NIC_PARAVIRT - /* recover space if needed */ - if (adapter->csb && adapter->csb->guest_csb_on && - (adapter->watchdog_check == TRUE) && - (ticks - adapter->watchdog_time > EM_WATCHDOG) && - (adapter->num_tx_desc_avail != adapter->num_tx_desc) ) { - lem_txeof(adapter); - /* - * lem_txeof() normally (except when space in the queue - * runs low XXX) cleans watchdog_check so that - * we do not hung. - */ - } -#endif /* NIC_PARAVIRT */ /* * We check the watchdog: the time since * the last TX descriptor was cleaned. @@ -3178,12 +3088,6 @@ lem_txeof(struct adapter *adapter) */ if (adapter->num_tx_desc_avail > EM_TX_CLEANUP_THRESHOLD) { if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); -#ifdef NIC_PARAVIRT - if (adapter->csb) { // XXX also csb_on ? - adapter->csb->guest_need_txkick = 2; /* acked */ - // XXX memory barrier - } -#endif /* NIC_PARAVIRT */ if (adapter->num_tx_desc_avail == adapter->num_tx_desc) { adapter->watchdog_check = FALSE; return; @@ -3572,15 +3476,6 @@ lem_rxeof(struct adapter *adapter, int count, int *done) #ifdef BATCH_DISPATCH struct mbuf *mh = NULL, *mt = NULL; #endif /* BATCH_DISPATCH */ -#ifdef NIC_PARAVIRT - int retries = 0; - struct paravirt_csb* csb = adapter->csb; - int csb_mode = csb && csb->guest_csb_on; - - //ND("clear guest_rxkick at %d", adapter->next_rx_desc_to_check); - if (csb_mode && csb->guest_need_rxkick) - csb->guest_need_rxkick = 0; -#endif /* NIC_PARAVIRT */ EM_RX_LOCK(adapter); #ifdef BATCH_DISPATCH @@ -3598,45 +3493,20 @@ lem_rxeof(struct adapter *adapter, int count, int *done) } #endif /* DEV_NETMAP */ -#if 1 // XXX optimization ? if (!((current_desc->status) & E1000_RXD_STAT_DD)) { if (done != NULL) *done = rx_sent; EM_RX_UNLOCK(adapter); return (FALSE); } -#endif /* 0 */ while (count != 0 && if_getdrvflags(ifp) & IFF_DRV_RUNNING) { struct mbuf *m = NULL; status = current_desc->status; if ((status & E1000_RXD_STAT_DD) == 0) { -#ifdef NIC_PARAVIRT - if (csb_mode) { - /* buffer not ready yet. Retry a few times before giving up */ - if (++retries <= adapter->rx_retries) { - continue; - } - if (csb->guest_need_rxkick == 0) { - // ND("set guest_rxkick at %d", adapter->next_rx_desc_to_check); - csb->guest_need_rxkick = 1; - // XXX memory barrier, status volatile ? - continue; /* double check */ - } - } - /* no buffer ready, give up */ -#endif /* NIC_PARAVIRT */ break; } -#ifdef NIC_PARAVIRT - if (csb_mode) { - if (csb->guest_need_rxkick) - // ND("clear again guest_rxkick at %d", adapter->next_rx_desc_to_check); - csb->guest_need_rxkick = 0; - retries = 0; - } -#endif /* NIC_PARAVIRT */ mp = adapter->rx_buffer_area[i].m_head; /* @@ -3761,18 +3631,6 @@ discard: bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); -#ifdef NIC_PARAVIRT - if (csb_mode) { - /* the buffer at i has been already replaced by lem_get_buf() - * so it is safe to set guest_rdt = i and possibly send a kick. - * XXX see if we can optimize it later. - */ - csb->guest_rdt = i; - // XXX memory barrier - if (i == csb->host_rxkick_at) - E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); - } -#endif /* NIC_PARAVIRT */ /* Advance our pointers to the next descriptor. */ if (++i == adapter->num_rx_desc) i = 0; @@ -3819,9 +3677,6 @@ discard: /* Advance the E1000's Receive Queue #0 "Tail Pointer". */ if (--i < 0) i = adapter->num_rx_desc - 1; -#ifdef NIC_PARAVIRT - if (!csb_mode) /* filter out writes */ -#endif /* NIC_PARAVIRT */ E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), i); if (done != NULL) *done = rx_sent; diff --git a/freebsd/sys/dev/mii/rgephy.c b/freebsd/sys/dev/mii/rgephy.c index 067bbadf..963197a1 100644 --- a/freebsd/sys/dev/mii/rgephy.c +++ b/freebsd/sys/dev/mii/rgephy.c @@ -123,6 +123,8 @@ rgephy_attach(device_t dev) flags = 0; if (mii_dev_mac_match(dev, "re")) flags |= MIIF_PHYPRIV0; + else if (mii_dev_mac_match(dev, "ure")) + flags |= MIIF_PHYPRIV1; mii_phy_dev_attach(dev, flags, &rgephy_funcs, 0); /* RTL8169S do not report auto-sense; add manually. */ @@ -295,7 +297,10 @@ rgephy_linkup(struct mii_softc *sc) linkup++; } } else { - reg = PHY_READ(sc, RL_GMEDIASTAT); + if (sc->mii_flags & MIIF_PHYPRIV1) + reg = PHY_READ(sc, URE_GMEDIASTAT); + else + reg = PHY_READ(sc, RL_GMEDIASTAT); if (reg & RL_GMEDIASTAT_LINK) linkup++; } @@ -380,7 +385,10 @@ rgephy_status(struct mii_softc *sc) mii->mii_media_active |= IFM_HDX; } } else { - bmsr = PHY_READ(sc, RL_GMEDIASTAT); + if (sc->mii_flags & MIIF_PHYPRIV1) + bmsr = PHY_READ(sc, URE_GMEDIASTAT); + else + bmsr = PHY_READ(sc, RL_GMEDIASTAT); if (bmsr & RL_GMEDIASTAT_1000MBPS) mii->mii_media_active |= IFM_1000_T; else if (bmsr & RL_GMEDIASTAT_100MBPS) diff --git a/freebsd/sys/dev/mii/rgephyreg.h b/freebsd/sys/dev/mii/rgephyreg.h index 7c24a1f7..35917daa 100644 --- a/freebsd/sys/dev/mii/rgephyreg.h +++ b/freebsd/sys/dev/mii/rgephyreg.h @@ -199,4 +199,7 @@ #define EEELPAR_1000T 0x0004 /* link partner 1000baseT EEE capable */ #define EEELPAR_100TX 0x0002 /* link partner 100baseTX EEE capable */ +/* RTL8153 */ +#define URE_GMEDIASTAT 0xe908 /* media status register */ + #endif /* _DEV_RGEPHY_MIIREG_H_ */ diff --git a/freebsd/sys/dev/nvme/nvme.h b/freebsd/sys/dev/nvme/nvme.h index 755e3766..9c1dab17 100644 --- a/freebsd/sys/dev/nvme/nvme.h +++ b/freebsd/sys/dev/nvme/nvme.h @@ -663,9 +663,27 @@ enum nvme_log_page { NVME_LOG_ERROR = 0x01, NVME_LOG_HEALTH_INFORMATION = 0x02, NVME_LOG_FIRMWARE_SLOT = 0x03, - /* 0x04-0x7F - reserved */ + NVME_LOG_CHANGED_NAMESPACE = 0x04, + NVME_LOG_COMMAND_EFFECT = 0x05, + /* 0x06-0x7F - reserved */ /* 0x80-0xBF - I/O command set specific */ + NVME_LOG_RES_NOTIFICATION = 0x80, /* 0xC0-0xFF - vendor specific */ + + /* + * The following are Intel Specific log pages, but they seem + * to be widely implemented. + */ + INTEL_LOG_READ_LAT_LOG = 0xc1, + INTEL_LOG_WRITE_LAT_LOG = 0xc2, + INTEL_LOG_TEMP_STATS = 0xc5, + INTEL_LOG_ADD_SMART = 0xca, + INTEL_LOG_DRIVE_MKT_NAME = 0xdd, + + /* + * HGST log page, with lots ofs sub pages. + */ + HGST_INFO_LOG = 0xc1, }; struct nvme_error_information_entry { @@ -724,8 +742,11 @@ struct nvme_health_information_page { uint64_t unsafe_shutdowns[2]; uint64_t media_errors[2]; uint64_t num_error_info_log_entries[2]; + uint32_t warning_temp_time; + uint32_t error_temp_time; + uint16_t temp_sensor[8]; - uint8_t reserved2[320]; + uint8_t reserved2[296]; } __packed __aligned(4); struct nvme_firmware_page { @@ -740,6 +761,19 @@ struct nvme_firmware_page { uint8_t reserved2[448]; } __packed __aligned(4); +struct intel_log_temp_stats +{ + uint64_t current; + uint64_t overtemp_flag_last; + uint64_t overtemp_flag_life; + uint64_t max_temp; + uint64_t min_temp; + uint64_t _rsvd[5]; + uint64_t max_oper_temp; + uint64_t min_oper_temp; + uint64_t est_offset; +} __packed __aligned(4); + #define NVME_TEST_MAX_THREADS 128 struct nvme_io_test { diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c index 789825dc..211562f0 100644 --- a/freebsd/sys/dev/pci/pci.c +++ b/freebsd/sys/dev/pci/pci.c @@ -3981,7 +3981,7 @@ pci_rescan_method(device_t dev) if (hdrtype & PCIM_MFDEV) pcifunchigh = PCIB_MAXFUNCS(pcib); for (f = 0; f <= pcifunchigh; f++) { - if (REG(PCIR_VENDOR, 2) == 0xfff) + if (REG(PCIR_VENDOR, 2) == 0xffff) continue; /* @@ -4081,6 +4081,7 @@ pci_add_child(device_t bus, struct pci_devinfo *dinfo) pci_print_verbose(dinfo); pci_add_resources(bus, dinfo->cfg.dev, 0, 0); pci_child_added(dinfo->cfg.dev); + EVENTHANDLER_INVOKE(pci_add_device, dinfo->cfg.dev); } void @@ -4617,6 +4618,9 @@ static const struct {PCIC_CRYPTO, PCIS_CRYPTO_ENTERTAIN, 1, "entertainment crypto"}, {PCIC_DASP, -1, 0, "dasp"}, {PCIC_DASP, PCIS_DASP_DPIO, 1, "DPIO module"}, + {PCIC_DASP, PCIS_DASP_PERFCNTRS, 1, "performance counters"}, + {PCIC_DASP, PCIS_DASP_COMM_SYNC, 1, "communication synchronizer"}, + {PCIC_DASP, PCIS_DASP_MGMT_CARD, 1, "signal processing management"}, {0, 0, 0, NULL} }; @@ -5009,6 +5013,7 @@ pci_reserve_map(device_t dev, device_t child, int type, int *rid, struct resource_list *rl = &dinfo->resources; struct resource *res; struct pci_map *pm; + uint16_t cmd; pci_addr_t map, testval; int mapsize; @@ -5107,8 +5112,17 @@ pci_reserve_map(device_t dev, device_t child, int type, int *rid, device_printf(child, "Lazy allocation of %#jx bytes rid %#x type %d at %#jx\n", count, *rid, type, rman_get_start(res)); + + /* Disable decoding via the CMD register before updating the BAR */ + cmd = pci_read_config(child, PCIR_COMMAND, 2); + pci_write_config(child, PCIR_COMMAND, + cmd & ~(PCI_BAR_MEM(map) ? PCIM_CMD_MEMEN : PCIM_CMD_PORTEN), 2); + map = rman_get_start(res); pci_write_bar(child, pm, map); + + /* Restore the original value of the CMD register */ + pci_write_config(child, PCIR_COMMAND, cmd, 2); out: return (res); } @@ -5331,6 +5345,8 @@ pci_child_deleted(device_t dev, device_t child) dinfo = device_get_ivars(child); rl = &dinfo->resources; + EVENTHANDLER_INVOKE(pci_delete_device, child); + /* Turn off access to resources we're about to free */ if (bus_child_present(child) != 0) { pci_write_config(child, PCIR_COMMAND, pci_read_config(child, @@ -5908,3 +5924,165 @@ pci_find_pcie_root_port(device_t dev) dev = pcib; } } + +/* + * Wait for pending transactions to complete on a PCI-express function. + * + * The maximum delay is specified in milliseconds in max_delay. Note + * that this function may sleep. + * + * Returns true if the function is idle and false if the timeout is + * exceeded. If dev is not a PCI-express function, this returns true. + */ +bool +pcie_wait_for_pending_transactions(device_t dev, u_int max_delay) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + uint16_t sta; + int cap; + + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) + return (true); + + sta = pci_read_config(dev, cap + PCIER_DEVICE_STA, 2); + while (sta & PCIEM_STA_TRANSACTION_PND) { + if (max_delay == 0) + return (false); + + /* Poll once every 100 milliseconds up to the timeout. */ + if (max_delay > 100) { + pause_sbt("pcietp", 100 * SBT_1MS, 0, C_HARDCLOCK); + max_delay -= 100; + } else { + pause_sbt("pcietp", max_delay * SBT_1MS, 0, + C_HARDCLOCK); + max_delay = 0; + } + sta = pci_read_config(dev, cap + PCIER_DEVICE_STA, 2); + } + + return (true); +} + +/* + * Determine the maximum Completion Timeout in microseconds. + * + * For non-PCI-express functions this returns 0. + */ +int +pcie_get_max_completion_timeout(device_t dev) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + int cap; + + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) + return (0); + + /* + * Functions using the 1.x spec use the default timeout range of + * 50 microseconds to 50 milliseconds. Functions that do not + * support programmable timeouts also use this range. + */ + if ((dinfo->cfg.pcie.pcie_flags & PCIEM_FLAGS_VERSION) < 2 || + (pci_read_config(dev, cap + PCIER_DEVICE_CAP2, 4) & + PCIEM_CAP2_COMP_TIMO_RANGES) == 0) + return (50 * 1000); + + switch (pci_read_config(dev, cap + PCIER_DEVICE_CTL2, 2) & + PCIEM_CTL2_COMP_TIMO_VAL) { + case PCIEM_CTL2_COMP_TIMO_100US: + return (100); + case PCIEM_CTL2_COMP_TIMO_10MS: + return (10 * 1000); + case PCIEM_CTL2_COMP_TIMO_55MS: + return (55 * 1000); + case PCIEM_CTL2_COMP_TIMO_210MS: + return (210 * 1000); + case PCIEM_CTL2_COMP_TIMO_900MS: + return (900 * 1000); + case PCIEM_CTL2_COMP_TIMO_3500MS: + return (3500 * 1000); + case PCIEM_CTL2_COMP_TIMO_13S: + return (13 * 1000 * 1000); + case PCIEM_CTL2_COMP_TIMO_64S: + return (64 * 1000 * 1000); + default: + return (50 * 1000); + } +} + +/* + * Perform a Function Level Reset (FLR) on a device. + * + * This function first waits for any pending transactions to complete + * within the timeout specified by max_delay. If transactions are + * still pending, the function will return false without attempting a + * reset. + * + * If dev is not a PCI-express function or does not support FLR, this + * function returns false. + * + * Note that no registers are saved or restored. The caller is + * responsible for saving and restoring any registers including + * PCI-standard registers via pci_save_state() and + * pci_restore_state(). + */ +bool +pcie_flr(device_t dev, u_int max_delay, bool force) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + uint16_t cmd, ctl; + int compl_delay; + int cap; + + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) + return (false); + + if (!(pci_read_config(dev, cap + PCIER_DEVICE_CAP, 4) & PCIEM_CAP_FLR)) + return (false); + + /* + * Disable busmastering to prevent generation of new + * transactions while waiting for the device to go idle. If + * the idle timeout fails, the command register is restored + * which will re-enable busmastering. + */ + cmd = pci_read_config(dev, PCIR_COMMAND, 2); + pci_write_config(dev, PCIR_COMMAND, cmd & ~(PCIM_CMD_BUSMASTEREN), 2); + if (!pcie_wait_for_pending_transactions(dev, max_delay)) { + if (!force) { + pci_write_config(dev, PCIR_COMMAND, cmd, 2); + return (false); + } + pci_printf(&dinfo->cfg, + "Resetting with transactions pending after %d ms\n", + max_delay); + + /* + * Extend the post-FLR delay to cover the maximum + * Completion Timeout delay of anything in flight + * during the FLR delay. Enforce a minimum delay of + * at least 10ms. + */ + compl_delay = pcie_get_max_completion_timeout(dev) / 1000; + if (compl_delay < 10) + compl_delay = 10; + } else + compl_delay = 0; + + /* Initiate the reset. */ + ctl = pci_read_config(dev, cap + PCIER_DEVICE_CTL, 2); + pci_write_config(dev, cap + PCIER_DEVICE_CTL, ctl | + PCIEM_CTL_INITIATE_FLR, 2); + + /* Wait for 100ms. */ + pause_sbt("pcieflr", (100 + compl_delay) * SBT_1MS, 0, C_HARDCLOCK); + + if (pci_read_config(dev, cap + PCIER_DEVICE_STA, 2) & + PCIEM_STA_TRANSACTION_PND) + pci_printf(&dinfo->cfg, "Transactions pending after FLR!\n"); + return (true); +} diff --git a/freebsd/sys/dev/pci/pcireg.h b/freebsd/sys/dev/pci/pcireg.h index d463b7a5..291bb2ea 100644 --- a/freebsd/sys/dev/pci/pcireg.h +++ b/freebsd/sys/dev/pci/pcireg.h @@ -885,10 +885,25 @@ #define PCIEM_ROOT_STA_PME_STATUS 0x00010000 #define PCIEM_ROOT_STA_PME_PEND 0x00020000 #define PCIER_DEVICE_CAP2 0x24 -#define PCIEM_CAP2_ARI 0x20 +#define PCIEM_CAP2_COMP_TIMO_RANGES 0x0000000f +#define PCIEM_CAP2_COMP_TIMO_RANGE_A 0x00000001 +#define PCIEM_CAP2_COMP_TIMO_RANGE_B 0x00000002 +#define PCIEM_CAP2_COMP_TIMO_RANGE_C 0x00000004 +#define PCIEM_CAP2_COMP_TIMO_RANGE_D 0x00000008 +#define PCIEM_CAP2_COMP_TIMO_DISABLE 0x00000010 +#define PCIEM_CAP2_ARI 0x00000020 #define PCIER_DEVICE_CTL2 0x28 -#define PCIEM_CTL2_COMP_TIMEOUT_VAL 0x000f -#define PCIEM_CTL2_COMP_TIMEOUT_DIS 0x0010 +#define PCIEM_CTL2_COMP_TIMO_VAL 0x000f +#define PCIEM_CTL2_COMP_TIMO_50MS 0x0000 +#define PCIEM_CTL2_COMP_TIMO_100US 0x0001 +#define PCIEM_CTL2_COMP_TIMO_10MS 0x0002 +#define PCIEM_CTL2_COMP_TIMO_55MS 0x0005 +#define PCIEM_CTL2_COMP_TIMO_210MS 0x0006 +#define PCIEM_CTL2_COMP_TIMO_900MS 0x0009 +#define PCIEM_CTL2_COMP_TIMO_3500MS 0x000a +#define PCIEM_CTL2_COMP_TIMO_13S 0x000d +#define PCIEM_CTL2_COMP_TIMO_64S 0x000e +#define PCIEM_CTL2_COMP_TIMO_DISABLE 0x0010 #define PCIEM_CTL2_ARI 0x0020 #define PCIEM_CTL2_ATOMIC_REQ_ENABLE 0x0040 #define PCIEM_CTL2_ATOMIC_EGR_BLOCK 0x0080 diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h index fc3fa5fb..4652715a 100644 --- a/freebsd/sys/dev/pci/pcivar.h +++ b/freebsd/sys/dev/pci/pcivar.h @@ -31,6 +31,7 @@ #define _PCIVAR_H_ #include +#include /* some PCI bus constants */ #define PCI_MAXMAPS_0 6 /* max. no. of memory/port maps */ @@ -594,7 +595,9 @@ uint32_t pcie_read_config(device_t dev, int reg, int width); void pcie_write_config(device_t dev, int reg, uint32_t value, int width); uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask, uint32_t value, int width); - +bool pcie_flr(device_t dev, u_int max_delay, bool force); +int pcie_get_max_completion_timeout(device_t dev); +bool pcie_wait_for_pending_transactions(device_t dev, u_int max_delay); #ifdef BUS_SPACE_MAXADDR #if (BUS_SPACE_MAXADDR > 0xFFFFFFFF) @@ -631,4 +634,12 @@ void * vga_pci_map_bios(device_t dev, size_t *size); void vga_pci_unmap_bios(device_t dev, void *bios); int vga_pci_repost(device_t dev); +/** + * Global eventhandlers invoked when PCI devices are added or removed + * from the system. + */ +typedef void (*pci_event_fn)(void *arg, device_t dev); +EVENTHANDLER_DECLARE(pci_add_device, pci_event_fn); +EVENTHANDLER_DECLARE(pci_delete_device, pci_event_fn); + #endif /* _PCIVAR_H_ */ diff --git a/freebsd/sys/dev/re/if_re.c b/freebsd/sys/dev/re/if_re.c index 554af66a..7e0e87f8 100644 --- a/freebsd/sys/dev/re/if_re.c +++ b/freebsd/sys/dev/re/if_re.c @@ -185,6 +185,8 @@ static const struct rl_type re_devs[] = { "RealTek 810xE PCIe 10/100baseTX" }, { RT_VENDORID, RT_DEVICEID_8168, 0, "RealTek 8168/8111 B/C/CP/D/DP/E/F/G PCIe Gigabit Ethernet" }, + { NCUBE_VENDORID, RT_DEVICEID_8168, 0, + "TP-Link TG-3468 v2 (RTL8168) Gigabit Ethernet" }, { RT_VENDORID, RT_DEVICEID_8169, 0, "RealTek 8169/8169S/8169SB(L)/8110S/8110SB(L) Gigabit Ethernet" }, { RT_VENDORID, RT_DEVICEID_8169SC, 0, @@ -1358,15 +1360,17 @@ re_attach(device_t dev) CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF); } - /* Disable ASPM L0S/L1. */ + /* Disable ASPM L0S/L1 and CLKREQ. */ if (sc->rl_expcap != 0) { cap = pci_read_config(dev, sc->rl_expcap + PCIER_LINK_CAP, 2); if ((cap & PCIEM_LINK_CAP_ASPM) != 0) { ctl = pci_read_config(dev, sc->rl_expcap + PCIER_LINK_CTL, 2); - if ((ctl & PCIEM_LINK_CTL_ASPMC) != 0) { - ctl &= ~PCIEM_LINK_CTL_ASPMC; + if ((ctl & (PCIEM_LINK_CTL_ECPM | + PCIEM_LINK_CTL_ASPMC))!= 0) { + ctl &= ~(PCIEM_LINK_CTL_ECPM | + PCIEM_LINK_CTL_ASPMC); pci_write_config(dev, sc->rl_expcap + PCIER_LINK_CTL, ctl, 2); device_printf(dev, "ASPM disabled\n"); diff --git a/freebsd/sys/dev/rl/if_rlreg.h b/freebsd/sys/dev/rl/if_rlreg.h index 2cef251b..2fa44efa 100644 --- a/freebsd/sys/dev/rl/if_rlreg.h +++ b/freebsd/sys/dev/rl/if_rlreg.h @@ -1158,3 +1158,8 @@ struct rl_softc { /* US Robotics 997902 device ID */ #define USR_DEVICEID_997902 0x0116 + +/* + * NCube vendor ID + */ +#define NCUBE_VENDORID 0x10FF diff --git a/freebsd/sys/dev/tsec/if_tsec.h b/freebsd/sys/dev/tsec/if_tsec.h index 108b0f21..60a565ea 100644 --- a/freebsd/sys/dev/tsec/if_tsec.h +++ b/freebsd/sys/dev/tsec/if_tsec.h @@ -137,6 +137,7 @@ struct tsec_softc { int phyaddr; bus_space_tag_t phy_bst; bus_space_handle_t phy_bsh; + int phy_regoff; }; /* interface to get/put generic objects */ @@ -260,9 +261,11 @@ extern struct mtx tsec_phy_mtx; #define TSEC_PHY_LOCK(sc) mtx_lock(&tsec_phy_mtx) #define TSEC_PHY_UNLOCK(sc) mtx_unlock(&tsec_phy_mtx) #define TSEC_PHY_READ(sc, reg) \ - bus_space_read_4((sc)->phy_bst, (sc)->phy_bsh, (reg)) + bus_space_read_4((sc)->phy_bst, (sc)->phy_bsh, \ + (reg) + (sc)->phy_regoff) #define TSEC_PHY_WRITE(sc, reg, val) \ - bus_space_write_4((sc)->phy_bst, (sc)->phy_bsh, (reg), (val)) + bus_space_write_4((sc)->phy_bst, (sc)->phy_bsh, \ + (reg) + (sc)->phy_regoff, (val)) /* Lock for transmitter */ #define TSEC_TRANSMIT_LOCK(sc) do { \ diff --git a/freebsd/sys/dev/usb/controller/dwc_otg.c b/freebsd/sys/dev/usb/controller/dwc_otg.c index d070f145..3450f6de 100644 --- a/freebsd/sys/dev/usb/controller/dwc_otg.c +++ b/freebsd/sys/dev/usb/controller/dwc_otg.c @@ -100,10 +100,6 @@ GINTSTS_WKUPINT | GINTSTS_USBSUSP | GINTMSK_OTGINTMSK | \ GINTSTS_SESSREQINT) -#define DWC_OTG_PHY_ULPI 0 -#define DWC_OTG_PHY_HSIC 1 -#define DWC_OTG_PHY_INTERNAL 2 - #ifndef DWC_OTG_PHY_DEFAULT #define DWC_OTG_PHY_DEFAULT DWC_OTG_PHY_ULPI #endif @@ -112,10 +108,10 @@ static int dwc_otg_phy_type = DWC_OTG_PHY_DEFAULT; static SYSCTL_NODE(_hw_usb, OID_AUTO, dwc_otg, CTLFLAG_RW, 0, "USB DWC OTG"); SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, phy_type, CTLFLAG_RDTUN, - &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2 - ULPI/HSIC/INTERNAL"); + &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2/3 - ULPI/HSIC/INTERNAL/UTMI+"); #ifdef USB_DEBUG -static int dwc_otg_debug; +static int dwc_otg_debug = 0; SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, debug, CTLFLAG_RWTUN, &dwc_otg_debug, 0, "DWC OTG debug level"); @@ -3891,8 +3887,13 @@ dwc_otg_init(struct dwc_otg_softc *sc) break; } - /* select HSIC, ULPI or internal PHY mode */ - switch (dwc_otg_phy_type) { + if (sc->sc_phy_type == 0) + sc->sc_phy_type = dwc_otg_phy_type + 1; + if (sc->sc_phy_bits == 0) + sc->sc_phy_bits = 16; + + /* select HSIC, ULPI, UTMI+ or internal PHY mode */ + switch (sc->sc_phy_type) { case DWC_OTG_PHY_HSIC: DWC_OTG_WRITE_4(sc, DOTG_GUSBCFG, GUSBCFG_PHYIF | @@ -3912,6 +3913,16 @@ dwc_otg_init(struct dwc_otg_softc *sc) GUSBCFG_TRD_TIM_SET(5) | temp); DWC_OTG_WRITE_4(sc, DOTG_GOTGCTL, 0); + temp = DWC_OTG_READ_4(sc, DOTG_GLPMCFG); + DWC_OTG_WRITE_4(sc, DOTG_GLPMCFG, + temp & ~GLPMCFG_HSIC_CONN); + break; + case DWC_OTG_PHY_UTMI: + DWC_OTG_WRITE_4(sc, DOTG_GUSBCFG, + (sc->sc_phy_bits == 16 ? GUSBCFG_PHYIF : 0) | + GUSBCFG_TRD_TIM_SET(5) | temp); + DWC_OTG_WRITE_4(sc, DOTG_GOTGCTL, 0); + temp = DWC_OTG_READ_4(sc, DOTG_GLPMCFG); DWC_OTG_WRITE_4(sc, DOTG_GLPMCFG, temp & ~GLPMCFG_HSIC_CONN); diff --git a/freebsd/sys/dev/usb/controller/dwc_otg.h b/freebsd/sys/dev/usb/controller/dwc_otg.h index 038b072a..7f5ede48 100644 --- a/freebsd/sys/dev/usb/controller/dwc_otg.h +++ b/freebsd/sys/dev/usb/controller/dwc_otg.h @@ -191,6 +191,13 @@ struct dwc_otg_softc { uint16_t sc_active_rx_ep; uint16_t sc_last_frame_num; + uint8_t sc_phy_type; + uint8_t sc_phy_bits; +#define DWC_OTG_PHY_ULPI 1 +#define DWC_OTG_PHY_HSIC 2 +#define DWC_OTG_PHY_INTERNAL 3 +#define DWC_OTG_PHY_UTMI 4 + uint8_t sc_timer_active; uint8_t sc_dev_ep_max; uint8_t sc_dev_in_ep_max; diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c index 1ff0afba..d73116e2 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.c +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c @@ -661,7 +661,7 @@ usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk) if (quirk == UQ_NONE) goto done; - mtx_lock(&usb_quirk_mtx); + USB_MTX_LOCK(&usb_quirk_mtx); for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) { /* see if quirk information does not match */ @@ -685,13 +685,13 @@ usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk) /* lookup quirk */ for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) { if (usb_quirks[x].quirks[y] == quirk) { - mtx_unlock(&usb_quirk_mtx); + USB_MTX_UNLOCK(&usb_quirk_mtx); DPRINTF("Found quirk '%s'.\n", usb_quirkstr(quirk)); return (1); } } } - mtx_unlock(&usb_quirk_mtx); + USB_MTX_UNLOCK(&usb_quirk_mtx); done: return (0); /* no quirk match */ } @@ -702,7 +702,7 @@ usb_quirk_get_entry(uint16_t vid, uint16_t pid, { uint16_t x; - mtx_assert(&usb_quirk_mtx, MA_OWNED); + USB_MTX_ASSERT(&usb_quirk_mtx, MA_OWNED); if ((vid | pid | lo_rev | hi_rev) == 0) { /* all zero - special case */ @@ -770,7 +770,7 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data, if (y >= USB_DEV_QUIRKS_MAX) { return (EINVAL); } - mtx_lock(&usb_quirk_mtx); + USB_MTX_LOCK(&usb_quirk_mtx); /* copy out data */ pgq->vid = usb_quirks[y].vid; pgq->pid = usb_quirks[y].pid; @@ -779,7 +779,7 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data, strlcpy(pgq->quirkname, usb_quirkstr(usb_quirks[y].quirks[x]), sizeof(pgq->quirkname)); - mtx_unlock(&usb_quirk_mtx); + USB_MTX_UNLOCK(&usb_quirk_mtx); return (0); /* success */ case USB_QUIRK_NAME_GET: @@ -812,11 +812,11 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data, if (y == UQ_NONE) { return (EINVAL); } - mtx_lock(&usb_quirk_mtx); + USB_MTX_LOCK(&usb_quirk_mtx); pqe = usb_quirk_get_entry(pgq->vid, pgq->pid, pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 1); if (pqe == NULL) { - mtx_unlock(&usb_quirk_mtx); + USB_MTX_UNLOCK(&usb_quirk_mtx); return (EINVAL); } for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) { @@ -825,7 +825,7 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data, break; } } - mtx_unlock(&usb_quirk_mtx); + USB_MTX_UNLOCK(&usb_quirk_mtx); if (x == USB_SUB_QUIRKS_MAX) { return (ENOMEM); } @@ -850,11 +850,11 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data, if (y == UQ_NONE) { return (EINVAL); } - mtx_lock(&usb_quirk_mtx); + USB_MTX_LOCK(&usb_quirk_mtx); pqe = usb_quirk_get_entry(pgq->vid, pgq->pid, pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 0); if (pqe == NULL) { - mtx_unlock(&usb_quirk_mtx); + USB_MTX_UNLOCK(&usb_quirk_mtx); return (EINVAL); } for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) { @@ -864,7 +864,7 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data, } } if (x == USB_SUB_QUIRKS_MAX) { - mtx_unlock(&usb_quirk_mtx); + USB_MTX_UNLOCK(&usb_quirk_mtx); return (ENOMEM); } for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) { @@ -876,7 +876,7 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data, /* all quirk entries are unused - release */ memset(pqe, 0, sizeof(*pqe)); } - mtx_unlock(&usb_quirk_mtx); + USB_MTX_UNLOCK(&usb_quirk_mtx); return (0); /* success */ default: @@ -967,14 +967,14 @@ usb_quirk_add_entry_from_str(const char *name, const char *env) printf("%s: Too many USB quirks, only %d allowed!\n", name, USB_SUB_QUIRKS_MAX); } - mtx_lock(&usb_quirk_mtx); + USB_MTX_LOCK(&usb_quirk_mtx); new = usb_quirk_get_entry(entry.vid, entry.pid, entry.lo_rev, entry.hi_rev, 1); if (new == NULL) printf("%s: USB quirks table is full!\n", name); else memcpy(new->quirks, entry.quirks, sizeof(entry.quirks)); - mtx_unlock(&usb_quirk_mtx); + USB_MTX_UNLOCK(&usb_quirk_mtx); } else { printf("%s: No USB quirks found!\n", name); } diff --git a/freebsd/sys/dev/usb/storage/umass.c b/freebsd/sys/dev/usb/storage/umass.c index 0fb810c1..e8ee210a 100644 --- a/freebsd/sys/dev/usb/storage/umass.c +++ b/freebsd/sys/dev/usb/storage/umass.c @@ -1149,7 +1149,7 @@ umass_cancel_ccb(struct umass_softc *sc) { union ccb *ccb; - mtx_assert(&sc->sc_mtx, MA_OWNED); + USB_MTX_ASSERT(&sc->sc_mtx, MA_OWNED); ccb = sc->sc_transfer.ccb; sc->sc_transfer.ccb = NULL; diff --git a/freebsd/sys/dev/usb/usb_busdma.c b/freebsd/sys/dev/usb/usb_busdma.c index 88566199..16fc7f7b 100644 --- a/freebsd/sys/dev/usb/usb_busdma.c +++ b/freebsd/sys/dev/usb/usb_busdma.c @@ -510,7 +510,7 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs, done: owned = mtx_owned(uptag->mtx); if (!owned) - mtx_lock(uptag->mtx); + USB_MTX_LOCK(uptag->mtx); uptag->dma_error = (error ? 1 : 0); if (isload) { @@ -519,7 +519,7 @@ done: cv_broadcast(uptag->cv); } if (!owned) - mtx_unlock(uptag->mtx); + USB_MTX_UNLOCK(uptag->mtx); } /*------------------------------------------------------------------------* @@ -594,7 +594,7 @@ usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg, pc->tag = utag->tag; pc->ismultiseg = (align == 1); - mtx_lock(uptag->mtx); + USB_MTX_LOCK(uptag->mtx); /* load memory into DMA */ err = bus_dmamap_load( @@ -605,7 +605,7 @@ usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg, cv_wait(uptag->cv, uptag->mtx); err = 0; } - mtx_unlock(uptag->mtx); + USB_MTX_UNLOCK(uptag->mtx); if (err || uptag->dma_error) { bus_dmamem_free(utag->tag, ptr, map); @@ -661,7 +661,7 @@ usb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size, uint8_t sync) pc->page_offset_end = size; pc->ismultiseg = 1; - mtx_assert(pc->tag_parent->mtx, MA_OWNED); + USB_MTX_ASSERT(pc->tag_parent->mtx, MA_OWNED); if (size > 0) { if (sync) { @@ -919,7 +919,7 @@ usb_bdma_work_loop(struct usb_xfer_queue *pq) xfer = pq->curr; info = xfer->xroot; - mtx_assert(info->xfer_mtx, MA_OWNED); + USB_MTX_ASSERT(info->xfer_mtx, MA_OWNED); if (xfer->error) { /* some error happened */ @@ -1043,7 +1043,7 @@ usb_bdma_done_event(struct usb_dma_parent_tag *udpt) info = USB_DMATAG_TO_XROOT(udpt); - mtx_assert(info->xfer_mtx, MA_OWNED); + USB_MTX_ASSERT(info->xfer_mtx, MA_OWNED); /* copy error */ info->dma_error = udpt->dma_error; diff --git a/freebsd/sys/dev/usb/usb_core.c b/freebsd/sys/dev/usb/usb_core.c index b5e66407..a74bdcaa 100644 --- a/freebsd/sys/dev/usb/usb_core.c +++ b/freebsd/sys/dev/usb/usb_core.c @@ -53,6 +53,8 @@ #include #include #include +#include +#include #include #include @@ -66,4 +68,16 @@ const struct usb_string_lang usb_string_lang_en = { MALLOC_DEFINE(M_USB, "USB", "USB"); MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device"); +int +usbd_in_polling_mode(void) +{ + return (USB_IN_POLLING_MODE_VALUE()); +} + +void +usbd_dummy_timeout(void *arg) +{ + /* NOP */ +} + MODULE_VERSION(usb, 1); diff --git a/freebsd/sys/dev/usb/usb_core.h b/freebsd/sys/dev/usb/usb_core.h index 739a0039..9f52e65a 100644 --- a/freebsd/sys/dev/usb/usb_core.h +++ b/freebsd/sys/dev/usb/usb_core.h @@ -39,17 +39,20 @@ USB_MODE_DEVICE ? (((xfer)->endpointno & UE_DIR_IN) ? 0 : 1) : \ (((xfer)->endpointno & UE_DIR_IN) ? 1 : 0)) -/* macros */ +/* locking wrappers for BUS lock */ +#define USB_BUS_LOCK(_b) USB_MTX_LOCK(&(_b)->bus_mtx) +#define USB_BUS_UNLOCK(_b) USB_MTX_UNLOCK(&(_b)->bus_mtx) +#define USB_BUS_LOCK_ASSERT(_b, _t) USB_MTX_ASSERT(&(_b)->bus_mtx, _t) -#define USB_BUS_LOCK(_b) mtx_lock(&(_b)->bus_mtx) -#define USB_BUS_UNLOCK(_b) mtx_unlock(&(_b)->bus_mtx) -#define USB_BUS_LOCK_ASSERT(_b, _t) mtx_assert(&(_b)->bus_mtx, _t) -#define USB_BUS_SPIN_LOCK(_b) mtx_lock_spin(&(_b)->bus_spin_lock) -#define USB_BUS_SPIN_UNLOCK(_b) mtx_unlock_spin(&(_b)->bus_spin_lock) -#define USB_BUS_SPIN_LOCK_ASSERT(_b, _t) mtx_assert(&(_b)->bus_spin_lock, _t) -#define USB_XFER_LOCK(_x) mtx_lock((_x)->xroot->xfer_mtx) -#define USB_XFER_UNLOCK(_x) mtx_unlock((_x)->xroot->xfer_mtx) -#define USB_XFER_LOCK_ASSERT(_x, _t) mtx_assert((_x)->xroot->xfer_mtx, _t) +/* locking wrappers for BUS spin lock */ +#define USB_BUS_SPIN_LOCK(_b) USB_MTX_LOCK_SPIN(&(_b)->bus_spin_lock) +#define USB_BUS_SPIN_UNLOCK(_b) USB_MTX_UNLOCK_SPIN(&(_b)->bus_spin_lock) +#define USB_BUS_SPIN_LOCK_ASSERT(_b, _t) USB_MTX_ASSERT(&(_b)->bus_spin_lock, _t) + +/* locking wrappers for XFER lock */ +#define USB_XFER_LOCK(_x) USB_MTX_LOCK((_x)->xroot->xfer_mtx) +#define USB_XFER_UNLOCK(_x) USB_MTX_UNLOCK((_x)->xroot->xfer_mtx) +#define USB_XFER_LOCK_ASSERT(_x, _t) USB_MTX_ASSERT((_x)->xroot->xfer_mtx, _t) /* helper for converting pointers to integers */ #define USB_P2U(ptr) \ diff --git a/freebsd/sys/dev/usb/usb_dev.c b/freebsd/sys/dev/usb/usb_dev.c index b31ba617..fe249c20 100644 --- a/freebsd/sys/dev/usb/usb_dev.c +++ b/freebsd/sys/dev/usb/usb_dev.c @@ -1161,7 +1161,7 @@ usb_filter_write(struct knote *kn, long hint) f = kn->kn_hook; - mtx_assert(f->priv_mtx, MA_OWNED); + USB_MTX_ASSERT(f->priv_mtx, MA_OWNED); cpd = f->curr_cpd; if (cpd == NULL) { @@ -1202,7 +1202,7 @@ usb_filter_read(struct knote *kn, long hint) f = kn->kn_hook; - mtx_assert(f->priv_mtx, MA_OWNED); + USB_MTX_ASSERT(f->priv_mtx, MA_OWNED); cpd = f->curr_cpd; if (cpd == NULL) { @@ -1732,7 +1732,7 @@ usb_fifo_wait(struct usb_fifo *f) { int err; - mtx_assert(f->priv_mtx, MA_OWNED); + USB_MTX_ASSERT(f->priv_mtx, MA_OWNED); if (f->flag_iserror) { /* we are gone */ diff --git a/freebsd/sys/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c index 26c694e8..06e70503 100644 --- a/freebsd/sys/dev/usb/usb_device.c +++ b/freebsd/sys/dev/usb/usb_device.c @@ -1109,10 +1109,8 @@ usb_detach_device_sub(struct usb_device *udev, device_t *ppdev, device_printf(dev, "Resume failed\n"); } } - if (device_detach(dev)) { - goto error; - } } + /* detach and delete child */ if (device_delete_child(udev->parent_dev, dev)) { goto error; } @@ -1517,13 +1515,13 @@ usbd_clear_stall_proc(struct usb_proc_msg *_pm) /* Change lock */ USB_BUS_UNLOCK(udev->bus); - mtx_lock(&udev->device_mtx); + USB_MTX_LOCK(&udev->device_mtx); /* Start clear stall callback */ usbd_transfer_start(udev->ctrl_xfer[1]); /* Change lock */ - mtx_unlock(&udev->device_mtx); + USB_MTX_UNLOCK(&udev->device_mtx); USB_BUS_LOCK(udev->bus); } @@ -1591,6 +1589,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, /* initialise our SX-lock */ sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK); sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS); + sx_init_flags(&udev->ctrl_sx, "USB control transfer SX lock", SX_DUPOK); cv_init(&udev->ctrlreq_cv, "WCTRL"); cv_init(&udev->ref_cv, "UGONE"); @@ -1776,7 +1775,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, */ /* Protect scratch area */ - do_unlock = usbd_enum_lock(udev); + do_unlock = usbd_ctrl_lock(udev); scratch_ptr = udev->scratch.data; @@ -1827,7 +1826,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, } if (do_unlock) - usbd_enum_unlock(udev); + usbd_ctrl_unlock(udev); /* assume 100mA bus powered for now. Changed when configured. */ udev->power = USB_MIN_POWER; @@ -1945,8 +1944,8 @@ config_done: udev->ugen_symlink = usb_alloc_symlink(udev->ugen_name); /* Announce device */ - printf("%s: <%s> at %s\n", udev->ugen_name, - usb_get_manufacturer(udev), + printf("%s: <%s %s> at %s\n", udev->ugen_name, + usb_get_manufacturer(udev), usb_get_product(udev), device_get_nameunit(udev->bus->bdev)); #endif @@ -2155,8 +2154,9 @@ usb_free_device(struct usb_device *udev, uint8_t flag) #if USB_HAVE_UGEN if (!rebooting) { - printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name, - usb_get_manufacturer(udev), device_get_nameunit(bus->bdev)); + printf("%s: <%s %s> at %s (disconnected)\n", udev->ugen_name, + usb_get_manufacturer(udev), usb_get_product(udev), + device_get_nameunit(bus->bdev)); } /* Destroy UGEN symlink, if any */ @@ -2201,6 +2201,7 @@ usb_free_device(struct usb_device *udev, uint8_t flag) sx_destroy(&udev->enum_sx); sx_destroy(&udev->sr_sx); + sx_destroy(&udev->ctrl_sx); cv_destroy(&udev->ctrlreq_cv); cv_destroy(&udev->ref_cv); @@ -2364,7 +2365,7 @@ usbd_set_device_strings(struct usb_device *udev) uint8_t do_unlock; /* Protect scratch area */ - do_unlock = usbd_enum_lock(udev); + do_unlock = usbd_ctrl_lock(udev); temp_ptr = (char *)udev->scratch.data; temp_size = sizeof(udev->scratch.data); @@ -2424,7 +2425,7 @@ usbd_set_device_strings(struct usb_device *udev) } if (do_unlock) - usbd_enum_unlock(udev); + usbd_ctrl_unlock(udev); } /* @@ -2830,6 +2831,40 @@ usbd_enum_is_locked(struct usb_device *udev) return (sx_xlocked(&udev->enum_sx)); } +/* + * The following function is used to serialize access to USB control + * transfers and the USB scratch area. If the lock is already grabbed + * this function returns zero. Else a value of one is returned. + */ +uint8_t +usbd_ctrl_lock(struct usb_device *udev) +{ + if (sx_xlocked(&udev->ctrl_sx)) + return (0); + sx_xlock(&udev->ctrl_sx); + + /* + * We need to allow suspend and resume at this point, else the + * control transfer will timeout if the device is suspended! + */ + if (usbd_enum_is_locked(udev)) + usbd_sr_unlock(udev); + return (1); +} + +void +usbd_ctrl_unlock(struct usb_device *udev) +{ + sx_xunlock(&udev->ctrl_sx); + + /* + * Restore the suspend and resume lock after we have unlocked + * the USB control transfer lock to avoid LOR: + */ + if (usbd_enum_is_locked(udev)) + usbd_sr_lock(udev); +} + /* * The following function is used to set the per-interface specific * plug and play information. The string referred to by the pnpinfo diff --git a/freebsd/sys/dev/usb/usb_device.h b/freebsd/sys/dev/usb/usb_device.h index 24a5a4a6..22e15606 100644 --- a/freebsd/sys/dev/usb/usb_device.h +++ b/freebsd/sys/dev/usb/usb_device.h @@ -162,7 +162,7 @@ struct usb_temp_setup { /* * The scratch area for USB devices. Access to this structure is - * protected by the enumeration SX lock. + * protected by the control SX lock. */ union usb_device_scratch { struct usb_hw_ep_scratch hw_ep_scratch[1]; @@ -183,6 +183,7 @@ struct usb_device { struct usb_udev_msg cs_msg[2]; struct sx enum_sx; struct sx sr_sx; + struct sx ctrl_sx; struct mtx device_mtx; struct cv ctrlreq_cv; struct cv ref_cv; @@ -320,6 +321,8 @@ uint8_t usbd_enum_lock_sig(struct usb_device *); void usbd_enum_unlock(struct usb_device *); void usbd_sr_lock(struct usb_device *); void usbd_sr_unlock(struct usb_device *); +uint8_t usbd_ctrl_lock(struct usb_device *); +void usbd_ctrl_unlock(struct usb_device *); uint8_t usbd_enum_is_locked(struct usb_device *); #if USB_HAVE_TT_SUPPORT diff --git a/freebsd/sys/dev/usb/usb_freebsd.h b/freebsd/sys/dev/usb/usb_freebsd.h index 0d2e8105..bc5d2422 100644 --- a/freebsd/sys/dev/usb/usb_freebsd.h +++ b/freebsd/sys/dev/usb/usb_freebsd.h @@ -92,6 +92,9 @@ #define USB_MAX_AUTO_QUIRK 8 /* maximum number of dynamic quirks */ +#define USB_IN_POLLING_MODE_FUNC() usbd_in_polling_mode() +#define USB_IN_POLLING_MODE_VALUE() (SCHEDULER_STOPPED() || kdb_active) + typedef uint32_t usb_timeout_t; /* milliseconds */ typedef uint32_t usb_frlength_t; /* bytes */ typedef uint32_t usb_frcount_t; /* units */ diff --git a/freebsd/sys/dev/usb/usb_generic.c b/freebsd/sys/dev/usb/usb_generic.c index 675a63d3..c0873a6a 100644 --- a/freebsd/sys/dev/usb/usb_generic.c +++ b/freebsd/sys/dev/usb/usb_generic.c @@ -238,7 +238,7 @@ ugen_open_pipe_write(struct usb_fifo *f) struct usb_endpoint *ep = usb_fifo_softc(f); struct usb_endpoint_descriptor *ed = ep->edesc; - mtx_assert(f->priv_mtx, MA_OWNED); + USB_MTX_ASSERT(f->priv_mtx, MA_OWNED); if (f->xfer[0] || f->xfer[1]) { /* transfers are already opened */ @@ -307,7 +307,7 @@ ugen_open_pipe_read(struct usb_fifo *f) struct usb_endpoint *ep = usb_fifo_softc(f); struct usb_endpoint_descriptor *ed = ep->edesc; - mtx_assert(f->priv_mtx, MA_OWNED); + USB_MTX_ASSERT(f->priv_mtx, MA_OWNED); if (f->xfer[0] || f->xfer[1]) { /* transfers are already opened */ @@ -716,16 +716,16 @@ ugen_get_cdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd) return (error); } -/* - * This function is called having the enumeration SX locked which - * protects the scratch area used. - */ static int ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd) { void *ptr; uint16_t size; int error; + uint8_t do_unlock; + + /* Protect scratch area */ + do_unlock = usbd_ctrl_lock(f->udev); ptr = f->udev->scratch.data; size = sizeof(f->udev->scratch.data); @@ -746,6 +746,9 @@ ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd) error = copyout(ptr, ugd->ugd_data, size); } + if (do_unlock) + usbd_ctrl_unlock(f->udev); + return (error); } diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c index a744a82e..d27728e9 100644 --- a/freebsd/sys/dev/usb/usb_hub.c +++ b/freebsd/sys/dev/usb/usb_hub.c @@ -272,11 +272,11 @@ uhub_reset_tt_proc(struct usb_proc_msg *_pm) /* Change lock */ USB_BUS_UNLOCK(udev->bus); - mtx_lock(&sc->sc_mtx); + USB_MTX_LOCK(&sc->sc_mtx); /* Start transfer */ usbd_transfer_start(sc->sc_xfer[UHUB_RESET_TT_TRANSFER]); /* Change lock */ - mtx_unlock(&sc->sc_mtx); + USB_MTX_UNLOCK(&sc->sc_mtx); USB_BUS_LOCK(udev->bus); } #endif @@ -1521,9 +1521,9 @@ uhub_attach(device_t dev) /* Start the interrupt endpoint, if any */ - mtx_lock(&sc->sc_mtx); + USB_MTX_LOCK(&sc->sc_mtx); usbd_transfer_start(sc->sc_xfer[UHUB_INTR_TRANSFER]); - mtx_unlock(&sc->sc_mtx); + USB_MTX_UNLOCK(&sc->sc_mtx); /* Enable automatic power save on all USB HUBs */ diff --git a/freebsd/sys/dev/usb/usb_msctest.c b/freebsd/sys/dev/usb/usb_msctest.c index cf29d09d..58849f13 100644 --- a/freebsd/sys/dev/usb/usb_msctest.c +++ b/freebsd/sys/dev/usb/usb_msctest.c @@ -553,13 +553,13 @@ bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun, memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len); DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw->CBWCDB, ":"); - mtx_lock(&sc->mtx); + USB_MTX_LOCK(&sc->mtx); usbd_transfer_start(sc->xfer[sc->state]); while (usbd_transfer_pending(sc->xfer[sc->state])) { cv_wait(&sc->cv, &sc->mtx); } - mtx_unlock(&sc->mtx); + USB_MTX_UNLOCK(&sc->mtx); return (sc->error); } @@ -584,11 +584,11 @@ bbb_raw_write(struct bbb_transfer *sc, const void *data_ptr, size_t data_len, DPRINTFN(1, "BULK DATA = %*D\n", (int)data_len, (const char *)data_ptr, ":"); - mtx_lock(&sc->mtx); + USB_MTX_LOCK(&sc->mtx); usbd_transfer_start(sc->xfer[0]); while (usbd_transfer_pending(sc->xfer[0])) cv_wait(&sc->cv, &sc->mtx); - mtx_unlock(&sc->mtx); + USB_MTX_UNLOCK(&sc->mtx); return (sc->error); } diff --git a/freebsd/sys/dev/usb/usb_process.c b/freebsd/sys/dev/usb/usb_process.c index 219a736a..569550e6 100644 --- a/freebsd/sys/dev/usb/usb_process.c +++ b/freebsd/sys/dev/usb/usb_process.c @@ -121,7 +121,7 @@ usb_process(void *arg) thread_unlock(td); #endif /* __rtems__ */ - mtx_lock(up->up_mtx); + USB_MTX_LOCK(up->up_mtx); up->up_curtd = td; @@ -190,7 +190,7 @@ usb_process(void *arg) continue; } - /* end if messages - check if anyone is waiting for sync */ + /* end of messages - check if anyone is waiting for sync */ if (up->up_dsleep) { up->up_dsleep = 0; cv_broadcast(&up->up_drain); @@ -201,7 +201,7 @@ usb_process(void *arg) up->up_ptr = NULL; cv_signal(&up->up_cv); - mtx_unlock(up->up_mtx); + USB_MTX_UNLOCK(up->up_mtx); #if (__FreeBSD_version >= 800000) /* Clear the proc pointer if this is the last thread. */ if (--usb_pcount == 0) @@ -297,11 +297,12 @@ usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1) usb_size_t d; uint8_t t; - /* check if gone, return dummy value */ - if (up->up_gone) + /* check if gone or in polling mode, return dummy value */ + if (up->up_gone != 0 || + USB_IN_POLLING_MODE_FUNC() != 0) return (_pm0); - mtx_assert(up->up_mtx, MA_OWNED); + USB_MTX_ASSERT(up->up_mtx, MA_OWNED); t = 0; @@ -382,7 +383,7 @@ usb_proc_is_gone(struct usb_process *up) * structure is initialised. */ if (up->up_mtx != NULL) - mtx_assert(up->up_mtx, MA_OWNED); + USB_MTX_ASSERT(up->up_mtx, MA_OWNED); return (0); } @@ -403,7 +404,7 @@ usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1) if (up->up_gone) return; - mtx_assert(up->up_mtx, MA_OWNED); + USB_MTX_ASSERT(up->up_mtx, MA_OWNED); if (up->up_curtd == curthread) { /* Just remove the messages from the queue. */ @@ -443,9 +444,9 @@ usb_proc_drain(struct usb_process *up) return; /* handle special case with Giant */ if (up->up_mtx != &Giant) - mtx_assert(up->up_mtx, MA_NOTOWNED); + USB_MTX_ASSERT(up->up_mtx, MA_NOTOWNED); - mtx_lock(up->up_mtx); + USB_MTX_LOCK(up->up_mtx); /* Set the gone flag */ @@ -482,7 +483,7 @@ usb_proc_drain(struct usb_process *up) DPRINTF("WARNING: Someone is waiting " "for USB process drain!\n"); } - mtx_unlock(up->up_mtx); + USB_MTX_UNLOCK(up->up_mtx); } /*------------------------------------------------------------------------* @@ -503,7 +504,7 @@ usb_proc_rewakeup(struct usb_process *up) if (up->up_gone) return; - mtx_assert(up->up_mtx, MA_OWNED); + USB_MTX_ASSERT(up->up_mtx, MA_OWNED); if (up->up_msleep == 0) { /* re-wakeup */ diff --git a/freebsd/sys/dev/usb/usb_request.c b/freebsd/sys/dev/usb/usb_request.c index f092094b..2d7634a2 100644 --- a/freebsd/sys/dev/usb/usb_request.c +++ b/freebsd/sys/dev/usb/usb_request.c @@ -457,21 +457,14 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, return (USB_ERR_INVAL); #endif if ((mtx != NULL) && (mtx != &Giant)) { - mtx_unlock(mtx); - mtx_assert(mtx, MA_NOTOWNED); + USB_MTX_UNLOCK(mtx); + USB_MTX_ASSERT(mtx, MA_NOTOWNED); } /* - * Grab the USB device enumeration SX-lock serialization is - * achieved when multiple threads are involved: + * Serialize access to this function: */ - do_unlock = usbd_enum_lock(udev); - - /* - * We need to allow suspend and resume at this point, else the - * control transfer will timeout if the device is suspended! - */ - usbd_sr_unlock(udev); + do_unlock = usbd_ctrl_lock(udev); hr_func = usbd_get_hr_func(udev); @@ -715,13 +708,11 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, USB_XFER_UNLOCK(xfer); done: - usbd_sr_lock(udev); - if (do_unlock) - usbd_enum_unlock(udev); + usbd_ctrl_unlock(udev); if ((mtx != NULL) && (mtx != &Giant)) - mtx_lock(mtx); + USB_MTX_LOCK(mtx); switch (err) { case USB_ERR_NORMAL_COMPLETION: diff --git a/freebsd/sys/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c index 9bb68fd3..9cd40349 100644 --- a/freebsd/sys/dev/usb/usb_transfer.c +++ b/freebsd/sys/dev/usb/usb_transfer.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include @@ -341,12 +340,12 @@ usbd_transfer_setup_sub_malloc(struct usb_setup_params *parm, pc->buffer = USB_ADD_BYTES(buf, y * size); pc->page_start = pg; - mtx_lock(pc->tag_parent->mtx); + USB_MTX_LOCK(pc->tag_parent->mtx); if (usb_pc_load_mem(pc, size, 1 /* synchronous */ )) { - mtx_unlock(pc->tag_parent->mtx); + USB_MTX_UNLOCK(pc->tag_parent->mtx); return (1); /* failure */ } - mtx_unlock(pc->tag_parent->mtx); + USB_MTX_UNLOCK(pc->tag_parent->mtx); } } } @@ -983,7 +982,7 @@ usbd_transfer_setup(struct usb_device *udev, return (error); /* Protect scratch area */ - do_unlock = usbd_enum_lock(udev); + do_unlock = usbd_ctrl_lock(udev); refcount = 0; info = NULL; @@ -1304,7 +1303,7 @@ done: error = parm->err; if (do_unlock) - usbd_enum_unlock(udev); + usbd_ctrl_unlock(udev); return (error); } @@ -2292,14 +2291,14 @@ usb_callback_proc(struct usb_proc_msg *_pm) * We exploit the fact that the mutex is the same for all * callbacks that will be called from this thread: */ - mtx_lock(info->xfer_mtx); + USB_MTX_LOCK(info->xfer_mtx); USB_BUS_LOCK(info->bus); /* Continue where we lost track */ usb_command_wrapper(&info->done_q, info->done_q.curr); - mtx_unlock(info->xfer_mtx); + USB_MTX_UNLOCK(info->xfer_mtx); } /*------------------------------------------------------------------------* @@ -2352,7 +2351,7 @@ usbd_callback_wrapper(struct usb_xfer_queue *pq) USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED); if ((pq->recurse_3 != 0 || mtx_owned(info->xfer_mtx) == 0) && - SCHEDULER_STOPPED() == 0) { + USB_IN_POLLING_MODE_FUNC() == 0) { /* * Cases that end up here: * @@ -3333,7 +3332,9 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max) struct usb_xfer_root *xroot; struct usb_device *udev; struct usb_proc_msg *pm; + struct usb_bus *bus; uint16_t n; + uint16_t drop_bus_spin; uint16_t drop_bus; uint16_t drop_xfer; @@ -3348,38 +3349,47 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max) udev = xroot->udev; if (udev == NULL) continue; /* no USB device */ - if (udev->bus == NULL) + bus = udev->bus; + if (bus == NULL) continue; /* no BUS structure */ - if (udev->bus->methods == NULL) + if (bus->methods == NULL) continue; /* no BUS methods */ - if (udev->bus->methods->xfer_poll == NULL) + if (bus->methods->xfer_poll == NULL) continue; /* no poll method */ - /* make sure that the BUS mutex is not locked */ + drop_bus_spin = 0; drop_bus = 0; - while (mtx_owned(&xroot->udev->bus->bus_mtx) && !SCHEDULER_STOPPED()) { - mtx_unlock(&xroot->udev->bus->bus_mtx); - drop_bus++; - } - - /* make sure that the transfer mutex is not locked */ drop_xfer = 0; - while (mtx_owned(xroot->xfer_mtx) && !SCHEDULER_STOPPED()) { - mtx_unlock(xroot->xfer_mtx); - drop_xfer++; + + if (USB_IN_POLLING_MODE_FUNC() == 0) { + /* make sure that the BUS spin mutex is not locked */ + while (mtx_owned(&bus->bus_spin_lock)) { + mtx_unlock_spin(&bus->bus_spin_lock); + drop_bus_spin++; + } + + /* make sure that the BUS mutex is not locked */ + while (mtx_owned(&bus->bus_mtx)) { + mtx_unlock(&bus->bus_mtx); + drop_bus++; + } + + /* make sure that the transfer mutex is not locked */ + while (mtx_owned(xroot->xfer_mtx)) { + mtx_unlock(xroot->xfer_mtx); + drop_xfer++; + } } -#if USB_HAVE_PER_BUS_PROCESS /* Make sure cv_signal() and cv_broadcast() is not called */ - USB_BUS_CONTROL_XFER_PROC(udev->bus)->up_msleep = 0; - USB_BUS_EXPLORE_PROC(udev->bus)->up_msleep = 0; - USB_BUS_GIANT_PROC(udev->bus)->up_msleep = 0; - USB_BUS_NON_GIANT_ISOC_PROC(udev->bus)->up_msleep = 0; - USB_BUS_NON_GIANT_BULK_PROC(udev->bus)->up_msleep = 0; -#endif + USB_BUS_CONTROL_XFER_PROC(bus)->up_msleep = 0; + USB_BUS_EXPLORE_PROC(bus)->up_msleep = 0; + USB_BUS_GIANT_PROC(bus)->up_msleep = 0; + USB_BUS_NON_GIANT_ISOC_PROC(bus)->up_msleep = 0; + USB_BUS_NON_GIANT_BULK_PROC(bus)->up_msleep = 0; /* poll USB hardware */ - (udev->bus->methods->xfer_poll) (udev->bus); + (bus->methods->xfer_poll) (bus); USB_BUS_LOCK(xroot->bus); @@ -3407,7 +3417,11 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max) /* restore BUS mutex */ while (drop_bus--) - mtx_lock(&xroot->udev->bus->bus_mtx); + mtx_lock(&bus->bus_mtx); + + /* restore BUS spin mutex */ + while (drop_bus_spin--) + mtx_lock_spin(&bus->bus_spin_lock); } } diff --git a/freebsd/sys/dev/usb/usb_util.c b/freebsd/sys/dev/usb/usb_util.c index a2a5cee7..377c2341 100644 --- a/freebsd/sys/dev/usb/usb_util.c +++ b/freebsd/sys/dev/usb/usb_util.c @@ -100,7 +100,7 @@ device_set_usb_desc(device_t dev) } /* Protect scratch area */ - do_unlock = usbd_enum_lock(udev); + do_unlock = usbd_ctrl_lock(udev); temp_p = (char *)udev->scratch.data; @@ -117,7 +117,7 @@ device_set_usb_desc(device_t dev) } if (do_unlock) - usbd_enum_unlock(udev); + usbd_ctrl_unlock(udev); device_set_desc_copy(dev, temp_p); device_printf(dev, "<%s> on %s\n", temp_p, diff --git a/freebsd/sys/dev/usb/usbdi.h b/freebsd/sys/dev/usb/usbdi.h index 202ad89f..6ad3e43e 100644 --- a/freebsd/sys/dev/usb/usbdi.h +++ b/freebsd/sys/dev/usb/usbdi.h @@ -434,6 +434,39 @@ struct usb_attach_arg { #define UAA_DEV_EJECTING 2 }; +/* + * General purpose locking wrappers to ease supporting + * USB polled mode: + */ +#ifdef INVARIANTS +#define USB_MTX_ASSERT(_m, _t) do { \ + if (!USB_IN_POLLING_MODE_FUNC()) \ + mtx_assert(_m, _t); \ +} while (0) +#else +#define USB_MTX_ASSERT(_m, _t) do { } while (0) +#endif + +#define USB_MTX_LOCK(_m) do { \ + if (!USB_IN_POLLING_MODE_FUNC()) \ + mtx_lock(_m); \ +} while (0) + +#define USB_MTX_UNLOCK(_m) do { \ + if (!USB_IN_POLLING_MODE_FUNC()) \ + mtx_unlock(_m); \ +} while (0) + +#define USB_MTX_LOCK_SPIN(_m) do { \ + if (!USB_IN_POLLING_MODE_FUNC()) \ + mtx_lock_spin(_m); \ +} while (0) + +#define USB_MTX_UNLOCK_SPIN(_m) do { \ + if (!USB_IN_POLLING_MODE_FUNC()) \ + mtx_unlock_spin(_m); \ +} while (0) + /* * The following is a wrapper for the callout structure to ease * porting the code to other platforms. @@ -442,8 +475,26 @@ struct usb_callout { struct callout co; }; #define usb_callout_init_mtx(c,m,f) callout_init_mtx(&(c)->co,m,f) -#define usb_callout_reset(c,t,f,d) callout_reset(&(c)->co,t,f,d) -#define usb_callout_stop(c) callout_stop(&(c)->co) +#define usb_callout_reset(c,...) do { \ + if (!USB_IN_POLLING_MODE_FUNC()) \ + callout_reset(&(c)->co, __VA_ARGS__); \ +} while (0) +#define usb_callout_reset_sbt(c,...) do { \ + if (!USB_IN_POLLING_MODE_FUNC()) \ + callout_reset_sbt(&(c)->co, __VA_ARGS__); \ +} while (0) +#define usb_callout_stop(c) do { \ + if (!USB_IN_POLLING_MODE_FUNC()) { \ + callout_stop(&(c)->co); \ + } else { \ + /* \ + * Cannot stop callout when \ + * polling. Set dummy callback \ + * function instead: \ + */ \ + (c)->co.c_func = &usbd_dummy_timeout; \ + } \ +} while (0) #define usb_callout_drain(c) callout_drain(&(c)->co) #define usb_callout_pending(c) callout_pending(&(c)->co) @@ -623,6 +674,8 @@ void usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset, void usbd_start_re_enumerate(struct usb_device *udev); usb_error_t usbd_start_set_config(struct usb_device *, uint8_t); +int usbd_in_polling_mode(void); +void usbd_dummy_timeout(void *); int usb_fifo_attach(struct usb_device *udev, void *priv_sc, struct mtx *priv_mtx, struct usb_fifo_methods *pm, diff --git a/freebsd/sys/i386/include/machine/md_var.h b/freebsd/sys/i386/include/machine/md_var.h index c3caf07a..c93d70c8 100644 --- a/freebsd/sys/i386/include/machine/md_var.h +++ b/freebsd/sys/i386/include/machine/md_var.h @@ -65,6 +65,7 @@ void i686_pagezero(void *addr); void sse2_pagezero(void *addr); void init_AMD_Elan_sc520(void); vm_paddr_t kvtop(void *addr); +void panicifcpuunsupported(void); void ppro_reenable_apic(void); void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec); union savefpu *get_pcb_user_save_td(struct thread *td); diff --git a/freebsd/sys/kern/init_main.c b/freebsd/sys/kern/init_main.c index 627c01e0..72bab872 100644 --- a/freebsd/sys/kern/init_main.c +++ b/freebsd/sys/kern/init_main.c @@ -215,9 +215,9 @@ void mi_startup(void) { - register struct sysinit **sipp; /* system initialization*/ - register struct sysinit **xipp; /* interior loop of sort*/ - register struct sysinit *save; /* bubble*/ + struct sysinit **sipp; /* system initialization*/ + struct sysinit **xipp; /* interior loop of sort*/ + struct sysinit *save; /* bubble*/ #ifdef __rtems__ struct sysinit **sysinit = NULL; struct sysinit **sysinit_end = NULL; @@ -339,16 +339,7 @@ restart: #endif /* __rtems__ */ } - #ifndef __rtems__ -/* - *************************************************************************** - **** - **** The following SYSINIT's belong elsewhere, but have not yet - **** been moved. - **** - *************************************************************************** - */ static void print_caddr_t(void *data) { @@ -442,17 +433,10 @@ struct sysentvec null_sysvec = { }; /* - *************************************************************************** - **** - **** The two following SYSINIT's are proc0 specific glue code. I am not - **** convinced that they can not be safely combined, but their order of - **** operation has been maintained as the same as the original init_main.c - **** for right now. - **** - **** These probably belong in init_proc.c or kern_proc.c, since they - **** deal with proc0 (the fork template process). - **** - *************************************************************************** + * The two following SYSINIT's are proc0 specific glue code. I am not + * convinced that they can not be safely combined, but their order of + * operation has been maintained as the same as the original init_main.c + * for right now. */ /* ARGSUSED*/ static void @@ -686,16 +670,6 @@ SYSINIT(random, SI_SUB_RANDOM, SI_ORDER_FIRST, random_init, NULL); *************************************************************************** */ - -/* - *************************************************************************** - **** - **** The following code probably belongs in another file, like - **** kern/init_init.c. - **** - *************************************************************************** - */ - /* * List of paths to try when searching for "init". */ @@ -843,7 +817,7 @@ start_init(void *dummy) } /* - * Like kproc_create(), but runs in it's own address space. + * Like kproc_create(), but runs in its own address space. * We do this early to reserve pid 1. * * Note special case - do not make it runnable yet. Other work diff --git a/freebsd/sys/kern/kern_condvar.c b/freebsd/sys/kern/kern_condvar.c index 239640e2..6358c376 100644 --- a/freebsd/sys/kern/kern_condvar.c +++ b/freebsd/sys/kern/kern_condvar.c @@ -407,6 +407,8 @@ cv_signal(struct cv *cvp) { int wakeup_swapper; + if (cvp->cv_waiters == 0) + return; wakeup_swapper = 0; sleepq_lock(cvp); if (cvp->cv_waiters > 0) { @@ -434,6 +436,8 @@ cv_broadcastpri(struct cv *cvp, int pri) { int wakeup_swapper; + if (cvp->cv_waiters == 0) + return; /* * XXX sleepq_broadcast pri argument changed from -1 meaning * no pri to 0 meaning no pri. diff --git a/freebsd/sys/kern/kern_linker.c b/freebsd/sys/kern/kern_linker.c index a115aa96..82a33023 100644 --- a/freebsd/sys/kern/kern_linker.c +++ b/freebsd/sys/kern/kern_linker.c @@ -1615,7 +1615,6 @@ restart: if (error) panic("cannot add dependency"); } - lf->userrefs++; /* so we can (try to) kldunload it */ error = linker_file_lookup_set(lf, MDT_SETNAME, &start, &stop, NULL); if (!error) { @@ -1653,6 +1652,8 @@ restart: goto fail; } linker_file_register_modules(lf); + if (!TAILQ_EMPTY(&lf->modules)) + lf->flags |= LINKER_FILE_MODULES; if (linker_file_lookup_set(lf, "sysinit_set", &si_start, &si_stop, NULL) == 0) sysinit_add(si_start, si_stop); @@ -1669,6 +1670,41 @@ fail: SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0); +/* + * Handle preload files that failed to load any modules. + */ +static void +linker_preload_finish(void *arg) +{ + linker_file_t lf, nlf; + + sx_xlock(&kld_sx); + TAILQ_FOREACH_SAFE(lf, &linker_files, link, nlf) { + /* + * If all of the modules in this file failed to load, unload + * the file and return an error of ENOEXEC. (Parity with + * linker_load_file.) + */ + if ((lf->flags & LINKER_FILE_MODULES) != 0 && + TAILQ_EMPTY(&lf->modules)) { + linker_file_unload(lf, LINKER_UNLOAD_FORCE); + continue; + } + + lf->flags &= ~LINKER_FILE_MODULES; + lf->userrefs++; /* so we can (try to) kldunload it */ + } + sx_xunlock(&kld_sx); +} + +/* + * Attempt to run after all DECLARE_MODULE SYSINITs. Unfortunately they can be + * scheduled at any subsystem and order, so run this as late as possible. init + * becomes runnable in SI_SUB_KTHREAD_INIT, so go slightly before that. + */ +SYSINIT(preload_finish, SI_SUB_KTHREAD_INIT - 100, SI_ORDER_MIDDLE, + linker_preload_finish, 0); + /* * Search for a not-loaded module by name. * diff --git a/freebsd/sys/kern/kern_mib.c b/freebsd/sys/kern/kern_mib.c index aa1c5774..63d8b44f 100644 --- a/freebsd/sys/kern/kern_mib.c +++ b/freebsd/sys/kern/kern_mib.c @@ -18,7 +18,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -144,9 +144,12 @@ SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD|CTLFLAG_CAPRD, char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ -SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, CTLFLAG_RW, +SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, CTLFLAG_RW | CTLFLAG_MPSAFE, kernelname, sizeof kernelname, "Name of kernel file booted"); +SYSCTL_INT(_kern, KERN_MAXPHYS, maxphys, CTLFLAG_RD | CTLFLAG_CAPRD, + SYSCTL_NULL_INT_PTR, MAXPHYS, "Maximum block I/O access size"); + SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD|CTLFLAG_CAPRD, &mp_ncpus, 0, "Number of active CPUs"); @@ -263,8 +266,9 @@ sysctl_hw_machine_arch(SYSCTL_HANDLER_ARGS) return (error); } -SYSCTL_PROC(_hw, HW_MACHINE_ARCH, machine_arch, CTLTYPE_STRING | CTLFLAG_RD, - NULL, 0, sysctl_hw_machine_arch, "A", "System architecture"); +SYSCTL_PROC(_hw, HW_MACHINE_ARCH, machine_arch, CTLTYPE_STRING | CTLFLAG_RD | + CTLFLAG_MPSAFE, NULL, 0, sysctl_hw_machine_arch, "A", + "System architecture"); #endif /* __rtems__ */ SYSCTL_STRING(_kern, OID_AUTO, supported_archs, CTLFLAG_RD | CTLFLAG_MPSAFE, @@ -339,15 +343,15 @@ sysctl_hostname(SYSCTL_HANDLER_ARGS) } SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname, - CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_CAPRD | CTLFLAG_MPSAFE, (void *)(offsetof(struct prison, pr_hostname)), MAXHOSTNAMELEN, sysctl_hostname, "A", "Hostname"); SYSCTL_PROC(_kern, KERN_NISDOMAINNAME, domainname, - CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_CAPRD | CTLFLAG_MPSAFE, (void *)(offsetof(struct prison, pr_domainname)), MAXHOSTNAMELEN, sysctl_hostname, "A", "Name of the current YP/NIS domain"); SYSCTL_PROC(_kern, KERN_HOSTUUID, hostuuid, - CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_CAPRD | CTLFLAG_MPSAFE, (void *)(offsetof(struct prison, pr_hostuuid)), HOSTUUIDLEN, sysctl_hostname, "A", "Host UUID"); @@ -407,8 +411,8 @@ SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel, /* Actual kernel configuration options. */ extern char kernconfstring[]; -SYSCTL_STRING(_kern, OID_AUTO, conftxt, CTLFLAG_RD, kernconfstring, 0, - "Kernel configuration file"); +SYSCTL_STRING(_kern, OID_AUTO, conftxt, CTLFLAG_RD | CTLFLAG_MPSAFE, + kernconfstring, 0, "Kernel configuration file"); #endif static int diff --git a/freebsd/sys/kern/kern_synch.c b/freebsd/sys/kern/kern_synch.c index 6ecedfd2..6a8e7754 100644 --- a/freebsd/sys/kern/kern_synch.c +++ b/freebsd/sys/kern/kern_synch.c @@ -17,7 +17,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -191,13 +191,7 @@ _sleep(void *ident, struct lock_object *lock, int priority, pri = priority; #endif /* __rtems__ */ - /* - * If we are already on a sleep queue, then remove us from that - * sleep queue first. We have to do this to handle recursive - * sleeps. - */ - if (TD_ON_SLEEPQ(td)) - sleepq_remove(td, td->td_wchan); + KASSERT(!TD_ON_SLEEPQ(td), ("recursive sleep")); if ((uint8_t *)ident >= &pause_wchan[0] && (uint8_t *)ident <= &pause_wchan[MAXCPU - 1]) diff --git a/freebsd/sys/kern/kern_sysctl.c b/freebsd/sys/kern/kern_sysctl.c index 3bcf6688..07ddded9 100644 --- a/freebsd/sys/kern/kern_sysctl.c +++ b/freebsd/sys/kern/kern_sysctl.c @@ -18,7 +18,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/freebsd/sys/kern/kern_time.c b/freebsd/sys/kern/kern_time.c index 2fb4dd2e..95111932 100644 --- a/freebsd/sys/kern/kern_time.c +++ b/freebsd/sys/kern/kern_time.c @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/freebsd/sys/kern/kern_timeout.c b/freebsd/sys/kern/kern_timeout.c index 37ec0956..73b55338 100644 --- a/freebsd/sys/kern/kern_timeout.c +++ b/freebsd/sys/kern/kern_timeout.c @@ -17,7 +17,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -1059,6 +1059,8 @@ callout_when(sbintime_t sbt, sbintime_t precision, int flags, spinlock_exit(); #endif #endif + if (cold && to_sbt == 0) + to_sbt = sbinuptime(); if ((flags & C_HARDCLOCK) == 0) to_sbt += tick_sbt; } else diff --git a/freebsd/sys/kern/subr_bus.c b/freebsd/sys/kern/subr_bus.c index 3eb7d7e9..1175456c 100644 --- a/freebsd/sys/kern/subr_bus.c +++ b/freebsd/sys/kern/subr_bus.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include @@ -67,6 +68,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL); SYSCTL_ROOT_NODE(OID_AUTO, dev, CTLFLAG_RW, NULL, NULL); @@ -147,6 +150,9 @@ static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc"); static void devctl2_init(void); #endif /* __rtems__ */ +#define DRIVERNAME(d) ((d)? d->name : "no driver") +#define DEVCLANAME(d) ((d)? d->name : "no devclass") + #ifdef BUS_DEBUG static int bus_debug = 1; @@ -155,8 +161,6 @@ SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RWTUN, &bus_debug, 0, #define PDEBUG(a) if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");} #define DEVICENAME(d) ((d)? device_get_name(d): "no device") -#define DRIVERNAME(d) ((d)? d->name : "no driver") -#define DEVCLANAME(d) ((d)? d->name : "no devclass") /** * Produce the indenting, indent*2 spaces plus a '.' ahead of that to @@ -180,8 +184,6 @@ void print_devclass_list(void); /* Make the compiler ignore the function calls */ #define PDEBUG(a) /* nop */ #define DEVICENAME(d) /* nop */ -#define DRIVERNAME(d) /* nop */ -#define DEVCLANAME(d) /* nop */ #define print_device_short(d,i) /* nop */ #define print_device(d,i) /* nop */ @@ -1981,15 +1983,17 @@ device_delete_child(device_t dev, device_t child) PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev))); - /* remove children first */ + /* detach parent before deleting children, if any */ + if ((error = device_detach(child)) != 0) + return (error); + + /* remove children second */ while ((grandchild = TAILQ_FIRST(&child->children)) != NULL) { error = device_delete_child(child, grandchild); if (error) return (error); } - if ((error = device_detach(child)) != 0) - return (error); if (child->devclass) devclass_delete_device(child->devclass, child); if (child->parent) @@ -2179,6 +2183,12 @@ device_probe_child(device_t dev, device_t child) break; } + /* + * Reset DF_QUIET in case this driver doesn't + * end up as the best driver. + */ + device_verbose(child); + /* * Probes that return BUS_PROBE_NOWILDCARD or lower * only match on devices whose driver was explicitly @@ -3008,6 +3018,7 @@ device_detach(device_t dev) if (!(dev->flags & DF_FIXEDCLASS)) devclass_delete_device(dev->devclass, dev); + device_verbose(dev); dev->state = DS_NOTPRESENT; (void)device_set_driver(dev, NULL); device_sysctl_fini(dev); @@ -5396,6 +5407,7 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, case DEV_SUSPEND: case DEV_RESUME: case DEV_SET_DRIVER: + case DEV_CLEAR_DRIVER: case DEV_RESCAN: case DEV_DELETE: error = priv_check(td, PRIV_DRIVER); @@ -5561,6 +5573,25 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, error = device_probe_and_attach(dev); break; } + case DEV_CLEAR_DRIVER: + if (!(dev->flags & DF_FIXEDCLASS)) { + error = 0; + break; + } + if (device_is_attached(dev)) { + if (req->dr_flags & DEVF_CLEAR_DRIVER_DETACH) + error = device_detach(dev); + else + error = EBUSY; + if (error) + break; + } + + dev->flags &= ~DF_FIXEDCLASS; + dev->flags |= DF_WILDCARD; + devclass_delete_device(dev->devclass, dev); + error = device_probe_and_attach(dev); + break; case DEV_RESCAN: if (!device_is_attached(dev)) { error = ENXIO; @@ -5604,4 +5635,33 @@ devctl2_init(void) make_dev_credf(MAKEDEV_ETERNAL, &devctl2_cdevsw, 0, NULL, UID_ROOT, GID_WHEEL, 0600, "devctl2"); } + +#ifdef DDB +DB_SHOW_COMMAND(device, db_show_device) +{ + device_t dev; + + if (!have_addr) + return; + + dev = (device_t)addr; + + db_printf("name: %s\n", device_get_nameunit(dev)); + db_printf(" driver: %s\n", DRIVERNAME(dev->driver)); + db_printf(" class: %s\n", DEVCLANAME(dev->devclass)); + db_printf(" addr: %p\n", dev); + db_printf(" parent: %p\n", dev->parent); + db_printf(" softc: %p\n", dev->softc); + db_printf(" ivars: %p\n", dev->ivars); +} + +DB_SHOW_ALL_COMMAND(devices, db_show_all_devices) +{ + device_t dev; + + TAILQ_FOREACH(dev, &bus_data_devices, devlink) { + db_show_device((db_expr_t)dev, true, count, modif); + } +} +#endif #endif /* __rtems__ */ diff --git a/freebsd/sys/kern/subr_hash.c b/freebsd/sys/kern/subr_hash.c index 1371a345..425fd34d 100644 --- a/freebsd/sys/kern/subr_hash.c +++ b/freebsd/sys/kern/subr_hash.c @@ -17,7 +17,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/freebsd/sys/kern/subr_pcpu.c b/freebsd/sys/kern/subr_pcpu.c index 4d223899..5c244b42 100644 --- a/freebsd/sys/kern/subr_pcpu.c +++ b/freebsd/sys/kern/subr_pcpu.c @@ -16,7 +16,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the author nor the names of any co-contributors + * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/freebsd/sys/kern/subr_prf.c b/freebsd/sys/kern/subr_prf.c index 9273cd2a..2aed7f68 100644 --- a/freebsd/sys/kern/subr_prf.c +++ b/freebsd/sys/kern/subr_prf.c @@ -17,7 +17,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -80,7 +80,11 @@ __FBSDID("$FreeBSD$"); * Note that stdarg.h and the ANSI style va_start macro is used for both * ANSI and traditional C compilers. */ +#ifdef _KERNEL #include +#else +#include +#endif #ifdef _KERNEL diff --git a/freebsd/sys/kern/subr_sleepqueue.c b/freebsd/sys/kern/subr_sleepqueue.c index be8e7721..a42c62f8 100644 --- a/freebsd/sys/kern/subr_sleepqueue.c +++ b/freebsd/sys/kern/subr_sleepqueue.c @@ -434,7 +434,7 @@ sleepq_set_timeout_sbt(void *wchan, sbintime_t sbt, sbintime_t pr, MPASS(TD_ON_SLEEPQ(td)); MPASS(td->td_sleepqueue == NULL); MPASS(wchan != NULL); - if (cold) + if (cold && td == &thread0) panic("timed sleep before timers are working"); KASSERT(td->td_sleeptimo == 0, ("td %d %p td_sleeptimo %jx", td->td_tid, td, (uintmax_t)td->td_sleeptimo)); @@ -1089,9 +1089,9 @@ sleepq_signal(void *wchan, int flags, int pri, int queue) * been sleeping the longest since threads are always added to * the tail of sleep queues. */ - besttd = NULL; + besttd = TAILQ_FIRST(&sq->sq_blocked[queue]); TAILQ_FOREACH(td, &sq->sq_blocked[queue], td_slpq) { - if (besttd == NULL || td->td_priority < besttd->td_priority) + if (td->td_priority < besttd->td_priority) besttd = td; } #else /* __rtems__ */ diff --git a/freebsd/sys/kern/subr_taskqueue.c b/freebsd/sys/kern/subr_taskqueue.c index 8580e8fc..5ef8683c 100644 --- a/freebsd/sys/kern/subr_taskqueue.c +++ b/freebsd/sys/kern/subr_taskqueue.c @@ -89,6 +89,7 @@ struct taskqueue { #define TQ_FLAGS_UNLOCKED_ENQUEUE (1 << 2) #define DT_CALLOUT_ARMED (1 << 0) +#define DT_DRAIN_IN_PROGRESS (1 << 1) #ifndef __rtems__ #define TQ_LOCK(tq) \ @@ -334,7 +335,11 @@ taskqueue_enqueue_timeout(struct taskqueue *queue, #endif /* __rtems__ */ timeout_task->q = queue; res = timeout_task->t.ta_pending; - if (ticks == 0) { + if (timeout_task->f & DT_DRAIN_IN_PROGRESS) { + /* Do nothing */ + TQ_UNLOCK(queue); + res = -1; + } else if (ticks == 0) { taskqueue_enqueue_locked(queue, &timeout_task->t); /* The lock is released inside. */ } else { @@ -598,8 +603,24 @@ taskqueue_drain_timeout(struct taskqueue *queue, struct timeout_task *timeout_task) { + /* + * Set flag to prevent timer from re-starting during drain: + */ + TQ_LOCK(queue); + KASSERT((timeout_task->f & DT_DRAIN_IN_PROGRESS) == 0, + ("Drain already in progress")); + timeout_task->f |= DT_DRAIN_IN_PROGRESS; + TQ_UNLOCK(queue); + callout_drain(&timeout_task->c); taskqueue_drain(queue, &timeout_task->t); + + /* + * Clear flag to allow timer to re-start: + */ + TQ_LOCK(queue); + timeout_task->f &= ~DT_DRAIN_IN_PROGRESS; + TQ_UNLOCK(queue); } static void @@ -666,6 +687,11 @@ _taskqueue_start_threads(struct taskqueue **tqp, int count, int pri, } else tq->tq_tcount++; } + if (tq->tq_tcount == 0) { + free(tq->tq_threads, M_TASKQUEUE); + tq->tq_threads = NULL; + return (ENOMEM); + } #ifndef __rtems__ for (i = 0; i < count; i++) { if (tq->tq_threads[i] == NULL) diff --git a/freebsd/sys/kern/subr_uio.c b/freebsd/sys/kern/subr_uio.c index a319685a..f5dc76e7 100644 --- a/freebsd/sys/kern/subr_uio.c +++ b/freebsd/sys/kern/subr_uio.c @@ -22,7 +22,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -556,7 +556,7 @@ fueword32(volatile const void *base, int32_t *val) int fueword64(volatile const void *base, int64_t *val) { - int32_t res; + int64_t res; res = fuword64(base); if (res == -1) diff --git a/freebsd/sys/kern/sys_generic.c b/freebsd/sys/kern/sys_generic.c index 26cd9d36..d6b3d15b 100644 --- a/freebsd/sys/kern/sys_generic.c +++ b/freebsd/sys/kern/sys_generic.c @@ -17,7 +17,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/freebsd/sys/kern/sys_socket.c b/freebsd/sys/kern/sys_socket.c index f312c8f4..a2537652 100644 --- a/freebsd/sys/kern/sys_socket.c +++ b/freebsd/sys/kern/sys_socket.c @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/freebsd/sys/kern/uipc_accf.c b/freebsd/sys/kern/uipc_accf.c index 6ecea0eb..7d6bde25 100644 --- a/freebsd/sys/kern/uipc_accf.c +++ b/freebsd/sys/kern/uipc_accf.c @@ -252,7 +252,7 @@ do_setopt_accept_filter(struct socket *so, struct sockopt *sopt) newaf = malloc(sizeof(*newaf), M_ACCF, M_WAITOK | M_ZERO); if (afp->accf_create != NULL && afap->af_name[0] != '\0') { - int len = strlen(afap->af_name) + 1; + size_t len = strlen(afap->af_name) + 1; newaf->so_accept_filter_str = malloc(len, M_ACCF, M_WAITOK); strcpy(newaf->so_accept_filter_str, afap->af_name); diff --git a/freebsd/sys/kern/uipc_domain.c b/freebsd/sys/kern/uipc_domain.c index 7c0e7085..ab301eb5 100644 --- a/freebsd/sys/kern/uipc_domain.c +++ b/freebsd/sys/kern/uipc_domain.c @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/freebsd/sys/kern/uipc_mbuf.c b/freebsd/sys/kern/uipc_mbuf.c index db4975ca..571dd3bd 100644 --- a/freebsd/sys/kern/uipc_mbuf.c +++ b/freebsd/sys/kern/uipc_mbuf.c @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -986,7 +986,7 @@ m_devget(char *buf, int totlen, int off, struct ifnet *ifp, len = MHLEN; /* Place initial small packet/header at end of mbuf */ - if (m && totlen + off + max_linkhdr <= MLEN) { + if (m && totlen + off + max_linkhdr <= MHLEN) { m->m_data += max_linkhdr; len -= max_linkhdr; } @@ -1338,7 +1338,7 @@ nospace: /* * Defragment an mbuf chain, returning at most maxfrags separate * mbufs+clusters. If this is not possible NULL is returned and - * the original mbuf chain is left in it's present (potentially + * the original mbuf chain is left in its present (potentially * modified) state. We use two techniques: collapsing consecutive * mbufs and replacing consecutive mbufs by a cluster. * diff --git a/freebsd/sys/kern/uipc_mbuf2.c b/freebsd/sys/kern/uipc_mbuf2.c index fef1c514..fc5c8e8a 100644 --- a/freebsd/sys/kern/uipc_mbuf2.c +++ b/freebsd/sys/kern/uipc_mbuf2.c @@ -43,7 +43,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/freebsd/sys/kern/uipc_sockbuf.c b/freebsd/sys/kern/uipc_sockbuf.c index f62014bc..a7977141 100644 --- a/freebsd/sys/kern/uipc_sockbuf.c +++ b/freebsd/sys/kern/uipc_sockbuf.c @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/freebsd/sys/kern/uipc_socket.c b/freebsd/sys/kern/uipc_socket.c index 3f2dba72..c086ee7c 100644 --- a/freebsd/sys/kern/uipc_socket.c +++ b/freebsd/sys/kern/uipc_socket.c @@ -15,7 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -1669,7 +1669,8 @@ dontblock: do { if (flags & MSG_PEEK) { if (controlp != NULL) { - *controlp = m_copy(m, 0, m->m_len); + *controlp = m_copym(m, 0, m->m_len, + M_NOWAIT); controlp = &(*controlp)->m_next; } m = m->m_next; diff --git a/freebsd/sys/kern/uipc_syscalls.c b/freebsd/sys/kern/uipc_syscalls.c index 99ae6392..2d81fc20 100644 --- a/freebsd/sys/kern/uipc_syscalls.c +++ b/freebsd/sys/kern/uipc_syscalls.c @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -94,20 +94,23 @@ static int sockargs(struct mbuf **, char *, socklen_t, int); /* * Convert a user file descriptor to a kernel file entry and check if required * capability rights are present. + * If required copy of current set of capability rights is returned. * A reference on the file entry is held upon returning. */ int getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, - struct file **fpp, u_int *fflagp) + struct file **fpp, u_int *fflagp, struct filecaps *havecapsp) { struct file *fp; int error; - error = fget_unlocked(td->td_proc->p_fd, fd, rightsp, &fp, NULL); + error = fget_cap(td, fd, rightsp, &fp, havecapsp); if (error != 0) return (error); if (fp->f_type != DTYPE_SOCKET) { fdrop(fp, td); + if (havecapsp != NULL) + filecaps_free(havecapsp); return (ENOTSOCK); } if (fflagp != NULL) @@ -148,7 +151,7 @@ rtems_bsd_getsock(int fd, struct file **fpp, u_int *fflagp) return (error); } -#define getsock_cap(td, fd, rights, fpp, fflagp) rtems_bsd_getsock(fd, fpp, fflagp) +#define getsock_cap(td, fd, rights, fpp, fflagp, havecapsp) rtems_bsd_getsock(fd, fpp, fflagp) #endif /* __rtems__ */ /* @@ -162,13 +165,7 @@ rtems_bsd_getsock(int fd, struct file **fpp, u_int *fflagp) static #endif /* __rtems__ */ int -sys_socket(td, uap) - struct thread *td; - struct socket_args /* { - int domain; - int type; - int protocol; - } */ *uap; +sys_socket(struct thread *td, struct socket_args *uap) { struct socket *so; struct file *fp; @@ -239,7 +236,6 @@ socket(int domain, int type, int protocol) } #endif /* __rtems__ */ -/* ARGSUSED */ #ifdef __rtems__ static int kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa); @@ -247,13 +243,7 @@ static int kern_bindat(struct thread *td, int dirfd, int fd, static #endif /* __rtems__ */ int -sys_bind(td, uap) - struct thread *td; - struct bind_args /* { - int s; - caddr_t name; - int namelen; - } */ *uap; +sys_bind(struct thread *td, struct bind_args *uap) { struct sockaddr *sa; int error; @@ -298,7 +288,7 @@ kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) AUDIT_ARG_FD(fd); AUDIT_ARG_SOCKADDR(td, dirfd, sa); error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND), - &fp, NULL); + &fp, NULL, NULL); if (error != 0) return (error); so = fp->f_data; @@ -321,18 +311,10 @@ kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) return (error); } -/* ARGSUSED */ #ifndef __rtems__ static int -sys_bindat(td, uap) - struct thread *td; - struct bindat_args /* { - int fd; - int s; - caddr_t name; - int namelen; - } */ *uap; +sys_bindat(struct thread *td, struct bindat_args *uap) { struct sockaddr *sa; int error; @@ -346,14 +328,8 @@ sys_bindat(td, uap) } #endif /* __rtems__ */ -/* ARGSUSED */ int -sys_listen(td, uap) - struct thread *td; - struct listen_args /* { - int s; - int backlog; - } */ *uap; +sys_listen(struct thread *td, struct listen_args *uap) { struct socket *so; struct file *fp; @@ -362,7 +338,7 @@ sys_listen(td, uap) AUDIT_ARG_FD(uap->s); error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_LISTEN), - &fp, NULL); + &fp, NULL, NULL); if (error == 0) { so = fp->f_data; #ifdef MAC @@ -483,6 +459,7 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, struct file *headfp, *nfp = NULL; struct sockaddr *sa = NULL; struct socket *head, *so; + struct filecaps fcaps; cap_rights_t rights; u_int fflag; pid_t pgid; @@ -493,7 +470,7 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, AUDIT_ARG_FD(s); error = getsock_cap(td, s, cap_rights_init(&rights, CAP_ACCEPT), - &headfp, &fflag); + &headfp, &fflag, &fcaps); if (error != 0) return (error); head = headfp->f_data; @@ -506,7 +483,8 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, if (error != 0) goto done; #endif - error = falloc(td, &nfp, &fd, (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0); + error = falloc_caps(td, &nfp, &fd, + (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0, &fcaps); if (error != 0) goto done; ACCEPT_LOCK(); @@ -615,6 +593,8 @@ noconnection: * a reference on nfp to the caller on success if they request it. */ done: + if (nfp == NULL) + filecaps_free(&fcaps); if (fp != NULL) { if (error == 0) { *fp = nfp; @@ -663,7 +643,6 @@ oaccept(td, uap) #endif /* COMPAT_OLDSOCK */ #endif /* __rtems__ */ -/* ARGSUSED */ #ifdef __rtems__ static int kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa); @@ -671,13 +650,7 @@ static int kern_connectat(struct thread *td, int dirfd, int fd, static #endif /* __rtems__ */ int -sys_connect(td, uap) - struct thread *td; - struct connect_args /* { - int s; - caddr_t name; - int namelen; - } */ *uap; +sys_connect(struct thread *td, struct connect_args *uap) { struct sockaddr *sa; int error; @@ -722,7 +695,7 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) AUDIT_ARG_FD(fd); AUDIT_ARG_SOCKADDR(td, dirfd, sa); error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT), - &fp, NULL); + &fp, NULL, NULL); if (error != 0) return (error); so = fp->f_data; @@ -775,16 +748,8 @@ done1: } #ifndef __rtems__ -/* ARGSUSED */ int -sys_connectat(td, uap) - struct thread *td; - struct connectat_args /* { - int fd; - int s; - caddr_t name; - int namelen; - } */ *uap; +sys_connectat(struct thread *td, struct connectat_args *uap) { struct sockaddr *sa; int error; @@ -936,11 +901,7 @@ kern_sendit( struct thread *td, int s, struct msghdr *mp, int flags, struct mbuf *control, enum uio_seg segflg); #endif /* __rtems__ */ static int -sendit(td, s, mp, flags) - struct thread *td; - int s; - struct msghdr *mp; - int flags; +sendit(struct thread *td, int s, struct msghdr *mp, int flags) { struct mbuf *control; struct sockaddr *to; @@ -998,13 +959,8 @@ bad: } int -kern_sendit(td, s, mp, flags, control, segflg) - struct thread *td; - int s; - struct msghdr *mp; - int flags; - struct mbuf *control; - enum uio_seg segflg; +kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags, + struct mbuf *control, enum uio_seg segflg) { struct file *fp; struct uio auio; @@ -1026,12 +982,12 @@ kern_sendit(td, s, mp, flags, control, segflg) AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name); cap_rights_set(&rights, CAP_CONNECT); } - error = getsock_cap(td, s, &rights, &fp, NULL); - if (error != 0) #endif /* __rtems__ */ - error = getsock_cap(td->td_proc->p_fd, s, rights, &fp, NULL); - if (error) + error = getsock_cap(td, s, &rights, &fp, NULL, NULL); + if (error != 0) { + m_freem(control); return (error); + } so = (struct socket *)fp->f_data; #ifdef KTRACE @@ -1042,12 +998,16 @@ kern_sendit(td, s, mp, flags, control, segflg) if (mp->msg_name != NULL) { error = mac_socket_check_connect(td->td_ucred, so, mp->msg_name); - if (error != 0) + if (error != 0) { + m_freem(control); goto bad; + } } error = mac_socket_check_send(td->td_ucred, so); - if (error != 0) + if (error != 0) { + m_freem(control); goto bad; + } #endif auio.uio_iov = mp->msg_iov; @@ -1061,6 +1021,7 @@ kern_sendit(td, s, mp, flags, control, segflg) for (i = 0; i < mp->msg_iovlen; i++, iov++) { if ((auio.uio_resid += iov->iov_len) < 0) { error = EINVAL; + m_freem(control); goto bad; } } @@ -1103,16 +1064,7 @@ bad: static #endif /* __rtems__ */ int -sys_sendto(td, uap) - struct thread *td; - struct sendto_args /* { - int s; - caddr_t buf; - size_t len; - int flags; - caddr_t to; - int tolen; - } */ *uap; +sys_sendto(struct thread *td, struct sendto_args *uap) { struct msghdr msg; struct iovec aiov; @@ -1167,7 +1119,7 @@ rtems_bsd_sendto(int socket, struct mbuf *m, int flags, struct socket *so; int error; - error = getsock_cap(td->td_proc->p_fd, socket, CAP_WRITE, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, socket, CAP_WRITE, &fp, NULL, NULL); if (error) return (error); so = (struct socket *)fp->f_data; @@ -1186,14 +1138,7 @@ rtems_bsd_sendto(int socket, struct mbuf *m, int flags, #ifndef __rtems__ #ifdef COMPAT_OLDSOCK int -osend(td, uap) - struct thread *td; - struct osend_args /* { - int s; - caddr_t buf; - int len; - int flags; - } */ *uap; +osend(struct thread *td, struct osend_args *uap) { struct msghdr msg; struct iovec aiov; @@ -1210,13 +1155,7 @@ osend(td, uap) } int -osendmsg(td, uap) - struct thread *td; - struct osendmsg_args /* { - int s; - caddr_t msg; - int flags; - } */ *uap; +osendmsg(struct thread *td, struct osendmsg_args *uap) { struct msghdr msg; struct iovec *iov; @@ -1241,13 +1180,7 @@ osendmsg(td, uap) static #endif /* __rtems__ */ int -sys_sendmsg(td, uap) - struct thread *td; - struct sendmsg_args /* { - int s; - caddr_t msg; - int flags; - } */ *uap; +sys_sendmsg(struct thread *td, struct sendmsg_args *uap) { struct msghdr msg; struct iovec *iov; @@ -1297,12 +1230,8 @@ sendmsg(int socket, const struct msghdr *message, int flags) static #endif /* __rtems__ */ int -kern_recvit(td, s, mp, fromseg, controlp) - struct thread *td; - int s; - struct msghdr *mp; - enum uio_seg fromseg; - struct mbuf **controlp; +kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg, + struct mbuf **controlp) { struct uio auio; struct iovec *iov; @@ -1323,7 +1252,7 @@ kern_recvit(td, s, mp, fromseg, controlp) AUDIT_ARG_FD(s); error = getsock_cap(td, s, cap_rights_init(&rights, CAP_RECV), - &fp, NULL); + &fp, NULL, NULL); if (error != 0) return (error); so = fp->f_data; @@ -1459,11 +1388,7 @@ out: } static int -recvit(td, s, mp, namelenp) - struct thread *td; - int s; - struct msghdr *mp; - void *namelenp; +recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp) { int error; @@ -1484,16 +1409,7 @@ recvit(td, s, mp, namelenp) static #endif /* __rtems__ */ int -sys_recvfrom(td, uap) - struct thread *td; - struct recvfrom_args /* { - int s; - caddr_t buf; - size_t len; - int flags; - struct sockaddr * __restrict from; - socklen_t * __restrict fromlenaddr; - } */ *uap; +sys_recvfrom(struct thread *td, struct recvfrom_args *uap) { struct msghdr msg; struct iovec aiov; @@ -1551,9 +1467,7 @@ recvfrom(int socket, void *__restrict buffer, size_t length, int flags, #ifndef __rtems__ #ifdef COMPAT_OLDSOCK int -orecvfrom(td, uap) - struct thread *td; - struct recvfrom_args *uap; +orecvfrom(struct thread *td, struct recvfrom_args *uap) { uap->flags |= MSG_COMPAT; @@ -1563,14 +1477,7 @@ orecvfrom(td, uap) #ifdef COMPAT_OLDSOCK int -orecv(td, uap) - struct thread *td; - struct orecv_args /* { - int s; - caddr_t buf; - int len; - int flags; - } */ *uap; +orecv(struct thread *td, struct orecv_args *uap) { struct msghdr msg; struct iovec aiov; @@ -1592,13 +1499,7 @@ orecv(td, uap) * rights where the control fields are now. */ int -orecvmsg(td, uap) - struct thread *td; - struct orecvmsg_args /* { - int s; - struct omsghdr *msg; - int flags; - } */ *uap; +orecvmsg(struct thread *td, struct orecvmsg_args *uap) { struct msghdr msg; struct iovec *iov; @@ -1626,13 +1527,7 @@ orecvmsg(td, uap) static #endif /* __rtems__ */ int -sys_recvmsg(td, uap) - struct thread *td; - struct recvmsg_args /* { - int s; - struct msghdr *msg; - int flags; - } */ *uap; +sys_recvmsg(struct thread *td, struct recvmsg_args *uap) { struct msghdr msg; struct iovec *uiov, *iov; @@ -1684,17 +1579,11 @@ recvmsg(int socket, struct msghdr *message, int flags) } #endif /* __rtems__ */ -/* ARGSUSED */ #ifdef __rtems__ static #endif /* __rtems__ */ int -sys_shutdown(td, uap) - struct thread *td; - struct shutdown_args /* { - int s; - int how; - } */ *uap; +sys_shutdown(struct thread *td, struct shutdown_args *uap) { struct socket *so; struct file *fp; @@ -1703,7 +1592,7 @@ sys_shutdown(td, uap) AUDIT_ARG_FD(uap->s); error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_SHUTDOWN), - &fp, NULL); + &fp, NULL, NULL); if (error == 0) { so = fp->f_data; error = soshutdown(so, uap->how); @@ -1736,7 +1625,6 @@ shutdown(int socket, int how) } #endif /* __rtems__ */ -/* ARGSUSED */ #ifdef __rtems__ static int kern_setsockopt( struct thread *td, int s, int level, int name, void *val, enum uio_seg valseg, socklen_t valsize); @@ -1744,15 +1632,7 @@ static int kern_setsockopt( struct thread *td, int s, int level, int name, static #endif /* __rtems__ */ int -sys_setsockopt(td, uap) - struct thread *td; - struct setsockopt_args /* { - int s; - int level; - int name; - caddr_t val; - int valsize; - } */ *uap; +sys_setsockopt(struct thread *td, struct setsockopt_args *uap) { return (kern_setsockopt(td, uap->s, uap->level, uap->name, @@ -1784,14 +1664,8 @@ setsockopt(int socket, int level, int option_name, const void *option_value, #endif /* __rtems__ */ int -kern_setsockopt(td, s, level, name, val, valseg, valsize) - struct thread *td; - int s; - int level; - int name; - void *val; - enum uio_seg valseg; - socklen_t valsize; +kern_setsockopt(struct thread *td, int s, int level, int name, void *val, + enum uio_seg valseg, socklen_t valsize) { struct socket *so; struct file *fp; @@ -1822,7 +1696,7 @@ kern_setsockopt(td, s, level, name, val, valseg, valsize) AUDIT_ARG_FD(s); error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SETSOCKOPT), - &fp, NULL); + &fp, NULL, NULL); if (error == 0) { so = fp->f_data; error = sosetopt(so, &sopt); @@ -1831,7 +1705,6 @@ kern_setsockopt(td, s, level, name, val, valseg, valsize) return(error); } -/* ARGSUSED */ #ifdef __rtems__ static int kern_getsockopt( struct thread *td, int s, int level, int name, void *val, enum uio_seg valseg, socklen_t *valsize); @@ -1839,15 +1712,7 @@ static int kern_getsockopt( struct thread *td, int s, int level, int name, static #endif /* __rtems__ */ int -sys_getsockopt(td, uap) - struct thread *td; - struct getsockopt_args /* { - int s; - int level; - int name; - void * __restrict val; - socklen_t * __restrict avalsize; - } */ *uap; +sys_getsockopt(struct thread *td, struct getsockopt_args *uap) { socklen_t valsize; int error; @@ -1895,14 +1760,8 @@ getsockopt(int socket, int level, int option_name, void *__restrict * optval can be a userland or userspace. optlen is always a kernel pointer. */ int -kern_getsockopt(td, s, level, name, val, valseg, valsize) - struct thread *td; - int s; - int level; - int name; - void *val; - enum uio_seg valseg; - socklen_t *valsize; +kern_getsockopt(struct thread *td, int s, int level, int name, void *val, + enum uio_seg valseg, socklen_t *valsize) { struct socket *so; struct file *fp; @@ -1933,7 +1792,7 @@ kern_getsockopt(td, s, level, name, val, valseg, valsize) AUDIT_ARG_FD(s); error = getsock_cap(td, s, cap_rights_init(&rights, CAP_GETSOCKOPT), - &fp, NULL); + &fp, NULL, NULL); if (error == 0) { so = fp->f_data; error = sogetopt(so, &sopt); @@ -1951,16 +1810,8 @@ kern_getsockname(struct thread *td, int fd, struct sockaddr **sa, /* * getsockname1() - Get socket name. */ -/* ARGSUSED */ static int -getsockname1(td, uap, compat) - struct thread *td; - struct getsockname_args /* { - int fdes; - struct sockaddr * __restrict asa; - socklen_t * __restrict alen; - } */ *uap; - int compat; +getsockname1(struct thread *td, struct getsockname_args *uap, int compat) { struct sockaddr *sa; socklen_t len; @@ -2000,7 +1851,7 @@ getsockname(int socket, struct sockaddr *__restrict address, int error; if (td != NULL) { - error = getsockname1(td, &ua); + error = getsockname1(td, &ua, 0); } else { error = ENOMEM; } @@ -2021,7 +1872,7 @@ kern_getsockname(struct thread *td, int fd, struct sockaddr **sa, AUDIT_ARG_FD(fd); error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETSOCKNAME), - &fp, NULL); + &fp, NULL, NULL); if (error != 0) return (error); so = fp->f_data; @@ -2051,9 +1902,7 @@ bad: #ifndef __rtems__ int -sys_getsockname(td, uap) - struct thread *td; - struct getsockname_args *uap; +sys_getsockname(struct thread *td, struct getsockname_args *uap) { return (getsockname1(td, uap, 0)); @@ -2061,9 +1910,7 @@ sys_getsockname(td, uap) #ifdef COMPAT_OLDSOCK int -ogetsockname(td, uap) - struct thread *td; - struct getsockname_args *uap; +ogetsockname(struct thread *td, struct getsockname_args *uap) { return (getsockname1(td, uap, 1)); @@ -2079,16 +1926,8 @@ kern_getpeername(struct thread *td, int fd, struct sockaddr **sa, /* * getpeername1() - Get name of peer for connected socket. */ -/* ARGSUSED */ static int -getpeername1(td, uap, compat) - struct thread *td; - struct getpeername_args /* { - int fdes; - struct sockaddr * __restrict asa; - socklen_t * __restrict alen; - } */ *uap; - int compat; +getpeername1(struct thread *td, struct getpeername_args *uap, int compat) { struct sockaddr *sa; socklen_t len; @@ -2128,7 +1967,7 @@ getpeername(int socket, struct sockaddr *__restrict address, int error; if (td != NULL) { - error = getpeername1(td, &ua); + error = getpeername1(td, &ua, 0); } else { error = ENOMEM; } @@ -2149,7 +1988,7 @@ kern_getpeername(struct thread *td, int fd, struct sockaddr **sa, AUDIT_ARG_FD(fd); error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETPEERNAME), - &fp, NULL); + &fp, NULL, NULL); if (error != 0) return (error); so = fp->f_data; @@ -2184,9 +2023,7 @@ done: #ifndef __rtems__ int -sys_getpeername(td, uap) - struct thread *td; - struct getpeername_args *uap; +sys_getpeername(struct thread *td, struct getpeername_args *uap) { return (getpeername1(td, uap, 0)); @@ -2194,9 +2031,7 @@ sys_getpeername(td, uap) #ifdef COMPAT_OLDSOCK int -ogetpeername(td, uap) - struct thread *td; - struct ogetpeername_args *uap; +ogetpeername(struct thread *td, struct ogetpeername_args *uap) { /* XXX uap should have type `getpeername_args *' to begin with. */ @@ -2242,10 +2077,7 @@ sockargs(struct mbuf **mp, char *buf, socklen_t buflen, int type) } int -getsockaddr(namp, uaddr, len) - struct sockaddr **namp; - caddr_t uaddr; - size_t len; +getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len) { struct sockaddr *sa; int error; diff --git a/freebsd/sys/kern/uipc_usrreq.c b/freebsd/sys/kern/uipc_usrreq.c index 7b2d1bc4..159de132 100644 --- a/freebsd/sys/kern/uipc_usrreq.c +++ b/freebsd/sys/kern/uipc_usrreq.c @@ -14,7 +14,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -291,8 +291,8 @@ static int unp_connectat(int, struct socket *, struct sockaddr *, static int unp_connect2(struct socket *so, struct socket *so2, int); static void unp_disconnect(struct unpcb *unp, struct unpcb *unp2); #ifndef __rtems__ -static void unp_dispose(struct mbuf *); -static void unp_dispose_so(struct socket *so); +static void unp_dispose(struct socket *so); +static void unp_dispose_mbuf(struct mbuf *); #endif /* __rtems__ */ static void unp_shutdown(struct unpcb *); static void unp_drop(struct unpcb *); @@ -355,7 +355,7 @@ static struct domain localdomain = { .dom_init = unp_init, #ifndef __rtems__ .dom_externalize = unp_externalize, - .dom_dispose = unp_dispose_so, + .dom_dispose = unp_dispose, #endif /* __rtems__ */ .dom_protosw = localsw, .dom_protoswNPROTOSW = &localsw[nitems(localsw)] @@ -1164,7 +1164,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, if (control != NULL && error != 0) #ifndef __rtems__ - unp_dispose(control); + unp_dispose_mbuf(control); #else /* __rtems__ */ BSD_ASSERT(0); #endif /* __rtems__ */ @@ -2511,7 +2511,7 @@ unp_gc(__unused void *arg, int pending) } static void -unp_dispose(struct mbuf *m) +unp_dispose_mbuf(struct mbuf *m) { if (m) @@ -2522,7 +2522,7 @@ unp_dispose(struct mbuf *m) * Synchronize against unp_gc, which can trip over data as we are freeing it. */ static void -unp_dispose_so(struct socket *so) +unp_dispose(struct socket *so) { struct unpcb *unp; @@ -2530,7 +2530,7 @@ unp_dispose_so(struct socket *so) UNP_LIST_LOCK(); unp->unp_gcflag |= UNPGC_IGNORE_RIGHTS; UNP_LIST_UNLOCK(); - unp_dispose(so->so_rcv.sb_mb); + unp_dispose_mbuf(so->so_rcv.sb_mb); } static void diff --git a/freebsd/sys/mips/include/machine/cpufunc.h b/freebsd/sys/mips/include/machine/cpufunc.h index 427aba74..5ebaf4cc 100644 --- a/freebsd/sys/mips/include/machine/cpufunc.h +++ b/freebsd/sys/mips/include/machine/cpufunc.h @@ -249,7 +249,8 @@ MIPS_RW32_COP0_SEL(config5, MIPS_COP_0_CONFIG, 5); #if defined(CPU_NLM) || defined(BERI_LARGE_TLB) MIPS_RW32_COP0_SEL(config6, MIPS_COP_0_CONFIG, 6); #endif -#if defined(CPU_NLM) || defined(CPU_MIPS1004K) +#if defined(CPU_NLM) || defined(CPU_MIPS1004K) || defined (CPU_MIPS74K) || \ + defined(CPU_MIPS24K) MIPS_RW32_COP0_SEL(config7, MIPS_COP_0_CONFIG, 7); #endif MIPS_RW32_COP0(count, MIPS_COP_0_COUNT); @@ -278,6 +279,13 @@ MIPS_RW32_COP0(entrylo1, MIPS_COP_0_TLB_LO1); MIPS_RW32_COP0(prid, MIPS_COP_0_PRID); /* XXX 64-bit? */ MIPS_RW32_COP0_SEL(ebase, MIPS_COP_0_PRID, 1); +#ifdef CPU_XBURST +MIPS_RW32_COP0_SEL(xburst_mbox0, MIPS_COP_0_XBURST_MBOX, 0); +MIPS_RW32_COP0_SEL(xburst_mbox1, MIPS_COP_0_XBURST_MBOX, 1); +MIPS_RW32_COP0_SEL(xburst_core_ctl, MIPS_COP_0_XBURST_C12, 2); +MIPS_RW32_COP0_SEL(xburst_core_sts, MIPS_COP_0_XBURST_C12, 3); +MIPS_RW32_COP0_SEL(xburst_reim, MIPS_COP_0_XBURST_C12, 4); +#endif MIPS_RW32_COP0(watchlo, MIPS_COP_0_WATCH_LO); MIPS_RW32_COP0_SEL(watchlo1, MIPS_COP_0_WATCH_LO, 1); MIPS_RW32_COP0_SEL(watchlo2, MIPS_COP_0_WATCH_LO, 2); diff --git a/freebsd/sys/mips/include/machine/cpuregs.h b/freebsd/sys/mips/include/machine/cpuregs.h index 4ce7e1b4..26bee195 100644 --- a/freebsd/sys/mips/include/machine/cpuregs.h +++ b/freebsd/sys/mips/include/machine/cpuregs.h @@ -522,12 +522,18 @@ #define MIPS_COP_0_COUNT _(9) #define MIPS_COP_0_COMPARE _(11) - +#ifdef CPU_XBURST +#define MIPS_COP_0_XBURST_C12 _(12) +#endif #define MIPS_COP_0_CONFIG _(16) #define MIPS_COP_0_LLADDR _(17) #define MIPS_COP_0_WATCH_LO _(18) #define MIPS_COP_0_WATCH_HI _(19) #define MIPS_COP_0_TLB_XCONTEXT _(20) +#ifdef CPU_XBURST +#define MIPS_COP_0_XBURST_MBOX _(20) +#endif + #define MIPS_COP_0_ECC _(26) #define MIPS_COP_0_CACHE_ERR _(27) #define MIPS_COP_0_TAG_LO _(28) diff --git a/freebsd/sys/net/altq/altq_subr.c b/freebsd/sys/net/altq/altq_subr.c index 66ff441d..a9a68b37 100644 --- a/freebsd/sys/net/altq/altq_subr.c +++ b/freebsd/sys/net/altq/altq_subr.c @@ -437,7 +437,7 @@ tbr_timeout(arg) VNET_FOREACH(vnet_iter) { CURVNET_SET(vnet_iter); for (ifp = TAILQ_FIRST(&V_ifnet); ifp; - ifp = TAILQ_NEXT(ifp, if_list)) { + ifp = TAILQ_NEXT(ifp, if_link)) { /* read from if_snd unlocked */ if (!TBR_IS_ENABLED(&ifp->if_snd)) continue; diff --git a/freebsd/sys/net/bpf_filter.c b/freebsd/sys/net/bpf_filter.c index 941fa290..ecfb3d14 100644 --- a/freebsd/sys/net/bpf_filter.c +++ b/freebsd/sys/net/bpf_filter.c @@ -436,6 +436,12 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) A /= X; continue; + case BPF_ALU|BPF_MOD|BPF_X: + if (X == 0) + return (0); + A %= X; + continue; + case BPF_ALU|BPF_AND|BPF_X: A &= X; continue; @@ -444,6 +450,10 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) A |= X; continue; + case BPF_ALU|BPF_XOR|BPF_X: + A ^= X; + continue; + case BPF_ALU|BPF_LSH|BPF_X: A <<= X; continue; @@ -468,6 +478,10 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) A /= pc->k; continue; + case BPF_ALU|BPF_MOD|BPF_K: + A %= pc->k; + continue; + case BPF_ALU|BPF_AND|BPF_K: A &= pc->k; continue; @@ -476,6 +490,10 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) A |= pc->k; continue; + case BPF_ALU|BPF_XOR|BPF_K: + A ^= pc->k; + continue; + case BPF_ALU|BPF_LSH|BPF_K: A <<= pc->k; continue; @@ -510,8 +528,8 @@ static const u_short bpf_code_map[] = { 0x1013, /* 0x60-0x6f: 1100100000001000 */ 0x1010, /* 0x70-0x7f: 0000100000001000 */ 0x0093, /* 0x80-0x8f: 1100100100000000 */ - 0x0000, /* 0x90-0x9f: 0000000000000000 */ - 0x0000, /* 0xa0-0xaf: 0000000000000000 */ + 0x1010, /* 0x90-0x9f: 0000100000001000 */ + 0x1010, /* 0xa0-0xaf: 0000100000001000 */ 0x0002, /* 0xb0-0xbf: 0100000000000000 */ 0x0000, /* 0xc0-0xcf: 0000000000000000 */ 0x0000, /* 0xd0-0xdf: 0000000000000000 */ @@ -579,7 +597,8 @@ bpf_validate(const struct bpf_insn *f, int len) /* * Check for constant division by 0. */ - if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) + if ((p->code == (BPF_ALU|BPF_DIV|BPF_K) || + p->code == (BPF_ALU|BPF_MOD|BPF_K)) && p->k == 0) return (0); } return (BPF_CLASS(f[len - 1].code) == BPF_RET); diff --git a/freebsd/sys/net/ethernet.h b/freebsd/sys/net/ethernet.h index bc5fa9cb..5ec9d20e 100644 --- a/freebsd/sys/net/ethernet.h +++ b/freebsd/sys/net/ethernet.h @@ -92,7 +92,7 @@ struct ether_vlan_header { #define EVL_PRIOFTAG(tag) (((tag) >> 13) & 7) #define EVL_CFIOFTAG(tag) (((tag) >> 12) & 1) #define EVL_MAKETAG(vlid, pri, cfi) \ - ((((((pri) & 7) << 1) | ((cfi) & 1)) << 12) | ((vlid) & EVL_VLID_MASK)) + ((((((pri) & 7) << 13) | ((cfi) & 1)) << 12) | ((vlid) & EVL_VLID_MASK)) /* * NOTE: 0x0000-0x05DC (0..1500) are generally IEEE 802.3 length fields. diff --git a/freebsd/sys/net/if.c b/freebsd/sys/net/if.c index 8bfa9e21..e1c525bd 100644 --- a/freebsd/sys/net/if.c +++ b/freebsd/sys/net/if.c @@ -2208,7 +2208,7 @@ do_link_state_change(void *arg, int pending) if (log_link_state_change) log(LOG_NOTICE, "%s: link state changed to %s\n", ifp->if_xname, (link_state == LINK_STATE_UP) ? "UP" : "DOWN" ); - EVENTHANDLER_INVOKE(ifnet_link_event, ifp, ifp->if_link_state); + EVENTHANDLER_INVOKE(ifnet_link_event, ifp, link_state); CURVNET_RESTORE(); } diff --git a/freebsd/sys/net/if_arcsubr.c b/freebsd/sys/net/if_arcsubr.c index 1954e262..042f3e84 100644 --- a/freebsd/sys/net/if_arcsubr.c +++ b/freebsd/sys/net/if_arcsubr.c @@ -227,7 +227,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { - struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); + struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT); (void) if_simloop(ifp, n, dst->sa_family, ARC_HDRLEN); } else if (ah->arc_dhost == ah->arc_shost) { diff --git a/freebsd/sys/net/if_bridge.c b/freebsd/sys/net/if_bridge.c index 77b376b9..fc0dbffd 100644 --- a/freebsd/sys/net/if_bridge.c +++ b/freebsd/sys/net/if_bridge.c @@ -335,7 +335,7 @@ static int bridge_ip_checkbasic(struct mbuf **mp); #ifdef INET6 static int bridge_ip6_checkbasic(struct mbuf **mp); #endif /* INET6 */ -static int bridge_fragment(struct ifnet *, struct mbuf *, +static int bridge_fragment(struct ifnet *, struct mbuf **mp, struct ether_header *, int, struct llc *); static void bridge_linkstate(struct ifnet *ifp); static void bridge_linkcheck(struct bridge_softc *sc); @@ -410,7 +410,7 @@ SYSCTL_INT(_net_link_bridge, OID_AUTO, inherit_mac, static VNET_DEFINE(int, allow_llz_overlap) = 0; #define V_allow_llz_overlap VNET(allow_llz_overlap) SYSCTL_INT(_net_link_bridge, OID_AUTO, allow_llz_overlap, - CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_VNET, &VNET_NAME(allow_llz_overlap), 0, + CTLFLAG_RW | CTLFLAG_VNET, &VNET_NAME(allow_llz_overlap), 0, "Allow overlap of link-local scope " "zones of a bridge interface and the member interfaces"); @@ -1919,6 +1919,7 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m) m->m_flags &= ~M_VLANTAG; } + M_ASSERTPKTHDR(m); /* We shouldn't transmit mbuf without pkthdr */ if ((err = dst_ifp->if_transmit(dst_ifp, m))) { m_freem(m0); if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1); @@ -3236,10 +3237,12 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir) break; /* check if we need to fragment the packet */ + /* bridge_fragment generates a mbuf chain of packets */ + /* that already include eth headers */ if (V_pfil_member && ifp != NULL && dir == PFIL_OUT) { i = (*mp)->m_pkthdr.len; if (i > ifp->if_mtu) { - error = bridge_fragment(ifp, *mp, &eh2, snap, + error = bridge_fragment(ifp, mp, &eh2, snap, &llc1); return (error); } @@ -3478,56 +3481,77 @@ bad: /* * bridge_fragment: * - * Return a fragmented mbuf chain. + * Fragment mbuf chain in multiple packets and prepend ethernet header. */ static int -bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh, +bridge_fragment(struct ifnet *ifp, struct mbuf **mp, struct ether_header *eh, int snap, struct llc *llc) { - struct mbuf *m0; + struct mbuf *m = *mp, *nextpkt = NULL, *mprev = NULL, *mcur = NULL; struct ip *ip; int error = -1; if (m->m_len < sizeof(struct ip) && (m = m_pullup(m, sizeof(struct ip))) == NULL) - goto out; + goto dropit; ip = mtod(m, struct ip *); m->m_pkthdr.csum_flags |= CSUM_IP; error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist); if (error) - goto out; + goto dropit; - /* walk the chain and re-add the Ethernet header */ - for (m0 = m; m0; m0 = m0->m_nextpkt) { - if (error == 0) { - if (snap) { - M_PREPEND(m0, sizeof(struct llc), M_NOWAIT); - if (m0 == NULL) { - error = ENOBUFS; - continue; - } - bcopy(llc, mtod(m0, caddr_t), - sizeof(struct llc)); - } - M_PREPEND(m0, ETHER_HDR_LEN, M_NOWAIT); - if (m0 == NULL) { + /* + * Walk the chain and re-add the Ethernet header for + * each mbuf packet. + */ + for (mcur = m; mcur; mcur = mcur->m_nextpkt) { + nextpkt = mcur->m_nextpkt; + mcur->m_nextpkt = NULL; + if (snap) { + M_PREPEND(mcur, sizeof(struct llc), M_NOWAIT); + if (mcur == NULL) { error = ENOBUFS; - continue; + if (mprev != NULL) + mprev->m_nextpkt = nextpkt; + goto dropit; } - bcopy(eh, mtod(m0, caddr_t), ETHER_HDR_LEN); - } else - m_freem(m); + bcopy(llc, mtod(mcur, caddr_t),sizeof(struct llc)); + } + + M_PREPEND(mcur, ETHER_HDR_LEN, M_NOWAIT); + if (mcur == NULL) { + error = ENOBUFS; + if (mprev != NULL) + mprev->m_nextpkt = nextpkt; + goto dropit; + } + bcopy(eh, mtod(mcur, caddr_t), ETHER_HDR_LEN); + + /* + * The previous two M_PREPEND could have inserted one or two + * mbufs in front so we have to update the previous packet's + * m_nextpkt. + */ + mcur->m_nextpkt = nextpkt; + if (mprev != NULL) + mprev->m_nextpkt = mcur; + else { + /* The first mbuf in the original chain needs to be + * updated. */ + *mp = mcur; + } + mprev = mcur; } - if (error == 0) - KMOD_IPSTAT_INC(ips_fragmented); - + KMOD_IPSTAT_INC(ips_fragmented); return (error); -out: - if (m != NULL) - m_freem(m); +dropit: + for (mcur = *mp; mcur; mcur = m) { /* droping the full packet chain */ + m = mcur->m_nextpkt; + m_freem(mcur); + } return (error); } diff --git a/freebsd/sys/net/if_fddisubr.c b/freebsd/sys/net/if_fddisubr.c index 9df882ec..98ac4cc3 100644 --- a/freebsd/sys/net/if_fddisubr.c +++ b/freebsd/sys/net/if_fddisubr.c @@ -277,7 +277,7 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { struct mbuf *n; - n = m_copy(m, 0, (int)M_COPYALL); + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); (void) if_simloop(ifp, n, dst->sa_family, FDDI_HDR_LEN); } else if (bcmp(fh->fddi_dhost, fh->fddi_shost, diff --git a/freebsd/sys/net/if_iso88025subr.c b/freebsd/sys/net/if_iso88025subr.c index d26d0ebd..38322b23 100644 --- a/freebsd/sys/net/if_iso88025subr.c +++ b/freebsd/sys/net/if_iso88025subr.c @@ -366,7 +366,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { struct mbuf *n; - n = m_copy(m, 0, (int)M_COPYALL); + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); (void) if_simloop(ifp, n, dst->sa_family, ISO88025_HDR_LEN); } else if (bcmp(th->iso88025_dhost, th->iso88025_shost, diff --git a/freebsd/sys/net/if_llatbl.c b/freebsd/sys/net/if_llatbl.c index 20c0b9d2..a4741884 100644 --- a/freebsd/sys/net/if_llatbl.c +++ b/freebsd/sys/net/if_llatbl.c @@ -68,8 +68,13 @@ static VNET_DEFINE(SLIST_HEAD(, lltable), lltables) = SLIST_HEAD_INITIALIZER(lltables); #define V_lltables VNET(lltables) -struct rwlock lltable_rwlock; -RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock"); +static struct rwlock lltable_list_lock; +RW_SYSINIT(lltable_list_lock, &lltable_list_lock, "lltable_list_lock"); +#define LLTABLE_LIST_RLOCK() rw_rlock(&lltable_list_lock) +#define LLTABLE_LIST_RUNLOCK() rw_runlock(&lltable_list_lock) +#define LLTABLE_LIST_WLOCK() rw_wlock(&lltable_list_lock) +#define LLTABLE_LIST_WUNLOCK() rw_wunlock(&lltable_list_lock) +#define LLTABLE_LIST_LOCK_ASSERT() rw_assert(&lltable_list_lock, RA_LOCKED) static void lltable_unlink(struct lltable *llt); static void llentries_unlink(struct lltable *llt, struct llentries *head); @@ -87,7 +92,7 @@ lltable_dump_af(struct lltable *llt, struct sysctl_req *wr) { int error; - LLTABLE_LOCK_ASSERT(); + LLTABLE_LIST_LOCK_ASSERT(); if (llt->llt_ifp->if_flags & IFF_LOOPBACK) return (0); @@ -110,7 +115,7 @@ lltable_sysctl_dumparp(int af, struct sysctl_req *wr) struct lltable *llt; int error = 0; - LLTABLE_RLOCK(); + LLTABLE_LIST_RLOCK(); SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af == af) { error = lltable_dump_af(llt, wr); @@ -119,7 +124,7 @@ lltable_sysctl_dumparp(int af, struct sysctl_req *wr) } } done: - LLTABLE_RUNLOCK(); + LLTABLE_LIST_RUNLOCK(); return (error); } @@ -533,7 +538,7 @@ lltable_drain(int af) struct llentry *lle; register int i; - LLTABLE_RLOCK(); + LLTABLE_LIST_RLOCK(); SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af != af) continue; @@ -549,7 +554,7 @@ lltable_drain(int af) } } } - LLTABLE_RUNLOCK(); + LLTABLE_LIST_RUNLOCK(); } #endif @@ -593,14 +598,14 @@ lltable_prefix_free(int af, struct sockaddr *addr, struct sockaddr *mask, { struct lltable *llt; - LLTABLE_RLOCK(); + LLTABLE_LIST_RLOCK(); SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af != af) continue; llt->llt_prefix_free(llt, addr, mask, flags); } - LLTABLE_RUNLOCK(); + LLTABLE_LIST_RUNLOCK(); } struct lltable * @@ -634,18 +639,18 @@ void lltable_link(struct lltable *llt) { - LLTABLE_WLOCK(); + LLTABLE_LIST_WLOCK(); SLIST_INSERT_HEAD(&V_lltables, llt, llt_link); - LLTABLE_WUNLOCK(); + LLTABLE_LIST_WUNLOCK(); } static void lltable_unlink(struct lltable *llt) { - LLTABLE_WLOCK(); + LLTABLE_LIST_WLOCK(); SLIST_REMOVE(&V_lltables, llt, lltable, llt_link); - LLTABLE_WUNLOCK(); + LLTABLE_LIST_WUNLOCK(); } @@ -741,13 +746,13 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info) } /* XXX linked list may be too expensive */ - LLTABLE_RLOCK(); + LLTABLE_LIST_RLOCK(); SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af == dst->sa_family && llt->llt_ifp == ifp) break; } - LLTABLE_RUNLOCK(); + LLTABLE_LIST_RUNLOCK(); KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n")); error = 0; diff --git a/freebsd/sys/net/if_llatbl.h b/freebsd/sys/net/if_llatbl.h index 51de726a..5e89fea0 100644 --- a/freebsd/sys/net/if_llatbl.h +++ b/freebsd/sys/net/if_llatbl.h @@ -37,17 +37,9 @@ struct ifnet; struct sysctl_req; struct rt_msghdr; struct rt_addrinfo; - struct llentry; LIST_HEAD(llentries, llentry); -extern struct rwlock lltable_rwlock; -#define LLTABLE_RLOCK() rw_rlock(&lltable_rwlock) -#define LLTABLE_RUNLOCK() rw_runlock(&lltable_rwlock) -#define LLTABLE_WLOCK() rw_wlock(&lltable_rwlock) -#define LLTABLE_WUNLOCK() rw_wunlock(&lltable_rwlock) -#define LLTABLE_LOCK_ASSERT() rw_assert(&lltable_rwlock, RA_LOCKED) - #define LLE_MAX_LINKHDR 24 /* Full IB header */ /* * Code referencing llentry must at least hold diff --git a/freebsd/sys/net/if_loop.c b/freebsd/sys/net/if_loop.c index aa5109eb..5ee82fc0 100644 --- a/freebsd/sys/net/if_loop.c +++ b/freebsd/sys/net/if_loop.c @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -226,6 +227,10 @@ looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); +#ifdef RSS + M_HASHTYPE_CLEAR(m); +#endif + /* BPF writes need to be handled specially. */ if (dst->sa_family == AF_UNSPEC || dst->sa_family == pseudo_AF_HDRCMPLT) bcopy(dst->sa_data, &af, sizeof(af)); diff --git a/freebsd/sys/net/if_var.h b/freebsd/sys/net/if_var.h index ec3719d4..6ddb6c7b 100644 --- a/freebsd/sys/net/if_var.h +++ b/freebsd/sys/net/if_var.h @@ -178,9 +178,6 @@ struct if_encap_req { /* * Structure defining a network interface. - * - * Size ILP32: 592 (approx) - * LP64: 1048 (approx) */ struct ifnet { /* General book keeping of interface lists. */ @@ -316,8 +313,6 @@ struct ifnet { }; /* for compatibility with other BSDs */ -#define if_addrlist if_addrhead -#define if_list if_link #define if_name(ifp) ((ifp)->if_xname) /* @@ -451,9 +446,6 @@ struct ifaddr { counter_u64_t ifa_obytes; }; -/* For compatibility with other BSDs. SCTP uses it. */ -#define ifa_list ifa_link - struct ifaddr * ifa_alloc(size_t size, int flags); void ifa_free(struct ifaddr *ifa); void ifa_ref(struct ifaddr *ifa); @@ -504,7 +496,7 @@ extern struct sx ifnet_sxlock; /* * Look up an ifnet given its index; the _ref variant also acquires a * reference that must be freed using if_rele(). It is almost always a bug - * to call ifnet_byindex() instead if ifnet_byindex_ref(). + * to call ifnet_byindex() instead of ifnet_byindex_ref(). */ struct ifnet *ifnet_byindex(u_short idx); struct ifnet *ifnet_byindex_locked(u_short idx); diff --git a/freebsd/sys/net/pfkeyv2.h b/freebsd/sys/net/pfkeyv2.h index c9b27695..35348819 100644 --- a/freebsd/sys/net/pfkeyv2.h +++ b/freebsd/sys/net/pfkeyv2.h @@ -283,6 +283,14 @@ struct sadb_x_nat_t_frag { }; _Static_assert(sizeof(struct sadb_x_nat_t_frag) == 8, "struct size mismatch"); +/* Additional large replay window support + */ +struct sadb_x_sa_replay { + u_int16_t sadb_x_sa_replay_len; + u_int16_t sadb_x_sa_replay_exttype; + u_int32_t sadb_x_sa_replay_replay; /* in packets */ +}; +_Static_assert(sizeof(struct sadb_x_sa_replay) == 8, "struct size mismatch"); #define SADB_EXT_RESERVED 0 #define SADB_EXT_SA 1 @@ -311,7 +319,8 @@ _Static_assert(sizeof(struct sadb_x_nat_t_frag) == 8, "struct size mismatch"); #define SADB_X_EXT_NAT_T_OAI 23 /* Peer's NAT_OA for src of SA. */ #define SADB_X_EXT_NAT_T_OAR 24 /* Peer's NAT_OA for dst of SA. */ #define SADB_X_EXT_NAT_T_FRAG 25 /* Manual MTU override. */ -#define SADB_EXT_MAX 25 +#define SADB_X_EXT_SA_REPLAY 26 /* Replay window override. */ +#define SADB_EXT_MAX 26 #define SADB_SATYPE_UNSPEC 0 #define SADB_SATYPE_AH 2 diff --git a/freebsd/sys/net/raw_usrreq.c b/freebsd/sys/net/raw_usrreq.c index e170ad74..6e9668f3 100644 --- a/freebsd/sys/net/raw_usrreq.c +++ b/freebsd/sys/net/raw_usrreq.c @@ -97,7 +97,7 @@ raw_input_ext(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src, continue; if (last) { struct mbuf *n; - n = m_copy(m, 0, (int)M_COPYALL); + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (n) { if (sbappendaddr(&last->so_rcv, src, n, (struct mbuf *)0) == 0) diff --git a/freebsd/sys/net/route.c b/freebsd/sys/net/route.c index 3eb05b94..a851efa8 100644 --- a/freebsd/sys/net/route.c +++ b/freebsd/sys/net/route.c @@ -362,7 +362,7 @@ rt_table_init(int offset) rh->head.rnh_masks = &rh->rmhead; /* Init locks */ - rw_init(&rh->rib_lock, "rib head lock"); + RIB_LOCK_INIT(rh); /* Finally, set base callbacks */ rh->rnh_addaddr = rn_addroute; @@ -394,7 +394,7 @@ rt_table_destroy(struct rib_head *rh) rn_walktree(&rh->rmhead.head, rt_freeentry, &rh->rmhead.head); /* Assume table is already empty */ - rw_destroy(&rh->rib_lock); + RIB_LOCK_DESTROY(rh); free(rh, M_RTABLE); } @@ -499,9 +499,8 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags, RIB_RUNLOCK(rh); /* - * Either we hit the root or couldn't find any match, - * Which basically means - * "caint get there frm here" + * Either we hit the root or could not find any match, + * which basically means: "cannot get there from here". */ miss: V_rtstat.rts_unreach++; diff --git a/freebsd/sys/net/route_var.h b/freebsd/sys/net/route_var.h index a8ef56a5..914bcfe2 100644 --- a/freebsd/sys/net/route_var.h +++ b/freebsd/sys/net/route_var.h @@ -48,6 +48,8 @@ struct rib_head { struct radix_mask_head rmhead; /* masks radix head */ }; +#define RIB_LOCK_INIT(rh) rw_init(&(rh)->rib_lock, "rib head lock") +#define RIB_LOCK_DESTROY(rh) rw_destroy(&(rh)->rib_lock) #define RIB_RLOCK(rh) rw_rlock(&(rh)->rib_lock) #define RIB_RUNLOCK(rh) rw_runlock(&(rh)->rib_lock) #define RIB_WLOCK(rh) rw_wlock(&(rh)->rib_lock) diff --git a/freebsd/sys/net/rtsock.c b/freebsd/sys/net/rtsock.c index 1e69bcdf..97b92127 100644 --- a/freebsd/sys/net/rtsock.c +++ b/freebsd/sys/net/rtsock.c @@ -1578,8 +1578,8 @@ sysctl_dumpentry(struct radix_node *rn, void *vw) } static int -sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info, - struct walkarg *w, int len) +sysctl_iflist_ifml(struct ifnet *ifp, const struct if_data *src_ifd, + struct rt_addrinfo *info, struct walkarg *w, int len) { struct if_msghdrl *ifm; struct if_data *ifd; @@ -1610,14 +1610,14 @@ sysctl_iflist_ifml(struct ifnet *ifp, struct rt_addrinfo *info, ifd = &ifm->ifm_data; } - if_data_copy(ifp, ifd); + memcpy(ifd, src_ifd, sizeof(*ifd)); return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len)); } static int -sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info, - struct walkarg *w, int len) +sysctl_iflist_ifm(struct ifnet *ifp, const struct if_data *src_ifd, + struct rt_addrinfo *info, struct walkarg *w, int len) { struct if_msghdr *ifm; struct if_data *ifd; @@ -1642,7 +1642,7 @@ sysctl_iflist_ifm(struct ifnet *ifp, struct rt_addrinfo *info, ifd = &ifm->ifm_data; } - if_data_copy(ifp, ifd); + memcpy(ifd, src_ifd, sizeof(*ifd)); return (SYSCTL_OUT(w->w_req, (caddr_t)ifm, len)); } @@ -1717,15 +1717,18 @@ sysctl_iflist(int af, struct walkarg *w) { struct ifnet *ifp; struct ifaddr *ifa; + struct if_data ifd; struct rt_addrinfo info; int len, error = 0; struct sockaddr_storage ss; bzero((caddr_t)&info, sizeof(info)); + bzero(&ifd, sizeof(ifd)); IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) continue; + if_data_copy(ifp, &ifd); IF_ADDR_RLOCK(ifp); ifa = ifp->if_addr; info.rti_info[RTAX_IFP] = ifa->ifa_addr; @@ -1735,9 +1738,11 @@ sysctl_iflist(int af, struct walkarg *w) info.rti_info[RTAX_IFP] = NULL; if (w->w_req && w->w_tmem) { if (w->w_op == NET_RT_IFLISTL) - error = sysctl_iflist_ifml(ifp, &info, w, len); + error = sysctl_iflist_ifml(ifp, &ifd, &info, w, + len); else - error = sysctl_iflist_ifm(ifp, &info, w, len); + error = sysctl_iflist_ifm(ifp, &ifd, &info, w, + len); if (error) goto done; } @@ -1780,13 +1785,15 @@ done: static int sysctl_ifmalist(int af, struct walkarg *w) { - struct ifnet *ifp; - struct ifmultiaddr *ifma; - struct rt_addrinfo info; - int len, error = 0; + struct rt_addrinfo info; struct ifaddr *ifa; + struct ifmultiaddr *ifma; + struct ifnet *ifp; + int error, len; + error = 0; bzero((caddr_t)&info, sizeof(info)); + IFNET_RLOCK_NOSLEEP(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) @@ -1806,7 +1813,7 @@ sysctl_ifmalist(int af, struct walkarg *w) ifma->ifma_lladdr : NULL; error = rtsock_msg_buffer(RTM_NEWMADDR, &info, w, &len); if (error != 0) - goto done; + break; if (w->w_req && w->w_tmem) { struct ifma_msghdr *ifmam; @@ -1815,15 +1822,14 @@ sysctl_ifmalist(int af, struct walkarg *w) ifmam->ifmam_flags = 0; ifmam->ifmam_addrs = info.rti_addrs; error = SYSCTL_OUT(w->w_req, w->w_tmem, len); - if (error) { - IF_ADDR_RUNLOCK(ifp); - goto done; - } + if (error != 0) + break; } } IF_ADDR_RUNLOCK(ifp); + if (error != 0) + break; } -done: IFNET_RUNLOCK_NOSLEEP(); return (error); } diff --git a/freebsd/sys/netinet/cc/cc.h b/freebsd/sys/netinet/cc/cc.h index 1da6f620..5e61b04b 100644 --- a/freebsd/sys/netinet/cc/cc.h +++ b/freebsd/sys/netinet/cc/cc.h @@ -86,6 +86,7 @@ struct cc_var { struct tcpcb *tcp; struct sctp_nets *sctp; } ccvc; + uint16_t nsegs; /* # segments coalesced into current chain. */ }; /* cc_var flags. */ diff --git a/freebsd/sys/netinet/cc/cc_newreno.c b/freebsd/sys/netinet/cc/cc_newreno.c index 8077bb22..4c21036a 100644 --- a/freebsd/sys/netinet/cc/cc_newreno.c +++ b/freebsd/sys/netinet/cc/cc_newreno.c @@ -139,7 +139,8 @@ newreno_ack_received(struct cc_var *ccv, uint16_t type) */ if (CCV(ccv, snd_nxt) == CCV(ccv, snd_max)) incr = min(ccv->bytes_this_ack, - V_tcp_abc_l_var * CCV(ccv, t_maxseg)); + ccv->nsegs * V_tcp_abc_l_var * + CCV(ccv, t_maxseg)); else incr = min(ccv->bytes_this_ack, CCV(ccv, t_maxseg)); } @@ -183,30 +184,42 @@ newreno_after_idle(struct cc_var *ccv) static void newreno_cong_signal(struct cc_var *ccv, uint32_t type) { - u_int win; + uint32_t cwin, ssthresh_on_loss; + u_int mss; + + cwin = CCV(ccv, snd_cwnd); + mss = CCV(ccv, t_maxseg); + ssthresh_on_loss = + max((CCV(ccv, snd_max) - CCV(ccv, snd_una)) / 2 / mss, 2) + * mss; /* Catch algos which mistakenly leak private signal types. */ KASSERT((type & CC_SIGPRIVMASK) == 0, ("%s: congestion signal type 0x%08x is private\n", __func__, type)); - win = max(CCV(ccv, snd_cwnd) / 2 / CCV(ccv, t_maxseg), 2) * - CCV(ccv, t_maxseg); + cwin = max(cwin / 2 / mss, 2) * mss; switch (type) { case CC_NDUPACK: if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) { - if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) - CCV(ccv, snd_ssthresh) = win; + if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { + CCV(ccv, snd_ssthresh) = ssthresh_on_loss; + CCV(ccv, snd_cwnd) = cwin; + } ENTER_RECOVERY(CCV(ccv, t_flags)); } break; case CC_ECN: if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) { - CCV(ccv, snd_ssthresh) = win; - CCV(ccv, snd_cwnd) = win; + CCV(ccv, snd_ssthresh) = ssthresh_on_loss; + CCV(ccv, snd_cwnd) = cwin; ENTER_CONGRECOVERY(CCV(ccv, t_flags)); } break; + case CC_RTO: + CCV(ccv, snd_ssthresh) = ssthresh_on_loss; + CCV(ccv, snd_cwnd) = mss; + break; } } diff --git a/freebsd/sys/netinet/if_ether.c b/freebsd/sys/netinet/if_ether.c index 0a8b101e..9fb25c21 100644 --- a/freebsd/sys/netinet/if_ether.c +++ b/freebsd/sys/netinet/if_ether.c @@ -139,6 +139,28 @@ SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_log_per_second, "Maximum number of remotely triggered ARP messages that can be " "logged per second"); +/* + * Due to the exponential backoff algorithm used for the interval between GARP + * retransmissions, the maximum number of retransmissions is limited for + * sanity. This limit corresponds to a maximum interval between retransmissions + * of 2^16 seconds ~= 18 hours. + * + * Making this limit more dynamic is more complicated than worthwhile, + * especially since sending out GARPs spaced days apart would be of little + * use. A maximum dynamic limit would look something like: + * + * const int max = fls(INT_MAX / hz) - 1; + */ +#define MAX_GARP_RETRANSMITS 16 +static int sysctl_garp_rexmit(SYSCTL_HANDLER_ARGS); +static int garp_rexmit_count = 0; /* GARP retransmission setting. */ + +SYSCTL_PROC(_net_link_ether_inet, OID_AUTO, garp_rexmit_count, + CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_MPSAFE, + &garp_rexmit_count, 0, sysctl_garp_rexmit, "I", + "Number of times to retransmit GARP packets;" + " 0 to disable, maximum of 16"); + #define ARP_LOG(pri, ...) do { \ if (ppsratecheck(&arp_lastlog, &arp_curpps, arp_maxpps)) \ log((pri), "arp: " __VA_ARGS__); \ @@ -1289,6 +1311,109 @@ arp_add_ifa_lle(struct ifnet *ifp, const struct sockaddr *dst) lltable_free_entry(LLTABLE(ifp), lle_tmp); } +/* + * Handle the garp_rexmit_count. Like sysctl_handle_int(), but limits the range + * of valid values. + */ +static int +sysctl_garp_rexmit(SYSCTL_HANDLER_ARGS) +{ + int error; + int rexmit_count = *(int *)arg1; + + error = sysctl_handle_int(oidp, &rexmit_count, 0, req); + + /* Enforce limits on any new value that may have been set. */ + if (!error && req->newptr) { + /* A new value was set. */ + if (rexmit_count < 0) { + rexmit_count = 0; + } else if (rexmit_count > MAX_GARP_RETRANSMITS) { + rexmit_count = MAX_GARP_RETRANSMITS; + } + *(int *)arg1 = rexmit_count; + } + + return (error); +} + +/* + * Retransmit a Gratuitous ARP (GARP) and, if necessary, schedule a callout to + * retransmit it again. A pending callout owns a reference to the ifa. + */ +static void +garp_rexmit(void *arg) +{ + struct in_ifaddr *ia = arg; + + if (callout_pending(&ia->ia_garp_timer) || + !callout_active(&ia->ia_garp_timer)) { + IF_ADDR_WUNLOCK(ia->ia_ifa.ifa_ifp); + ifa_free(&ia->ia_ifa); + return; + } + + /* + * Drop lock while the ARP request is generated. + */ + IF_ADDR_WUNLOCK(ia->ia_ifa.ifa_ifp); + + arprequest(ia->ia_ifa.ifa_ifp, &IA_SIN(ia)->sin_addr, + &IA_SIN(ia)->sin_addr, IF_LLADDR(ia->ia_ifa.ifa_ifp)); + + /* + * Increment the count of retransmissions. If the count has reached the + * maximum value, stop sending the GARP packets. Otherwise, schedule + * the callout to retransmit another GARP packet. + */ + ++ia->ia_garp_count; + if (ia->ia_garp_count >= garp_rexmit_count) { + ifa_free(&ia->ia_ifa); + } else { + int rescheduled; + IF_ADDR_WLOCK(ia->ia_ifa.ifa_ifp); + rescheduled = callout_reset(&ia->ia_garp_timer, + (1 << ia->ia_garp_count) * hz, + garp_rexmit, ia); + IF_ADDR_WUNLOCK(ia->ia_ifa.ifa_ifp); + if (rescheduled) { + ifa_free(&ia->ia_ifa); + } + } +} + +/* + * Start the GARP retransmit timer. + * + * A single GARP is always transmitted when an IPv4 address is added + * to an interface and that is usually sufficient. However, in some + * circumstances, such as when a shared address is passed between + * cluster nodes, this single GARP may occasionally be dropped or + * lost. This can lead to neighbors on the network link working with a + * stale ARP cache and sending packets destined for that address to + * the node that previously owned the address, which may not respond. + * + * To avoid this situation, GARP retransmits can be enabled by setting + * the net.link.ether.inet.garp_rexmit_count sysctl to a value greater + * than zero. The setting represents the maximum number of + * retransmissions. The interval between retransmissions is calculated + * using an exponential backoff algorithm, doubling each time, so the + * retransmission intervals are: {1, 2, 4, 8, 16, ...} (seconds). + */ +static void +garp_timer_start(struct ifaddr *ifa) +{ + struct in_ifaddr *ia = (struct in_ifaddr *) ifa; + + IF_ADDR_WLOCK(ia->ia_ifa.ifa_ifp); + ia->ia_garp_count = 0; + if (callout_reset(&ia->ia_garp_timer, (1 << ia->ia_garp_count) * hz, + garp_rexmit, ia) == 0) { + ifa_ref(ifa); + } + IF_ADDR_WUNLOCK(ia->ia_ifa.ifa_ifp); +} + void arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) { @@ -1304,6 +1429,9 @@ arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) if (ntohl(dst_in->sin_addr.s_addr) == INADDR_ANY) return; arp_announce_ifaddr(ifp, dst_in->sin_addr, IF_LLADDR(ifp)); + if (garp_rexmit_count > 0) { + garp_timer_start(ifa); + } arp_add_ifa_lle(ifp, dst); } diff --git a/freebsd/sys/netinet/igmp.c b/freebsd/sys/netinet/igmp.c index cd57e426..12bb2f07 100644 --- a/freebsd/sys/netinet/igmp.c +++ b/freebsd/sys/netinet/igmp.c @@ -545,10 +545,10 @@ igmp_ra_alloc(void) m = m_get(M_WAITOK, MT_DATA); p = mtod(m, struct ipoption *); p->ipopt_dst.s_addr = INADDR_ANY; - p->ipopt_list[0] = IPOPT_RA; /* Router Alert Option */ - p->ipopt_list[1] = 0x04; /* 4 bytes long */ - p->ipopt_list[2] = IPOPT_EOL; /* End of IP option list */ - p->ipopt_list[3] = 0x00; /* pad byte */ + p->ipopt_list[0] = (char)IPOPT_RA; /* Router Alert Option */ + p->ipopt_list[1] = 0x04; /* 4 bytes long */ + p->ipopt_list[2] = IPOPT_EOL; /* End of IP option list */ + p->ipopt_list[3] = 0x00; /* pad byte */ m->m_len = sizeof(p->ipopt_dst) + p->ipopt_list[1]; return (m); diff --git a/freebsd/sys/netinet/in.c b/freebsd/sys/netinet/in.c index 06b23973..f08e550b 100644 --- a/freebsd/sys/netinet/in.c +++ b/freebsd/sys/netinet/in.c @@ -401,6 +401,8 @@ in_aifaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr; ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr; ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask; + callout_init_rw(&ia->ia_garp_timer, &ifp->if_addr_lock, + CALLOUT_RETURNUNLOCKED); ia->ia_ifp = ifp; ia->ia_addr = *addr; @@ -639,6 +641,12 @@ in_difaddr_ioctl(caddr_t data, struct ifnet *ifp, struct thread *td) IN_MULTI_UNLOCK(); } + IF_ADDR_WLOCK(ifp); + if (callout_stop(&ia->ia_garp_timer) == 1) { + ifa_free(&ia->ia_ifa); + } + IF_ADDR_WUNLOCK(ifp); + EVENTHANDLER_INVOKE(ifaddr_event, ifp); ifa_free(&ia->ia_ifa); /* in_ifaddrhead */ diff --git a/freebsd/sys/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c index f8790938..809a7de0 100644 --- a/freebsd/sys/netinet/in_pcb.c +++ b/freebsd/sys/netinet/in_pcb.c @@ -1311,10 +1311,7 @@ in_pcbfree(struct inpcb *inp) if (inp->inp_moptions != NULL) inp_freemoptions(inp->inp_moptions); #endif - if (inp->inp_route.ro_rt) { - RTFREE(inp->inp_route.ro_rt); - inp->inp_route.ro_rt = (struct rtentry *)NULL; - } + RO_RTFREE(&inp->inp_route); if (inp->inp_route.ro_lle) LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */ @@ -2254,10 +2251,7 @@ void in_losing(struct inpcb *inp) { - if (inp->inp_route.ro_rt) { - RTFREE(inp->inp_route.ro_rt); - inp->inp_route.ro_rt = (struct rtentry *)NULL; - } + RO_RTFREE(&inp->inp_route); if (inp->inp_route.ro_lle) LLE_FREE(inp->inp_route.ro_lle); /* zeros ro_lle */ return; diff --git a/freebsd/sys/netinet/in_var.h b/freebsd/sys/netinet/in_var.h index af83e9a1..08055c4f 100644 --- a/freebsd/sys/netinet/in_var.h +++ b/freebsd/sys/netinet/in_var.h @@ -82,6 +82,8 @@ struct in_ifaddr { struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ #define ia_broadaddr ia_dstaddr struct sockaddr_in ia_sockmask; /* reserve space for general netmask */ + struct callout ia_garp_timer; /* timer for retransmitting GARPs */ + int ia_garp_count; /* count of retransmitted GARPs */ }; /* diff --git a/freebsd/sys/netinet/ip_fastfwd.c b/freebsd/sys/netinet/ip_fastfwd.c index 19dfb1ab..bc4d70b4 100644 --- a/freebsd/sys/netinet/ip_fastfwd.c +++ b/freebsd/sys/netinet/ip_fastfwd.c @@ -99,6 +99,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -109,40 +110,33 @@ __FBSDID("$FreeBSD$"); #include -static struct sockaddr_in * -ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m) +static int +ip_findroute(struct nhop4_basic *pnh, struct in_addr dest, struct mbuf *m) { - struct sockaddr_in *dst; - struct rtentry *rt; - /* - * Find route to destination. - */ - bzero(ro, sizeof(*ro)); - dst = (struct sockaddr_in *)&ro->ro_dst; - dst->sin_family = AF_INET; - dst->sin_len = sizeof(*dst); - dst->sin_addr.s_addr = dest.s_addr; - in_rtalloc_ign(ro, 0, M_GETFIB(m)); - - /* - * Route there and interface still up? - */ - rt = ro->ro_rt; - if (rt && (rt->rt_flags & RTF_UP) && - (rt->rt_ifp->if_flags & IFF_UP) && - (rt->rt_ifp->if_drv_flags & IFF_DRV_RUNNING)) { - if (rt->rt_flags & RTF_GATEWAY) - dst = (struct sockaddr_in *)rt->rt_gateway; - } else { + bzero(pnh, sizeof(*pnh)); + if (fib4_lookup_nh_basic(M_GETFIB(m), dest, 0, 0, pnh) != 0) { IPSTAT_INC(ips_noroute); IPSTAT_INC(ips_cantforward); - if (rt) - RTFREE(rt); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); - return NULL; + return (EHOSTUNREACH); } - return dst; + /* + * Drop blackholed traffic and directed broadcasts. + */ + if ((pnh->nh_flags & (NHF_BLACKHOLE | NHF_BROADCAST)) != 0) { + IPSTAT_INC(ips_cantforward); + m_freem(m); + return (EHOSTUNREACH); + } + + if (pnh->nh_flags & NHF_REJECT) { + IPSTAT_INC(ips_cantforward); + icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); + return (EHOSTUNREACH); + } + + return (0); } /* @@ -157,13 +151,11 @@ ip_tryforward(struct mbuf *m) { struct ip *ip; struct mbuf *m0 = NULL; - struct route ro; - struct sockaddr_in *dst = NULL; - struct ifnet *ifp; + struct nhop4_basic nh; + struct sockaddr_in dst; struct in_addr odest, dest; uint16_t ip_len, ip_off; int error = 0; - int mtu; struct m_tag *fwd_tag = NULL; /* @@ -173,9 +165,6 @@ ip_tryforward(struct mbuf *m) M_ASSERTVALID(m); M_ASSERTPKTHDR(m); - bzero(&ro, sizeof(ro)); - - #ifdef ALTQ /* * Is packet dropped by traffic conditioner? @@ -307,29 +296,17 @@ passin: /* * Find route to destination. */ - if ((dst = ip_findroute(&ro, dest, m)) == NULL) - return NULL; /* icmp unreach already sent */ - ifp = ro.ro_rt->rt_ifp; - - /* - * Immediately drop blackholed traffic, and directed broadcasts - * for either the all-ones or all-zero subnet addresses on - * locally attached networks. - */ - if ((ro.ro_rt->rt_flags & (RTF_BLACKHOLE|RTF_BROADCAST)) != 0) - goto drop; + if (ip_findroute(&nh, dest, m) != 0) + return (NULL); /* icmp unreach already sent */ /* * Step 5: outgoing firewall packet processing */ - - /* - * Run through list of hooks for output packets. - */ if (!PFIL_HOOKED(&V_inet_pfil_hook)) goto passout; - if (pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_OUT, NULL) || m == NULL) { + if (pfil_run_hooks(&V_inet_pfil_hook, &m, nh.nh_ifp, PFIL_OUT, NULL) || + m == NULL) { goto drop; } @@ -354,9 +331,7 @@ forwardlocal: * Return packet for processing by ip_input(). */ m->m_flags |= M_FASTFWD_OURS; - if (ro.ro_rt) - RTFREE(ro.ro_rt); - return m; + return (m); } /* * Redo route lookup with new destination address @@ -367,10 +342,8 @@ forwardlocal: m_tag_delete(m, fwd_tag); m->m_flags &= ~M_IP_NEXTHOP; } - RTFREE(ro.ro_rt); - if ((dst = ip_findroute(&ro, dest, m)) == NULL) - return NULL; /* icmp unreach already sent */ - ifp = ro.ro_rt->rt_ifp; + if (ip_findroute(&nh, dest, m) != 0) + return (NULL); /* icmp unreach already sent */ } passout: @@ -380,32 +353,15 @@ passout: ip_len = ntohs(ip->ip_len); ip_off = ntohs(ip->ip_off); - /* - * Check if route is dampned (when ARP is unable to resolve) - */ - if ((ro.ro_rt->rt_flags & RTF_REJECT) && - (ro.ro_rt->rt_expire == 0 || time_uptime < ro.ro_rt->rt_expire)) { - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); - goto consumed; - } - - /* - * Check if media link state of interface is not down - */ - if (ifp->if_link_state == LINK_STATE_DOWN) { - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); - goto consumed; - } + bzero(&dst, sizeof(dst)); + dst.sin_family = AF_INET; + dst.sin_len = sizeof(dst); + dst.sin_addr = nh.nh_addr; /* * Check if packet fits MTU or if hardware will fragment for us */ - if (ro.ro_rt->rt_mtu) - mtu = min(ro.ro_rt->rt_mtu, ifp->if_mtu); - else - mtu = ifp->if_mtu; - - if (ip_len <= mtu) { + if (ip_len <= nh.nh_mtu) { /* * Avoid confusing lower layers. */ @@ -413,9 +369,9 @@ passout: /* * Send off the packet via outgoing interface */ - IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL); - error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst, &ro); + IP_PROBE(send, NULL, NULL, ip, nh.nh_ifp, ip, NULL); + error = (*nh.nh_ifp->if_output)(nh.nh_ifp, m, + (struct sockaddr *)&dst, NULL); } else { /* * Handle EMSGSIZE with icmp reply needfrag for TCP MTU discovery @@ -423,14 +379,15 @@ passout: if (ip_off & IP_DF) { IPSTAT_INC(ips_cantfrag); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, - 0, mtu); + 0, nh.nh_mtu); goto consumed; } else { /* * We have to fragment the packet */ m->m_pkthdr.csum_flags |= CSUM_IP; - if (ip_fragment(ip, &m, mtu, ifp->if_hwassist)) + if (ip_fragment(ip, &m, nh.nh_mtu, + nh.nh_ifp->if_hwassist) != 0) goto drop; KASSERT(m != NULL, ("null mbuf and no error")); /* @@ -445,9 +402,11 @@ passout: */ m_clrprotoflags(m); - IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL); - error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst, &ro); + IP_PROBE(send, NULL, NULL, ip, nh.nh_ifp, + ip, NULL); + /* XXX: we can use cached route here */ + error = (*nh.nh_ifp->if_output)(nh.nh_ifp, m, + (struct sockaddr *)&dst, NULL); if (error) break; } while ((m = m0) != NULL); @@ -465,17 +424,13 @@ passout: if (error != 0) IPSTAT_INC(ips_odropped); else { - counter_u64_add(ro.ro_rt->rt_pksent, 1); IPSTAT_INC(ips_forward); IPSTAT_INC(ips_fastforward); } consumed: - RTFREE(ro.ro_rt); return NULL; drop: if (m) m_freem(m); - if (ro.ro_rt) - RTFREE(ro.ro_rt); return NULL; } diff --git a/freebsd/sys/netinet/ip_icmp.c b/freebsd/sys/netinet/ip_icmp.c index f34cc4bd..a1331cac 100644 --- a/freebsd/sys/netinet/ip_icmp.c +++ b/freebsd/sys/netinet/ip_icmp.c @@ -459,6 +459,8 @@ icmp_input(struct mbuf **mp, int *offp, int proto) * Treat subcodes 2,3 as immediate RST */ case ICMP_UNREACH_PROTOCOL: + code = PRC_UNREACH_PROTOCOL; + break; case ICMP_UNREACH_PORT: code = PRC_UNREACH_PORT; break; diff --git a/freebsd/sys/netinet/ip_input.c b/freebsd/sys/netinet/ip_input.c index 425dbc1f..a2278616 100644 --- a/freebsd/sys/netinet/ip_input.c +++ b/freebsd/sys/netinet/ip_input.c @@ -1002,7 +1002,7 @@ ip_forward(struct mbuf *m, int srcrt) * because unnecessary, or because rate limited), so we are * really we are wasting a lot of work here. * - * We don't use m_copy() because it might return a reference + * We don't use m_copym() because it might return a reference * to a shared cluster. Both this function and ip_output() * assume exclusive access to the IP header in `m', so any * data in a cluster may change before we reach icmp_error(). diff --git a/freebsd/sys/netinet/ip_mroute.c b/freebsd/sys/netinet/ip_mroute.c index f8b14735..f5aa0a38 100644 --- a/freebsd/sys/netinet/ip_mroute.c +++ b/freebsd/sys/netinet/ip_mroute.c @@ -1346,7 +1346,7 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m, goto fail; /* Make a copy of the header to send to the user level process */ - mm = m_copy(mb0, 0, hlen); + mm = m_copym(mb0, 0, hlen, M_NOWAIT); if (mm == NULL) goto fail1; @@ -1544,7 +1544,7 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET }; struct igmpmsg *im; int hlen = ip->ip_hl << 2; - struct mbuf *mm = m_copy(m, 0, hlen); + struct mbuf *mm = m_copym(m, 0, hlen, M_NOWAIT); if (mm && (!M_WRITABLE(mm) || mm->m_len < hlen)) mm = m_pullup(mm, hlen); @@ -2736,9 +2736,9 @@ pim_input(struct mbuf **mp, int *offp, int proto) * actions (e.g., send back PIM_REGISTER_STOP). * XXX: here m->m_data points to the outer IP header. */ - mcp = m_copy(m, 0, iphlen + PIM_REG_MINLEN); + mcp = m_copym(m, 0, iphlen + PIM_REG_MINLEN, M_NOWAIT); if (mcp == NULL) { - CTR1(KTR_IPMF, "%s: m_copy() failed", __func__); + CTR1(KTR_IPMF, "%s: m_copym() failed", __func__); m_freem(m); return (IPPROTO_DONE); } diff --git a/freebsd/sys/netinet/ip_output.c b/freebsd/sys/netinet/ip_output.c index 81e7b123..5436ea2d 100644 --- a/freebsd/sys/netinet/ip_output.c +++ b/freebsd/sys/netinet/ip_output.c @@ -352,7 +352,8 @@ again: have_ia_ref = 1; ifp = ia->ia_ifp; ip->ip_ttl = 1; - isbroadcast = in_ifaddr_broadcast(dst->sin_addr, ia); + isbroadcast = ifp->if_flags & IFF_BROADCAST ? + in_ifaddr_broadcast(dst->sin_addr, ia) : 0; } else if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) && imo != NULL && imo->imo_multicast_ifp != NULL) { /* @@ -405,8 +406,10 @@ again: gw = (struct sockaddr_in *)rte->rt_gateway; if (rte->rt_flags & RTF_HOST) isbroadcast = (rte->rt_flags & RTF_BROADCAST); - else + else if (ifp->if_flags & IFF_BROADCAST) isbroadcast = in_ifaddr_broadcast(gw->sin_addr, ia); + else + isbroadcast = 0; } /* @@ -706,11 +709,7 @@ sendit: IPSTAT_INC(ips_fragmented); done: - /* - * Release the route if using our private route, or if - * (with flowtable) we don't have our own reference. - */ - if (ro == &iproute || ro->ro_flags & RT_NORTREF) + if (ro == &iproute) RO_RTFREE(ro); else if (rte == NULL) /* diff --git a/freebsd/sys/netinet/raw_ip.c b/freebsd/sys/netinet/raw_ip.c index a4679586..c379d681 100644 --- a/freebsd/sys/netinet/raw_ip.c +++ b/freebsd/sys/netinet/raw_ip.c @@ -324,7 +324,7 @@ rip_input(struct mbuf **mp, int *offp, int proto) if (last != NULL) { struct mbuf *n; - n = m_copy(m, 0, (int)M_COPYALL); + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (n != NULL) (void) rip_append(last, ip, n, &ripsrc); /* XXX count dropped packet */ @@ -402,7 +402,7 @@ rip_input(struct mbuf **mp, int *offp, int proto) if (last != NULL) { struct mbuf *n; - n = m_copy(m, 0, (int)M_COPYALL); + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (n != NULL) (void) rip_append(last, ip, n, &ripsrc); /* XXX count dropped packet */ diff --git a/freebsd/sys/netinet/sctp_asconf.c b/freebsd/sys/netinet/sctp_asconf.c index 4256ab51..5d86e520 100644 --- a/freebsd/sys/netinet/sctp_asconf.c +++ b/freebsd/sys/netinet/sctp_asconf.c @@ -153,24 +153,19 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap union sctp_sockstore store; struct sctp_paramhdr *ph; uint16_t param_type, aparam_length; - #if defined(INET) || defined(INET6) uint16_t param_length; - #endif struct sockaddr *sa; int zero_address = 0; int bad_address = 0; - #ifdef INET struct sockaddr_in *sin; struct sctp_ipv4addr_param *v4addr; - #endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *v6addr; - #endif aparam_length = ntohs(aph->ph.param_length); @@ -308,24 +303,19 @@ sctp_process_asconf_delete_ip(struct sockaddr *src, union sctp_sockstore store; struct sctp_paramhdr *ph; uint16_t param_type, aparam_length; - #if defined(INET) || defined(INET6) uint16_t param_length; - #endif struct sockaddr *sa; int zero_address = 0; int result; - #ifdef INET struct sockaddr_in *sin; struct sctp_ipv4addr_param *v4addr; - #endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *v6addr; - #endif aparam_length = ntohs(aph->ph.param_length); @@ -443,23 +433,18 @@ sctp_process_asconf_set_primary(struct sockaddr *src, union sctp_sockstore store; struct sctp_paramhdr *ph; uint16_t param_type, aparam_length; - #if defined(INET) || defined(INET6) uint16_t param_length; - #endif struct sockaddr *sa; int zero_address = 0; - #ifdef INET struct sockaddr_in *sin; struct sctp_ipv4addr_param *v4addr; - #endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *v6addr; - #endif aparam_length = ntohs(aph->ph.param_length); @@ -1787,7 +1772,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset, * if there are any "sent" params still on the queue, these are * implicitly "success", or "failed" (if we got an error back) ... * so process these appropriately - * + * * we assume that the correlation_id's are monotonically increasing * beginning from 1 and that we don't have *that* many outstanding * at any given time @@ -1863,7 +1848,6 @@ sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa) /* didn't find one */ return (0); } - #endif /* @@ -2437,10 +2421,8 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa) } } - /* - * we want to find the sequences which consist of ADD -> DEL -> ADD - * or DEL -> ADD - */ + /* we want to find the sequences which consist of ADD -> DEL -> ADD + * or DEL -> ADD */ if (add_cnt > del_cnt || (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) { return (1); @@ -2492,10 +2474,8 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) if (sctp_is_addr_restricted(stcb, sctp_ifa) && (!sctp_is_addr_pending(stcb, sctp_ifa))) continue; - /* - * found a valid local v4 address to - * use - */ + /* found a valid local v4 address to + * use */ if (addr_locked == SCTP_ADDR_NOT_LOCKED) SCTP_IPI_ADDR_RUNLOCK(); return (&sctp_ifa->address.sa); @@ -2512,10 +2492,8 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) } sin6 = &sctp_ifa->address.sin6; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - /* - * we skip unspecifed - * addresses - */ + /* we skip unspecifed + * addresses */ continue; } if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, @@ -2532,10 +2510,8 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) if (sctp_is_addr_restricted(stcb, sctp_ifa) && (!sctp_is_addr_pending(stcb, sctp_ifa))) continue; - /* - * found a valid local v6 address to - * use - */ + /* found a valid local v6 address to + * use */ if (addr_locked == SCTP_ADDR_NOT_LOCKED) SCTP_IPI_ADDR_RUNLOCK(); return (&sctp_ifa->address.sa); @@ -2783,14 +2759,11 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, uint16_t plen, ptype; struct sctp_ifa *sctp_ifa; union sctp_sockstore store; - #ifdef INET6 struct sctp_ipv6addr_param addr6_store; - #endif #ifdef INET struct sctp_ipv4addr_param addr4_store; - #endif SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n"); @@ -2917,19 +2890,16 @@ sctp_addr_in_initack(struct mbuf *m, uint32_t offset, uint32_t length, struct so { struct sctp_paramhdr tmp_param, *ph; uint16_t plen, ptype; - #ifdef INET struct sockaddr_in *sin; struct sctp_ipv4addr_param *a4p; struct sctp_ipv6addr_param addr4_store; - #endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *a6p; struct sctp_ipv6addr_param addr6_store; struct sockaddr_in6 sin6_tmp; - #endif switch (sa->sa_family) { @@ -3081,14 +3051,11 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset, struct sctp_ifn *sctp_ifn; struct sctp_ifa *sctp_ifa; uint32_t vrf_id; - #ifdef INET struct sockaddr_in *sin; - #endif #ifdef INET6 struct sockaddr_in6 *sin6; - #endif if (stcb) { @@ -3303,14 +3270,11 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, struct sctp_asconf_addr *aa; struct sctp_ifa *sctp_ifap; struct sctp_asconf_tag_param *vtag; - #ifdef INET struct sockaddr_in *to; - #endif #ifdef INET6 struct sockaddr_in6 *to6; - #endif if (net == NULL) { SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n"); diff --git a/freebsd/sys/netinet/sctp_asconf.h b/freebsd/sys/netinet/sctp_asconf.h index 183c99b4..c8d670e5 100644 --- a/freebsd/sys/netinet/sctp_asconf.h +++ b/freebsd/sys/netinet/sctp_asconf.h @@ -90,7 +90,6 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, extern int sctp_is_addr_pending(struct sctp_tcb *, struct sctp_ifa *); - #endif /* _KERNEL */ #endif /* !_NETINET_SCTP_ASCONF_H_ */ diff --git a/freebsd/sys/netinet/sctp_bsd_addr.c b/freebsd/sys/netinet/sctp_bsd_addr.c index bfd7f816..72c63d76 100644 --- a/freebsd/sys/netinet/sctp_bsd_addr.c +++ b/freebsd/sys/netinet/sctp_bsd_addr.c @@ -142,7 +142,6 @@ sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa) ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; } } - #endif /* INET6 */ @@ -203,20 +202,18 @@ sctp_init_ifns_for_vrf(int vrfid) struct ifaddr *ifa; struct sctp_ifa *sctp_ifa; uint32_t ifa_flags; - #ifdef INET6 struct in6_ifaddr *ifa6; - #endif IFNET_RLOCK(); - TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { + TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_link) { if (sctp_is_desired_interface_type(ifn) == 0) { /* non desired type */ continue; } IF_ADDR_RLOCK(ifn); - TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { + TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) { if (ifa->ifa_addr == NULL) { continue; } @@ -363,11 +360,11 @@ void struct ifaddr *ifa; IFNET_RLOCK(); - TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { + TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_link) { if (!(*pred) (ifn)) { continue; } - TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { + TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) { sctp_addr_change(ifa, add ? RTM_ADD : RTM_DELETE); } } diff --git a/freebsd/sys/netinet/sctp_bsd_addr.h b/freebsd/sys/netinet/sctp_bsd_addr.h index 24660ca5..5fb1efb4 100644 --- a/freebsd/sys/netinet/sctp_bsd_addr.h +++ b/freebsd/sys/netinet/sctp_bsd_addr.h @@ -48,7 +48,6 @@ void sctp_startup_iterator(void); #ifdef INET6 void sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa); - #endif #ifdef SCTP_PACKET_LOGGING diff --git a/freebsd/sys/netinet/sctp_cc_functions.c b/freebsd/sys/netinet/sctp_cc_functions.c index 68dc460a..49670e9b 100644 --- a/freebsd/sys/netinet/sctp_cc_functions.c +++ b/freebsd/sys/netinet/sctp_cc_functions.c @@ -162,17 +162,13 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb, uint32_t srtt; srtt = net->lastsa; - /* - * lastsa>>3; we don't need - * to devide ... - */ + /* lastsa>>3; we don't need + * to devide ... */ if (srtt == 0) { srtt = 1; } - /* - * Short Version => Equal to - * Contel Version MBe - */ + /* Short Version => Equal to + * Contel Version MBe */ net->ssthresh = (uint32_t) (((uint64_t) 4 * (uint64_t) net->mtu * (uint64_t) net->cwnd) / @@ -211,7 +207,7 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb, /* Mark end of the window */ asoc->fast_recovery_tsn = asoc->sending_seq - 1; } else { - asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1; + asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1; } /* @@ -224,7 +220,7 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb, /* Mark end of the window */ net->fast_recovery_tsn = asoc->sending_seq - 1; } else { - net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1; + net->fast_recovery_tsn = lchk->rec.data.tsn - 1; } sctp_timer_stop(SCTP_TIMER_TYPE_SEND, @@ -407,10 +403,8 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6 net->flight_size, probepoint); if (net->cc_mod.rtcc.ret_from_eq) { - /* - * Switch over to CA if we are less - * aggressive - */ + /* Switch over to CA if we are less + * aggressive */ net->ssthresh = net->cwnd - 1; net->partial_bytes_acked = 0; } @@ -786,9 +780,9 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, /* * At this point our bw_bytes has been updated by * incoming sack information. - * + * * But our bw may not yet be set. - * + * */ if ((net->cc_mod.rtcc.new_tot_time / 1000) > 0) { nbw = net->cc_mod.rtcc.bw_bytes / (net->cc_mod.rtcc.new_tot_time / 1000); @@ -853,10 +847,8 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, } break; case SCTP_CMT_RPV2: - /* - * lastsa>>3; we don't need - * to divide ... - */ + /* lastsa>>3; we don't need + * to divide ... */ srtt = net->lastsa; if (srtt == 0) { srtt = 1; @@ -940,10 +932,8 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, } break; case SCTP_CMT_RPV2: - /* - * lastsa>>3; we don't need - * to divide ... - */ + /* lastsa>>3; we don't need + * to divide ... */ srtt = net->lastsa; if (srtt == 0) { srtt = 1; @@ -1110,10 +1100,8 @@ sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets * sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT); } } else { - /* - * Further tuning down required over the drastic - * original cut - */ + /* Further tuning down required over the drastic + * original cut */ net->ssthresh -= (net->mtu * num_pkt_lost); net->cwnd -= (net->mtu * num_pkt_lost); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { @@ -1127,10 +1115,8 @@ sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets * net->ssthresh = net->cwnd / 2; if (net->ssthresh < net->mtu) { net->ssthresh = net->mtu; - /* - * here back off the timer as well, to slow - * us down - */ + /* here back off the timer as well, to slow + * us down */ net->RTO <<= 1; } net->cwnd = net->ssthresh; @@ -1377,10 +1363,8 @@ sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb, cwnd_in_mtu = SCTP_BASE_SYSCTL(sctp_initial_cwnd); if (cwnd_in_mtu == 0) { - /* - * Using 0 means that the value of RFC 4960 - * is used. - */ + /* Using 0 means that the value of RFC 4960 + * is used. */ cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND)); } else { /* @@ -1392,10 +1376,8 @@ sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb, cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu; } if (net->cwnd > cwnd) { - /* - * Only set if we are not a timeout (i.e. - * down to 1 mtu) - */ + /* Only set if we are not a timeout (i.e. + * down to 1 mtu) */ net->cwnd = cwnd; } } @@ -1718,7 +1700,7 @@ sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb, /* Mark end of the window */ asoc->fast_recovery_tsn = asoc->sending_seq - 1; } else { - asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1; + asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1; } /* @@ -1731,7 +1713,7 @@ sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb, /* Mark end of the window */ net->fast_recovery_tsn = asoc->sending_seq - 1; } else { - net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1; + net->fast_recovery_tsn = lchk->rec.data.tsn - 1; } sctp_timer_stop(SCTP_TIMER_TYPE_SEND, @@ -2025,10 +2007,8 @@ htcp_param_update(struct sctp_nets *net) htcp_beta_update(&net->cc_mod.htcp_ca, minRTT, maxRTT); htcp_alpha_update(&net->cc_mod.htcp_ca); - /* - * add slowly fading memory for maxRTT to accommodate routing - * changes etc - */ + /* add slowly fading memory for maxRTT to accommodate routing + * changes etc */ if (minRTT > 0 && maxRTT > minRTT) net->cc_mod.htcp_ca.maxRTT = minRTT + ((maxRTT - minRTT) * 95) / 100; } @@ -2111,7 +2091,6 @@ htcp_min_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net) { return (net->ssthresh); } - #endif static void @@ -2251,7 +2230,7 @@ sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb, /* Mark end of the window */ asoc->fast_recovery_tsn = asoc->sending_seq - 1; } else { - asoc->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1; + asoc->fast_recovery_tsn = lchk->rec.data.tsn - 1; } /* @@ -2264,7 +2243,7 @@ sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb, /* Mark end of the window */ net->fast_recovery_tsn = asoc->sending_seq - 1; } else { - net->fast_recovery_tsn = lchk->rec.data.TSN_seq - 1; + net->fast_recovery_tsn = lchk->rec.data.tsn - 1; } sctp_timer_stop(SCTP_TIMER_TYPE_SEND, diff --git a/freebsd/sys/netinet/sctp_constants.h b/freebsd/sys/netinet/sctp_constants.h index ecde4fee..e779051d 100644 --- a/freebsd/sys/netinet/sctp_constants.h +++ b/freebsd/sys/netinet/sctp_constants.h @@ -898,8 +898,9 @@ __FBSDID("$FreeBSD$"); #define SCTP_SSN_GE(a, b) SCTP_UINT16_GE(a, b) #define SCTP_TSN_GT(a, b) SCTP_UINT32_GT(a, b) #define SCTP_TSN_GE(a, b) SCTP_UINT32_GE(a, b) -#define SCTP_MSGID_GT(o, a, b) ((o == 1) ? SCTP_UINT16_GT((uint16_t)a, (uint16_t)b) : SCTP_UINT32_GT(a, b)) -#define SCTP_MSGID_GE(o, a, b) ((o == 1) ? SCTP_UINT16_GE((uint16_t)a, (uint16_t)b) : SCTP_UINT32_GE(a, b)) +#define SCTP_MID_GT(i, a, b) (((i) == 1) ? SCTP_UINT32_GT(a, b) : SCTP_UINT16_GT((uint16_t)a, (uint16_t)b)) +#define SCTP_MID_GE(i, a, b) (((i) == 1) ? SCTP_UINT32_GE(a, b) : SCTP_UINT16_GE((uint16_t)a, (uint16_t)b)) +#define SCTP_MID_EQ(i, a, b) (((i) == 1) ? a == b : (uint16_t)a == (uint16_t)b) /* Mapping array manipulation routines */ #define SCTP_IS_TSN_PRESENT(arry, gap) ((arry[(gap >> 3)] >> (gap & 0x07)) & 0x01) diff --git a/freebsd/sys/netinet/sctp_crc32.c b/freebsd/sys/netinet/sctp_crc32.c index bb081e8f..9130feb2 100644 --- a/freebsd/sys/netinet/sctp_crc32.c +++ b/freebsd/sys/netinet/sctp_crc32.c @@ -115,7 +115,6 @@ sctp_calculate_cksum(struct mbuf *m, uint32_t offset) base = sctp_finalize_crc32c(base); return (base); } - #endif /* !defined(SCTP_WITH_NO_CSUM) */ diff --git a/freebsd/sys/netinet/sctp_crc32.h b/freebsd/sys/netinet/sctp_crc32.h index 3f98be41..7fe02f5c 100644 --- a/freebsd/sys/netinet/sctp_crc32.h +++ b/freebsd/sys/netinet/sctp_crc32.h @@ -39,9 +39,7 @@ __FBSDID("$FreeBSD$"); #if defined(_KERNEL) #if !defined(SCTP_WITH_NO_CSUM) uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t); - #endif void sctp_delayed_cksum(struct mbuf *, uint32_t offset); - #endif /* _KERNEL */ #endif /* __crc32c_h__ */ diff --git a/freebsd/sys/netinet/sctp_header.h b/freebsd/sys/netinet/sctp_header.h index 3f4948dd..b650d930 100644 --- a/freebsd/sys/netinet/sctp_header.h +++ b/freebsd/sys/netinet/sctp_header.h @@ -141,9 +141,9 @@ struct sctp_supported_chunk_types_param { */ struct sctp_data { uint32_t tsn; - uint16_t stream_id; - uint16_t stream_sequence; - uint32_t protocol_id; + uint16_t sid; + uint16_t ssn; + uint32_t ppid; /* user data follows */ } SCTP_PACKED; @@ -154,11 +154,11 @@ struct sctp_data_chunk { struct sctp_idata { uint32_t tsn; - uint16_t stream_id; + uint16_t sid; uint16_t reserved; /* Where does the SSN go? */ - uint32_t msg_id; + uint32_t mid; union { - uint32_t protocol_id; + uint32_t ppid; uint32_t fsn; /* Fragment Sequence Number */ } ppid_fsn; /* user data follows */ @@ -182,7 +182,6 @@ struct sctp_init { uint32_t initial_tsn; /* I-TSN */ /* optional param's follow */ } SCTP_PACKED; - #define SCTP_IDENTIFICATION_SIZE 16 #define SCTP_ADDRESS_SIZE 4 #define SCTP_RESERVE_SPACE 6 @@ -391,14 +390,14 @@ struct sctp_forward_tsn_chunk { } SCTP_PACKED; struct sctp_strseq { - uint16_t stream; - uint16_t sequence; + uint16_t sid; + uint16_t ssn; } SCTP_PACKED; struct sctp_strseq_mid { - uint16_t stream; + uint16_t sid; uint16_t flags; - uint32_t msg_id; + uint32_t mid; }; struct sctp_forward_tsn_msg { diff --git a/freebsd/sys/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c index 12c2c80f..d9449a66 100644 --- a/freebsd/sys/netinet/sctp_indata.c +++ b/freebsd/sys/netinet/sctp_indata.c @@ -132,8 +132,8 @@ struct sctp_queued_to_read * sctp_build_readq_entry(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t tsn, uint32_t ppid, - uint32_t context, uint16_t stream_no, - uint32_t stream_seq, uint8_t flags, + uint32_t context, uint16_t sid, + uint32_t mid, uint8_t flags, struct mbuf *dm) { struct sctp_queued_to_read *read_queue_e = NULL; @@ -143,14 +143,14 @@ sctp_build_readq_entry(struct sctp_tcb *stcb, goto failed_build; } memset(read_queue_e, 0, sizeof(struct sctp_queued_to_read)); - read_queue_e->sinfo_stream = stream_no; - read_queue_e->sinfo_ssn = stream_seq; + read_queue_e->sinfo_stream = sid; read_queue_e->sinfo_flags = (flags << 8); read_queue_e->sinfo_ppid = ppid; read_queue_e->sinfo_context = context; read_queue_e->sinfo_tsn = tsn; read_queue_e->sinfo_cumtsn = tsn; read_queue_e->sinfo_assoc_id = sctp_get_associd(stcb); + read_queue_e->mid = mid; read_queue_e->top_fsn = read_queue_e->fsn_included = 0xffffffff; TAILQ_INIT(&read_queue_e->reasm); read_queue_e->whoFrom = net; @@ -343,10 +343,8 @@ sctp_place_control_in_stream(struct sctp_stream_in *strm, q = &strm->uno_inqueue; if (asoc->idata_supported == 0) { if (!TAILQ_EMPTY(q)) { - /* - * Only one stream can be here in old style - * -- abort - */ + /* Only one stream can be here in old style + * -- abort */ return (-1); } TAILQ_INSERT_TAIL(q, control, next_instrm); @@ -370,7 +368,7 @@ sctp_place_control_in_stream(struct sctp_stream_in *strm, return (0); } else { TAILQ_FOREACH(at, q, next_instrm) { - if (SCTP_TSN_GT(at->msg_id, control->msg_id)) { + if (SCTP_MID_GT(asoc->idata_supported, at->mid, control->mid)) { /* * one in queue is bigger than the new one, * insert before this one @@ -382,7 +380,7 @@ sctp_place_control_in_stream(struct sctp_stream_in *strm, control->on_strm_q = SCTP_ON_ORDERED; } break; - } else if (at->msg_id == control->msg_id) { + } else if (SCTP_MID_EQ(asoc->idata_supported, at->mid, control->mid)) { /* * Gak, He sent me a duplicate msg id * number?? return -1 to abort. @@ -427,18 +425,18 @@ sctp_abort_in_reasm(struct sctp_tcb *stcb, "Reass %x,CF:%x,TSN=%8.8x,SID=%4.4x,FSN=%8.8x,MID:%8.8x", opspot, control->fsn_included, - chk->rec.data.TSN_seq, - chk->rec.data.stream_number, - chk->rec.data.fsn_num, chk->rec.data.stream_seq); + chk->rec.data.tsn, + chk->rec.data.sid, + chk->rec.data.fsn, chk->rec.data.mid); } else { snprintf(msg, sizeof(msg), "Reass %x,CI:%x,TSN=%8.8x,SID=%4.4x,FSN=%4.4x,SSN:%4.4x", opspot, control->fsn_included, - chk->rec.data.TSN_seq, - chk->rec.data.stream_number, - chk->rec.data.fsn_num, - (uint16_t) chk->rec.data.stream_seq); + chk->rec.data.tsn, + chk->rec.data.sid, + chk->rec.data.fsn, + (uint16_t) chk->rec.data.mid); } oper = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); sctp_m_freem(chk->data); @@ -489,13 +487,13 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, * has wrapped but not in the stream. Is this worth worrying about * or should we just change our queue sort at the bottom to be by * TSN. - * - * Could it also be legal for a peer to send ssn 1 with TSN 2 and ssn 2 - * with TSN 1? If the peer is doing some sort of funky TSN/SSN + * + * Could it also be legal for a peer to send ssn 1 with TSN 2 and + * ssn 2 with TSN 1? If the peer is doing some sort of funky TSN/SSN * assignment this could happen... and I don't see how this would be * a violation. So for now I am undecided an will leave the sort by * SSN alone. Maybe a hybred approach is the answer - * + * */ struct sctp_queued_to_read *at; int queue_needed; @@ -506,19 +504,27 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INTO_STRD); } - if (SCTP_MSGID_GT((!asoc->idata_supported), strm->last_sequence_delivered, control->sinfo_ssn)) { + if (SCTP_MID_GT((asoc->idata_supported), strm->last_mid_delivered, control->mid)) { /* The incoming sseq is behind where we last delivered? */ SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ: %u delivered: %u from peer, Abort association\n", - control->sinfo_ssn, strm->last_sequence_delivered); + control->mid, strm->last_mid_delivered); protocol_error: /* * throw it in the stream so it gets cleaned up in * association destruction */ TAILQ_INSERT_HEAD(&strm->inqueue, control, next_instrm); - snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", - strm->last_sequence_delivered, control->sinfo_tsn, - control->sinfo_stream, control->sinfo_ssn); + if (asoc->idata_supported) { + snprintf(msg, sizeof(msg), "Delivered MID=%8.8x, got TSN=%8.8x, SID=%4.4x, MID=%8.8x", + strm->last_mid_delivered, control->sinfo_tsn, + control->sinfo_stream, control->mid); + } else { + snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + (uint16_t) strm->last_mid_delivered, + control->sinfo_tsn, + control->sinfo_stream, + (uint16_t) control->mid); + } op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_2; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); @@ -532,8 +538,8 @@ protocol_error: queue_needed = 1; asoc->size_on_all_streams += control->length; sctp_ucount_incr(asoc->cnt_on_all_streams); - nxt_todel = strm->last_sequence_delivered + 1; - if (nxt_todel == control->sinfo_ssn) { + nxt_todel = strm->last_mid_delivered + 1; + if (SCTP_MID_EQ(asoc->idata_supported, nxt_todel, control->mid)) { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; @@ -556,7 +562,7 @@ protocol_error: queue_needed = 0; asoc->size_on_all_streams -= control->length; sctp_ucount_decr(asoc->cnt_on_all_streams); - strm->last_sequence_delivered++; + strm->last_mid_delivered++; sctp_mark_non_revokable(asoc, control->sinfo_tsn); sctp_add_to_readq(stcb->sctp_ep, stcb, control, @@ -564,8 +570,8 @@ protocol_error: SCTP_READ_LOCK_NOT_HELD, SCTP_SO_LOCKED); TAILQ_FOREACH_SAFE(control, &strm->inqueue, next_instrm, at) { /* all delivered */ - nxt_todel = strm->last_sequence_delivered + 1; - if ((nxt_todel == control->sinfo_ssn) && + nxt_todel = strm->last_mid_delivered + 1; + if (SCTP_MID_EQ(asoc->idata_supported, nxt_todel, control->mid) && (((control->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG)) { asoc->size_on_all_streams -= control->length; sctp_ucount_decr(asoc->cnt_on_all_streams); @@ -578,7 +584,7 @@ protocol_error: #endif } control->on_strm_q = 0; - strm->last_sequence_delivered++; + strm->last_mid_delivered++; /* * We ignore the return of deliver_data here * since we always can hold the chunk on the @@ -596,7 +602,7 @@ protocol_error: SCTP_READ_LOCK_NOT_HELD, SCTP_SO_LOCKED); continue; - } else if (nxt_todel == control->sinfo_ssn) { + } else if (SCTP_MID_EQ(asoc->idata_supported, nxt_todel, control->mid)) { *need_reasm = 1; } break; @@ -612,8 +618,8 @@ protocol_error: */ if (sctp_place_control_in_stream(strm, asoc, control)) { snprintf(msg, sizeof(msg), - "Queue to str msg_id: %u duplicate", - control->msg_id); + "Queue to str MID: %u duplicate", + control->mid); sctp_clean_up_control(stcb, control); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_3; @@ -724,10 +730,10 @@ sctp_build_readq_entry_from_ctl(struct sctp_queued_to_read *nc, struct sctp_queu { memset(nc, 0, sizeof(struct sctp_queued_to_read)); nc->sinfo_stream = control->sinfo_stream; - nc->sinfo_ssn = control->sinfo_ssn; + nc->mid = control->mid; TAILQ_INIT(&nc->reasm); nc->top_fsn = control->top_fsn; - nc->msg_id = control->msg_id; + nc->mid = control->mid; nc->sinfo_flags = control->sinfo_flags; nc->sinfo_ppid = control->sinfo_ppid; nc->sinfo_context = control->sinfo_context; @@ -766,11 +772,11 @@ sctp_handle_old_unordered_data(struct sctp_tcb *stcb, { /* * Special handling for the old un-ordered data chunk. All the - * chunks/TSN's go to msg_id 0. So we have to do the old style - * watching to see if we have it all. If you return one, no other - * control entries on the un-ordered queue will be looked at. In - * theory there should be no others entries in reality, unless the - * guy is sending both unordered NDATA and unordered DATA... + * chunks/TSN's go to mid 0. So we have to do the old style watching + * to see if we have it all. If you return one, no other control + * entries on the un-ordered queue will be looked at. In theory + * there should be no others entries in reality, unless the guy is + * sending both unordered NDATA and unordered DATA... */ struct sctp_tmit_chunk *chk, *lchk, *tchk; uint32_t fsn; @@ -787,7 +793,7 @@ restart: fsn = control->fsn_included + 1; /* Now what can we add? */ TAILQ_FOREACH_SAFE(chk, &control->reasm, sctp_next, lchk) { - if (chk->rec.data.fsn_num == fsn) { + if (chk->rec.data.fsn == fsn) { /* Ok lets add it */ sctp_alloc_a_readq(stcb, nc); if (nc == NULL) { @@ -811,12 +817,14 @@ restart: tchk = TAILQ_FIRST(&control->reasm); if (tchk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) { TAILQ_REMOVE(&control->reasm, tchk, sctp_next); + asoc->size_on_reasm_queue -= tchk->send_size; + sctp_ucount_decr(asoc->cnt_on_reasm_queue); nc->first_frag_seen = 1; - nc->fsn_included = tchk->rec.data.fsn_num; + nc->fsn_included = tchk->rec.data.fsn; nc->data = tchk->data; - nc->sinfo_ppid = tchk->rec.data.payloadtype; - nc->sinfo_tsn = tchk->rec.data.TSN_seq; - sctp_mark_non_revokable(asoc, tchk->rec.data.TSN_seq); + nc->sinfo_ppid = tchk->rec.data.ppid; + nc->sinfo_tsn = tchk->rec.data.tsn; + sctp_mark_non_revokable(asoc, tchk->rec.data.tsn); tchk->data = NULL; sctp_free_a_chunk(stcb, tchk, SCTP_SO_NOT_LOCKED); sctp_setup_tail_pointer(nc); @@ -828,10 +836,8 @@ restart: TAILQ_INSERT_TAIL(&nc->reasm, tchk, sctp_next); tchk = TAILQ_FIRST(&control->reasm); } - /* - * Now lets add it to the queue - * after removing control - */ + /* Now lets add it to the queue + * after removing control */ TAILQ_INSERT_TAIL(&strm->uno_inqueue, nc, next_instrm); nc->on_strm_q = SCTP_ON_UNORDERED; if (control->on_strm_q) { @@ -855,10 +861,8 @@ restart: } sctp_wakeup_the_read_socket(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); if ((nc->first_frag_seen) && !TAILQ_EMPTY(&nc->reasm)) { - /* - * Switch to the new guy and - * continue - */ + /* Switch to the new guy and + * continue */ control = nc; goto restart; } else { @@ -906,7 +910,7 @@ sctp_inject_old_unordered_data(struct sctp_tcb *stcb, /* Its the very first one. */ SCTPDBG(SCTP_DEBUG_XXX, "chunk is a first fsn: %u becomes fsn_included\n", - chk->rec.data.fsn_num); + chk->rec.data.fsn); if (control->first_frag_seen) { /* * In old un-ordered we can reassembly on one @@ -917,24 +921,22 @@ sctp_inject_old_unordered_data(struct sctp_tcb *stcb, struct mbuf *tdata; uint32_t tmp; - if (SCTP_TSN_GT(chk->rec.data.fsn_num, control->fsn_included)) { - /* - * Easy way the start of a new guy beyond - * the lowest - */ + if (SCTP_TSN_GT(chk->rec.data.fsn, control->fsn_included)) { + /* Easy way the start of a new guy beyond + * the lowest */ goto place_chunk; } - if ((chk->rec.data.fsn_num == control->fsn_included) || + if ((chk->rec.data.fsn == control->fsn_included) || (control->pdapi_started)) { /* * Ok this should not happen, if it does we * started the pd-api on the higher TSN * (since the equals part is a TSN failure * it must be that). - * - * We are completly hosed in that case since I - * have no way to recover. This really will - * only happen if we can get more TSN's + * + * We are completly hosed in that case since + * I have no way to recover. This really + * will only happen if we can get more TSN's * higher before the pd-api-point. */ sctp_abort_in_reasm(stcb, control, chk, @@ -958,25 +960,25 @@ sctp_inject_old_unordered_data(struct sctp_tcb *stcb, sctp_setup_tail_pointer(control); /* Fix the FSN included */ tmp = control->fsn_included; - control->fsn_included = chk->rec.data.fsn_num; - chk->rec.data.fsn_num = tmp; + control->fsn_included = chk->rec.data.fsn; + chk->rec.data.fsn = tmp; /* Fix the TSN included */ tmp = control->sinfo_tsn; - control->sinfo_tsn = chk->rec.data.TSN_seq; - chk->rec.data.TSN_seq = tmp; + control->sinfo_tsn = chk->rec.data.tsn; + chk->rec.data.tsn = tmp; /* Fix the PPID included */ tmp = control->sinfo_ppid; - control->sinfo_ppid = chk->rec.data.payloadtype; - chk->rec.data.payloadtype = tmp; + control->sinfo_ppid = chk->rec.data.ppid; + chk->rec.data.ppid = tmp; /* Fix tail pointer */ goto place_chunk; } control->first_frag_seen = 1; - control->top_fsn = control->fsn_included = chk->rec.data.fsn_num; - control->sinfo_tsn = chk->rec.data.TSN_seq; - control->sinfo_ppid = chk->rec.data.payloadtype; + control->top_fsn = control->fsn_included = chk->rec.data.fsn; + control->sinfo_tsn = chk->rec.data.tsn; + control->sinfo_ppid = chk->rec.data.ppid; control->data = chk->data; - sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq); + sctp_mark_non_revokable(asoc, chk->rec.data.tsn); chk->data = NULL; sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); sctp_setup_tail_pointer(control); @@ -985,7 +987,7 @@ sctp_inject_old_unordered_data(struct sctp_tcb *stcb, place_chunk: inserted = 0; TAILQ_FOREACH(at, &control->reasm, sctp_next) { - if (SCTP_TSN_GT(at->rec.data.fsn_num, chk->rec.data.fsn_num)) { + if (SCTP_TSN_GT(at->rec.data.fsn, chk->rec.data.fsn)) { /* * This one in queue is bigger than the new one, * insert the new one before at. @@ -995,7 +997,7 @@ place_chunk: inserted = 1; TAILQ_INSERT_BEFORE(at, chk, sctp_next); break; - } else if (at->rec.data.fsn_num == chk->rec.data.fsn_num) { + } else if (at->rec.data.fsn == chk->rec.data.fsn) { /* * They sent a duplicate fsn number. This really * should not happen since the FSN is a TSN and it @@ -1011,7 +1013,7 @@ place_chunk: /* Its at the end */ asoc->size_on_reasm_queue += chk->send_size; sctp_ucount_incr(asoc->cnt_on_reasm_queue); - control->top_fsn = chk->rec.data.fsn_num; + control->top_fsn = chk->rec.data.fsn; TAILQ_INSERT_TAIL(&control->reasm, chk, sctp_next); } } @@ -1052,7 +1054,7 @@ sctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc, } while (control) { SCTPDBG(SCTP_DEBUG_XXX, "Looking at control: %p e(%d) ssn: %u top_fsn: %u inc_fsn: %u -uo\n", - control, control->end_added, control->sinfo_ssn, control->top_fsn, control->fsn_included); + control, control->end_added, control->mid, control->top_fsn, control->fsn_included); nctl = TAILQ_NEXT(control, next_instrm); if (control->end_added) { /* We just put the last bit on */ @@ -1097,7 +1099,7 @@ done_un: if (control == NULL) { return (ret); } - if (strm->last_sequence_delivered == control->sinfo_ssn) { + if (SCTP_MID_EQ(asoc->idata_supported, strm->last_mid_delivered, control->mid)) { /* * Ok the guy at the top was being partially delivered * completed, so we remove it. Note the pd_api flag was @@ -1107,9 +1109,9 @@ done_un: nctl = TAILQ_NEXT(control, next_instrm); SCTPDBG(SCTP_DEBUG_XXX, "Looking at control: %p e(%d) ssn: %u top_fsn: %u inc_fsn: %u (lastdel: %u)- o\n", - control, control->end_added, control->sinfo_ssn, + control, control->end_added, control->mid, control->top_fsn, control->fsn_included, - strm->last_sequence_delivered); + strm->last_mid_delivered); if (control->end_added) { if (control->on_strm_q) { #ifdef INVARIANTS @@ -1136,21 +1138,19 @@ done_un: } } if (strm->pd_api_started) { - /* - * Can't add more must have gotten an un-ordered above being - * partially delivered. - */ + /* Can't add more must have gotten an un-ordered above being + * partially delivered. */ return (0); } deliver_more: - next_to_del = strm->last_sequence_delivered + 1; + next_to_del = strm->last_mid_delivered + 1; if (control) { SCTPDBG(SCTP_DEBUG_XXX, "Looking at control: %p e(%d) ssn: %u top_fsn: %u inc_fsn: %u (nxtdel: %u)- o\n", - control, control->end_added, control->sinfo_ssn, control->top_fsn, control->fsn_included, + control, control->end_added, control->mid, control->top_fsn, control->fsn_included, next_to_del); nctl = TAILQ_NEXT(control, next_instrm); - if ((control->sinfo_ssn == next_to_del) && + if (SCTP_MID_EQ(asoc->idata_supported, control->mid, next_to_del) && (control->first_frag_seen)) { int done; @@ -1171,21 +1171,15 @@ deliver_more: ret++; } if (((control->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG) { - /* - * A singleton now slipping through - mark - * it non-revokable too - */ + /* A singleton now slipping through - mark + * it non-revokable too */ sctp_mark_non_revokable(asoc, control->sinfo_tsn); } else if (control->end_added == 0) { - /* - * Check if we can defer adding until its - * all there - */ + /* Check if we can defer adding until its + * all there */ if ((control->length < pd_point) || (strm->pd_api_started)) { - /* - * Don't need it or cannot add more - * (one being delivered that way) - */ + /* Don't need it or cannot add more + * (one being delivered that way) */ goto out; } } @@ -1196,7 +1190,7 @@ deliver_more: &stcb->sctp_socket->so_rcv, control->end_added, inp_read_lock_held, SCTP_SO_NOT_LOCKED); } - strm->last_sequence_delivered = next_to_del; + strm->last_mid_delivered = next_to_del; if (done) { control = nctl; goto deliver_more; @@ -1237,10 +1231,10 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *control, } else { sctp_add_to_tail_pointer(control, chk->data); } - control->fsn_included = chk->rec.data.fsn_num; + control->fsn_included = chk->rec.data.fsn; asoc->size_on_reasm_queue -= chk->send_size; sctp_ucount_decr(asoc->cnt_on_reasm_queue); - sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq); + sctp_mark_non_revokable(asoc, chk->rec.data.tsn); chk->data = NULL; if (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) { control->first_frag_seen = 1; @@ -1341,7 +1335,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, /* Its the very first one. */ SCTPDBG(SCTP_DEBUG_XXX, "chunk is a first fsn: %u becomes fsn_included\n", - chk->rec.data.fsn_num); + chk->rec.data.fsn); if (control->first_frag_seen) { /* * Error on senders part, they either sent us two @@ -1355,9 +1349,9 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, return; } control->first_frag_seen = 1; - control->fsn_included = chk->rec.data.fsn_num; + control->fsn_included = chk->rec.data.fsn; control->data = chk->data; - sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq); + sctp_mark_non_revokable(asoc, chk->rec.data.tsn); chk->data = NULL; sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); sctp_setup_tail_pointer(control); @@ -1367,16 +1361,16 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, if (control->last_frag_seen == 0) { /* Still willing to raise highest FSN seen */ - if (SCTP_TSN_GT(chk->rec.data.fsn_num, control->top_fsn)) { + if (SCTP_TSN_GT(chk->rec.data.fsn, control->top_fsn)) { SCTPDBG(SCTP_DEBUG_XXX, "We have a new top_fsn: %u\n", - chk->rec.data.fsn_num); - control->top_fsn = chk->rec.data.fsn_num; + chk->rec.data.fsn); + control->top_fsn = chk->rec.data.fsn; } if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { SCTPDBG(SCTP_DEBUG_XXX, "The last fsn is now in place fsn: %u\n", - chk->rec.data.fsn_num); + chk->rec.data.fsn); control->last_frag_seen = 1; } if (asoc->idata_supported || control->first_frag_seen) { @@ -1386,11 +1380,9 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, * DATA we have to receive the first before * we know the first FSN (which is the TSN). */ - if (SCTP_TSN_GE(control->fsn_included, chk->rec.data.fsn_num)) { - /* - * We have already delivered up to - * this so its a dup - */ + if (SCTP_TSN_GE(control->fsn_included, chk->rec.data.fsn)) { + /* We have already delivered up to + * this so its a dup */ sctp_abort_in_reasm(stcb, control, chk, abort_flag, SCTP_FROM_SCTP_INDATA + SCTP_LOC_9); @@ -1402,7 +1394,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, /* Second last? huh? */ SCTPDBG(SCTP_DEBUG_XXX, "Duplicate last fsn: %u (top: %u) -- abort\n", - chk->rec.data.fsn_num, control->top_fsn); + chk->rec.data.fsn, control->top_fsn); sctp_abort_in_reasm(stcb, control, chk, abort_flag, SCTP_FROM_SCTP_INDATA + SCTP_LOC_10); @@ -1416,28 +1408,24 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, * we know the first FSN (which is the TSN). */ - if (SCTP_TSN_GE(control->fsn_included, chk->rec.data.fsn_num)) { - /* - * We have already delivered up to - * this so its a dup - */ + if (SCTP_TSN_GE(control->fsn_included, chk->rec.data.fsn)) { + /* We have already delivered up to + * this so its a dup */ SCTPDBG(SCTP_DEBUG_XXX, "New fsn: %u is already seen in included_fsn: %u -- abort\n", - chk->rec.data.fsn_num, control->fsn_included); + chk->rec.data.fsn, control->fsn_included); sctp_abort_in_reasm(stcb, control, chk, abort_flag, SCTP_FROM_SCTP_INDATA + SCTP_LOC_11); return; } } - /* - * validate not beyond top FSN if we have seen last - * one - */ - if (SCTP_TSN_GT(chk->rec.data.fsn_num, control->top_fsn)) { + /* validate not beyond top FSN if we have seen last + * one */ + if (SCTP_TSN_GT(chk->rec.data.fsn, control->top_fsn)) { SCTPDBG(SCTP_DEBUG_XXX, "New fsn: %u is beyond or at top_fsn: %u -- abort\n", - chk->rec.data.fsn_num, + chk->rec.data.fsn, control->top_fsn); sctp_abort_in_reasm(stcb, control, chk, abort_flag, @@ -1451,26 +1439,24 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, */ SCTPDBG(SCTP_DEBUG_XXX, "chunk is a not first fsn: %u needs to be inserted\n", - chk->rec.data.fsn_num); + chk->rec.data.fsn); TAILQ_FOREACH(at, &control->reasm, sctp_next) { - if (SCTP_TSN_GT(at->rec.data.fsn_num, chk->rec.data.fsn_num)) { + if (SCTP_TSN_GT(at->rec.data.fsn, chk->rec.data.fsn)) { /* * This one in queue is bigger than the new * one, insert the new one before at. */ SCTPDBG(SCTP_DEBUG_XXX, "Insert it before fsn: %u\n", - at->rec.data.fsn_num); + at->rec.data.fsn); asoc->size_on_reasm_queue += chk->send_size; sctp_ucount_incr(asoc->cnt_on_reasm_queue); TAILQ_INSERT_BEFORE(at, chk, sctp_next); inserted = 1; break; - } else if (at->rec.data.fsn_num == chk->rec.data.fsn_num) { - /* - * Gak, He sent me a duplicate str seq - * number - */ + } else if (at->rec.data.fsn == chk->rec.data.fsn) { + /* Gak, He sent me a duplicate str seq + * number */ /* * foo bar, I guess I will just free this * new guy, should we abort too? FIX ME @@ -1481,7 +1467,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, */ SCTPDBG(SCTP_DEBUG_XXX, "Duplicate to fsn: %u -- abort\n", - at->rec.data.fsn_num); + at->rec.data.fsn); sctp_abort_in_reasm(stcb, control, chk, abort_flag, SCTP_FROM_SCTP_INDATA + SCTP_LOC_13); @@ -1491,7 +1477,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, if (inserted == 0) { /* Goes on the end */ SCTPDBG(SCTP_DEBUG_XXX, "Inserting at tail of list fsn: %u\n", - chk->rec.data.fsn_num); + chk->rec.data.fsn); asoc->size_on_reasm_queue += chk->send_size; sctp_ucount_incr(asoc->cnt_on_reasm_queue); TAILQ_INSERT_TAIL(&control->reasm, chk, sctp_next); @@ -1509,12 +1495,12 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, if (control->first_frag_seen) { next_fsn = control->fsn_included + 1; TAILQ_FOREACH_SAFE(at, &control->reasm, sctp_next, nat) { - if (at->rec.data.fsn_num == next_fsn) { + if (at->rec.data.fsn == next_fsn) { /* We can add this one now to the control */ SCTPDBG(SCTP_DEBUG_XXX, "Adding more to control: %p at: %p fsn: %u next_fsn: %u included: %u\n", control, at, - at->rec.data.fsn_num, + at->rec.data.fsn, next_fsn, control->fsn_included); TAILQ_REMOVE(&control->reasm, at, sctp_next); sctp_add_chk_to_control(control, strm, stcb, asoc, at, SCTP_READ_LOCK_NOT_HELD); @@ -1548,25 +1534,25 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, } static struct sctp_queued_to_read * -sctp_find_reasm_entry(struct sctp_stream_in *strm, uint32_t msg_id, int ordered, int old) +sctp_find_reasm_entry(struct sctp_stream_in *strm, uint32_t mid, int ordered, int idata_supported) { struct sctp_queued_to_read *control; if (ordered) { TAILQ_FOREACH(control, &strm->inqueue, next_instrm) { - if (control->msg_id == msg_id) { + if (SCTP_MID_EQ(idata_supported, control->mid, mid)) { break; } } } else { - if (old) { - control = TAILQ_FIRST(&strm->uno_inqueue); - return (control); - } - TAILQ_FOREACH(control, &strm->uno_inqueue, next_instrm) { - if (control->msg_id == msg_id) { - break; + if (idata_supported) { + TAILQ_FOREACH(control, &strm->uno_inqueue, next_instrm) { + if (SCTP_MID_EQ(idata_supported, control->mid, mid)) { + break; + } } + } else { + control = TAILQ_FIRST(&strm->uno_inqueue); } } return (control); @@ -1583,22 +1569,21 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_data_chunk *ch; struct sctp_idata_chunk *nch, chunk_buf; struct sctp_tmit_chunk *chk; - uint32_t tsn, fsn, gap, msg_id; + uint32_t tsn, fsn, gap, mid; struct mbuf *dmbuf; int the_len; int need_reasm_check = 0; - uint16_t strmno; + uint16_t sid; struct mbuf *op_err; char msg[SCTP_DIAG_INFO_LEN]; struct sctp_queued_to_read *control = NULL; - uint32_t protocol_id; + uint32_t ppid; uint8_t chunk_flags; struct sctp_stream_reset_list *liste; struct sctp_stream_in *strm; int ordered; size_t clen; int created_control = 0; - uint8_t old_data; chk = NULL; if (chtype == SCTP_IDATA) { @@ -1607,23 +1592,21 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, ch = (struct sctp_data_chunk *)nch; clen = sizeof(struct sctp_idata_chunk); tsn = ntohl(ch->dp.tsn); - msg_id = ntohl(nch->dp.msg_id); - protocol_id = nch->dp.ppid_fsn.protocol_id; + mid = ntohl(nch->dp.mid); + ppid = nch->dp.ppid_fsn.ppid; if (ch->ch.chunk_flags & SCTP_DATA_FIRST_FRAG) fsn = 0; else fsn = ntohl(nch->dp.ppid_fsn.fsn); - old_data = 0; } else { ch = (struct sctp_data_chunk *)sctp_m_getptr(*m, offset, sizeof(struct sctp_data_chunk), (uint8_t *) & chunk_buf); tsn = ntohl(ch->dp.tsn); - protocol_id = ch->dp.protocol_id; + ppid = ch->dp.ppid; clen = sizeof(struct sctp_data_chunk); fsn = tsn; - msg_id = (uint32_t) (ntohs(ch->dp.stream_sequence)); + mid = (uint32_t) (ntohs(ch->dp.ssn)); nch = NULL; - old_data = 1; } chunk_flags = ch->ch.chunk_flags; if ((size_t)chk_length == clen) { @@ -1709,9 +1692,9 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, */ /* Is the stream valid? */ - strmno = ntohs(ch->dp.stream_id); + sid = ntohs(ch->dp.sid); - if (strmno >= asoc->streamincnt) { + if (sid >= asoc->streamincnt) { struct sctp_error_invalid_stream *cause; op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_invalid_stream), @@ -1728,7 +1711,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_invalid_stream); cause->cause.code = htons(SCTP_CAUSE_INVALID_STREAM); cause->cause.length = htons(sizeof(struct sctp_error_invalid_stream)); - cause->stream_id = ch->dp.stream_id; + cause->stream_id = ch->dp.sid; cause->reserved = htons(0); sctp_queue_op_err(stcb, op_err); } @@ -1744,7 +1727,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, } return (0); } - strm = &asoc->strmin[strmno]; + strm = &asoc->strmin[sid]; /* * If its a fragmented message, lets see if we can find the control * on the reassembly queues. @@ -1758,18 +1741,18 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, * wrap around. Ignore is for now. */ snprintf(msg, sizeof(msg), "FSN zero for MID=%8.8x, but flags=%2.2x", - msg_id, chunk_flags); + mid, chunk_flags); goto err_out; } - control = sctp_find_reasm_entry(strm, msg_id, ordered, old_data); + control = sctp_find_reasm_entry(strm, mid, ordered, asoc->idata_supported); SCTPDBG(SCTP_DEBUG_XXX, "chunk_flags:0x%x look for control on queues %p\n", chunk_flags, control); if ((chunk_flags & SCTP_DATA_NOT_FRAG) != SCTP_DATA_NOT_FRAG) { /* See if we can find the re-assembly entity */ if (control != NULL) { /* We found something, does it belong? */ - if (ordered && (msg_id != control->sinfo_ssn)) { - snprintf(msg, sizeof(msg), "Reassembly problem (MID=%8.8x)", msg_id); + if (ordered && (mid != control->mid)) { + snprintf(msg, sizeof(msg), "Reassembly problem (MID=%8.8x)", mid); err_out: op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_15; @@ -1778,19 +1761,15 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, return (0); } if (ordered && ((control->sinfo_flags >> 8) & SCTP_DATA_UNORDERED)) { - /* - * We can't have a switched order with an - * unordered chunk - */ + /* We can't have a switched order with an + * unordered chunk */ snprintf(msg, sizeof(msg), "All fragments of a user message must be ordered or unordered (TSN=%8.8x)", tsn); goto err_out; } if (!ordered && (((control->sinfo_flags >> 8) & SCTP_DATA_UNORDERED) == 0)) { - /* - * We can't have a switched unordered with a - * ordered chunk - */ + /* We can't have a switched unordered with a + * ordered chunk */ snprintf(msg, sizeof(msg), "All fragments of a user message must be ordered or unordered (TSN=%8.8x)", tsn); goto err_out; @@ -1803,10 +1782,10 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, * ordered) or in the same Stream for unordered. */ if (control != NULL) { - if (ordered || (old_data == 0)) { - SCTPDBG(SCTP_DEBUG_XXX, "chunk_flags: 0x%x dup detected on msg_id: %u\n", - chunk_flags, msg_id); - snprintf(msg, sizeof(msg), "Duplicate MID=%8.8x detected.", msg_id); + if (ordered || asoc->idata_supported) { + SCTPDBG(SCTP_DEBUG_XXX, "chunk_flags: 0x%x dup detected on MID: %u\n", + chunk_flags, mid); + snprintf(msg, sizeof(msg), "Duplicate MID=%8.8x detected.", mid); goto err_out; } else { if ((tsn == control->fsn_included + 1) && @@ -1883,8 +1862,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, asoc->tsn_in_wrapped = 1; } asoc->in_tsnlog[asoc->tsn_in_at].tsn = tsn; - asoc->in_tsnlog[asoc->tsn_in_at].strm = strmno; - asoc->in_tsnlog[asoc->tsn_in_at].seq = msg_id; + asoc->in_tsnlog[asoc->tsn_in_at].strm = sid; + asoc->in_tsnlog[asoc->tsn_in_at].seq = mid; asoc->in_tsnlog[asoc->tsn_in_at].sz = chk_length; asoc->in_tsnlog[asoc->tsn_in_at].flgs = chunk_flags; asoc->in_tsnlog[asoc->tsn_in_at].stcb = (void *)stcb; @@ -1902,14 +1881,24 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, if ((chunk_flags & SCTP_DATA_FIRST_FRAG) && (TAILQ_EMPTY(&asoc->resetHead)) && (chunk_flags & SCTP_DATA_UNORDERED) == 0 && - SCTP_MSGID_GE(old_data, asoc->strmin[strmno].last_sequence_delivered, msg_id)) { + SCTP_MID_GE(asoc->idata_supported, asoc->strmin[sid].last_mid_delivered, mid)) { /* The incoming sseq is behind where we last delivered? */ SCTPDBG(SCTP_DEBUG_INDATA1, "EVIL/Broken-Dup S-SEQ: %u delivered: %u from peer, Abort!\n", - msg_id, asoc->strmin[strmno].last_sequence_delivered); + mid, asoc->strmin[sid].last_mid_delivered); - snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", - asoc->strmin[strmno].last_sequence_delivered, - tsn, strmno, msg_id); + if (asoc->idata_supported) { + snprintf(msg, sizeof(msg), "Delivered MID=%8.8x, got TSN=%8.8x, SID=%4.4x, MID=%8.8x", + asoc->strmin[sid].last_mid_delivered, + tsn, + sid, + mid); + } else { + snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", + (uint16_t) asoc->strmin[sid].last_mid_delivered, + tsn, + sid, + (uint16_t) mid); + } op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_16; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); @@ -1982,10 +1971,10 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, if (control == NULL) { sctp_alloc_a_readq(stcb, control); sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn, - protocol_id, - strmno, msg_id, + ppid, + sid, chunk_flags, - NULL, fsn, msg_id); + NULL, fsn, mid); if (control == NULL) { SCTP_STAT_INCR(sctps_nomem); return (0); @@ -1998,13 +1987,13 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, } created_control = 1; } - SCTPDBG(SCTP_DEBUG_XXX, "chunk_flags: 0x%x ordered: %d msgid: %u control: %p\n", - chunk_flags, ordered, msg_id, control); + SCTPDBG(SCTP_DEBUG_XXX, "chunk_flags: 0x%x ordered: %d MID: %u control: %p\n", + chunk_flags, ordered, mid, control); if ((chunk_flags & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG && TAILQ_EMPTY(&asoc->resetHead) && ((ordered == 0) || - ((uint16_t) (asoc->strmin[strmno].last_sequence_delivered + 1) == msg_id && - TAILQ_EMPTY(&asoc->strmin[strmno].inqueue)))) { + (SCTP_MID_EQ(asoc->idata_supported, asoc->strmin[sid].last_mid_delivered + 1, mid) && + TAILQ_EMPTY(&asoc->strmin[sid].inqueue)))) { /* Candidate for express delivery */ /* * Its not fragmented, No PD-API is up, Nothing in the @@ -2017,8 +2006,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) { asoc->highest_tsn_inside_nr_map = tsn; } - SCTPDBG(SCTP_DEBUG_XXX, "Injecting control: %p to be read (msg_id: %u)\n", - control, msg_id); + SCTPDBG(SCTP_DEBUG_XXX, "Injecting control: %p to be read (MID: %u)\n", + control, mid); sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, @@ -2026,11 +2015,11 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) { /* for ordered, bump what we delivered */ - strm->last_sequence_delivered++; + strm->last_mid_delivered++; } SCTP_STAT_INCR(sctps_recvexpress); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { - sctp_log_strm_del_alt(stcb, tsn, msg_id, strmno, + sctp_log_strm_del_alt(stcb, tsn, mid, sid, SCTP_STR_LOG_FROM_EXPRS_DEL); } control = NULL; @@ -2048,21 +2037,21 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, } return (0); } - chk->rec.data.TSN_seq = tsn; + chk->rec.data.tsn = tsn; chk->no_fr_allowed = 0; - chk->rec.data.fsn_num = fsn; - chk->rec.data.stream_seq = msg_id; - chk->rec.data.stream_number = strmno; - chk->rec.data.payloadtype = protocol_id; + chk->rec.data.fsn = fsn; + chk->rec.data.mid = mid; + chk->rec.data.sid = sid; + chk->rec.data.ppid = ppid; chk->rec.data.context = stcb->asoc.context; chk->rec.data.doing_fast_retransmit = 0; chk->rec.data.rcv_flags = chunk_flags; chk->asoc = asoc; chk->send_size = the_len; chk->whoTo = net; - SCTPDBG(SCTP_DEBUG_XXX, "Building ck: %p for control: %p to be read (msg_id: %u)\n", + SCTPDBG(SCTP_DEBUG_XXX, "Building ck: %p for control: %p to be read (MID: %u)\n", chk, - control, msg_id); + control, mid); atomic_add_int(&net->ref_count, 1); chk->data = dmbuf; } @@ -2086,7 +2075,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, * if it is not being reset.. that way we would not create a * HOLB when amongst streams being reset and those not being * reset. - * + * */ if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) && SCTP_TSN_GT(tsn, liste->tsn)) { @@ -2125,8 +2114,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, } if (chunk_flags & SCTP_DATA_UNORDERED) { /* queue directly into socket buffer */ - SCTPDBG(SCTP_DEBUG_XXX, "Unordered data to be read control: %p msg_id: %u\n", - control, msg_id); + SCTPDBG(SCTP_DEBUG_XXX, "Unordered data to be read control: %p MID: %u\n", + control, mid); sctp_mark_non_revokable(asoc, control->sinfo_tsn); sctp_add_to_readq(stcb->sctp_ep, stcb, control, @@ -2134,8 +2123,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); } else { - SCTPDBG(SCTP_DEBUG_XXX, "Queue control: %p for reordering msg_id: %u\n", control, - msg_id); + SCTPDBG(SCTP_DEBUG_XXX, "Queue control: %p for reordering MID: %u\n", control, + mid); sctp_queue_data_to_stream(stcb, strm, asoc, control, abort_flag, &need_reasm_check); if (*abort_flag) { if (last_chunk) { @@ -2149,8 +2138,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, /* If we reach here its a reassembly */ need_reasm_check = 1; SCTPDBG(SCTP_DEBUG_XXX, - "Queue data to stream for reasm control: %p msg_id: %u\n", - control, msg_id); + "Queue data to stream for reasm control: %p MID: %u\n", + control, mid); sctp_queue_data_for_reasm(stcb, asoc, strm, control, chk, created_control, abort_flag, tsn); if (*abort_flag) { /* @@ -2179,7 +2168,7 @@ finish_express_del: SCTP_STAT_INCR(sctps_recvdata); /* Set it present please */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { - sctp_log_strm_del_alt(stcb, tsn, msg_id, strmno, SCTP_STR_LOG_FROM_MARK_TSN); + sctp_log_strm_del_alt(stcb, tsn, mid, sid, SCTP_STR_LOG_FROM_MARK_TSN); } if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, @@ -2284,10 +2273,10 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb) /* * Now we also need to check the mapping array in a couple of ways. * 1) Did we move the cum-ack point? - * - * When you first glance at this you might think that all entries that - * make up the position of the cum-ack would be in the nr-mapping - * array only.. i.e. things up to the cum-ack are always + * + * When you first glance at this you might think that all entries + * that make up the position of the cum-ack would be in the + * nr-mapping array only.. i.e. things up to the cum-ack are always * deliverable. Thats true with one exception, when its a fragmented * message we may not deliver the data until some threshold (or all * of it) is in place. So we must OR the nr_mapping_array and @@ -2346,10 +2335,8 @@ sctp_slide_mapping_arrays(struct sctp_tcb *stcb) /* The complete array was completed by a single FR */ /* highest becomes the cum-ack */ int clr; - #ifdef INVARIANTS unsigned int i; - #endif /* clear the array */ @@ -2497,8 +2484,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap) (stcb->asoc.numduptsns) || /* we have dup's */ (is_a_gap) || /* is still a gap */ (stcb->asoc.delayed_ack == 0) || /* Delayed sack disabled */ - (stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) /* hit limit of pkts */ - ) { + (stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) /* hit limit of pkts */ ) { if ((stcb->asoc.sctp_cmt_on_off > 0) && (SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) && @@ -2510,9 +2496,9 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap) /* * CMT DAC algorithm: With CMT, delay acks * even in the face of - * - * reordering. Therefore, if acks that do not - * have to be sent because of the above + * + * reordering. Therefore, if acks that do + * not have to be sent because of the above * reasons, will be delayed. That is, acks * that would have been sent due to gap * reports will be delayed with DAC. Start @@ -2719,7 +2705,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, * Now, what do we do with KNOWN * chunks that are NOT in the right * place? - * + * * For now, I do nothing but ignore * them. We may later want to add * sysctl stuff to switch out and do @@ -2761,8 +2747,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, /* discard the rest of this packet */ stop_proc = 1; } /* else skip this bad chunk and - * continue... */ - break; + * continue... */ break; } /* switch of chunk type */ } *offset += SCTP_SIZE32(chk_length); @@ -2845,16 +2830,16 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (tp1->whoTo->find_pseudo_cumack == 1) && (tp1->snd_count == 1)) { - tp1->whoTo->pseudo_cumack = tp1->rec.data.TSN_seq; + tp1->whoTo->pseudo_cumack = tp1->rec.data.tsn; tp1->whoTo->find_pseudo_cumack = 0; } if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (tp1->whoTo->find_rtx_pseudo_cumack == 1) && (tp1->snd_count > 1)) { - tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq; + tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.tsn; tp1->whoTo->find_rtx_pseudo_cumack = 0; } - if (tp1->rec.data.TSN_seq == theTSN) { + if (tp1->rec.data.tsn == theTSN) { if (tp1->sent != SCTP_DATAGRAM_UNSENT) { /*- * must be held until @@ -2868,9 +2853,9 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 * via previous Gap Ack Blocks... * i.e. ACKED or RESEND. */ - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, + if (SCTP_TSN_GT(tp1->rec.data.tsn, *biggest_newly_acked_tsn)) { - *biggest_newly_acked_tsn = tp1->rec.data.TSN_seq; + *biggest_newly_acked_tsn = tp1->rec.data.tsn; } /*- * CMT: SFR algo (and HTNA) - set @@ -2882,10 +2867,10 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 if (tp1->rec.data.chunk_was_revoked == 0) tp1->whoTo->saw_newack = 1; - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, + if (SCTP_TSN_GT(tp1->rec.data.tsn, tp1->whoTo->this_sack_highest_newack)) { tp1->whoTo->this_sack_highest_newack = - tp1->rec.data.TSN_seq; + tp1->rec.data.tsn; } /*- * CMT DAC algo: also update @@ -2895,12 +2880,12 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { sctp_log_sack(*this_sack_lowest_newack, last_tsn, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, 0, 0, SCTP_LOG_TSN_ACKED); } - *this_sack_lowest_newack = tp1->rec.data.TSN_seq; + *this_sack_lowest_newack = tp1->rec.data.tsn; } /*- * CMT: CUCv2 algorithm. If (rtx-)pseudo-cumack for corresp @@ -2910,16 +2895,16 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 * Separate pseudo_cumack trackers for first transmissions and * retransmissions. */ - if (tp1->rec.data.TSN_seq == tp1->whoTo->pseudo_cumack) { + if (tp1->rec.data.tsn == tp1->whoTo->pseudo_cumack) { if (tp1->rec.data.chunk_was_revoked == 0) { tp1->whoTo->new_pseudo_cumack = 1; } tp1->whoTo->find_pseudo_cumack = 1; } if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { - sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); + sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.tsn, SCTP_CWND_LOG_FROM_SACK); } - if (tp1->rec.data.TSN_seq == tp1->whoTo->rtx_pseudo_cumack) { + if (tp1->rec.data.tsn == tp1->whoTo->rtx_pseudo_cumack) { if (tp1->rec.data.chunk_was_revoked == 0) { tp1->whoTo->new_pseudo_cumack = 1; } @@ -2928,7 +2913,7 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { sctp_log_sack(*biggest_newly_acked_tsn, last_tsn, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, frag_strt, frag_end, SCTP_LOG_TSN_ACKED); @@ -2938,7 +2923,7 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 tp1->whoTo->flight_size, tp1->book_size, (uint32_t) (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); + tp1->rec.data.tsn); } sctp_flight_size_decrease(tp1); if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) { @@ -2976,10 +2961,10 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 } } if (tp1->sent <= SCTP_DATAGRAM_RESEND) { - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, + if (SCTP_TSN_GT(tp1->rec.data.tsn, stcb->asoc.this_sack_highest_gap)) { stcb->asoc.this_sack_highest_gap = - tp1->rec.data.TSN_seq; + tp1->rec.data.tsn; } if (tp1->sent == SCTP_DATAGRAM_RESEND) { sctp_ucount_decr(stcb->asoc.sent_queue_retran_cnt); @@ -3005,24 +2990,22 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 /* NR Sack code here */ if (nr_sacking && (tp1->sent != SCTP_DATAGRAM_NR_ACKED)) { - if (stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) { - stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues--; + if (stcb->asoc.strmout[tp1->rec.data.sid].chunks_on_queues > 0) { + stcb->asoc.strmout[tp1->rec.data.sid].chunks_on_queues--; #ifdef INVARIANTS } else { - panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number); + panic("No chunks on the queues for sid %u.", tp1->rec.data.sid); #endif } - if ((stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) && - (stcb->asoc.strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && - TAILQ_EMPTY(&stcb->asoc.strmout[tp1->rec.data.stream_number].outqueue)) { + if ((stcb->asoc.strmout[tp1->rec.data.sid].chunks_on_queues == 0) && + (stcb->asoc.strmout[tp1->rec.data.sid].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&stcb->asoc.strmout[tp1->rec.data.sid].outqueue)) { stcb->asoc.trigger_reset = 1; } tp1->sent = SCTP_DATAGRAM_NR_ACKED; if (tp1->data) { - /* - * sa_ignore - * NO_NULL_CHK - */ + /* sa_ignore + * NO_NULL_CHK */ sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); sctp_m_freem(tp1->data); tp1->data = NULL; @@ -3031,8 +3014,7 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 } } break; - } /* if (tp1->TSN_seq == theTSN) */ - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, theTSN)) { + } /* if (tp1->tsn == theTSN) */ if (SCTP_TSN_GT(tp1->rec.data.tsn, theTSN)) { break; } tp1 = TAILQ_NEXT(tp1, sctp_next); @@ -3124,14 +3106,14 @@ sctp_check_for_revoked(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1; TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, cumack)) { + if (SCTP_TSN_GT(tp1->rec.data.tsn, cumack)) { /* * ok this guy is either ACK or MARKED. If it is * ACKED it has been previously acked but not this * time i.e. revoked. If it is MARKED it was ACK'ed * again. */ - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, biggest_tsn_acked)) { + if (SCTP_TSN_GT(tp1->rec.data.tsn, biggest_tsn_acked)) { break; } if (tp1->sent == SCTP_DATAGRAM_ACKED) { @@ -3147,7 +3129,7 @@ sctp_check_for_revoked(struct sctp_tcb *stcb, tp1->whoTo->flight_size, tp1->book_size, (uint32_t) (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); + tp1->rec.data.tsn); } sctp_flight_size_increase(tp1); sctp_total_flight_increase(stcb, tp1); @@ -3159,7 +3141,7 @@ sctp_check_for_revoked(struct sctp_tcb *stcb, if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { sctp_log_sack(asoc->last_acked_seq, cumack, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, 0, 0, SCTP_LOG_TSN_REVOKED); @@ -3195,7 +3177,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, if (tp1 == NULL) { sending_seq = asoc->sending_seq; } else { - sending_seq = tp1->rec.data.TSN_seq; + sending_seq = tp1->rec.data.tsn; } /* CMT DAC algo: finding out if SACK is a mixed SACK */ @@ -3218,11 +3200,11 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { if (tp1->sent < SCTP_DATAGRAM_RESEND) sctp_log_fr(biggest_tsn_newly_acked, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, tp1->sent, SCTP_FR_LOG_CHECK_STRIKE); } - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, biggest_tsn_acked) || + if (SCTP_TSN_GT(tp1->rec.data.tsn, biggest_tsn_acked) || tp1->sent == SCTP_DATAGRAM_UNSENT) { /* done */ break; @@ -3240,7 +3222,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, } } } - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, asoc->this_sack_highest_gap)) { + if (SCTP_TSN_GT(tp1->rec.data.tsn, asoc->this_sack_highest_gap)) { /* we are beyond the tsn in the sack */ break; } @@ -3264,7 +3246,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * FR using this SACK. */ continue; - } else if (tp1->whoTo && SCTP_TSN_GT(tp1->rec.data.TSN_seq, + } else if (tp1->whoTo && SCTP_TSN_GT(tp1->rec.data.tsn, tp1->whoTo->this_sack_highest_newack)) { /* * CMT: New acks were receieved for data sent to @@ -3294,7 +3276,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { sctp_log_fr(biggest_tsn_newly_acked, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, tp1->sent, SCTP_FR_LOG_STRIKE_CHUNK); } @@ -3316,10 +3298,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * received after this missing TSN. */ if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) && - SCTP_TSN_GT(this_sack_lowest_newack, tp1->rec.data.TSN_seq)) { + SCTP_TSN_GT(this_sack_lowest_newack, tp1->rec.data.tsn)) { if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { sctp_log_fr(16 + num_dests_sacked, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, tp1->sent, SCTP_FR_LOG_STRIKE_CHUNK); } @@ -3357,7 +3339,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { sctp_log_fr(biggest_tsn_newly_acked, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, tp1->sent, SCTP_FR_LOG_STRIKE_CHUNK); } @@ -3389,10 +3371,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) && SCTP_TSN_GT(this_sack_lowest_newack, - tp1->rec.data.TSN_seq)) { + tp1->rec.data.tsn)) { if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { sctp_log_fr(32 + num_dests_sacked, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, tp1->sent, SCTP_FR_LOG_STRIKE_CHUNK); } @@ -3407,7 +3389,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * JRI: TODO: remove code for HTNA algo. CMT's SFR * algo covers HTNA. */ - } else if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, + } else if (SCTP_TSN_GT(tp1->rec.data.tsn, biggest_tsn_newly_acked)) { /* * We don't strike these: This is the HTNA @@ -3419,7 +3401,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, /* Strike the TSN */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { sctp_log_fr(biggest_tsn_newly_acked, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, tp1->sent, SCTP_FR_LOG_STRIKE_CHUNK); } @@ -3441,10 +3423,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * received after this missing TSN. */ if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) && - SCTP_TSN_GT(this_sack_lowest_newack, tp1->rec.data.TSN_seq)) { + SCTP_TSN_GT(this_sack_lowest_newack, tp1->rec.data.tsn)) { if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { sctp_log_fr(48 + num_dests_sacked, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, tp1->sent, SCTP_FR_LOG_STRIKE_CHUNK); } @@ -3461,7 +3443,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, (tp1->whoTo ? (tp1->whoTo->flight_size) : 0), tp1->book_size, (uint32_t) (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); + tp1->rec.data.tsn); } if (tp1->whoTo) { tp1->whoTo->net_ack++; @@ -3483,10 +3465,8 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, if ((stcb->asoc.prsctp_supported) && (PR_SCTP_RTX_ENABLED(tp1->flags))) { - /* - * Has it been retransmitted tv_sec times? - - * we store the retran count there. - */ + /* Has it been retransmitted tv_sec times? - + * we store the retran count there. */ if (tp1->snd_count > tp1->rec.data.timetodrop.tv_sec) { /* Yes, so drop it */ if (tp1->data != NULL) { @@ -3498,12 +3478,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, continue; } } - /* - * SCTP_PRINTF("OK, we are now ready to FR this - * guy\n"); - */ + /* SCTP_PRINTF("OK, we are now ready to FR this + * guy\n"); */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { - sctp_log_fr(tp1->rec.data.TSN_seq, tp1->snd_count, + sctp_log_fr(tp1->rec.data.tsn, tp1->snd_count, 0, SCTP_FR_MARKED); } if (strike_flag) { @@ -3521,18 +3499,14 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, alt = tp1->whoTo; /* sa_ignore NO_NULL_CHK */ if (asoc->sctp_cmt_pf > 0) { - /* - * JRS 5/18/07 - If CMT PF is on, + /* JRS 5/18/07 - If CMT PF is on, * use the PF version of - * find_alt_net() - */ + * find_alt_net() */ alt = sctp_find_alternate_net(stcb, alt, 2); } else { - /* - * JRS 5/18/07 - If only CMT is on, + /* JRS 5/18/07 - If only CMT is on, * use the CMT version of - * find_alt_net() - */ + * find_alt_net() */ /* sa_ignore NO_NULL_CHK */ alt = sctp_find_alternate_net(stcb, alt, 1); } @@ -3570,7 +3544,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, /* mark the sending seq for possible subsequent FR's */ /* * SCTP_PRINTF("Marking TSN for FR new value %x\n", - * (uint32_t)tpi->rec.data.TSN_seq); + * (uint32_t)tpi->rec.data.tsn); */ if (TAILQ_EMPTY(&asoc->send_queue)) { /* @@ -3593,7 +3567,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, ttt = TAILQ_FIRST(&asoc->send_queue); tp1->rec.data.fast_retran_tsn = - ttt->rec.data.TSN_seq; + ttt->rec.data.tsn; } if (tp1->do_rtt) { @@ -3641,7 +3615,7 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb, (tp1->sent == SCTP_DATAGRAM_NR_ACKED)) { sctp_misc_ints(SCTP_FWD_TSN_CHECK, asoc->advanced_peer_ack_point, - tp1->rec.data.TSN_seq, 0, 0); + tp1->rec.data.tsn, 0, 0); } } if (!PR_SCTP_ENABLED(tp1->flags)) { @@ -3689,10 +3663,10 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb, if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) || (tp1->sent == SCTP_DATAGRAM_NR_ACKED)) { /* advance PeerAckPoint goes forward */ - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, asoc->advanced_peer_ack_point)) { - asoc->advanced_peer_ack_point = tp1->rec.data.TSN_seq; + if (SCTP_TSN_GT(tp1->rec.data.tsn, asoc->advanced_peer_ack_point)) { + asoc->advanced_peer_ack_point = tp1->rec.data.tsn; a_adv = tp1; - } else if (tp1->rec.data.TSN_seq == asoc->advanced_peer_ack_point) { + } else if (tp1->rec.data.tsn == asoc->advanced_peer_ack_point) { /* No update but we do save the chk */ a_adv = tp1; } @@ -3713,10 +3687,8 @@ sctp_fs_audit(struct sctp_association *asoc) struct sctp_tmit_chunk *chk; int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0; int ret; - #ifndef INVARIANTS int entry_flight, entry_cnt; - #endif ret = 0; @@ -3730,7 +3702,7 @@ sctp_fs_audit(struct sctp_association *asoc) TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { if (chk->sent < SCTP_DATAGRAM_RESEND) { SCTP_PRINTF("Chk TSN: %u size: %d inflight cnt: %d\n", - chk->rec.data.TSN_seq, + chk->rec.data.tsn, chk->send_size, chk->snd_count); inflight++; @@ -3773,7 +3745,7 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb, tp1->whoTo ? tp1->whoTo->flight_size : 0, tp1->book_size, (uint32_t) (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); + tp1->rec.data.tsn); return; } /* First setup this by shrinking flight */ @@ -3792,7 +3764,7 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb, tp1->whoTo->flight_size, tp1->book_size, (uint32_t) (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); + tp1->rec.data.tsn); } } @@ -3863,7 +3835,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, if (!TAILQ_EMPTY(&asoc->sent_queue)) { tp1 = TAILQ_LAST(&asoc->sent_queue, sctpchunk_listhead); - send_s = tp1->rec.data.TSN_seq + 1; + send_s = tp1->rec.data.tsn + 1; } else { send_s = asoc->sending_seq; } @@ -3892,7 +3864,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, if (SCTP_TSN_GT(cumack, asoc->last_acked_seq)) { /* process the new consecutive TSN first */ TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) { - if (SCTP_TSN_GE(cumack, tp1->rec.data.TSN_seq)) { + if (SCTP_TSN_GE(cumack, tp1->rec.data.tsn)) { if (tp1->sent == SCTP_DATAGRAM_UNSENT) { SCTP_PRINTF("Warning, an unsent is now acked?\n"); } @@ -3908,7 +3880,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, tp1->whoTo->flight_size, tp1->book_size, (uint32_t) (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); + tp1->rec.data.tsn); } sctp_flight_size_decrease(tp1); if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) { @@ -3933,8 +3905,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, tp1->whoTo->RTO = /* * sa_ignore - * NO_NULL_CH - * K + * NO_NULL_CHK */ sctp_calculate_rto(stcb, asoc, tp1->whoTo, @@ -3967,7 +3938,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { /* sa_ignore NO_NULL_CHK */ - sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); + sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.tsn, SCTP_CWND_LOG_FROM_SACK); } } if (tp1->sent == SCTP_DATAGRAM_RESEND) { @@ -3979,17 +3950,17 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, tp1->rec.data.chunk_was_revoked = 0; } if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) { - if (asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) { - asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--; + if (asoc->strmout[tp1->rec.data.sid].chunks_on_queues > 0) { + asoc->strmout[tp1->rec.data.sid].chunks_on_queues--; #ifdef INVARIANTS } else { - panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number); + panic("No chunks on the queues for sid %u.", tp1->rec.data.sid); #endif } } - if ((asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) && - (asoc->strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && - TAILQ_EMPTY(&asoc->strmout[tp1->rec.data.stream_number].outqueue)) { + if ((asoc->strmout[tp1->rec.data.sid].chunks_on_queues == 0) && + (asoc->strmout[tp1->rec.data.sid].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&asoc->strmout[tp1->rec.data.sid].outqueue)) { asoc->trigger_reset = 1; } TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); @@ -4002,7 +3973,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { sctp_log_sack(asoc->last_acked_seq, cumack, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, 0, 0, SCTP_LOG_FREE_SENT); @@ -4066,10 +4037,8 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, } if (net == stcb->asoc.primary_destination) { if (stcb->asoc.alternate) { - /* - * release the alternate, - * primary is good - */ + /* release the alternate, + * primary is good */ sctp_free_remote_addr(stcb->asoc.alternate); stcb->asoc.alternate = NULL; } @@ -4152,10 +4121,8 @@ again: } } else { if (net->window_probe) { - /* - * In window probes we must assure a timer - * is still running there - */ + /* In window probes we must assure a timer + * is still running there */ net->window_probe = 0; if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks, @@ -4406,7 +4373,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, if (!TAILQ_EMPTY(&asoc->sent_queue)) { tp1 = TAILQ_LAST(&asoc->sent_queue, sctpchunk_listhead); - send_s = tp1->rec.data.TSN_seq + 1; + send_s = tp1->rec.data.tsn + 1; } else { tp1 = NULL; send_s = asoc->sending_seq; @@ -4423,7 +4390,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, cum_ack, send_s); if (tp1) { SCTP_PRINTF("Got send_s from tsn:%x + 1 of tp1: %p\n", - tp1->rec.data.TSN_seq, (void *)tp1); + tp1->rec.data.tsn, (void *)tp1); } hopeless_peer: *abort_now = 1; @@ -4498,7 +4465,7 @@ hopeless_peer: } /* process the new consecutive TSN first */ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { - if (SCTP_TSN_GE(last_tsn, tp1->rec.data.TSN_seq)) { + if (SCTP_TSN_GE(last_tsn, tp1->rec.data.tsn)) { if (tp1->sent != SCTP_DATAGRAM_UNSENT) { accum_moved = 1; if (tp1->sent < SCTP_DATAGRAM_ACKED) { @@ -4527,7 +4494,7 @@ hopeless_peer: tp1->whoTo->flight_size, tp1->book_size, (uint32_t) (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); + tp1->rec.data.tsn); } sctp_flight_size_decrease(tp1); sctp_total_flight_decrease(stcb, tp1); @@ -4539,7 +4506,7 @@ hopeless_peer: tp1->whoTo->net_ack += tp1->send_size; /* CMT SFR and DAC algos */ - this_sack_lowest_newack = tp1->rec.data.TSN_seq; + this_sack_lowest_newack = tp1->rec.data.tsn; tp1->whoTo->saw_newack = 1; if (tp1->snd_count < 2) { @@ -4587,13 +4554,13 @@ hopeless_peer: if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { sctp_log_sack(asoc->last_acked_seq, cum_ack, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, 0, 0, SCTP_LOG_TSN_ACKED); } if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { - sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); + sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.tsn, SCTP_CWND_LOG_FROM_SACK); } } if (tp1->sent == SCTP_DATAGRAM_RESEND) { @@ -4682,21 +4649,21 @@ hopeless_peer: asoc->last_acked_seq = cum_ack; TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) { - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, cum_ack)) { + if (SCTP_TSN_GT(tp1->rec.data.tsn, cum_ack)) { break; } if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) { - if (asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) { - asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--; + if (asoc->strmout[tp1->rec.data.sid].chunks_on_queues > 0) { + asoc->strmout[tp1->rec.data.sid].chunks_on_queues--; #ifdef INVARIANTS } else { - panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number); + panic("No chunks on the queues for sid %u.", tp1->rec.data.sid); #endif } } - if ((asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) && - (asoc->strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && - TAILQ_EMPTY(&asoc->strmout[tp1->rec.data.stream_number].outqueue)) { + if ((asoc->strmout[tp1->rec.data.sid].chunks_on_queues == 0) && + (asoc->strmout[tp1->rec.data.sid].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&asoc->strmout[tp1->rec.data.sid].outqueue)) { asoc->trigger_reset = 1; } TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); @@ -4717,7 +4684,7 @@ hopeless_peer: if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) { sctp_log_sack(asoc->last_acked_seq, cum_ack, - tp1->rec.data.TSN_seq, + tp1->rec.data.tsn, 0, 0, SCTP_LOG_FREE_SENT); @@ -4775,7 +4742,7 @@ hopeless_peer: } /* * Check for revoked fragments: - * + * * if Previous sack - Had no frags then we can't have any revoked if * Previous sack - Had frag's then - If we now have frags aka * num_seg > 0 call sctp_check_for_revoked() to tell if peer revoked @@ -4798,7 +4765,7 @@ hopeless_peer: tp1->whoTo->flight_size, tp1->book_size, (uint32_t) (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); + tp1->rec.data.tsn); } sctp_flight_size_increase(tp1); sctp_total_flight_increase(stcb, tp1); @@ -4840,10 +4807,8 @@ hopeless_peer: } if (net == stcb->asoc.primary_destination) { if (stcb->asoc.alternate) { - /* - * release the alternate, - * primary is good - */ + /* release the alternate, + * primary is good */ sctp_free_remote_addr(stcb->asoc.alternate); stcb->asoc.alternate = NULL; } @@ -5054,10 +5019,8 @@ again: } } else { if (net->window_probe) { - /* - * In window probes we must assure a timer - * is still running there - */ + /* In window probes we must assure a timer + * is still running there */ if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); @@ -5167,22 +5130,17 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, { struct sctp_queued_to_read *ctl, *nctl; struct sctp_association *asoc; - uint32_t tt; - int need_reasm_check = 0, old; + uint32_t mid; + int need_reasm_check = 0; asoc = &stcb->asoc; - tt = strmin->last_sequence_delivered; - if (asoc->idata_supported) { - old = 0; - } else { - old = 1; - } + mid = strmin->last_mid_delivered; /* * First deliver anything prior to and including the stream no that * came in. */ TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next_instrm, nctl) { - if (SCTP_MSGID_GE(old, tt, ctl->sinfo_ssn)) { + if (SCTP_MID_GE(asoc->idata_supported, mid, ctl->mid)) { /* this is deliverable now */ if (((ctl->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG) { if (ctl->on_strm_q) { @@ -5213,11 +5171,9 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, } else { /* Its a fragmented message */ if (ctl->first_frag_seen) { - /* - * Make it so this is next to - * deliver, we restore later - */ - strmin->last_sequence_delivered = ctl->sinfo_ssn - 1; + /* Make it so this is next to + * deliver, we restore later */ + strmin->last_mid_delivered = ctl->mid - 1; need_reasm_check = 1; break; } @@ -5231,9 +5187,9 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, int ret; ret = sctp_deliver_reasm_check(stcb, &stcb->asoc, strmin, SCTP_READ_LOCK_HELD); - if (SCTP_MSGID_GT(old, tt, strmin->last_sequence_delivered)) { + if (SCTP_MID_GT(asoc->idata_supported, mid, strmin->last_mid_delivered)) { /* Restore the next to deliver unless we are ahead */ - strmin->last_sequence_delivered = tt; + strmin->last_mid_delivered = mid; } if (ret == 0) { /* Left the front Partial one on */ @@ -5245,9 +5201,9 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, * now we must deliver things in queue the normal way if any are * now ready. */ - tt = strmin->last_sequence_delivered + 1; + mid = strmin->last_mid_delivered + 1; TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next_instrm, nctl) { - if (tt == ctl->sinfo_ssn) { + if (SCTP_MID_EQ(asoc->idata_supported, mid, ctl->mid)) { if (((ctl->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG) { /* this is deliverable now */ if (ctl->on_strm_q) { @@ -5267,7 +5223,7 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, asoc->size_on_all_streams -= ctl->length; sctp_ucount_decr(asoc->cnt_on_all_streams); /* deliver it to at least the delivery-q */ - strmin->last_sequence_delivered = ctl->sinfo_ssn; + strmin->last_mid_delivered = ctl->mid; if (stcb->sctp_socket) { sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); sctp_add_to_readq(stcb->sctp_ep, stcb, @@ -5276,15 +5232,13 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); } - tt = strmin->last_sequence_delivered + 1; + mid = strmin->last_mid_delivered + 1; } else { /* Its a fragmented message */ if (ctl->first_frag_seen) { - /* - * Make it so this is next to - * deliver - */ - strmin->last_sequence_delivered = ctl->sinfo_ssn - 1; + /* Make it so this is next to + * deliver */ + strmin->last_mid_delivered = ctl->mid - 1; need_reasm_check = 1; break; } @@ -5303,7 +5257,7 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, static void sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb, struct sctp_association *asoc, - uint16_t stream, uint32_t seq, int ordered, int old, uint32_t cumtsn) + uint16_t stream, uint32_t mid, int ordered, uint32_t cumtsn) { struct sctp_queued_to_read *control; struct sctp_stream_in *strm; @@ -5319,15 +5273,18 @@ sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb, * queue. */ strm = &asoc->strmin[stream]; - control = sctp_find_reasm_entry(strm, (uint32_t) seq, ordered, old); + control = sctp_find_reasm_entry(strm, mid, ordered, asoc->idata_supported); if (control == NULL) { /* Not found */ return; } + if (!asoc->idata_supported && !ordered && SCTP_TSN_GT(control->fsn_included, cumtsn)) { + return; + } TAILQ_FOREACH_SAFE(chk, &control->reasm, sctp_next, nchk) { /* Purge hanging chunks */ - if (old && (ordered == 0)) { - if (SCTP_TSN_GT(chk->rec.data.TSN_seq, cumtsn)) { + if (!asoc->idata_supported && (ordered == 0)) { + if (SCTP_TSN_GT(chk->rec.data.tsn, cumtsn)) { break; } } @@ -5389,11 +5346,11 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, /* * here we will perform all the data receiver side steps for * processing FwdTSN, as required in by pr-sctp draft: - * + * * Assume we get FwdTSN(x): - * - * 1) update local cumTSN to x 2) try to further advance cumTSN to x + - * others we have 3) examine and update re-ordering queue on + * + * 1) update local cumTSN to x 2) try to further advance cumTSN to x + * + others we have 3) examine and update re-ordering queue on * pr-in-streams 4) clean up re-assembly queue 5) Send a sack to * report where we are. */ @@ -5479,7 +5436,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, /* Flush all the un-ordered data based on cum-tsn */ SCTP_INP_READ_LOCK(stcb->sctp_ep); for (sid = 0; sid < asoc->streamincnt; sid++) { - sctp_flush_reassm_for_str_seq(stcb, asoc, sid, 0, 0, 1, new_cum_tsn); + sctp_flush_reassm_for_str_seq(stcb, asoc, sid, 0, 0, new_cum_tsn); } SCTP_INP_READ_UNLOCK(stcb->sctp_ep); } @@ -5491,10 +5448,9 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, if (m && fwd_sz) { /* New method. */ unsigned int num_str; - uint32_t sequence; - uint16_t stream; + uint32_t mid, cur_mid; + uint16_t sid; uint16_t ordered, flags; - int old; struct sctp_strseq *stseq, strseqbuf; struct sctp_strseq_mid *stseq_m, strseqbuf_m; @@ -5503,10 +5459,8 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, SCTP_INP_READ_LOCK(stcb->sctp_ep); if (asoc->idata_supported) { num_str = fwd_sz / sizeof(struct sctp_strseq_mid); - old = 0; } else { num_str = fwd_sz / sizeof(struct sctp_strseq); - old = 1; } for (i = 0; i < num_str; i++) { if (asoc->idata_supported) { @@ -5517,8 +5471,8 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, if (stseq_m == NULL) { break; } - stream = ntohs(stseq_m->stream); - sequence = ntohl(stseq_m->msg_id); + sid = ntohs(stseq_m->sid); + mid = ntohl(stseq_m->mid); flags = ntohs(stseq_m->flags); if (flags & PR_SCTP_UNORDERED_FLAG) { ordered = 0; @@ -5533,8 +5487,8 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, if (stseq == NULL) { break; } - stream = ntohs(stseq->stream); - sequence = (uint32_t) ntohs(stseq->sequence); + sid = ntohs(stseq->sid); + mid = (uint32_t) ntohs(stseq->ssn); ordered = 1; } /* Convert */ @@ -5546,12 +5500,12 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, * queue where its not all delivered. If we find it * we transmute the read entry into a PDI_ABORTED. */ - if (stream >= asoc->streamincnt) { + if (sid >= asoc->streamincnt) { /* screwed up streams, stop! */ break; } - if ((asoc->str_of_pdapi == stream) && - (asoc->ssn_of_pdapi == sequence)) { + if ((asoc->str_of_pdapi == sid) && + (asoc->ssn_of_pdapi == mid)) { /* * If this is the one we were partially * delivering now then we no longer are. @@ -5560,24 +5514,14 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, */ asoc->fragmented_delivery_inprogress = 0; } - strm = &asoc->strmin[stream]; - if (asoc->idata_supported == 0) { - uint16_t strm_at; - - for (strm_at = strm->last_sequence_delivered; SCTP_MSGID_GE(1, sequence, strm_at); strm_at++) { - sctp_flush_reassm_for_str_seq(stcb, asoc, stream, strm_at, ordered, old, new_cum_tsn); - } - } else { - uint32_t strm_at; - - for (strm_at = strm->last_sequence_delivered; SCTP_MSGID_GE(0, sequence, strm_at); strm_at++) { - sctp_flush_reassm_for_str_seq(stcb, asoc, stream, strm_at, ordered, old, new_cum_tsn); - } + strm = &asoc->strmin[sid]; + for (cur_mid = strm->last_mid_delivered; SCTP_MID_GE(asoc->idata_supported, mid, cur_mid); cur_mid++) { + sctp_flush_reassm_for_str_seq(stcb, asoc, sid, cur_mid, ordered, new_cum_tsn); } TAILQ_FOREACH(ctl, &stcb->sctp_ep->read_queue, next) { - if ((ctl->sinfo_stream == stream) && - (ctl->sinfo_ssn == sequence)) { - str_seq = (stream << 16) | (0x0000ffff & sequence); + if ((ctl->sinfo_stream == sid) && + (SCTP_MID_EQ(asoc->idata_supported, ctl->mid, mid))) { + str_seq = (sid << 16) | (0x0000ffff & mid); ctl->pdapi_aborted = 1; sv = stcb->asoc.control_pdapi; ctl->end_added = 1; @@ -5600,15 +5544,15 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, SCTP_SO_NOT_LOCKED); stcb->asoc.control_pdapi = sv; break; - } else if ((ctl->sinfo_stream == stream) && - SCTP_MSGID_GT(old, ctl->sinfo_ssn, sequence)) { + } else if ((ctl->sinfo_stream == sid) && + SCTP_MID_GT(asoc->idata_supported, ctl->mid, mid)) { /* We are past our victim SSN */ break; } } - if (SCTP_MSGID_GT(old, sequence, strm->last_sequence_delivered)) { + if (SCTP_MID_GT(asoc->idata_supported, mid, strm->last_mid_delivered)) { /* Update the sequence number */ - strm->last_sequence_delivered = sequence; + strm->last_mid_delivered = mid; } /* now kick the stream the new way */ /* sa_ignore NO_NULL_CHK */ diff --git a/freebsd/sys/netinet/sctp_indata.h b/freebsd/sys/netinet/sctp_indata.h index 162ca905..e277ae88 100644 --- a/freebsd/sys/netinet/sctp_indata.h +++ b/freebsd/sys/netinet/sctp_indata.h @@ -42,20 +42,19 @@ struct sctp_queued_to_read * sctp_build_readq_entry(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t tsn, uint32_t ppid, - uint32_t context, uint16_t stream_no, - uint32_t stream_seq, uint8_t flags, + uint32_t context, uint16_t sid, + uint32_t mid, uint8_t flags, struct mbuf *dm); -#define sctp_build_readq_entry_mac(_ctl, in_it, context, net, tsn, ppid, stream_no, stream_seq, flags, dm, tfsn, msgid) do { \ +#define sctp_build_readq_entry_mac(_ctl, in_it, context, net, tsn, ppid, sid, flags, dm, tfsn, mid) do { \ if (_ctl) { \ atomic_add_int(&((net)->ref_count), 1); \ memset(_ctl, 0, sizeof(struct sctp_queued_to_read)); \ - (_ctl)->sinfo_stream = stream_no; \ - (_ctl)->sinfo_ssn = stream_seq; \ + (_ctl)->sinfo_stream = sid; \ TAILQ_INIT(&_ctl->reasm); \ (_ctl)->top_fsn = tfsn; \ - (_ctl)->msg_id = msgid; \ + (_ctl)->mid = mid; \ (_ctl)->sinfo_flags = (flags << 8); \ (_ctl)->sinfo_ppid = ppid; \ (_ctl)->sinfo_context = context; \ diff --git a/freebsd/sys/netinet/sctp_input.c b/freebsd/sys/netinet/sctp_input.c index 621784ea..3c596c48 100644 --- a/freebsd/sys/netinet/sctp_input.c +++ b/freebsd/sys/netinet/sctp_input.c @@ -163,10 +163,8 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, *abort_no_unlock = 1; goto outnow; } - /* - * We are only accepting if we have a socket with positive - * so_qlimit. - */ + /* We are only accepting if we have a socket with positive + * so_qlimit. */ if ((stcb == NULL) && ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || @@ -322,14 +320,14 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) /* abandon the upper streams */ newcnt = ntohs(init->num_inbound_streams); TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { - if (chk->rec.data.stream_number >= newcnt) { + if (chk->rec.data.sid >= newcnt) { TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); asoc->send_queue_cnt--; - if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { - asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; + if (asoc->strmout[chk->rec.data.sid].chunks_on_queues > 0) { + asoc->strmout[chk->rec.data.sid].chunks_on_queues--; #ifdef INVARIANTS } else { - panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); + panic("No chunks on the queues for sid %u.", chk->rec.data.sid); #endif } if (chk->data != NULL) { @@ -414,8 +412,8 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) return (-1); } for (i = 0; i < asoc->streamincnt; i++) { - asoc->strmin[i].stream_no = i; - asoc->strmin[i].last_sequence_delivered = 0xffffffff; + asoc->strmin[i].sid = i; + asoc->strmin[i].last_mid_delivered = 0xffffffff; TAILQ_INIT(&asoc->strmin[i].inqueue); TAILQ_INIT(&asoc->strmin[i].uno_inqueue); asoc->strmin[i].pd_api_started = 0; @@ -711,10 +709,8 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb) LIST_REMOVE(stcb, sctp_asocs); stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; - /* - * put it in the bucket in the vtag hash of assoc's for the - * system - */ + /* put it in the bucket in the vtag hash of assoc's for the + * system */ LIST_INSERT_HEAD(head, stcb, sctp_asocs); sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); return (1); @@ -732,10 +728,8 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb) sctp_toss_old_cookies(stcb, &stcb->asoc); stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; - /* - * put it in the bucket in the vtag hash of assoc's for the - * system - */ + /* put it in the bucket in the vtag hash of assoc's for the + * system */ LIST_INSERT_HEAD(head, stcb, sctp_asocs); sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); return (1); @@ -766,7 +760,6 @@ sctp_handle_abort(struct sctp_abort_chunk *abort, { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif uint16_t len; uint16_t error; @@ -868,10 +861,8 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, struct sctp_association *asoc; int some_on_streamwheel; int old_state; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif SCTPDBG(SCTP_DEBUG_INPUT2, @@ -948,10 +939,8 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); - /* - * notify upper layer that peer has initiated a - * shutdown - */ + /* notify upper layer that peer has initiated a + * shutdown */ sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); /* reset time */ @@ -1001,7 +990,6 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, struct sctp_nets *net) { struct sctp_association *asoc; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; @@ -1171,10 +1159,8 @@ sctp_handle_error(struct sctp_chunkhdr *ch, uint16_t error_len; struct sctp_association *asoc; int adjust; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif /* parse through all of the errors and process */ @@ -1494,10 +1480,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, int retval; int spec_flag = 0; uint32_t how_indx; - #if defined(SCTP_DETAILED_STR_STATS) int j; - #endif net = *netp; @@ -1621,7 +1605,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, ) { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif /* * Here is where collision would go if we @@ -1822,7 +1805,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, (inp->sctp_socket->so_qlimit == 0)) { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; @@ -1882,10 +1864,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce && cookie->tie_tag_peer_vtag != 0) { struct sctpasochead *head; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif if (asoc->peer_supports_nat) { @@ -1977,7 +1957,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, asoc->strmout[i].abandoned_sent[0] = 0; asoc->strmout[i].abandoned_unsent[0] = 0; #endif - stcb->asoc.strmout[i].stream_no = i; + stcb->asoc.strmout[i].sid = i; stcb->asoc.strmout[i].next_mid_ordered = 0; stcb->asoc.strmout[i].next_mid_unordered = 0; stcb->asoc.strmout[i].last_msg_incomplete = 0; @@ -2069,7 +2049,6 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, int retval; int error = 0; uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE]; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; @@ -2444,14 +2423,11 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, struct sctp_nets *netl; int had_a_existing_tcb = 0; int send_int_conf = 0; - #ifdef INET struct sockaddr_in sin; - #endif #ifdef INET6 struct sockaddr_in6 sin6; - #endif SCTPDBG(SCTP_DEBUG_INPUT2, @@ -2773,10 +2749,8 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, if (so == NULL) { struct mbuf *op_err; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *pcb_so; - #endif /* Too many sockets */ SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n"); @@ -2889,10 +2863,8 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); } - /* - * Pull it from the incomplete queue and wake the - * guy - */ + /* Pull it from the incomplete queue and wake the + * guy */ #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) atomic_add_int(&(*stcb)->asoc.refcnt, 1); SCTP_TCB_UNLOCK((*stcb)); @@ -3057,18 +3029,18 @@ sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp, if (lchk == NULL) { window_data_tsn = stcb->asoc.sending_seq - 1; } else { - window_data_tsn = lchk->rec.data.TSN_seq; + window_data_tsn = lchk->rec.data.tsn; } /* Find where it was sent to if possible. */ net = NULL; TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) { - if (lchk->rec.data.TSN_seq == tsn) { + if (lchk->rec.data.tsn == tsn) { net = lchk->whoTo; net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send; break; } - if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) { + if (SCTP_TSN_GT(lchk->rec.data.tsn, tsn)) { break; } } @@ -3104,10 +3076,8 @@ sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp, } if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) && ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) { - /* - * JRS - Use the congestion control given in the pluggable - * CC module - */ + /* JRS - Use the congestion control given in the pluggable + * CC module */ stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt); /* * We reduce once every RTT. So we will only lower cwnd at @@ -3195,10 +3165,8 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSE struct sctp_tcb *stcb, struct sctp_nets *net) { struct sctp_association *asoc; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif SCTPDBG(SCTP_DEBUG_INPUT2, @@ -3262,11 +3230,11 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, tsn = ntohl(desc->tsn_ifany); TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { - if (tp1->rec.data.TSN_seq == tsn) { + if (tp1->rec.data.tsn == tsn) { /* found it */ break; } - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, tsn)) { + if (SCTP_TSN_GT(tp1->rec.data.tsn, tsn)) { /* not found */ tp1 = NULL; break; @@ -3279,7 +3247,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, */ SCTP_STAT_INCR(sctps_pdrpdnfnd); TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { - if (tp1->rec.data.TSN_seq == tsn) { + if (tp1->rec.data.tsn == tsn) { /* found it */ break; } @@ -3345,7 +3313,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; } else { - tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq; + tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.tsn; } /* restart the timer */ @@ -3361,7 +3329,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, tp1->whoTo->flight_size, tp1->book_size, (uint32_t) (uintptr_t) stcb, - tp1->rec.data.TSN_seq); + tp1->rec.data.tsn); } if (tp1->sent < SCTP_DATAGRAM_RESEND) { sctp_flight_size_decrease(tp1); @@ -3432,10 +3400,8 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, case SCTP_HEARTBEAT_REQUEST: /* resend a demand HB */ if ((stcb->asoc.overall_error_count + 3) < stcb->asoc.max_send_times) { - /* - * Only retransmit if we KNOW we wont destroy the - * tcb - */ + /* Only retransmit if we KNOW we wont destroy the + * tcb */ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); } break; @@ -3507,12 +3473,12 @@ sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * if (temp >= stcb->asoc.streamincnt) { continue; } - stcb->asoc.strmin[temp].last_sequence_delivered = 0xffffffff; + stcb->asoc.strmin[temp].last_mid_delivered = 0xffffffff; } } else { list = NULL; for (i = 0; i < stcb->asoc.streamincnt; i++) { - stcb->asoc.strmin[i].last_sequence_delivered = 0xffffffff; + stcb->asoc.strmin[i].last_mid_delivered = 0xffffffff; } } sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); @@ -3676,10 +3642,8 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED); } else if (action == SCTP_STREAM_RESET_RESULT_IN_PROGRESS) { - /* - * Set it up so we don't stop - * retransmitting - */ + /* Set it up so we don't stop + * retransmitting */ asoc->stream_reset_outstanding++; stcb->asoc.str_reset_seq_out--; asoc->stream_reset_out_is_outstanding = 1; @@ -4056,8 +4020,8 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch for (i = 0; i < stcb->asoc.streamincnt; i++) { TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); TAILQ_INIT(&stcb->asoc.strmin[i].uno_inqueue); - stcb->asoc.strmin[i].stream_no = i; - stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered; + stcb->asoc.strmin[i].sid = i; + stcb->asoc.strmin[i].last_mid_delivered = oldstrm[i].last_mid_delivered; stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started; stcb->asoc.strmin[i].pd_api_started = oldstrm[i].pd_api_started; /* now anything on those queues? */ @@ -4074,8 +4038,8 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch for (i = stcb->asoc.streamincnt; i < num_stream; i++) { TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); TAILQ_INIT(&stcb->asoc.strmin[i].uno_inqueue); - stcb->asoc.strmin[i].stream_no = i; - stcb->asoc.strmin[i].last_sequence_delivered = 0xffffffff; + stcb->asoc.strmin[i].sid = i; + stcb->asoc.strmin[i].last_mid_delivered = 0xffffffff; stcb->asoc.strmin[i].pd_api_started = 0; stcb->asoc.strmin[i].delivery_started = 0; } @@ -4532,10 +4496,8 @@ __attribute__((noinline)) uint32_t auth_offset = 0, auth_len = 0; int auth_skipped = 0; int asconf_cnt = 0; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n", @@ -4735,10 +4697,8 @@ __attribute__((noinline)) return (NULL); } } - } /* end if !SCTP_COOKIE_ECHO */ - /* - * process all control chunks... - */ + } /* end if !SCTP_COOKIE_ECHO *//* process all + * control chunks... */ if (((ch->chunk_type == SCTP_SELECTIVE_ACK) || (ch->chunk_type == SCTP_NR_SELECTIVE_ACK) || (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) && @@ -5032,10 +4992,8 @@ process_control_chunks: } } break; - /* - * EY - nr_sack: If the received chunk is an - * nr_sack chunk - */ + /* EY - nr_sack: If the received chunk is an + * nr_sack chunk */ case SCTP_NR_SELECTIVE_ACK: { struct sctp_nr_sack_chunk *nr_sack; @@ -5517,6 +5475,11 @@ process_control_chunks: *offset = length; return (NULL); } + /* + * For sending a SACK this looks like DATA + * chunks. + */ + stcb->asoc.last_data_chunk_from = stcb->asoc.last_control_chunk_from; sctp_handle_forward_tsn(stcb, (struct sctp_forward_tsn_chunk *)ch, &abort_flag, m, *offset); if (abort_flag) { @@ -5648,8 +5611,7 @@ process_control_chunks: /* discard this packet */ *offset = length; return (stcb); - } /* else skip this bad chunk and continue... */ - break; + } /* else skip this bad chunk and continue... */ break; } /* switch (ch->chunk_type) */ @@ -6106,10 +6068,8 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) struct sctphdr *sh; struct sctp_chunkhdr *ch; int length, offset; - #if !defined(SCTP_WITH_NO_CSUM) uint8_t compute_crc; - #endif uint32_t mflowid; uint8_t mflowtype; @@ -6210,7 +6170,6 @@ out: #if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) extern int *sctp_cpuarry; - #endif int @@ -6258,5 +6217,4 @@ sctp_input(struct mbuf **mp, int *offp, int proto SCTP_UNUSED) sctp_input_with_port(m, off, 0); return (IPPROTO_DONE); } - #endif diff --git a/freebsd/sys/netinet/sctp_os_bsd.h b/freebsd/sys/netinet/sctp_os_bsd.h index e87914e5..438973cb 100644 --- a/freebsd/sys/netinet/sctp_os_bsd.h +++ b/freebsd/sys/netinet/sctp_os_bsd.h @@ -247,7 +247,6 @@ MALLOC_DECLARE(SCTP_M_MCORE); /* SCTP_ZONE_INIT: initialize the zone */ typedef struct uma_zone *sctp_zone_t; - #define SCTP_ZONE_INIT(zone, name, size, number) { \ zone = uma_zcreate(name, size, NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,\ 0); \ diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c index 9e12e775..94f9d866 100644 --- a/freebsd/sys/netinet/sctp_output.c +++ b/freebsd/sys/netinet/sctp_output.c @@ -1945,7 +1945,6 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t * len) struct sctp_paramhdr *parmh; struct mbuf *mret; uint16_t plen; - #endif switch (ifa->address.sa.sa_family) { @@ -2141,10 +2140,8 @@ skip_count: cnt++; total_count++; if (cnt >= 2) { - /* - * two from each - * address - */ + /* two from each + * address */ break; } if (total_count > SCTP_ADDRESS_LIMIT) { @@ -2786,7 +2783,6 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, { struct sctp_ifa *ifa, *sifa; int num_eligible_addr = 0; - #ifdef INET6 struct sockaddr_in6 sin6, lsa6; @@ -2831,10 +2827,8 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, if (fam == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&sifa->address.sin6.sin6_addr) && IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)) { - /* - * link-local <-> link-local must belong to the same - * scope. - */ + /* link-local <-> link-local must belong to the same + * scope. */ memcpy(&lsa6, &sifa->address.sin6, sizeof(struct sockaddr_in6)); (void)sa6_recoverscope(&lsa6); if (sin6.sin6_scope_id != lsa6.sin6_scope_id) { @@ -2968,10 +2962,8 @@ sctp_choose_boundall(struct sctp_inpcb *inp, struct sctp_ifa *sctp_ifa, *sifa; uint32_t ifn_index; struct sctp_vrf *vrf; - #ifdef INET int retried = 0; - #endif /*- @@ -3317,14 +3309,11 @@ sctp_source_address_selection(struct sctp_inpcb *inp, struct sctp_ifa *answer; uint8_t dest_is_priv, dest_is_loop; sa_family_t fam; - #ifdef INET struct sockaddr_in *to = (struct sockaddr_in *)&ro->ro_dst; - #endif #ifdef INET6 struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)&ro->ro_dst; - #endif /** @@ -3572,14 +3561,11 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er struct cmsghdr cmh; int tlen, at; struct sctp_initmsg initmsg; - #ifdef INET struct sockaddr_in sin; - #endif #ifdef INET6 struct sockaddr_in6 sin6; - #endif tlen = SCTP_BUF_LEN(control); @@ -3620,10 +3606,8 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er if (stcb->asoc.streamoutcnt < stcb->asoc.pre_open_streams) { struct sctp_stream_out *tmp_str; unsigned int i; - #if defined(SCTP_DETAILED_STR_STATS) int j; - #endif /* Default is NOT correct */ @@ -3656,7 +3640,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er stcb->asoc.strmout[i].abandoned_sent[0] = 0; stcb->asoc.strmout[i].abandoned_unsent[0] = 0; #endif - stcb->asoc.strmout[i].stream_no = i; + stcb->asoc.strmout[i].sid = i; stcb->asoc.strmout[i].last_msg_incomplete = 0; stcb->asoc.strmout[i].state = SCTP_STREAM_OPENING; stcb->asoc.ss_functions.sctp_ss_init_stream(stcb, &stcb->asoc.strmout[i], NULL); @@ -3746,14 +3730,11 @@ sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p, int tlen, at; struct sctp_tcb *stcb; struct sockaddr *addr; - #ifdef INET struct sockaddr_in sin; - #endif #ifdef INET6 struct sockaddr_in6 sin6; - #endif tlen = SCTP_BUF_LEN(control); @@ -3972,7 +3953,6 @@ sctp_handle_no_route(struct sctp_tcb *stcb, } } } - #endif static int @@ -4018,22 +3998,17 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, struct sctphdr *sctphdr; int packet_length; int ret; - #if defined(INET) || defined(INET6) uint32_t vrf_id; - #endif #if defined(INET) || defined(INET6) struct mbuf *o_pak; sctp_route_t *ro = NULL; struct udphdr *udp = NULL; - #endif uint8_t tos_value; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so = NULL; - #endif if ((net) && (net->dest_state & SCTP_ADDR_OUT_OF_SCOPE)) { @@ -4291,10 +4266,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, /* free tempy routes */ RO_RTFREE(ro); } else { - /* - * PMTU check versus smallest asoc MTU goes - * here - */ + /* PMTU check versus smallest asoc MTU goes + * here */ if ((ro->ro_rt != NULL) && (net->ro._s_addr)) { uint32_t mtu; @@ -4569,10 +4542,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT3, (struct sockaddr *)sin6); if (net) { sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; - /* - * preserve the port and scope for link - * local send - */ + /* preserve the port and scope for link + * local send */ prev_scope = sin6->sin6_scope_id; prev_port = sin6->sin6_port; } @@ -4638,10 +4609,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, /* Now if we had a temp route free it */ RO_RTFREE(ro); } else { - /* - * PMTU check versus smallest asoc MTU goes - * here - */ + /* PMTU check versus smallest asoc MTU goes + * here */ if (ro->ro_rt == NULL) { /* Route was freed */ if (net->ro._s_addr && @@ -4971,11 +4940,11 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, * being equal to the beginning of the params i.e. (iphlen + * sizeof(struct sctp_init_msg) parse through the parameters to the * end of the mbuf verifying that all parameters are known. - * + * * For unknown parameters build and return a mbuf with * UNRECOGNIZED_PARAMETER errors. If the flags indicate to stop * processing this chunk stop, and set *abort_processing to 1. - * + * * By having param_offset be pre-set to where parameters begin it is * hoped that this routine may be reused in the future by new * features. @@ -5262,7 +5231,6 @@ invalid_size: *abort_processing = 1; if ((op_err == NULL) && phdr) { int l_len; - #ifdef INET6 l_len = SCTP_MIN_OVERHEAD; #else @@ -5320,14 +5288,11 @@ sctp_are_there_new_addresses(struct sctp_association *asoc, uint8_t fnd; struct sctp_nets *net; int check_src; - #ifdef INET struct sockaddr_in sin4, *sa4; - #endif #ifdef INET6 struct sockaddr_in6 sin6, *sa6; - #endif #ifdef INET @@ -5511,18 +5476,15 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_paramhdr *ph; union sctp_sockstore *over_addr; struct sctp_scoping scp; - #ifdef INET struct sockaddr_in *dst4 = (struct sockaddr_in *)dst; struct sockaddr_in *src4 = (struct sockaddr_in *)src; struct sockaddr_in *sin; - #endif #ifdef INET6 struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst; struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)src; struct sockaddr_in6 *sin6; - #endif struct sockaddr *to; struct sctp_state_cookie stc; @@ -5546,10 +5508,10 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* * new addresses, out of here in non-cookie-wait * states - * - * Send an ABORT, without the new address error cause. - * This looks no different than if no listener was - * present. + * + * Send an ABORT, without the new address error + * cause. This looks no different than if no + * listener was present. */ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), "Address added"); @@ -5562,9 +5524,9 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* * change of remote encapsulation port, out of here * in non-cookie-wait states - * - * Send an ABORT, without an specific error cause. This - * looks no different than if no listener was + * + * Send an ABORT, without an specific error cause. + * This looks no different than if no listener was * present. */ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), @@ -5718,10 +5680,8 @@ do_a_abort: * show up in our scoped count. */ cnt_inits_to = 1; - /* - * pull out the scope_id from - * incoming pkt - */ + /* pull out the scope_id from + * incoming pkt */ } else if (IN6_IS_ADDR_SITELOCAL(&src6->sin6_addr) || IN6_IS_ADDR_SITELOCAL(&dst6->sin6_addr)) { /* @@ -5746,7 +5706,6 @@ do_a_abort: #ifdef INET6 struct sctp_nets *lnet; - #endif stc.loopback_scope = asoc->scope.loopback_scope; @@ -6208,9 +6167,9 @@ sctp_prune_prsctp(struct sctp_tcb *stcb, if (freed_spc >= dataout) { return; } - } /* if chunk was present */ - } /* if of sufficient priority */ - } /* if chunk has enabled */ + } /* if chunk was present */ + } /* if of sufficient priority */ + } /* if chunk has enabled */ } /* tailqforeach */ TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { @@ -6231,11 +6190,11 @@ sctp_prune_prsctp(struct sctp_tcb *stcb, if (freed_spc >= dataout) { return; } - } /* end if chk->data */ - } /* end if right class */ - } /* end if chk pr-sctp */ + } /* end if chk->data */ + } /* end if right class */ + } /* end if chk pr-sctp */ } /* tailqforeachsafe (chk) */ - } /* if enabled in asoc */ + } /* if enabled in asoc */ } int @@ -6391,7 +6350,7 @@ sctp_msg_append(struct sctp_tcb *stcb, sp->net = NULL; } (void)SCTP_GETTIME_TIMEVAL(&sp->ts); - sp->stream = srcv->sinfo_stream; + sp->sid = srcv->sinfo_stream; sp->msg_is_complete = 1; sp->sender_all_done = 1; sp->some_taken = 0; @@ -6478,10 +6437,8 @@ error_out: /* get the prepend space */ SCTP_BUF_RESV_UF(outchain, (SCTP_FIRST_MBUF_RESV + 4)); } else { - /* - * We really should not get a NULL - * in endofchain - */ + /* We really should not get a NULL + * in endofchain */ /* find end */ m = outchain; while (m) { @@ -6493,10 +6450,8 @@ error_out: } /* sanity */ if (*endofchain == NULL) { - /* - * huh, TSNH XXX maybe we - * should panic - */ + /* huh, TSNH XXX maybe we + * should panic */ sctp_m_freem(outchain); goto new_mbuf; } @@ -6695,17 +6650,13 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) { goto abort_anyway; } - /* - * there is nothing queued to send, so I'm - * done... - */ + /* there is nothing queued to send, so I'm + * done... */ if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) && (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { - /* - * only send SHUTDOWN the first time - * through - */ + /* only send SHUTDOWN the first time + * through */ if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } @@ -6982,14 +6933,14 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb, /* record time */ data_list[i]->sent_rcv_time = net->last_sent_time; data_list[i]->rec.data.cwnd_at_send = net->cwnd; - data_list[i]->rec.data.fast_retran_tsn = data_list[i]->rec.data.TSN_seq; + data_list[i]->rec.data.fast_retran_tsn = data_list[i]->rec.data.tsn; if (data_list[i]->whoTo == NULL) { data_list[i]->whoTo = net; atomic_add_int(&net->ref_count, 1); } /* on to the sent queue */ tp1 = TAILQ_LAST(&asoc->sent_queue, sctpchunk_listhead); - if ((tp1) && SCTP_TSN_GT(tp1->rec.data.TSN_seq, data_list[i]->rec.data.TSN_seq)) { + if ((tp1) && SCTP_TSN_GT(tp1->rec.data.tsn, data_list[i]->rec.data.tsn)) { struct sctp_tmit_chunk *tpp; /* need to move back */ @@ -7000,7 +6951,7 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb, goto all_done; } tp1 = tpp; - if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, data_list[i]->rec.data.TSN_seq)) { + if (SCTP_TSN_GT(tp1->rec.data.tsn, data_list[i]->rec.data.tsn)) { goto back_up_more; } TAILQ_INSERT_AFTER(&asoc->sent_queue, tp1, data_list[i], sctp_next); @@ -7029,7 +6980,7 @@ all_done: data_list[i]->whoTo->flight_size, data_list[i]->book_size, (uint32_t) (uintptr_t) data_list[i]->whoTo, - data_list[i]->rec.data.TSN_seq); + data_list[i]->rec.data.tsn); } sctp_flight_size_increase(data_list[i]); sctp_total_flight_increase(stcb, data_list[i]); @@ -7197,7 +7148,7 @@ one_more_time: (stcb->asoc.idata_supported == 0) && (strq->last_msg_incomplete)) { SCTP_PRINTF("Huh? Stream:%d lm_in_c=%d but queue is NULL\n", - strq->stream_no, + strq->sid, strq->last_msg_incomplete); strq->last_msg_incomplete = 0; } @@ -7336,10 +7287,8 @@ re_look: SCTP_TCB_SEND_LOCK(stcb); send_lock_up = 1; if (sp->msg_is_complete) { - /* - * the sender finished the - * msg - */ + /* the sender finished the + * msg */ goto re_look; } } @@ -7546,28 +7495,28 @@ dont_do_it: if (stcb->asoc.idata_supported == 0) { if (rcv_flags & SCTP_DATA_UNORDERED) { /* Just use 0. The receiver ignores the values. */ - chk->rec.data.stream_seq = 0; + chk->rec.data.mid = 0; } else { - chk->rec.data.stream_seq = strq->next_mid_ordered; + chk->rec.data.mid = strq->next_mid_ordered; if (rcv_flags & SCTP_DATA_LAST_FRAG) { strq->next_mid_ordered++; } } } else { if (rcv_flags & SCTP_DATA_UNORDERED) { - chk->rec.data.stream_seq = strq->next_mid_unordered; + chk->rec.data.mid = strq->next_mid_unordered; if (rcv_flags & SCTP_DATA_LAST_FRAG) { strq->next_mid_unordered++; } } else { - chk->rec.data.stream_seq = strq->next_mid_ordered; + chk->rec.data.mid = strq->next_mid_ordered; if (rcv_flags & SCTP_DATA_LAST_FRAG) { strq->next_mid_ordered++; } } } - chk->rec.data.stream_number = sp->stream; - chk->rec.data.payloadtype = sp->ppid; + chk->rec.data.sid = sp->sid; + chk->rec.data.ppid = sp->ppid; chk->rec.data.context = sp->context; chk->rec.data.doing_fast_retransmit = 0; @@ -7585,12 +7534,12 @@ dont_do_it: sctp_auth_key_acquire(stcb, chk->auth_keyid); chk->holds_key_ref = 1; } - chk->rec.data.TSN_seq = atomic_fetchadd_int(&asoc->sending_seq, 1); + chk->rec.data.tsn = atomic_fetchadd_int(&asoc->sending_seq, 1); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_AT_SEND_2_OUTQ) { sctp_misc_ints(SCTP_STRMOUT_LOG_SEND, (uint32_t) (uintptr_t) stcb, sp->length, - (uint32_t) ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq), - chk->rec.data.TSN_seq); + (uint32_t) ((chk->rec.data.sid << 16) | (0x0000ffff & chk->rec.data.mid)), + chk->rec.data.tsn); } if (stcb->asoc.idata_supported == 0) { dchkh = mtod(chk->data, struct sctp_data_chunk *); @@ -7608,9 +7557,9 @@ dont_do_it: asoc->tsn_out_at = 0; asoc->tsn_out_wrapped = 1; } - asoc->out_tsnlog[asoc->tsn_out_at].tsn = chk->rec.data.TSN_seq; - asoc->out_tsnlog[asoc->tsn_out_at].strm = chk->rec.data.stream_number; - asoc->out_tsnlog[asoc->tsn_out_at].seq = chk->rec.data.stream_seq; + asoc->out_tsnlog[asoc->tsn_out_at].tsn = chk->rec.data.tsn; + asoc->out_tsnlog[asoc->tsn_out_at].strm = chk->rec.data.sid; + asoc->out_tsnlog[asoc->tsn_out_at].seq = chk->rec.data.mid; asoc->out_tsnlog[asoc->tsn_out_at].sz = chk->send_size; asoc->out_tsnlog[asoc->tsn_out_at].flgs = chk->rec.data.rcv_flags; asoc->out_tsnlog[asoc->tsn_out_at].stcb = (void *)stcb; @@ -7621,20 +7570,20 @@ dont_do_it: if (stcb->asoc.idata_supported == 0) { dchkh->ch.chunk_type = SCTP_DATA; dchkh->ch.chunk_flags = chk->rec.data.rcv_flags; - dchkh->dp.tsn = htonl(chk->rec.data.TSN_seq); - dchkh->dp.stream_id = htons((strq->stream_no & 0x0000ffff)); - dchkh->dp.stream_sequence = htons((uint16_t) chk->rec.data.stream_seq); - dchkh->dp.protocol_id = chk->rec.data.payloadtype; + dchkh->dp.tsn = htonl(chk->rec.data.tsn); + dchkh->dp.sid = htons(strq->sid); + dchkh->dp.ssn = htons((uint16_t) chk->rec.data.mid); + dchkh->dp.ppid = chk->rec.data.ppid; dchkh->ch.chunk_length = htons(chk->send_size); } else { ndchkh->ch.chunk_type = SCTP_IDATA; ndchkh->ch.chunk_flags = chk->rec.data.rcv_flags; - ndchkh->dp.tsn = htonl(chk->rec.data.TSN_seq); - ndchkh->dp.stream_id = htons(strq->stream_no); + ndchkh->dp.tsn = htonl(chk->rec.data.tsn); + ndchkh->dp.sid = htons(strq->sid); ndchkh->dp.reserved = htons(0); - ndchkh->dp.msg_id = htonl(chk->rec.data.stream_seq); + ndchkh->dp.mid = htonl(chk->rec.data.mid); if (sp->fsn == 0) - ndchkh->dp.ppid_fsn.protocol_id = chk->rec.data.payloadtype; + ndchkh->dp.ppid_fsn.ppid = chk->rec.data.ppid; else ndchkh->dp.ppid_fsn.fsn = htonl(sp->fsn); sp->fsn++; @@ -7957,9 +7906,9 @@ nothing_to_send: * (when CMT is off) then it calls * sctp_fill_outqueue for the net. This gets data on * the send queue for that network. - * - * In sctp_fill_outqueue TSN's are assigned and data is - * copied out of the stream buffers. Note mostly + * + * In sctp_fill_outqueue TSN's are assigned and data + * is copied out of the stream buffers. Note mostly * copy by reference (we hope). */ net->window_probe = 0; @@ -8228,10 +8177,8 @@ again_one_more_time: net->port, NULL, 0, 0, so_locked))) { - /* - * error, we could not - * output - */ + /* error, we could not + * output */ SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error); if (from_where == 0) { SCTP_STAT_INCR(sctps_lowlevelerrusr); @@ -8304,16 +8251,12 @@ again_one_more_time: * to where the sack is going.. */ if (chk->whoTo == net) { - /* - * Don't transmit it to where its - * going (current net) - */ + /* Don't transmit it to where its + * going (current net) */ continue; } else if (sack_goes_to == net) { - /* - * But do transmit it to this - * address - */ + /* But do transmit it to this + * address */ goto skip_net_check; } } @@ -8506,10 +8449,8 @@ again_one_more_time: net->port, NULL, 0, 0, so_locked))) { - /* - * error, we could not - * output - */ + /* error, we could not + * output */ SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error); if (from_where == 0) { SCTP_STAT_INCR(sctps_lowlevelerrusr); @@ -8706,17 +8647,13 @@ again_one_more_time: override_ok = 0; SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks); } else if (override_ok) { - /* - * use this data's - * keyid - */ + /* use this data's + * keyid */ auth_keyid = chk->auth_keyid; override_ok = 0; } else if (auth_keyid != chk->auth_keyid) { - /* - * different keyid, - * so done bundling - */ + /* different keyid, + * so done bundling */ break; } } @@ -8795,8 +8732,7 @@ again_one_more_time: break; } } /* for (chunk gather loop for this net) */ - } /* if asoc.state OPEN */ -no_data_fill: +} /* if asoc.state OPEN */ no_data_fill: /* Is there something to send for this destination? */ if (outchain) { /* We may need to start a control timer or two */ @@ -8883,7 +8819,7 @@ no_data_fill: } if (bundle_at) { /* setup for a RTO measurement */ - tsns_sent = data_list[0]->rec.data.TSN_seq; + tsns_sent = data_list[0]->rec.data.tsn; /* fill time if not already filled */ if (*now_filled == 0) { (void)SCTP_GETTIME_TIMEVAL(&asoc->time_last_sent); @@ -9564,7 +9500,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, } if (chk->data == NULL) { SCTP_PRINTF("TSN:%x chk->snd_count:%d chk->sent:%d can't retran - no data\n", - chk->rec.data.TSN_seq, chk->snd_count, chk->sent); + chk->rec.data.tsn, chk->snd_count, chk->sent); continue; } if ((SCTP_BASE_SYSCTL(sctp_max_retran_chunk)) && @@ -9573,7 +9509,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, char msg[SCTP_DIAG_INFO_LEN]; snprintf(msg, sizeof(msg), "TSN %8.8x retransmitted %d times, giving up", - chk->rec.data.TSN_seq, chk->snd_count); + chk->rec.data.tsn, chk->snd_count); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); atomic_add_int(&stcb->asoc.refcnt, 1); @@ -9607,7 +9543,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, uint32_t tsn; tsn = asoc->last_acked_seq + 1; - if (tsn == chk->rec.data.TSN_seq) { + if (tsn == chk->rec.data.tsn) { /* * we make a special exception for this * case. The peer has no rwnd but is missing @@ -9736,10 +9672,8 @@ one_chunk_around: auth_keyid = fwd->auth_keyid; override_ok = 0; } else if (fwd->auth_keyid != auth_keyid) { - /* - * different keyid, - * so done bundling - */ + /* different keyid, + * so done bundling */ break; } } @@ -9819,7 +9753,7 @@ one_chunk_around: sctp_audit_log(0xC4, bundle_at); #endif if (bundle_at) { - tsns_sent = data_list[0]->rec.data.TSN_seq; + tsns_sent = data_list[0]->rec.data.tsn; } for (i = 0; i < bundle_at; i++) { SCTP_STAT_INCR(sctps_sendretransdata); @@ -9869,7 +9803,7 @@ one_chunk_around: data_list[i]->whoTo->flight_size, data_list[i]->book_size, (uint32_t) (uintptr_t) data_list[i]->whoTo, - data_list[i]->rec.data.TSN_seq); + data_list[i]->rec.data.tsn); } sctp_flight_size_increase(data_list[i]); sctp_total_flight_increase(stcb, data_list[i]); @@ -10115,11 +10049,9 @@ do_it_again: if (asoc->max_burst > 0) { if (SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst)) { if ((net->flight_size + (asoc->max_burst * net->mtu)) < net->cwnd) { - /* - * JRS - Use the congestion + /* JRS - Use the congestion * control given in the - * congestion control module - */ + * congestion control module */ asoc->cc_functions.sctp_cwnd_update_after_output(stcb, net, asoc->max_burst); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_MAXBURST_ENABLE) { sctp_log_maxburst(stcb, net, 0, asoc->max_burst, SCTP_MAX_BURST_APPLIED); @@ -10129,10 +10061,8 @@ do_it_again: net->fast_retran_ip = 0; } else { if (net->flight_size == 0) { - /* - * Should be decaying the - * cwnd here - */ + /* Should be decaying the + * cwnd here */ ; } } @@ -10268,13 +10198,7 @@ send_forward_tsn(struct sctp_tcb *stcb, unsigned int cnt_of_space, i, ovh; unsigned int space_needed; unsigned int cnt_of_skipped = 0; - int old; - if (asoc->idata_supported) { - old = 0; - } else { - old = 1; - } SCTP_TCB_LOCK_ASSERT(stcb); TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) { if (chk->rec.chunk_id.id == SCTP_FORWARD_CUM_TSN) { @@ -10328,18 +10252,18 @@ sctp_fill_in_rest: /* no more to look at */ break; } - if (old && (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) { + if (!asoc->idata_supported && (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) { /* We don't report these */ continue; } cnt_of_skipped++; } - if (old) { - space_needed = (sizeof(struct sctp_forward_tsn_chunk) + - (cnt_of_skipped * sizeof(struct sctp_strseq))); - } else { + if (asoc->idata_supported) { space_needed = (sizeof(struct sctp_forward_tsn_chunk) + (cnt_of_skipped * sizeof(struct sctp_strseq_mid))); + } else { + space_needed = (sizeof(struct sctp_forward_tsn_chunk) + + (cnt_of_skipped * sizeof(struct sctp_strseq))); } cnt_of_space = (unsigned int)M_TRAILINGSPACE(chk->data); @@ -10368,12 +10292,11 @@ sctp_fill_in_rest: 0xff, 0xff, cnt_of_space, space_needed); } - if (old) { - cnt_of_skipped = cnt_of_space - sizeof(struct sctp_forward_tsn_chunk); - cnt_of_skipped /= sizeof(struct sctp_strseq); - } else { - cnt_of_skipped = cnt_of_space - sizeof(struct sctp_forward_tsn_chunk); + cnt_of_skipped = cnt_of_space - sizeof(struct sctp_forward_tsn_chunk); + if (asoc->idata_supported) { cnt_of_skipped /= sizeof(struct sctp_strseq_mid); + } else { + cnt_of_skipped /= sizeof(struct sctp_strseq); } /*- * Go through and find the TSN that will be the one @@ -10391,7 +10314,7 @@ sctp_fill_in_rest: } if (at && SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) { sctp_misc_ints(SCTP_FWD_TSN_CHECK, - 0xff, cnt_of_skipped, at->rec.data.TSN_seq, + 0xff, cnt_of_skipped, at->rec.data.tsn, asoc->advanced_peer_ack_point); } last = at; @@ -10400,14 +10323,14 @@ sctp_fill_in_rest: * peer ack point */ if (last) { - advance_peer_ack_point = last->rec.data.TSN_seq; + advance_peer_ack_point = last->rec.data.tsn; } - if (old) { - space_needed = sizeof(struct sctp_forward_tsn_chunk) + - cnt_of_skipped * sizeof(struct sctp_strseq); - } else { + if (asoc->idata_supported) { space_needed = sizeof(struct sctp_forward_tsn_chunk) + cnt_of_skipped * sizeof(struct sctp_strseq_mid); + } else { + space_needed = sizeof(struct sctp_forward_tsn_chunk) + + cnt_of_skipped * sizeof(struct sctp_strseq); } } chk->send_size = space_needed; @@ -10415,10 +10338,10 @@ sctp_fill_in_rest: fwdtsn = mtod(chk->data, struct sctp_forward_tsn_chunk *); fwdtsn->ch.chunk_length = htons(chk->send_size); fwdtsn->ch.chunk_flags = 0; - if (old) { - fwdtsn->ch.chunk_type = SCTP_FORWARD_CUM_TSN; - } else { + if (asoc->idata_supported) { fwdtsn->ch.chunk_type = SCTP_IFORWARD_CUM_TSN; + } else { + fwdtsn->ch.chunk_type = SCTP_FORWARD_CUM_TSN; } fwdtsn->new_cumulative_tsn = htonl(advance_peer_ack_point); SCTP_BUF_LEN(chk->data) = chk->send_size; @@ -10427,10 +10350,12 @@ sctp_fill_in_rest: * Move pointer to after the fwdtsn and transfer to the * strseq pointer. */ - if (old) { - strseq = (struct sctp_strseq *)fwdtsn; - } else { + if (asoc->idata_supported) { strseq_m = (struct sctp_strseq_mid *)fwdtsn; + strseq = NULL; + } else { + strseq = (struct sctp_strseq *)fwdtsn; + strseq_m = NULL; } /*- * Now populate the strseq list. This is done blindly @@ -10449,26 +10374,26 @@ sctp_fill_in_rest: if (i >= cnt_of_skipped) { break; } - if (old && (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) { + if (!asoc->idata_supported && (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) { /* We don't report these */ continue; } - if (at->rec.data.TSN_seq == advance_peer_ack_point) { + if (at->rec.data.tsn == advance_peer_ack_point) { at->rec.data.fwd_tsn_cnt = 0; } - if (old) { - strseq->stream = htons(at->rec.data.stream_number); - strseq->sequence = htons((uint16_t) at->rec.data.stream_seq); - strseq++; - } else { - strseq_m->stream = htons(at->rec.data.stream_number); + if (asoc->idata_supported) { + strseq_m->sid = htons(at->rec.data.sid); if (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED) { strseq_m->flags = htons(PR_SCTP_UNORDERED_FLAG); } else { strseq_m->flags = 0; } - strseq_m->msg_id = htonl(at->rec.data.stream_seq); + strseq_m->mid = htonl(at->rec.data.mid); strseq_m++; + } else { + strseq->sid = htons(at->rec.data.sid); + strseq->ssn = htons((uint16_t) at->rec.data.mid); + strseq++; } i++; } @@ -11019,23 +10944,18 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, struct mbuf *mout; struct sctphdr *shout; struct sctp_chunkhdr *ch; - #if defined(INET) || defined(INET6) struct udphdr *udp; int ret; - #endif int len, cause_len, padding_len; - #ifdef INET struct sockaddr_in *src_sin, *dst_sin; struct ip *ip; - #endif #ifdef INET6 struct sockaddr_in6 *src_sin6, *dst_sin6; struct ip6_hdr *ip6; - #endif /* Compute the length of the cause and add final padding. */ @@ -11624,10 +11544,8 @@ sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn, u asoc = &stcb->asoc; TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) { if ((chk->rec.chunk_id.id == SCTP_ECN_CWR) && (net == chk->whoTo)) { - /* - * found a previous CWR queued to same destination - * update it if needed - */ + /* found a previous CWR queued to same destination + * update it if needed */ uint32_t ctsn; cwr = mtod(chk->data, struct sctp_cwr_chunk *); @@ -12171,10 +12089,8 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, struct sctp_stream_out *oldstream; struct sctp_stream_queue_pending *sp, *nsp; int i; - #if defined(SCTP_DETAILED_STR_STATS) int j; - #endif oldstream = stcb->asoc.strmout; @@ -12203,13 +12119,11 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, stcb->asoc.strmout[i].next_mid_ordered = oldstream[i].next_mid_ordered; stcb->asoc.strmout[i].next_mid_unordered = oldstream[i].next_mid_unordered; stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete; - stcb->asoc.strmout[i].stream_no = i; + stcb->asoc.strmout[i].sid = i; stcb->asoc.strmout[i].state = oldstream[i].state; /* FIX ME FIX ME */ - /* - * This should be a SS_COPY operation FIX ME STREAM - * SCHEDULER EXPERT - */ + /* This should be a SS_COPY operation FIX ME STREAM + * SCHEDULER EXPERT */ stcb->asoc.ss_functions.sctp_ss_init_stream(stcb, &stcb->asoc.strmout[i], &oldstream[i]); /* now anything on those queues? */ TAILQ_FOREACH_SAFE(sp, &oldstream[i].outqueue, next, nsp) { @@ -12234,7 +12148,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, #endif stcb->asoc.strmout[i].next_mid_ordered = 0; stcb->asoc.strmout[i].next_mid_unordered = 0; - stcb->asoc.strmout[i].stream_no = i; + stcb->asoc.strmout[i].sid = i; stcb->asoc.strmout[i].last_msg_incomplete = 0; stcb->asoc.ss_functions.sctp_ss_init_stream(stcb, &stcb->asoc.strmout[i], NULL); stcb->asoc.strmout[i].state = SCTP_STREAM_CLOSED; @@ -12393,7 +12307,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb, sp->fsn = 0; (void)SCTP_GETTIME_TIMEVAL(&sp->ts); - sp->stream = srcv->sinfo_stream; + sp->sid = srcv->sinfo_stream; sp->length = (uint32_t) min(uio->uio_resid, max_send_len); if ((sp->length == (uint32_t) uio->uio_resid) && ((user_marks_eor == 0) || @@ -12453,10 +12367,8 @@ sctp_sosend(struct socket *so, int error, use_sndinfo = 0; struct sctp_sndrcvinfo sndrcvninfo; struct sockaddr *addr_to_use; - #if defined(INET) && defined(INET6) struct sockaddr_in sin; - #endif if (control) { @@ -12741,10 +12653,8 @@ sctp_lower_sosend(struct socket *so, } if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) { stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; - /* - * Set the connected flag so we can queue - * data - */ + /* Set the connected flag so we can queue + * data */ soisconnecting(so); } hold_tcblock = 1; @@ -12754,10 +12664,8 @@ sctp_lower_sosend(struct socket *so, } else { SCTP_PRINTF("Huh-3? create lock should have been on??\n"); } - /* - * Turn on queue only flag to prevent data from - * being sent - */ + /* Turn on queue only flag to prevent data from + * being sent */ queue_only = 1; asoc = &stcb->asoc; SCTP_SET_STATE(asoc, SCTP_STATE_COOKIE_WAIT); @@ -13252,10 +13160,8 @@ skip_preblock: } /* PR-SCTP? */ if ((asoc->prsctp_supported) && (asoc->sent_queue_cnt_removeable > 0)) { - /* - * This is ugly but we must assure locking - * order - */ + /* This is ugly but we must assure locking + * order */ if (hold_tcblock == 0) { SCTP_TCB_LOCK(stcb); hold_tcblock = 1; @@ -13532,10 +13438,8 @@ dataless_eof: msg); sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_LOCKED); - /* - * now relock the stcb so everything - * is sane - */ + /* now relock the stcb so everything + * is sane */ hold_tcblock = 0; stcb = NULL; goto out; @@ -13609,10 +13513,8 @@ skip_out_eof: if ((queue_only == 0) && (nagle_applies == 0) && (stcb->asoc.peers_rwnd && un_sent)) { /* we can attempt to send too. */ if (hold_tcblock == 0) { - /* - * If there is activity recv'ing sacks no need to - * send - */ + /* If there is activity recv'ing sacks no need to + * send */ if (SCTP_TCB_TRYLOCK(stcb)) { sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED); hold_tcblock = 1; @@ -13751,6 +13653,7 @@ sctp_v6src_match_nexthop(struct sockaddr_in6 *src6, sctp_route_t * ro) return (0); /* get prefix entry of address */ + ND6_RLOCK(); LIST_FOREACH(pfx, &MODULE_GLOBAL(nd_prefix), ndpr_entry) { if (pfx->ndpr_stateflags & NDPRF_DETACHED) continue; @@ -13760,6 +13663,7 @@ sctp_v6src_match_nexthop(struct sockaddr_in6 *src6, sctp_route_t * ro) } /* no prefix entry in the prefix list */ if (pfx == NULL) { + ND6_RUNLOCK(); SCTPDBG(SCTP_DEBUG_OUTPUT2, "No prefix entry for "); SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)src6); return (0); @@ -13778,16 +13682,16 @@ sctp_v6src_match_nexthop(struct sockaddr_in6 *src6, sctp_route_t * ro) SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&gw6); SCTPDBG(SCTP_DEBUG_OUTPUT2, "installed router is "); SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, ro->ro_rt->rt_gateway); - if (sctp_cmpaddr((struct sockaddr *)&gw6, - ro->ro_rt->rt_gateway)) { + if (sctp_cmpaddr((struct sockaddr *)&gw6, ro->ro_rt->rt_gateway)) { + ND6_RUNLOCK(); SCTPDBG(SCTP_DEBUG_OUTPUT2, "pfxrouter is installed\n"); return (1); } } + ND6_RUNLOCK(); SCTPDBG(SCTP_DEBUG_OUTPUT2, "pfxrouter is not installed\n"); return (0); } - #endif int diff --git a/freebsd/sys/netinet/sctp_pcb.c b/freebsd/sys/netinet/sctp_pcb.c index 62ef1e3d..ca86a139 100644 --- a/freebsd/sys/netinet/sctp_pcb.c +++ b/freebsd/sys/netinet/sctp_pcb.c @@ -79,7 +79,6 @@ SCTP6_ARE_ADDR_EQUAL(struct sockaddr_in6 *a, struct sockaddr_in6 *b) } return (IN6_ARE_ADDR_EQUAL(&tmp_a.sin6_addr, &tmp_b.sin6_addr)); } - #endif void @@ -839,14 +838,11 @@ static int sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) { int loopback_scope; - #if defined(INET) int ipv4_local_scope, ipv4_addr_legal; - #endif #if defined(INET6) int local_scope, site_scope, ipv6_addr_legal; - #endif struct sctp_vrf *vrf; struct sctp_ifn *sctp_ifn; @@ -1218,10 +1214,8 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, if (netp != NULL) { *netp = net; } - /* - * Update the endpoint - * pointer - */ + /* Update the endpoint + * pointer */ *inp_p = inp; SCTP_INP_RUNLOCK(inp); return (stcb); @@ -1242,10 +1236,8 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, if (netp != NULL) { *netp = net; } - /* - * Update the endpoint - * pointer - */ + /* Update the endpoint + * pointer */ *inp_p = inp; SCTP_INP_RUNLOCK(inp); return (stcb); @@ -1624,15 +1616,12 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, { struct sctp_inpcb *inp; struct sctp_laddr *laddr; - #ifdef INET struct sockaddr_in *sin; - #endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sockaddr_in6 *intf_addr6; - #endif int fnd; @@ -1675,10 +1664,8 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, case AF_INET: if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && SCTP_IPV6_V6ONLY(inp)) { - /* - * IPv4 on a IPv6 socket with ONLY - * IPv6 set - */ + /* IPv4 on a IPv6 socket with ONLY + * IPv6 set */ SCTP_INP_RUNLOCK(inp); continue; } @@ -1691,10 +1678,8 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, #endif #ifdef INET6 case AF_INET6: - /* - * A V6 address and the endpoint is NOT - * bound V6 - */ + /* A V6 address and the endpoint is NOT + * bound V6 */ if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { SCTP_INP_RUNLOCK(inp); continue; @@ -1928,14 +1913,11 @@ sctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock, struct sctppcbhead *head; int lport; unsigned int i; - #ifdef INET struct sockaddr_in *sin; - #endif #ifdef INET6 struct sockaddr_in6 *sin6; - #endif switch (nam->sa_family) { @@ -2059,21 +2041,16 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset, struct sockaddr *dst) { struct sctp_paramhdr *phdr, parm_buf; - #if defined(INET) || defined(INET6) struct sctp_tcb *stcb; uint16_t ptype; - #endif uint16_t plen; - #ifdef INET struct sockaddr_in sin4; - #endif #ifdef INET6 struct sockaddr_in6 sin6; - #endif #ifdef INET @@ -2200,10 +2177,8 @@ sctp_findassoc_by_vtag(struct sockaddr *from, struct sockaddr *to, uint32_t vtag continue; } if (remote_tag) { - /* - * If we have both vtags that's all we match - * on - */ + /* If we have both vtags that's all we match + * on */ if (stcb->asoc.peer_vtag == remote_tag) { /* * If both tags match we consider it @@ -2321,14 +2296,11 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, struct sctp_paramhdr parm_buf, *phdr; int ptype; int zero_address = 0; - #ifdef INET struct sockaddr_in *sin; - #endif #ifdef INET6 struct sockaddr_in6 *sin6; - #endif memset(&remote_store, 0, sizeof(remote_store)); @@ -2899,10 +2871,8 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, #ifdef INET6 case AF_INET6: { - /* - * Only for pure IPv6 Address. (No IPv4 - * Mapped!) - */ + /* Only for pure IPv6 Address. (No IPv4 + * Mapped!) */ struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)addr; @@ -2979,10 +2949,8 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, /* unlock info */ if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) && (sctp_is_feature_on(inp_tmp, SCTP_PCB_FLAGS_PORTREUSE))) { - /* - * Ok, must be one-2-one and - * allowing port re-use - */ + /* Ok, must be one-2-one and + * allowing port re-use */ port_reuse_active = 1; goto continue_anyway; } @@ -3005,10 +2973,8 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, /* unlock info */ if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) && (sctp_is_feature_on(inp_tmp, SCTP_PCB_FLAGS_PORTREUSE))) { - /* - * Ok, must be one-2-one and - * allowing port re-use - */ + /* Ok, must be one-2-one and + * allowing port re-use */ port_reuse_active = 1; goto continue_anyway; } @@ -3148,11 +3114,11 @@ continue_anyway: * bind specific, make sure flags is off and add a new * address structure to the sctp_addr_list inside the ep * structure. - * - * We will need to allocate one and insert it at the head. The - * socketopt call can just insert new addresses in there as - * well. It will also have to do the embed scope kame hack - * too (before adding). + * + * We will need to allocate one and insert it at the head. + * The socketopt call can just insert new addresses in there + * as well. It will also have to do the embed scope kame + * hack too (before adding). */ struct sctp_ifa *ifa; union sctp_sockstore store; @@ -3270,11 +3236,11 @@ sctp_iterator_inp_being_freed(struct sctp_inpcb *inp) * from happening. But of course the iterator has a * reference on the stcb and inp. We can mark it and it will * stop. - * - * If its a single iterator situation, we set the end iterator - * flag. Otherwise we set the iterator to go to the next - * inp. - * + * + * If its a single iterator situation, we set the end + * iterator flag. Otherwise we set the iterator to go to the + * next inp. + * */ if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; @@ -3307,10 +3273,8 @@ sctp_iterator_inp_being_freed(struct sctp_inpcb *inp) SCTP_INP_INCR_REF(it->inp); } } - /* - * When its put in the refcnt is incremented so decr - * it - */ + /* When its put in the refcnt is incremented so decr + * it */ SCTP_INP_DECR_REF(inp); } } @@ -3995,10 +3959,8 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, rmtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, net->ro.ro_rt); if (rmtu == 0) { - /* - * Start things off to match mtu of - * interface please. - */ + /* Start things off to match mtu of + * interface please. */ SCTP_SET_MTU_OF_ROUTE(&net->ro._l_addr.sa, net->ro.ro_rt, net->mtu); } else { @@ -4820,7 +4782,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre uint32_t strseq; stcb->asoc.control_pdapi = sq; - strseq = (sq->sinfo_stream << 16) | sq->sinfo_ssn; + strseq = (sq->sinfo_stream << 16) | (sq->mid & 0x0000ffff); sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION, stcb, SCTP_PARTIAL_DELIVERY_ABORTED, @@ -4912,6 +4874,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre SS_ISCONNECTED); } socantrcvmore_locked(so); + socantsendmore(so); sctp_sowwakeup(inp, so); sctp_sorwakeup(inp, so); SCTP_SOWAKEUP(so); @@ -5040,11 +5003,11 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre } /* pending send queue SHOULD be empty */ TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { - if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { - asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; + if (asoc->strmout[chk->rec.data.sid].chunks_on_queues > 0) { + asoc->strmout[chk->rec.data.sid].chunks_on_queues--; #ifdef INVARIANTS } else { - panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); + panic("No chunks on the queues for sid %u.", chk->rec.data.sid); #endif } TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); @@ -5072,11 +5035,11 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre /* sent queue SHOULD be empty */ TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { - if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { - asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; + if (asoc->strmout[chk->rec.data.sid].chunks_on_queues > 0) { + asoc->strmout[chk->rec.data.sid].chunks_on_queues--; #ifdef INVARIANTS } else { - panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); + panic("No chunks on the queues for sid %u.", chk->rec.data.sid); #endif } } @@ -5488,10 +5451,8 @@ sctp_del_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa) if (stcb->asoc.last_used_address == laddr) /* delete this address */ stcb->asoc.last_used_address = NULL; - /* - * Now spin through all the nets and purge any ref - * to laddr - */ + /* Now spin through all the nets and purge any ref + * to laddr */ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { if (net->ro._s_addr == laddr->ifa) { /* Yep, purge src address selected */ @@ -5759,7 +5720,6 @@ sctp_startup_mcore_threads(void) } } - #endif void @@ -6101,14 +6061,11 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, uint8_t peer_supports_nrsack; uint8_t peer_supports_pktdrop; uint8_t peer_supports_idata; - #ifdef INET struct sockaddr_in sin; - #endif #ifdef INET6 struct sockaddr_in6 sin6; - #endif /* First get the destination address setup too. */ @@ -6271,10 +6228,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, struct mbuf *op_err; char msg[SCTP_DIAG_INFO_LEN]; - /* - * in setup state we - * abort this guy - */ + /* in setup state we + * abort this guy */ snprintf(msg, sizeof(msg), "%s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), @@ -6316,10 +6271,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, goto next_param; } if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)) { - /* - * Link local make no sense without - * scope - */ + /* Link local make no sense without + * scope */ goto next_param; } sa = (struct sockaddr *)&sin6; @@ -6370,10 +6323,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, struct mbuf *op_err; char msg[SCTP_DIAG_INFO_LEN]; - /* - * in setup state we - * abort this guy - */ + /* in setup state we + * abort this guy */ snprintf(msg, sizeof(msg), "%s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), @@ -6413,10 +6364,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, struct sctp_asconf_addr_param lstore, *fee; int lptype; struct sockaddr *lsa = NULL; - #ifdef INET struct sctp_asconf_addrv4_param *fii; - #endif if (stcb->asoc.asconf_supported == 0) { @@ -6896,7 +6845,7 @@ sctp_drain_mbufs(struct sctp_tcb *stcb) /* Now its reasm? */ TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, nchk) { cnt++; - SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.TSN_seq, asoc->mapping_array_base_tsn); + SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.tsn, asoc->mapping_array_base_tsn); asoc->size_on_reasm_queue = sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size); sctp_ucount_decr(asoc->cnt_on_reasm_queue); SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); @@ -6938,7 +6887,7 @@ sctp_drain_mbufs(struct sctp_tcb *stcb) /* Now its reasm? */ TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, nchk) { cnt++; - SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.TSN_seq, asoc->mapping_array_base_tsn); + SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.tsn, asoc->mapping_array_base_tsn); asoc->size_on_reasm_queue = sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size); sctp_ucount_decr(asoc->cnt_on_reasm_queue); SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); diff --git a/freebsd/sys/netinet/sctp_pcb.h b/freebsd/sys/netinet/sctp_pcb.h index 98204096..a2a1e7d7 100644 --- a/freebsd/sys/netinet/sctp_pcb.h +++ b/freebsd/sys/netinet/sctp_pcb.h @@ -353,7 +353,6 @@ struct sctp_pcbtsn_rlog { uint16_t sz; uint16_t flgs; }; - #define SCTP_READ_LOG_SIZE 135 /* we choose the number to make a pcb a page */ @@ -380,10 +379,8 @@ struct sctp_inpcb { /* list of addrs in use by the EP, NULL if bound-all */ struct sctpladdr sctp_addr_list; - /* - * used for source address selection rotation when we are subset - * bound - */ + /* used for source address selection rotation when we are subset + * bound */ struct sctp_laddr *next_addr_touse; /* back pointer to our socket */ @@ -490,7 +487,6 @@ VNET_DECLARE(struct sctp_base_info, system_base_info); #ifdef INET6 int SCTP6_ARE_ADDR_EQUAL(struct sockaddr_in6 *a, struct sockaddr_in6 *b); - #endif void sctp_fill_pcbinfo(struct sctp_pcbinfo *); @@ -646,7 +642,6 @@ sctp_initiate_iterator(inp_func inpf, end_func ef, struct sctp_inpcb *, uint8_t co_off); - #if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) void sctp_queue_to_mcore(struct mbuf *m, int off, int cpu_to_use); diff --git a/freebsd/sys/netinet/sctp_peeloff.h b/freebsd/sys/netinet/sctp_peeloff.h index dd905676..00b87031 100644 --- a/freebsd/sys/netinet/sctp_peeloff.h +++ b/freebsd/sys/netinet/sctp_peeloff.h @@ -38,6 +38,5 @@ __FBSDID("$FreeBSD$"); #if defined(_KERNEL) int sctp_can_peel_off(struct socket *, sctp_assoc_t); int sctp_do_peeloff(struct socket *, struct socket *, sctp_assoc_t); - #endif /* _KERNEL */ #endif /* _NETINET_SCTP_PEELOFF_H_ */ diff --git a/freebsd/sys/netinet/sctp_structs.h b/freebsd/sys/netinet/sctp_structs.h index 280100bb..22a3c736 100644 --- a/freebsd/sys/netinet/sctp_structs.h +++ b/freebsd/sys/netinet/sctp_structs.h @@ -183,7 +183,6 @@ struct iterator_control { uint32_t iterator_running; uint32_t iterator_flags; }; - #define SCTP_ITERATOR_STOP_CUR_IT 0x00000004 #define SCTP_ITERATOR_STOP_CUR_INP 0x00000008 @@ -389,10 +388,10 @@ struct sctp_nets { struct sctp_data_chunkrec { - uint32_t TSN_seq; /* the TSN of this transmit */ - uint32_t stream_seq; /* the stream sequence number of this transmit */ - uint16_t stream_number; /* the stream number of this guy */ - uint32_t payloadtype; + uint32_t tsn; /* the TSN of this transmit */ + uint32_t mid; /* the message identifier of this transmit */ + uint16_t sid; /* the stream number of this guy */ + uint32_t ppid; uint32_t context; /* from send */ uint32_t cwnd_at_send; /* @@ -401,7 +400,7 @@ struct sctp_data_chunkrec { */ uint32_t fast_retran_tsn; /* sending_seq at the time of FR */ struct timeval timetodrop; /* time we drop it from queue */ - uint32_t fsn_num; /* Fragment Sequence Number */ + uint32_t fsn; /* Fragment Sequence Number */ uint8_t doing_fast_retransmit; uint8_t rcv_flags; /* flags pulled from data chunk on inbound for * outbound holds sending flags for PR-SCTP. */ @@ -455,7 +454,6 @@ struct sctp_tmit_chunk { struct sctp_queued_to_read { /* sinfo structure Pluse more */ uint16_t sinfo_stream; /* off the wire */ - uint32_t sinfo_ssn; /* off the wire */ uint16_t sinfo_flags; /* SCTP_UNORDERED from wire use SCTP_EOF for * EOR */ uint32_t sinfo_ppid; /* off the wire */ @@ -465,7 +463,7 @@ struct sctp_queued_to_read { /* sinfo structure Pluse more */ uint32_t sinfo_cumtsn; /* Use this in reassembly as last TSN */ sctp_assoc_t sinfo_assoc_id; /* our assoc id */ /* Non sinfo stuff */ - uint32_t msg_id; /* Fragment Index */ + uint32_t mid; /* Fragment Index */ uint32_t length; /* length of data */ uint32_t held_length; /* length held in sb */ uint32_t top_fsn; /* Highest FSN in queue */ @@ -527,7 +525,7 @@ struct sctp_stream_queue_pending { uint32_t ppid; uint32_t context; uint16_t sinfo_flags; - uint16_t stream; + uint16_t sid; uint16_t act_flags; uint16_t auth_keyid; uint8_t holds_key_ref; @@ -546,8 +544,8 @@ TAILQ_HEAD(sctpwheelunrel_listhead, sctp_stream_in); struct sctp_stream_in { struct sctp_readhead inqueue; struct sctp_readhead uno_inqueue; - uint32_t last_sequence_delivered; /* used for re-order */ - uint16_t stream_no; + uint32_t last_mid_delivered; /* used for re-order */ + uint16_t sid; uint8_t delivery_started; uint8_t pd_api_started; }; @@ -630,7 +628,7 @@ struct sctp_stream_out { */ uint32_t next_mid_ordered; uint32_t next_mid_unordered; - uint16_t stream_no; + uint16_t sid; uint8_t last_msg_incomplete; uint8_t state; }; @@ -883,10 +881,8 @@ struct sctp_association { /* JRS - the congestion control functions are in this struct */ struct sctp_cc_functions cc_functions; - /* - * JRS - value to store the currently loaded congestion control - * module - */ + /* JRS - value to store the currently loaded congestion control + * module */ uint32_t congestion_control_module; /* RS - the stream scheduling functions are in this struct */ struct sctp_ss_functions ss_functions; diff --git a/freebsd/sys/netinet/sctp_sysctl.c b/freebsd/sys/netinet/sctp_sysctl.c index 8715c69b..152a2996 100644 --- a/freebsd/sys/netinet/sctp_sysctl.c +++ b/freebsd/sys/netinet/sctp_sysctl.c @@ -645,12 +645,10 @@ static int sctp_sysctl_handle_stats(SYSCTL_HANDLER_ARGS) { int error; - #if defined(SMP) && defined(SCTP_USE_PERCPU_STAT) struct sctpstat *sarry; struct sctpstat sb; int cpu; - #endif struct sctpstat sb_temp; @@ -830,7 +828,6 @@ sctp_sysctl_handle_trace_log_clear(SYSCTL_HANDLER_ARGS) memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log)); return (error); } - #endif #define SCTP_UINT_SYSCTL(mib_name, var_name, prefix) \ diff --git a/freebsd/sys/netinet/sctp_timer.c b/freebsd/sys/netinet/sctp_timer.c index c851317b..2d427e48 100644 --- a/freebsd/sys/netinet/sctp_timer.c +++ b/freebsd/sys/netinet/sctp_timer.c @@ -195,10 +195,8 @@ sctp_find_alternate_net(struct sctp_tcb *stcb, */ if (mode == 2) { TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) { - /* - * JRS 5/14/07 - If the destination is unreachable - * or unconfirmed, skip it. - */ + /* JRS 5/14/07 - If the destination is unreachable + * or unconfirmed, skip it. */ if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) || (mnet->dest_state & SCTP_ADDR_UNCONFIRMED)) { continue; @@ -288,11 +286,8 @@ sctp_find_alternate_net(struct sctp_tcb *stcb, } else { return (max_cwnd_net); } - } - /* - * JRS 5/14/07 - If mode is set to 1, use the CMT policy for - * choosing an alternate net. - */ + } /* JRS 5/14/07 - If mode is set to 1, use the + * CMT policy for choosing an alternate net. */ else if (mode == 1) { TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) { if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) || @@ -436,17 +431,17 @@ sctp_recover_sent_list(struct sctp_tcb *stcb) asoc = &stcb->asoc; TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { - if (SCTP_TSN_GE(asoc->last_acked_seq, chk->rec.data.TSN_seq)) { + if (SCTP_TSN_GE(asoc->last_acked_seq, chk->rec.data.tsn)) { SCTP_PRINTF("Found chk:%p tsn:%x <= last_acked_seq:%x\n", - (void *)chk, chk->rec.data.TSN_seq, asoc->last_acked_seq); + (void *)chk, chk->rec.data.tsn, asoc->last_acked_seq); if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { - if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { - asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; + if (asoc->strmout[chk->rec.data.sid].chunks_on_queues > 0) { + asoc->strmout[chk->rec.data.sid].chunks_on_queues--; } } - if ((asoc->strmout[chk->rec.data.stream_number].chunks_on_queues == 0) && - (asoc->strmout[chk->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && - TAILQ_EMPTY(&asoc->strmout[chk->rec.data.stream_number].outqueue)) { + if ((asoc->strmout[chk->rec.data.sid].chunks_on_queues == 0) && + (asoc->strmout[chk->rec.data.sid].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&asoc->strmout[chk->rec.data.sid].outqueue)) { asoc->trigger_reset = 1; } TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); @@ -469,10 +464,9 @@ sctp_recover_sent_list(struct sctp_tcb *stcb) } SCTP_PRINTF("after recover order is as follows\n"); TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { - SCTP_PRINTF("chk:%p TSN:%x\n", (void *)chk, chk->rec.data.TSN_seq); + SCTP_PRINTF("chk:%p TSN:%x\n", (void *)chk, chk->rec.data.tsn); } } - #endif static int @@ -554,10 +548,10 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, start_again: #endif TAILQ_FOREACH_SAFE(chk, &stcb->asoc.sent_queue, sctp_next, nchk) { - if (SCTP_TSN_GE(stcb->asoc.last_acked_seq, chk->rec.data.TSN_seq)) { + if (SCTP_TSN_GE(stcb->asoc.last_acked_seq, chk->rec.data.tsn)) { /* Strange case our list got out of order? */ SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x\n", - (unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.TSN_seq); + (unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.tsn); recovery_cnt++; #ifdef INVARIANTS panic("last acked >= chk on sent-Q"); @@ -582,7 +576,7 @@ start_again: /* validate its been outstanding long enough */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { - sctp_log_fr(chk->rec.data.TSN_seq, + sctp_log_fr(chk->rec.data.tsn, chk->sent_rcv_time.tv_sec, chk->sent_rcv_time.tv_usec, SCTP_FR_T3_MARK_TIME); @@ -646,11 +640,11 @@ start_again: num_mk++; if (fir == 0) { fir = 1; - tsnfirst = chk->rec.data.TSN_seq; + tsnfirst = chk->rec.data.tsn; } - tsnlast = chk->rec.data.TSN_seq; + tsnlast = chk->rec.data.tsn; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { - sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count, + sctp_log_fr(chk->rec.data.tsn, chk->snd_count, 0, SCTP_FR_T3_MARKED); } if (chk->rec.data.chunk_was_revoked) { @@ -665,7 +659,7 @@ start_again: chk->whoTo->flight_size, chk->book_size, (uint32_t) (uintptr_t) chk->whoTo, - chk->rec.data.TSN_seq); + chk->rec.data.tsn); } sctp_flight_size_decrease(chk); sctp_total_flight_decrease(stcb, chk); @@ -695,7 +689,7 @@ start_again: if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { chk->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; } else { - chk->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq; + chk->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.tsn; } } /* @@ -793,7 +787,7 @@ start_again: chk->whoTo->flight_size, chk->book_size, (uint32_t) (uintptr_t) chk->whoTo, - chk->rec.data.TSN_seq); + chk->rec.data.tsn); } sctp_flight_size_increase(chk); sctp_total_flight_increase(stcb, chk); diff --git a/freebsd/sys/netinet/sctp_uio.h b/freebsd/sys/netinet/sctp_uio.h index e65b7b5e..d6055163 100644 --- a/freebsd/sys/netinet/sctp_uio.h +++ b/freebsd/sys/netinet/sctp_uio.h @@ -147,7 +147,6 @@ struct sctp_extrcvinfo { uint16_t sinfo_keynumber_valid; uint8_t __reserve_pad[SCTP_ALIGN_RESV_PAD_SHORT]; }; - #define sinfo_pr_value sinfo_timetolive #define sreinfo_next_flags serinfo_next_flags #define sreinfo_next_stream serinfo_next_stream @@ -573,7 +572,6 @@ struct sctp_paddrparams { uint16_t spp_pathmaxrxt; uint8_t spp_dscp; }; - #define spp_ipv4_tos spp_dscp #define SPP_HB_ENABLE 0x00000001 @@ -1284,7 +1282,6 @@ sctp_sorecvmsg(struct socket *so, int *msg_flags, struct sctp_sndrcvinfo *sinfo, int filling_sinfo); - #endif /* diff --git a/freebsd/sys/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c index 1cbb7076..e3e398d4 100644 --- a/freebsd/sys/netinet/sctp_usrreq.c +++ b/freebsd/sys/netinet/sctp_usrreq.c @@ -137,7 +137,7 @@ sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz) chk->whoTo->flight_size, chk->book_size, (uint32_t) (uintptr_t) chk->whoTo, - chk->rec.data.TSN_seq); + chk->rec.data.tsn); } /* Clear any time so NO RTT is being done */ chk->do_rtt = 0; @@ -158,7 +158,6 @@ sctp_notify(struct sctp_inpcb *inp, { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif int timer_stopped; @@ -346,7 +345,6 @@ sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip) } return; } - #endif static int @@ -979,10 +977,8 @@ sctp_shutdown(struct socket *so) } } sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, netp); - /* - * XXX: Why do this in the case where we have still data - * queued? - */ + /* XXX: Why do this in the case where we have still data + * queued? */ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED); SCTP_TCB_UNLOCK(stcb); SCTP_INP_RUNLOCK(inp); @@ -1023,14 +1019,11 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, struct sctp_ifa *sctp_ifa; size_t actual; int loopback_scope; - #if defined(INET) int ipv4_local_scope, ipv4_addr_legal; - #endif #if defined(INET6) int local_scope, site_scope, ipv6_addr_legal; - #endif struct sctp_vrf *vrf; @@ -1176,19 +1169,14 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, if (sin6->sin6_scope_id == 0) { if (sa6_recoverscope(sin6) != 0) /* - * + * * bad - * - * li - * nk - * - * loc - * al - * - * add - * re - * ss - * */ + * link + * + * local + * + * address + */ continue; } } @@ -1523,19 +1511,19 @@ out_now: stcb = LIST_FIRST(&inp->sctp_asoc_list); \ if (stcb) { \ SCTP_TCB_LOCK(stcb); \ - } \ + } \ SCTP_INP_RUNLOCK(inp); \ } else if (assoc_id > SCTP_ALL_ASSOC) { \ stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \ if (stcb == NULL) { \ - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \ + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \ error = ENOENT; \ break; \ } \ } else { \ stcb = NULL; \ - } \ - } + } \ +} #define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\ @@ -1546,7 +1534,7 @@ out_now: } else { \ destp = (type *)srcp; \ } \ - } +} static int sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, @@ -1825,10 +1813,8 @@ flags_out: } SCTP_TCB_UNLOCK(stcb); } else { - /* - * Can't get stream value without - * association - */ + /* Can't get stream value without + * association */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; } @@ -2328,10 +2314,8 @@ flags_out: struct sctp_paddrparams *paddrp; struct sctp_nets *net; struct sockaddr *addr; - #if defined(INET) && defined(INET6) struct sockaddr_in sin_store; - #endif SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize); @@ -2531,10 +2515,8 @@ flags_out: struct sctp_paddrinfo *paddri; struct sctp_nets *net; struct sockaddr *addr; - #if defined(INET) && defined(INET6) struct sockaddr_in sin_store; - #endif SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize); @@ -3200,10 +3182,8 @@ flags_out: struct sctp_paddrthlds *thlds; struct sctp_nets *net; struct sockaddr *addr; - #if defined(INET) && defined(INET6) struct sockaddr_in sin_store; - #endif SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize); @@ -3314,10 +3294,8 @@ flags_out: struct sctp_udpencaps *encaps; struct sctp_nets *net; struct sockaddr *addr; - #if defined(INET) && defined(INET6) struct sockaddr_in sin_store; - #endif SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize); @@ -3911,12 +3889,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS))) { inp->idata_supported = 1; } else { - /* - * Must have Frag + /* Must have Frag * interleave and * stream interleave - * on - */ + * on */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; } @@ -4127,10 +4103,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } SCTP_INP_RUNLOCK(inp); } else { - /* - * Can't set stream value without - * association - */ + /* Can't set stream value without + * association */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; } @@ -4360,10 +4334,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { SCTP_TCB_LOCK(stcb); shared_keys = &stcb->asoc.shared_keys; - /* - * clear the cached keys for - * this key id - */ + /* clear the cached keys for + * this key id */ sctp_clear_cachedkeys(stcb, sca->sca_keynumber); /* * create the new shared key @@ -4762,10 +4734,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, int cnt; addstream |= 2; - /* - * We allocate inside - * sctp_send_str_reset_req() - */ + /* We allocate inside + * sctp_send_str_reset_req() */ add_i_strmcnt = stradd->sas_instrms; cnt = add_i_strmcnt; cnt += stcb->asoc.streamincnt; @@ -4813,10 +4783,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_TCB_UNLOCK(stcb); break; } - /* - * Is there any data pending in the send or sent - * queues? - */ + /* Is there any data pending in the send or sent + * queues? */ if (!TAILQ_EMPTY(&stcb->asoc.send_queue) || !TAILQ_EMPTY(&stcb->asoc.sent_queue)) { busy_out: @@ -4962,10 +4930,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || (av->assoc_id == SCTP_FUTURE_ASSOC)) { SCTP_INP_WLOCK(inp); - /* - * FIXME MT: I think this is not in - * tune with the API ID - */ + /* FIXME MT: I think this is not in + * tune with the API ID */ if (av->assoc_value) { inp->sctp_frag_point = (av->assoc_value + ovh); } else { @@ -5108,10 +5074,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } SCTP_TCB_UNLOCK(stcb); } - /* - * Send up the sender dry event only for 1-to-1 - * style sockets. - */ + /* Send up the sender dry event only for 1-to-1 + * style sockets. */ if (events->sctp_sender_dry_event) { if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { @@ -5197,10 +5161,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, struct sctp_paddrparams *paddrp; struct sctp_nets *net; struct sockaddr *addr; - #if defined(INET) && defined(INET6) struct sockaddr_in sin_store; - #endif SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize); @@ -5701,10 +5663,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, struct sctp_setprim *spa; struct sctp_nets *net; struct sockaddr *addr; - #if defined(INET) && defined(INET6) struct sockaddr_in sin_store; - #endif SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize); @@ -5793,10 +5753,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, { struct sctp_setpeerprim *sspp; struct sockaddr *addr; - #if defined(INET) && defined(INET6) struct sockaddr_in sin_store; - #endif SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize); @@ -5828,10 +5786,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, goto out_of_it; } if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { - /* - * Must validate the ifa found is in - * our ep - */ + /* Must validate the ifa found is in + * our ep */ struct sctp_laddr *laddr; int found = 0; @@ -6246,10 +6202,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, struct sctp_paddrthlds *thlds; struct sctp_nets *net; struct sockaddr *addr; - #if defined(INET) && defined(INET6) struct sockaddr_in sin_store; - #endif SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize); @@ -6417,10 +6371,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, struct sctp_udpencaps *encaps; struct sctp_nets *net; struct sockaddr *addr; - #if defined(INET) && defined(INET6) struct sockaddr_in sin_store; - #endif SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize); @@ -6591,10 +6543,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (av->assoc_id == SCTP_FUTURE_ASSOC)) { if ((av->assoc_value == 0) && (inp->asconf_supported == 1)) { - /* - * AUTH is required for - * ASCONF - */ + /* AUTH is required for + * ASCONF */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; } else { @@ -6630,10 +6580,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (av->assoc_id == SCTP_FUTURE_ASSOC)) { if ((av->assoc_value != 0) && (inp->auth_supported == 0)) { - /* - * AUTH is required for - * ASCONF - */ + /* AUTH is required for + * ASCONF */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; } else { @@ -7012,7 +6960,6 @@ out_now: SCTP_INP_DECR_REF(inp); return (error); } - #endif int @@ -7066,10 +7013,8 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && (tinp->sctp_socket->so_qlimit)) { - /* - * we have a listener already and - * its not this inp. - */ + /* we have a listener already and + * its not this inp. */ SCTP_INP_DECR_REF(tinp); return (EADDRINUSE); } else if (tinp) { @@ -7110,10 +7055,8 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && (tinp->sctp_socket->so_qlimit)) { - /* - * we have a listener already and its not - * this inp. - */ + /* we have a listener already and its not + * this inp. */ SCTP_INP_DECR_REF(tinp); return (EADDRINUSE); } else if (tinp) { @@ -7186,10 +7129,8 @@ sctp_accept(struct socket *so, struct sockaddr **addr) struct sctp_tcb *stcb; struct sctp_inpcb *inp; union sctp_sockstore store; - #ifdef INET6 int error; - #endif inp = (struct sctp_inpcb *)so->so_pcb; @@ -7472,5 +7413,4 @@ struct pr_usrreqs sctp_usrreqs = { .pru_sosend = sctp_sosend, .pru_soreceive = sctp_soreceive }; - #endif diff --git a/freebsd/sys/netinet/sctp_var.h b/freebsd/sys/netinet/sctp_var.h index a4d2b998..6365dfec 100644 --- a/freebsd/sys/netinet/sctp_var.h +++ b/freebsd/sys/netinet/sctp_var.h @@ -267,7 +267,7 @@ extern struct pr_usrreqs sctp_usrreqs; if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \ stcb->asoc.fs_index = 0;\ stcb->asoc.fslog[stcb->asoc.fs_index].total_flight = stcb->asoc.total_flight; \ - stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.TSN_seq; \ + stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.tsn; \ stcb->asoc.fslog[stcb->asoc.fs_index].book = tp1->book_size; \ stcb->asoc.fslog[stcb->asoc.fs_index].sent = tp1->sent; \ stcb->asoc.fslog[stcb->asoc.fs_index].incr = 0; \ @@ -288,7 +288,7 @@ extern struct pr_usrreqs sctp_usrreqs; if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \ stcb->asoc.fs_index = 0;\ stcb->asoc.fslog[stcb->asoc.fs_index].total_flight = stcb->asoc.total_flight; \ - stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.TSN_seq; \ + stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.tsn; \ stcb->asoc.fslog[stcb->asoc.fs_index].book = tp1->book_size; \ stcb->asoc.fslog[stcb->asoc.fs_index].sent = tp1->sent; \ stcb->asoc.fslog[stcb->asoc.fs_index].incr = 1; \ @@ -332,11 +332,9 @@ void sctp_close(struct socket *so); int sctp_disconnect(struct socket *so); void sctp_ctlinput(int, struct sockaddr *, void *); int sctp_ctloutput(struct socket *, struct sockopt *); - #ifdef INET void sctp_input_with_port(struct mbuf *, int, uint16_t); int sctp_input(struct mbuf **, int *, int); - #endif void sctp_pathmtu_adjustment(struct sctp_tcb *, uint16_t); void sctp_drain(void); diff --git a/freebsd/sys/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c index 36a9c2ce..136b4bb6 100644 --- a/freebsd/sys/netinet/sctputil.c +++ b/freebsd/sys/netinet/sctputil.c @@ -257,7 +257,6 @@ sctp_log_mbc(struct mbuf *m, int from) sctp_log_mb(mat, from); } } - #endif void @@ -271,11 +270,11 @@ sctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_rea } sctp_clog.x.strlog.stcb = control->stcb; sctp_clog.x.strlog.n_tsn = control->sinfo_tsn; - sctp_clog.x.strlog.n_sseq = control->sinfo_ssn; + sctp_clog.x.strlog.n_sseq = (uint16_t) control->mid; sctp_clog.x.strlog.strm = control->sinfo_stream; if (poschk != NULL) { sctp_clog.x.strlog.e_tsn = poschk->sinfo_tsn; - sctp_clog.x.strlog.e_sseq = poschk->sinfo_ssn; + sctp_clog.x.strlog.e_sseq = (uint16_t) poschk->mid; } else { sctp_clog.x.strlog.e_tsn = 0; sctp_clog.x.strlog.e_sseq = 0; @@ -449,7 +448,6 @@ sctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mb sctp_clog.x.misc.log3, sctp_clog.x.misc.log4); } - #endif void @@ -959,10 +957,8 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * caller in the sctp_aloc_assoc() function. */ int i; - #if defined(SCTP_DETAILED_STR_STATS) int j; - #endif asoc = &stcb->asoc; @@ -1137,7 +1133,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, asoc->strmout[i].abandoned_sent[0] = 0; asoc->strmout[i].abandoned_unsent[0] = 0; #endif - asoc->strmout[i].stream_no = i; + asoc->strmout[i].sid = i; asoc->strmout[i].last_msg_incomplete = 0; asoc->strmout[i].state = SCTP_STREAM_OPENING; asoc->ss_functions.sctp_ss_init_stream(stcb, &asoc->strmout[i], NULL); @@ -1488,10 +1484,8 @@ sctp_handle_addr_wq(void) sctp_asconf_iterator_end, NULL, 0); if (ret) { SCTP_PRINTF("Failed to initiate iterator for handle_addr_wq\n"); - /* - * Freeing if we are stopping or put back on the - * addr_wq. - */ + /* Freeing if we are stopping or put back on the + * addr_wq. */ if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) { sctp_asconf_iterator_end(asc, 0); } else { @@ -1514,10 +1508,8 @@ sctp_timeout_handler(void *t) struct sctp_nets *net; struct sctp_timer *tmr; struct mbuf *op_err; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif int did_output; int type; @@ -2493,10 +2485,8 @@ sctp_calculate_rto(struct sctp_tcb *stcb, /* compute rtt in ms */ rtt = (int32_t) (net->rtt / 1000); if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) { - /* - * Tell the CC module that a new update has just occurred - * from a sack - */ + /* Tell the CC module that a new update has just occurred + * from a sack */ (*asoc->cc_functions.sctp_rtt_calculated) (stcb, net, &now); } /* @@ -2688,10 +2678,8 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, unsigned int notif_len; uint16_t abort_len; unsigned int i; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif if (stcb == NULL) { @@ -2989,9 +2977,9 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error, ssfe->ssfe_length = (uint32_t) (notifhdr_len + payload_len); ssfe->ssfe_error = error; /* not exactly what the user sent in, but should be close :) */ - ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number; + ssfe->ssfe_info.snd_sid = chk->rec.data.sid; ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags; - ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype; + ssfe->ssfe_info.snd_ppid = chk->rec.data.ppid; ssfe->ssfe_info.snd_context = chk->rec.data.context; ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb); ssfe->ssfe_assoc_id = sctp_get_associd(stcb); @@ -3007,10 +2995,10 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error, ssf->ssf_length = (uint32_t) (notifhdr_len + payload_len); ssf->ssf_error = error; /* not exactly what the user sent in, but should be close :) */ - ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number; - ssf->ssf_info.sinfo_ssn = (uint16_t) chk->rec.data.stream_seq; + ssf->ssf_info.sinfo_stream = chk->rec.data.sid; + ssf->ssf_info.sinfo_ssn = (uint16_t) chk->rec.data.mid; ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags; - ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype; + ssf->ssf_info.sinfo_ppid = chk->rec.data.ppid; ssf->ssf_info.sinfo_context = chk->rec.data.context; ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb); ssf->ssf_assoc_id = sctp_get_associd(stcb); @@ -3093,7 +3081,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, ssfe->ssfe_length = (uint32_t) (notifhdr_len + sp->length); ssfe->ssfe_error = error; /* not exactly what the user sent in, but should be close :) */ - ssfe->ssfe_info.snd_sid = sp->stream; + ssfe->ssfe_info.snd_sid = sp->sid; if (sp->some_taken) { ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG; } else { @@ -3111,7 +3099,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, ssf->ssf_length = (uint32_t) (notifhdr_len + sp->length); ssf->ssf_error = error; /* not exactly what the user sent in, but should be close :) */ - ssf->ssf_info.sinfo_stream = sp->stream; + ssf->ssf_info.sinfo_stream = sp->sid; ssf->ssf_info.sinfo_ssn = 0; if (sp->some_taken) { ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG; @@ -3861,11 +3849,11 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); asoc->sent_queue_cnt--; if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { - if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { - asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; + if (asoc->strmout[chk->rec.data.sid].chunks_on_queues > 0) { + asoc->strmout[chk->rec.data.sid].chunks_on_queues--; #ifdef INVARIANTS } else { - panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); + panic("No chunks on the queues for sid %u.", chk->rec.data.sid); #endif } } @@ -3885,11 +3873,11 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); asoc->send_queue_cnt--; - if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { - asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; + if (asoc->strmout[chk->rec.data.sid].chunks_on_queues > 0) { + asoc->strmout[chk->rec.data.sid].chunks_on_queues--; #ifdef INVARIANTS } else { - panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); + panic("No chunks on the queues for sid %u.", chk->rec.data.sid); #endif } if (chk->data != NULL) { @@ -3977,25 +3965,22 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint32_t vrf_id, uint16_t port) { uint32_t vtag; - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif vtag = 0; if (stcb != NULL) { - /* We have a TCB to abort, send notification too */ vtag = stcb->asoc.peer_vtag; - sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); - /* get the assoc vrf id and table id */ vrf_id = stcb->asoc.vrf_id; - stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; } sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err, mflowtype, mflowid, inp->fibnum, vrf_id, port); if (stcb != NULL) { + /* We have a TCB to abort, send notification too */ + sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); + stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; /* Ok, now lets free it */ #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) so = SCTP_INP_SO(inp); @@ -4017,7 +4002,6 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, #endif } } - #ifdef SCTP_ASOCLOG_OF_TSNS void sctp_print_out_track_log(struct sctp_tcb *stcb) @@ -4079,7 +4063,6 @@ none_in: } #endif } - #endif void @@ -4093,7 +4076,6 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) @@ -4111,10 +4093,6 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } else { stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; } - /* notify the ulp */ - if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { - sctp_abort_notification(stcb, 0, 0, NULL, so_locked); - } /* notify the peer */ sctp_send_abort_tcb(stcb, op_err, so_locked); SCTP_STAT_INCR_COUNTER32(sctps_aborted); @@ -4122,6 +4100,10 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } + /* notify the ulp */ + if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { + sctp_abort_notification(stcb, 0, 0, NULL, so_locked); + } /* now free the asoc */ #ifdef SCTP_ASOCLOG_OF_TSNS sctp_print_out_track_log(stcb); @@ -4305,7 +4287,6 @@ sctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store) } return (addr); } - #endif /* @@ -4359,7 +4340,6 @@ sctp_print_address(struct sockaddr *sa) { #ifdef INET6 char ip6buf[INET6_ADDRSTRLEN]; - #endif switch (sa->sa_family) { @@ -4712,25 +4692,26 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, struct sctp_stream_out *strq; struct sctp_tmit_chunk *chk = NULL, *tp2; struct sctp_stream_queue_pending *sp; - uint16_t stream = 0, seq = 0; + uint32_t mid; + uint16_t sid; uint8_t foundeom = 0; int ret_sz = 0; int notdone; int do_wakeup_routine = 0; - stream = tp1->rec.data.stream_number; - seq = tp1->rec.data.stream_seq; + sid = tp1->rec.data.sid; + mid = tp1->rec.data.mid; if (sent || !(tp1->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) { stcb->asoc.abandoned_sent[0]++; stcb->asoc.abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++; - stcb->asoc.strmout[stream].abandoned_sent[0]++; + stcb->asoc.strmout[sid].abandoned_sent[0]++; #if defined(SCTP_DETAILED_STR_STATS) stcb->asoc.strmout[stream].abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++; #endif } else { stcb->asoc.abandoned_unsent[0]++; stcb->asoc.abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++; - stcb->asoc.strmout[stream].abandoned_unsent[0]++; + stcb->asoc.strmout[sid].abandoned_unsent[0]++; #if defined(SCTP_DETAILED_STR_STATS) stcb->asoc.strmout[stream].abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++; #endif @@ -4784,8 +4765,8 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, * sent queue. */ TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) { - if ((tp1->rec.data.stream_number != stream) || - (tp1->rec.data.stream_seq != seq)) { + if ((tp1->rec.data.sid != sid) || + (!SCTP_MID_EQ(stcb->asoc.idata_supported, tp1->rec.data.mid, mid))) { break; } /* @@ -4813,10 +4794,8 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, do_wakeup_routine = 1; tp1->sent = SCTP_FORWARD_TSN_SKIP; TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next); - /* - * on to the sent queue so we can wait for it to be - * passed by. - */ + /* on to the sent queue so we can wait for it to be + * passed by. */ TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1, sctp_next); stcb->asoc.send_queue_cnt--; @@ -4829,7 +4808,7 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, * stream out queue.. yuck. */ SCTP_TCB_SEND_LOCK(stcb); - strq = &stcb->asoc.strmout[stream]; + strq = &stcb->asoc.strmout[sid]; sp = TAILQ_FIRST(&strq->outqueue); if (sp != NULL) { sp->discard_rest = 1; @@ -4856,23 +4835,23 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, chk->asoc = &stcb->asoc; if (stcb->asoc.idata_supported == 0) { if (sp->sinfo_flags & SCTP_UNORDERED) { - chk->rec.data.stream_seq = 0; + chk->rec.data.mid = 0; } else { - chk->rec.data.stream_seq = strq->next_mid_ordered; + chk->rec.data.mid = strq->next_mid_ordered; } } else { if (sp->sinfo_flags & SCTP_UNORDERED) { - chk->rec.data.stream_seq = strq->next_mid_unordered; + chk->rec.data.mid = strq->next_mid_unordered; } else { - chk->rec.data.stream_seq = strq->next_mid_ordered; + chk->rec.data.mid = strq->next_mid_ordered; } } - chk->rec.data.stream_number = sp->stream; - chk->rec.data.payloadtype = sp->ppid; + chk->rec.data.sid = sp->sid; + chk->rec.data.ppid = sp->ppid; chk->rec.data.context = sp->context; chk->flags = sp->act_flags; chk->whoTo = NULL; - chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1); + chk->rec.data.tsn = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1); strq->chunks_on_queues++; TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next); stcb->asoc.sent_queue_cnt++; @@ -5190,7 +5169,7 @@ sctp_sorecvmsg(struct socket *so, * mp=NULL thus uio is the copy method to userland) MSG_WAITALL - ?? * On the way out we may send out any combination of: * MSG_NOTIFICATION MSG_EOR - * + * */ struct sctp_inpcb *inp = NULL; int my_len = 0; @@ -5309,10 +5288,8 @@ restart_nosblocks: * connect. */ if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) { - /* - * You were aborted, passive side - * always hits here - */ + /* You were aborted, passive side + * always hits here */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); error = ECONNRESET; } @@ -5411,10 +5388,8 @@ restart_nosblocks: } if ((control->length == 0) && (control->end_added == 1)) { - /* - * Do we also need to check for (control->pdapi_aborted == - * 1)? - */ + /* Do we also need to check for (control->pdapi_aborted == + * 1)? */ if (hold_rlock == 0) { hold_rlock = 1; SCTP_INP_READ_LOCK(inp); @@ -5555,7 +5530,7 @@ found_one: /* First lets get off the sinfo and sockaddr info */ if ((sinfo != NULL) && (filling_sinfo != 0)) { sinfo->sinfo_stream = control->sinfo_stream; - sinfo->sinfo_ssn = (uint16_t) control->sinfo_ssn; + sinfo->sinfo_ssn = (uint16_t) control->mid; sinfo->sinfo_flags = control->sinfo_flags; sinfo->sinfo_ppid = control->sinfo_ppid; sinfo->sinfo_context = control->sinfo_context; @@ -5631,7 +5606,7 @@ found_one: entry = &inp->readlog[index]; entry->vtag = control->sinfo_assoc_id; entry->strm = control->sinfo_stream; - entry->seq = control->sinfo_ssn; + entry->seq = (uint16_t) control->mid; entry->sz = control->length; entry->flgs = control->sinfo_flags; } @@ -5757,10 +5732,8 @@ get_more_data: atomic_subtract_int(&control->length, cp_len); control->data = sctp_m_free(m); m = control->data; - /* - * been through it all, must hold sb - * lock ok to null tail - */ + /* been through it all, must hold sb + * lock ok to null tail */ if (control->data == NULL) { #ifdef INVARIANTS if ((control->end_added == 0) || @@ -5979,10 +5952,8 @@ wait_some_more: */ SCTP_INP_READ_LOCK(inp); if ((control->length > 0) && (control->data == NULL)) { - /* - * big trouble.. we have the lock and its - * corrupt? - */ + /* big trouble.. we have the lock and its + * corrupt? */ #ifdef INVARIANTS panic("Impossible data==NULL length !=0"); #endif @@ -6273,14 +6244,11 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, struct sctp_inpcb *inp; struct sockaddr *sa; size_t incr = 0; - #ifdef INET struct sockaddr_in *sin; - #endif #ifdef INET6 struct sockaddr_in6 *sin6; - #endif sa = addr; @@ -6402,6 +6370,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr, #endif default: *totaddr = i; + incr = 0; /* we are done */ break; } @@ -6435,10 +6404,8 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp, uint32_t vrf_id, int *error, void *p) { struct sockaddr *addr_touse; - #if defined(INET) && defined(INET6) struct sockaddr_in sin; - #endif /* see if we're bound all already! */ @@ -6567,10 +6534,8 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp, uint32_t vrf_id, int *error) { struct sockaddr *addr_touse; - #if defined(INET) && defined(INET6) struct sockaddr_in sin; - #endif /* see if we're bound all already! */ @@ -6584,7 +6549,6 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp, if (sa->sa_family == AF_INET6) { #ifdef INET struct sockaddr_in6 *sin6; - #endif if (sa->sa_len != sizeof(struct sockaddr_in6)) { @@ -6655,14 +6619,11 @@ int sctp_local_addr_count(struct sctp_tcb *stcb) { int loopback_scope; - #if defined(INET) int ipv4_local_scope, ipv4_addr_legal; - #endif #if defined (INET6) int local_scope, site_scope, ipv6_addr_legal; - #endif struct sctp_vrf *vrf; struct sctp_ifn *sctp_ifn; @@ -6707,10 +6668,8 @@ sctp_local_addr_count(struct sctp_tcb *stcb) sin = &sctp_ifa->address.sin; if (sin->sin_addr.s_addr == 0) { - /* - * skip unspecified - * addrs - */ + /* skip unspecified + * addrs */ continue; } if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, @@ -6747,19 +6706,14 @@ sctp_local_addr_count(struct sctp_tcb *stcb) if (sin6->sin6_scope_id == 0) { if (sa6_recoverscope(sin6) != 0) /* - * + * * bad - * - * li - * nk - * - * loc - * al - * - * add - * re - * ss - * */ + * link + * + * local + * + * address + */ continue; } } @@ -6831,10 +6785,8 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp, const struct sockaddr *sa SCTP_UNUSED, void *ctx SCTP_UNUSED) { struct ip *iph; - #ifdef INET6 struct ip6_hdr *ip6; - #endif struct mbuf *sp, *last; struct udphdr *uhdr; @@ -7019,7 +6971,6 @@ sctp_recv_icmp_tunneled_packet(int cmd, struct sockaddr *sa, void *vip, void *ct } return; } - #endif #ifdef INET6 @@ -7161,7 +7112,6 @@ sctp_recv_icmp6_tunneled_packet(int cmd, struct sockaddr *sa, void *d, void *ctx } } } - #endif void @@ -7190,14 +7140,11 @@ sctp_over_udp_start(void) { uint16_t port; int ret; - #ifdef INET struct sockaddr_in sin; - #endif #ifdef INET6 struct sockaddr_in6 sin6; - #endif /* * This function assumes sysctl caller holds sctp_sysctl_info_lock() diff --git a/freebsd/sys/netinet/sctputil.h b/freebsd/sys/netinet/sctputil.h index 292068af..a3a4f3c6 100644 --- a/freebsd/sys/netinet/sctputil.h +++ b/freebsd/sys/netinet/sctputil.h @@ -43,13 +43,11 @@ __FBSDID("$FreeBSD$"); #ifdef SCTP_ASOCLOG_OF_TSNS void sctp_print_out_track_log(struct sctp_tcb *stcb); - #endif #ifdef SCTP_MBUF_LOGGING struct mbuf *sctp_m_free(struct mbuf *m); void sctp_m_freem(struct mbuf *m); - #else #define sctp_m_free m_free #define sctp_m_freem m_freem @@ -58,7 +56,6 @@ void sctp_m_freem(struct mbuf *m); #if defined(SCTP_LOCAL_TRACE_BUF) || defined(__APPLE__) void sctp_log_trace(uint32_t fr, const char *str SCTP_UNUSED, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f); - #endif #define sctp_get_associd(stcb) ((sctp_assoc_t)stcb->asoc.assoc_id) @@ -222,7 +219,6 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr, int *error, unsigned int limit, int *bad_addr); int sctp_is_there_an_abort_here(struct mbuf *, int, uint32_t *); - #ifdef INET6 uint32_t sctp_is_same_scope(struct sockaddr_in6 *, struct sockaddr_in6 *); @@ -357,7 +353,6 @@ void void sctp_log_mbc(struct mbuf *m, int from); - #endif void diff --git a/freebsd/sys/netinet/tcp_debug.c b/freebsd/sys/netinet/tcp_debug.c index c5f74182..707e7c5d 100644 --- a/freebsd/sys/netinet/tcp_debug.c +++ b/freebsd/sys/netinet/tcp_debug.c @@ -217,9 +217,9 @@ tcp_trace(short act, short ostate, struct tcpcb *tp, void *ipgen, return; printf( "\trcv_(nxt,wnd,up) (%lx,%lx,%lx) snd_(una,nxt,max) (%lx,%lx,%lx)\n", - (u_long)tp->rcv_nxt, tp->rcv_wnd, (u_long)tp->rcv_up, + (u_long)tp->rcv_nxt, (u_long)tp->rcv_wnd, (u_long)tp->rcv_up, (u_long)tp->snd_una, (u_long)tp->snd_nxt, (u_long)tp->snd_max); printf("\tsnd_(wl1,wl2,wnd) (%lx,%lx,%lx)\n", - (u_long)tp->snd_wl1, (u_long)tp->snd_wl2, tp->snd_wnd); + (u_long)tp->snd_wl1, (u_long)tp->snd_wl2, (u_long)tp->snd_wnd); #endif /* TCPDEBUG */ } diff --git a/freebsd/sys/netinet/tcp_fsm.h b/freebsd/sys/netinet/tcp_fsm.h index 61fd0c1f..5423e1f1 100644 --- a/freebsd/sys/netinet/tcp_fsm.h +++ b/freebsd/sys/netinet/tcp_fsm.h @@ -73,7 +73,8 @@ #define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED) #define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED) -#define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT) +#define TCPS_HAVERCVDFIN(s) \ + ((s) == TCPS_CLOSE_WAIT || ((s) >= TCPS_CLOSING && (s) != TCPS_FIN_WAIT_2)) #ifdef TCPOUTFLAGS /* diff --git a/freebsd/sys/netinet/tcp_hostcache.c b/freebsd/sys/netinet/tcp_hostcache.c index 4e78b8b2..e0c4b493 100644 --- a/freebsd/sys/netinet/tcp_hostcache.c +++ b/freebsd/sys/netinet/tcp_hostcache.c @@ -126,6 +126,12 @@ static void tcp_hc_purge(void *); static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, hostcache, CTLFLAG_RW, 0, "TCP Host cache"); +VNET_DEFINE(int, tcp_use_hostcache) = 1; +#define V_tcp_use_hostcache VNET(tcp_use_hostcache) +SYSCTL_INT(_net_inet_tcp_hostcache, OID_AUTO, enable, CTLFLAG_VNET | CTLFLAG_RW, + &VNET_NAME(tcp_use_hostcache), 0, + "Enable the TCP hostcache"); + SYSCTL_UINT(_net_inet_tcp_hostcache, OID_AUTO, cachelimit, CTLFLAG_VNET | CTLFLAG_RDTUN, &VNET_NAME(tcp_hostcache.cache_limit), 0, "Overall entry limit for hostcache"); @@ -278,6 +284,9 @@ tcp_hc_lookup(struct in_conninfo *inc) struct hc_head *hc_head; struct hc_metrics *hc_entry; + if (!V_tcp_use_hostcache) + return NULL; + KASSERT(inc != NULL, ("tcp_hc_lookup with NULL in_conninfo pointer")); /* @@ -334,6 +343,9 @@ tcp_hc_insert(struct in_conninfo *inc) struct hc_head *hc_head; struct hc_metrics *hc_entry; + if (!V_tcp_use_hostcache) + return NULL; + KASSERT(inc != NULL, ("tcp_hc_insert with NULL in_conninfo pointer")); /* @@ -423,6 +435,9 @@ tcp_hc_get(struct in_conninfo *inc, struct hc_metrics_lite *hc_metrics_lite) { struct hc_metrics *hc_entry; + if (!V_tcp_use_hostcache) + return; + /* * Find the right bucket. */ @@ -454,14 +469,17 @@ tcp_hc_get(struct in_conninfo *inc, struct hc_metrics_lite *hc_metrics_lite) /* * External function: look up an entry in the hostcache and return the - * discovered path MTU. Returns NULL if no entry is found or value is not + * discovered path MTU. Returns 0 if no entry is found or value is not * set. */ -u_long +uint32_t tcp_hc_getmtu(struct in_conninfo *inc) { struct hc_metrics *hc_entry; - u_long mtu; + uint32_t mtu; + + if (!V_tcp_use_hostcache) + return 0; hc_entry = tcp_hc_lookup(inc); if (hc_entry == NULL) { @@ -480,10 +498,13 @@ tcp_hc_getmtu(struct in_conninfo *inc) * Creates a new entry if none was found. */ void -tcp_hc_updatemtu(struct in_conninfo *inc, u_long mtu) +tcp_hc_updatemtu(struct in_conninfo *inc, uint32_t mtu) { struct hc_metrics *hc_entry; + if (!V_tcp_use_hostcache) + return; + /* * Find the right bucket. */ @@ -523,6 +544,9 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml) { struct hc_metrics *hc_entry; + if (!V_tcp_use_hostcache) + return; + hc_entry = tcp_hc_lookup(inc); if (hc_entry == NULL) { hc_entry = tcp_hc_insert(inc); @@ -536,16 +560,16 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml) if (hc_entry->rmx_rtt == 0) hc_entry->rmx_rtt = hcml->rmx_rtt; else - hc_entry->rmx_rtt = - (hc_entry->rmx_rtt + hcml->rmx_rtt) / 2; + hc_entry->rmx_rtt = ((uint64_t)hc_entry->rmx_rtt + + (uint64_t)hcml->rmx_rtt) / 2; TCPSTAT_INC(tcps_cachedrtt); } if (hcml->rmx_rttvar != 0) { if (hc_entry->rmx_rttvar == 0) hc_entry->rmx_rttvar = hcml->rmx_rttvar; else - hc_entry->rmx_rttvar = - (hc_entry->rmx_rttvar + hcml->rmx_rttvar) / 2; + hc_entry->rmx_rttvar = ((uint64_t)hc_entry->rmx_rttvar + + (uint64_t)hcml->rmx_rttvar) / 2; TCPSTAT_INC(tcps_cachedrttvar); } if (hcml->rmx_ssthresh != 0) { @@ -560,8 +584,8 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml) if (hc_entry->rmx_cwnd == 0) hc_entry->rmx_cwnd = hcml->rmx_cwnd; else - hc_entry->rmx_cwnd = - (hc_entry->rmx_cwnd + hcml->rmx_cwnd) / 2; + hc_entry->rmx_cwnd = ((uint64_t)hc_entry->rmx_cwnd + + (uint64_t)hcml->rmx_cwnd) / 2; /* TCPSTAT_INC(tcps_cachedcwnd); */ } if (hcml->rmx_sendpipe != 0) { @@ -569,7 +593,8 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml) hc_entry->rmx_sendpipe = hcml->rmx_sendpipe; else hc_entry->rmx_sendpipe = - (hc_entry->rmx_sendpipe + hcml->rmx_sendpipe) /2; + ((uint64_t)hc_entry->rmx_sendpipe + + (uint64_t)hcml->rmx_sendpipe) /2; /* TCPSTAT_INC(tcps_cachedsendpipe); */ } if (hcml->rmx_recvpipe != 0) { @@ -577,7 +602,8 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml) hc_entry->rmx_recvpipe = hcml->rmx_recvpipe; else hc_entry->rmx_recvpipe = - (hc_entry->rmx_recvpipe + hcml->rmx_recvpipe) /2; + ((uint64_t)hc_entry->rmx_recvpipe + + (uint64_t)hcml->rmx_recvpipe) /2; /* TCPSTAT_INC(tcps_cachedrecvpipe); */ } @@ -614,7 +640,7 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS) TAILQ_FOREACH(hc_entry, &V_tcp_hostcache.hashbase[i].hch_bucket, rmx_q) { sbuf_printf(&sb, - "%-15s %5lu %8lu %6lums %6lums %8lu %8lu %8lu %4lu " + "%-15s %5u %8u %6lums %6lums %8u %8u %8u %4lu " "%4lu %4i\n", hc_entry->ip4.s_addr ? inet_ntoa(hc_entry->ip4) : #ifdef INET6 @@ -624,9 +650,9 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS) #endif hc_entry->rmx_mtu, hc_entry->rmx_ssthresh, - msec(hc_entry->rmx_rtt * + msec((u_long)hc_entry->rmx_rtt * (RTM_RTTUNIT / (hz * TCP_RTT_SCALE))), - msec(hc_entry->rmx_rttvar * + msec((u_long)hc_entry->rmx_rttvar * (RTM_RTTUNIT / (hz * TCP_RTTVAR_SCALE))), hc_entry->rmx_cwnd, hc_entry->rmx_sendpipe, diff --git a/freebsd/sys/netinet/tcp_hostcache.h b/freebsd/sys/netinet/tcp_hostcache.h index 44875ff6..23a0c673 100644 --- a/freebsd/sys/netinet/tcp_hostcache.h +++ b/freebsd/sys/netinet/tcp_hostcache.h @@ -48,22 +48,22 @@ struct hc_head { struct hc_metrics { /* housekeeping */ TAILQ_ENTRY(hc_metrics) rmx_q; - struct hc_head *rmx_head; /* head of bucket tail queue */ - struct in_addr ip4; /* IP address */ - struct in6_addr ip6; /* IP6 address */ - uint32_t ip6_zoneid; /* IPv6 scope zone id */ + struct hc_head *rmx_head; /* head of bucket tail queue */ + struct in_addr ip4; /* IP address */ + struct in6_addr ip6; /* IP6 address */ + uint32_t ip6_zoneid; /* IPv6 scope zone id */ /* endpoint specific values for tcp */ - u_long rmx_mtu; /* MTU for this path */ - u_long rmx_ssthresh; /* outbound gateway buffer limit */ - u_long rmx_rtt; /* estimated round trip time */ - u_long rmx_rttvar; /* estimated rtt variance */ - u_long rmx_cwnd; /* congestion window */ - u_long rmx_sendpipe; /* outbound delay-bandwidth product */ - u_long rmx_recvpipe; /* inbound delay-bandwidth product */ + uint32_t rmx_mtu; /* MTU for this path */ + uint32_t rmx_ssthresh; /* outbound gateway buffer limit */ + uint32_t rmx_rtt; /* estimated round trip time */ + uint32_t rmx_rttvar; /* estimated rtt variance */ + uint32_t rmx_cwnd; /* congestion window */ + uint32_t rmx_sendpipe; /* outbound delay-bandwidth product */ + uint32_t rmx_recvpipe; /* inbound delay-bandwidth product */ /* TCP hostcache internal data */ - int rmx_expire; /* lifetime for object */ - u_long rmx_hits; /* number of hits */ - u_long rmx_updates; /* number of updates */ + int rmx_expire; /* lifetime for object */ + u_long rmx_hits; /* number of hits */ + u_long rmx_updates; /* number of updates */ }; struct tcp_hostcache { diff --git a/freebsd/sys/netinet/tcp_input.c b/freebsd/sys/netinet/tcp_input.c index eaa3eb3d..7e07fc0a 100644 --- a/freebsd/sys/netinet/tcp_input.c +++ b/freebsd/sys/netinet/tcp_input.c @@ -59,7 +59,9 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef TCP_HHOOK #include +#endif #include #include #include /* for proc0 declaration */ @@ -280,6 +282,7 @@ kmod_tcpstat_inc(int statnum) counter_u64_add(VNET(tcpstat)[statnum], 1); } +#ifdef TCP_HHOOK /* * Wrapper for the TCP established input helper hook. */ @@ -297,15 +300,18 @@ hhook_run_tcp_est_in(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to) tp->osd); } } +#endif /* * CC wrapper hook functions */ void -cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t type) +cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t nsegs, + uint16_t type) { INP_WLOCK_ASSERT(tp->t_inpcb); + tp->ccv->nsegs = nsegs; tp->ccv->bytes_this_ack = BYTES_THIS_ACK(tp, th); if (tp->snd_cwnd <= tp->snd_wnd) tp->ccv->flags |= CCF_CWND_LIMITED; @@ -315,7 +321,7 @@ cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t type) if (type == CC_ACK) { if (tp->snd_cwnd > tp->snd_ssthresh) { tp->t_bytes_acked += min(tp->ccv->bytes_this_ack, - V_tcp_abc_l_var * tcp_maxseg(tp)); + nsegs * V_tcp_abc_l_var * tcp_maxseg(tp)); if (tp->t_bytes_acked >= tp->snd_cwnd) { tp->t_bytes_acked -= tp->snd_cwnd; tp->ccv->flags |= CCF_ABC_SENTAWND; @@ -434,9 +440,16 @@ cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type) tp->t_dupacks = 0; tp->t_bytes_acked = 0; EXIT_RECOVERY(tp->t_flags); - tp->snd_ssthresh = max(2, min(tp->snd_wnd, tp->snd_cwnd) / 2 / - maxseg) * maxseg; - tp->snd_cwnd = maxseg; + if (CC_ALGO(tp)->cong_signal == NULL) { + /* + * RFC5681 Section 3.1 + * ssthresh = max (FlightSize / 2, 2*SMSS) eq (4) + */ + tp->snd_ssthresh = + max((tp->snd_max - tp->snd_una) / 2 / maxseg, 2) + * maxseg; + tp->snd_cwnd = maxseg; + } break; case CC_RTO_ERR: TCPSTAT_INC(tcps_sndrexmitbad); @@ -603,7 +616,7 @@ tcp_input(struct mbuf **mp, int *offp, int proto) #ifdef TCP_SIGNATURE uint8_t sig_checked = 0; #endif - uint8_t iptos = 0; + uint8_t iptos; struct m_tag *fwd_tag = NULL; #ifdef INET6 struct ip6_hdr *ip6 = NULL; @@ -675,6 +688,7 @@ tcp_input(struct mbuf **mp, int *offp, int proto) /* XXX stat */ goto drop; } + iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; } #endif #if defined(INET) && defined(INET6) @@ -701,6 +715,7 @@ tcp_input(struct mbuf **mp, int *offp, int proto) th = (struct tcphdr *)((caddr_t)ip + off0); tlen = ntohs(ip->ip_len) - off0; + iptos = ip->ip_tos; if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) th->th_sum = m->m_pkthdr.csum_data; @@ -721,29 +736,20 @@ tcp_input(struct mbuf **mp, int *offp, int proto) ipov->ih_len = htons(tlen); th->th_sum = in_cksum(m, len); /* Reset length for SDT probes. */ - ip->ip_len = htons(tlen + off0); + ip->ip_len = htons(len); + /* Reset TOS bits */ + ip->ip_tos = iptos; + /* Re-initialization for later version check */ + ip->ip_v = IPVERSION; } if (th->th_sum) { TCPSTAT_INC(tcps_rcvbadsum); goto drop; } - /* Re-initialization for later version check */ - ip->ip_v = IPVERSION; } #endif /* INET */ -#ifdef INET6 - if (isipv6) - iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; -#endif -#if defined(INET) && defined(INET6) - else -#endif -#ifdef INET - iptos = ip->ip_tos; -#endif - /* * Check that TCP offset makes sense, * pull out TCP options and adjust length. XXX @@ -923,6 +929,16 @@ findpcb: goto dropwithreset; } INP_WLOCK_ASSERT(inp); + /* + * While waiting for inp lock during the lookup, another thread + * can have dropped the inpcb, in which case we need to loop back + * and try to find a new inpcb to deliver to. + */ + if (inp->inp_flags & INP_DROPPED) { + INP_WUNLOCK(inp); + inp = NULL; + goto findpcb; + } if ((inp->inp_flowtype == M_HASHTYPE_NONE) && (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) && ((inp->inp_socket == NULL) || @@ -983,6 +999,10 @@ relocked: if (in_pcbrele_wlocked(inp)) { inp = NULL; goto findpcb; + } else if (inp->inp_flags & INP_DROPPED) { + INP_WUNLOCK(inp); + inp = NULL; + goto findpcb; } } else ti_locked = TI_RLOCKED; @@ -1031,7 +1051,7 @@ relocked: #endif if (!((tp->t_state == TCPS_ESTABLISHED && (thflags & TH_SYN) == 0) || (tp->t_state == TCPS_LISTEN && (thflags & TH_SYN) && - !(tp->t_flags & TF_FASTOPEN)))) { + !IS_FASTOPEN(tp->t_flags)))) { if (ti_locked == TI_UNLOCKED) { if (INP_INFO_TRY_RLOCK(&V_tcbinfo) == 0) { in_pcbref(inp); @@ -1042,6 +1062,10 @@ relocked: if (in_pcbrele_wlocked(inp)) { inp = NULL; goto findpcb; + } else if (inp->inp_flags & INP_DROPPED) { + INP_WUNLOCK(inp); + inp = NULL; + goto findpcb; } goto relocked; } else @@ -1074,11 +1098,11 @@ relocked: * state) we look into the SYN cache if this is a new connection * attempt or the completion of a previous one. */ - if (so->so_options & SO_ACCEPTCONN) { + KASSERT(tp->t_state == TCPS_LISTEN || !(so->so_options & SO_ACCEPTCONN), + ("%s: so accepting but tp %p not listening", __func__, tp)); + if (tp->t_state == TCPS_LISTEN && (so->so_options & SO_ACCEPTCONN)) { struct in_conninfo inc; - KASSERT(tp->t_state == TCPS_LISTEN, ("%s: so accepting but " - "tp not listening", __func__)); bzero(&inc, sizeof(inc)); #ifdef INET6 if (isipv6) { @@ -1124,7 +1148,7 @@ relocked: goto dropwithreset; } #ifdef TCP_RFC7413 -new_tfo_socket: +tfo_socket_result: #endif if (so == NULL) { /* @@ -1390,7 +1414,7 @@ new_tfo_socket: tcp_dooptions(&to, optp, optlen, TO_SYN); #ifdef TCP_RFC7413 if (syncache_add(&inc, &to, th, inp, &so, m, NULL, NULL)) - goto new_tfo_socket; + goto tfo_socket_result; #else syncache_add(&inc, &to, th, inp, &so, m, NULL, NULL); #endif @@ -1503,12 +1527,15 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, { int thflags, acked, ourfinisacked, needoutput = 0, sack_changed; int rstreason, todrop, win; - u_long tiwin; + uint32_t tiwin; + uint16_t nsegs; char *s; struct in_conninfo *inc; struct mbuf *mfree; struct tcpopt to; +#ifdef TCP_RFC7413 int tfo_syn; +#endif #ifdef TCPDEBUG /* @@ -1523,6 +1550,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, inc = &tp->t_inpcb->inp_inc; tp->sackhint.last_sack_ack = 0; sack_changed = 0; + nsegs = max(1, m->m_pkthdr.lro_nsegs); /* * If this is either a state-changing packet or current state isn't @@ -1564,8 +1592,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * validation to ignore broken/spoofed segs. */ tp->t_rcvtime = ticks; - if (TCPS_HAVEESTABLISHED(tp->t_state)) - tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); /* * Scale up the window into a 32-bit value. @@ -1741,7 +1767,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ if ((to.to_flags & TOF_TS) != 0 && to.to_tsecr) { - u_int t; + uint32_t t; t = tcp_ts_getticks() - to.to_tsecr; if (!tp->t_rttlow || tp->t_rttlow > t) @@ -1758,10 +1784,12 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, } acked = BYTES_THIS_ACK(tp, th); +#ifdef TCP_HHOOK /* Run HHOOK_TCP_ESTABLISHED_IN helper hooks. */ hhook_run_tcp_est_in(tp, th, &to); +#endif - TCPSTAT_INC(tcps_rcvackpack); + TCPSTAT_ADD(tcps_rcvackpack, nsegs); TCPSTAT_ADD(tcps_rcvackbyte, acked); sbdrop(&so->so_snd, acked); if (SEQ_GT(tp->snd_una, tp->snd_recover) && @@ -1774,7 +1802,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * typically means increasing the congestion * window. */ - cc_ack_received(tp, th, CC_ACK); + cc_ack_received(tp, th, nsegs, CC_ACK); tp->snd_una = th->th_ack; /* @@ -1840,7 +1868,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * rcv_nxt. */ tp->rcv_up = tp->rcv_nxt; - TCPSTAT_INC(tcps_rcvpack); + TCPSTAT_ADD(tcps_rcvpack, nsegs); TCPSTAT_ADD(tcps_rcvbyte, tlen); #ifdef TCPDEBUG if (so->so_options & SO_DEBUG) @@ -1963,7 +1991,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, goto dropwithreset; } #ifdef TCP_RFC7413 - if (tp->t_flags & TF_FASTOPEN) { + if (IS_FASTOPEN(tp->t_flags)) { /* * When a TFO connection is in SYN_RECEIVED, the * only valid packets are the initial SYN, a @@ -2030,7 +2058,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, (TF_RCVD_SCALE|TF_REQ_SCALE)) { tp->rcv_scale = tp->request_r_scale; } - tp->rcv_adv += imin(tp->rcv_wnd, + tp->rcv_adv += min(tp->rcv_wnd, TCP_MAXWIN << tp->rcv_scale); tp->snd_una++; /* SYN is acked */ /* @@ -2176,9 +2204,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, case TCPS_FIN_WAIT_1: case TCPS_FIN_WAIT_2: case TCPS_CLOSE_WAIT: + case TCPS_CLOSING: + case TCPS_LAST_ACK: so->so_error = ECONNRESET; close: - tcp_state_change(tp, TCPS_CLOSED); /* FALLTHROUGH */ default: tp = tcp_close(tp); @@ -2397,7 +2426,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, (tp->t_flags & TF_NEEDSYN)) { #ifdef TCP_RFC7413 if (tp->t_state == TCPS_SYN_RECEIVED && - tp->t_flags & TF_FASTOPEN) { + IS_FASTOPEN(tp->t_flags)) { tp->snd_wnd = tiwin; cc_conn_init(tp); } @@ -2460,7 +2489,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * snd_cwnd reduction that occurs when a TFO SYN|ACK * is retransmitted. */ - if (!(tp->t_flags & TF_FASTOPEN)) + if (!IS_FASTOPEN(tp->t_flags)) #endif cc_conn_init(tp); tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); @@ -2504,8 +2533,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ tp->sackhint.sacked_bytes = 0; +#ifdef TCP_HHOOK /* Run HHOOK_TCP_ESTABLISHED_IN helper hooks. */ hhook_run_tcp_est_in(tp, th, &to); +#endif if (SEQ_LEQ(th->th_ack, tp->snd_una)) { u_int maxseg; @@ -2572,7 +2603,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, tp->t_dupacks = 0; else if (++tp->t_dupacks > tcprexmtthresh || IN_FASTRECOVERY(tp->t_flags)) { - cc_ack_received(tp, th, CC_DUPACK); + cc_ack_received(tp, th, nsegs, + CC_DUPACK); if ((tp->t_flags & TF_SACK_PERMIT) && IN_FASTRECOVERY(tp->t_flags)) { int awnd; @@ -2591,6 +2623,15 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, if (awnd < tp->snd_ssthresh) { tp->snd_cwnd += maxseg; + /* + * RFC5681 Section 3.2 talks about cwnd + * inflation on additional dupacks and + * deflation on recovering from loss. + * + * We keep cwnd into check so that + * we don't have to 'deflate' it when we + * get out of recovery. + */ if (tp->snd_cwnd > tp->snd_ssthresh) tp->snd_cwnd = tp->snd_ssthresh; } @@ -2622,26 +2663,30 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, } /* Congestion signal before ack. */ cc_cong_signal(tp, th, CC_NDUPACK); - cc_ack_received(tp, th, CC_DUPACK); + cc_ack_received(tp, th, nsegs, + CC_DUPACK); tcp_timer_activate(tp, TT_REXMT, 0); tp->t_rtttime = 0; if (tp->t_flags & TF_SACK_PERMIT) { TCPSTAT_INC( tcps_sack_recovery_episode); tp->sack_newdata = tp->snd_nxt; - tp->snd_cwnd = maxseg; + if (CC_ALGO(tp)->cong_signal == NULL) + tp->snd_cwnd = maxseg; (void) tp->t_fb->tfb_tcp_output(tp); goto drop; } tp->snd_nxt = th->th_ack; - tp->snd_cwnd = maxseg; + if (CC_ALGO(tp)->cong_signal == NULL) + tp->snd_cwnd = maxseg; (void) tp->t_fb->tfb_tcp_output(tp); KASSERT(tp->snd_limited <= 2, ("%s: tp->snd_limited too big", __func__)); - tp->snd_cwnd = tp->snd_ssthresh + - maxseg * - (tp->t_dupacks - tp->snd_limited); + if (CC_ALGO(tp)->cong_signal == NULL) + tp->snd_cwnd = tp->snd_ssthresh + + maxseg * + (tp->t_dupacks - tp->snd_limited); if (SEQ_GT(onxt, tp->snd_nxt)) tp->snd_nxt = onxt; goto drop; @@ -2656,8 +2701,9 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * segment. Restore the original * snd_cwnd after packet transmission. */ - cc_ack_received(tp, th, CC_DUPACK); - u_long oldcwnd = tp->snd_cwnd; + cc_ack_received(tp, th, nsegs, + CC_DUPACK); + uint32_t oldcwnd = tp->snd_cwnd; tcp_seq oldsndmax = tp->snd_max; u_int sent; int avail; @@ -2758,7 +2804,7 @@ process_ACK: KASSERT(acked >= 0, ("%s: acked unexepectedly negative " "(tp->snd_una=%u, th->th_ack=%u, tp=%p, m=%p)", __func__, tp->snd_una, th->th_ack, tp, m)); - TCPSTAT_INC(tcps_rcvackpack); + TCPSTAT_ADD(tcps_rcvackpack, nsegs); TCPSTAT_ADD(tcps_rcvackbyte, acked); /* @@ -2787,7 +2833,7 @@ process_ACK: * huge RTT and blow up the retransmit timer. */ if ((to.to_flags & TOF_TS) != 0 && to.to_tsecr) { - u_int t; + uint32_t t; t = tcp_ts_getticks() - to.to_tsecr; if (!tp->t_rttlow || tp->t_rttlow > t) @@ -2823,7 +2869,7 @@ process_ACK: * control related information. This typically means increasing * the congestion window. */ - cc_ack_received(tp, th, CC_ACK); + cc_ack_received(tp, th, nsegs, CC_ACK); SOCKBUF_LOCK(&so->so_snd); if (acked > sbavail(&so->so_snd)) { @@ -2836,7 +2882,7 @@ process_ACK: ourfinisacked = 1; } else { mfree = sbcut_locked(&so->so_snd, acked); - if (tp->snd_wnd >= (u_long) acked) + if (tp->snd_wnd >= (uint32_t) acked) tp->snd_wnd -= acked; else tp->snd_wnd = 0; @@ -2997,7 +3043,7 @@ step6: * but if two URG's are pending at once, some out-of-band * data may creep in... ick. */ - if (th->th_urp <= (u_long)tlen && + if (th->th_urp <= (uint32_t)tlen && !(so->so_options & SO_OOBINLINE)) { /* hdr drop is delayed */ tcp_pulloutofband(so, th, m, drop_hdrlen); @@ -3022,8 +3068,12 @@ dodata: /* XXX */ * case PRU_RCVD). If a FIN has already been received on this * connection then we just ignore the text. */ +#ifdef TCP_RFC7413 tfo_syn = ((tp->t_state == TCPS_SYN_RECEIVED) && - (tp->t_flags & TF_FASTOPEN)); + IS_FASTOPEN(tp->t_flags)); +#else +#define tfo_syn (false) +#endif if ((tlen || (thflags & TH_FIN) || tfo_syn) && TCPS_HAVERCVDFIN(tp->t_state) == 0) { tcp_seq save_start = th->th_seq; @@ -3247,6 +3297,9 @@ drop: if (tp != NULL) INP_WUNLOCK(tp->t_inpcb); m_freem(m); +#ifndef TCP_RFC7413 +#undef tfo_syn +#endif } /* @@ -3306,6 +3359,8 @@ tcp_dropwithreset(struct mbuf *m, struct tcphdr *th, struct tcpcb *tp, } else { if (th->th_flags & TH_SYN) tlen++; + if (th->th_flags & TH_FIN) + tlen++; tcp_respond(tp, mtod(m, void *), th, m, th->th_seq+tlen, (tcp_seq)0, TH_RST|TH_ACK); } @@ -3562,7 +3617,7 @@ tcp_mss_update(struct tcpcb *tp, int offer, int mtuoffer, struct hc_metrics_lite *metricptr, struct tcp_ifcap *cap) { int mss = 0; - u_long maxmtu = 0; + uint32_t maxmtu = 0; struct inpcb *inp = tp->t_inpcb; struct hc_metrics_lite metrics; #ifdef INET6 @@ -3708,7 +3763,7 @@ void tcp_mss(struct tcpcb *tp, int offer) { int mss; - u_long bufsize; + uint32_t bufsize; struct inpcb *inp; struct socket *so; struct hc_metrics_lite metrics; @@ -3745,7 +3800,15 @@ tcp_mss(struct tcpcb *tp, int offer) (void)sbreserve_locked(&so->so_snd, bufsize, so, NULL); } SOCKBUF_UNLOCK(&so->so_snd); - tp->t_maxseg = mss; + /* + * Sanity check: make sure that maxseg will be large + * enough to allow some data on segments even if the + * all the option space is used (40bytes). Otherwise + * funny things may happen in tcp_output. + * + * XXXGL: shouldn't we reserve space for IP/IPv6 options? + */ + tp->t_maxseg = max(mss, 64); SOCKBUF_LOCK(&so->so_rcv); if ((so->so_rcv.sb_hiwat == V_tcp_recvspace) && metrics.rmx_recvpipe) @@ -3777,8 +3840,8 @@ int tcp_mssopt(struct in_conninfo *inc) { int mss = 0; - u_long maxmtu = 0; - u_long thcmtu = 0; + uint32_t thcmtu = 0; + uint32_t maxmtu = 0; size_t min_protoh; KASSERT(inc != NULL, ("tcp_mssopt with NULL in_conninfo pointer")); @@ -3823,7 +3886,7 @@ void tcp_newreno_partial_ack(struct tcpcb *tp, struct tcphdr *th) { tcp_seq onxt = tp->snd_nxt; - u_long ocwnd = tp->snd_cwnd; + uint32_t ocwnd = tp->snd_cwnd; u_int maxseg = tcp_maxseg(tp); INP_WLOCK_ASSERT(tp->t_inpcb); diff --git a/freebsd/sys/netinet/tcp_lro.c b/freebsd/sys/netinet/tcp_lro.c index 3550ab84..f318e78b 100644 --- a/freebsd/sys/netinet/tcp_lro.c +++ b/freebsd/sys/netinet/tcp_lro.c @@ -394,6 +394,7 @@ tcp_lro_flush(struct lro_ctrl *lc, struct lro_entry *le) #endif } + le->m_head->m_pkthdr.lro_nsegs = le->append_cnt + 1; (*lc->ifp->if_input)(lc->ifp, le->m_head); lc->lro_queued += le->append_cnt + 1; lc->lro_flushed++; diff --git a/freebsd/sys/netinet/tcp_output.c b/freebsd/sys/netinet/tcp_output.c index af11d805..a310512e 100644 --- a/freebsd/sys/netinet/tcp_output.c +++ b/freebsd/sys/netinet/tcp_output.c @@ -42,7 +42,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef TCP_HHOOK #include +#endif #include #include #include @@ -142,17 +144,20 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, sendbuf_max, CTLFLAG_VNET | CTLFLAG_RW, tcp_timer_active((tp), TT_PERSIST), \ ("neither rexmt nor persist timer is set")) +#ifdef TCP_HHOOK static void inline hhook_run_tcp_est_out(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to, - long len, int tso); + uint32_t len, int tso); +#endif static void inline cc_after_idle(struct tcpcb *tp); +#ifdef TCP_HHOOK /* * Wrapper for the TCP established output helper hook. */ static void inline hhook_run_tcp_est_out(struct tcpcb *tp, struct tcphdr *th, - struct tcpopt *to, long len, int tso) + struct tcpopt *to, uint32_t len, int tso) { struct tcp_hhook_data hhook_data; @@ -167,6 +172,7 @@ hhook_run_tcp_est_out(struct tcpcb *tp, struct tcphdr *th, tp->osd); } } +#endif /* * CC wrapper hook functions @@ -187,7 +193,8 @@ int tcp_output(struct tcpcb *tp) { struct socket *so = tp->t_inpcb->inp_socket; - long len, recwin, sendwin; + int32_t len; + uint32_t recwin, sendwin; int off, flags, error = 0; /* Keep compiler happy */ struct mbuf *m; struct ip *ip = NULL; @@ -225,7 +232,7 @@ tcp_output(struct tcpcb *tp) * For TFO connections in SYN_RECEIVED, only allow the initial * SYN|ACK and those sent by the retransmit timer. */ - if ((tp->t_flags & TF_FASTOPEN) && + if (IS_FASTOPEN(tp->t_flags) && (tp->t_state == TCPS_SYN_RECEIVED) && SEQ_GT(tp->snd_max, tp->snd_una) && /* initial SYN|ACK sent */ (tp->snd_nxt != tp->snd_una)) /* not a retransmit */ @@ -279,11 +286,10 @@ again: p = NULL; if ((tp->t_flags & TF_SACK_PERMIT) && IN_FASTRECOVERY(tp->t_flags) && (p = tcp_sack_output(tp, &sack_bytes_rxmt))) { - long cwin; + uint32_t cwin; - cwin = min(tp->snd_wnd, tp->snd_cwnd) - sack_bytes_rxmt; - if (cwin < 0) - cwin = 0; + cwin = + imax(min(tp->snd_wnd, tp->snd_cwnd) - sack_bytes_rxmt, 0); /* Do not retransmit SACK segments beyond snd_recover */ if (SEQ_GT(p->end, tp->snd_recover)) { /* @@ -302,10 +308,10 @@ again: goto after_sack_rexmit; } else /* Can rexmit part of the current hole */ - len = ((long)ulmin(cwin, + len = ((int32_t)ulmin(cwin, tp->snd_recover - p->rxmit)); } else - len = ((long)ulmin(cwin, p->end - p->rxmit)); + len = ((int32_t)ulmin(cwin, p->end - p->rxmit)); off = p->rxmit - tp->snd_una; KASSERT(off >= 0,("%s: sack block to the left of una : %d", __func__, off)); @@ -378,17 +384,17 @@ after_sack_rexmit: */ if (sack_rxmit == 0) { if (sack_bytes_rxmt == 0) - len = ((long)ulmin(sbavail(&so->so_snd), sendwin) - + len = ((int32_t)ulmin(sbavail(&so->so_snd), sendwin) - off); else { - long cwin; + int32_t cwin; /* * We are inside of a SACK recovery episode and are * sending new data, having retransmitted all the * data possible in the scoreboard. */ - len = ((long)ulmin(sbavail(&so->so_snd), tp->snd_wnd) - + len = ((int32_t)min(sbavail(&so->so_snd), tp->snd_wnd) - off); /* * Don't remove this (len > 0) check ! @@ -404,7 +410,7 @@ after_sack_rexmit: sack_bytes_rxmt; if (cwin < 0) cwin = 0; - len = lmin(len, cwin); + len = imin(len, cwin); } } } @@ -422,7 +428,7 @@ after_sack_rexmit: * When sending additional segments following a TFO SYN|ACK, * do not include the SYN bit. */ - if ((tp->t_flags & TF_FASTOPEN) && + if (IS_FASTOPEN(tp->t_flags) && (tp->t_state == TCPS_SYN_RECEIVED)) flags &= ~TH_SYN; #endif @@ -445,7 +451,7 @@ after_sack_rexmit: * don't include data, as the presence of data may have caused the * original SYN|ACK to have been dropped by a middlebox. */ - if ((tp->t_flags & TF_FASTOPEN) && + if (IS_FASTOPEN(tp->t_flags) && (((tp->t_state == TCPS_SYN_RECEIVED) && (tp->t_rxtshift > 0)) || (flags & TH_RST))) len = 0; @@ -568,7 +574,8 @@ after_sack_rexmit: flags &= ~TH_FIN; } - recwin = sbspace(&so->so_rcv); + recwin = lmin(lmax(sbspace(&so->so_rcv), 0), + (long)TCP_MAXWIN << tp->rcv_scale); /* * Sender silly window avoidance. We transmit under the following @@ -594,7 +601,7 @@ after_sack_rexmit: */ if (!(tp->t_flags & TF_MORETOCOME) && /* normal case */ (idle || (tp->t_flags & TF_NODELAY)) && - len + off >= sbavail(&so->so_snd) && + (uint32_t)len + (uint32_t)off >= sbavail(&so->so_snd) && (tp->t_flags & TF_NOPUSH) == 0) { goto send; } @@ -645,10 +652,10 @@ after_sack_rexmit: * taking into account that we are limited by * TCP_MAXWIN << tp->rcv_scale. */ - long adv; + int32_t adv; int oldwin; - adv = min(recwin, (long)TCP_MAXWIN << tp->rcv_scale); + adv = recwin; if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt)) { oldwin = (tp->rcv_adv - tp->rcv_nxt); adv -= oldwin; @@ -656,15 +663,16 @@ after_sack_rexmit: oldwin = 0; /* - * If the new window size ends up being the same as the old - * size when it is scaled, then don't force a window update. + * If the new window size ends up being the same as or less + * than the old size when it is scaled, then don't force + * a window update. */ - if (oldwin >> tp->rcv_scale == (adv + oldwin) >> tp->rcv_scale) + if (oldwin >> tp->rcv_scale >= (adv + oldwin) >> tp->rcv_scale) goto dontupdate; - if (adv >= (long)(2 * tp->t_maxseg) && - (adv >= (long)(so->so_rcv.sb_hiwat / 4) || - recwin <= (long)(so->so_rcv.sb_hiwat / 8) || + if (adv >= (int32_t)(2 * tp->t_maxseg) && + (adv >= (int32_t)(so->so_rcv.sb_hiwat / 4) || + recwin <= (so->so_rcv.sb_hiwat / 8) || so->so_rcv.sb_hiwat <= 8 * tp->t_maxseg)) goto send; } @@ -780,7 +788,7 @@ send: * the TFO option may have caused the original * SYN|ACK to have been dropped by a middlebox. */ - if ((tp->t_flags & TF_FASTOPEN) && + if (IS_FASTOPEN(tp->t_flags) && (tp->t_state == TCPS_SYN_RECEIVED) && (tp->t_rxtshift == 0)) { to.to_tfo_len = TCP_FASTOPEN_COOKIE_LEN; @@ -951,7 +959,8 @@ send: * emptied: */ max_len = (tp->t_maxseg - optlen); - if ((off + len) < sbavail(&so->so_snd)) { + if (((uint32_t)off + (uint32_t)len) < + sbavail(&so->so_snd)) { moff = len % max_len; if (moff != 0) { len -= moff; @@ -1047,11 +1056,11 @@ send: mb = sbsndptr(&so->so_snd, off, len, &moff); if (len <= MHLEN - hdrlen - max_linkhdr) { - m_copydata(mb, moff, (int)len, + m_copydata(mb, moff, len, mtod(m, caddr_t) + hdrlen); m->m_len += len; } else { - m->m_next = m_copy(mb, moff, (int)len); + m->m_next = m_copym(mb, moff, len, M_NOWAIT); if (m->m_next == NULL) { SOCKBUF_UNLOCK(&so->so_snd); (void) m_free(m); @@ -1067,7 +1076,8 @@ send: * give data to the user when a buffer fills or * a PUSH comes in.) */ - if ((off + len == sbused(&so->so_snd)) && !(flags & TH_SYN)) + if (((uint32_t)off + (uint32_t)len == sbused(&so->so_snd)) && + !(flags & TH_SYN)) flags |= TH_PUSH; SOCKBUF_UNLOCK(&so->so_snd); } else { @@ -1200,14 +1210,12 @@ send: * Calculate receive window. Don't shrink window, * but avoid silly window syndrome. */ - if (recwin < (long)(so->so_rcv.sb_hiwat / 4) && - recwin < (long)tp->t_maxseg) + if (recwin < (so->so_rcv.sb_hiwat / 4) && + recwin < tp->t_maxseg) recwin = 0; if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt) && - recwin < (long)(tp->rcv_adv - tp->rcv_nxt)) - recwin = (long)(tp->rcv_adv - tp->rcv_nxt); - if (recwin > (long)TCP_MAXWIN << tp->rcv_scale) - recwin = (long)TCP_MAXWIN << tp->rcv_scale; + recwin < (tp->rcv_adv - tp->rcv_nxt)) + recwin = (tp->rcv_adv - tp->rcv_nxt); /* * According to RFC1323 the window field in a SYN (i.e., a @@ -1298,16 +1306,18 @@ send: #ifdef IPSEC KASSERT(len + hdrlen + ipoptlen - ipsec_optlen == m_length(m, NULL), - ("%s: mbuf chain shorter than expected: %ld + %u + %u - %u != %u", + ("%s: mbuf chain shorter than expected: %d + %u + %u - %u != %u", __func__, len, hdrlen, ipoptlen, ipsec_optlen, m_length(m, NULL))); #else KASSERT(len + hdrlen + ipoptlen == m_length(m, NULL), - ("%s: mbuf chain shorter than expected: %ld + %u + %u != %u", + ("%s: mbuf chain shorter than expected: %d + %u + %u != %u", __func__, len, hdrlen, ipoptlen, m_length(m, NULL))); #endif +#ifdef TCP_HHOOK /* Run HHOOK_TCP_ESTABLISHED_OUT helper hooks. */ hhook_run_tcp_est_out(tp, th, &to, len, tso); +#endif #ifdef TCPDEBUG /* @@ -1521,7 +1531,7 @@ timer: tp->t_flags |= TF_SENTFIN; } if (SEQ_GT(tp->snd_nxt + xlen, tp->snd_max)) - tp->snd_max = tp->snd_nxt + len; + tp->snd_max = tp->snd_nxt + xlen; } if (error) { @@ -1598,7 +1608,7 @@ timer: * then remember the size of the advertised window. * Any pending ACK has now been sent. */ - if (recwin >= 0 && SEQ_GT(tp->rcv_nxt + recwin, tp->rcv_adv)) + if (SEQ_GT(tp->rcv_nxt + recwin, tp->rcv_adv)) tp->rcv_adv = tp->rcv_nxt + recwin; tp->last_ack_sent = tp->rcv_nxt; tp->t_flags &= ~(TF_ACKNOW | TF_DELACK); diff --git a/freebsd/sys/netinet/tcp_seq.h b/freebsd/sys/netinet/tcp_seq.h index 51d971f2..666cf603 100644 --- a/freebsd/sys/netinet/tcp_seq.h +++ b/freebsd/sys/netinet/tcp_seq.h @@ -75,20 +75,17 @@ * tcp_ts_getticks() in ms, should be 1ms < x < 1000ms according to RFC 1323. * We always use 1ms granularity independent of hz. */ -static __inline u_int +static __inline uint32_t tcp_ts_getticks(void) { struct timeval tv; - u_long ms; /* * getmicrouptime() should be good enough for any 1-1000ms granularity. * Do not use getmicrotime() here as it might break nfsroot/tcp. */ getmicrouptime(&tv); - ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; - - return (ms); + return (tv.tv_sec * 1000 + tv.tv_usec / 1000); } #endif /* _KERNEL */ diff --git a/freebsd/sys/netinet/tcp_subr.c b/freebsd/sys/netinet/tcp_subr.c index cff9bd7b..4f196a15 100644 --- a/freebsd/sys/netinet/tcp_subr.c +++ b/freebsd/sys/netinet/tcp_subr.c @@ -48,9 +48,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef TCP_HHOOK #include +#endif #include +#ifdef TCP_HHOOK #include +#endif #include #include #include @@ -244,7 +248,9 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, signature_verify_input, CTLFLAG_RW, VNET_DEFINE(uma_zone_t, sack_hole_zone); #define V_sack_hole_zone VNET(sack_hole_zone) +#ifdef TCP_HHOOK VNET_DEFINE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST+1]); +#endif static struct inpcb *tcp_notify(struct inpcb *, int); static struct inpcb *tcp_mtudisc_notify(struct inpcb *, int); @@ -455,7 +461,9 @@ struct tcpcb_mem { struct tcpcb tcb; struct tcp_timer tt; struct cc_var ccv; +#ifdef TCP_HHOOK struct osd osd; +#endif }; static VNET_DEFINE(uma_zone_t, tcpcb_zone); @@ -611,12 +619,14 @@ tcp_init(void) tcbhash_tuneable = "net.inet.tcp.tcbhashsize"; +#ifdef TCP_HHOOK if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_IN, &V_tcp_hhh[HHOOK_TCP_EST_IN], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0) printf("%s: WARNING: unable to register helper hook\n", __func__); if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_OUT, &V_tcp_hhh[HHOOK_TCP_EST_OUT], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0) printf("%s: WARNING: unable to register helper hook\n", __func__); +#endif hashsize = TCBHASHSIZE; TUNABLE_INT_FETCH(tcbhash_tuneable, &hashsize); if (hashsize == 0) { @@ -738,7 +748,10 @@ tcp_init(void) static void tcp_destroy(void *unused __unused) { - int error, n; + int n; +#ifdef TCP_HHOOK + int error; +#endif /* * All our processes are gone, all our sockets should be cleaned @@ -769,6 +782,7 @@ tcp_destroy(void *unused __unused) tcp_fastopen_destroy(); #endif +#ifdef TCP_HHOOK error = hhook_head_deregister(V_tcp_hhh[HHOOK_TCP_EST_IN]); if (error != 0) { printf("%s: WARNING: unable to deregister helper hook " @@ -781,6 +795,7 @@ tcp_destroy(void *unused __unused) "type=%d, id=%d: error %d returned\n", __func__, HHOOK_TYPE_TCP, HHOOK_TCP_EST_OUT, error); } +#endif } VNET_SYSUNINIT(tcp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, tcp_destroy, NULL); #endif @@ -919,8 +934,8 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, if (tp != NULL) { if (!(flags & TH_RST)) { win = sbspace(&inp->inp_socket->so_rcv); - if (win > (long)TCP_MAXWIN << tp->rcv_scale) - win = (long)TCP_MAXWIN << tp->rcv_scale; + if (win > TCP_MAXWIN << tp->rcv_scale) + win = TCP_MAXWIN << tp->rcv_scale; } if ((tp->t_flags & TF_NOOPT) == 0) incl_opts = true; @@ -1210,6 +1225,7 @@ tcp_newtcpcb(struct inpcb *inp) return (NULL); } +#ifdef TCP_HHOOK tp->osd = &tm->osd; if (khelp_init_osd(HELPER_CLASS_TCP, tp->osd)) { if (tp->t_fb->tfb_tcp_fb_fini) @@ -1218,6 +1234,7 @@ tcp_newtcpcb(struct inpcb *inp) uma_zfree(V_tcpcb_zone, tm); return (NULL); } +#endif #ifdef VIMAGE tp->t_vnet = inp->inp_vnet; @@ -1418,7 +1435,7 @@ tcp_discardcb(struct tcpcb *tp) */ if (tp->t_rttupdated >= 4) { struct hc_metrics_lite metrics; - u_long ssthresh; + uint32_t ssthresh; bzero(&metrics, sizeof(metrics)); /* @@ -1439,7 +1456,7 @@ tcp_discardcb(struct tcpcb *tp) ssthresh = (ssthresh + tp->t_maxseg / 2) / tp->t_maxseg; if (ssthresh < 2) ssthresh = 2; - ssthresh *= (u_long)(tp->t_maxseg + + ssthresh *= (tp->t_maxseg + #ifdef INET6 (isipv6 ? sizeof (struct ip6_hdr) + sizeof (struct tcphdr) : @@ -1483,12 +1500,15 @@ tcp_discardcb(struct tcpcb *tp) if (CC_ALGO(tp)->cb_destroy != NULL) CC_ALGO(tp)->cb_destroy(tp->ccv); +#ifdef TCP_HHOOK khelp_destroy_osd(tp->osd); +#endif CC_ALGO(tp) = NULL; inp->inp_ppcb = NULL; if (tp->t_timers->tt_draincnt == 0) { /* We own the last reference on tcpcb, let's free it. */ + TCPSTATES_DEC(tp->t_state); if (tp->t_fb->tfb_tcp_fb_fini) (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); @@ -1518,6 +1538,7 @@ tcp_timer_discard(void *ptp) tp->t_timers->tt_draincnt--; if (tp->t_timers->tt_draincnt == 0) { /* We own the last reference on this tcpcb, let's free it. */ + TCPSTATES_DEC(tp->t_state); if (tp->t_fb->tfb_tcp_fb_fini) (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); refcount_release(&tp->t_fb->tfb_refcnt); @@ -1564,7 +1585,8 @@ tcp_close(struct tcpcb *tp) #endif in_pcbdrop(inp); TCPSTAT_INC(tcps_closed); - TCPSTATES_DEC(tp->t_state); + if (tp->t_state != TCPS_CLOSED) + tcp_state_change(tp, TCPS_CLOSED); KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL")); so = inp->inp_socket; soisdisconnected(so); @@ -1955,7 +1977,8 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip) if (cmd == PRC_MSGSIZE) notify = tcp_mtudisc_notify; else if (V_icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB || - cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip) + cmd == PRC_UNREACH_PORT || cmd == PRC_UNREACH_PROTOCOL || + cmd == PRC_TIMXCEED_INTRANS) && ip) notify = tcp_drop_syn_sent; /* @@ -2087,8 +2110,8 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d) if (cmd == PRC_MSGSIZE) notify = tcp_mtudisc_notify; else if (V_icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB || - cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && - ip6 != NULL) + cmd == PRC_UNREACH_PORT || cmd == PRC_UNREACH_PROTOCOL || + cmd == PRC_TIMXCEED_INTRANS) && ip6 != NULL) notify = tcp_drop_syn_sent; /* @@ -2388,12 +2411,12 @@ tcp_mtudisc(struct inpcb *inp, int mtuoffer) * is called by TCP routines that access the rmx structure and by * tcp_mss_update to get the peer/interface MTU. */ -u_long +uint32_t tcp_maxmtu(struct in_conninfo *inc, struct tcp_ifcap *cap) { struct nhop4_extended nh4; struct ifnet *ifp; - u_long maxmtu = 0; + uint32_t maxmtu = 0; KASSERT(inc != NULL, ("tcp_maxmtu with NULL in_conninfo pointer")); @@ -2423,14 +2446,14 @@ tcp_maxmtu(struct in_conninfo *inc, struct tcp_ifcap *cap) #endif /* INET */ #ifdef INET6 -u_long +uint32_t tcp_maxmtu6(struct in_conninfo *inc, struct tcp_ifcap *cap) { struct nhop6_extended nh6; struct in6_addr dst6; uint32_t scopeid; struct ifnet *ifp; - u_long maxmtu = 0; + uint32_t maxmtu = 0; KASSERT(inc != NULL, ("tcp_maxmtu6 with NULL in_conninfo pointer")); @@ -2717,6 +2740,7 @@ tcp_signature_do_compute(struct mbuf *m, int len, int optlen, * Note: Upper-Layer Packet Length comes before Next Header. */ case (IPV6_VERSION >> 4): + ip6 = mtod(m, struct ip6_hdr *); in6 = ip6->ip6_src; in6_clearscope(&in6); MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr)); diff --git a/freebsd/sys/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c index d7da3a01..453d5ba4 100644 --- a/freebsd/sys/netinet/tcp_syncache.c +++ b/freebsd/sys/netinet/tcp_syncache.c @@ -928,8 +928,6 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) tp->t_keepcnt = sototcpcb(lso)->t_keepcnt; tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp)); - soisconnected(so); - TCPSTAT_INC(tcps_accepts); return (so); @@ -1081,10 +1079,17 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, } /* - * If timestamps were negotiated the reflected timestamp - * must be equal to what we actually sent in the SYN|ACK. + * If timestamps were negotiated, the reflected timestamp + * must be equal to what we actually sent in the SYN|ACK + * except in the case of 0. Some boxes are known for sending + * broken timestamp replies during the 3whs (and potentially + * during the connection also). + * + * Accept the final ACK of 3whs with reflected timestamp of 0 + * instead of sending a RST and deleting the syncache entry. */ - if ((to->to_flags & TOF_TS) && to->to_tsecr != sc->sc_ts) { + if ((to->to_flags & TOF_TS) && to->to_tsecr && + to->to_tsecr != sc->sc_ts) { if ((s = tcp_log_addrs(inc, th, NULL, NULL))) log(LOG_DEBUG, "%s; %s: TSECR %u != TS %u, " "segment rejected\n", @@ -1159,11 +1164,10 @@ syncache_tfo_expand(struct syncache *sc, struct socket **lsop, struct mbuf *m, * the data, we avoid this DoS scenario. * * The exception to the above is when a SYN with a valid TCP Fast Open (TFO) - * cookie is processed, V_tcp_fastopen_enabled set to true, and the - * TCP_FASTOPEN socket option is set. In this case, a new socket is created - * and returned via lsop, the mbuf is not freed so that tcp_input() can - * queue its data to the socket, and 1 is returned to indicate the - * TFO-socket-creation path was taken. + * cookie is processed and a new socket is created. In this case, any data + * accompanying the SYN will be queued to the socket by tcp_input() and will + * be ACKed either when the application sends response data or the delayed + * ACK timer expires, whichever comes first. */ int syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, @@ -1189,6 +1193,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, struct ucred *cred; #ifdef TCP_RFC7413 uint64_t tfo_response_cookie; + unsigned int *tfo_pending = NULL; int tfo_cookie_valid = 0; int tfo_response_cookie_valid = 0; #endif @@ -1217,7 +1222,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, ltflags = (tp->t_flags & (TF_NOOPT | TF_SIGNATURE)); #ifdef TCP_RFC7413 - if (V_tcp_fastopen_enabled && (tp->t_flags & TF_FASTOPEN) && + if (V_tcp_fastopen_enabled && IS_FASTOPEN(tp->t_flags) && (tp->t_tfo_pending != NULL) && (to->to_flags & TOF_FASTOPEN)) { /* * Limit the number of pending TFO connections to @@ -1234,8 +1239,13 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, &tfo_response_cookie); tfo_cookie_valid = (result > 0); tfo_response_cookie_valid = (result >= 0); - } else - atomic_subtract_int(tp->t_tfo_pending, 1); + } + + /* + * Remember the TFO pending counter as it will have to be + * decremented below if we don't make it to syncache_tfo_expand(). + */ + tfo_pending = tp->t_tfo_pending; } #endif @@ -1476,9 +1486,9 @@ skip_alloc: #ifdef TCP_RFC7413 if (tfo_cookie_valid) { syncache_tfo_expand(sc, lsop, m, tfo_response_cookie); - /* INP_WUNLOCK(inp) will be performed by the called */ + /* INP_WUNLOCK(inp) will be performed by the caller */ rv = 1; - goto tfo_done; + goto tfo_expanded; } #endif @@ -1504,7 +1514,16 @@ done: m_freem(m); } #ifdef TCP_RFC7413 -tfo_done: + /* + * If tfo_pending is not NULL here, then a TFO SYN that did not + * result in a new socket was processed and the associated pending + * counter has not yet been decremented. All such TFO processing paths + * transit this point. + */ + if (tfo_pending != NULL) + tcp_fastopen_decrement_counter(tfo_pending); + +tfo_expanded: #endif if (cred != NULL) crfree(cred); diff --git a/freebsd/sys/netinet/tcp_timer.c b/freebsd/sys/netinet/tcp_timer.c index edfc3829..89b61ad8 100644 --- a/freebsd/sys/netinet/tcp_timer.c +++ b/freebsd/sys/netinet/tcp_timer.c @@ -470,6 +470,26 @@ tcp_timer_keep(void *xtp) } KASSERT((tp->t_timers->tt_flags & TT_STOPPED) == 0, ("%s: tp %p tcpcb can't be stopped here", __func__, tp)); + + /* + * Because we don't regularly reset the keepalive callout in + * the ESTABLISHED state, it may be that we don't actually need + * to send a keepalive yet. If that occurs, schedule another + * call for the next time the keepalive timer might expire. + */ + if (TCPS_HAVEESTABLISHED(tp->t_state)) { + u_int idletime; + + idletime = ticks - tp->t_rcvtime; + if (idletime < TP_KEEPIDLE(tp)) { + callout_reset(&tp->t_timers->tt_keep, + TP_KEEPIDLE(tp) - idletime, tcp_timer_keep, tp); + INP_WUNLOCK(inp); + CURVNET_RESTORE(); + return; + } + } + /* * Keep-alive timer went off; send something * or drop connection if idle for too long. diff --git a/freebsd/sys/netinet/tcp_timewait.c b/freebsd/sys/netinet/tcp_timewait.c index 330e842e..7eb05462 100644 --- a/freebsd/sys/netinet/tcp_timewait.c +++ b/freebsd/sys/netinet/tcp_timewait.c @@ -233,6 +233,10 @@ tcp_twstart(struct tcpcb *tp) INP_INFO_RLOCK_ASSERT(&V_tcbinfo); INP_WLOCK_ASSERT(inp); + /* A dropped inp should never transition to TIME_WAIT state. */ + KASSERT((inp->inp_flags & INP_DROPPED) == 0, ("tcp_twstart: " + "(inp->inp_flags & INP_DROPPED) != 0")); + if (V_nolocaltimewait) { int error = 0; #ifdef INET6 @@ -338,6 +342,7 @@ tcp_twstart(struct tcpcb *tp) tcp_twrespond(tw, TH_ACK); inp->inp_ppcb = tw; inp->inp_flags |= INP_TIMEWAIT; + TCPSTATES_INC(TCPS_TIME_WAIT); tcp_tw_2msl_reset(tw, 0); /* diff --git a/freebsd/sys/netinet/tcp_usrreq.c b/freebsd/sys/netinet/tcp_usrreq.c index d5fa680f..436f30f8 100644 --- a/freebsd/sys/netinet/tcp_usrreq.c +++ b/freebsd/sys/netinet/tcp_usrreq.c @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #ifdef DDB #include @@ -212,10 +213,26 @@ tcp_detach(struct socket *so, struct inpcb *inp) * In all three cases the tcptw should not be freed here. */ if (inp->inp_flags & INP_DROPPED) { - KASSERT(tp == NULL, ("tcp_detach: INP_TIMEWAIT && " - "INP_DROPPED && tp != NULL")); in_pcbdetach(inp); - in_pcbfree(inp); + if (__predict_true(tp == NULL)) { + in_pcbfree(inp); + } else { + /* + * This case should not happen as in TIMEWAIT + * state the inp should not be destroyed before + * its tcptw. If INVARIANTS is defined, panic. + */ +#ifdef INVARIANTS + panic("%s: Panic before an inp double-free: " + "INP_TIMEWAIT && INP_DROPPED && tp != NULL" + , __func__); +#else + log(LOG_ERR, "%s: Avoid an inp double-free: " + "INP_TIMEWAIT && INP_DROPPED && tp != NULL" + , __func__); +#endif + INP_WUNLOCK(inp); + } } else { in_pcbdetach(inp); INP_WUNLOCK(inp); @@ -412,7 +429,7 @@ tcp_usr_listen(struct socket *so, int backlog, struct thread *td) SOCK_UNLOCK(so); #ifdef TCP_RFC7413 - if (tp->t_flags & TF_FASTOPEN) + if (IS_FASTOPEN(tp->t_flags)) tp->t_tfo_pending = tcp_fastopen_alloc_counter(); #endif out: @@ -462,7 +479,7 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td) SOCK_UNLOCK(so); #ifdef TCP_RFC7413 - if (tp->t_flags & TF_FASTOPEN) + if (IS_FASTOPEN(tp->t_flags)) tp->t_tfo_pending = tcp_fastopen_alloc_counter(); #endif out: @@ -828,7 +845,7 @@ tcp_usr_rcvd(struct socket *so, int flags) * application response data, or failing that, when the DELACK timer * expires. */ - if ((tp->t_flags & TF_FASTOPEN) && + if (IS_FASTOPEN(tp->t_flags) && (tp->t_state == TCPS_SYN_RECEIVED)) goto out; #endif @@ -1331,9 +1348,11 @@ tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti) ti->tcpi_snd_wscale = tp->snd_scale; ti->tcpi_rcv_wscale = tp->rcv_scale; } + if (tp->t_flags & TF_ECN_PERMIT) + ti->tcpi_options |= TCPI_OPT_ECN; ti->tcpi_rto = tp->t_rxtcur * tick; - ti->tcpi_last_data_recv = (long)(ticks - (int)tp->t_rcvtime) * tick; + ti->tcpi_last_data_recv = ((uint32_t)ticks - tp->t_rcvtime) * tick; ti->tcpi_rtt = ((u_int64_t)tp->t_srtt * tick) >> TCP_RTT_SHIFT; ti->tcpi_rttvar = ((u_int64_t)tp->t_rttvar * tick) >> TCP_RTTVAR_SHIFT; @@ -1819,16 +1838,16 @@ unlock_and_done: case TCP_KEEPCNT: switch (sopt->sopt_name) { case TCP_KEEPIDLE: - ui = tp->t_keepidle / hz; + ui = TP_KEEPIDLE(tp) / hz; break; case TCP_KEEPINTVL: - ui = tp->t_keepintvl / hz; + ui = TP_KEEPINTVL(tp) / hz; break; case TCP_KEEPINIT: - ui = tp->t_keepinit / hz; + ui = TP_KEEPINIT(tp) / hz; break; case TCP_KEEPCNT: - ui = tp->t_keepcnt; + ui = TP_KEEPCNT(tp); break; } INP_WUNLOCK(inp); @@ -2242,15 +2261,15 @@ db_print_tcpcb(struct tcpcb *tp, const char *name, int indent) tp->iss, tp->irs, tp->rcv_nxt); db_print_indent(indent); - db_printf("rcv_adv: 0x%08x rcv_wnd: %lu rcv_up: 0x%08x\n", + db_printf("rcv_adv: 0x%08x rcv_wnd: %u rcv_up: 0x%08x\n", tp->rcv_adv, tp->rcv_wnd, tp->rcv_up); db_print_indent(indent); - db_printf("snd_wnd: %lu snd_cwnd: %lu\n", + db_printf("snd_wnd: %u snd_cwnd: %u\n", tp->snd_wnd, tp->snd_cwnd); db_print_indent(indent); - db_printf("snd_ssthresh: %lu snd_recover: " + db_printf("snd_ssthresh: %u snd_recover: " "0x%08x\n", tp->snd_ssthresh, tp->snd_recover); db_print_indent(indent); @@ -2271,7 +2290,7 @@ db_print_tcpcb(struct tcpcb *tp, const char *name, int indent) tp->t_rttbest); db_print_indent(indent); - db_printf("t_rttupdated: %lu max_sndwnd: %lu t_softerror: %d\n", + db_printf("t_rttupdated: %lu max_sndwnd: %u t_softerror: %d\n", tp->t_rttupdated, tp->max_sndwnd, tp->t_softerror); db_print_indent(indent); @@ -2289,10 +2308,10 @@ db_print_tcpcb(struct tcpcb *tp, const char *name, int indent) db_print_indent(indent); db_printf("ts_offset: %u last_ack_sent: 0x%08x snd_cwnd_prev: " - "%lu\n", tp->ts_offset, tp->last_ack_sent, tp->snd_cwnd_prev); + "%u\n", tp->ts_offset, tp->last_ack_sent, tp->snd_cwnd_prev); db_print_indent(indent); - db_printf("snd_ssthresh_prev: %lu snd_recover_prev: 0x%08x " + db_printf("snd_ssthresh_prev: %u snd_recover_prev: 0x%08x " "t_badrxtwin: %u\n", tp->snd_ssthresh_prev, tp->snd_recover_prev, tp->t_badrxtwin); diff --git a/freebsd/sys/netinet/tcp_var.h b/freebsd/sys/netinet/tcp_var.h index 5dcd35b8..f4ea246b 100644 --- a/freebsd/sys/netinet/tcp_var.h +++ b/freebsd/sys/netinet/tcp_var.h @@ -192,13 +192,13 @@ struct tcpcb { tcp_seq rcv_nxt; /* receive next */ tcp_seq rcv_adv; /* advertised window */ - u_long rcv_wnd; /* receive window */ + uint32_t rcv_wnd; /* receive window */ tcp_seq rcv_up; /* receive urgent pointer */ - u_long snd_wnd; /* send window */ - u_long snd_cwnd; /* congestion-controlled window */ + uint32_t snd_wnd; /* send window */ + uint32_t snd_cwnd; /* congestion-controlled window */ u_long snd_spare1; /* unused */ - u_long snd_ssthresh; /* snd_cwnd size threshold for + uint32_t snd_ssthresh; /* snd_cwnd size threshold for * for slow start exponential to * linear switch */ @@ -223,7 +223,7 @@ struct tcpcb { u_int t_rttmin; /* minimum rtt allowed */ u_int t_rttbest; /* best rtt we've seen */ u_long t_rttupdated; /* number of times rtt sampled */ - u_long max_sndwnd; /* largest window peer has offered */ + uint32_t max_sndwnd; /* largest window peer has offered */ int t_softerror; /* possible error not yet reported */ /* out-of-band data */ @@ -239,8 +239,8 @@ struct tcpcb { tcp_seq last_ack_sent; /* experimental */ - u_long snd_cwnd_prev; /* cwnd prior to retransmit */ - u_long snd_ssthresh_prev; /* ssthresh prior to retransmit */ + uint32_t snd_cwnd_prev; /* cwnd prior to retransmit */ + uint32_t snd_ssthresh_prev; /* ssthresh prior to retransmit */ tcp_seq snd_recover_prev; /* snd_recover prior to retransmit */ int t_sndzerowin; /* zero-window updates sent */ u_int t_badrxtwin; /* window for retransmit recovery */ @@ -349,6 +349,12 @@ struct tcpcb { #define ENTER_RECOVERY(t_flags) t_flags |= (TF_CONGRECOVERY | TF_FASTRECOVERY) #define EXIT_RECOVERY(t_flags) t_flags &= ~(TF_CONGRECOVERY | TF_FASTRECOVERY) +#if defined(_KERNEL) && !defined(TCP_RFC7413) +#define IS_FASTOPEN(t_flags) (false) +#else +#define IS_FASTOPEN(t_flags) (t_flags & TF_FASTOPEN) +#endif + #define BYTES_THIS_ACK(tp, th) (th->th_ack - tp->snd_una) /* @@ -415,13 +421,13 @@ struct tcpopt { #define TO_SYN 0x01 /* parse SYN-only options */ struct hc_metrics_lite { /* must stay in sync with hc_metrics */ - u_long rmx_mtu; /* MTU for this path */ - u_long rmx_ssthresh; /* outbound gateway buffer limit */ - u_long rmx_rtt; /* estimated round trip time */ - u_long rmx_rttvar; /* estimated rtt variance */ - u_long rmx_cwnd; /* congestion window */ - u_long rmx_sendpipe; /* outbound delay-bandwidth product */ - u_long rmx_recvpipe; /* inbound delay-bandwidth product */ + uint32_t rmx_mtu; /* MTU for this path */ + uint32_t rmx_ssthresh; /* outbound gateway buffer limit */ + uint32_t rmx_rtt; /* estimated round trip time */ + uint32_t rmx_rttvar; /* estimated rtt variance */ + uint32_t rmx_cwnd; /* congestion window */ + uint32_t rmx_sendpipe; /* outbound delay-bandwidth product */ + uint32_t rmx_recvpipe; /* inbound delay-bandwidth product */ }; /* @@ -657,7 +663,7 @@ struct tcp_hhook_data { struct tcpcb *tp; struct tcphdr *th; struct tcpopt *to; - long len; + uint32_t len; int tso; tcp_seq curack; }; @@ -749,8 +755,10 @@ VNET_DECLARE(int, tcp_ecn_maxretries); #define V_tcp_do_ecn VNET(tcp_do_ecn) #define V_tcp_ecn_maxretries VNET(tcp_ecn_maxretries) +#ifdef TCP_HHOOK VNET_DECLARE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST + 1]); #define V_tcp_hhh VNET(tcp_hhh) +#endif VNET_DECLARE(int, tcp_do_rfc6675_pipe); #define V_tcp_do_rfc6675_pipe VNET(tcp_do_rfc6675_pipe) @@ -784,12 +792,14 @@ void tcp_pulloutofband(struct socket *, void tcp_xmit_timer(struct tcpcb *, int); void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *); void cc_ack_received(struct tcpcb *tp, struct tcphdr *th, - uint16_t type); + uint16_t nsegs, uint16_t type); void cc_conn_init(struct tcpcb *tp); void cc_post_recovery(struct tcpcb *tp, struct tcphdr *th); void cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type); +#ifdef TCP_HHOOK void hhook_run_tcp_est_in(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to); +#endif int tcp_input(struct mbuf **, int *, int); void tcp_do_segment(struct mbuf *, struct tcphdr *, @@ -802,8 +812,8 @@ struct tcp_function_block *find_and_ref_tcp_functions(struct tcp_function_set *f struct tcp_function_block *find_and_ref_tcp_fb(struct tcp_function_block *blk); int tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp, struct tcpcb *tp); -u_long tcp_maxmtu(struct in_conninfo *, struct tcp_ifcap *); -u_long tcp_maxmtu6(struct in_conninfo *, struct tcp_ifcap *); +uint32_t tcp_maxmtu(struct in_conninfo *, struct tcp_ifcap *); +uint32_t tcp_maxmtu6(struct in_conninfo *, struct tcp_ifcap *); u_int tcp_maxseg(const struct tcpcb *); void tcp_mss_update(struct tcpcb *, int, int, struct hc_metrics_lite *, struct tcp_ifcap *); @@ -852,8 +862,8 @@ void tcp_hc_init(void); void tcp_hc_destroy(void); #endif void tcp_hc_get(struct in_conninfo *, struct hc_metrics_lite *); -u_long tcp_hc_getmtu(struct in_conninfo *); -void tcp_hc_updatemtu(struct in_conninfo *, u_long); +uint32_t tcp_hc_getmtu(struct in_conninfo *); +void tcp_hc_updatemtu(struct in_conninfo *, uint32_t); void tcp_hc_update(struct in_conninfo *, struct hc_metrics_lite *); extern struct pr_usrreqs tcp_usrreqs; @@ -867,7 +877,6 @@ struct sackhole *tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt); void tcp_sack_partialack(struct tcpcb *, struct tcphdr *); void tcp_free_sackholes(struct tcpcb *tp); int tcp_newreno(struct tcpcb *, struct tcphdr *); -u_long tcp_seq_subtract(u_long, u_long ); int tcp_compute_pipe(struct tcpcb *); static inline void diff --git a/freebsd/sys/netinet/udp_usrreq.c b/freebsd/sys/netinet/udp_usrreq.c index 7eb11648..42461ce9 100644 --- a/freebsd/sys/netinet/udp_usrreq.c +++ b/freebsd/sys/netinet/udp_usrreq.c @@ -603,7 +603,8 @@ udp_input(struct mbuf **mp, int *offp, int proto) if (last != NULL) { struct mbuf *n; - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { + if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != + NULL) { UDP_PROBE(receive, NULL, last, ip, last, uh); if (udp_append(last, ip, n, iphlen, @@ -1572,12 +1573,18 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr, release: if (unlock_udbinfo == UH_WLOCKED) { + KASSERT(unlock_inp == UH_WLOCKED, + ("%s: excl udbinfo lock, shared inp lock", __func__)); INP_HASH_WUNLOCK(pcbinfo); INP_WUNLOCK(inp); } else if (unlock_udbinfo == UH_RLOCKED) { + KASSERT(unlock_inp == UH_RLOCKED, + ("%s: shared udbinfo lock, excl inp lock", __func__)); INP_HASH_RUNLOCK(pcbinfo); INP_RUNLOCK(inp); - } else + } else if (unlock_inp == UH_WLOCKED) + INP_WUNLOCK(inp); + else INP_RUNLOCK(inp); m_freem(m); return (error); diff --git a/freebsd/sys/netinet6/icmp6.c b/freebsd/sys/netinet6/icmp6.c index 6e3a4873..14ce2b3b 100644 --- a/freebsd/sys/netinet6/icmp6.c +++ b/freebsd/sys/netinet6/icmp6.c @@ -492,7 +492,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ICMP6_DST_UNREACH_ADMIN: icmp6_ifstat_inc(ifp, ifs6_in_adminprohib); - code = PRC_UNREACH_PROTOCOL; /* is this a good code? */ + code = PRC_UNREACH_ADMIN_PROHIB; break; case ICMP6_DST_UNREACH_BEYONDSCOPE: /* I mean "source address was incorrect." */ @@ -556,7 +556,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) icmp6_ifstat_inc(ifp, ifs6_in_echo); if (code != 0) goto badcode; - if ((n = m_copy(m, 0, M_COPYALL)) == NULL) { + if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) { /* Give up remote */ break; } @@ -653,7 +653,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_nodeinfo), IPPROTO_DONE); #endif - n = m_copy(m, 0, M_COPYALL); + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (n) n = ni6_input(n, off); /* XXX meaningless if n == NULL */ @@ -740,36 +740,19 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) goto badcode; if (icmp6len < sizeof(struct nd_router_solicit)) goto badlen; - if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) { - /* give up local */ - - /* Send incoming SeND packet to user space. */ - if (send_sendso_input_hook != NULL) { - IP6_EXTHDR_CHECK(m, off, - icmp6len, IPPROTO_DONE); - error = send_sendso_input_hook(m, ifp, - SND_IN, ip6len); - /* -1 == no app on SEND socket */ - if (error == 0) - return (IPPROTO_DONE); - nd6_rs_input(m, off, icmp6len); - } else - nd6_rs_input(m, off, icmp6len); - m = NULL; - goto freeit; - } if (send_sendso_input_hook != NULL) { - IP6_EXTHDR_CHECK(n, off, - icmp6len, IPPROTO_DONE); - error = send_sendso_input_hook(n, ifp, - SND_IN, ip6len); - if (error == 0) + IP6_EXTHDR_CHECK(m, off, icmp6len, IPPROTO_DONE); + error = send_sendso_input_hook(m, ifp, SND_IN, ip6len); + if (error == 0) { + m = NULL; goto freeit; - /* -1 == no app on SEND socket */ - nd6_rs_input(n, off, icmp6len); - } else - nd6_rs_input(n, off, icmp6len); - /* m stays. */ + } + } + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); + nd6_rs_input(m, off, icmp6len); + m = n; + if (m == NULL) + goto freeit; break; case ND_ROUTER_ADVERT: @@ -778,29 +761,18 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) goto badcode; if (icmp6len < sizeof(struct nd_router_advert)) goto badlen; - if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) { - - /* Send incoming SeND-protected/ND packet to user space. */ - if (send_sendso_input_hook != NULL) { - error = send_sendso_input_hook(m, ifp, - SND_IN, ip6len); - if (error == 0) - return (IPPROTO_DONE); - nd6_ra_input(m, off, icmp6len); - } else - nd6_ra_input(m, off, icmp6len); - m = NULL; - goto freeit; - } if (send_sendso_input_hook != NULL) { - error = send_sendso_input_hook(n, ifp, - SND_IN, ip6len); - if (error == 0) + error = send_sendso_input_hook(m, ifp, SND_IN, ip6len); + if (error == 0) { + m = NULL; goto freeit; - nd6_ra_input(n, off, icmp6len); - } else - nd6_ra_input(n, off, icmp6len); - /* m stays. */ + } + } + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); + nd6_ra_input(m, off, icmp6len); + m = n; + if (m == NULL) + goto freeit; break; case ND_NEIGHBOR_SOLICIT: @@ -809,27 +781,18 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) goto badcode; if (icmp6len < sizeof(struct nd_neighbor_solicit)) goto badlen; - if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) { - if (send_sendso_input_hook != NULL) { - error = send_sendso_input_hook(m, ifp, - SND_IN, ip6len); - if (error == 0) - return (IPPROTO_DONE); - nd6_ns_input(m, off, icmp6len); - } else - nd6_ns_input(m, off, icmp6len); - m = NULL; - goto freeit; - } if (send_sendso_input_hook != NULL) { - error = send_sendso_input_hook(n, ifp, - SND_IN, ip6len); - if (error == 0) + error = send_sendso_input_hook(m, ifp, SND_IN, ip6len); + if (error == 0) { + m = NULL; goto freeit; - nd6_ns_input(n, off, icmp6len); - } else - nd6_ns_input(n, off, icmp6len); - /* m stays. */ + } + } + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); + nd6_ns_input(m, off, icmp6len); + m = n; + if (m == NULL) + goto freeit; break; case ND_NEIGHBOR_ADVERT: @@ -838,29 +801,18 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) goto badcode; if (icmp6len < sizeof(struct nd_neighbor_advert)) goto badlen; - if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) { - - /* Send incoming SeND-protected/ND packet to user space. */ - if (send_sendso_input_hook != NULL) { - error = send_sendso_input_hook(m, ifp, - SND_IN, ip6len); - if (error == 0) - return (IPPROTO_DONE); - nd6_na_input(m, off, icmp6len); - } else - nd6_na_input(m, off, icmp6len); - m = NULL; - goto freeit; - } if (send_sendso_input_hook != NULL) { - error = send_sendso_input_hook(n, ifp, - SND_IN, ip6len); - if (error == 0) + error = send_sendso_input_hook(m, ifp, SND_IN, ip6len); + if (error == 0) { + m = NULL; goto freeit; - nd6_na_input(n, off, icmp6len); - } else - nd6_na_input(n, off, icmp6len); - /* m stays. */ + } + } + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); + nd6_na_input(m, off, icmp6len); + m = n; + if (m == NULL) + goto freeit; break; case ND_REDIRECT: @@ -869,27 +821,18 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) goto badcode; if (icmp6len < sizeof(struct nd_redirect)) goto badlen; - if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) { - if (send_sendso_input_hook != NULL) { - error = send_sendso_input_hook(m, ifp, - SND_IN, ip6len); - if (error == 0) - return (IPPROTO_DONE); - icmp6_redirect_input(m, off); - } else - icmp6_redirect_input(m, off); - m = NULL; - goto freeit; - } if (send_sendso_input_hook != NULL) { - error = send_sendso_input_hook(n, ifp, - SND_IN, ip6len); - if (error == 0) + error = send_sendso_input_hook(m, ifp, SND_IN, ip6len); + if (error == 0) { + m = NULL; goto freeit; - icmp6_redirect_input(n, off); - } else - icmp6_redirect_input(n, off); - /* m stays. */ + } + } + n = m_copym(m, 0, M_COPYALL, M_NOWAIT); + icmp6_redirect_input(m, off); + m = n; + if (m == NULL) + goto freeit; break; case ICMP6_ROUTER_RENUMBERING: @@ -2053,7 +1996,7 @@ icmp6_rip6_input(struct mbuf **mp, int off) } } if (n != NULL || - (n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { + (n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != NULL) { if (last->inp_flags & INP_CONTROLOPTS) ip6_savecontrol(last, n, &opts); /* strip intermediate headers */ @@ -2217,7 +2160,7 @@ icmp6_reflect(struct mbuf *m, size_t off) * that we do not own. Select a source address based on the * source address of the erroneous packet. */ - in6_splitscope(&ip6->ip6_dst, &dst6, &scopeid); + in6_splitscope(&ip6->ip6_src, &dst6, &scopeid); error = in6_selectsrc_addr(RT_DEFAULT_FIB, &dst6, scopeid, NULL, &src6, &hlim); diff --git a/freebsd/sys/netinet6/in6.c b/freebsd/sys/netinet6/in6.c index f5d82524..8a4c3663 100644 --- a/freebsd/sys/netinet6/in6.c +++ b/freebsd/sys/netinet6/in6.c @@ -634,7 +634,7 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, /* relate the address to the prefix */ if (ia->ia6_ndpr == NULL) { ia->ia6_ndpr = pr; - pr->ndpr_refcnt++; + pr->ndpr_addrcnt++; /* * If this is the first autoconf address from the @@ -642,7 +642,7 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, * (when required). */ if ((ia->ia6_flags & IN6_IFF_AUTOCONF) && - V_ip6_use_tempaddr && pr->ndpr_refcnt == 1) { + V_ip6_use_tempaddr && pr->ndpr_addrcnt == 1) { int e; if ((e = in6_tmpifadd(ia, 1, 0)) != 0) { log(LOG_NOTICE, "in6_control: failed " @@ -651,6 +651,7 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, } } } + nd6_prefix_rele(pr); /* * this might affect the status of autoconfigured addresses, @@ -694,12 +695,16 @@ aifaddr_out: * and the prefix management. We do this, however, to provide * as much backward compatibility as possible in terms of * the ioctl operation. - * Note that in6_purgeaddr() will decrement ndpr_refcnt. + * Note that in6_purgeaddr() will decrement ndpr_addrcnt. */ pr = ia->ia6_ndpr; in6_purgeaddr(&ia->ia_ifa); - if (pr && pr->ndpr_refcnt == 0) - prelist_remove(pr); + if (pr != NULL && pr->ndpr_addrcnt == 0) { + ND6_WLOCK(); + nd6_prefix_unlink(pr, NULL); + ND6_WUNLOCK(); + nd6_prefix_del(pr); + } EVENTHANDLER_INVOKE(ifaddr_event, ifp); break; } @@ -1309,9 +1314,9 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp) "in6_unlink_ifa: autoconf'ed address " "%s has no prefix\n", ip6_sprintf(ip6buf, IA6_IN6(ia)))); } else { - ia->ia6_ndpr->ndpr_refcnt--; + ia->ia6_ndpr->ndpr_addrcnt--; /* Do not delete lles within prefix if refcont != 0 */ - if (ia->ia6_ndpr->ndpr_refcnt == 0) + if (ia->ia6_ndpr->ndpr_addrcnt == 0) remove_lle = 1; ia->ia6_ndpr = NULL; } diff --git a/freebsd/sys/netinet6/in6_ifattach.c b/freebsd/sys/netinet6/in6_ifattach.c index 791e9e27..879336a4 100644 --- a/freebsd/sys/netinet6/in6_ifattach.c +++ b/freebsd/sys/netinet6/in6_ifattach.c @@ -459,6 +459,7 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) struct in6_ifaddr *ia; struct in6_aliasreq ifra; struct nd_prefixctl pr0; + struct nd_prefix *pr; int error; /* @@ -541,10 +542,11 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp) * address, and then reconfigure another one, the prefix is still * valid with referring to the old link-local address. */ - if (nd6_prefix_lookup(&pr0) == NULL) { + if ((pr = nd6_prefix_lookup(&pr0)) == NULL) { if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0) return (error); - } + } else + nd6_prefix_rele(pr); return 0; } @@ -787,15 +789,6 @@ _in6_ifdetach(struct ifnet *ifp, int purgeulp) if (ifp->if_afdata[AF_INET6] == NULL) return; - /* - * Remove neighbor management table. - * Enabling the nd6_purge will panic on vmove for interfaces on VNET - * teardown as the IPv6 layer is cleaned up already and the locks - * are destroyed. - */ - if (purgeulp) - nd6_purge(ifp); - /* * nuke any of IPv6 addresses we have * XXX: all addresses should be already removed @@ -814,12 +807,10 @@ _in6_ifdetach(struct ifnet *ifp, int purgeulp) in6_purgemaddrs(ifp); /* - * remove neighbor management table. we call it twice just to make - * sure we nuke everything. maybe we need just one call. - * XXX: since the first call did not release addresses, some prefixes - * might remain. We should call nd6_purge() again to release the - * prefixes after removing all addresses above. - * (Or can we just delay calling nd6_purge until at this point?) + * Remove neighbor management table. + * Enabling the nd6_purge will panic on vmove for interfaces on VNET + * teardown as the IPv6 layer is cleaned up already and the locks + * are destroyed. */ if (purgeulp) nd6_purge(ifp); diff --git a/freebsd/sys/netinet6/ip6_forward.c b/freebsd/sys/netinet6/ip6_forward.c index 50583537..b57d31fa 100644 --- a/freebsd/sys/netinet6/ip6_forward.c +++ b/freebsd/sys/netinet6/ip6_forward.c @@ -168,7 +168,8 @@ ip6_forward(struct mbuf *m, int srcrt) * It is important to save it before IPsec processing as IPsec * processing may modify the mbuf. */ - mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN)); + mcopy = m_copym(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN), + M_NOWAIT); #ifdef IPSEC /* get a security policy for this packet */ diff --git a/freebsd/sys/netinet6/ip6_input.c b/freebsd/sys/netinet6/ip6_input.c index c7ffe759..6af5acd7 100644 --- a/freebsd/sys/netinet6/ip6_input.c +++ b/freebsd/sys/netinet6/ip6_input.c @@ -1774,6 +1774,6 @@ u_char inet6ctlerrmap[PRC_NCMDS] = { 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, EMSGSIZE, EHOSTUNREACH, 0, 0, - 0, 0, 0, 0, - ENOPROTOOPT + 0, 0, EHOSTUNREACH, 0, + ENOPROTOOPT, ECONNREFUSED }; diff --git a/freebsd/sys/netinet6/ip6_mroute.c b/freebsd/sys/netinet6/ip6_mroute.c index f74b71c3..e40ce06c 100644 --- a/freebsd/sys/netinet6/ip6_mroute.c +++ b/freebsd/sys/netinet6/ip6_mroute.c @@ -1147,7 +1147,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) MFC6_UNLOCK(); return (ENOBUFS); } - mb0 = m_copy(m, 0, M_COPYALL); + mb0 = m_copym(m, 0, M_COPYALL, M_NOWAIT); /* * Pullup packet header if needed before storing it, * as other references may modify it in the meantime. @@ -1187,7 +1187,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) * Make a copy of the header to send to the user * level process */ - mm = m_copy(mb0, 0, sizeof(struct ip6_hdr)); + mm = m_copym(mb0, 0, sizeof(struct ip6_hdr), M_NOWAIT); if (mm == NULL) { free(rte, M_MRTABLE6); m_freem(mb0); @@ -1419,7 +1419,8 @@ ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt) struct omrt6msg *oim; #endif - mm = m_copy(m, 0, sizeof(struct ip6_hdr)); + mm = m_copym(m, 0, sizeof(struct ip6_hdr), + M_NOWAIT); if (mm && (!M_WRITABLE(mm) || mm->m_len < sizeof(struct ip6_hdr))) @@ -1549,7 +1550,7 @@ phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m) * the IPv6 header is actually copied, not just referenced, * so that ip6_output() only scribbles on the copy. */ - mb_copy = m_copy(m, 0, M_COPYALL); + mb_copy = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (mb_copy && (!M_WRITABLE(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr))) mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr)); @@ -1653,7 +1654,7 @@ register_send(struct ip6_hdr *ip6, struct mif6 *mif, struct mbuf *m) mm->m_data += max_linkhdr; mm->m_len = sizeof(struct ip6_hdr); - if ((mm->m_next = m_copy(m, 0, M_COPYALL)) == NULL) { + if ((mm->m_next = m_copym(m, 0, M_COPYALL, M_NOWAIT)) == NULL) { m_freem(mm); return (ENOBUFS); } @@ -1872,7 +1873,7 @@ pim6_input(struct mbuf **mp, int *offp, int proto) /* * make a copy of the whole header to pass to the daemon later. */ - mcp = m_copy(m, 0, off + PIM6_REG_MINLEN); + mcp = m_copym(m, 0, off + PIM6_REG_MINLEN, M_NOWAIT); if (mcp == NULL) { MRT6_DLOG(DEBUG_ANY | DEBUG_ERR, "pim register: " "could not copy register head"); diff --git a/freebsd/sys/netinet6/ip6_output.c b/freebsd/sys/netinet6/ip6_output.c index d3dc973e..63d1dac1 100644 --- a/freebsd/sys/netinet6/ip6_output.c +++ b/freebsd/sys/netinet6/ip6_output.c @@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -260,7 +261,7 @@ ip6_fragment(struct ifnet *ifp, struct mbuf *m0, int hlen, u_char nextproto, ip6f->ip6f_offlg |= IP6F_MORE_FRAG; mhip6->ip6_plen = htons((u_short)(mtu + hlen + sizeof(*ip6f) - sizeof(struct ip6_hdr))); - if ((m_frgpart = m_copy(m0, off, mtu)) == NULL) { + if ((m_frgpart = m_copym(m0, off, mtu, M_NOWAIT)) == NULL) { IP6STAT_INC(ip6s_odropped); return (ENOBUFS); } @@ -554,6 +555,9 @@ again: rt = ro->ro_rt; ifp = ro->ro_rt->rt_ifp; } else { + if (ro->ro_lle) + LLE_FREE(ro->ro_lle); /* zeros ro_lle */ + ro->ro_lle = NULL; if (fwd_tag == NULL) { bzero(&dst_sa, sizeof(dst_sa)); dst_sa.sin6_family = AF_INET6; @@ -823,6 +827,9 @@ again: } else { RO_RTFREE(ro); needfiblookup = 1; /* Redo the routing table lookup. */ + if (ro->ro_lle) + LLE_FREE(ro->ro_lle); /* zeros ro_lle */ + ro->ro_lle = NULL; } } /* See if fib was changed by packet filter. */ @@ -831,6 +838,9 @@ again: fibnum = M_GETFIB(m); RO_RTFREE(ro); needfiblookup = 1; + if (ro->ro_lle) + LLE_FREE(ro->ro_lle); /* zeros ro_lle */ + ro->ro_lle = NULL; } if (needfiblookup) goto again; @@ -1056,12 +1066,7 @@ sendorfree: IP6STAT_INC(ip6s_fragmented); done: - /* - * Release the route if using our private route, or if - * (with flowtable) we don't have our own reference. - */ - if (ro == &ip6route || - (ro != NULL && ro->ro_flags & RT_NORTREF)) + if (ro == &ip6route) RO_RTFREE(ro); return (error); @@ -1390,6 +1395,15 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt) int retval; #endif +/* + * Don't use more than a quarter of mbuf clusters. N.B.: + * nmbclusters is an int, but nmbclusters * MCLBYTES may overflow + * on LP64 architectures, so cast to u_long to avoid undefined + * behavior. ILP32 architectures cannot have nmbclusters + * large enough to overflow for other reasons. + */ +#define IPV6_PKTOPTIONS_MBUF_LIMIT ((u_long)nmbclusters * MCLBYTES / 4) + level = sopt->sopt_level; op = sopt->sopt_dir; optname = sopt->sopt_name; @@ -1445,6 +1459,12 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt) { struct mbuf *m; + if (optlen > IPV6_PKTOPTIONS_MBUF_LIMIT) { + printf("ip6_ctloutput: mbuf limit hit\n"); + error = ENOBUFS; + break; + } + error = soopt_getm(sopt, &m); /* XXX */ if (error != 0) break; @@ -2995,7 +3015,7 @@ ip6_mloopback(struct ifnet *ifp, struct mbuf *m) struct mbuf *copym; struct ip6_hdr *ip6; - copym = m_copy(m, 0, M_COPYALL); + copym = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (copym == NULL) return; diff --git a/freebsd/sys/netinet6/nd6.c b/freebsd/sys/netinet6/nd6.c index d1c7036d..3e019a62 100644 --- a/freebsd/sys/netinet6/nd6.c +++ b/freebsd/sys/netinet6/nd6.c @@ -40,8 +40,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +#include #include #include #include @@ -49,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -120,6 +121,8 @@ static eventhandler_tag lle_event_eh, iflladdr_event_eh; VNET_DEFINE(struct nd_drhead, nd_defrouter); VNET_DEFINE(struct nd_prhead, nd_prefix); VNET_DEFINE(struct rwlock, nd6_lock); +VNET_DEFINE(uint64_t, nd6_list_genid); +VNET_DEFINE(struct mtx, nd6_onlink_mtx); VNET_DEFINE(int, nd6_recalc_reachtm_interval) = ND6_RECALC_REACHTM_INTERVAL; #define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval) @@ -211,11 +214,10 @@ void nd6_init(void) { - rw_init(&V_nd6_lock, "nd6"); + mtx_init(&V_nd6_onlink_mtx, "nd6 onlink", NULL, MTX_DEF); + rw_init(&V_nd6_lock, "nd6 list"); LIST_INIT(&V_nd_prefix); - - /* initialization of the default router list */ TAILQ_INIT(&V_nd_defrouter); /* Start timers. */ @@ -247,6 +249,7 @@ nd6_destroy() EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_event_eh); } rw_destroy(&V_nd6_lock); + mtx_destroy(&V_nd6_onlink_mtx); } #endif @@ -905,13 +908,15 @@ nd6_timer(void *arg) { CURVNET_SET((struct vnet *) arg); struct nd_drhead drq; + struct nd_prhead prl; struct nd_defrouter *dr, *ndr; struct nd_prefix *pr, *npr; struct in6_ifaddr *ia6, *nia6; + bool onlink_locked; TAILQ_INIT(&drq); + LIST_INIT(&prl); - /* expire default router list */ ND6_WLOCK(); TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) if (dr->expire && dr->expire < time_uptime) @@ -1018,22 +1023,50 @@ nd6_timer(void *arg) } } - /* expire prefix list */ + ND6_WLOCK(); + onlink_locked = false; +restart: LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) { /* - * check prefix lifetime. - * since pltime is just for autoconf, pltime processing for - * prefix is not necessary. + * Expire prefixes. Since the pltime is only used for + * autoconfigured addresses, pltime processing for prefixes is + * not necessary. + * + * Only unlink after all derived addresses have expired. This + * may not occur until two hours after the prefix has expired + * per RFC 4862. If the prefix expires before its derived + * addresses, mark it off-link. This will be done automatically + * after unlinking if no address references remain. */ - if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME && - time_uptime - pr->ndpr_lastupdate > pr->ndpr_vltime) { + if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME || + time_uptime - pr->ndpr_lastupdate <= pr->ndpr_vltime) + continue; - /* - * address expiration and prefix expiration are - * separate. NEVER perform in6_purgeaddr here. - */ - prelist_remove(pr); + if (pr->ndpr_addrcnt == 0) { + nd6_prefix_unlink(pr, &prl); + continue; } + if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) { + if (!onlink_locked) { + onlink_locked = ND6_ONLINK_TRYLOCK(); + if (!onlink_locked) { + ND6_WUNLOCK(); + ND6_ONLINK_LOCK(); + onlink_locked = true; + ND6_WLOCK(); + goto restart; + } + } + (void)nd6_prefix_offlink(pr); + } + } + ND6_WUNLOCK(); + if (onlink_locked) + ND6_ONLINK_UNLOCK(); + + while ((pr = LIST_FIRST(&prl)) != NULL) { + LIST_REMOVE(pr, ndpr_entry); + nd6_prefix_del(pr); } callout_reset(&V_nd6_timer_ch, V_nd6_prune * hz, @@ -1120,10 +1153,12 @@ void nd6_purge(struct ifnet *ifp) { struct nd_drhead drq; + struct nd_prhead prl; struct nd_defrouter *dr, *ndr; struct nd_prefix *pr, *npr; TAILQ_INIT(&drq); + LIST_INIT(&prl); /* * Nuke default router list entries toward ifp. @@ -1138,33 +1173,31 @@ nd6_purge(struct ifnet *ifp) if (dr->ifp == ifp) defrouter_unlink(dr, &drq); } - TAILQ_FOREACH_SAFE(dr, &V_nd_defrouter, dr_entry, ndr) { if (!dr->installed) continue; if (dr->ifp == ifp) defrouter_unlink(dr, &drq); } + + /* + * Remove prefixes on ifp. We should have already removed addresses on + * this interface, so no addresses should be referencing these prefixes. + */ + LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) { + if (pr->ndpr_ifp == ifp) + nd6_prefix_unlink(pr, &prl); + } ND6_WUNLOCK(); + /* Delete the unlinked router and prefix objects. */ while ((dr = TAILQ_FIRST(&drq)) != NULL) { TAILQ_REMOVE(&drq, dr, dr_entry); defrouter_del(dr); } - - /* Nuke prefix list entries toward ifp */ - LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, npr) { - if (pr->ndpr_ifp == ifp) { - /* - * Because if_detach() does *not* release prefixes - * while purging addresses the reference count will - * still be above zero. We therefore reset it to - * make sure that the prefix really gets purged. - */ - pr->ndpr_refcnt = 0; - - prelist_remove(pr); - } + while ((pr = LIST_FIRST(&prl)) != NULL) { + LIST_REMOVE(pr, ndpr_entry); + nd6_prefix_del(pr); } /* cancel default outgoing interface setting */ @@ -1229,8 +1262,9 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp) struct ifaddr *dstaddr; struct rt_addrinfo info; struct sockaddr_in6 rt_key; - struct sockaddr *dst6; - int fibnum; + const struct sockaddr *dst6; + uint64_t genid; + int error, fibnum; /* * A link-local address is always a neighbor. @@ -1268,19 +1302,29 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp) * If the address matches one of our on-link prefixes, it should be a * neighbor. */ + ND6_RLOCK(); +restart: LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) { if (pr->ndpr_ifp != ifp) continue; - if (!(pr->ndpr_stateflags & NDPRF_ONLINK)) { - + if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) { /* Always use the default FIB here. */ - dst6 = (struct sockaddr *)&pr->ndpr_prefix; + dst6 = (const struct sockaddr *)&pr->ndpr_prefix; + + genid = V_nd6_list_genid; + ND6_RUNLOCK(); /* Restore length field before retrying lookup */ rt_key.sin6_len = sizeof(rt_key); - if (rib_lookup_info(fibnum, dst6, 0, 0, &info) != 0) + error = rib_lookup_info(fibnum, dst6, 0, 0, &info); + + ND6_RLOCK(); + if (genid != V_nd6_list_genid) + goto restart; + if (error != 0) continue; + /* * This is the case where multiple interfaces * have the same prefix, but only one is installed @@ -1292,14 +1336,17 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp) * differ. */ if (!IN6_ARE_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr, - &rt_key.sin6_addr)) + &rt_key.sin6_addr)) continue; } if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr, - &addr->sin6_addr, &pr->ndpr_mask)) + &addr->sin6_addr, &pr->ndpr_mask)) { + ND6_RUNLOCK(); return (1); + } } + ND6_RUNLOCK(); /* * If the address is assigned on the node of the other side of @@ -1730,15 +1777,22 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) case SIOCSPFXFLUSH_IN6: { /* flush all the prefix advertised by routers */ + struct in6_ifaddr *ia, *ia_next; struct nd_prefix *pr, *next; + struct nd_prhead prl; + LIST_INIT(&prl); + + ND6_WLOCK(); LIST_FOREACH_SAFE(pr, &V_nd_prefix, ndpr_entry, next) { - struct in6_ifaddr *ia, *ia_next; - if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr)) continue; /* XXX */ + nd6_prefix_unlink(pr, &prl); + } + ND6_WUNLOCK(); - /* do we really have to remove addresses as well? */ + while ((pr = LIST_FIRST(&prl)) != NULL) { + LIST_REMOVE(pr, ndpr_entry); /* XXXRW: in6_ifaddrhead locking. */ TAILQ_FOREACH_SAFE(ia, &V_in6_ifaddrhead, ia_link, ia_next) { @@ -1748,7 +1802,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) if (ia->ia6_ndpr == pr) in6_purgeaddr(&ia->ia_ifa); } - prelist_remove(pr); + nd6_prefix_del(pr); } break; } @@ -2676,7 +2730,7 @@ nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS) else p.expire = maxexpire; } - p.refcnt = pr->ndpr_refcnt; + p.refcnt = pr->ndpr_addrcnt; p.flags = pr->ndpr_stateflags; p.advrtrs = 0; LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) @@ -2692,9 +2746,10 @@ nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS) ip6_sprintf(ip6buf, &pfr->router->rtaddr)); error = SYSCTL_OUT(req, &s6, sizeof(s6)); if (error != 0) - break; + goto out; } } +out: ND6_RUNLOCK(); return (error); } diff --git a/freebsd/sys/netinet6/nd6.h b/freebsd/sys/netinet6/nd6.h index 33ac4386..9b9fa3d1 100644 --- a/freebsd/sys/netinet6/nd6.h +++ b/freebsd/sys/netinet6/nd6.h @@ -256,7 +256,7 @@ struct nd_prefixctl { struct prf_ra ndpr_flags; }; - +LIST_HEAD(nd_prhead, nd_prefix); struct nd_prefix { struct ifnet *ndpr_ifp; LIST_ENTRY(nd_prefix) ndpr_entry; @@ -275,7 +275,8 @@ struct nd_prefix { /* list of routers that advertise the prefix: */ LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs; u_char ndpr_plen; - int ndpr_refcnt; /* reference couter from addresses */ + int ndpr_addrcnt; /* count of derived addresses */ + volatile u_int ndpr_refcnt; }; #define ndpr_raf ndpr_flags @@ -314,8 +315,6 @@ struct nd_pfxrouter { struct nd_defrouter *router; }; -LIST_HEAD(nd_prhead, nd_prefix); - #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_IP6NDP); #endif @@ -346,17 +345,30 @@ VNET_DECLARE(int, nd6_onlink_ns_rfc4861); /* Lock for the prefix and default router lists. */ VNET_DECLARE(struct rwlock, nd6_lock); +VNET_DECLARE(uint64_t, nd6_list_genid); #define V_nd6_lock VNET(nd6_lock) +#define V_nd6_list_genid VNET(nd6_list_genid) #define ND6_RLOCK() rw_rlock(&V_nd6_lock) #define ND6_RUNLOCK() rw_runlock(&V_nd6_lock) #define ND6_WLOCK() rw_wlock(&V_nd6_lock) #define ND6_WUNLOCK() rw_wunlock(&V_nd6_lock) +#define ND6_TRY_UPGRADE() rw_try_upgrade(&V_nd6_lock) #define ND6_WLOCK_ASSERT() rw_assert(&V_nd6_lock, RA_WLOCKED) #define ND6_RLOCK_ASSERT() rw_assert(&V_nd6_lock, RA_RLOCKED) #define ND6_LOCK_ASSERT() rw_assert(&V_nd6_lock, RA_LOCKED) #define ND6_UNLOCK_ASSERT() rw_assert(&V_nd6_lock, RA_UNLOCKED) +/* Mutex for prefix onlink/offlink transitions. */ +VNET_DECLARE(struct mtx, nd6_onlink_mtx); +#define V_nd6_onlink_mtx VNET(nd6_onlink_mtx) + +#define ND6_ONLINK_LOCK() mtx_lock(&V_nd6_onlink_mtx) +#define ND6_ONLINK_TRYLOCK() mtx_trylock(&V_nd6_onlink_mtx) +#define ND6_ONLINK_UNLOCK() mtx_unlock(&V_nd6_onlink_mtx) +#define ND6_ONLINK_LOCK_ASSERT() mtx_assert(&V_nd6_onlink_mtx, MA_OWNED) +#define ND6_ONLINK_UNLOCK_ASSERT() mtx_assert(&V_nd6_onlink_mtx, MA_NOTOWNED) + #define nd6log(x) do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0) /* nd6_rtr.c */ @@ -463,9 +475,14 @@ void defrouter_rele(struct nd_defrouter *); bool defrouter_remove(struct in6_addr *, struct ifnet *); void defrouter_unlink(struct nd_defrouter *, struct nd_drhead *); void defrouter_del(struct nd_defrouter *); -void prelist_remove(struct nd_prefix *); int nd6_prelist_add(struct nd_prefixctl *, struct nd_defrouter *, - struct nd_prefix **); + struct nd_prefix **); +void nd6_prefix_unlink(struct nd_prefix *, struct nd_prhead *); +void nd6_prefix_del(struct nd_prefix *); +void nd6_prefix_ref(struct nd_prefix *); +void nd6_prefix_rele(struct nd_prefix *); +int nd6_prefix_onlink(struct nd_prefix *); +int nd6_prefix_offlink(struct nd_prefix *); void pfxlist_onlink_check(void); struct nd_defrouter *defrouter_lookup(struct in6_addr *, struct ifnet *); struct nd_defrouter *defrouter_lookup_locked(struct in6_addr *, struct ifnet *); diff --git a/freebsd/sys/netinet6/nd6_nbr.c b/freebsd/sys/netinet6/nd6_nbr.c index df50fa93..e30dca8e 100644 --- a/freebsd/sys/netinet6/nd6_nbr.c +++ b/freebsd/sys/netinet6/nd6_nbr.c @@ -1219,40 +1219,26 @@ nd6_dad_start(struct ifaddr *ifa, int delay) struct dadq *dp; char ip6buf[INET6_ADDRSTRLEN]; + KASSERT((ia->ia6_flags & IN6_IFF_TENTATIVE) != 0, + ("starting DAD on non-tentative address %p", ifa)); + /* * If we don't need DAD, don't do it. * There are several cases: - * - DAD is disabled (ip6_dad_count == 0) + * - DAD is disabled globally or on the interface * - the interface address is anycast */ - if (!(ia->ia6_flags & IN6_IFF_TENTATIVE)) { - log(LOG_DEBUG, - "nd6_dad_start: called with non-tentative address " - "%s(%s)\n", - ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), - ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); - return; - } - if (ia->ia6_flags & IN6_IFF_ANYCAST) { + if ((ia->ia6_flags & IN6_IFF_ANYCAST) != 0 || + V_ip6_dad_count == 0 || + (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_NO_DAD) != 0) { ia->ia6_flags &= ~IN6_IFF_TENTATIVE; return; } - if (!V_ip6_dad_count) { - ia->ia6_flags &= ~IN6_IFF_TENTATIVE; + if ((ifa->ifa_ifp->if_flags & IFF_UP) == 0 || + (ifa->ifa_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || + (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IFDISABLED) != 0) return; - } - if (ifa->ifa_ifp == NULL) - panic("nd6_dad_start: ifa->ifa_ifp == NULL"); - if (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_NO_DAD) { - ia->ia6_flags &= ~IN6_IFF_TENTATIVE; - return; - } - if (!(ifa->ifa_ifp->if_flags & IFF_UP) || - !(ifa->ifa_ifp->if_drv_flags & IFF_DRV_RUNNING) || - (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IFDISABLED)) { - ia->ia6_flags |= IN6_IFF_TENTATIVE; - return; - } + if ((dp = nd6_dad_find(ifa, NULL)) != NULL) { /* * DAD is already in progress. Let the existing entry @@ -1331,11 +1317,8 @@ nd6_dad_timer(struct dadq *dp) struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; char ip6buf[INET6_ADDRSTRLEN]; - /* Sanity check */ - if (ia == NULL) { - log(LOG_ERR, "nd6_dad_timer: called with null parameter\n"); - goto err; - } + KASSERT(ia != NULL, ("DAD entry %p with no address", dp)); + if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) { /* Do not need DAD for ifdisabled interface. */ log(LOG_ERR, "nd6_dad_timer: cancel DAD on %s because of " diff --git a/freebsd/sys/netinet6/nd6_rtr.c b/freebsd/sys/netinet6/nd6_rtr.c index c8d7c0ef..33d8fa2a 100644 --- a/freebsd/sys/netinet6/nd6_rtr.c +++ b/freebsd/sys/netinet6/nd6_rtr.c @@ -78,20 +78,16 @@ static int prelist_update(struct nd_prefixctl *, struct nd_defrouter *, struct mbuf *, int); static struct in6_ifaddr *in6_ifadd(struct nd_prefixctl *, int); static struct nd_pfxrouter *pfxrtr_lookup(struct nd_prefix *, - struct nd_defrouter *); + struct nd_defrouter *); static void pfxrtr_add(struct nd_prefix *, struct nd_defrouter *); static void pfxrtr_del(struct nd_pfxrouter *); -static struct nd_pfxrouter *find_pfxlist_reachable_router -(struct nd_prefix *); +static struct nd_pfxrouter *find_pfxlist_reachable_router(struct nd_prefix *); static void defrouter_delreq(struct nd_defrouter *); static void nd6_rtmsg(int, struct rtentry *); static int in6_init_prefix_ltimes(struct nd_prefix *); static void in6_init_address_ltimes(struct nd_prefix *, - struct in6_addrlifetime *); - -static int nd6_prefix_onlink(struct nd_prefix *); -static int nd6_prefix_offlink(struct nd_prefix *); + struct in6_addrlifetime *); static int rt6_deleteroute(const struct rtentry *, void *); @@ -664,6 +660,7 @@ defrouter_unlink(struct nd_defrouter *dr, struct nd_drhead *drq) ND6_WLOCK_ASSERT(); TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry); + V_nd6_list_genid++; if (drq != NULL) TAILQ_INSERT_TAIL(drq, dr, dr_entry); } @@ -673,6 +670,7 @@ defrouter_del(struct nd_defrouter *dr) { struct nd_defrouter *deldr = NULL; struct nd_prefix *pr; + struct nd_pfxrouter *pfxrtr; ND6_UNLOCK_ASSERT(); @@ -691,11 +689,13 @@ defrouter_del(struct nd_defrouter *dr) /* * Also delete all the pointers to the router in each prefix lists. */ + ND6_WLOCK(); LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) { - struct nd_pfxrouter *pfxrtr; if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL) pfxrtr_del(pfxrtr); } + ND6_WUNLOCK(); + pfxlist_onlink_check(); /* @@ -855,14 +855,18 @@ static struct nd_defrouter * defrtrlist_update(struct nd_defrouter *new) { struct nd_defrouter *dr, *n; + uint64_t genid; int oldpref; + bool writelocked; if (new->rtlifetime == 0) { defrouter_remove(&new->rtaddr, new->ifp); return (NULL); } - ND6_WLOCK(); + ND6_RLOCK(); + writelocked = false; +restart: dr = defrouter_lookup_locked(&new->rtaddr, new->ifp); if (dr != NULL) { oldpref = rtpref(dr); @@ -878,10 +882,32 @@ defrtrlist_update(struct nd_defrouter *new) * router is still installed in the kernel. */ if (dr->installed && rtpref(new) == oldpref) { - ND6_WUNLOCK(); + if (writelocked) + ND6_WUNLOCK(); + else + ND6_RUNLOCK(); return (dr); } + } + /* + * The router needs to be reinserted into the default router + * list, so upgrade to a write lock. If that fails and the list + * has potentially changed while the lock was dropped, we'll + * redo the lookup with the write lock held. + */ + if (!writelocked) { + writelocked = true; + if (!ND6_TRY_UPGRADE()) { + genid = V_nd6_list_genid; + ND6_RUNLOCK(); + ND6_WLOCK(); + if (genid != V_nd6_list_genid) + goto restart; + } + } + + if (dr != NULL) { /* * The preferred router may have changed, so relocate this * router. @@ -915,6 +941,7 @@ defrtrlist_update(struct nd_defrouter *new) TAILQ_INSERT_BEFORE(dr, n, dr_entry); else TAILQ_INSERT_TAIL(&V_nd_defrouter, n, dr_entry); + V_nd6_list_genid++; ND6_WUNLOCK(); defrouter_select(); @@ -927,11 +954,12 @@ pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr) { struct nd_pfxrouter *search; + ND6_LOCK_ASSERT(); + LIST_FOREACH(search, &pr->ndpr_advrtrs, pfr_entry) { if (search->router == dr) break; } - return (search); } @@ -939,55 +967,110 @@ static void pfxrtr_add(struct nd_prefix *pr, struct nd_defrouter *dr) { struct nd_pfxrouter *new; + bool update; + + ND6_UNLOCK_ASSERT(); + + ND6_RLOCK(); + if (pfxrtr_lookup(pr, dr) != NULL) { + ND6_RUNLOCK(); + return; + } + ND6_RUNLOCK(); new = malloc(sizeof(*new), M_IP6NDP, M_NOWAIT | M_ZERO); if (new == NULL) return; - new->router = dr; defrouter_ref(dr); + new->router = dr; - LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry); + ND6_WLOCK(); + if (pfxrtr_lookup(pr, dr) == NULL) { + LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry); + update = true; + } else { + /* We lost a race to add the reference. */ + defrouter_rele(dr); + free(new, M_IP6NDP); + update = false; + } + ND6_WUNLOCK(); - pfxlist_onlink_check(); + if (update) + pfxlist_onlink_check(); } static void pfxrtr_del(struct nd_pfxrouter *pfr) { + ND6_WLOCK_ASSERT(); + LIST_REMOVE(pfr, pfr_entry); defrouter_rele(pfr->router); free(pfr, M_IP6NDP); } +static struct nd_prefix * +nd6_prefix_lookup_locked(struct nd_prefixctl *key) +{ + struct nd_prefix *search; + + ND6_LOCK_ASSERT(); + + LIST_FOREACH(search, &V_nd_prefix, ndpr_entry) { + if (key->ndpr_ifp == search->ndpr_ifp && + key->ndpr_plen == search->ndpr_plen && + in6_are_prefix_equal(&key->ndpr_prefix.sin6_addr, + &search->ndpr_prefix.sin6_addr, key->ndpr_plen)) { + nd6_prefix_ref(search); + break; + } + } + return (search); +} + struct nd_prefix * nd6_prefix_lookup(struct nd_prefixctl *key) { struct nd_prefix *search; - LIST_FOREACH(search, &V_nd_prefix, ndpr_entry) { - if (key->ndpr_ifp == search->ndpr_ifp && - key->ndpr_plen == search->ndpr_plen && - in6_are_prefix_equal(&key->ndpr_prefix.sin6_addr, - &search->ndpr_prefix.sin6_addr, key->ndpr_plen)) { - break; - } - } - + ND6_RLOCK(); + search = nd6_prefix_lookup_locked(key); + ND6_RUNLOCK(); return (search); } +void +nd6_prefix_ref(struct nd_prefix *pr) +{ + + refcount_acquire(&pr->ndpr_refcnt); +} + +void +nd6_prefix_rele(struct nd_prefix *pr) +{ + + if (refcount_release(&pr->ndpr_refcnt)) { + KASSERT(LIST_EMPTY(&pr->ndpr_advrtrs), + ("prefix %p has advertising routers", pr)); + free(pr, M_IP6NDP); + } +} + int nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr, struct nd_prefix **newp) { - struct nd_prefix *new = NULL; - int error = 0; + struct nd_prefix *new; char ip6buf[INET6_ADDRSTRLEN]; + int error; new = malloc(sizeof(*new), M_IP6NDP, M_NOWAIT | M_ZERO); if (new == NULL) return (ENOMEM); + refcount_init(&new->ndpr_refcnt, newp != NULL ? 2 : 1); new->ndpr_ifp = pr->ndpr_ifp; new->ndpr_prefix = pr->ndpr_prefix; new->ndpr_plen = pr->ndpr_plen; @@ -1006,20 +1089,22 @@ nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr, /* make prefix in the canonical form */ IN6_MASK_ADDR(&new->ndpr_prefix.sin6_addr, &new->ndpr_mask); - /* link ndpr_entry to nd_prefix list */ + ND6_WLOCK(); LIST_INSERT_HEAD(&V_nd_prefix, new, ndpr_entry); + V_nd6_list_genid++; + ND6_WUNLOCK(); /* ND_OPT_PI_FLAG_ONLINK processing */ if (new->ndpr_raf_onlink) { - int e; - - if ((e = nd6_prefix_onlink(new)) != 0) { + ND6_ONLINK_LOCK(); + if ((error = nd6_prefix_onlink(new)) != 0) { nd6log((LOG_ERR, "nd6_prelist_add: failed to make " "the prefix %s/%d on-link on %s (errno=%d)\n", ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr), - pr->ndpr_plen, if_name(pr->ndpr_ifp), e)); + pr->ndpr_plen, if_name(pr->ndpr_ifp), error)); /* proceed anyway. XXX: is it correct? */ } + ND6_ONLINK_UNLOCK(); } if (dr != NULL) @@ -1029,51 +1114,69 @@ nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr, return (0); } +/* + * Remove a prefix from the prefix list and optionally stash it in a + * caller-provided list. + * + * The ND6 lock must be held. + */ void -prelist_remove(struct nd_prefix *pr) +nd6_prefix_unlink(struct nd_prefix *pr, struct nd_prhead *list) +{ + + KASSERT(pr->ndpr_addrcnt == 0, + ("prefix %p has referencing addresses", pr)); + ND6_WLOCK_ASSERT(); + + LIST_REMOVE(pr, ndpr_entry); + V_nd6_list_genid++; + if (list != NULL) + LIST_INSERT_HEAD(list, pr, ndpr_entry); +} + +/* + * Free an unlinked prefix, first marking it off-link if necessary. + */ +void +nd6_prefix_del(struct nd_prefix *pr) { struct nd_pfxrouter *pfr, *next; int e; char ip6buf[INET6_ADDRSTRLEN]; - /* make sure to invalidate the prefix until it is really freed. */ - pr->ndpr_vltime = 0; - pr->ndpr_pltime = 0; + KASSERT(pr->ndpr_addrcnt == 0, + ("prefix %p has referencing addresses", pr)); + ND6_UNLOCK_ASSERT(); /* * Though these flags are now meaningless, we'd rather keep the value * of pr->ndpr_raf_onlink and pr->ndpr_raf_auto not to confuse users * when executing "ndp -p". */ - - if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0 && - (e = nd6_prefix_offlink(pr)) != 0) { - nd6log((LOG_ERR, "prelist_remove: failed to make %s/%d offlink " - "on %s, errno=%d\n", - ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr), - pr->ndpr_plen, if_name(pr->ndpr_ifp), e)); - /* what should we do? */ + if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) { + ND6_ONLINK_LOCK(); + if ((e = nd6_prefix_offlink(pr)) != 0) { + nd6log((LOG_ERR, + "nd6_prefix_del: failed to make %s/%d offlink " + "on %s, errno=%d\n", + ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr), + pr->ndpr_plen, if_name(pr->ndpr_ifp), e)); + /* what should we do? */ + } + ND6_ONLINK_UNLOCK(); } - if (pr->ndpr_refcnt > 0) - return; /* notice here? */ - - /* unlink ndpr_entry from nd_prefix list */ - LIST_REMOVE(pr, ndpr_entry); - - /* free list of routers that advertised the prefix */ - LIST_FOREACH_SAFE(pfr, &pr->ndpr_advrtrs, pfr_entry, next) { + /* Release references to routers that have advertised this prefix. */ + ND6_WLOCK(); + LIST_FOREACH_SAFE(pfr, &pr->ndpr_advrtrs, pfr_entry, next) pfxrtr_del(pfr); - } - free(pr, M_IP6NDP); + ND6_WUNLOCK(); + + nd6_prefix_rele(pr); pfxlist_onlink_check(); } -/* - * dr - may be NULL - */ - static int prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, struct mbuf *m, int mcast) @@ -1123,21 +1226,22 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, if (new->ndpr_raf_onlink && (pr->ndpr_stateflags & NDPRF_ONLINK) == 0) { - int e; - - if ((e = nd6_prefix_onlink(pr)) != 0) { + ND6_ONLINK_LOCK(); + if ((error = nd6_prefix_onlink(pr)) != 0) { nd6log((LOG_ERR, "prelist_update: failed to make " "the prefix %s/%d on-link on %s " "(errno=%d)\n", ip6_sprintf(ip6buf, - &pr->ndpr_prefix.sin6_addr), - pr->ndpr_plen, if_name(pr->ndpr_ifp), e)); + &pr->ndpr_prefix.sin6_addr), + pr->ndpr_plen, if_name(pr->ndpr_ifp), + error)); /* proceed anyway. XXX: is it correct? */ } + ND6_ONLINK_UNLOCK(); } - if (dr && pfxrtr_lookup(pr, dr) == NULL) + if (dr != NULL) pfxrtr_add(pr, dr); } else { if (new->ndpr_vltime == 0) @@ -1358,7 +1462,7 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, /* * note that we should use pr (not new) for reference. */ - pr->ndpr_refcnt++; + pr->ndpr_addrcnt++; ia6->ia6_ndpr = pr; /* @@ -1396,8 +1500,10 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, } } - end: - return error; +end: + if (pr != NULL) + nd6_prefix_rele(pr); + return (error); } /* @@ -1412,6 +1518,8 @@ find_pfxlist_reachable_router(struct nd_prefix *pr) struct llentry *ln; int canreach; + ND6_LOCK_ASSERT(); + LIST_FOREACH(pfxrtr, &pr->ndpr_advrtrs, pfr_entry) { IF_AFDATA_RLOCK(pfxrtr->router->ifp); ln = nd6_lookup(&pfxrtr->router->rtaddr, 0, pfxrtr->router->ifp); @@ -1434,7 +1542,7 @@ find_pfxlist_reachable_router(struct nd_prefix *pr) * we have moved from the network but the lifetime of the prefix has not * expired yet. So we should not use the prefix if there is another prefix * that has an available router. - * But, if there is no prefix that has an available router, we still regards + * But, if there is no prefix that has an available router, we still regard * all the prefixes as on-link. This is because we can't tell if all the * routers are simply dead or if we really moved from the network and there * is no router around us. @@ -1447,6 +1555,11 @@ pfxlist_onlink_check(void) struct nd_defrouter *dr; struct nd_pfxrouter *pfxrtr = NULL; struct rm_priotracker in6_ifa_tracker; + uint64_t genid; + uint32_t flags; + + ND6_ONLINK_LOCK(); + ND6_RLOCK(); /* * Check if there is a prefix that has a reachable advertising @@ -1462,7 +1575,6 @@ pfxlist_onlink_check(void) * that does not advertise any prefixes. */ if (pr == NULL) { - ND6_RLOCK(); TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) { struct nd_prefix *pr0; @@ -1473,7 +1585,6 @@ pfxlist_onlink_check(void) if (pfxrtr != NULL) break; } - ND6_RUNLOCK(); } if (pr != NULL || (!TAILQ_EMPTY(&V_nd_defrouter) && pfxrtr == NULL)) { /* @@ -1487,40 +1598,26 @@ pfxlist_onlink_check(void) */ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) { /* XXX: a link-local prefix should never be detached */ - if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr)) - continue; - - /* - * we aren't interested in prefixes without the L bit - * set. - */ - if (pr->ndpr_raf_onlink == 0) - continue; - - if (pr->ndpr_raf_auto == 0) + if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) || + pr->ndpr_raf_onlink == 0 || + pr->ndpr_raf_auto == 0) continue; if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 && find_pfxlist_reachable_router(pr) == NULL) pr->ndpr_stateflags |= NDPRF_DETACHED; - if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 && + else if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 && find_pfxlist_reachable_router(pr) != NULL) pr->ndpr_stateflags &= ~NDPRF_DETACHED; } } else { /* there is no prefix that has a reachable router */ LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) { - if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr)) + if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) || + pr->ndpr_raf_onlink == 0 || + pr->ndpr_raf_auto == 0) continue; - - if (pr->ndpr_raf_onlink == 0) - continue; - - if (pr->ndpr_raf_auto == 0) - continue; - - if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0) - pr->ndpr_stateflags &= ~NDPRF_DETACHED; + pr->ndpr_stateflags &= ~NDPRF_DETACHED; } } @@ -1532,34 +1629,30 @@ pfxlist_onlink_check(void) * interfaces. Such cases will be handled in nd6_prefix_onlink, * so we don't have to care about them. */ +restart: LIST_FOREACH(pr, &V_nd_prefix, ndpr_entry) { - int e; char ip6buf[INET6_ADDRSTRLEN]; + int e; - if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr)) + if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) || + pr->ndpr_raf_onlink == 0 || + pr->ndpr_raf_auto == 0) continue; - if (pr->ndpr_raf_onlink == 0) - continue; - - if (pr->ndpr_raf_auto == 0) - continue; - - if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 && - (pr->ndpr_stateflags & NDPRF_ONLINK) != 0) { - if ((e = nd6_prefix_offlink(pr)) != 0) { + flags = pr->ndpr_stateflags & (NDPRF_DETACHED | NDPRF_ONLINK); + if (flags == 0 || flags == (NDPRF_DETACHED | NDPRF_ONLINK)) { + genid = V_nd6_list_genid; + ND6_RUNLOCK(); + if ((flags & NDPRF_ONLINK) != 0 && + (e = nd6_prefix_offlink(pr)) != 0) { nd6log((LOG_ERR, "pfxlist_onlink_check: failed to " "make %s/%d offlink, errno=%d\n", ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr), pr->ndpr_plen, e)); - } - } - if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 && - (pr->ndpr_stateflags & NDPRF_ONLINK) == 0 && - pr->ndpr_raf_onlink) { - if ((e = nd6_prefix_onlink(pr)) != 0) { + } else if ((flags & NDPRF_ONLINK) == 0 && + (e = nd6_prefix_onlink(pr)) != 0) { nd6log((LOG_ERR, "pfxlist_onlink_check: failed to " "make %s/%d onlink, errno=%d\n", @@ -1567,6 +1660,9 @@ pfxlist_onlink_check(void) &pr->ndpr_prefix.sin6_addr), pr->ndpr_plen, e)); } + ND6_RLOCK(); + if (genid != V_nd6_list_genid) + goto restart; } } @@ -1627,6 +1723,8 @@ pfxlist_onlink_check(void) } } IN6_IFADDR_RUNLOCK(&in6_ifa_tracker); + ND6_RUNLOCK(); + ND6_ONLINK_UNLOCK(); } static int @@ -1707,23 +1805,20 @@ nd6_prefix_onlink_rtrequest(struct nd_prefix *pr, struct ifaddr *ifa) return (a_failure); } -static int +int nd6_prefix_onlink(struct nd_prefix *pr) { struct ifaddr *ifa; struct ifnet *ifp = pr->ndpr_ifp; struct nd_prefix *opr; - int error = 0; char ip6buf[INET6_ADDRSTRLEN]; + int error; - /* sanity check */ - if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) { - nd6log((LOG_ERR, - "nd6_prefix_onlink: %s/%d is already on-link\n", - ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr), - pr->ndpr_plen)); + ND6_ONLINK_LOCK_ASSERT(); + ND6_UNLOCK_ASSERT(); + + if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) return (EEXIST); - } /* * Add the interface route associated with the prefix. Before @@ -1732,6 +1827,7 @@ nd6_prefix_onlink(struct nd_prefix *pr) * Although such a configuration is expected to be rare, we explicitly * allow it. */ + ND6_RLOCK(); LIST_FOREACH(opr, &V_nd_prefix, ndpr_entry) { if (opr == pr) continue; @@ -1741,9 +1837,12 @@ nd6_prefix_onlink(struct nd_prefix *pr) if (opr->ndpr_plen == pr->ndpr_plen && in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr, - &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen)) + &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen)) { + ND6_RUNLOCK(); return (0); + } } + ND6_RUNLOCK(); /* * We prefer link-local addresses as the associated interface address. @@ -1755,11 +1854,11 @@ nd6_prefix_onlink(struct nd_prefix *pr) /* XXX: freebsd does not have ifa_ifwithaf */ IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - if (ifa->ifa_addr->sa_family == AF_INET6) + if (ifa->ifa_addr->sa_family == AF_INET6) { + ifa_ref(ifa); break; + } } - if (ifa != NULL) - ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); /* should we care about ia6_flags? */ } @@ -1786,7 +1885,7 @@ nd6_prefix_onlink(struct nd_prefix *pr) return (error); } -static int +int nd6_prefix_offlink(struct nd_prefix *pr) { int error = 0; @@ -1795,16 +1894,14 @@ nd6_prefix_offlink(struct nd_prefix *pr) struct sockaddr_in6 sa6, mask6; struct rtentry *rt; char ip6buf[INET6_ADDRSTRLEN]; + uint64_t genid; int fibnum, a_failure; - /* sanity check */ - if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) { - nd6log((LOG_ERR, - "nd6_prefix_offlink: %s/%d is already off-link\n", - ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr), - pr->ndpr_plen)); + ND6_ONLINK_LOCK_ASSERT(); + ND6_UNLOCK_ASSERT(); + + if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) return (EEXIST); - } bzero(&sa6, sizeof(sa6)); sa6.sin6_family = AF_INET6; @@ -1845,18 +1942,15 @@ nd6_prefix_offlink(struct nd_prefix *pr) * If there's one, try to make the prefix on-link on the * interface. */ + ND6_RLOCK(); +restart: LIST_FOREACH(opr, &V_nd_prefix, ndpr_entry) { - if (opr == pr) - continue; - - if ((opr->ndpr_stateflags & NDPRF_ONLINK) != 0) - continue; - /* * KAME specific: detached prefixes should not be * on-link. */ - if ((opr->ndpr_stateflags & NDPRF_DETACHED) != 0) + if (opr == pr || (opr->ndpr_stateflags & + (NDPRF_ONLINK | NDPRF_DETACHED)) != 0) continue; if (opr->ndpr_plen == pr->ndpr_plen && @@ -1864,6 +1958,8 @@ nd6_prefix_offlink(struct nd_prefix *pr) &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen)) { int e; + genid = V_nd6_list_genid; + ND6_RUNLOCK(); if ((e = nd6_prefix_onlink(opr)) != 0) { nd6log((LOG_ERR, "nd6_prefix_offlink: failed to " @@ -1875,8 +1971,12 @@ nd6_prefix_offlink(struct nd_prefix *pr) if_name(opr->ndpr_ifp), e)); } else a_failure = 0; + ND6_RLOCK(); + if (genid != V_nd6_list_genid) + goto restart; } } + ND6_RUNLOCK(); } else { /* XXX: can we still set the NDPRF_ONLINK flag? */ nd6log((LOG_ERR, @@ -2116,7 +2216,7 @@ in6_tmpifadd(const struct in6_ifaddr *ia0, int forcegen, int delay) return (EINVAL); /* XXX */ } newia->ia6_ndpr = ia0->ia6_ndpr; - newia->ia6_ndpr->ndpr_refcnt++; + newia->ia6_ndpr->ndpr_addrcnt++; ifa_free(&newia->ia_ifa); /* diff --git a/freebsd/sys/netinet6/raw_ip6.c b/freebsd/sys/netinet6/raw_ip6.c index dfd7c45b..5b0577d3 100644 --- a/freebsd/sys/netinet6/raw_ip6.c +++ b/freebsd/sys/netinet6/raw_ip6.c @@ -258,7 +258,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto) } } if (last != NULL) { - struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); + struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT); #ifdef IPSEC /* diff --git a/freebsd/sys/netinet6/sctp6_usrreq.c b/freebsd/sys/netinet6/sctp6_usrreq.c index 962a622e..735de62a 100644 --- a/freebsd/sys/netinet6/sctp6_usrreq.c +++ b/freebsd/sys/netinet6/sctp6_usrreq.c @@ -76,10 +76,8 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port) struct sctphdr *sh; struct sctp_chunkhdr *ch; int length, offset; - #if !defined(SCTP_WITH_NO_CSUM) uint8_t compute_crc; - #endif uint32_t mflowid; uint8_t mflowtype; @@ -196,7 +194,6 @@ sctp6_notify(struct sctp_inpcb *inp, { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; - #endif int timer_stopped; @@ -700,7 +697,6 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, #ifdef INET struct sockaddr_in6 *sin6; - #endif /* INET */ /* No SPL needed since sctp_output does this */ @@ -802,12 +798,10 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p) int error = 0; struct sctp_inpcb *inp; struct sctp_tcb *stcb; - #ifdef INET struct in6pcb *inp6; struct sockaddr_in6 *sin6; union sctp_sockstore store; - #endif #ifdef INET diff --git a/freebsd/sys/netinet6/sctp6_var.h b/freebsd/sys/netinet6/sctp6_var.h index 782567c5..232fee15 100644 --- a/freebsd/sys/netinet6/sctp6_var.h +++ b/freebsd/sys/netinet6/sctp6_var.h @@ -50,6 +50,5 @@ void sctp6_ctlinput(int, struct sockaddr *, void *); void sctp6_notify(struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *, uint8_t, uint8_t, uint16_t); - #endif #endif diff --git a/freebsd/sys/netinet6/udp6_usrreq.c b/freebsd/sys/netinet6/udp6_usrreq.c index 790bed2b..2f950e62 100644 --- a/freebsd/sys/netinet6/udp6_usrreq.c +++ b/freebsd/sys/netinet6/udp6_usrreq.c @@ -368,7 +368,8 @@ udp6_input(struct mbuf **mp, int *offp, int proto) if (last != NULL) { struct mbuf *n; - if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { + if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != + NULL) { INP_RLOCK(last); UDP_PROBE(receive, NULL, last, ip6, last, uh); @@ -900,7 +901,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6, UDP_PROBE(send, NULL, inp, ip6, inp, udp6); UDPSTAT_INC(udps_opackets); - error = ip6_output(m, optp, NULL, flags, + error = ip6_output(m, optp, &inp->inp_route6, flags, inp->in6p_moptions, NULL, inp); break; case AF_INET: diff --git a/freebsd/sys/netpfil/ipfw/ip_fw2.c b/freebsd/sys/netpfil/ipfw/ip_fw2.c index a3a11819..945ad170 100644 --- a/freebsd/sys/netpfil/ipfw/ip_fw2.c +++ b/freebsd/sys/netpfil/ipfw/ip_fw2.c @@ -2728,6 +2728,7 @@ ipfw_init(void) default_fw_tables = IPFW_TABLES_MAX; ipfw_init_sopt_handler(); + ipfw_init_obj_rewriter(); ipfw_iface_init(); return (error); } @@ -2742,6 +2743,7 @@ ipfw_destroy(void) ipfw_iface_destroy(); ipfw_destroy_sopt_handler(); + ipfw_destroy_obj_rewriter(); printf("IP firewall unloaded\n"); } #endif /* __rtems__ */ @@ -2777,7 +2779,6 @@ vnet_ipfw_init(const void *unused) /* Init shared services hash table */ ipfw_init_srv(chain); - ipfw_init_obj_rewriter(); ipfw_init_counters(); /* insert the default rule and create the initial map */ chain->n_rules = 1; @@ -2883,7 +2884,6 @@ vnet_ipfw_uninit(const void *unused) IPFW_LOCK_DESTROY(chain); ipfw_dyn_uninit(1); /* free the remaining parts */ ipfw_destroy_counters(); - ipfw_destroy_obj_rewriter(); ipfw_bpf_uninit(last); return (0); } diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c b/freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c index 4696faac..5694b1d1 100644 --- a/freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c +++ b/freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c @@ -258,9 +258,8 @@ hash_packet6(struct ipfw_flow_id *id) i = (id->dst_ip6.__u6_addr.__u6_addr32[2]) ^ (id->dst_ip6.__u6_addr.__u6_addr32[3]) ^ (id->src_ip6.__u6_addr.__u6_addr32[2]) ^ - (id->src_ip6.__u6_addr.__u6_addr32[3]) ^ - (id->dst_port) ^ (id->src_port); - return i; + (id->src_ip6.__u6_addr.__u6_addr32[3]); + return ntohl(i); } #endif @@ -279,9 +278,9 @@ hash_packet(struct ipfw_flow_id *id, int buckets) i = hash_packet6(id); else #endif /* INET6 */ - i = (id->dst_ip) ^ (id->src_ip) ^ (id->dst_port) ^ (id->src_port); - i &= (buckets - 1); - return i; + i = (id->dst_ip) ^ (id->src_ip); + i ^= (id->dst_port) ^ (id->src_port); + return (i & (buckets - 1)); } #if 0 diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_pfil.c b/freebsd/sys/netpfil/ipfw/ip_fw_pfil.c index 59c13aa5..167d2028 100644 --- a/freebsd/sys/netpfil/ipfw/ip_fw_pfil.c +++ b/freebsd/sys/netpfil/ipfw/ip_fw_pfil.c @@ -305,11 +305,9 @@ again: /* * ipfw processing for ethernet packets (in and out). - * Inteface is NULL from ether_demux, and ifp from - * ether_output_frame. */ int -ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir, +ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir, struct inpcb *inp) { struct ether_header *eh; @@ -319,20 +317,15 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir, struct ip_fw_args args; struct m_tag *mtag; - /* fetch start point from rule, if any */ + /* fetch start point from rule, if any. remove the tag if present. */ mtag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL); if (mtag == NULL) { args.rule.slot = 0; } else { - /* dummynet packet, already partially processed */ - struct ipfw_rule_ref *r; - - /* XXX can we free it after use ? */ - mtag->m_tag_id = PACKET_TAG_NONE; - r = (struct ipfw_rule_ref *)(mtag + 1); - if (r->info & IPFW_ONEPASS) + args.rule = *((struct ipfw_rule_ref *)(mtag+1)); + m_tag_delete(*m0, mtag); + if (args.rule.info & IPFW_ONEPASS) return (0); - args.rule = *r; } /* I need some amt of data to be contiguous */ @@ -350,7 +343,7 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir, m_adj(m, ETHER_HDR_LEN); /* strip ethernet header */ args.m = m; /* the packet we are looking at */ - args.oif = dir == PFIL_OUT ? dst: NULL; /* destination, if any */ + args.oif = dir == PFIL_OUT ? ifp: NULL; /* destination, if any */ args.next_hop = NULL; /* we do not support forward yet */ args.next_hop6 = NULL; /* we do not support forward yet */ args.eh = &save_eh; /* MAC header for bridged/MAC packets */ @@ -385,14 +378,13 @@ ipfw_check_frame(void *arg, struct mbuf **m0, struct ifnet *dst, int dir, case IP_FW_DUMMYNET: ret = EACCES; - int dir; if (ip_dn_io_ptr == NULL) break; /* i.e. drop */ *m0 = NULL; - dir = PROTO_LAYER2 | (dst ? DIR_OUT : DIR_IN); - ip_dn_io_ptr(&m, dir, &args); + dir = (dir == PFIL_IN) ? DIR_IN : DIR_OUT; + ip_dn_io_ptr(&m, dir | PROTO_LAYER2, &args); return 0; default: diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_table.c b/freebsd/sys/netpfil/ipfw/ip_fw_table.c index 9d2baad2..17c5f017 100644 --- a/freebsd/sys/netpfil/ipfw/ip_fw_table.c +++ b/freebsd/sys/netpfil/ipfw/ip_fw_table.c @@ -1089,6 +1089,7 @@ find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct table_config *tc; struct table_algo *ta; struct table_info *kti; + struct table_value *pval; struct namedobj_instance *ni; int error; size_t sz; @@ -1134,7 +1135,10 @@ find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3, return (ENOTSUP); error = ta->find_tentry(tc->astate, kti, tent); - + if (error == 0) { + pval = get_table_value(ch, tc, tent->v.kidx); + ipfw_export_table_value_v1(pval, &tent->v.value); + } IPFW_UH_RUNLOCK(ch); return (error); @@ -2878,13 +2882,12 @@ table_manage_sets(struct ip_fw_chain *ch, uint16_t set, uint8_t new_set, switch (cmd) { case SWAP_ALL: case TEST_ALL: - /* - * Return success for TEST_ALL, since nothing prevents - * move rules from one set to another. All tables are - * accessible from all sets when per-set tables sysctl - * is disabled. - */ case MOVE_ALL: + /* + * Always return success, the real action and decision + * should make table_manage_sets_all(). + */ + return (0); case TEST_ONE: case MOVE_ONE: /* @@ -2909,6 +2912,39 @@ table_manage_sets(struct ip_fw_chain *ch, uint16_t set, uint8_t new_set, set, new_set, cmd)); } +/* + * We register several opcode rewriters for lookup tables. + * All tables opcodes have the same ETLV type, but different subtype. + * To avoid invoking sets handler several times for XXX_ALL commands, + * we use separate manage_sets handler. O_RECV has the lowest value, + * so it should be called first. + */ +static int +table_manage_sets_all(struct ip_fw_chain *ch, uint16_t set, uint8_t new_set, + enum ipfw_sets_cmd cmd) +{ + + switch (cmd) { + case SWAP_ALL: + case TEST_ALL: + /* + * Return success for TEST_ALL, since nothing prevents + * move rules from one set to another. All tables are + * accessible from all sets when per-set tables sysctl + * is disabled. + */ + case MOVE_ALL: + if (V_fw_tables_sets == 0) + return (0); + break; + default: + return (table_manage_sets(ch, set, new_set, cmd)); + } + /* Use generic sets handler when per-set sysctl is enabled. */ + return (ipfw_obj_manage_sets(CHAIN_TO_NI(ch), IPFW_TLV_TBL_NAME, + set, new_set, cmd)); +} + static struct opcode_obj_rewrite opcodes[] = { { .opcode = O_IP_SRC_LOOKUP, @@ -2958,7 +2994,7 @@ static struct opcode_obj_rewrite opcodes[] = { .find_byname = table_findbyname, .find_bykidx = table_findbykidx, .create_object = create_table_compat, - .manage_sets = table_manage_sets, + .manage_sets = table_manage_sets_all, }, { .opcode = O_VIA, diff --git a/freebsd/sys/netpfil/ipfw/nat64/nat64_translate.c b/freebsd/sys/netpfil/ipfw/nat64/nat64_translate.c index d2507674..2f881476 100644 --- a/freebsd/sys/netpfil/ipfw/nat64/nat64_translate.c +++ b/freebsd/sys/netpfil/ipfw/nat64/nat64_translate.c @@ -1258,9 +1258,9 @@ nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t aaddr, uint16_t aport, */ mtu -= sizeof(struct ip6_hdr) - sizeof(struct ip); break; - case ICMP6_TIME_EXCEED_TRANSIT: + case ICMP6_TIME_EXCEEDED: type = ICMP_TIMXCEED; - code = ICMP_TIMXCEED_INTRANS; + code = icmp6->icmp6_code; break; case ICMP6_PARAM_PROB: switch (icmp6->icmp6_code) { diff --git a/freebsd/sys/netpfil/pf/if_pflog.c b/freebsd/sys/netpfil/pf/if_pflog.c index 3a364abc..09473f17 100644 --- a/freebsd/sys/netpfil/pf/if_pflog.c +++ b/freebsd/sys/netpfil/pf/if_pflog.c @@ -223,7 +223,7 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir, if (am == NULL) { hdr.rulenr = htonl(rm->nr); - hdr.subrulenr = 1; + hdr.subrulenr = -1; } else { hdr.rulenr = htonl(am->nr); hdr.subrulenr = htonl(rm->nr); diff --git a/freebsd/sys/netpfil/pf/if_pfsync.c b/freebsd/sys/netpfil/pf/if_pfsync.c index d6a0dfc0..d82a6b74 100644 --- a/freebsd/sys/netpfil/pf/if_pfsync.c +++ b/freebsd/sys/netpfil/pf/if_pfsync.c @@ -1511,7 +1511,7 @@ pfsync_sendout(int schedswi) struct ip *ip; struct pfsync_header *ph; struct pfsync_subheader *subh; - struct pf_state *st; + struct pf_state *st, *st_next; struct pfsync_upd_req_item *ur; int offset; int q, count = 0; @@ -1561,7 +1561,7 @@ pfsync_sendout(int schedswi) offset += sizeof(*subh); count = 0; - TAILQ_FOREACH(st, &sc->sc_qs[q], sync_list) { + TAILQ_FOREACH_SAFE(st, &sc->sc_qs[q], sync_list, st_next) { KASSERT(st->sync_state == q, ("%s: st->sync_state == q", __func__)); @@ -1933,6 +1933,8 @@ pfsync_delete_state(struct pf_state *st) if (sc->sc_len == PFSYNC_MINPKT) callout_reset(&sc->sc_tmo, 1 * hz, pfsync_timeout, V_pfsyncif); + pf_ref_state(st); + switch (st->sync_state) { case PFSYNC_S_INS: /* We never got to tell the world so just forget about it. */ @@ -1952,6 +1954,9 @@ pfsync_delete_state(struct pf_state *st) default: panic("%s: unexpected sync state %d", __func__, st->sync_state); } + + pf_release_state(st); + PFSYNC_UNLOCK(sc); } diff --git a/freebsd/sys/netpfil/pf/pf.c b/freebsd/sys/netpfil/pf/pf.c index 7ac181b5..5b6be3cb 100644 --- a/freebsd/sys/netpfil/pf/pf.c +++ b/freebsd/sys/netpfil/pf/pf.c @@ -3644,7 +3644,7 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a, s->timeout = PFTM_OTHER_FIRST_PACKET; } - if (r->rt && r->rt != PF_FASTROUTE) { + if (r->rt) { if (pf_map_addr(pd->af, r, pd->src, &s->rt_addr, NULL, &sn)) { REASON_SET(&reason, PFRES_MAPFAILED); pf_src_tree_remove_state(s); @@ -5451,41 +5451,24 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, dst.sin_len = sizeof(dst); dst.sin_addr = ip->ip_dst; - if (r->rt == PF_FASTROUTE) { - struct nhop4_basic nh4; - - if (s) - PF_STATE_UNLOCK(s); - - if (fib4_lookup_nh_basic(M_GETFIB(m0), ip->ip_dst, 0, - m0->m_pkthdr.flowid, &nh4) != 0) { - KMOD_IPSTAT_INC(ips_noroute); - error = EHOSTUNREACH; - goto bad; - } - - ifp = nh4.nh_ifp; - dst.sin_addr = nh4.nh_addr; + if (TAILQ_EMPTY(&r->rpool.list)) { + DPFPRINTF(PF_DEBUG_URGENT, + ("%s: TAILQ_EMPTY(&r->rpool.list)\n", __func__)); + goto bad_locked; + } + if (s == NULL) { + pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src, + &naddr, NULL, &sn); + if (!PF_AZERO(&naddr, AF_INET)) + dst.sin_addr.s_addr = naddr.v4.s_addr; + ifp = r->rpool.cur->kif ? + r->rpool.cur->kif->pfik_ifp : NULL; } else { - if (TAILQ_EMPTY(&r->rpool.list)) { - DPFPRINTF(PF_DEBUG_URGENT, - ("%s: TAILQ_EMPTY(&r->rpool.list)\n", __func__)); - goto bad_locked; - } - if (s == NULL) { - pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src, - &naddr, NULL, &sn); - if (!PF_AZERO(&naddr, AF_INET)) - dst.sin_addr.s_addr = naddr.v4.s_addr; - ifp = r->rpool.cur->kif ? - r->rpool.cur->kif->pfik_ifp : NULL; - } else { - if (!PF_AZERO(&s->rt_addr, AF_INET)) - dst.sin_addr.s_addr = - s->rt_addr.v4.s_addr; - ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL; - PF_STATE_UNLOCK(s); - } + if (!PF_AZERO(&s->rt_addr, AF_INET)) + dst.sin_addr.s_addr = + s->rt_addr.v4.s_addr; + ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL; + PF_STATE_UNLOCK(s); } if (ifp == NULL) goto bad; @@ -5627,16 +5610,6 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, dst.sin6_len = sizeof(dst); dst.sin6_addr = ip6->ip6_dst; - /* Cheat. XXX why only in the v6 case??? */ - if (r->rt == PF_FASTROUTE) { - if (s) - PF_STATE_UNLOCK(s); - m0->m_flags |= M_SKIP_FIREWALL; - ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL); - *m = NULL; - return; - } - if (TAILQ_EMPTY(&r->rpool.list)) { DPFPRINTF(PF_DEBUG_URGENT, ("%s: TAILQ_EMPTY(&r->rpool.list)\n", __func__)); @@ -5932,7 +5905,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) pd.sidx = (dir == PF_IN) ? 0 : 1; pd.didx = (dir == PF_IN) ? 1 : 0; pd.af = AF_INET; - pd.tos = h->ip_tos; + pd.tos = h->ip_tos & ~IPTOS_ECN_MASK; pd.tot_len = ntohs(h->ip_len); /* handle fragments that didn't get reassembled by normalization */ diff --git a/freebsd/sys/netpfil/pf/pf_if.c b/freebsd/sys/netpfil/pf/pf_if.c index d1c54b22..29f8e941 100644 --- a/freebsd/sys/netpfil/pf/pf_if.c +++ b/freebsd/sys/netpfil/pf/pf_if.c @@ -525,7 +525,7 @@ pfi_instance_add(struct ifnet *ifp, int net, int flags) int net2, af; IF_ADDR_RLOCK(ifp); - TAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_list) { + TAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) { if (ia->ifa_addr == NULL) continue; af = ia->ifa_addr->sa_family; diff --git a/freebsd/sys/netpfil/pf/pf_ioctl.c b/freebsd/sys/netpfil/pf/pf_ioctl.c index 9c1523ca..076ed5f8 100644 --- a/freebsd/sys/netpfil/pf/pf_ioctl.c +++ b/freebsd/sys/netpfil/pf/pf_ioctl.c @@ -1274,7 +1274,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td pf_mv_pool(&V_pf_pabuf, &rule->rpool.list); if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) || (rule->action == PF_BINAT)) && rule->anchor == NULL) || - (rule->rt > PF_FASTROUTE)) && + (rule->rt > PF_NOPFROUTE)) && (TAILQ_FIRST(&rule->rpool.list) == NULL)) error = EINVAL; @@ -1539,7 +1539,7 @@ DIOCADDRULE_error: if (((((newrule->action == PF_NAT) || (newrule->action == PF_RDR) || (newrule->action == PF_BINAT) || - (newrule->rt > PF_FASTROUTE)) && + (newrule->rt > PF_NOPFROUTE)) && !newrule->anchor)) && (TAILQ_FIRST(&newrule->rpool.list) == NULL)) error = EINVAL; diff --git a/freebsd/sys/netpfil/pf/pf_norm.c b/freebsd/sys/netpfil/pf/pf_norm.c index 86d2c8eb..42b44c70 100644 --- a/freebsd/sys/netpfil/pf/pf_norm.c +++ b/freebsd/sys/netpfil/pf/pf_norm.c @@ -1813,7 +1813,7 @@ pf_scrub_ip(struct mbuf **m0, u_int32_t flags, u_int8_t min_ttl, u_int8_t tos) u_int16_t ov, nv; ov = *(u_int16_t *)h; - h->ip_tos = tos; + h->ip_tos = tos | (h->ip_tos & IPTOS_ECN_MASK); nv = *(u_int16_t *)h; h->ip_sum = pf_cksum_fixup(h->ip_sum, ov, nv, 0); diff --git a/freebsd/sys/opencrypto/crypto.c b/freebsd/sys/opencrypto/crypto.c index 4a013648..2d9787bd 100644 --- a/freebsd/sys/opencrypto/crypto.c +++ b/freebsd/sys/opencrypto/crypto.c @@ -83,7 +83,7 @@ __FBSDID("$FreeBSD$"); #include #include -#if defined(__i386__) || defined(__amd64__) +#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) #include #endif @@ -1254,7 +1254,7 @@ crypto_proc(void) int result, hint; #ifndef __rtems__ -#if defined(__i386__) || defined(__amd64__) +#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) fpu_kern_thread(FPU_KERN_NORMAL); #endif #endif /* __rtems__ */ diff --git a/freebsd/sys/powerpc/include/machine/cpufunc.h b/freebsd/sys/powerpc/include/machine/cpufunc.h index c949d53d..378274b6 100644 --- a/freebsd/sys/powerpc/include/machine/cpufunc.h +++ b/freebsd/sys/powerpc/include/machine/cpufunc.h @@ -82,7 +82,7 @@ static __inline void mtsrin(vm_offset_t va, register_t value) { - __asm __volatile ("mtsrin %0,%1" :: "r"(value), "r"(va)); + __asm __volatile ("mtsrin %0,%1; isync" :: "r"(value), "r"(va)); } static __inline register_t diff --git a/freebsd/sys/powerpc/include/machine/spr.h b/freebsd/sys/powerpc/include/machine/spr.h index 86dac97b..35bd9009 100644 --- a/freebsd/sys/powerpc/include/machine/spr.h +++ b/freebsd/sys/powerpc/include/machine/spr.h @@ -192,6 +192,7 @@ #define FSL_E5500 0x8024 #define FSL_E6500 0x8040 +#define SPR_SPEFSCR 0x200 /* ..8 Signal Processing Engine FSCR. */ #define SPR_IBAT0U 0x210 /* .68 Instruction BAT Reg 0 Upper */ #define SPR_IBAT0U 0x210 /* .6. Instruction BAT Reg 0 Upper */ #define SPR_IBAT0L 0x211 /* .6. Instruction BAT Reg 0 Lower */ @@ -697,8 +698,12 @@ #define SVR_MPC8572E 0x80e8 #define SVR_P1011 0x80e5 #define SVR_P1011E 0x80ed +#define SVR_P1013 0x80e7 +#define SVR_P1013E 0x80ef #define SVR_P1020 0x80e4 #define SVR_P1020E 0x80ec +#define SVR_P1022 0x80e6 +#define SVR_P1022E 0x80ee #define SVR_P2010 0x80e3 #define SVR_P2010E 0x80eb #define SVR_P2020 0x80e2 diff --git a/freebsd/sys/sys/buf.h b/freebsd/sys/sys/buf.h index f32c6ca1..8688056f 100644 --- a/freebsd/sys/sys/buf.h +++ b/freebsd/sys/sys/buf.h @@ -68,6 +68,7 @@ extern struct bio_ops { } bioops; struct vm_object; +struct vm_page; typedef unsigned char b_xflags_t; @@ -139,6 +140,15 @@ struct buf { void *b_fsprivate1; void *b_fsprivate2; void *b_fsprivate3; + +#if defined(FULL_BUF_TRACKING) +#define BUF_TRACKING_SIZE 32 +#define BUF_TRACKING_ENTRY(x) ((x) & (BUF_TRACKING_SIZE - 1)) + const char *b_io_tracking[BUF_TRACKING_SIZE]; + uint32_t b_io_tcnt; +#elif defined(BUF_TRACKING) + const char *b_io_tracking; +#endif }; #define b_object b_bufobj->bo_object @@ -428,6 +438,17 @@ buf_countdeps(struct buf *bp, int i) return (0); } +static __inline void +buf_track(struct buf *bp, const char *location) +{ + +#if defined(FULL_BUF_TRACKING) + bp->b_io_tracking[BUF_TRACKING_ENTRY(bp->b_io_tcnt++)] = location; +#elif defined(BUF_TRACKING) + bp->b_io_tracking = location; +#endif +} + #endif /* _KERNEL */ /* @@ -517,9 +538,11 @@ int cluster_read(struct vnode *, u_quad_t, daddr_t, long, struct ucred *, long, int, int, struct buf **); int cluster_wbuild(struct vnode *, long, daddr_t, int, int); void cluster_write(struct vnode *, struct buf *, u_quad_t, int, int); +void vfs_bio_brelse(struct buf *bp, int ioflags); void vfs_bio_bzero_buf(struct buf *bp, int base, int size); -void vfs_bio_set_valid(struct buf *, int base, int size); void vfs_bio_clrbuf(struct buf *); +void vfs_bio_set_flags(struct buf *bp, int ioflags); +void vfs_bio_set_valid(struct buf *, int base, int size); void vfs_busy_pages(struct buf *, int clear_modify); void vfs_unbusy_pages(struct buf *); int vmapbuf(struct buf *, int); @@ -537,6 +560,12 @@ struct buf *trypbuf(int *); void bwait(struct buf *, u_char, const char *); void bdone(struct buf *); +typedef daddr_t (vbg_get_lblkno_t)(struct vnode *, vm_ooffset_t); +typedef int (vbg_get_blksize_t)(struct vnode *, daddr_t); +int vfs_bio_getpages(struct vnode *vp, struct vm_page **ma, int count, + int *rbehind, int *rahead, vbg_get_lblkno_t get_lblkno, + vbg_get_blksize_t get_blksize); + #endif /* _KERNEL */ #endif /* !_SYS_BUF_H_ */ diff --git a/freebsd/sys/sys/bufobj.h b/freebsd/sys/sys/bufobj.h index 0fa6c8ce..657702c1 100644 --- a/freebsd/sys/sys/bufobj.h +++ b/freebsd/sys/sys/bufobj.h @@ -94,11 +94,6 @@ struct bufobj { struct vm_object *bo_object; /* v Place to store VM object */ LIST_ENTRY(bufobj) bo_synclist; /* S dirty vnode list */ void *bo_private; /* private pointer */ - struct vnode *__bo_vnode; /* - * XXX: This vnode pointer is here - * XXX: only to keep the syncer working - * XXX: for now. - */ struct bufv bo_clean; /* i Clean buffers */ struct bufv bo_dirty; /* i Dirty buffers */ long bo_numoutput; /* i Writes in progress */ diff --git a/freebsd/sys/sys/bus.h b/freebsd/sys/sys/bus.h index 6e356e9c..e62c9bab 100644 --- a/freebsd/sys/sys/bus.h +++ b/freebsd/sys/sys/bus.h @@ -117,6 +117,7 @@ struct devreq { #define DEV_SUSPEND _IOW('D', 5, struct devreq) #define DEV_RESUME _IOW('D', 6, struct devreq) #define DEV_SET_DRIVER _IOW('D', 7, struct devreq) +#define DEV_CLEAR_DRIVER _IOW('D', 8, struct devreq) #define DEV_RESCAN _IOW('D', 9, struct devreq) #define DEV_DELETE _IOW('D', 10, struct devreq) @@ -126,6 +127,9 @@ struct devreq { /* Flags for DEV_SET_DRIVER. */ #define DEVF_SET_DRIVER_DETACH 0x0000001 /* Detach existing driver. */ +/* Flags for DEV_CLEAR_DRIVER. */ +#define DEVF_CLEAR_DRIVER_DETACH 0x0000001 /* Detach existing driver. */ + /* Flags for DEV_DELETE. */ #define DEVF_FORCE_DELETE 0x0000001 diff --git a/freebsd/sys/sys/capsicum.h b/freebsd/sys/sys/capsicum.h index af4da032..a5e64925 100644 --- a/freebsd/sys/sys/capsicum.h +++ b/freebsd/sys/sys/capsicum.h @@ -374,6 +374,8 @@ int cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd); int cap_fcntl_check_fde(struct filedescent *fde, int cmd); int cap_fcntl_check(struct filedesc *fdp, int fd, int cmd); +extern int trap_enotcap; + #else /* !_KERNEL */ __BEGIN_DECLS diff --git a/freebsd/sys/sys/eventhandler.h b/freebsd/sys/sys/eventhandler.h index 9315f8c8..845b28c1 100644 --- a/freebsd/sys/sys/eventhandler.h +++ b/freebsd/sys/sys/eventhandler.h @@ -270,4 +270,11 @@ typedef void (*unregister_framebuffer_fn)(void *, struct fb_info *); EVENTHANDLER_DECLARE(register_framebuffer, register_framebuffer_fn); EVENTHANDLER_DECLARE(unregister_framebuffer, unregister_framebuffer_fn); +/* Veto ada attachment */ +struct cam_path; +struct ata_params; +typedef void (*ada_probe_veto_fn)(void *, struct cam_path *, + struct ata_params *, int *); +EVENTHANDLER_DECLARE(ada_probe_veto, ada_probe_veto_fn); + #endif /* _SYS_EVENTHANDLER_H_ */ diff --git a/freebsd/sys/sys/filedesc.h b/freebsd/sys/sys/filedesc.h index 30c2deef..1e99bfae 100644 --- a/freebsd/sys/sys/filedesc.h +++ b/freebsd/sys/sys/filedesc.h @@ -175,7 +175,11 @@ void filecaps_init(struct filecaps *fcaps); int filecaps_copy(const struct filecaps *src, struct filecaps *dst, bool locked); void filecaps_move(struct filecaps *src, struct filecaps *dst); +#ifndef __rtems__ void filecaps_free(struct filecaps *fcaps); +#else /* __rtems__ */ +#define filecaps_free(fcaps) do { } while (0) +#endif /* __rtems__ */ int closef(struct file *fp, struct thread *td); int dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode, @@ -245,6 +249,11 @@ int getvnode(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); void mountcheckdirs(struct vnode *olddp, struct vnode *newdp); +int fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, + struct file **fpp, struct filecaps *havecapsp); +int fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, + struct file **fpp, struct filecaps *havecapsp); + /* Return a referenced file from an unlocked descriptor. */ #ifndef __rtems__ int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, @@ -282,12 +291,31 @@ fget_locked(struct filedesc *fdp, int fd) return (fdp->fd_ofiles[fd].fde_file); } +static __inline struct filedescent * +fdeget_locked(struct filedesc *fdp, int fd) +{ + struct filedescent *fde; + + FILEDESC_LOCK_ASSERT(fdp); + + if (fd < 0 || fd > fdp->fd_lastfile) + return (NULL); + + fde = &fdp->fd_ofiles[fd]; + if (fde->fde_file == NULL) + return (NULL); + + return (fde); +} + +#ifdef CAPABILITIES static __inline bool fd_modified(struct filedesc *fdp, int fd, seq_t seq) { return (!seq_consistent(fd_seq(fdp->fd_files, fd), seq)); } +#endif #endif /* __rtems__ */ /* cdir/rdir/jdir manipulation functions. */ diff --git a/freebsd/sys/sys/linker.h b/freebsd/sys/sys/linker.h index 90db1b8c..eecb4cdd 100644 --- a/freebsd/sys/sys/linker.h +++ b/freebsd/sys/sys/linker.h @@ -73,6 +73,7 @@ struct linker_file { int userrefs; /* kldload(2) count */ int flags; #define LINKER_FILE_LINKED 0x1 /* file has been fully linked */ +#define LINKER_FILE_MODULES 0x2 /* file has >0 modules at preload */ TAILQ_ENTRY(linker_file) link; /* list of all loaded files */ char* filename; /* file which was loaded */ char* pathname; /* file name with full path */ diff --git a/freebsd/sys/sys/mbuf.h b/freebsd/sys/sys/mbuf.h index 95194e0b..9ce52a17 100644 --- a/freebsd/sys/sys/mbuf.h +++ b/freebsd/sys/sys/mbuf.h @@ -174,6 +174,7 @@ struct pkthdr { #define PH_vt PH_per #define vt_nrecs sixteen[0] #define tso_segsz PH_per.sixteen[1] +#define lro_nsegs tso_segsz #define csum_phsum PH_per.sixteen[2] #define csum_data PH_per.thirtytwo[1] @@ -334,7 +335,7 @@ struct mbuf { #define M_HASHTYPE_RSS_TCP_IPV6 M_HASHTYPE_HASH(4) /* TCPv6 4-tuple */ #define M_HASHTYPE_RSS_IPV6_EX M_HASHTYPE_HASH(5) /* IPv6 2-tuple + * ext hdrs */ -#define M_HASHTYPE_RSS_TCP_IPV6_EX M_HASHTYPE_HASH(6) /* TCPv6 4-tiple + +#define M_HASHTYPE_RSS_TCP_IPV6_EX M_HASHTYPE_HASH(6) /* TCPv6 4-tuple + * ext hdrs */ /* Non-standard RSS hash types */ #define M_HASHTYPE_RSS_UDP_IPV4 M_HASHTYPE_HASH(7) /* IPv4 UDP 4-tuple*/ @@ -392,7 +393,7 @@ struct mbuf { #define EXT_JUMBO9 4 /* jumbo cluster 9216 bytes */ #define EXT_JUMBO16 5 /* jumbo cluster 16184 bytes */ #define EXT_PACKET 6 /* mbuf+cluster from packet zone */ -#define EXT_MBUF 7 /* external mbuf reference (M_IOVEC) */ +#define EXT_MBUF 7 /* external mbuf reference */ #ifndef __rtems__ #define EXT_SFBUF_NOCACHE 8 /* sendfile(2)'s sf_buf not to be cached */ #endif /* __rtems__ */ @@ -983,9 +984,6 @@ m_align(struct mbuf *m, int len) /* Length to m_copy to copy all. */ #define M_COPYALL 1000000000 -/* Compatibility with 4.3. */ -#define m_copy(m, o, l) m_copym((m), (o), (l), M_NOWAIT) - extern int max_datalen; /* MHLEN - max_hdr */ extern int max_hdr; /* Largest link + protocol header */ extern int max_linkhdr; /* Largest link-level header */ diff --git a/freebsd/sys/sys/module.h b/freebsd/sys/sys/module.h index 07464fc6..71aa9954 100644 --- a/freebsd/sys/sys/module.h +++ b/freebsd/sys/sys/module.h @@ -233,7 +233,7 @@ extern int mod_debug; #define MOD_DPF(cat, args) do { \ if (mod_debug & MOD_DEBUG_##cat) \ - printf(args); \ + printf args; \ } while (0) #else /* !MOD_DEBUG */ diff --git a/freebsd/sys/sys/mount.h b/freebsd/sys/sys/mount.h index 49e688f3..1bf583a6 100644 --- a/freebsd/sys/sys/mount.h +++ b/freebsd/sys/sys/mount.h @@ -147,6 +147,7 @@ struct vfsopt { * put on a doubly linked list. * * Lock reference: + * l - mnt_listmtx * m - mountlist_mtx * i - interlock * v - vnode freelist mutex @@ -166,8 +167,6 @@ struct mount { int mnt_ref; /* (i) Reference count */ struct vnodelst mnt_nvnodelist; /* (i) list of vnodes */ int mnt_nvnodelistsize; /* (i) # of vnodes */ - struct vnodelst mnt_activevnodelist; /* (v) list of active vnodes */ - int mnt_activevnodelistsize;/* (v) # of active vnodes */ int mnt_writeopcount; /* (i) write syscalls pending */ int mnt_kern_flag; /* (i) kernel only flags */ uint64_t mnt_flag; /* (i) flags shared with user */ @@ -188,6 +187,11 @@ struct mount { struct thread *mnt_susp_owner; /* (i) thread owning suspension */ #define mnt_endzero mnt_gjprovider char *mnt_gjprovider; /* gjournal provider name */ + struct mtx mnt_listmtx; + struct vnodelst mnt_activevnodelist; /* (l) list of active vnodes */ + int mnt_activevnodelistsize;/* (l) # of active vnodes */ + struct vnodelst mnt_tmpfreevnodelist; /* (l) list of free vnodes */ + int mnt_tmpfreevnodelistsize;/* (l) # of free vnodes */ struct lock mnt_explock; /* vfs_export walkers lock */ TAILQ_ENTRY(mount) mnt_upper_link; /* (m) we in the all uppers */ TAILQ_HEAD(, mount) mnt_uppers; /* (m) upper mounts over us*/ @@ -366,7 +370,8 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *); #define MNTK_SUSPEND 0x08000000 /* request write suspension */ #define MNTK_SUSPEND2 0x04000000 /* block secondary writes */ #define MNTK_SUSPENDED 0x10000000 /* write operations are suspended */ -#define MNTK_UNUSED1 0x20000000 +#define MNTK_NULL_NOCACHE 0x20000000 /* auto disable cache for nullfs + mounts over this fs */ #define MNTK_LOOKUP_SHARED 0x40000000 /* FS supports shared lock lookups */ #define MNTK_NOKNOTE 0x80000000 /* Don't send KNOTEs from VOP hooks */ diff --git a/freebsd/sys/sys/proc.h b/freebsd/sys/sys/proc.h index 4a695ef9..03aae8f8 100644 --- a/freebsd/sys/sys/proc.h +++ b/freebsd/sys/sys/proc.h @@ -761,6 +761,7 @@ struct proc { #define P2_NOTRACE_EXEC 0x00000004 /* Keep P2_NOPTRACE on exec(2). */ #define P2_AST_SU 0x00000008 /* Handles SU ast for kthreads. */ #define P2_PTRACE_FSTP 0x00000010 /* SIGSTOP from PT_ATTACH not yet handled. */ +#define P2_TRAPCAP 0x00000020 /* SIGTRAP on ENOTCAPABLE */ /* Flags protected by proctree_lock, kept in p_treeflags. */ #define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */ diff --git a/freebsd/sys/sys/sf_buf.h b/freebsd/sys/sys/sf_buf.h index b5970d95..6aebe430 100644 --- a/freebsd/sys/sys/sf_buf.h +++ b/freebsd/sys/sys/sf_buf.h @@ -41,6 +41,7 @@ struct sfstat { /* sendfile statistics */ uint64_t sf_busy; /* times aborted on a busy page */ uint64_t sf_allocfail; /* times sfbuf allocation failed */ uint64_t sf_allocwait; /* times sfbuf allocation had to wait */ + uint64_t sf_pages_bogus; /* times bogus page was used */ }; #ifdef _KERNEL diff --git a/freebsd/sys/sys/socket.h b/freebsd/sys/sys/socket.h index f23b5f69..ea3d9b6b 100644 --- a/freebsd/sys/sys/socket.h +++ b/freebsd/sys/sys/socket.h @@ -590,6 +590,7 @@ struct sf_hdtr { #define SF_NODISKIO 0x00000001 #define SF_MNOWAIT 0x00000002 /* obsolete */ #define SF_SYNC 0x00000004 +#define SF_USER_READAHEAD 0x00000008 #define SF_NOCACHE 0x00000010 #define SF_FLAGS(rh, flags) (((rh) << 16) | (flags)) diff --git a/freebsd/sys/sys/socketvar.h b/freebsd/sys/sys/socketvar.h index 72eaa998..1e599a66 100644 --- a/freebsd/sys/sys/socketvar.h +++ b/freebsd/sys/sys/socketvar.h @@ -321,6 +321,7 @@ extern u_long sb_max; extern so_gen_t so_gencnt; struct file; +struct filecaps; struct filedesc; struct mbuf; struct sockaddr; @@ -340,7 +341,7 @@ struct uio; */ int getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len); int getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp, - struct file **fpp, u_int *fflagp); + struct file **fpp, u_int *fflagp, struct filecaps *havecaps); void soabort(struct socket *so); int soaccept(struct socket *so, struct sockaddr **nam); void soaio_enqueue(struct task *task); diff --git a/freebsd/sys/sys/sysctl.h b/freebsd/sys/sys/sysctl.h index 687fb23b..291b7e44 100644 --- a/freebsd/sys/sys/sysctl.h +++ b/freebsd/sys/sys/sysctl.h @@ -876,6 +876,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); #define KERN_IOV_MAX 35 /* int: value of UIO_MAXIOV */ #define KERN_HOSTUUID 36 /* string: host UUID identifier */ #define KERN_ARND 37 /* int: from arc4rand() */ +#define KERN_MAXPHYS 38 /* int: MAXPHYS value */ /* * KERN_PROC subtypes */ diff --git a/freebsd/sys/sys/sysproto.h b/freebsd/sys/sys/sysproto.h index 1ee7bb4e..b3c944bf 100644 --- a/freebsd/sys/sys/sysproto.h +++ b/freebsd/sys/sys/sysproto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 304395 2016-08-18 10:50:40Z gnn + * created from FreeBSD: head/sys/kern/syscalls.master 309677 2016-12-07 16:11:55Z rwatson */ #ifndef _SYS_SYSPROTO_H_ diff --git a/freebsd/sys/sys/user.h b/freebsd/sys/sys/user.h index d0da0455..9dad4d0a 100644 --- a/freebsd/sys/sys/user.h +++ b/freebsd/sys/sys/user.h @@ -180,12 +180,13 @@ struct kinfo_proc { char ki_comm[COMMLEN+1]; /* command name */ char ki_emul[KI_EMULNAMELEN+1]; /* emulation name */ char ki_loginclass[LOGINCLASSLEN+1]; /* login class */ + char ki_moretdname[MAXCOMLEN-TDNAMLEN+1]; /* more thread name */ /* * When adding new variables, take space for char-strings from the * front of ki_sparestrings, and ints from the end of ki_spareints. * That way the spare room from both arrays will remain contiguous. */ - char ki_sparestrings[50]; /* spare string space */ + char ki_sparestrings[46]; /* spare string space */ int ki_spareints[KI_NSPARE_INT]; /* spare room for growth */ int ki_oncpu; /* Which cpu we are on */ int ki_lastcpu; /* Last cpu we were on */ diff --git a/freebsd/sys/sys/vmmeter.h b/freebsd/sys/sys/vmmeter.h index 39f03d0d..31312b0a 100644 --- a/freebsd/sys/sys/vmmeter.h +++ b/freebsd/sys/sys/vmmeter.h @@ -75,11 +75,11 @@ struct vmmeter { u_int v_vnodepgsin; /* (p) vnode_pager pages paged in */ u_int v_vnodepgsout; /* (p) vnode pager pages paged out */ u_int v_intrans; /* (p) intransit blocking page faults */ - u_int v_reactivated; /* (f) pages reactivated from free list */ + u_int v_reactivated; /* (p) pages reactivated by the pagedaemon */ u_int v_pdwakeups; /* (p) times daemon has awaken from sleep */ u_int v_pdpages; /* (p) pages analyzed by daemon */ + u_int v_pdshortfalls; /* (p) page reclamation shortfalls */ - u_int v_tcached; /* (p) total pages cached */ u_int v_dfree; /* (p) pages freed by daemon */ u_int v_pfree; /* (p) pages freed by exiting processes */ u_int v_tfree; /* (p) total pages freed */ @@ -96,7 +96,7 @@ struct vmmeter { u_int v_active_count; /* (q) pages active */ u_int v_inactive_target; /* (c) pages desired inactive */ u_int v_inactive_count; /* (q) pages inactive */ - u_int v_cache_count; /* (f) pages on cache queue */ + u_int v_laundry_count; /* (q) pages eligible for laundering */ u_int v_pageout_free_min; /* (c) min pages reserved for kernel */ u_int v_interrupt_free_min; /* (c) reserved pages for int code */ u_int v_free_severe; /* (c) severe page depletion point */ @@ -111,7 +111,6 @@ struct vmmeter { u_int v_vforkpages; /* (p) VM pages affected by vfork() */ u_int v_rforkpages; /* (p) VM pages affected by rfork() */ u_int v_kthreadpages; /* (p) VM pages affected by fork() by kernel */ - u_int v_spare[2]; }; #ifdef _KERNEL @@ -129,8 +128,7 @@ static inline int vm_page_count_severe(void) { - return (vm_cnt.v_free_severe > vm_cnt.v_free_count + - vm_cnt.v_cache_count); + return (vm_cnt.v_free_severe > vm_cnt.v_free_count); } /* @@ -146,7 +144,7 @@ static inline int vm_page_count_min(void) { - return (vm_cnt.v_free_min > vm_cnt.v_free_count + vm_cnt.v_cache_count); + return (vm_cnt.v_free_min > vm_cnt.v_free_count); } /* @@ -157,8 +155,7 @@ static inline int vm_page_count_target(void) { - return (vm_cnt.v_free_target > vm_cnt.v_free_count + - vm_cnt.v_cache_count); + return (vm_cnt.v_free_target > vm_cnt.v_free_count); } /* @@ -169,8 +166,7 @@ static inline int vm_paging_target(void) { - return (vm_cnt.v_free_target - (vm_cnt.v_free_count + - vm_cnt.v_cache_count)); + return (vm_cnt.v_free_target - vm_cnt.v_free_count); } /* @@ -180,10 +176,28 @@ static inline int vm_paging_needed(void) { - return (vm_cnt.v_free_count + vm_cnt.v_cache_count < - vm_pageout_wakeup_thresh); + return (vm_cnt.v_free_count < vm_pageout_wakeup_thresh); } +/* + * Return the number of pages we need to launder. + * A positive number indicates that we have a shortfall of clean pages. + */ +static inline int +vm_laundry_target(void) +{ + + return (vm_paging_target()); +} + +/* + * Obtain the value of a per-CPU counter. + */ +#define VM_METER_PCPU_CNT(member) \ + vm_meter_cnt(__offsetof(struct vmmeter, member)) + +u_int vm_meter_cnt(size_t); + #endif /* systemwide totals computed every five seconds */ diff --git a/freebsd/sys/sys/vnode.h b/freebsd/sys/sys/vnode.h index a047bc67..5400fe1c 100644 --- a/freebsd/sys/sys/vnode.h +++ b/freebsd/sys/sys/vnode.h @@ -76,8 +76,8 @@ struct vpollinfo { * * Lock reference: * c - namecache mutex - * f - freelist mutex * i - interlock + * l - mp mnt_listmtx or freelist mutex * I - updated with atomics, 0->1 and 1->0 transitions with interlock held * m - mount point interlock * p - pollinfo lock @@ -145,7 +145,7 @@ struct vnode { /* * The machinery of being a vnode */ - TAILQ_ENTRY(vnode) v_actfreelist; /* f vnode active/free lists */ + TAILQ_ENTRY(vnode) v_actfreelist; /* l vnode active/free lists */ struct bufobj v_bufobj; /* * Buffer cache object */ /* @@ -168,6 +168,7 @@ struct vnode { u_int v_usecount; /* I ref count of users */ u_int v_iflag; /* i vnode flags (see below) */ u_int v_vflag; /* v vnode flags */ + u_int v_mflag; /* l mnt-specific vnode flags */ int v_writecount; /* v ref count of writers */ u_int v_hash; enum vtype v_type; /* u vnode type */ @@ -180,6 +181,8 @@ struct vnode { #define v_rdev v_un.vu_cdev #define v_fifoinfo v_un.vu_fifoinfo +#define bo2vnode(bo) __containerof((bo), struct vnode, v_bufobj) + /* XXX: These are temporary to avoid a source sweep at this time */ #define v_object v_bufobj.bo_object @@ -255,6 +258,8 @@ struct xvnode { #define VV_MD 0x0800 /* vnode backs the md device */ #define VV_FORCEINSMQ 0x1000 /* force the insmntque to succeed */ +#define VMP_TMPMNTFREELIST 0x0001 /* Vnode is on mnt's tmp free list */ + /* * Vnode attributes. A field value of VNOVAL represents a field whose value * is unavailable (getattr) or which is not to be changed (setattr). @@ -303,6 +308,7 @@ struct vattr { #define IO_INVAL 0x0040 /* invalidate after I/O */ #define IO_SYNC 0x0080 /* do I/O synchronously */ #define IO_DIRECT 0x0100 /* attempt to bypass buffer cache */ +#define IO_NOREUSE 0x0200 /* VMIO data won't be reused */ #define IO_EXT 0x0400 /* operate on external attributes */ #define IO_NORMAL 0x0800 /* operate on regular data */ #define IO_NOMACCHECK 0x1000 /* MAC checks unnecessary */ @@ -604,7 +610,7 @@ int cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct timespec *tsp, int *ticksp); void cache_purge(struct vnode *vp); void cache_purge_negative(struct vnode *vp); -void cache_purgevfs(struct mount *mp); +void cache_purgevfs(struct mount *mp, bool force); int change_dir(struct vnode *vp, struct thread *td); void cvtstat(struct stat *st, struct ostat *ost); void cvtnstat(struct stat *sb, struct nstat *nsb); @@ -655,6 +661,7 @@ int vtruncbuf(struct vnode *vp, struct ucred *cred, off_t length, void vunref(struct vnode *); void vn_printf(struct vnode *vp, const char *fmt, ...) __printflike(2,3); int vrecycle(struct vnode *vp); +int vrecyclel(struct vnode *vp); int vn_bmap_seekhole(struct vnode *vp, u_long cmd, off_t *off, struct ucred *cred); int vn_close(struct vnode *vp, diff --git a/freebsd/sys/vm/uma_core.c b/freebsd/sys/vm/uma_core.c index 3957a223..00ac3e5a 100644 --- a/freebsd/sys/vm/uma_core.c +++ b/freebsd/sys/vm/uma_core.c @@ -880,8 +880,7 @@ static void keg_drain(uma_keg_t keg) { struct slabhead freeslabs = { 0 }; - uma_slab_t slab; - uma_slab_t n; + uma_slab_t slab, tmp; /* * We don't want to take pages from statically allocated kegs at this @@ -897,16 +896,11 @@ keg_drain(uma_keg_t keg) if (keg->uk_free == 0) goto finished; - slab = LIST_FIRST(&keg->uk_free_slab); - while (slab) { - n = LIST_NEXT(slab, us_link); - + LIST_FOREACH_SAFE(slab, &keg->uk_free_slab, us_link, tmp) { #ifndef __rtems__ - /* We have no where to free these to */ - if (slab->us_flags & UMA_SLAB_BOOT) { - slab = n; + /* We have nowhere to free these to. */ + if (slab->us_flags & UMA_SLAB_BOOT) continue; - } #endif /* __rtems__ */ LIST_REMOVE(slab, us_link); @@ -917,8 +911,6 @@ keg_drain(uma_keg_t keg) UMA_HASH_REMOVE(&keg->uk_hash, slab, slab->us_data); SLIST_INSERT_HEAD(&freeslabs, slab, us_hlink); - - slab = n; } finished: KEG_UNLOCK(keg); diff --git a/freebsd/usr.bin/netstat/mbuf.c b/freebsd/usr.bin/netstat/mbuf.c index 81f57292..446592ae 100644 --- a/freebsd/usr.bin/netstat/mbuf.c +++ b/freebsd/usr.bin/netstat/mbuf.c @@ -361,6 +361,9 @@ mbpr(void *kvmd, u_long mbaddr) xo_emit("{:sendfile-pages-valid/%ju} " "{N:pages were valid at time of a sendfile request}\n", (uintmax_t)sfstat.sf_pages_valid); + xo_emit("{:sendfile-pages-bogus/%ju} " + "{N:pages were valid and substituted to bogus page}\n", + (uintmax_t)sfstat.sf_pages_bogus); xo_emit("{:sendfile-requested-readahead/%ju} " "{N:pages were requested for read ahead by applications}\n", (uintmax_t)sfstat.sf_rhpages_requested); diff --git a/freebsd/usr.bin/netstat/route.c b/freebsd/usr.bin/netstat/route.c index bed58b06..da799825 100644 --- a/freebsd/usr.bin/netstat/route.c +++ b/freebsd/usr.bin/netstat/route.c @@ -125,7 +125,9 @@ static int ifmap_size; static struct timespec uptime; static const char *netname4(in_addr_t, in_addr_t); +#ifdef INET6 static const char *netname6(struct sockaddr_in6 *, struct sockaddr_in6 *); +#endif static void p_rtable_sysctl(int, int); static void p_rtentry_sysctl(const char *name, struct rt_msghdr *); static int p_sockaddr(const char *name, struct sockaddr *, struct sockaddr *, diff --git a/freebsd/usr.bin/vmstat/vmstat.c b/freebsd/usr.bin/vmstat/vmstat.c index ed146562..8f9daa9a 100644 --- a/freebsd/usr.bin/vmstat/vmstat.c +++ b/freebsd/usr.bin/vmstat/vmstat.c @@ -623,7 +623,7 @@ fill_vmmeter(struct vmmeter *vmmp) GET_VM_STATS(vm, v_reactivated); GET_VM_STATS(vm, v_pdwakeups); GET_VM_STATS(vm, v_pdpages); - GET_VM_STATS(vm, v_tcached); + GET_VM_STATS(vm, v_pdshortfalls); GET_VM_STATS(vm, v_dfree); GET_VM_STATS(vm, v_pfree); GET_VM_STATS(vm, v_tfree); @@ -637,7 +637,7 @@ fill_vmmeter(struct vmmeter *vmmp) GET_VM_STATS(vm, v_active_count); GET_VM_STATS(vm, v_inactive_target); GET_VM_STATS(vm, v_inactive_count); - GET_VM_STATS(vm, v_cache_count); + GET_VM_STATS(vm, v_laundry_count); GET_VM_STATS(vm, v_pageout_free_min); GET_VM_STATS(vm, v_interrupt_free_min); /*GET_VM_STATS(vm, v_free_severe);*/ @@ -1115,7 +1115,9 @@ dosum(void) sum.v_pdwakeups); xo_emit("{:page-daemon-pages/%9u} {N:pages examined by the page daemon}\n", sum.v_pdpages); - xo_emit("{:reactivated/%9u} {N:pages reactivated}\n", + xo_emit("{:page-reclamation-shortfalls/%9u} {N:clean page reclamation shortfalls}\n", + sum.v_pdshortfalls); + xo_emit("{:reactivated/%9u} {N:pages reactivated by the page daemon}\n", sum.v_reactivated); xo_emit("{:copy-on-write-faults/%9u} {N:copy-on-write faults}\n", sum.v_cow_faults); @@ -1139,8 +1141,6 @@ dosum(void) sum.v_vforkpages); xo_emit("{:pages-rfork/%9u} {N:pages affected by rfork}()\n", sum.v_rforkpages); - xo_emit("{:pages-total-cached/%9u} {N:pages cached}\n", - sum.v_tcached); xo_emit("{:pages-freed/%9u} {N:pages freed}\n", sum.v_tfree); xo_emit("{:pages-freed-by-daemon/%9u} {N:pages freed by daemon}\n", @@ -1151,8 +1151,8 @@ dosum(void) sum.v_active_count); xo_emit("{:inactive-pages/%9u} {N:pages inactive}\n", sum.v_inactive_count); - xo_emit("{:vm-cache/%9u} {N:pages in VM cache}\n", - sum.v_cache_count); + xo_emit("{:laundry-pages/%9u} {N:pages in the laundry queue}\n", + sum.v_laundry_count); xo_emit("{:wired-pages/%9u} {N:pages wired down}\n", sum.v_wire_count); xo_emit("{:free-pages/%9u} {N:pages free}\n", diff --git a/libbsd.txt b/libbsd.txt index 2d0a012c..12a28809 100644 --- a/libbsd.txt +++ b/libbsd.txt @@ -776,7 +776,7 @@ detail and debug level information from the command. == FreeBSD version of imported files and directories -. *, trunk, 2016-08-23, 9fe7c416e6abb28b1398fd3e5687099846800cfd +. *, trunk, 2016-12-10, 80c55f08a05ab3b26a73b226ccb56adc3122a55c. == How to import code from FreeBSD diff --git a/rtemsbsd/include/machine/rtems-bsd-kernel-space.h b/rtemsbsd/include/machine/rtems-bsd-kernel-space.h index 49dc3aad..10ce9d2d 100644 --- a/rtemsbsd/include/machine/rtems-bsd-kernel-space.h +++ b/rtemsbsd/include/machine/rtems-bsd-kernel-space.h @@ -80,4 +80,6 @@ void rtems_bsd_assert_func(const char *file, int line, const char *func, const c #define BSD_DEFAULT_PRISON (&prison0) +#define kdb_active 0 + #endif /* _RTEMS_BSD_MACHINE_RTEMS_BSD_KERNEL_SPACE_H_ */ diff --git a/rtemsbsd/include/rtems/bsd/sys/param.h b/rtemsbsd/include/rtems/bsd/sys/param.h index a21e94aa..fb9b80cc 100644 --- a/rtemsbsd/include/rtems/bsd/sys/param.h +++ b/rtemsbsd/include/rtems/bsd/sys/param.h @@ -62,7 +62,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1200003 /* Master, propagated to newvers */ +#define __FreeBSD_version 1200018 /* Master, propagated to newvers */ #ifdef _KERNEL #define P_OSREL_SIGWAIT 700000