fixeria has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-trx/+/43109?usp=email )


Change subject: libosmo-trx/client: add optional limit for retransmissions
......................................................................

libosmo-trx/client: add optional limit for retransmissions

The client used to retransmit an unacknowledged command forever, like
osmo-bts-trx does.  trxcon, however, gives up after 3 retransmission
attempts, concluding that the transceiver is offline.  Add a new API
function osmo_trxc_client_set_max_retrans() enabling this behavior:
once a command has been retransmitted the given number of times
without a response, the client escalates to the fatal_error call-back
(with rsp == NULL) and freezes the command queue.  The default (0)
retains the old behavior (no limit).

This is a preparation for porting trxcon to libosmo-trx.

Change-Id: Ib90a032b38c69ae26023e726992d3f5f7e502fcf
---
M libosmo-trx/include/osmocom/trx/trxc_client.h
M libosmo-trx/src/trxc_client.c
M tests/libosmo-trx/trxc_client_test.c
M tests/libosmo-trx/trxc_client_test.err
M tests/libosmo-trx/trxc_client_test.ok
5 files changed, 111 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/09/43109/1

diff --git a/libosmo-trx/include/osmocom/trx/trxc_client.h 
b/libosmo-trx/include/osmocom/trx/trxc_client.h
index 7984b93..a182f40 100644
--- a/libosmo-trx/include/osmocom/trx/trxc_client.h
+++ b/libosmo-trx/include/osmocom/trx/trxc_client.h
@@ -48,6 +48,7 @@
 int osmo_trxc_client_set_name(struct osmo_trxc_client *client, const char 
*fmt, ...);
 void osmo_trxc_client_set_log_cat(struct osmo_trxc_client *client, int 
log_cat);
 void osmo_trxc_client_set_retrans(struct osmo_trxc_client *client, unsigned 
int sec);
+void osmo_trxc_client_set_max_retrans(struct osmo_trxc_client *client, 
unsigned int n);

 /*! escalate to the fatal_error call-back on NACK */
 #define OSMO_TRXC_F_CRITICAL           (1 << 0)
diff --git a/libosmo-trx/src/trxc_client.c b/libosmo-trx/src/trxc_client.c
index 39b2a43..f9c393b 100644
--- a/libosmo-trx/src/trxc_client.c
+++ b/libosmo-trx/src/trxc_client.c
@@ -44,11 +44,15 @@
 /*! Default retransmit timeout (in seconds) */
 #define TRXC_CLIENT_RETRANS_SEC                2

+static int trxc_client_fatal(struct osmo_trxc_client *client,
+                            const struct osmo_trxc_msg *rsp);
+
 /*! A single command in the queue */
 struct trxc_cmd_entry {
        struct llist_head list;
        struct osmo_trxc_msg msg;       /* type == OSMO_TRXC_MT_CMD */
        uint32_t flags;                 /* OSMO_TRXC_F_* */
+       unsigned int n_retrans; /* number of retransmissions so far */
        osmo_trxc_client_rsp_cb *rsp_cb;
        void *cb_data;
 };
@@ -58,6 +62,7 @@
        char *name;                     /* log prefix */
        int log_cat;                    /* logging category (default DLGLOBAL) 
*/
        unsigned int retrans_sec;       /* retransmit timeout */
+       unsigned int max_retrans;       /* maximum number of retransmissions (0 
= no limit) */

        struct llist_head cmd_queue;    /* list of struct trxc_cmd_entry */
        struct trxc_cmd_entry *last_acked;
@@ -113,6 +118,15 @@
        LOGCL(client, LOGL_NOTICE, "No response from transceiver for '" 
CMD_NAME_FMT "'\n",
              CMD_NAME_ARGS(e));

+       if (client->max_retrans != 0 && e->n_retrans >= client->max_retrans) {
+               LOGCL(client, LOGL_FATAL, "Giving up on '" CMD_NAME_FMT "' 
after %u "
+                     "retransmissions, transceiver offline?\n",
+                     CMD_NAME_ARGS(e), e->n_retrans);
+               trxc_client_fatal(client, NULL);
+               return; /* keep the command queue frozen, do not re-arm the 
timer */
+       }
+
+       e->n_retrans++;
        trxc_client_send_next(client);
 }

