paging: Use bsub->active_paging_requests to allow early loop termination adding paging_req

Before this patch, the entire queue of paging_request had to be iterated
in order to find if the subscriber already had an active paging request
(discarding duplicates).

Now that bsc_subscriber holds a list of its active paging requests, it's
easier to look at its list to find out if it is already active on that
BTS.

As a result, there's no need to unconditionally iterate the whole list
and we can optimize the loop finding the spot to insert the new queue:
- First the potentially way smaller loop over
  bsub->active_paging_requests is done
- Second, only if the first loop allowed, the bts->pending_requests is
  iterated and potentially early terminated.

Related: SYS#6200
Change-Id: I7912275026c4d4983269c8870aa5565c93277c5a
This commit is contained in:
Pau Espin 2022-11-22 14:30:36 +01:00
parent 70a1d60a83
commit 0ed7700c1e
1 changed files with 28 additions and 17 deletions

View File

@ -415,31 +415,42 @@ static int _paging_request(const struct bsc_paging_params *params, struct gsm_bt
return -ENOSPC;
}
/* Iterate list of pending requests to find if we already have one for
* the given subscriber. While on it, find the last
* not-yet-ever-once-transmitted request; the new request will be added
* immediately after it, giving higher prio to initial transmissions
* (no retrans). This avoids new subscribers being paged to be delayed
* if the paging queue is full due to a lot of retranmissions.
/* Find if we already have one for the given subscriber on this BTS: */
if (bsc_subscr_find_req_by_bts(params->bsub, bts)) {
LOG_PAGING_BTS(params, bts, DPAG, LOGL_INFO, "Paging request already pending for this subscriber\n");
rate_ctr_inc(rate_ctr_group_get_ctr(bts->bts_ctrs, BTS_CTR_PAGING_ALREADY));
return -EEXIST;
}
/* Find the last not-yet-ever-once-transmitted request; the new request
* will be added immediately after it, giving higher prio to initial
* transmissions (no retrans). This avoids new subscribers being paged to
* be delayed if the paging queue is full due to a lot of retranmissions.
* Retranmissions usually mean MS are not reachable/available, so the
* rationale here is to prioritize new subs which may be available. */
* rationale here is to prioritize new subs which may be available.
*/
llist_for_each_entry(req, &bts_entry->pending_requests, entry) {
if (params->bsub == req->bsub) {
LOG_PAGING_BTS(params, bts, DPAG, LOGL_INFO, "Paging request already pending for this subscriber\n");
rate_ctr_inc(rate_ctr_group_get_ctr(bts->bts_ctrs, BTS_CTR_PAGING_ALREADY));
return -EEXIST;
}
if (req->attempts == 0) {
/* Keep counting no-retransmits (general and per same pgroup): */
last_initial_req = req;
reqs_before++;
if (req->pgroup == pgroup)
reqs_before_same_pgroup++;
} else if (last_initial_req == NULL) {
/* If no req with attempts=0 was found, we'll append to end of list, so keep counting. */
reqs_before++;
if (req->pgroup == pgroup)
reqs_before_same_pgroup++;
continue;
}
/* Here first retransmit in queue is reached: */
if (last_initial_req) {
/* There were no-retransmit in the queue, done
* iterating, new req will be inserted here
* (see below the current loop). */
break;
}
/* last_initial_req == NULL: No req with attempts=0 was found,
* we'll append to end of list, so keep counting. */
reqs_before++;
if (req->pgroup == pgroup)
reqs_before_same_pgroup++;
}
LOG_PAGING_BTS(params, bts, DPAG, LOGL_DEBUG, "Start paging\n");