Lines Matching refs:mesh
2 * services/mesh.c - deal with mesh of query states and handle events for that.
39 * This file contains functions to assist in dealing with a mesh of
40 * query states. This mesh is supposed to be thread-specific.
46 #include "services/mesh.h"
95 * Compare two response-ip client info entries for the purpose of mesh state
99 * We cannot share the mesh state for two queries if different response-ip
209 struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area));
210 if(!mesh) {
211 log_err("mesh area alloc: out of memory");
214 mesh->histogram = timehist_setup();
215 mesh->qbuf_bak = sldns_buffer_new(env->cfg->msg_buffer_size);
216 if(!mesh->histogram || !mesh->qbuf_bak) {
217 free(mesh);
218 log_err("mesh area alloc: out of memory");
221 mesh->mods = *stack;
222 mesh->env = env;
223 rbtree_init(&mesh->run, &mesh_state_compare);
224 rbtree_init(&mesh->all, &mesh_state_compare);
225 mesh->num_reply_addrs = 0;
226 mesh->num_reply_states = 0;
227 mesh->num_detached_states = 0;
228 mesh->num_forever_states = 0;
229 mesh->stats_jostled = 0;
230 mesh->stats_dropped = 0;
231 mesh->ans_expired = 0;
232 mesh->ans_cachedb = 0;
233 mesh->num_queries_discard_timeout = 0;
234 mesh->num_queries_replyaddr_limit = 0;
235 mesh->num_queries_wait_limit = 0;
236 mesh->num_dns_error_reports = 0;
237 mesh->max_reply_states = env->cfg->num_queries_per_thread;
238 mesh->max_forever_states = (mesh->max_reply_states+1)/2;
240 mesh->jostle_max.tv_sec = (time_t)(env->cfg->jostle_time / 1000);
241 mesh->jostle_max.tv_usec = (time_t)((env->cfg->jostle_time % 1000)
244 return mesh;
247 /** help mesh delete delete mesh states */
253 * because other callbacks expect a clean state in the mesh.
261 mesh_delete(struct mesh_area* mesh)
263 if(!mesh)
266 while(mesh->all.count)
267 mesh_delete_helper(mesh->all.root);
268 timehist_delete(mesh->histogram);
269 sldns_buffer_free(mesh->qbuf_bak);
270 free(mesh);
274 mesh_delete_all(struct mesh_area* mesh)
277 while(mesh->all.count)
278 mesh_delete_helper(mesh->all.root);
279 mesh->stats_dropped += mesh->num_reply_addrs;
280 /* clear mesh area references */
281 rbtree_init(&mesh->run, &mesh_state_compare);
282 rbtree_init(&mesh->all, &mesh_state_compare);
283 mesh->num_reply_addrs = 0;
284 mesh->num_reply_states = 0;
285 mesh->num_detached_states = 0;
286 mesh->num_forever_states = 0;
287 mesh->forever_first = NULL;
288 mesh->forever_last = NULL;
289 mesh->jostle_first = NULL;
290 mesh->jostle_last = NULL;
293 int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf)
295 struct mesh_state* m = mesh->jostle_first;
297 if(mesh->num_reply_states < mesh->max_reply_states)
304 timeval_subtract(&age, mesh->env->now_tv,
307 timeval_smaller(&mesh->jostle_max, &age)) {
314 if(qbuf) sldns_buffer_copy(mesh->qbuf_bak, qbuf);
320 mesh_walk_supers(mesh, m);
322 mesh->stats_jostled ++;
326 if(qbuf) sldns_buffer_copy(qbuf, mesh->qbuf_bak);
427 void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
433 int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
437 int timeout = mesh->env->cfg->serve_expired?
438 mesh->env->cfg->serve_expired_client_timeout:0;
444 if(!infra_wait_limit_allowed(mesh->env->infra_cache, rep,
445 edns->cookie_valid, mesh->env->cfg)) {
448 mesh->num_queries_wait_limit++;
450 mesh->env->scratch, LDNS_EDE_OTHER,
452 if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
453 LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv))
457 regional_free_all(mesh->env->scratch);
462 s = mesh_area_find(mesh, cinfo, qinfo, mesh_flags, 0, 0);
465 if(!mesh_make_new_space(mesh, rep->c->buffer)) {
471 mesh->stats_dropped++;
478 if(mesh->num_reply_addrs > mesh->max_reply_states*16) {
484 mesh->num_queries_replyaddr_limit++;
493 s = mesh_state_create(mesh->env, qinfo, cinfo,
497 if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
498 LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv))
506 mesh->num_detached_states++;
516 if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL,
517 NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv))
532 rbtree_insert(&mesh->all, &s->node);
548 if(!tcp_req_info_add_meshstate(rep->c->tcp_req_info, mesh, s)) {
554 http2_stream_add_meshstate(rep->c->h2_stream, mesh, s);
562 if(!timeout && mesh->env->cfg->serve_expired &&
563 !mesh->env->cfg->serve_expired_client_timeout &&
564 (mesh->env->cachedb_enabled &&
565 mesh->env->cfg->cachedb_check_when_serve_expired)) {
572 infra_wait_limit_inc(mesh->env->infra_cache, rep, *mesh->env->now,
573 mesh->env->cfg);
576 log_assert(mesh->num_detached_states > 0);
577 mesh->num_detached_states--;
580 mesh->num_reply_states ++;
582 mesh->num_reply_addrs++;
585 if(mesh->num_forever_states < mesh->max_forever_states) {
586 mesh->num_forever_states ++;
587 mesh_list_insert(s, &mesh->forever_first,
588 &mesh->forever_last);
591 mesh_list_insert(s, &mesh->jostle_first,
592 &mesh->jostle_last);
597 mesh_run(mesh, s, module_event_new, NULL);
601 if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
602 NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv))
615 mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
620 int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
621 int timeout = mesh->env->cfg->serve_expired?
622 mesh->env->cfg->serve_expired_client_timeout:0;
628 s = mesh_area_find(mesh, NULL, qinfo, mesh_flags, 0, 0);
637 s = mesh_state_create(mesh->env, qinfo, NULL,
643 mesh->num_detached_states++;
660 rbtree_insert(&mesh->all, &s->node);
683 if(!timeout && mesh->env->cfg->serve_expired &&
684 !mesh->env->cfg->serve_expired_client_timeout &&
685 (mesh->env->cachedb_enabled &&
686 mesh->env->cfg->cachedb_check_when_serve_expired)) {
696 log_assert(mesh->num_detached_states > 0);
697 mesh->num_detached_states--;
700 mesh->num_reply_states ++;
702 mesh->num_reply_addrs++;
704 mesh_run(mesh, s, module_event_new, NULL);
713 static void mesh_schedule_prefetch(struct mesh_area* mesh,
721 struct mesh_state* s = mesh_area_find(mesh, NULL, qinfo,
736 if(!mesh_make_new_space(mesh, NULL)) {
738 mesh->stats_dropped ++;
742 s = mesh_state_create(mesh->env, qinfo, NULL, mesh_flags, 0, 0);
752 rbtree_insert(&mesh->all, &s->node);
755 mesh->num_detached_states++;
762 if(mesh->num_forever_states < mesh->max_forever_states) {
763 mesh->num_forever_states ++;
764 mesh_list_insert(s, &mesh->forever_first,
765 &mesh->forever_last);
768 mesh_list_insert(s, &mesh->jostle_first,
769 &mesh->jostle_last);
781 rbtree_insert(&mesh->run, &s->run_node);
786 mesh_run(mesh, s, module_event_new, NULL);
794 static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
807 if(!mesh_make_new_space(mesh, NULL)) {
809 mesh->stats_dropped ++;
813 s = mesh_state_create(mesh->env, qinfo, NULL, mesh_flags, 0, 0);
820 opt = edns_opt_list_find(edns_list, mesh->env->cfg->client_subnet_opcode);
839 rbtree_insert(&mesh->all, &s->node);
842 mesh->num_detached_states++;
849 if(mesh->num_forever_states < mesh->max_forever_states) {
850 mesh->num_forever_states ++;
851 mesh_list_insert(s, &mesh->forever_first,
852 &mesh->forever_last);
855 mesh_list_insert(s, &mesh->jostle_first,
856 &mesh->jostle_last);
868 rbtree_insert(&mesh->run, &s->run_node);
873 mesh_run(mesh, s, module_event_new, NULL);
877 void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
885 mesh_schedule_prefetch_subnet(mesh, qinfo, qflags, leeway, 1,
889 mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1,
893 void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
903 mesh_run(mesh, e->qstate->mesh_info, event, e);
1045 for(i=0; i<env->mesh->mods.num; i++) {
1067 struct mesh_area* mesh;
1071 mesh = mstate->s.env->mesh;
1091 * takes no time and also it does not do the mesh accounting */
1094 infra_wait_limit_dec(mesh->env->infra_cache,
1095 &rep->query_reply, mesh->env->cfg);
1097 log_assert(mesh->num_reply_addrs > 0);
1098 mesh->num_reply_addrs--;
1105 log_assert(mesh->num_reply_addrs > 0);
1106 mesh->num_reply_addrs--;
1111 for(i=0; i<mesh->mods.num; i++) {
1112 fptr_ok(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear));
1113 (*mesh->mods.mod[i]->clear)(&mstate->s, i);
1123 struct mesh_area* mesh;
1129 mesh = mstate->s.env->mesh;
1132 mesh->num_forever_states --;
1133 mesh_list_remove(mstate, &mesh->forever_first,
1134 &mesh->forever_last);
1136 mesh_list_remove(mstate, &mesh->jostle_first,
1137 &mesh->jostle_last);
1141 log_assert(mesh->num_detached_states > 0);
1142 mesh->num_detached_states--;
1145 log_assert(mesh->num_reply_states > 0);
1146 mesh->num_reply_states--;
1153 (void)rbtree_delete(&mesh->run, mstate);
1154 (void)rbtree_delete(&mesh->all, mstate);
1189 struct mesh_area* mesh = qstate->env->mesh;
1206 mesh->num_detached_states++;
1207 log_assert(mesh->num_detached_states +
1208 mesh->num_reply_states <= mesh->all.count);
1219 struct mesh_area* mesh = qstate->env->mesh;
1220 *sub = mesh_area_find(mesh, cinfo, qinfo, qflags, prime, valrec);
1237 rbtree_insert(&mesh->all, &(*sub)->node);
1240 mesh->num_detached_states++;
1247 rbtree_insert(&mesh->run, &(*sub)->run_node);
1264 struct mesh_area* mesh = qstate->env->mesh;
1277 log_assert(mesh->num_detached_states > 0);
1278 mesh->num_detached_states--;
1322 * callback results to mesh cb entry
1323 * @param m: mesh state to send it for.
1328 * a value from one of the packets if the mesh state had packets.
1391 log_assert(m->s.env->mesh->num_reply_addrs > 0);
1392 m->s.env->mesh->num_reply_addrs--;
1439 * Send reply to mesh reply entry
1440 * @param m: mesh state to send it for.
1459 * null stops the mesh state remove and thus
1474 m->s.env->mesh->ans_bogus++;
1483 /* Mesh reply won't exist for long anymore. Make it impossible
1484 * for HTTP/2 stream to refer to mesh state, in case
1583 log_assert(m->s.env->mesh->num_reply_addrs > 0);
1584 m->s.env->mesh->num_reply_addrs--;
1589 m->s.env->mesh->replies_sent++;
1590 timeval_add(&m->s.env->mesh->replies_sum_wait, &duration);
1591 timehist_insert(m->s.env->mesh->histogram, &duration);
1595 if(secure) m->s.env->mesh->ans_secure++;
1596 m->s.env->mesh->ans_rcode[ rc ] ++;
1598 m->s.env->mesh->ans_nodata++;
1649 /* Get the EDE generated from the mesh state, these are mostly
1712 qstate->env->mesh->num_dns_error_reports++;
1769 * tcp req info cleanup routine that calls the mesh
1782 log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
1783 mstate->s.env->mesh->num_reply_addrs--;
1784 mstate->s.env->mesh->num_queries_discard_timeout++;
1804 * mesh processing, this is the point to take that action. */
1807 * tcp req info cleanup routine that calls the mesh
1820 log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
1821 mstate->s.env->mesh->num_reply_addrs--;
1834 /* mesh_send_reply removed mesh state from
1846 mstate->s.env->mesh->rpz_action[RPZ_DISABLED_ACTION] += i;
1848 mstate->s.env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION] += i;
1850 mstate->s.env->mesh->rpz_action[respip_action_to_rpz_action(
1856 mstate->s.env->mesh->ans_cachedb += i;
1860 /* Mesh area accounting */
1865 log_assert(mstate->s.env->mesh->num_reply_states > 0);
1866 mstate->s.env->mesh->num_reply_states--;
1870 mstate->s.env->mesh->num_detached_states++;
1879 log_assert(mstate->s.env->mesh->num_reply_states > 0);
1880 mstate->s.env->mesh->num_reply_states--;
1885 mstate->s.env->mesh->num_detached_states++;
1890 void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
1896 (void)rbtree_insert(&mesh->run, &ref->s->run_node);
1899 mesh->mods.mod[ref->s->s.curmod]->inform_super));
1900 (*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
1907 struct mesh_state* mesh_area_find(struct mesh_area* mesh,
1919 /* We are searching for a similar mesh state when we DO want to
1925 result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
1929 /** remove mesh state callback */
2084 * Continue processing the mesh state at another module.
2087 * @param mesh: the mesh area.
2088 * @param mstate: currently active mesh state.
2090 * send replies to clients and inform other mesh states.
2091 * This in turn may create additional runnable mesh states.
2099 mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
2106 mesh->mods.mod[mstate->s.curmod]->name);
2114 if(mesh->mods.num == mstate->s.curmod) {
2119 return mesh_continue(mesh, mstate, module_error, ev);
2123 for(; mstate->s.curmod < mesh->mods.num;
2126 mesh->mods.mod[mstate->s.curmod]->clear));
2127 (*mesh->mods.mod[mstate->s.curmod]->clear)
2148 mesh_walk_supers(mesh, mstate);
2163 modstack_find(&mesh->mods, "subnetcache") != -1 &&
2171 mesh_walk_supers(mesh, mstate);
2195 mesh_new_prefetch(mesh, qinfo, qflags, 0,
2212 void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
2220 mesh->mods.mod[mstate->s.curmod]->operate));
2221 (*mesh->mods.mod[mstate->s.curmod]->operate)
2229 mesh->mods.mod[mstate->s.curmod]->name, strextstate(s));
2231 if(mesh_continue(mesh, mstate, s, &ev))
2236 if(mesh->run.count > 0) {
2238 mstate = (struct mesh_state*)mesh->run.root->key;
2239 (void)rbtree_delete(&mesh->run, mstate);
2243 mesh_stats(mesh, "mesh_run: end");
2244 mesh_log_list(mesh);
2249 mesh_log_list(struct mesh_area* mesh)
2254 RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
2270 mesh_stats(struct mesh_area* mesh, const char* str)
2275 str, (unsigned)mesh->all.count,
2276 (unsigned)mesh->num_reply_states,
2277 (unsigned)mesh->num_detached_states,
2278 (unsigned)mesh->num_reply_addrs,
2279 (unsigned)mesh->replies_sent,
2280 (unsigned)mesh->stats_dropped,
2281 (unsigned)mesh->stats_jostled);
2282 if(mesh->replies_sent > 0) {
2284 timeval_divide(&avg, &mesh->replies_sum_wait,
2285 mesh->replies_sent);
2290 timehist_log(mesh->histogram, "recursions");
2295 mesh_stats_clear(struct mesh_area* mesh)
2297 if(!mesh)
2299 mesh->num_query_authzone_up = 0;
2300 mesh->num_query_authzone_down = 0;
2301 mesh->replies_sent = 0;
2302 mesh->replies_sum_wait.tv_sec = 0;
2303 mesh->replies_sum_wait.tv_usec = 0;
2304 mesh->stats_jostled = 0;
2305 mesh->stats_dropped = 0;
2306 timehist_clear(mesh->histogram);
2307 mesh->ans_secure = 0;
2308 mesh->ans_bogus = 0;
2309 mesh->val_ops = 0;
2310 mesh->ans_expired = 0;
2311 mesh->ans_cachedb = 0;
2312 memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM);
2313 memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM);
2314 mesh->ans_nodata = 0;
2315 mesh->num_queries_discard_timeout = 0;
2316 mesh->num_queries_replyaddr_limit = 0;
2317 mesh->num_queries_wait_limit = 0;
2318 mesh->num_dns_error_reports = 0;
2322 mesh_get_mem(struct mesh_area* mesh)
2325 size_t s = sizeof(*mesh) + sizeof(struct timehist) +
2326 sizeof(struct th_buck)*mesh->histogram->num +
2327 sizeof(sldns_buffer) + sldns_buffer_capacity(mesh->qbuf_bak);
2328 RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
2339 struct mesh_area* mesh = qstate->env->mesh;
2341 dep_m = mesh_area_find(mesh, NULL, qinfo, flags, prime, valrec);
2368 void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
2382 log_assert(mesh->num_reply_addrs > 0);
2383 mesh->num_reply_addrs--;
2384 infra_wait_limit_dec(mesh->env->infra_cache,
2385 &n->query_reply, mesh->env->cfg);
2401 mesh->num_detached_states++;
2405 log_assert(mesh->num_reply_states > 0);
2406 mesh->num_reply_states--;
2444 struct mesh_area* mesh = qstate->env->mesh;
2492 if((mesh->use_response_ip || mesh->use_rpz) &&
2546 * tcp req info cleanup routine that calls the mesh
2559 mstate->s.env->mesh
2592 /* mesh_send_reply removed mesh state from http2_stream. */
2600 mesh->ans_expired += i;
2604 qstate->env->mesh->rpz_action[RPZ_DISABLED_ACTION] += i;
2606 qstate->env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION] += i;
2608 qstate->env->mesh->rpz_action[
2613 /* Mesh area accounting */
2617 log_assert(mesh->num_reply_states > 0);
2618 mesh->num_reply_states--;
2620 mesh->num_detached_states++;
2630 log_assert(qstate->env->mesh->num_reply_states > 0);
2631 qstate->env->mesh->num_reply_states--;
2636 qstate->env->mesh->num_detached_states++;
2649 int mesh_jostle_exceeded(struct mesh_area* mesh)
2651 if(mesh->all.count < mesh->max_reply_states)
2656 void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
2660 s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
2665 log_assert(mesh->num_reply_addrs > 0);
2666 mesh->num_reply_addrs--;
2669 log_assert(mesh->num_reply_states > 0);
2670 mesh->num_reply_states--;
2674 mesh->num_detached_states++;