@@ -192,6 +206,16 @@
        client->retrans_sec = sec;
 }

+/*! Set the maximum number of retransmissions of a command (default: 0).
+ *  Once a command has been retransmitted the given number of times without
+ *  a response, the engine gives up and escalates to the fatal_error
+ *  call-back (with rsp == NULL); the command queue remains frozen.
+ *  The special value 0 means no limit: retransmit indefinitely. */
+void osmo_trxc_client_set_max_retrans(struct osmo_trxc_client *client, 
unsigned int n)
+{
+       client->max_retrans = n;
+}
+
 /*! Enqueue a new command for transmission.
  *
  *  The new command is added to the end of the queue; there's at most one
@@ -398,6 +422,9 @@
                 * implement a fallback (see the SETFORMAT negotiation). */
        }

+       /* the transceiver is responsive (again) */
+       e->n_retrans = 0;
+
        client->in_rx = true;
        if (e->rsp_cb != NULL)
                rc = e->rsp_cb(client, &rsp, e->cb_data);
diff --git a/tests/libosmo-trx/trxc_client_test.c 
b/tests/libosmo-trx/trxc_client_test.c
index e042e10..eb9930d 100644
--- a/tests/libosmo-trx/trxc_client_test.c
+++ b/tests/libosmo-trx/trxc_client_test.c
@@ -164,6 +164,39 @@
        osmo_trxc_client_free(client);
 }

