From: Alan T. DeKok Date: Sun, 1 Oct 2017 21:58:32 +0000 (-0400) Subject: move retransmission timers to rlm_radius_udp_t X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fa6fc2e35d7dd9af3e756db8cc4b0302f386ed91;p=thirdparty%2Ffreeradius-server.git move retransmission timers to rlm_radius_udp_t so that they operate across connections --- diff --git a/src/modules/rlm_radius/rlm_radius_udp.c b/src/modules/rlm_radius/rlm_radius_udp.c index ee2e68dcc16..7b814b7f4f2 100644 --- a/src/modules/rlm_radius/rlm_radius_udp.c +++ b/src/modules/rlm_radius/rlm_radius_udp.c @@ -152,6 +152,9 @@ struct rlm_radius_udp_request_t { rlm_radius_udp_connection_t *c; //!< The connection state machine. rlm_radius_link_t *link; //!< More link stuff. rlm_radius_request_t *rr; //!< ID tracking, resend count, etc. + + rlm_radius_retransmit_t timer; //!< retransmission data structures + uint8_t *packet; //!< Packet we write to the network. size_t packet_len; //!< Length of the packet. }; @@ -618,7 +621,7 @@ redo: /* * Stop all retransmissions for this packet. */ - if (u->rr->ev) (void) fr_event_timer_delete(c->thread->el, &u->rr->ev); + if (u->timer.ev) (void) fr_event_timer_delete(c->thread->el, &u->timer.ev); switch (c->state) { default: @@ -647,8 +650,8 @@ redo: /* * Track the Most Recently Started with reply */ - if (timercmp(&rr->start, &c->mrs_time, >)) { - c->mrs_time = rr->start; + if (timercmp(&u->timer.start, &c->mrs_time, >)) { + c->mrs_time = u->timer.start; } (void) fr_heap_insert(c->thread->active, c); @@ -941,7 +944,7 @@ static void retransmit_packet(rlm_radius_udp_request_t *u, struct timeval *now) uint32_t delay; struct timeval diff; - fr_timeval_subtract(&diff, now, &u->rr->start); + fr_timeval_subtract(&diff, now, &u->timer.start); delay = u->initial_delay_time + diff.tv_sec; delay = htonl(delay); memcpy(u->acct_delay_time, &delay, 4); @@ -958,8 +961,8 @@ static void retransmit_packet(rlm_radius_udp_request_t *u, struct timeval *now) } } - RDEBUG("Retransmitting request. Expecting response within %d.%06ds", - u->rr->rt / USEC, u->rr->rt % USEC); + RDEBUG("Retransmitting request (%d/%d). Expecting response within %d.%06ds", + u->timer.count, c->inst->parent->retry[u->code].mrc, u->timer.rt / USEC, u->timer.rt % USEC); /* * Debug the packet again, including any extra @@ -1295,7 +1298,7 @@ static int conn_write(rlm_radius_udp_connection_t *c, rlm_radius_udp_request_t * * Start the retransmission timers. */ u->link->time_sent = fr_time(); - fr_time_to_timeval(&u->rr->start, u->link->time_sent); + fr_time_to_timeval(&u->timer.start, u->link->time_sent); if (proxy_state) { c->num_requests++; @@ -1309,7 +1312,7 @@ static int conn_write(rlm_radius_udp_connection_t *c, rlm_radius_udp_request_t * if (!c->inst->parent->synchronous) { RDEBUG("Proxying request. Expecting response within %d.%06ds", - u->rr->rt / USEC, u->rr->rt % USEC); + u->timer.rt / USEC, u->timer.rt % USEC); if (rr_track_start(c->id, u->rr, c->thread->el, response_timeout, u, &c->inst->parent->retry[u->code]) < 0) { @@ -1330,7 +1333,7 @@ static int conn_write(rlm_radius_udp_connection_t *c, rlm_radius_udp_request_t * RDEBUG("Proxying request. Relying on NAS to perform retransmissions"); } - } else if (u->rr->count == 0) { + } else if (u->timer.count == 0) { if (rr_track_start(c->id, u->rr, c->thread->el, status_check_timeout, u, &c->inst->parent->retry[u->code]) < 0) { RDEBUG("Failed starting retransmit tracking"); @@ -1339,12 +1342,12 @@ static int conn_write(rlm_radius_udp_connection_t *c, rlm_radius_udp_request_t * RDEBUG("Sending %s status check. Expecting response within %d.%06ds", fr_packet_codes[u->code], - u->rr->rt / USEC, u->rr->rt % USEC); + u->timer.rt / USEC, u->timer.rt % USEC); } else { RDEBUG("Retransmitting %s status check. Expecting response within %d.%06ds", fr_packet_codes[u->code], - u->rr->rt / USEC, u->rr->rt % USEC); + u->timer.rt / USEC, u->timer.rt % USEC); } fr_dlist_remove(&u->entry); @@ -1533,7 +1536,7 @@ static int status_udp_request_free(rlm_radius_udp_request_t *u) * * @param[in] fd of connection that failed. * @param[in] state the connection was in when it failed. - * @param[in] uctx the connection. + * @param[in] uctx the connection. */ static fr_connection_state_t _conn_failed(int fd, fr_connection_state_t state, void *uctx) { @@ -1707,7 +1710,7 @@ static fr_connection_state_t _conn_open(UNUSED fr_event_list_t *el, UNUSED int f * demand. If the proxied packets use all of the * IDs, then we can't send a Status-Server check. */ - u->rr = rr_track_alloc(c->id, request, u->code, link); + u->rr = rr_track_alloc(c->id, request, u->code, link, &u->timer); if (!u->rr) { ERROR("%s - Failed allocating status_check ID for new connection %s", c->inst->parent->name, c->name); @@ -1851,7 +1854,7 @@ static int _conn_free(rlm_radius_udp_connection_t *c) */ u->rr = NULL; u->c = NULL; - (void) fr_event_timer_delete(c->thread->el, &u->rr->ev); + (void) fr_event_timer_delete(c->thread->el, &u->timer.ev); fr_dlist_remove(&u->entry); (void) fr_heap_insert(t->queued, u); t->pending = true; @@ -1994,13 +1997,13 @@ static rlm_radius_udp_connection_t *connection_get(rlm_radius_udp_thread_t *t, r rad_assert(c->state == CONN_ACTIVE); rad_assert(c->num_requests < c->max_requests); - u->rr = rr_track_alloc(c->id, u->link->request, u->code, u->link); + u->rr = rr_track_alloc(c->id, u->link->request, u->code, u->link, &u->timer); if (!u->rr) { rad_assert(0 == 1); return NULL; } - rad_assert(u->rr->count == 0); + rad_assert(u->timer.count == 0); u->c = c; fr_heap_extract(t->active, c); diff --git a/src/modules/rlm_radius/track.c b/src/modules/rlm_radius/track.c index b4960d13c5c..d9e9d1e76ae 100644 --- a/src/modules/rlm_radius/track.c +++ b/src/modules/rlm_radius/track.c @@ -45,7 +45,7 @@ static int rr_track_free(rlm_radius_id_t *id) * The timers are parented from the request, so * we have to manually free them here. */ - talloc_const_free(id->id[i].ev); + talloc_const_free(id->id[i].timer->ev); } return 0; @@ -104,7 +104,8 @@ static int rr_cmp(void const *one, void const *two) * - NULL on error * - rlm_radius_request_t on success */ -rlm_radius_request_t *rr_track_alloc(rlm_radius_id_t *id, REQUEST *request, int code, rlm_radius_link_t *link) +rlm_radius_request_t *rr_track_alloc(rlm_radius_id_t *id, REQUEST *request, int code, rlm_radius_link_t *link, + rlm_radius_retransmit_t *timer) { fr_dlist_t *entry; rlm_radius_request_t *rr; @@ -169,13 +170,15 @@ retry: done: rr->link = link; rr->request = request; - rr->ev = NULL; + + rr->timer = timer; + rr->timer->ev = NULL; rr->code = code; /* rr->id is already allocated */ - rr->start.tv_sec = 0; - rr->start.tv_usec = 0; - rr->count = 0; - rr->rt = 0; + rr->timer->start.tv_sec = 0; + rr->timer->start.tv_usec = 0; + rr->timer->count = 0; + rr->timer->rt = 0; id->num_requests++; return rr; @@ -233,9 +236,9 @@ int rr_track_delete(rlm_radius_id_t *id, rlm_radius_request_t *rr) (void) talloc_get_type_abort(id, rlm_radius_id_t); rr->request = NULL; - if (rr->ev) { - talloc_const_free(rr->ev); - rr->ev = NULL; + if (rr->timer->ev) { + talloc_const_free(rr->timer->ev); + rr->timer->ev = NULL; } rad_assert(id->num_requests > 0); @@ -389,18 +392,18 @@ int rr_track_retry(rlm_radius_id_t *id, rlm_radius_request_t *rr, fr_event_list_ * Get when we SHOULD have woken up, which might not be * the same as 'now'. */ - next = rr->start; - next.tv_usec += rr->rt; + next = rr->timer->start; + next.tv_usec += rr->timer->rt; /* * Increment retransmission counter */ - rr->count++; + rr->timer->count++; /* * We retried too many times. Fail. */ - if (retry->mrc && (rr->count > retry->mrc)) { + if (retry->mrc && (rr->timer->count > retry->mrc)) { DEBUG3("RETRANSMIT - reached MRC %d", retry->mrc); return 0; } @@ -411,7 +414,7 @@ int rr_track_retry(rlm_radius_id_t *id, rlm_radius_request_t *rr, fr_event_list_ if (retry->mrd) { struct timeval end; - end = rr->start; + end = rr->timer->start; end.tv_sec += retry->mrd; if (timercmp(now, &end, >=)) { @@ -430,10 +433,10 @@ int rr_track_retry(rlm_radius_id_t *id, rlm_radius_request_t *rr, fr_event_list_ delay = fr_rand(); delay ^= (delay >> 16); delay &= 0xffff; - frac = rr->rt / 5; + frac = rr->timer->rt / 5; delay = ((frac >> 16) * delay) + (((frac & 0xffff) * delay) >> 16); - delay += (2 * rr->rt) - (rr->rt / 10); + delay += (2 * rr->timer->rt) - (rr->timer->rt / 10); /* * Cap delay at MRT @@ -455,20 +458,20 @@ int rr_track_retry(rlm_radius_id_t *id, rlm_radius_request_t *rr, fr_event_list_ /* * And finally set the retransmission timer. */ - rr->rt = delay; + rr->timer->rt = delay; /* * Get the next delay time. */ - next.tv_usec += rr->rt; + next.tv_usec += rr->timer->rt; next.tv_sec += (next.tv_usec / USEC); next.tv_usec %= USEC; - if (fr_event_timer_insert(id, el, &rr->ev, &next, callback, uctx) < 0) { + if (fr_event_timer_insert(id, el, &rr->timer->ev, &next, callback, uctx) < 0) { return -1; } - DEBUG3("RETRANSMIT - in %d.%06ds", rr->rt / USEC, rr->rt % USEC); + DEBUG3("RETRANSMIT - in %d.%06ds", rr->timer->rt / USEC, rr->timer->rt % USEC); return 1; } @@ -478,15 +481,15 @@ int rr_track_start(rlm_radius_id_t *id, rlm_radius_request_t *rr, fr_event_list_ { struct timeval next; - rr->count = 1; - rr->rt = retry->irt * USEC; /* rt is in usec */ + rr->timer->count = 1; + rr->timer->rt = retry->irt * USEC; /* rt is in usec */ - next = rr->start; - next.tv_usec += rr->rt; + next = rr->timer->start; + next.tv_usec += rr->timer->rt; next.tv_sec += (next.tv_usec / USEC); next.tv_usec %= USEC; - if (fr_event_timer_insert(id, el, &rr->ev, &next, callback, uctx) < 0) { + if (fr_event_timer_insert(id, el, &rr->timer->ev, &next, callback, uctx) < 0) { return -1; } diff --git a/src/modules/rlm_radius/track.h b/src/modules/rlm_radius/track.h index adc0e52cfc2..3cea850c8eb 100644 --- a/src/modules/rlm_radius/track.h +++ b/src/modules/rlm_radius/track.h @@ -27,6 +27,13 @@ * @copyright 2017 Alan DeKok */ +typedef struct rlm_radius_retransmit_t { + struct timeval start; //!< when we started sending the packet + uint32_t count; //!< how many times we sent this packet + uint32_t rt; //!< retransmit timer (microseconds) + fr_event_timer_t const *ev; //!< timer event associated with this packet +} rlm_radius_retransmit_t; + /** Track one request to a response * */ @@ -34,13 +41,10 @@ typedef struct rlm_radius_request_t { rlm_radius_link_t *link; //!< to the rlm_radius thread context, and to the IO submodule REQUEST *request; //!< as always... - fr_event_timer_t const *ev; //!< timer event associated with this packet - int code; //!< packet code (sigh) int id; //!< our ID - struct timeval start; //!< when we started sending the packet - uint32_t count; //!< how many times we sent this packet - uint32_t rt; //!< retransmit timer (microseconds) + + rlm_radius_retransmit_t *timer; //!< retransmission union { fr_dlist_t entry; //!< for free chain @@ -63,7 +67,8 @@ typedef struct rlm_radius_id_t { } rlm_radius_id_t; rlm_radius_id_t *rr_track_create(TALLOC_CTX *ctx); -rlm_radius_request_t *rr_track_alloc(rlm_radius_id_t *id, REQUEST *request, int code, rlm_radius_link_t *link) CC_HINT(nonnull); +rlm_radius_request_t *rr_track_alloc(rlm_radius_id_t *id, REQUEST *request, int code, + rlm_radius_link_t *link, rlm_radius_retransmit_t *timer) CC_HINT(nonnull); int rr_track_update(rlm_radius_id_t *id, rlm_radius_request_t *rr, uint8_t *vector) CC_HINT(nonnull); rlm_radius_request_t *rr_track_find(rlm_radius_id_t *id, int packet_id, uint8_t *vector) CC_HINT(nonnull(1)); int rr_track_delete(rlm_radius_id_t *id, rlm_radius_request_t *rr) CC_HINT(nonnull);