}
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
- if (ip6_mapped_addr_on && (inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
if (IN6_IS_ADDR_UNSPECIFIED(&sin6p->sin6_addr))
inp->inp_vflag |= INP_IPV4;
else if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) {
COMMON_START();
if (inp->inp_lport == 0) {
inp->inp_vflag &= ~INP_IPV4;
- if (ip6_mapped_addr_on &&
- (inp->inp_flags & IN6P_IPV6_V6ONLY) == 0)
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0)
inp->inp_vflag |= INP_IPV4;
error = in6_pcbbind(inp, (struct sockaddr *)0, p);
}
if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) {
struct sockaddr_in sin;
- if (!ip6_mapped_addr_on ||
- (inp->inp_flags & IN6P_IPV6_V6ONLY))
- return(EINVAL);
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)
+ return (EINVAL);
in6_sin6_2_sin(&sin, sin6p);
inp->inp_vflag |= INP_IPV4;
error = EINVAL;
break;
+ case TCP_KEEPALIVE:
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ break;
+ if (optval < 0)
+ error = EINVAL;
+ else
+ tp->t_keepidle = optval * PR_SLOWHZ;
+ break;
+
default:
error = ENOPROTOOPT;
break;
case TCP_MAXSEG:
optval = tp->t_maxseg;
break;
+ case TCP_KEEPALIVE:
+ optval = tp->t_keepidle / PR_SLOWHZ;
+ break;
case TCP_NOOPT:
optval = tp->t_flags & TF_NOOPT;
break;
SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
&tcp_recvspace , 0, "Maximum incoming TCP datagram size");
+__private_extern__ int tcp_sockthreshold = 256;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, sockthreshold, CTLFLAG_RW,
+ &tcp_sockthreshold , 0, "TCP Socket size increased if less than threshold");
+
+#define TCP_INCREASED_SPACE 65535 /* Automatically increase tcp send/rcv space to this value */
/*
* Attach TCP protocol to socket, allocating
* internet protocol control block, tcp control block,
int isipv6 = INP_CHECK_SOCKAF(so, AF_INET6) != NULL;
#endif
- if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
- error = soreserve(so, tcp_sendspace, tcp_recvspace);
- if (error)
- return (error);
- }
error = in_pcballoc(so, &tcbinfo, p);
if (error)
return (error);
+
inp = sotoinpcb(so);
+
+ if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
+ /*
+ * The goal is to let clients have large send/rcv default windows (TCP_INCREASED_SPACE)
+ * while not hogging mbuf space for servers. This is done by watching a threshold
+ * of tcpcbs in use and bumping the default send and rcvspace only if under that threshold.
+ * The theory being that busy servers have a lot more active tcpcbs and don't want the potential
+ * memory penalty of having much larger sockbuffs. The sysctl allows to fine tune that threshold value. */
+
+ if (inp->inp_pcbinfo->ipi_count < tcp_sockthreshold)
+ error = soreserve(so, MAX(TCP_INCREASED_SPACE, tcp_sendspace), MAX(TCP_INCREASED_SPACE,tcp_recvspace));
+ else
+ error = soreserve(so, tcp_sendspace, tcp_recvspace);
+ if (error)
+ return (error);
+ }
+
#if INET6
if (isipv6) {
inp->inp_vflag |= INP_IPV6;