summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet/tcp_hostcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet/tcp_hostcache.c')
-rw-r--r--freebsd/sys/netinet/tcp_hostcache.c81
1 files changed, 50 insertions, 31 deletions
diff --git a/freebsd/sys/netinet/tcp_hostcache.c b/freebsd/sys/netinet/tcp_hostcache.c
index 260d161d..4e78b8b2 100644
--- a/freebsd/sys/netinet/tcp_hostcache.c
+++ b/freebsd/sys/netinet/tcp_hostcache.c
@@ -34,8 +34,8 @@
* table to a dedicated structure indexed by the remote IP address. It keeps
* information on the measured TCP parameters of past TCP sessions to allow
* better initial start values to be used with later connections to/from the
- * same source. Depending on the network parameters (delay, bandwidth, max
- * MTU, congestion window) between local and remote sites, this can lead to
+ * same source. Depending on the network parameters (delay, max MTU,
+ * congestion window) between local and remote sites, this can lead to
* significant speed-ups for new TCP connections after the first one.
*
* Due to the tcp_hostcache, all TCP-specific metrics information in the
@@ -81,6 +81,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/route.h>
#include <net/vnet.h>
@@ -118,37 +119,38 @@ static VNET_DEFINE(struct callout, tcp_hc_callout);
static struct hc_metrics *tcp_hc_lookup(struct in_conninfo *);
static struct hc_metrics *tcp_hc_insert(struct in_conninfo *);
static int sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS);
+static int sysctl_tcp_hc_purgenow(SYSCTL_HANDLER_ARGS);
static void tcp_hc_purge_internal(int);
static void tcp_hc_purge(void *);
static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, hostcache, CTLFLAG_RW, 0,
"TCP Host cache");
-SYSCTL_VNET_UINT(_net_inet_tcp_hostcache, OID_AUTO, cachelimit, CTLFLAG_RDTUN,
+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");
-SYSCTL_VNET_UINT(_net_inet_tcp_hostcache, OID_AUTO, hashsize, CTLFLAG_RDTUN,
+SYSCTL_UINT(_net_inet_tcp_hostcache, OID_AUTO, hashsize, CTLFLAG_VNET | CTLFLAG_RDTUN,
&VNET_NAME(tcp_hostcache.hashsize), 0,
"Size of TCP hostcache hashtable");
-SYSCTL_VNET_UINT(_net_inet_tcp_hostcache, OID_AUTO, bucketlimit,
- CTLFLAG_RDTUN, &VNET_NAME(tcp_hostcache.bucket_limit), 0,
+SYSCTL_UINT(_net_inet_tcp_hostcache, OID_AUTO, bucketlimit,
+ CTLFLAG_VNET | CTLFLAG_RDTUN, &VNET_NAME(tcp_hostcache.bucket_limit), 0,
"Per-bucket hash limit for hostcache");
-SYSCTL_VNET_UINT(_net_inet_tcp_hostcache, OID_AUTO, count, CTLFLAG_RD,
+SYSCTL_UINT(_net_inet_tcp_hostcache, OID_AUTO, count, CTLFLAG_VNET | CTLFLAG_RD,
&VNET_NAME(tcp_hostcache.cache_count), 0,
"Current number of entries in hostcache");
-SYSCTL_VNET_INT(_net_inet_tcp_hostcache, OID_AUTO, expire, CTLFLAG_RW,
+SYSCTL_INT(_net_inet_tcp_hostcache, OID_AUTO, expire, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_hostcache.expire), 0,
"Expire time of TCP hostcache entries");
-SYSCTL_VNET_INT(_net_inet_tcp_hostcache, OID_AUTO, prune, CTLFLAG_RW,
+SYSCTL_INT(_net_inet_tcp_hostcache, OID_AUTO, prune, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_hostcache.prune), 0,
"Time between purge runs");
-SYSCTL_VNET_INT(_net_inet_tcp_hostcache, OID_AUTO, purge, CTLFLAG_RW,
+SYSCTL_INT(_net_inet_tcp_hostcache, OID_AUTO, purge, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_hostcache.purgeall), 0,
"Expire all entires on next purge run");
@@ -156,6 +158,9 @@ SYSCTL_PROC(_net_inet_tcp_hostcache, OID_AUTO, list,
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_SKIP, 0, 0,
sysctl_tcp_hc_list, "A", "List of all hostcache entries");
+SYSCTL_PROC(_net_inet_tcp_hostcache, OID_AUTO, purgenow,
+ CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
+ sysctl_tcp_hc_purgenow, "I", "Immediately purge all entries");
static MALLOC_DEFINE(M_HOSTCACHE, "hostcache", "TCP hostcache");
@@ -235,7 +240,7 @@ tcp_hc_init(void)
/*
* Set up periodic cache cleanup.
*/
- callout_init(&V_tcp_hc_callout, CALLOUT_MPSAFE);
+ callout_init(&V_tcp_hc_callout, 1);
callout_reset(&V_tcp_hc_callout, V_tcp_hostcache.prune * hz,
tcp_hc_purge, curvnet);
}
@@ -297,6 +302,7 @@ tcp_hc_lookup(struct in_conninfo *inc)
*/
TAILQ_FOREACH(hc_entry, &hc_head->hch_bucket, rmx_q) {
if (inc->inc_flags & INC_ISIPV6) {
+ /* XXX: check ip6_zoneid */
if (memcmp(&inc->inc6_faddr, &hc_entry->ip6,
sizeof(inc->inc6_faddr)) == 0)
return hc_entry;
@@ -388,9 +394,10 @@ tcp_hc_insert(struct in_conninfo *inc)
* Initialize basic information of hostcache entry.
*/
bzero(hc_entry, sizeof(*hc_entry));
- if (inc->inc_flags & INC_ISIPV6)
- bcopy(&inc->inc6_faddr, &hc_entry->ip6, sizeof(hc_entry->ip6));
- else
+ if (inc->inc_flags & INC_ISIPV6) {
+ hc_entry->ip6 = inc->inc6_faddr;
+ hc_entry->ip6_zoneid = inc->inc6_zoneid;
+ } else
hc_entry->ip4 = inc->inc_faddr;
hc_entry->rmx_head = hc_head;
hc_entry->rmx_expire = V_tcp_hostcache.expire;
@@ -435,7 +442,6 @@ tcp_hc_get(struct in_conninfo *inc, struct hc_metrics_lite *hc_metrics_lite)
hc_metrics_lite->rmx_ssthresh = hc_entry->rmx_ssthresh;
hc_metrics_lite->rmx_rtt = hc_entry->rmx_rtt;
hc_metrics_lite->rmx_rttvar = hc_entry->rmx_rttvar;
- hc_metrics_lite->rmx_bandwidth = hc_entry->rmx_bandwidth;
hc_metrics_lite->rmx_cwnd = hc_entry->rmx_cwnd;
hc_metrics_lite->rmx_sendpipe = hc_entry->rmx_sendpipe;
hc_metrics_lite->rmx_recvpipe = hc_entry->rmx_recvpipe;
@@ -550,14 +556,6 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml)
(hc_entry->rmx_ssthresh + hcml->rmx_ssthresh) / 2;
TCPSTAT_INC(tcps_cachedssthresh);
}
- if (hcml->rmx_bandwidth != 0) {
- if (hc_entry->rmx_bandwidth == 0)
- hc_entry->rmx_bandwidth = hcml->rmx_bandwidth;
- else
- hc_entry->rmx_bandwidth =
- (hc_entry->rmx_bandwidth + hcml->rmx_bandwidth) / 2;
- /* TCPSTAT_INC(tcps_cachedbandwidth); */
- }
if (hcml->rmx_cwnd != 0) {
if (hc_entry->rmx_cwnd == 0)
hc_entry->rmx_cwnd = hcml->rmx_cwnd;
@@ -595,7 +593,7 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml)
static int
sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
{
- int linesize = 128;
+ const int linesize = 128;
struct sbuf sb;
int i, error;
struct hc_metrics *hc_entry;
@@ -604,10 +602,10 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
#endif
sbuf_new(&sb, NULL, linesize * (V_tcp_hostcache.cache_count + 1),
- SBUF_FIXEDLEN);
+ SBUF_INCLUDENUL);
sbuf_printf(&sb,
- "\nIP address MTU SSTRESH RTT RTTVAR BANDWIDTH "
+ "\nIP address MTU SSTRESH RTT RTTVAR "
" CWND SENDPIPE RECVPIPE HITS UPD EXP\n");
#define msec(u) (((u) + 500) / 1000)
@@ -616,8 +614,8 @@ 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 %9lu %8lu %8lu %8lu "
- "%4lu %4lu %4i\n",
+ "%-15s %5lu %8lu %6lums %6lums %8lu %8lu %8lu %4lu "
+ "%4lu %4i\n",
hc_entry->ip4.s_addr ? inet_ntoa(hc_entry->ip4) :
#ifdef INET6
ip6_sprintf(ip6buf, &hc_entry->ip6),
@@ -630,7 +628,6 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
(RTM_RTTUNIT / (hz * TCP_RTT_SCALE))),
msec(hc_entry->rmx_rttvar *
(RTM_RTTUNIT / (hz * TCP_RTTVAR_SCALE))),
- hc_entry->rmx_bandwidth * 8,
hc_entry->rmx_cwnd,
hc_entry->rmx_sendpipe,
hc_entry->rmx_recvpipe,
@@ -641,8 +638,9 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
THC_UNLOCK(&V_tcp_hostcache.hashbase[i].hch_mtx);
}
#undef msec
- sbuf_finish(&sb);
- error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb));
+ error = sbuf_finish(&sb);
+ if (error == 0)
+ error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb));
sbuf_delete(&sb);
return(error);
}
@@ -694,3 +692,24 @@ tcp_hc_purge(void *arg)
tcp_hc_purge, arg);
CURVNET_RESTORE();
}
+
+/*
+ * Expire and purge all entries in hostcache immediately.
+ */
+static int
+sysctl_tcp_hc_purgenow(SYSCTL_HANDLER_ARGS)
+{
+ int error, val;
+
+ val = 0;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error || !req->newptr)
+ return (error);
+
+ tcp_hc_purge_internal(1);
+
+ callout_reset(&V_tcp_hc_callout, V_tcp_hostcache.prune * hz,
+ tcp_hc_purge, curvnet);
+
+ return (0);
+}