]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
move retransmission timers to rlm_radius_udp_t
authorAlan T. DeKok <aland@freeradius.org>
Sun, 1 Oct 2017 21:58:32 +0000 (17:58 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Sun, 1 Oct 2017 22:00:30 +0000 (18:00 -0400)
so that they operate across connections

src/modules/rlm_radius/rlm_radius_udp.c
src/modules/rlm_radius/track.c
src/modules/rlm_radius/track.h

index ee2e68dcc16230f506bd47ed7e0bc5770d61bb78..7b814b7f4f2eb7bb31f02b7293e286a6f947048c 100644 (file)
@@ -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);
index b4960d13c5cf269c7e0e707172ddd2740ca62b30..d9e9d1e76ae39686669efd1d747ccb3fcb65de0f 100644 (file)
@@ -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;
        }
 
index adc0e52cfc2322234211fb8f25a84b0ae330e6cc..3cea850c8ebe5d6e89ac34892456a62de7fc0b01 100644 (file)
  * @copyright 2017 Alan DeKok <aland@freeradius.org>
  */
 
+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);