Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_subr.c
Show All 36 Lines | |||||
#include "opt_inet6.h" | #include "opt_inet6.h" | ||||
#include "opt_ipsec.h" | #include "opt_ipsec.h" | ||||
#include "opt_tcpdebug.h" | #include "opt_tcpdebug.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/callout.h> | #include <sys/callout.h> | ||||
#include <sys/eventhandler.h> | #include <sys/eventhandler.h> | ||||
#ifdef TCP_HHOOK | |||||
#include <sys/hhook.h> | #include <sys/hhook.h> | ||||
#endif | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#ifdef TCP_HHOOK | |||||
#include <sys/khelp.h> | #include <sys/khelp.h> | ||||
#endif | |||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/refcount.h> | #include <sys/refcount.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#ifdef INET6 | #ifdef INET6 | ||||
#include <sys/domain.h> | #include <sys/domain.h> | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | |||||
static int tcp_sig_checksigs = 1; | static int tcp_sig_checksigs = 1; | ||||
SYSCTL_INT(_net_inet_tcp, OID_AUTO, signature_verify_input, CTLFLAG_RW, | SYSCTL_INT(_net_inet_tcp, OID_AUTO, signature_verify_input, CTLFLAG_RW, | ||||
&tcp_sig_checksigs, 0, "Verify RFC2385 digests on inbound traffic"); | &tcp_sig_checksigs, 0, "Verify RFC2385 digests on inbound traffic"); | ||||
#endif | #endif | ||||
VNET_DEFINE(uma_zone_t, sack_hole_zone); | VNET_DEFINE(uma_zone_t, sack_hole_zone); | ||||
#define V_sack_hole_zone VNET(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]); | VNET_DEFINE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST+1]); | ||||
#endif | |||||
static struct inpcb *tcp_notify(struct inpcb *, int); | static struct inpcb *tcp_notify(struct inpcb *, int); | ||||
static struct inpcb *tcp_mtudisc_notify(struct inpcb *, int); | static struct inpcb *tcp_mtudisc_notify(struct inpcb *, int); | ||||
static void tcp_mtudisc(struct inpcb *, int); | static void tcp_mtudisc(struct inpcb *, int); | ||||
static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th, | static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th, | ||||
void *ip4hdr, const void *ip6hdr); | void *ip4hdr, const void *ip6hdr); | ||||
▲ Show 20 Lines • Show All 194 Lines • ▼ Show 20 Lines | |||||
* Callouts should be moved into struct tcp directly. They are currently | * Callouts should be moved into struct tcp directly. They are currently | ||||
* separate because the tcpcb structure is exported to userland for sysctl | * separate because the tcpcb structure is exported to userland for sysctl | ||||
* parsing purposes, which do not know about callouts. | * parsing purposes, which do not know about callouts. | ||||
*/ | */ | ||||
struct tcpcb_mem { | struct tcpcb_mem { | ||||
struct tcpcb tcb; | struct tcpcb tcb; | ||||
struct tcp_timer tt; | struct tcp_timer tt; | ||||
struct cc_var ccv; | struct cc_var ccv; | ||||
#ifdef TCP_HHOOK | |||||
struct osd osd; | struct osd osd; | ||||
#endif | |||||
}; | }; | ||||
static VNET_DEFINE(uma_zone_t, tcpcb_zone); | static VNET_DEFINE(uma_zone_t, tcpcb_zone); | ||||
#define V_tcpcb_zone VNET(tcpcb_zone) | #define V_tcpcb_zone VNET(tcpcb_zone) | ||||
MALLOC_DEFINE(M_TCPLOG, "tcplog", "TCP address and flags print buffers"); | MALLOC_DEFINE(M_TCPLOG, "tcplog", "TCP address and flags print buffers"); | ||||
MALLOC_DEFINE(M_TCPFUNCTIONS, "tcpfunc", "TCP function set memory"); | MALLOC_DEFINE(M_TCPFUNCTIONS, "tcpfunc", "TCP function set memory"); | ||||
▲ Show 20 Lines • Show All 139 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
tcp_init(void) | tcp_init(void) | ||||
{ | { | ||||
const char *tcbhash_tuneable; | const char *tcbhash_tuneable; | ||||
int hashsize; | int hashsize; | ||||
tcbhash_tuneable = "net.inet.tcp.tcbhashsize"; | tcbhash_tuneable = "net.inet.tcp.tcbhashsize"; | ||||
#ifdef TCP_HHOOK | |||||
if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_IN, | if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_IN, | ||||
&V_tcp_hhh[HHOOK_TCP_EST_IN], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0) | &V_tcp_hhh[HHOOK_TCP_EST_IN], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0) | ||||
printf("%s: WARNING: unable to register helper hook\n", __func__); | printf("%s: WARNING: unable to register helper hook\n", __func__); | ||||
if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_OUT, | if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_OUT, | ||||
&V_tcp_hhh[HHOOK_TCP_EST_OUT], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0) | &V_tcp_hhh[HHOOK_TCP_EST_OUT], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0) | ||||
printf("%s: WARNING: unable to register helper hook\n", __func__); | printf("%s: WARNING: unable to register helper hook\n", __func__); | ||||
#endif | |||||
hashsize = TCBHASHSIZE; | hashsize = TCBHASHSIZE; | ||||
TUNABLE_INT_FETCH(tcbhash_tuneable, &hashsize); | TUNABLE_INT_FETCH(tcbhash_tuneable, &hashsize); | ||||
if (hashsize == 0) { | if (hashsize == 0) { | ||||
/* | /* | ||||
* Auto tune the hash size based on maxsockets. | * Auto tune the hash size based on maxsockets. | ||||
* A perfect hash would have a 1:1 mapping | * A perfect hash would have a 1:1 mapping | ||||
* (hashsize = maxsockets) however it's been | * (hashsize = maxsockets) however it's been | ||||
* suggested that O(2) average is better. | * suggested that O(2) average is better. | ||||
▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | |||||
#ifdef TCP_RFC7413 | #ifdef TCP_RFC7413 | ||||
/* | /* | ||||
* Cannot free the zone until all tcpcbs are released as we attach | * Cannot free the zone until all tcpcbs are released as we attach | ||||
* the allocations to them. | * the allocations to them. | ||||
*/ | */ | ||||
tcp_fastopen_destroy(); | tcp_fastopen_destroy(); | ||||
#endif | #endif | ||||
#ifdef TCP_HHOOK | |||||
error = hhook_head_deregister(V_tcp_hhh[HHOOK_TCP_EST_IN]); | error = hhook_head_deregister(V_tcp_hhh[HHOOK_TCP_EST_IN]); | ||||
if (error != 0) { | if (error != 0) { | ||||
printf("%s: WARNING: unable to deregister helper hook " | printf("%s: WARNING: unable to deregister helper hook " | ||||
"type=%d, id=%d: error %d returned\n", __func__, | "type=%d, id=%d: error %d returned\n", __func__, | ||||
HHOOK_TYPE_TCP, HHOOK_TCP_EST_IN, error); | HHOOK_TYPE_TCP, HHOOK_TCP_EST_IN, error); | ||||
} | } | ||||
error = hhook_head_deregister(V_tcp_hhh[HHOOK_TCP_EST_OUT]); | error = hhook_head_deregister(V_tcp_hhh[HHOOK_TCP_EST_OUT]); | ||||
if (error != 0) { | if (error != 0) { | ||||
printf("%s: WARNING: unable to deregister helper hook " | printf("%s: WARNING: unable to deregister helper hook " | ||||
"type=%d, id=%d: error %d returned\n", __func__, | "type=%d, id=%d: error %d returned\n", __func__, | ||||
HHOOK_TYPE_TCP, HHOOK_TCP_EST_OUT, error); | HHOOK_TYPE_TCP, HHOOK_TCP_EST_OUT, error); | ||||
} | } | ||||
#endif | |||||
} | } | ||||
VNET_SYSUNINIT(tcp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, tcp_destroy, NULL); | VNET_SYSUNINIT(tcp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, tcp_destroy, NULL); | ||||
#endif | #endif | ||||
void | void | ||||
tcp_fini(void *xtp) | tcp_fini(void *xtp) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 413 Lines • ▼ Show 20 Lines | if (CC_ALGO(tp)->cb_init != NULL) | ||||
if (CC_ALGO(tp)->cb_init(tp->ccv) > 0) { | if (CC_ALGO(tp)->cb_init(tp->ccv) > 0) { | ||||
if (tp->t_fb->tfb_tcp_fb_fini) | if (tp->t_fb->tfb_tcp_fb_fini) | ||||
(*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); | (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); | ||||
refcount_release(&tp->t_fb->tfb_refcnt); | refcount_release(&tp->t_fb->tfb_refcnt); | ||||
uma_zfree(V_tcpcb_zone, tm); | uma_zfree(V_tcpcb_zone, tm); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
#ifdef TCP_HHOOK | |||||
tp->osd = &tm->osd; | tp->osd = &tm->osd; | ||||
if (khelp_init_osd(HELPER_CLASS_TCP, tp->osd)) { | if (khelp_init_osd(HELPER_CLASS_TCP, tp->osd)) { | ||||
if (tp->t_fb->tfb_tcp_fb_fini) | if (tp->t_fb->tfb_tcp_fb_fini) | ||||
(*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); | (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); | ||||
refcount_release(&tp->t_fb->tfb_refcnt); | refcount_release(&tp->t_fb->tfb_refcnt); | ||||
uma_zfree(V_tcpcb_zone, tm); | uma_zfree(V_tcpcb_zone, tm); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
#else | |||||
tp->osd = NULL; | |||||
lstewart: Not needed given that we pass M_ZERO to uma_zalloc() | |||||
Not Done Inline ActionsGood catch. Thanks! jtl: Good catch. Thanks! | |||||
#endif | |||||
#ifdef VIMAGE | #ifdef VIMAGE | ||||
tp->t_vnet = inp->inp_vnet; | tp->t_vnet = inp->inp_vnet; | ||||
#endif | #endif | ||||
tp->t_timers = &tm->tt; | tp->t_timers = &tm->tt; | ||||
/* LIST_INIT(&tp->t_segq); */ /* XXX covered by M_ZERO */ | /* LIST_INIT(&tp->t_segq); */ /* XXX covered by M_ZERO */ | ||||
tp->t_maxseg = | tp->t_maxseg = | ||||
#ifdef INET6 | #ifdef INET6 | ||||
▲ Show 20 Lines • Show All 249 Lines • ▼ Show 20 Lines | #ifdef TCPPCAP | ||||
tcp_pcap_drain(&(tp->t_inpkts)); | tcp_pcap_drain(&(tp->t_inpkts)); | ||||
tcp_pcap_drain(&(tp->t_outpkts)); | tcp_pcap_drain(&(tp->t_outpkts)); | ||||
#endif | #endif | ||||
/* Allow the CC algorithm to clean up after itself. */ | /* Allow the CC algorithm to clean up after itself. */ | ||||
if (CC_ALGO(tp)->cb_destroy != NULL) | if (CC_ALGO(tp)->cb_destroy != NULL) | ||||
CC_ALGO(tp)->cb_destroy(tp->ccv); | CC_ALGO(tp)->cb_destroy(tp->ccv); | ||||
#ifdef TCP_HHOOK | |||||
khelp_destroy_osd(tp->osd); | khelp_destroy_osd(tp->osd); | ||||
#endif | |||||
CC_ALGO(tp) = NULL; | CC_ALGO(tp) = NULL; | ||||
inp->inp_ppcb = NULL; | inp->inp_ppcb = NULL; | ||||
if (tp->t_timers->tt_draincnt == 0) { | if (tp->t_timers->tt_draincnt == 0) { | ||||
/* We own the last reference on tcpcb, let's free it. */ | /* We own the last reference on tcpcb, let's free it. */ | ||||
if (tp->t_fb->tfb_tcp_fb_fini) | if (tp->t_fb->tfb_tcp_fb_fini) | ||||
(*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); | (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); | ||||
refcount_release(&tp->t_fb->tfb_refcnt); | refcount_release(&tp->t_fb->tfb_refcnt); | ||||
▲ Show 20 Lines • Show All 1,605 Lines • Show Last 20 Lines |
Not needed given that we pass M_ZERO to uma_zalloc()