trx: Initial attempt to implement a single TRX commands queue.

This commit is contained in:
Alexander Chemeris 2015-06-29 22:08:11 -04:00
parent 4e3bfe1412
commit 917d214872
3 changed files with 73 additions and 56 deletions

View File

@ -142,12 +142,9 @@ struct trx_config {
}; };
struct trx_l1h { struct trx_l1h {
struct llist_head trx_ctrl_list;
struct gsm_bts_trx *trx; struct gsm_bts_trx *trx;
struct osmo_fd trx_ofd_ctrl; struct osmo_fd trx_ofd_ctrl;
struct osmo_timer_list trx_ctrl_timer;
struct osmo_fd trx_ofd_data; struct osmo_fd trx_ofd_data;
/* transceiver config */ /* transceiver config */

View File

@ -49,6 +49,10 @@ const char *transceiver_ip = "127.0.0.1";
int settsc_enabled = 0; int settsc_enabled = 0;
int setbsic_enabled = 0; int setbsic_enabled = 0;
/* control socket queue */
struct llist_head trx_ctrl_list;
struct osmo_timer_list trx_ctrl_timer;
/* /*
* socket * socket
*/ */
@ -158,35 +162,39 @@ static int trx_clk_read_cb(struct osmo_fd *ofd, unsigned int what)
static void trx_ctrl_timer_cb(void *data); static void trx_ctrl_timer_cb(void *data);
/* send first ctrl message and start timer */ /* send first ctrl message and start timer */
static void trx_ctrl_send(struct trx_l1h *l1h) static void trx_ctrl_send(struct gsm_bts *bts)
{ {
struct trx_ctrl_msg *tcm; struct trx_ctrl_msg *tcm;
struct gsm_bts_trx *trx;
struct trx_l1h *l1h;
/* get first command */ /* get first command */
if (llist_empty(&l1h->trx_ctrl_list)) if (llist_empty(&trx_ctrl_list))
return; return;
tcm = llist_entry(l1h->trx_ctrl_list.next, struct trx_ctrl_msg, list); tcm = llist_entry(trx_ctrl_list.next, struct trx_ctrl_msg, list);
LOGP(DTRX, LOGL_DEBUG, "Sending control '%s' to trx=%u\n", tcm->cmd, LOGP(DTRX, LOGL_DEBUG, "Sending control '%s' to trx=%u\n", tcm->cmd,
l1h->trx->nr); tcm->trx_num);
/* send command */ /* send command */
trx = gsm_bts_trx_num(bts, tcm->trx_num);
l1h = trx_l1h_hdl(trx);
send(l1h->trx_ofd_ctrl.fd, tcm->cmd, strlen(tcm->cmd)+1, 0); send(l1h->trx_ofd_ctrl.fd, tcm->cmd, strlen(tcm->cmd)+1, 0);
/* start timer */ /* start timer */
l1h->trx_ctrl_timer.cb = trx_ctrl_timer_cb; trx_ctrl_timer.cb = trx_ctrl_timer_cb;
l1h->trx_ctrl_timer.data = l1h; trx_ctrl_timer.data = trx;
osmo_timer_schedule(&l1h->trx_ctrl_timer, 2, 0); osmo_timer_schedule(&trx_ctrl_timer, 2, 0);
} }
/* send first ctrl message and start timer */ /* send first ctrl message and start timer */
static void trx_ctrl_timer_cb(void *data) static void trx_ctrl_timer_cb(void *data)
{ {
struct trx_l1h *l1h = data; struct gsm_bts_trx *trx = data;
LOGP(DTRX, LOGL_NOTICE, "No response from transceiver for trx=%d\n", LOGP(DTRX, LOGL_NOTICE, "No response from transceiver for trx=%d\n",
l1h->trx->nr); trx->nr);
trx_ctrl_send(l1h); trx_ctrl_send(trx->bts);
} }
/* add a new ctrl command */ /* add a new ctrl command */
@ -203,11 +211,12 @@ static int trx_ctrl_cmd(struct trx_l1h *l1h, int critical, const char *cmd,
return -EIO; return -EIO;
} }
if (!llist_empty(&l1h->trx_ctrl_list)) if (!llist_empty(&trx_ctrl_list))
pending = 1; pending = 1;
/* create message */ /* create message */
tcm = talloc_zero(tall_bts_ctx, struct trx_ctrl_msg); tcm = talloc_zero(tall_bts_ctx, struct trx_ctrl_msg);
tcm->trx_num = l1h->trx->nr;
if (!tcm) if (!tcm)
return -ENOMEM; return -ENOMEM;
if (fmt && fmt[0]) { if (fmt && fmt[0]) {
@ -219,12 +228,12 @@ static int trx_ctrl_cmd(struct trx_l1h *l1h, int critical, const char *cmd,
snprintf(tcm->cmd, sizeof(tcm->cmd)-1, "CMD %s", cmd); snprintf(tcm->cmd, sizeof(tcm->cmd)-1, "CMD %s", cmd);
tcm->cmd_len = strlen(cmd); tcm->cmd_len = strlen(cmd);
tcm->critical = critical; tcm->critical = critical;
llist_add_tail(&tcm->list, &l1h->trx_ctrl_list); llist_add_tail(&tcm->list, &trx_ctrl_list);
LOGP(DTRX, LOGL_INFO, "Adding new control '%s'\n", tcm->cmd); LOGP(DTRX, LOGL_INFO, "Adding new control '%s'\n", tcm->cmd);
/* send message, if no pending message */ /* send this message, if there are no other pending messages */
if (!pending) if (!pending)
trx_ctrl_send(l1h); trx_ctrl_send(l1h->trx->bts);
return 0; return 0;
} }
@ -319,12 +328,46 @@ int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss)
return trx_ctrl_cmd(l1h, 1, "NOHANDOVER", "%d %d", tn, ss); return trx_ctrl_cmd(l1h, 1, "NOHANDOVER", "%d %d", tn, ss);
} }
static int check_resp(char *buf, struct trx_ctrl_msg *tcm, struct trx_l1h *l1h)
{
char *p;
int rsp_len = 0;
int resp;
/* calculate the length of response item */
p = strchr(buf + 4, ' ');
if (p)
rsp_len = p - buf - 4;
else
rsp_len = strlen(buf) - 4;
/* check if respose matches command */
if (rsp_len != tcm->cmd_len
|| !!strncmp(buf + 4, tcm->cmd + 4, rsp_len)) {
LOGP(DTRX, (tcm->critical) ? LOGL_FATAL : LOGL_NOTICE,
"Response message '%s' does not match command "
"message '%s'\n", buf, tcm->cmd);
return -EIO;
}
/* check for response code */
sscanf(p + 1, "%d", &resp);
if (resp) {
LOGP(DTRX, (tcm->critical) ? LOGL_FATAL : LOGL_NOTICE,
"transceiver (trx=%d) rejected TRX command "
"with response: '%s'\n", l1h->trx->nr, buf);
return -EIO;
}
return 0;
}
/* get response from ctrl socket */ /* get response from ctrl socket */
static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what) static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what)
{ {
struct trx_l1h *l1h = ofd->data; struct trx_l1h *l1h = ofd->data;
char buf[1500]; char buf[1500];
int len, resp; int len;
len = recv(ofd->fd, buf, sizeof(buf) - 1, 0); len = recv(ofd->fd, buf, sizeof(buf) - 1, 0);
if (len <= 0) if (len <= 0)
@ -333,49 +376,23 @@ static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what)
if (!strncmp(buf, "RSP ", 4)) { if (!strncmp(buf, "RSP ", 4)) {
struct trx_ctrl_msg *tcm; struct trx_ctrl_msg *tcm;
char *p;
int rsp_len = 0;
/* calculate the length of response item */
p = strchr(buf + 4, ' ');
if (p)
rsp_len = p - buf - 4;
else
rsp_len = strlen(buf) - 4;
LOGP(DTRX, LOGL_INFO, "Response message: '%s'\n", buf); LOGP(DTRX, LOGL_INFO, "Response message: '%s'\n", buf);
/* abort timer and send next message, if any */ /* abort timer */
if (osmo_timer_pending(&l1h->trx_ctrl_timer)) if (osmo_timer_pending(&trx_ctrl_timer))
osmo_timer_del(&l1h->trx_ctrl_timer); osmo_timer_del(&trx_ctrl_timer);
/* get command for response message */ /* get command for response message */
if (llist_empty(&l1h->trx_ctrl_list)) { if (llist_empty(&trx_ctrl_list)) {
LOGP(DTRX, LOGL_NOTICE, "Response message without " LOGP(DTRX, LOGL_NOTICE, "Response message without "
"command\n"); "command\n");
return -EINVAL; return -EINVAL;
} }
tcm = llist_entry(l1h->trx_ctrl_list.next, struct trx_ctrl_msg, tcm = llist_entry(trx_ctrl_list.next, struct trx_ctrl_msg, list);
list);
/* check if respose matches command */ /* check if respose matches command and it's a success response */
if (rsp_len != tcm->cmd_len) { if (check_resp(buf, tcm, l1h) < 0) {
notmatch:
LOGP(DTRX, (tcm->critical) ? LOGL_FATAL : LOGL_NOTICE,
"Response message '%s' does not match command "
"message '%s'\n", buf, tcm->cmd);
goto rsp_error;
}
if (!!strncmp(buf + 4, tcm->cmd + 4, rsp_len))
goto notmatch;
/* check for response code */
sscanf(p + 1, "%d", &resp);
if (resp) {
LOGP(DTRX, (tcm->critical) ? LOGL_FATAL : LOGL_NOTICE,
"transceiver (trx=%d) rejected TRX command "
"with response: '%s'\n", l1h->trx->nr, buf);
rsp_error:
if (tcm->critical) { if (tcm->critical) {
bts_shutdown(l1h->trx->bts, "SIGINT"); bts_shutdown(l1h->trx->bts, "SIGINT");
/* keep tcm list, so process is stopped */ /* keep tcm list, so process is stopped */
@ -387,7 +404,8 @@ rsp_error:
llist_del(&tcm->list); llist_del(&tcm->list);
talloc_free(tcm); talloc_free(tcm);
trx_ctrl_send(l1h); /* send next command */
trx_ctrl_send(l1h->trx->bts);
} else } else
LOGP(DTRX, LOGL_NOTICE, "Unknown message on ctrl port: %s\n", LOGP(DTRX, LOGL_NOTICE, "Unknown message on ctrl port: %s\n",
buf); buf);
@ -478,7 +496,7 @@ int trx_if_data(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr,
/* we must be sure that we have clock, and we have sent all control /* we must be sure that we have clock, and we have sent all control
* data */ * data */
if (transceiver_available && llist_empty(&l1h->trx_ctrl_list)) { if (transceiver_available && llist_empty(&trx_ctrl_list)) {
send(l1h->trx_ofd_data.fd, buf, 154, 0); send(l1h->trx_ofd_data.fd, buf, 154, 0);
} else } else
LOGP(DTRX, LOGL_DEBUG, "Ignoring TX data, transceiver " LOGP(DTRX, LOGL_DEBUG, "Ignoring TX data, transceiver "
@ -499,7 +517,8 @@ int trx_if_open(struct trx_l1h *l1h)
LOGP(DTRX, LOGL_NOTICE, "Open transceiver for trx=%u\n", l1h->trx->nr); LOGP(DTRX, LOGL_NOTICE, "Open transceiver for trx=%u\n", l1h->trx->nr);
/* initialize ctrl queue */ /* initialize ctrl queue */
INIT_LLIST_HEAD(&l1h->trx_ctrl_list); if (l1h->trx->nr == 0)
INIT_LLIST_HEAD(&trx_ctrl_list);
/* open sockets */ /* open sockets */
if (l1h->trx->nr == 0) { if (l1h->trx->nr == 0) {
@ -537,8 +556,8 @@ void trx_if_flush(struct trx_l1h *l1h)
struct trx_ctrl_msg *tcm; struct trx_ctrl_msg *tcm;
/* free ctrl message list */ /* free ctrl message list */
while (!llist_empty(&l1h->trx_ctrl_list)) { while (!llist_empty(&trx_ctrl_list)) {
tcm = llist_entry(l1h->trx_ctrl_list.next, struct trx_ctrl_msg, tcm = llist_entry(trx_ctrl_list.next, struct trx_ctrl_msg,
list); list);
llist_del(&tcm->list); llist_del(&tcm->list);
talloc_free(tcm); talloc_free(tcm);

View File

@ -9,6 +9,7 @@ extern int setbsic_enabled;
struct trx_ctrl_msg { struct trx_ctrl_msg {
struct llist_head list; struct llist_head list;
int trx_num;
char cmd[128]; char cmd[128];
int cmd_len; int cmd_len;
int critical; int critical;