aboutsummaryrefslogtreecommitdiffstats
path: root/src/gprs_rlcmac.cpp
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2012-10-07 15:26:00 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2012-12-18 10:02:20 +0100
commitb83e2a7d5cae302fb33ad56fa6dbad7906165909 (patch)
treed398de81ccc921a64076baf0ca15202477b39594 /src/gprs_rlcmac.cpp
parent5cae087ae9ed58910af69e9869b5dca4c0234628 (diff)
Adding flow chart diagram of ongoing TBFs and their events
It is quite essential. It shows how TBFs are related and helps to estimate states and timers (timeouts) of the MS. In order to use it, it must be defined by a switch at gprs_rlcmac.h.
Diffstat (limited to 'src/gprs_rlcmac.cpp')
-rw-r--r--src/gprs_rlcmac.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp
index fcd92c64..b5e0f352 100644
--- a/src/gprs_rlcmac.cpp
+++ b/src/gprs_rlcmac.cpp
@@ -89,6 +89,90 @@ llist_head *gprs_rlcmac_tbfs_lists[] = {
};
extern void *tall_pcu_ctx;
+#ifdef DEBUG_DIAGRAM
+struct timeval diagram_time = {0,0};
+struct timeval diagram_last_tv = {0,0};
+
+void debug_diagram(int diag, const char *format, ...)
+{
+ va_list ap;
+ char debug[128];
+ char line[1024];
+ struct gprs_rlcmac_tbf *tbf, *tbf_a[16];
+ int max_diag = -1, i;
+ uint64_t diff = 0;
+
+ va_start(ap, format);
+ vsnprintf(debug, sizeof(debug) - 1, format, ap);
+ debug[19] = ' ';
+ debug[20] = '\0';
+ va_end(ap);
+
+ memset(tbf_a, 0, sizeof(tbf_a));
+ llist_for_each_entry(tbf, &gprs_rlcmac_ul_tbfs, list) {
+ if (tbf->diag < 16) {
+ if (tbf->diag > max_diag)
+ max_diag = tbf->diag;
+ tbf_a[tbf->diag] = tbf;
+ }
+ }
+ llist_for_each_entry(tbf, &gprs_rlcmac_dl_tbfs, list) {
+ if (tbf->diag < 16) {
+ if (tbf->diag > max_diag)
+ max_diag = tbf->diag;
+ tbf_a[tbf->diag] = tbf;
+ }
+ }
+
+ if (diagram_last_tv.tv_sec) {
+ diff = (uint64_t)(diagram_time.tv_sec -
+ diagram_last_tv.tv_sec) * 1000;
+ diff += diagram_time.tv_usec / 1000;
+ diff -= diagram_last_tv.tv_usec / 1000;
+ }
+ memcpy(&diagram_last_tv, &diagram_time, sizeof(struct timeval));
+
+ if (diff > 0) {
+ if (diff > 99999)
+ strcpy(line, " ... : ");
+ else
+ sprintf(line, "%3d.%03d: ", (int)(diff / 1000),
+ (int)(diff % 1000));
+ for (i = 0; i <= max_diag; i++) {
+ if (tbf_a[i] == NULL) {
+ strcat(line, " ");
+ continue;
+ }
+ if (tbf_a[i]->diag_new) {
+ strcat(line, " | ");
+ continue;
+ }
+ strcat(line, " ");
+ }
+ puts(line);
+ }
+ strcpy(line, " : ");
+ for (i = 0; i <= max_diag; i++) {
+ if (tbf_a[i] == NULL) {
+ strcat(line, " ");
+ continue;
+ }
+ if (tbf_a[i]->diag != diag) {
+ strcat(line, " | ");
+ continue;
+ }
+ if (strlen(debug) < 19) {
+ strcat(line, " ");
+ memcpy(line + strlen(line) - 11 - strlen(debug) / 2,
+ debug, strlen(debug));
+ } else
+ strcat(line, debug);
+ tbf_a[i]->diag_new = 1;
+ }
+ puts(line);
+}
+#endif
+
/* FIXME: spread ressources over multiple TRX. Also add option to use same
* TRX in case of existing TBF for TLLI in the other direction. */
/* search for free TFI and return TFI, TRX and first TS */
@@ -246,6 +330,24 @@ struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_tbf *old_tbf,
struct gprs_rlcmac_tbf *tbf;
int rc;
+#ifdef DEBUG_DIAGRAM
+ /* hunt for first free number in diagram */
+ int diagram_num;
+ for (diagram_num = 0; ; diagram_num++) {
+ llist_for_each_entry(tbf, &gprs_rlcmac_ul_tbfs, list) {
+ if (tbf->diag == diagram_num)
+ goto next_diagram;
+ }
+ llist_for_each_entry(tbf, &gprs_rlcmac_dl_tbfs, list) {
+ if (tbf->diag == diagram_num)
+ goto next_diagram;
+ }
+ break;
+next_diagram:
+ continue;
+ }
+#endif
+
LOGP(DRLCMAC, LOGL_DEBUG, "********** TBF starts here **********\n");
LOGP(DRLCMAC, LOGL_INFO, "Allocating %s TBF: TFI=%d TRX=%d "
"MS_CLASS=%d\n", (dir == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL",
@@ -258,6 +360,9 @@ struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_tbf *old_tbf,
if (!tbf)
return NULL;
+#ifdef DEBUG_DIAGRAM
+ tbf->diag = diagram_num;
+#endif
tbf->direction = dir;
tbf->tfi = tfi;
tbf->trx = trx;
@@ -296,6 +401,11 @@ struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_tbf *old_tbf,
else
llist_add(&tbf->list, &gprs_rlcmac_dl_tbfs);
+ debug_diagram(tbf->diag, "+-----------------+");
+ debug_diagram(tbf->diag, "|NEW %s TBF TFI=%2d|",
+ (dir == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tfi);
+ debug_diagram(tbf->diag, "+-----------------+");
+
return tbf;
}
@@ -741,6 +851,9 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf)
{
struct msgb *msg;
+ debug_diagram(tbf->diag, "+---------------+");
+ debug_diagram(tbf->diag, "| THE END |");
+ debug_diagram(tbf->diag, "+---------------+");
LOGP(DRLCMAC, LOGL_INFO, "Free %s TBF=%d with TLLI=0x%08x.\n",
(tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi,
tbf->tlli);
@@ -818,6 +931,7 @@ const char *tbf_state_name[] = {
void tbf_new_state(struct gprs_rlcmac_tbf *tbf,
enum gprs_rlcmac_tbf_state state)
{
+ debug_diagram(tbf->diag, "->%s", tbf_state_name[state]);
LOGP(DRLCMAC, LOGL_DEBUG, "%s TBF=%d changes state from %s to %s\n",
(tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi,
tbf_state_name[tbf->state], tbf_state_name[state]);