Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
U
unique-xids
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
uplex-varnish
unique-xids
Commits
e91ca73f
Commit
e91ca73f
authored
Mar 05, 2013
by
Poul-Henning Kamp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rewite the sockopt code to be table-driven.
parent
a71250e7
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
158 additions
and
262 deletions
+158
-262
cache_acceptor.c
bin/varnishd/cache/cache_acceptor.c
+158
-262
No files found.
bin/varnishd/cache/cache_acceptor.c
View file @
e91ca73f
...
...
@@ -41,6 +41,7 @@
#include "config.h"
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
...
...
@@ -54,12 +55,47 @@
#include "vtim.h"
static
pthread_t
VCA_thread
;
static
struct
timeval
tv_sndtimeo
;
static
struct
timeval
tv_rcvtimeo
;
static
int
hack_ready
;
static
double
vca_pace
=
0
.
0
;
static
struct
lock
pace_mtx
;
/*--------------------------------------------------------------------
* TCP options we want to control
*/
static
struct
tcp_opt
{
int
level
;
int
optname
;
const
char
*
strname
;
socklen_t
sz
;
void
*
ptr
;
int
need
;
}
tcp_opts
[]
=
{
#define TCPO(lvl, nam, sz) { lvl, nam, #nam, sizeof(sz), 0, 0},
TCPO
(
SOL_SOCKET
,
SO_LINGER
,
struct
linger
)
TCPO
(
SOL_SOCKET
,
SO_KEEPALIVE
,
int
)
TCPO
(
IPPROTO_TCP
,
TCP_NODELAY
,
int
)
#ifdef SO_SNDTIMEO_WORKS
TCPO
(
SOL_SOCKET
,
SO_SNDTIMEO
,
struct
timeval
)
#endif
#ifdef SO_RCVTIMEO_WORKS
TCPO
(
SOL_SOCKET
,
SO_RCVTIMEO
,
struct
timeval
)
#endif
#ifdef HAVE_TCP_KEEP
TCPO
(
IPPROTO_TCP
,
TCP_KEEPIDLE
,
int
)
TCPO
(
IPPROTO_TCP
,
TCP_KEEPCNT
,
int
)
TCPO
(
IPPROTO_TCP
,
TCP_KEEPINTVL
,
int
)
#endif
#undef TCPO
};
static
const
int
n_tcp_opts
=
sizeof
tcp_opts
/
sizeof
tcp_opts
[
0
];
/*--------------------------------------------------------------------
* We want to get out of any kind of trouble-hit TCP connections as fast
* as absolutely possible, so we set them LINGER enabled with zero timeout,
...
...
@@ -74,22 +110,8 @@ static const struct linger linger = {
* We turn on keepalives by default to assist in detecting clients that have
* hung up on connections returning from waitinglists
*/
static
const
int
keepalive
=
1
;
static
unsigned
char
need_sndtimeo
,
need_rcvtimeo
,
need_linger
,
need_test
,
need_tcpnodelay
;
static
unsigned
char
need_keepalive
=
0
;
#ifdef HAVE_TCP_KEEP
static
unsigned
char
need_ka_time
=
0
;
static
unsigned
char
need_ka_probes
=
0
;
static
unsigned
char
need_ka_intvl
=
0
;
static
int
ka_time_cur
=
0
;
static
int
ka_probes_cur
=
0
;
static
int
ka_intvl_cur
=
0
;
static
int
ka_time
,
ka_time_sys
;
static
int
ka_probes
,
ka_probes_sys
;
static
int
ka_intvl
,
ka_intvl_sys
;
#endif
static
unsigned
need_test
;
/*--------------------------------------------------------------------
* Some kernels have bugs/limitations with respect to which options are
...
...
@@ -97,113 +119,106 @@ static int ka_intvl, ka_intvl_sys;
* which, if any, sockopts we have to set on the accepted socket.
*/
static
void
sock_test
(
int
fd
)
static
int
vca_tcp_opt_init
(
)
{
struct
linger
lin
;
int
tka
;
#ifdef HAVE_TCP_KEEP
int
tka_time
,
tka_probes
,
tka_intvl
;
#endif
int
n
,
x
;
int
one
=
1
;
// int zero = 0;
struct
tcp_opt
*
to
;
struct
timeval
tv
;
socklen_t
l
;
int
i
,
tcp_nodelay
;
l
=
sizeof
lin
;
i
=
getsockopt
(
fd
,
SOL_SOCKET
,
SO_LINGER
,
&
lin
,
&
l
);
if
(
i
)
{
VTCP_Assert
(
i
);
return
;
}
assert
(
l
==
sizeof
lin
);
if
(
memcmp
(
&
lin
,
&
linger
,
l
))
need_linger
=
1
;
l
=
sizeof
tka
;
i
=
getsockopt
(
fd
,
SOL_SOCKET
,
SO_KEEPALIVE
,
&
tka
,
&
l
);
if
(
i
)
{
VTCP_Assert
(
i
);
return
;
}
assert
(
l
==
sizeof
tka
);
if
(
tka
!=
keepalive
)
need_keepalive
=
1
;
int
chg
=
0
;
for
(
n
=
0
;
n
<
n_tcp_opts
;
n
++
)
{
to
=
&
tcp_opts
[
n
];
if
(
to
->
ptr
==
NULL
)
to
->
ptr
=
calloc
(
to
->
sz
,
1
);
AN
(
to
->
ptr
);
if
(
!
strcmp
(
to
->
strname
,
"SO_LINGER"
))
{
assert
(
to
->
sz
==
sizeof
linger
);
memcpy
(
to
->
ptr
,
&
linger
,
sizeof
linger
);
to
->
need
=
1
;
}
else
if
(
!
strcmp
(
to
->
strname
,
"TCP_NODELAY"
))
{
assert
(
to
->
sz
==
sizeof
one
);
memcpy
(
to
->
ptr
,
&
one
,
sizeof
one
);
to
->
need
=
1
;
}
else
if
(
!
strcmp
(
to
->
strname
,
"SO_KEEPALIVE"
))
{
assert
(
to
->
sz
==
sizeof
one
);
memcpy
(
to
->
ptr
,
&
one
,
sizeof
one
);
to
->
need
=
1
;
#define NEW_VAL(to, xx) \
do { \
assert(to->sz == sizeof xx); \
if (memcmp(to->ptr, &(xx), sizeof xx)) { \
memcpy(to->ptr, &(xx), sizeof xx); \
to->need = 1; \
chg = 1; \
need_test = 1; \
} \
} while (0)
#ifdef SO_SNDTIMEO_WORKS
}
else
if
(
!
strcmp
(
to
->
strname
,
"SO_SNDTIMEO"
))
{
tv
=
VTIM_timeval
(
cache_param
->
idle_send_timeout
);
NEW_VAL
(
to
,
tv
);
#endif
#ifdef SO_RCVTIMEO_WORKS
}
else
if
(
!
strcmp
(
to
->
strname
,
"SO_RCVTIMEO"
))
{
tv
=
VTIM_timeval
(
cache_param
->
timeout_idle
);
NEW_VAL
(
to
,
tv
);
#endif
#ifdef HAVE_TCP_KEEP
l
=
sizeof
tka_time
;
i
=
getsockopt
(
fd
,
IPPROTO_TCP
,
TCP_KEEPIDLE
,
&
tka_time
,
&
l
);
if
(
i
)
{
VTCP_Assert
(
i
);
return
;
}
assert
(
l
==
sizeof
tka_time
);
if
(
tka_time
!=
ka_time_cur
)
need_ka_time
=
1
;
l
=
sizeof
tka_probes
;
i
=
getsockopt
(
fd
,
IPPROTO_TCP
,
TCP_KEEPCNT
,
&
tka_probes
,
&
l
);
if
(
i
)
{
VTCP_Assert
(
i
);
return
;
}
else
if
(
!
strcmp
(
to
->
strname
,
"TCP_KEEPIDLE"
))
{
x
=
cache_param
->
tcp_keepalive_time
;
NEW_VAL
(
to
,
x
);
}
else
if
(
!
strcmp
(
to
->
strname
,
"TCP_KEEPCNT"
))
{
x
=
cache_param
->
tcp_keepalive_probes
;
NEW_VAL
(
to
,
x
);
}
else
if
(
!
strcmp
(
to
->
strname
,
"TCP_KEEPINTVL"
))
{
x
=
cache_param
->
tcp_keepalive_intvl
;
NEW_VAL
(
to
,
x
);
#endif
}
assert
(
l
==
sizeof
tka_probes
);
if
(
tka_probes
!=
ka_probes_cur
)
need_ka_probes
=
1
;
l
=
sizeof
tka_intvl
;
i
=
getsockopt
(
fd
,
IPPROTO_TCP
,
TCP_KEEPINTVL
,
&
tka_intvl
,
&
l
);
if
(
i
)
{
VTCP_Assert
(
i
);
return
;
}
assert
(
l
==
sizeof
tka_intvl
);
if
(
tka_intvl
!=
ka_intvl_cur
)
need_ka_intvl
=
1
;
#endif
return
(
chg
);
}
#ifdef SO_SNDTIMEO_WORKS
l
=
sizeof
tv
;
i
=
getsockopt
(
fd
,
SOL_SOCKET
,
SO_SNDTIMEO
,
&
tv
,
&
l
);
if
(
i
)
{
static
void
vca_tcp_opt_test
(
int
sock
)
{
int
i
,
n
;
struct
tcp_opt
*
to
;
socklen_t
l
;
void
*
ptr
;
for
(
n
=
0
;
n
<
n_tcp_opts
;
n
++
)
{
to
=
&
tcp_opts
[
n
];
to
->
need
=
1
;
ptr
=
calloc
(
to
->
sz
,
1
);
AN
(
ptr
);
l
=
to
->
sz
;
i
=
getsockopt
(
sock
,
to
->
level
,
to
->
optname
,
ptr
,
&
l
);
if
(
i
==
0
&&
!
memcmp
(
ptr
,
to
->
ptr
,
to
->
sz
))
to
->
need
=
0
;
free
(
ptr
);
if
(
i
&&
errno
!=
ENOPROTOOPT
)
VTCP_Assert
(
i
);
return
;
}
assert
(
l
==
sizeof
tv
);
if
(
memcmp
(
&
tv
,
&
tv_sndtimeo
,
l
))
need_sndtimeo
=
1
;
#else
(
void
)
tv
;
(
void
)
tv_sndtimeo
;
(
void
)
need_sndtimeo
;
#endif
}
#ifdef SO_RCVTIMEO_WORKS
l
=
sizeof
tv
;
i
=
getsockopt
(
fd
,
SOL_SOCKET
,
SO_RCVTIMEO
,
&
tv
,
&
l
);
if
(
i
)
{
VTCP_Assert
(
i
);
return
;
static
void
vca_tcp_opt_set
(
int
sock
,
int
force
)
{
int
n
;
struct
tcp_opt
*
to
;
for
(
n
=
0
;
n
<
n_tcp_opts
;
n
++
)
{
to
=
&
tcp_opts
[
n
];
if
(
to
->
need
||
force
)
{
VTCP_Assert
(
setsockopt
(
sock
,
to
->
level
,
to
->
optname
,
to
->
ptr
,
to
->
sz
));
}
assert
(
l
==
sizeof
tv
);
if
(
memcmp
(
&
tv
,
&
tv_rcvtimeo
,
l
))
need_rcvtimeo
=
1
;
#else
(
void
)
tv
;
(
void
)
tv_rcvtimeo
;
(
void
)
need_rcvtimeo
;
#endif
l
=
sizeof
tcp_nodelay
;
i
=
getsockopt
(
fd
,
IPPROTO_TCP
,
TCP_NODELAY
,
&
tcp_nodelay
,
&
l
);
if
(
i
)
{
VTCP_Assert
(
i
);
return
;
}
assert
(
l
==
sizeof
tcp_nodelay
);
if
(
!
tcp_nodelay
)
need_tcpnodelay
=
1
;
need_test
=
0
;
}
/*--------------------------------------------------------------------
...
...
@@ -325,7 +340,6 @@ VCA_SetupSess(struct worker *wrk, struct sess *sp)
{
struct
wrk_accept
*
wa
;
const
char
*
retval
;
int
tcp_nodelay
=
1
;
CHECK_OBJ_NOTNULL
(
wrk
,
WORKER_MAGIC
);
CHECK_OBJ_NOTNULL
(
sp
,
SESS_MAGIC
);
...
...
@@ -340,123 +354,55 @@ VCA_SetupSess(struct worker *wrk, struct sess *sp)
wrk
->
stats
.
sess_conn
++
;
WS_Release
(
wrk
->
aws
,
0
);
if
(
need_test
)
sock_test
(
sp
->
fd
);
if
(
need_linger
)
VTCP_Assert
(
setsockopt
(
sp
->
fd
,
SOL_SOCKET
,
SO_LINGER
,
&
linger
,
sizeof
linger
));
if
(
need_keepalive
)
VTCP_Assert
(
setsockopt
(
sp
->
fd
,
SOL_SOCKET
,
SO_KEEPALIVE
,
&
keepalive
,
sizeof
keepalive
));
#ifdef HAVE_TCP_KEEP
AN
(
ka_time
);
if
(
need_ka_time
)
VTCP_Assert
(
setsockopt
(
sp
->
fd
,
IPPROTO_TCP
,
TCP_KEEPIDLE
,
&
ka_time_cur
,
sizeof
ka_time_cur
));
if
(
need_ka_probes
)
VTCP_Assert
(
setsockopt
(
sp
->
fd
,
IPPROTO_TCP
,
TCP_KEEPCNT
,
&
ka_probes_cur
,
sizeof
ka_probes_cur
));
if
(
need_ka_intvl
)
VTCP_Assert
(
setsockopt
(
sp
->
fd
,
IPPROTO_TCP
,
TCP_KEEPINTVL
,
&
ka_intvl_cur
,
sizeof
ka_intvl_cur
));
#endif
#ifdef SO_SNDTIMEO_WORKS
if
(
need_sndtimeo
)
VTCP_Assert
(
setsockopt
(
sp
->
fd
,
SOL_SOCKET
,
SO_SNDTIMEO
,
&
tv_sndtimeo
,
sizeof
tv_sndtimeo
));
#endif
#ifdef SO_RCVTIMEO_WORKS
if
(
need_rcvtimeo
)
VTCP_Assert
(
setsockopt
(
sp
->
fd
,
SOL_SOCKET
,
SO_RCVTIMEO
,
&
tv_rcvtimeo
,
sizeof
tv_rcvtimeo
));
#endif
if
(
need_tcpnodelay
)
VTCP_Assert
(
setsockopt
(
sp
->
fd
,
IPPROTO_TCP
,
TCP_NODELAY
,
&
tcp_nodelay
,
sizeof
tcp_nodelay
));
if
(
need_test
)
{
vca_tcp_opt_test
(
sp
->
fd
);
need_test
=
0
;
}
vca_tcp_opt_set
(
sp
->
fd
,
0
);
return
(
retval
);
}
/*--------------------------------------------------------------------*/
#ifdef HAVE_TCP_KEEP
static
void
vca_tcp_keep_probe
(
int
sock
,
int
nam
,
volatile
unsigned
*
dst
)
{
int
i
,
x
;
socklen_t
l
;
l
=
sizeof
x
;
i
=
getsockopt
(
sock
,
IPPROTO_TCP
,
nam
,
&
x
,
&
l
);
if
(
i
==
0
&&
x
<
*
dst
)
*
dst
=
x
;
}
#endif
static
void
*
vca_acct
(
void
*
arg
)
{
#ifdef SO_RCVTIMEO_WORKS
double
timeout_idle
=
0
;
#endif
#ifdef SO_SNDTIMEO_WORKS
double
send_timeout
=
0
;
#endif
int
tcp_nodelay
=
1
;
struct
listen_sock
*
ls
;
double
t0
,
now
;
int
i
;
#ifdef HAVE_TCP_KEEP
socklen_t
len
;
#endif
THR_SetName
(
"cache-acceptor"
);
(
void
)
arg
;
#ifdef HAVE_TCP_KEEP
ka_time
=
cache_param
->
tcp_keepalive_time
;
ka_probes
=
cache_param
->
tcp_keepalive_probes
;
ka_intvl
=
cache_param
->
tcp_keepalive_intvl
;
#endif
(
void
)
vca_tcp_opt_init
();
VTAILQ_FOREACH
(
ls
,
&
heritage
.
socks
,
list
)
{
if
(
ls
->
sock
<
0
)
continue
;
AZ
(
listen
(
ls
->
sock
,
cache_param
->
listen_depth
));
AZ
(
setsockopt
(
ls
->
sock
,
SOL_SOCKET
,
SO_LINGER
,
&
linger
,
sizeof
linger
));
AZ
(
setsockopt
(
ls
->
sock
,
IPPROTO_TCP
,
TCP_NODELAY
,
&
tcp_nodelay
,
sizeof
tcp_nodelay
));
AZ
(
setsockopt
(
ls
->
sock
,
SOL_SOCKET
,
SO_KEEPALIVE
,
&
keepalive
,
sizeof
keepalive
));
#ifdef HAVE_TCP_KEEP
if
(
!
ka_time_cur
)
{
len
=
sizeof
ka_time_sys
;
AZ
(
getsockopt
(
ls
->
sock
,
IPPROTO_TCP
,
TCP_KEEPIDLE
,
&
ka_time_sys
,
&
len
));
assert
(
len
==
sizeof
ka_time_sys
);
AN
(
ka_time_sys
);
ka_time_cur
=
ka_time
=
(
ka_time_sys
<
cache_param
->
tcp_keepalive_time
?
ka_time_sys
:
cache_param
->
tcp_keepalive_time
);
}
AZ
(
setsockopt
(
ls
->
sock
,
IPPROTO_TCP
,
TCP_KEEPIDLE
,
&
ka_time_cur
,
sizeof
ka_time_cur
));
if
(
!
ka_probes_cur
)
{
len
=
sizeof
ka_probes_sys
;
AZ
(
getsockopt
(
ls
->
sock
,
IPPROTO_TCP
,
TCP_KEEPCNT
,
&
ka_probes_sys
,
&
len
));
assert
(
len
==
sizeof
ka_probes_sys
);
AN
(
ka_probes_sys
);
ka_probes_cur
=
ka_probes
=
(
ka_probes_sys
<
cache_param
->
tcp_keepalive_probes
?
ka_probes_sys
:
cache_param
->
tcp_keepalive_probes
);
}
AZ
(
setsockopt
(
ls
->
sock
,
IPPROTO_TCP
,
TCP_KEEPCNT
,
&
ka_probes_cur
,
sizeof
ka_probes_cur
));
if
(
!
ka_intvl_cur
)
{
len
=
sizeof
ka_intvl_sys
;
AZ
(
getsockopt
(
ls
->
sock
,
IPPROTO_TCP
,
TCP_KEEPINTVL
,
&
ka_intvl_sys
,
&
len
));
assert
(
len
==
sizeof
ka_intvl_sys
);
AN
(
ka_intvl_sys
);
ka_intvl_cur
=
ka_intvl
=
(
ka_intvl_sys
<
cache_param
->
tcp_keepalive_intvl
?
ka_intvl_sys
:
cache_param
->
tcp_keepalive_intvl
);
}
AZ
(
setsockopt
(
ls
->
sock
,
IPPROTO_TCP
,
TCP_KEEPINTVL
,
&
ka_intvl_cur
,
sizeof
ka_intvl_cur
));
vca_tcp_keep_probe
(
ls
->
sock
,
TCP_KEEPIDLE
,
&
cache_param
->
tcp_keepalive_time
);
vca_tcp_keep_probe
(
ls
->
sock
,
TCP_KEEPCNT
,
&
cache_param
->
tcp_keepalive_probes
);
vca_tcp_keep_probe
(
ls
->
sock
,
TCP_KEEPINTVL
,
&
cache_param
->
tcp_keepalive_intvl
);
#endif
vca_tcp_opt_set
(
ls
->
sock
,
1
);
if
(
cache_param
->
accept_filter
)
{
i
=
VTCP_filter_http
(
ls
->
sock
);
if
(
i
)
...
...
@@ -472,63 +418,13 @@ vca_acct(void *arg)
t0
=
VTIM_real
();
while
(
1
)
{
(
void
)
sleep
(
1
);
#ifdef HAVE_TCP_KEEP
ka_time
=
(
ka_time_sys
<
cache_param
->
tcp_keepalive_time
?
ka_time_sys
:
cache_param
->
tcp_keepalive_time
);
ka_probes
=
(
ka_probes_sys
<
cache_param
->
tcp_keepalive_probes
?
ka_probes_sys
:
cache_param
->
tcp_keepalive_probes
);
ka_intvl
=
(
ka_intvl_sys
<
cache_param
->
tcp_keepalive_intvl
?
ka_intvl_sys
:
cache_param
->
tcp_keepalive_intvl
);
if
(
ka_time_cur
!=
ka_time
||
ka_probes_cur
!=
ka_probes
||
ka_intvl_cur
!=
ka_intvl
)
{
need_test
=
1
;
ka_time_cur
=
ka_time
;
ka_probes_cur
=
ka_probes
;
ka_intvl_cur
=
ka_intvl
;
VTAILQ_FOREACH
(
ls
,
&
heritage
.
socks
,
list
)
{
if
(
ls
->
sock
<
0
)
continue
;
AZ
(
setsockopt
(
ls
->
sock
,
IPPROTO_TCP
,
TCP_KEEPIDLE
,
&
ka_time_cur
,
sizeof
ka_time_cur
));
AZ
(
setsockopt
(
ls
->
sock
,
IPPROTO_TCP
,
TCP_KEEPCNT
,
&
ka_probes_cur
,
sizeof
ka_probes_cur
));
AZ
(
setsockopt
(
ls
->
sock
,
IPPROTO_TCP
,
TCP_KEEPINTVL
,
&
ka_intvl_cur
,
sizeof
ka_intvl_cur
));
}
}
#endif
#ifdef SO_SNDTIMEO_WORKS
if
(
cache_param
->
idle_send_timeout
!=
send_timeout
)
{
need_test
=
1
;
send_timeout
=
cache_param
->
idle_send_timeout
;
tv_sndtimeo
=
VTIM_timeval
(
send_timeout
);
VTAILQ_FOREACH
(
ls
,
&
heritage
.
socks
,
list
)
{
if
(
ls
->
sock
<
0
)
continue
;
AZ
(
setsockopt
(
ls
->
sock
,
SOL_SOCKET
,
SO_SNDTIMEO
,
&
tv_sndtimeo
,
sizeof
tv_sndtimeo
));
}
}
#endif
#ifdef SO_RCVTIMEO_WORKS
if
(
cache_param
->
timeout_idle
!=
timeout_idle
)
{
need_test
=
1
;
timeout_idle
=
cache_param
->
timeout_idle
;
tv_rcvtimeo
=
VTIM_timeval
(
timeout_idle
);
if
(
vca_tcp_opt_init
())
{
VTAILQ_FOREACH
(
ls
,
&
heritage
.
socks
,
list
)
{
if
(
ls
->
sock
<
0
)
continue
;
AZ
(
setsockopt
(
ls
->
sock
,
SOL_SOCKET
,
SO_RCVTIMEO
,
&
tv_rcvtimeo
,
sizeof
tv_rcvtimeo
));
vca_tcp_opt_set
(
ls
->
sock
,
1
);
}
}
#endif
now
=
VTIM_real
();
VSC_C_main
->
uptime
=
(
uint64_t
)(
now
-
t0
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment