diff options
Diffstat (limited to 'freebsd/sys/netinet/tcp_hostcache.c')
-rw-r--r-- | freebsd/sys/netinet/tcp_hostcache.c | 81 |
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); +} |