varnish-cache/bin/varnishd/acceptor/cache_acceptor.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * This source file has the various trickery surrounding the accept/listen
31
 * sockets.
32
 *
33
 */
34
35
#include "config.h"
36
37
#include <stdlib.h>
38
#include <netinet/in.h>
39
#include <netinet/tcp.h>
40
41
#include "cache/cache_varnishd.h"
42
#include "acceptor/cache_acceptor.h"
43
#include "acceptor/acceptor_priv.h"
44
45
#include "cache/cache_transport.h"
46
#include "cache/cache_pool.h"
47
#include "common/heritage.h"
48
49
#include "vcli_serve.h"
50
#include "vtim.h"
51
52
unsigned pool_accepting;
53
54
static pthread_t        VCA_thread;
55
static vtim_dur vca_pace = 0.0;
56
static struct lock pace_mtx;
57
static pthread_mutex_t shut_mtx = PTHREAD_MUTEX_INITIALIZER;
58
59
/*--------------------------------------------------------------------
60
 * lacking a better place, we put some generic periodic updates
61
 * into the vca_acct() loop which we are running anyway
62
 */
63
static void
64 70110
vca_periodic(vtim_real t0)
65
{
66
        vtim_real now;
67
68 70110
        now = VTIM_real();
69 70110
        VSC_C_main->uptime = (uint64_t)(now - t0);
70
71 70110
        VTIM_postel = FEATURE(FEATURE_HTTP_DATE_POSTEL);
72 70110
}
73
74
/*--------------------------------------------------------------------
75
 * If accept(2)'ing fails, we pace ourselves to relive any resource
76
 * shortage if possible.
77
 */
78
79
void
80 157092
vca_pace_check(void)
81
{
82
        vtim_dur p;
83
84 157092
        if (vca_pace == 0.0)
85 157092
                return;
86 0
        Lck_Lock(&pace_mtx);
87 0
        p = vca_pace;
88 0
        Lck_Unlock(&pace_mtx);
89 0
        if (p > 0.0)
90 0
                VTIM_sleep(p);
91 157092
}
92
93
void
94 0
vca_pace_bad(void)
95
{
96
97 0
        Lck_Lock(&pace_mtx);
98 0
        vca_pace += cache_param->acceptor_sleep_incr;
99 0
        if (vca_pace > cache_param->acceptor_sleep_max)
100 0
                vca_pace = cache_param->acceptor_sleep_max;
101 0
        Lck_Unlock(&pace_mtx);
102 0
}
103
104
void
105 84582
vca_pace_good(void)
106
{
107
108 84582
        if (vca_pace == 0.0)
109 84582
                return;
110 0
        Lck_Lock(&pace_mtx);
111 0
        vca_pace *= cache_param->acceptor_sleep_decay;
112 0
        if (vca_pace < cache_param->acceptor_sleep_incr)
113 0
                vca_pace = 0.0;
114 0
        Lck_Unlock(&pace_mtx);
115 84582
}
116
117
/*--------------------------------------------------------------------
118
 * Called when a worker and attached thread pool is created, to
119
 * allocate the tasks which will listen to sockets for that pool.
120
 */