+static void test_max_retrans(void)
+{
+       struct osmo_trxc_client *client = client_alloc();
+
+       printf("=== %s ===\n", __func__);
+
+       /* give up after 3 retransmissions (like trxcon does) */
+       osmo_trxc_client_set_max_retrans(client, 3);
+
+       osmo_trxc_client_poweron(client, &rsp_cb, "poweron");
+       /* no response: 3 retransmissions, then fatal_error escalation */
+       for (unsigned int i = 0; i < 5; i++)
+               fake_time_passes(2);
+
+       osmo_trxc_client_free(client);
+
+       /* a response resets the retransmission counter */
+       client = client_alloc();
+       osmo_trxc_client_set_max_retrans(client, 3);
+
+       osmo_trxc_client_poweron(client, &rsp_cb, "poweron");
+       fake_time_passes(2);
+       fake_time_passes(2);
+       rx_rsp(client, "RSP POWERON 0");
+       osmo_trxc_client_rxtune(client, 890000, &rsp_cb, "rxtune");
+       /* the previous 2 retransmissions shall not count for RXTUNE */
+       fake_time_passes(2);
+       fake_time_passes(2);
+       rx_rsp(client, "RSP RXTUNE 0 890000");
+
+       osmo_trxc_client_free(client);
+}
+
 static int rsp_retry_cb(struct osmo_trxc_client *client,
                        const struct osmo_trxc_msg *rsp, void *cb_data)
 {
@@ -307,6 +340,7 @@
        test_queueing();
        test_dup_rsp();
        test_retrans();
+       test_max_retrans();
        test_rsp_cb_retry();
        test_fatal_error();
        test_negotiate_format();
diff --git a/tests/libosmo-trx/trxc_client_test.err 
b/tests/libosmo-trx/trxc_client_test.err
index e280bf1..115a9de 100644
--- a/tests/libosmo-trx/trxc_client_test.err
+++ b/tests/libosmo-trx/trxc_client_test.err
@@ -27,6 +27,30 @@
 DLGLOBAL INFO phy0.trx0: Rx 'RSP POWERON 0'
 DLGLOBAL INFO phy0.trx0: Enqueueing 'CMD POWERON'
 DLGLOBAL DEBUG phy0.trx0: Tx 'CMD POWERON'
+DLGLOBAL NOTICE phy0.trx0: No response from transceiver for 'CMD POWERON'
+DLGLOBAL DEBUG phy0.trx0: Tx 'CMD POWERON'
+DLGLOBAL NOTICE phy0.trx0: No response from transceiver for 'CMD POWERON'
+DLGLOBAL DEBUG phy0.trx0: Tx 'CMD POWERON'
+DLGLOBAL NOTICE phy0.trx0: No response from transceiver for 'CMD POWERON'
+DLGLOBAL DEBUG phy0.trx0: Tx 'CMD POWERON'
+DLGLOBAL NOTICE phy0.trx0: No response from transceiver for 'CMD POWERON'
+DLGLOBAL FATAL phy0.trx0: Giving up on 'CMD POWERON' after 3 retransmissions, 
transceiver offline?
+DLGLOBAL INFO phy0.trx0: Enqueueing 'CMD POWERON'
+DLGLOBAL DEBUG phy0.trx0: Tx 'CMD POWERON'
+DLGLOBAL NOTICE phy0.trx0: No response from transceiver for 'CMD POWERON'
+DLGLOBAL DEBUG phy0.trx0: Tx 'CMD POWERON'
+DLGLOBAL NOTICE phy0.trx0: No response from transceiver for 'CMD POWERON'
+DLGLOBAL DEBUG phy0.trx0: Tx 'CMD POWERON'
+DLGLOBAL INFO phy0.trx0: Rx 'RSP POWERON 0'
+DLGLOBAL INFO phy0.trx0: Enqueueing 'CMD RXTUNE 890000'
+DLGLOBAL DEBUG phy0.trx0: Tx 'CMD RXTUNE 890000'
+DLGLOBAL NOTICE phy0.trx0: No response from transceiver for 'CMD RXTUNE 890000'
+DLGLOBAL DEBUG phy0.trx0: Tx 'CMD RXTUNE 890000'
+DLGLOBAL NOTICE phy0.trx0: No response from transceiver for 'CMD RXTUNE 890000'
+DLGLOBAL DEBUG phy0.trx0: Tx 'CMD RXTUNE 890000'
+DLGLOBAL INFO phy0.trx0: Rx 'RSP RXTUNE 0 890000'
+DLGLOBAL INFO phy0.trx0: Enqueueing 'CMD POWERON'
+DLGLOBAL DEBUG phy0.trx0: Tx 'CMD POWERON'
 DLGLOBAL INFO phy0.trx0: Rx 'RSP POWERON 1'
 DLGLOBAL NOTICE phy0.trx0: No response from transceiver for 'CMD POWERON'
 DLGLOBAL DEBUG phy0.trx0: Tx 'CMD POWERON'
diff --git a/tests/libosmo-trx/trxc_client_test.ok 
b/tests/libosmo-trx/trxc_client_test.ok
index 5e908ce..0c0d09d 100644
--- a/tests/libosmo-trx/trxc_client_test.ok
+++ b/tests/libosmo-trx/trxc_client_test.ok
@@ -28,6 +28,31 @@
 rx_rsp: 'RSP POWERON 0'
 rsp_cb(poweron): 'RSP POWERON 0'
 (time passes: 10 s)
+=== test_max_retrans ===
+tx_msg: 'CMD POWERON'
+(time passes: 2 s)
+tx_msg: 'CMD POWERON'
+(time passes: 2 s)
+tx_msg: 'CMD POWERON'
+(time passes: 2 s)
+tx_msg: 'CMD POWERON'
+(time passes: 2 s)
+fatal_error: '(null)'
+(time passes: 2 s)
+tx_msg: 'CMD POWERON'
+(time passes: 2 s)
+tx_msg: 'CMD POWERON'
+(time passes: 2 s)
+tx_msg: 'CMD POWERON'
+rx_rsp: 'RSP POWERON 0'
+rsp_cb(poweron): 'RSP POWERON 0'
+tx_msg: 'CMD RXTUNE 890000'
+(time passes: 2 s)
+tx_msg: 'CMD RXTUNE 890000'
+(time passes: 2 s)
+tx_msg: 'CMD RXTUNE 890000'
+rx_rsp: 'RSP RXTUNE 0 890000'
+rsp_cb(rxtune): 'RSP RXTUNE 0 890000'
 === test_rsp_cb_retry ===
 tx_msg: 'CMD POWERON'
 rx_rsp: 'RSP POWERON 1'

--
To view, visit https://gerrit.osmocom.org/c/osmo-trx/+/43109?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: osmo-trx
Gerrit-Branch: master
Gerrit-Change-Id: Ib90a032b38c69ae26023e726992d3f5f7e502fcf
Gerrit-Change-Number: 43109
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>

Reply via email to