121
122
void
123 72552
VCA_NewPool(struct pool *pp)
124
{
125
        struct acceptor *vca;
126
127 217656
        VCA_Foreach(vca) {
128 145104
                CHECK_OBJ_NOTNULL(vca, ACCEPTOR_MAGIC);
129 145104
                vca->accept(pp);
130
        }
131 72552
}
132
133
void
134 80
VCA_DestroyPool(struct pool *pp)
135
{
136
        struct poolsock *ps;
137
138 160
        while (!VTAILQ_EMPTY(&pp->poolsocks)) {
139 80
                ps = VTAILQ_FIRST(&pp->poolsocks);
140 80
                VTAILQ_REMOVE(&pp->poolsocks, ps, list);
141
        }
142 80
}
143
144
/*--------------------------------------------------------------------*/
145
146
static void * v_matchproto_()
147 0
vca_acct(void *arg)
148
{
149
        struct acceptor *vca;
150
        vtim_real t0;
151
152
        // XXX Actually a misnomer now because the accept happens in a pool
153
        // thread. Rename to accept-nanny or so?
154 0
        THR_SetName("cache-acceptor");
155 0
        THR_Init();
156 0
        (void)arg;
157
158 0
        t0 = VTIM_real();
159 0
        vca_periodic(t0);
160
161 0
        pool_accepting = 1;
162
163 33630
        while (1) {
164 33630
                (void)sleep(1);
165
166 100890
                VCA_Foreach(vca) {
167 67260
                        CHECK_OBJ_NOTNULL(vca, ACCEPTOR_MAGIC);
168 67260
                        vca->update(&shut_mtx);
169
                }
170
171 33630
                vca_periodic(t0);
172
        }
173
174
        NEEDLESS(return (NULL));
175
}
176
177
/*--------------------------------------------------------------------*/
178
179
void
180 36480
VCA_Start(struct cli *cli)
181
{
182
        struct acceptor *vca;
183
184 36480
        ASSERT_CLI();
185
186 109440
        VCA_Foreach(vca) {
187 72960
                CHECK_OBJ_NOTNULL(vca, ACCEPTOR_MAGIC);
188 72960
                vca->start(cli);
189
        }
190
191 36480
        PTOK(pthread_create(&VCA_thread, NULL, vca_acct, NULL));
192 36480
}
193
194
/*--------------------------------------------------------------------*/
195
196
static void v_matchproto_(cli_func_t)
197 72440
ccf_listen_address(struct cli *cli, const char * const *av, void *priv)
198
{
199
        struct listen_sock *ls;
200
201 72440
        (void)av;
202 72440
        (void)priv;
203
204
        /*
205
         * This CLI command is primarily used by varnishtest.  Don't
206
         * respond until listen(2) has been called, in order to avoid
207
         * a race where varnishtest::client would attempt to connect(2)
208
         * before listen(2) has been called.
209
         */
210 72440
        while (!pool_accepting)
211 0
                VTIM_sleep(.1);
212
213 72440
        PTOK(pthread_mutex_lock(&shut_mtx));
214
215
        /*
216
         * Varnishtest expects the list of listen sockets to come out in the
217
         * same order as it is specified on the command line.
218
         */
219 145360
        VTAILQ_FOREACH(ls, &heritage.socks, list) {
220 72920
                CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
221 72920
                CHECK_OBJ_NOTNULL(ls->vca, ACCEPTOR_MAGIC);
222 72920
                ls->vca->event(cli, ls, VCA_EVENT_LADDR);
223 72920
        }
224
225 72440
        PTOK(pthread_mutex_unlock(&shut_mtx));
226 72440
}
227
228
/*--------------------------------------------------------------------*/
229
230
static struct cli_proto vca_cmds[] = {
231
        { CLICMD_DEBUG_LISTEN_ADDRESS,  "d", ccf_listen_address },
232
        { NULL }
233
};
234
235
void
236 36671
VCA_Init(void)
237
{
238
        struct acceptor *vca;
239
240 36671
        CLI_AddFuncs(vca_cmds);
241 36671
        Lck_New(&pace_mtx, lck_vcapace);
242
243 110013
        VCA_Foreach(vca) {
244 73342
                CHECK_OBJ_NOTNULL(vca, ACCEPTOR_MAGIC);
245 73342
                vca->init();
246
        }
247 36671
}
248
249
void
250 36160
VCA_Shutdown(void)
251
{
252
        struct acceptor *vca;
253
254 36160
        PTOK(pthread_mutex_lock(&shut_mtx));
255
256 108480
        VCA_Foreach(vca) {
257 72320
                CHECK_OBJ_NOTNULL(vca, ACCEPTOR_MAGIC);
258 72320
                vca->shutdown();
259
        }
260
261 36160
        PTOK(pthread_mutex_unlock(&shut_mtx));
262 36160
}
263
264
/*--------------------------------------------------------------------
265
 * Transport protocol registration
266
 *
267
 */
268
269
static VTAILQ_HEAD(,transport)  transports =
270
    VTAILQ_HEAD_INITIALIZER(transports);
271
272
static uint16_t next_xport;
273
274
void
275 119520
XPORT_Register(struct transport *xp)
276
{
277
278 119520
        CHECK_OBJ_NOTNULL(xp, TRANSPORT_MAGIC);
279 119520
        AZ(xp->number);
280
281 119520
        xp->number = ++next_xport;
282 119520
        VTAILQ_INSERT_TAIL(&transports, xp, list);
283 119520
}
284
285
void
286 39840
XPORT_Init(void)
287
{
288
289 39840
        ASSERT_MGT();
290
291
#define TRANSPORT_MACRO(name) XPORT_Register(&name##_transport);
292 39840
        TRANSPORTS
293
#undef TRANSPORT_MACRO
294 39840
}
295
296
const struct transport *
297 38800
XPORT_Find(const char *name)
298
{
299
        const struct transport *xp;
300
301 38800
        ASSERT_MGT();
302
303 77040
        VTAILQ_FOREACH(xp, &transports, list)
304 76960
                if (xp->proto_ident != NULL &&
305 76960
                    !strcasecmp(xp->proto_ident, name))
306 38720
                        return (xp);
307 80
        return (NULL);
308 38800
}
309
310
const struct transport *
311 91969
XPORT_ByNumber(uint16_t no)
312
{
313
        const struct transport *xp;
314
315 183977
        VTAILQ_FOREACH(xp, &transports, list)
316 183977
                if (xp->number == no)
317 91969
                        return (xp);
318 0
        return (NULL);
319 91969
}