fixeria submitted this change.
trxcon: rework L1CTL socket API to support multiple clients
Change-Id: I1cfc49f36ead6e2ba0a6110b0fb65c55412ef5e3
---
M src/host/trxcon/include/osmocom/bb/trxcon/l1ctl.h
M src/host/trxcon/include/osmocom/bb/trxcon/l1ctl_link.h
M src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h
M src/host/trxcon/src/l1ctl.c
M src/host/trxcon/src/l1ctl_link.c
M src/host/trxcon/src/trx_if.c
M src/host/trxcon/src/trxcon.c
7 files changed, 272 insertions(+), 270 deletions(-)
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl.h b/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl.h
index 4d1670e..348e5c5 100644
--- a/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl.h
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl.h
@@ -7,21 +7,21 @@
#include <osmocom/bb/trxcon/l1ctl_proto.h>
/* Event handlers */
-int l1ctl_rx_cb(struct l1ctl_link *l1l, struct msgb *msg);
+int l1ctl_rx_cb(struct l1ctl_client *l1c, struct msgb *msg);
-int l1ctl_tx_fbsb_conf(struct l1ctl_link *l1l, uint8_t result,
+int l1ctl_tx_fbsb_conf(struct l1ctl_client *l1c, uint8_t result,
const struct l1ctl_info_dl *dl_info, uint8_t bsic);
-int l1ctl_tx_ccch_mode_conf(struct l1ctl_link *l1l, uint8_t mode);
-int l1ctl_tx_pm_conf(struct l1ctl_link *l1l, uint16_t band_arfcn,
+int l1ctl_tx_ccch_mode_conf(struct l1ctl_client *l1c, uint8_t mode);
+int l1ctl_tx_pm_conf(struct l1ctl_client *l1c, uint16_t band_arfcn,
int dbm, int last);
-int l1ctl_tx_reset_conf(struct l1ctl_link *l1l, uint8_t type);
-int l1ctl_tx_reset_ind(struct l1ctl_link *l1l, uint8_t type);
+int l1ctl_tx_reset_conf(struct l1ctl_client *l1c, uint8_t type);
+int l1ctl_tx_reset_ind(struct l1ctl_client *l1c, uint8_t type);
-int l1ctl_tx_dt_ind(struct l1ctl_link *l1l,
+int l1ctl_tx_dt_ind(struct l1ctl_client *l1c,
const struct l1ctl_info_dl *dl_info,
const uint8_t *l2, size_t l2_len,
bool traffic);
-int l1ctl_tx_dt_conf(struct l1ctl_link *l1l,
+int l1ctl_tx_dt_conf(struct l1ctl_client *l1c,
struct l1ctl_info_dl *data, bool traffic);
-int l1ctl_tx_rach_conf(struct l1ctl_link *l1l,
+int l1ctl_tx_rach_conf(struct l1ctl_client *l1c,
uint16_t band_arfcn, uint32_t fn);
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl_link.h b/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl_link.h
index 84a8638..84420f2 100644
--- a/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl_link.h
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/l1ctl_link.h
@@ -6,7 +6,6 @@
#include <osmocom/core/select.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/msgb.h>
-#include <osmocom/core/fsm.h>
#define L1CTL_LENGTH 256
#define L1CTL_HEADROOM 32
@@ -17,22 +16,49 @@
*/
#define L1CTL_MSG_LEN_FIELD 2
-enum l1ctl_fsm_states {
- L1CTL_STATE_IDLE = 0,
- L1CTL_STATE_CONNECTED,
+struct l1ctl_client;
+
+typedef int l1ctl_conn_data_func(struct l1ctl_client *, struct msgb *);
+typedef void l1ctl_conn_state_func(struct l1ctl_client *);
+
+struct l1ctl_server_cfg {
+ /* UNIX socket path to listen on */
+ const char *sock_path;
+ /* talloc context to be used for new clients */
+ void *talloc_ctx;
+ /* maximum number of connected clients */
+ unsigned int num_clients_max;
+ /* functions to be called on various events */
+ l1ctl_conn_data_func *conn_read_cb; /* mandatory */
+ l1ctl_conn_state_func *conn_accept_cb; /* optional */
+ l1ctl_conn_state_func *conn_close_cb; /* optional */
};
-struct l1ctl_link {
- struct osmo_fsm_inst *fsm;
- struct osmo_fd listen_bfd;
- struct osmo_wqueue wq;
+struct l1ctl_server {
+ /* list of connected clients */
+ struct llist_head clients;
+ /* number of connected clients */
+ unsigned int num_clients;
+ /* socket on which we listen for connections */
+ struct osmo_fd ofd;
+ /* server configuration */
+ const struct l1ctl_server_cfg *cfg;
+};
- /* Some private data */
+struct l1ctl_client {
+ /* list head in l1ctl_server.clients */
+ struct llist_head list;
+ /* struct l1ctl_server we belong to */
+ struct l1ctl_server *server;
+ /* client's write queue */
+ struct osmo_wqueue wq;
+ /* some private data */
void *priv;
};
-struct l1ctl_link *l1ctl_link_init(void *tall_ctx, const char *sock_path);
-void l1ctl_link_shutdown(struct l1ctl_link *l1l);
+int l1ctl_server_start(struct l1ctl_server *server,
+ const struct l1ctl_server_cfg *cfg);
+void l1ctl_server_shutdown(struct l1ctl_server *server);
-int l1ctl_link_send(struct l1ctl_link *l1l, struct msgb *msg);
-int l1ctl_link_close_conn(struct l1ctl_link *l1l);
+int l1ctl_client_send(struct l1ctl_client *client, struct msgb *msg);
+void l1ctl_client_conn_close(struct l1ctl_client *client);
diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h
index 986f423..2a068b7 100644
--- a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h
+++ b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h
@@ -4,7 +4,7 @@
struct l1sched_state;
struct trx_instance;
-struct l1ctl_link;
+struct l1ctl_client;
enum trxcon_fsm_states {
TRXCON_STATE_IDLE = 0,
@@ -28,7 +28,7 @@
struct l1sched_state *sched;
/* L1/L2 interfaces */
struct trx_instance *trx;
- struct l1ctl_link *l1l;
+ struct l1ctl_client *l1c;
/* TODO: implement this as an FSM state with timeout */
struct osmo_timer_list fbsb_timer;
diff --git a/src/host/trxcon/src/l1ctl.c b/src/host/trxcon/src/l1ctl.c
index 9d762d3..ddcc953 100644
--- a/src/host/trxcon/src/l1ctl.c
+++ b/src/host/trxcon/src/l1ctl.c
@@ -77,7 +77,7 @@
return msg;
}
-int l1ctl_tx_pm_conf(struct l1ctl_link *l1l, uint16_t band_arfcn,
+int l1ctl_tx_pm_conf(struct l1ctl_client *l1c, uint16_t band_arfcn,
int dbm, int last)
{
struct l1ctl_pm_conf *pmc;
@@ -101,10 +101,10 @@
l1h->flags |= L1CTL_F_DONE;
}
- return l1ctl_link_send(l1l, msg);
+ return l1ctl_client_send(l1c, msg);
}
-int l1ctl_tx_reset_ind(struct l1ctl_link *l1l, uint8_t type)
+int l1ctl_tx_reset_ind(struct l1ctl_client *l1c, uint8_t type)
{
struct msgb *msg;
struct l1ctl_reset *res;
@@ -118,10 +118,10 @@
res = (struct l1ctl_reset *) msgb_put(msg, sizeof(*res));
res->type = type;
- return l1ctl_link_send(l1l, msg);
+ return l1ctl_client_send(l1c, msg);
}
-int l1ctl_tx_reset_conf(struct l1ctl_link *l1l, uint8_t type)
+int l1ctl_tx_reset_conf(struct l1ctl_client *l1c, uint8_t type)
{
struct msgb *msg;
struct l1ctl_reset *res;
@@ -134,7 +134,7 @@
res = (struct l1ctl_reset *) msgb_put(msg, sizeof(*res));
res->type = type;
- return l1ctl_link_send(l1l, msg);
+ return l1ctl_client_send(l1c, msg);
}
static struct l1ctl_info_dl *put_dl_info_hdr(struct msgb *msg,
@@ -164,10 +164,10 @@
return conf;
}
-int l1ctl_tx_fbsb_conf(struct l1ctl_link *l1l, uint8_t result,
+int l1ctl_tx_fbsb_conf(struct l1ctl_client *l1c, uint8_t result,
const struct l1ctl_info_dl *dl_info, uint8_t bsic)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
struct l1ctl_fbsb_conf *conf;
struct msgb *msg;
@@ -189,10 +189,10 @@
if (osmo_timer_pending(&trxcon->fbsb_timer))
osmo_timer_del(&trxcon->fbsb_timer);
- return l1ctl_link_send(l1l, msg);
+ return l1ctl_client_send(l1c, msg);
}
-int l1ctl_tx_ccch_mode_conf(struct l1ctl_link *l1l, uint8_t mode)
+int l1ctl_tx_ccch_mode_conf(struct l1ctl_client *l1c, uint8_t mode)
{
struct l1ctl_ccch_mode_conf *conf;
struct msgb *msg;
@@ -204,13 +204,13 @@
conf = (struct l1ctl_ccch_mode_conf *) msgb_put(msg, sizeof(*conf));
conf->ccch_mode = mode;
- return l1ctl_link_send(l1l, msg);
+ return l1ctl_client_send(l1c, msg);
}
/**
* Handles both L1CTL_DATA_IND and L1CTL_TRAFFIC_IND.
*/
-int l1ctl_tx_dt_ind(struct l1ctl_link *l1l,
+int l1ctl_tx_dt_ind(struct l1ctl_client *l1c,
const struct l1ctl_info_dl *dl_info,
const uint8_t *l2, size_t l2_len,
bool traffic)
@@ -232,10 +232,10 @@
}
/* Put message to upper layers */
- return l1ctl_link_send(l1l, msg);
+ return l1ctl_client_send(l1c, msg);
}
-int l1ctl_tx_rach_conf(struct l1ctl_link *l1l,
+int l1ctl_tx_rach_conf(struct l1ctl_client *l1c,
uint16_t band_arfcn, uint32_t fn)
{
struct l1ctl_info_dl *dl;
@@ -251,14 +251,14 @@
dl->band_arfcn = htons(band_arfcn);
dl->frame_nr = htonl(fn);
- return l1ctl_link_send(l1l, msg);
+ return l1ctl_client_send(l1c, msg);
}
/**
* Handles both L1CTL_DATA_CONF and L1CTL_TRAFFIC_CONF.
*/
-int l1ctl_tx_dt_conf(struct l1ctl_link *l1l,
+int l1ctl_tx_dt_conf(struct l1ctl_client *l1c,
struct l1ctl_info_dl *data, bool traffic)
{
struct msgb *msg;
@@ -271,7 +271,7 @@
/* Copy DL frame header from source message */
put_dl_info_hdr(msg, data);
- return l1ctl_link_send(l1l, msg);
+ return l1ctl_client_send(l1c, msg);
}
static enum gsm_phys_chan_config l1ctl_ccch_mode2pchan_config(enum ccch_mode mode)
@@ -297,8 +297,8 @@
/* FBSB expire timer */
static void fbsb_timer_cb(void *data)
{
- struct l1ctl_link *l1l = (struct l1ctl_link *) data;
- struct trxcon_inst *trxcon = l1l->priv;
+ struct l1ctl_client *l1c = (struct l1ctl_client *) data;
+ struct trxcon_inst *trxcon = l1c->priv;
struct l1ctl_info_dl *dl;
struct msgb *msg;
@@ -319,12 +319,12 @@
/* Ask SCH handler not to send L1CTL_FBSB_CONF anymore */
trxcon->fbsb_conf_sent = true;
- l1ctl_link_send(l1l, msg);
+ l1ctl_client_send(l1c, msg);
}
-static int l1ctl_rx_fbsb_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_fbsb_req(struct l1ctl_client *l1c, struct msgb *msg)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
enum gsm_phys_chan_config ch_config;
struct l1ctl_fbsb_req *fbsb;
uint16_t band_arfcn;
@@ -372,7 +372,7 @@
trx_if_cmd_poweron(trxcon->trx);
/* Start FBSB expire timer */
- trxcon->fbsb_timer.data = l1l;
+ trxcon->fbsb_timer.data = l1c;
trxcon->fbsb_timer.cb = fbsb_timer_cb;
LOGP(DL1C, LOGL_INFO, "Starting FBSB timer %u ms\n", timeout * GSM_TDMA_FN_DURATION_uS / 1000);
osmo_timer_schedule(&trxcon->fbsb_timer, 0,
@@ -383,10 +383,10 @@
return rc;
}
-static int l1ctl_rx_pm_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_pm_req(struct l1ctl_client *l1c, struct msgb *msg)
{
uint16_t band_arfcn_start, band_arfcn_stop;
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
struct l1ctl_pm_req *pmr;
int rc = 0;
@@ -415,9 +415,9 @@
return rc;
}
-static int l1ctl_rx_reset_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_reset_req(struct l1ctl_client *l1c, struct msgb *msg)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
struct l1ctl_reset *res;
int rc = 0;
@@ -448,14 +448,14 @@
}
/* Confirm */
- rc = l1ctl_tx_reset_conf(l1l, res->type);
+ rc = l1ctl_tx_reset_conf(l1c, res->type);
exit:
msgb_free(msg);
return rc;
}
-static int l1ctl_rx_echo_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_echo_req(struct l1ctl_client *l1c, struct msgb *msg)
{
struct l1ctl_hdr *l1h;
@@ -467,12 +467,12 @@
l1h->msg_type = L1CTL_ECHO_CONF;
msg->data = msg->l1h;
- return l1ctl_link_send(l1l, msg);
+ return l1ctl_client_send(l1c, msg);
}
-static int l1ctl_rx_ccch_mode_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_ccch_mode_req(struct l1ctl_client *l1c, struct msgb *msg)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
enum gsm_phys_chan_config ch_config;
struct l1ctl_ccch_mode_req *req;
struct l1sched_ts *ts;
@@ -506,16 +506,16 @@
/* Confirm reconfiguration */
if (!rc)
- rc = l1ctl_tx_ccch_mode_conf(l1l, req->ccch_mode);
+ rc = l1ctl_tx_ccch_mode_conf(l1c, req->ccch_mode);
exit:
msgb_free(msg);
return rc;
}
-static int l1ctl_rx_rach_req(struct l1ctl_link *l1l, struct msgb *msg, bool ext)
+static int l1ctl_rx_rach_req(struct l1ctl_client *l1c, struct msgb *msg, bool ext)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
struct l1ctl_info_ul *ul;
struct l1sched_ts_prim *prim;
struct l1sched_ts_prim_rach rach;
@@ -631,9 +631,9 @@
return 0;
}
-static int l1ctl_rx_dm_est_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_dm_est_req(struct l1ctl_client *l1c, struct msgb *msg)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
enum gsm_phys_chan_config config;
struct l1ctl_dm_est_req *est_req;
struct l1ctl_info_ul *ul;
@@ -691,9 +691,9 @@
return rc;
}
-static int l1ctl_rx_dm_rel_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_dm_rel_req(struct l1ctl_client *l1c, struct msgb *msg)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
LOGP(DL1C, LOGL_NOTICE, "Received L1CTL_DM_REL_REQ, resetting scheduler\n");
@@ -707,10 +707,10 @@
/**
* Handles both L1CTL_DATA_REQ and L1CTL_TRAFFIC_REQ.
*/
-static int l1ctl_rx_dt_req(struct l1ctl_link *l1l,
+static int l1ctl_rx_dt_req(struct l1ctl_client *l1c,
struct msgb *msg, bool traffic)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
struct l1ctl_info_ul *ul;
struct l1sched_ts_prim *prim;
uint8_t chan_nr, link_id;
@@ -742,9 +742,9 @@
return rc;
}
-static int l1ctl_rx_param_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_param_req(struct l1ctl_client *l1c, struct msgb *msg)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
struct l1ctl_par_req *par_req;
struct l1ctl_info_ul *ul;
@@ -766,9 +766,9 @@
return 0;
}
-static int l1ctl_rx_tch_mode_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_tch_mode_req(struct l1ctl_client *l1c, struct msgb *msg)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
struct l1ctl_tch_mode_req *req;
struct l1sched_lchan_state *lchan;
struct l1sched_ts *ts;
@@ -807,12 +807,12 @@
struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
l1h->msg_type = L1CTL_TCH_MODE_CONF;
- return l1ctl_link_send(l1l, msg);
+ return l1ctl_client_send(l1c, msg);
}
-static int l1ctl_rx_crypto_req(struct l1ctl_link *l1l, struct msgb *msg)
+static int l1ctl_rx_crypto_req(struct l1ctl_client *l1c, struct msgb *msg)
{
- struct trxcon_inst *trxcon = l1l->priv;
+ struct trxcon_inst *trxcon = l1c->priv;
struct l1ctl_crypto_req *req;
struct l1ctl_info_ul *ul;
struct l1sched_ts *ts;
@@ -849,7 +849,7 @@
return rc;
}
-int l1ctl_rx_cb(struct l1ctl_link *l1l, struct msgb *msg)
+int l1ctl_rx_cb(struct l1ctl_client *l1c, struct msgb *msg)
{
struct l1ctl_hdr *l1h;
@@ -858,33 +858,33 @@
switch (l1h->msg_type) {
case L1CTL_FBSB_REQ:
- return l1ctl_rx_fbsb_req(l1l, msg);
+ return l1ctl_rx_fbsb_req(l1c, msg);
case L1CTL_PM_REQ:
- return l1ctl_rx_pm_req(l1l, msg);
+ return l1ctl_rx_pm_req(l1c, msg);
case L1CTL_RESET_REQ:
- return l1ctl_rx_reset_req(l1l, msg);
+ return l1ctl_rx_reset_req(l1c, msg);
case L1CTL_ECHO_REQ:
- return l1ctl_rx_echo_req(l1l, msg);
+ return l1ctl_rx_echo_req(l1c, msg);
case L1CTL_CCCH_MODE_REQ:
- return l1ctl_rx_ccch_mode_req(l1l, msg);
+ return l1ctl_rx_ccch_mode_req(l1c, msg);
case L1CTL_RACH_REQ:
- return l1ctl_rx_rach_req(l1l, msg, false);
+ return l1ctl_rx_rach_req(l1c, msg, false);
case L1CTL_EXT_RACH_REQ:
- return l1ctl_rx_rach_req(l1l, msg, true);
+ return l1ctl_rx_rach_req(l1c, msg, true);
case L1CTL_DM_EST_REQ:
- return l1ctl_rx_dm_est_req(l1l, msg);
+ return l1ctl_rx_dm_est_req(l1c, msg);
case L1CTL_DM_REL_REQ:
- return l1ctl_rx_dm_rel_req(l1l, msg);
+ return l1ctl_rx_dm_rel_req(l1c, msg);
case L1CTL_DATA_REQ:
- return l1ctl_rx_dt_req(l1l, msg, false);
+ return l1ctl_rx_dt_req(l1c, msg, false);
case L1CTL_TRAFFIC_REQ:
- return l1ctl_rx_dt_req(l1l, msg, true);
+ return l1ctl_rx_dt_req(l1c, msg, true);
case L1CTL_PARAM_REQ:
- return l1ctl_rx_param_req(l1l, msg);
+ return l1ctl_rx_param_req(l1c, msg);
case L1CTL_TCH_MODE_REQ:
- return l1ctl_rx_tch_mode_req(l1l, msg);
+ return l1ctl_rx_tch_mode_req(l1c, msg);
case L1CTL_CRYPTO_REQ:
- return l1ctl_rx_crypto_req(l1l, msg);
+ return l1ctl_rx_crypto_req(l1c, msg);
/* Not (yet) handled messages */
case L1CTL_NEIGH_PM_REQ:
diff --git a/src/host/trxcon/src/l1ctl_link.c b/src/host/trxcon/src/l1ctl_link.c
index 672991c..93ee6cb 100644
--- a/src/host/trxcon/src/l1ctl_link.c
+++ b/src/host/trxcon/src/l1ctl_link.c
@@ -1,9 +1,10 @@
/*
* OsmocomBB <-> SDR connection bridge
- * GSM L1 control socket (/tmp/osmocom_l2) handlers
+ * UNIX socket server for L1CTL
*
* (C) 2013 by Sylvain Munaut <tnt@246tNt.com>
* (C) 2016-2017 by Vadim Yanitskiy <axilirator@gmail.com>
+ * (C) 2022 by by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
@@ -24,60 +25,33 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/socket.h>
-#include <osmocom/core/fsm.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/select.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/write_queue.h>
-#include <osmocom/bb/trxcon/trxcon.h>
#include <osmocom/bb/trxcon/logging.h>
#include <osmocom/bb/trxcon/l1ctl_link.h>
-#include <osmocom/bb/trxcon/l1ctl.h>
-static struct value_string l1ctl_evt_names[] = {
- { 0, NULL } /* no events? */
-};
-
-static struct osmo_fsm_state l1ctl_fsm_states[] = {
- [L1CTL_STATE_IDLE] = {
- .out_state_mask = GEN_MASK(L1CTL_STATE_CONNECTED),
- .name = "IDLE",
- },
- [L1CTL_STATE_CONNECTED] = {
- .out_state_mask = GEN_MASK(L1CTL_STATE_IDLE),
- .name = "CONNECTED",
- },
-};
-
-static struct osmo_fsm l1ctl_fsm = {
- .name = "l1ctl_link_fsm",
- .states = l1ctl_fsm_states,
- .num_states = ARRAY_SIZE(l1ctl_fsm_states),
- .log_subsys = DL1C,
- .event_names = l1ctl_evt_names,
-};
-
-static int l1ctl_link_read_cb(struct osmo_fd *bfd)
+static int l1ctl_client_read_cb(struct osmo_fd *ofd)
{
- struct l1ctl_link *l1l = (struct l1ctl_link *) bfd->data;
+ struct l1ctl_client *client = (struct l1ctl_client *)ofd->data;
struct msgb *msg;
uint16_t len;
int rc;
/* Attempt to read from socket */
- rc = read(bfd->fd, &len, L1CTL_MSG_LEN_FIELD);
+ rc = read(ofd->fd, &len, L1CTL_MSG_LEN_FIELD);
if (rc < L1CTL_MSG_LEN_FIELD) {
- LOGP(DL1D, LOGL_NOTICE, "L1CTL has lost connection\n");
+ LOGP(DL1D, LOGL_NOTICE, "L1CTL server has lost connection\n");
if (rc >= 0)
rc = -EIO;
- l1ctl_link_close_conn(l1l);
+ l1ctl_client_conn_close(client);
return rc;
}
@@ -97,7 +71,7 @@
}
msg->l1h = msgb_put(msg, len);
- rc = read(bfd->fd, msg->l1h, msgb_l1len(msg));
+ rc = read(ofd->fd, msg->l1h, msgb_l1len(msg));
if (rc != len) {
LOGP(DL1D, LOGL_ERROR, "Can not read data: len=%d < rc=%d: "
"%s\n", len, rc, strerror(errno));
@@ -110,19 +84,19 @@
osmo_hexdump(msg->data, msg->len));
/* Call L1CTL handler */
- l1ctl_rx_cb(l1l, msg);
+ client->server->cfg->conn_read_cb(client, msg);
return 0;
}
-static int l1ctl_link_write_cb(struct osmo_fd *bfd, struct msgb *msg)
+static int l1ctl_client_write_cb(struct osmo_fd *ofd, struct msgb *msg)
{
int len;
- if (bfd->fd <= 0)
+ if (ofd->fd <= 0)
return -EINVAL;
- len = write(bfd->fd, msg->data, msg->len);
+ len = write(ofd->fd, msg->data, msg->len);
if (len != msg->len) {
LOGP(DL1D, LOGL_ERROR, "Failed to write data: "
"written (%d) < msg_len (%d)\n", len, msg->len);
@@ -133,53 +107,64 @@
}
/* Connection handler */
-static int l1ctl_link_accept(struct osmo_fd *bfd, unsigned int flags)
+static int l1ctl_server_conn_cb(struct osmo_fd *sfd, unsigned int flags)
{
- struct l1ctl_link *l1l = (struct l1ctl_link *) bfd->data;
- struct trxcon_inst *trxcon = l1l->priv;
- struct osmo_fd *conn_bfd = &l1l->wq.bfd;
- struct sockaddr_un un_addr;
- socklen_t len;
- int cfd;
+ struct l1ctl_server *server = (struct l1ctl_server *)sfd->data;
+ struct l1ctl_client *client;
+ int rc, client_fd;
- len = sizeof(un_addr);
- cfd = accept(bfd->fd, (struct sockaddr *) &un_addr, &len);
- if (cfd < 0) {
- LOGP(DL1C, LOGL_ERROR, "Failed to accept a new connection\n");
- return -1;
+ client_fd = accept(sfd->fd, NULL, NULL);
+ if (client_fd < 0) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to accept() a new connection: "
+ "%s\n", strerror(errno));
+ return client_fd;
}
- /* Check if we already have an active connection */
- if (conn_bfd->fd != -1) {
- LOGP(DL1C, LOGL_NOTICE, "A new connection rejected: "
- "we already have another active\n");
- close(cfd);
- return 0;
+ if (server->cfg->num_clients_max > 0 /* 0 means unlimited */ &&
+ server->num_clients >= server->cfg->num_clients_max) {
+ LOGP(DL1C, LOGL_NOTICE, "L1CTL server cannot accept more "
+ "than %u connection(s)\n", server->cfg->num_clients_max);
+ close(client_fd);
+ return -ENOMEM;
}
- osmo_wqueue_init(&l1l->wq, 100);
- INIT_LLIST_HEAD(&conn_bfd->list);
-
- l1l->wq.write_cb = l1ctl_link_write_cb;
- l1l->wq.read_cb = l1ctl_link_read_cb;
- osmo_fd_setup(conn_bfd, cfd, OSMO_FD_READ, osmo_wqueue_bfd_cb, l1l, 0);
-
- if (osmo_fd_register(conn_bfd) != 0) {
- LOGP(DL1C, LOGL_ERROR, "Failed to register new connection fd\n");
- close(conn_bfd->fd);
- conn_bfd->fd = -1;
- return -1;
+ client = talloc_zero(server->cfg->talloc_ctx, struct l1ctl_client);
+ if (client == NULL) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to allocate an L1CTL client\n");
+ close(client_fd);
+ return -ENOMEM;
}
- osmo_fsm_inst_dispatch(trxcon->fi, L1CTL_EVENT_CONNECT, l1l);
- osmo_fsm_inst_state_chg(l1l->fsm, L1CTL_STATE_CONNECTED, 0, 0);
+ /* Init the client's write queue */
+ osmo_wqueue_init(&client->wq, 100);
+ INIT_LLIST_HEAD(&client->wq.bfd.list);
- LOGP(DL1C, LOGL_NOTICE, "L1CTL has a new connection\n");
+ client->wq.write_cb = &l1ctl_client_write_cb;
+ client->wq.read_cb = &l1ctl_client_read_cb;
+ osmo_fd_setup(&client->wq.bfd, client_fd, OSMO_FD_READ, &osmo_wqueue_bfd_cb, client, 0);
+
+ /* Register the client's write queue */
+ rc = osmo_fd_register(&client->wq.bfd);
+ if (rc != 0) {
+ LOGP(DL1C, LOGL_ERROR, "Failed to register a new connection fd\n");
+ close(client->wq.bfd.fd);
+ talloc_free(client);
+ return rc;
+ }
+
+ LOGP(DL1C, LOGL_NOTICE, "L1CTL server got a new connection\n");
+
+ llist_add_tail(&client->list, &server->clients);
+ client->server = server;
+ server->num_clients++;
+
+ if (client->server->cfg->conn_accept_cb != NULL)
+ client->server->cfg->conn_accept_cb(client);
return 0;
}
-int l1ctl_link_send(struct l1ctl_link *l1l, struct msgb *msg)
+int l1ctl_client_send(struct l1ctl_client *client, struct msgb *msg)
{
uint8_t *len;
@@ -194,7 +179,7 @@
len = msgb_push(msg, L1CTL_MSG_LEN_FIELD);
osmo_store16be(msg->len - L1CTL_MSG_LEN_FIELD, len);
- if (osmo_wqueue_enqueue(&l1l->wq, msg) != 0) {
+ if (osmo_wqueue_enqueue(&client->wq, msg) != 0) {
LOGP(DL1D, LOGL_ERROR, "Failed to enqueue msg!\n");
msgb_free(msg);
return -EIO;
@@ -203,105 +188,70 @@
return 0;
}
-int l1ctl_link_close_conn(struct l1ctl_link *l1l)
+void l1ctl_client_conn_close(struct l1ctl_client *client)
{
- struct osmo_fd *conn_bfd = &l1l->wq.bfd;
- struct trxcon_inst *trxcon = l1l->priv;
-
- if (conn_bfd->fd <= 0)
- return -EINVAL;
+ if (client->server->cfg->conn_close_cb != NULL)
+ client->server->cfg->conn_close_cb(client);
/* Close connection socket */
- osmo_fd_unregister(conn_bfd);
- close(conn_bfd->fd);
- conn_bfd->fd = -1;
+ osmo_fd_unregister(&client->wq.bfd);
+ close(client->wq.bfd.fd);
+ client->wq.bfd.fd = -1;
/* Clear pending messages */
- osmo_wqueue_clear(&l1l->wq);
+ osmo_wqueue_clear(&client->wq);
- osmo_fsm_inst_dispatch(trxcon->fi, L1CTL_EVENT_DISCONNECT, l1l);
- osmo_fsm_inst_state_chg(l1l->fsm, L1CTL_STATE_IDLE, 0, 0);
+ client->server->num_clients--;
+ llist_del(&client->list);
+ talloc_free(client);
+}
+
+int l1ctl_server_start(struct l1ctl_server *server,
+ const struct l1ctl_server_cfg *cfg)
+{
+ int rc;
+
+ LOGP(DL1C, LOGL_NOTICE, "Init L1CTL server (sock_path=%s)\n", cfg->sock_path);
+
+ *server = (struct l1ctl_server) {
+ .clients = LLIST_HEAD_INIT(server->clients),
+ .cfg = cfg,
+ };
+
+ /* conn_read_cb shall not be NULL */
+ OSMO_ASSERT(cfg->conn_read_cb != NULL);
+
+ /* Bind connection handler */
+ osmo_fd_setup(&server->ofd, -1, OSMO_FD_READ, &l1ctl_server_conn_cb, server, 0);
+
+ rc = osmo_sock_unix_init_ofd(&server->ofd, SOCK_STREAM, 0,
+ cfg->sock_path, OSMO_SOCK_F_BIND);
+ if (rc < 0) {
+ LOGP(DL1C, LOGL_ERROR, "Could not create UNIX socket: %s\n",
+ strerror(errno));
+ talloc_free(server);
+ return rc;
+ }
return 0;
}
-struct l1ctl_link *l1ctl_link_init(void *tall_ctx, const char *sock_path)
+void l1ctl_server_shutdown(struct l1ctl_server *server)
{
- struct l1ctl_link *l1l;
- struct osmo_fd *bfd;
- int rc;
+ LOGP(DL1C, LOGL_NOTICE, "Shutdown L1CTL server\n");
- LOGP(DL1C, LOGL_NOTICE, "Init L1CTL link (%s)\n", sock_path);
-
- l1l = talloc_zero(tall_ctx, struct l1ctl_link);
- if (!l1l) {
- LOGP(DL1C, LOGL_ERROR, "Failed to allocate memory\n");
- return NULL;
+ /* Close all client connections */
+ while (!llist_empty(&server->clients)) {
+ struct l1ctl_client *client = llist_entry(server->clients.next,
+ struct l1ctl_client,
+ list);
+ l1ctl_client_conn_close(client);
}
- /* Allocate a new dedicated state machine */
- l1l->fsm = osmo_fsm_inst_alloc(&l1ctl_fsm, l1l,
- NULL, LOGL_DEBUG, "l1ctl_link");
- if (l1l->fsm == NULL) {
- LOGP(DTRX, LOGL_ERROR, "Failed to allocate an instance "
- "of FSM '%s'\n", l1ctl_fsm.name);
- talloc_free(l1l);
- return NULL;
- }
-
- /* Create a socket and bind handlers */
- bfd = &l1l->listen_bfd;
-
- /* Bind connection handler */
- osmo_fd_setup(bfd, -1, OSMO_FD_READ, l1ctl_link_accept, l1l, 0);
-
- rc = osmo_sock_unix_init_ofd(bfd, SOCK_STREAM, 0, sock_path,
- OSMO_SOCK_F_BIND);
- if (rc < 0) {
- LOGP(DL1C, LOGL_ERROR, "Could not create UNIX socket: %s\n",
- strerror(errno));
- osmo_fsm_inst_free(l1l->fsm);
- talloc_free(l1l);
- return NULL;
- }
-
- /**
- * To be able to accept first connection and
- * drop others, it should be set to -1
- */
- l1l->wq.bfd.fd = -1;
-
- return l1l;
-}
-
-void l1ctl_link_shutdown(struct l1ctl_link *l1l)
-{
- struct osmo_fd *listen_bfd;
-
- /* May be unallocated due to init error */
- if (!l1l)
- return;
-
- LOGP(DL1C, LOGL_NOTICE, "Shutdown L1CTL link\n");
-
- listen_bfd = &l1l->listen_bfd;
-
- /* Check if we have an established connection */
- if (l1l->wq.bfd.fd != -1)
- l1ctl_link_close_conn(l1l);
-
/* Unbind listening socket */
- if (listen_bfd->fd != -1) {
- osmo_fd_unregister(listen_bfd);
- close(listen_bfd->fd);
- listen_bfd->fd = -1;
+ if (server->ofd.fd != -1) {
+ osmo_fd_unregister(&server->ofd);
+ close(server->ofd.fd);
+ server->ofd.fd = -1;
}
-
- osmo_fsm_inst_free(l1l->fsm);
- talloc_free(l1l);
-}
-
-static __attribute__((constructor)) void on_dso_load(void)
-{
- OSMO_ASSERT(osmo_fsm_register(&l1ctl_fsm) == 0);
}
diff --git a/src/host/trxcon/src/trx_if.c b/src/host/trxcon/src/trx_if.c
index 3e1e4b1..b624962 100644
--- a/src/host/trxcon/src/trx_if.c
+++ b/src/host/trxcon/src/trx_if.c
@@ -387,7 +387,7 @@
}
/* Send L1CTL_PM_CONF */
- l1ctl_tx_pm_conf(trxcon->l1l, band_arfcn, dbm,
+ l1ctl_tx_pm_conf(trxcon->l1c, band_arfcn, dbm,
band_arfcn == trx->pm_band_arfcn_stop);
/* Schedule a next measurement */
diff --git a/src/host/trxcon/src/trxcon.c b/src/host/trxcon/src/trxcon.c
index 179594c..b78f661 100644
--- a/src/host/trxcon/src/trxcon.c
+++ b/src/host/trxcon/src/trxcon.c
@@ -157,16 +157,16 @@
switch (dt) {
case L1SCHED_DT_TRAFFIC:
case L1SCHED_DT_PACKET_DATA:
- rc = l1ctl_tx_dt_ind(trxcon->l1l, &dl_hdr, data, data_len, true);
+ rc = l1ctl_tx_dt_ind(trxcon->l1c, &dl_hdr, data, data_len, true);
break;
case L1SCHED_DT_SIGNALING:
- rc = l1ctl_tx_dt_ind(trxcon->l1l, &dl_hdr, data, data_len, false);
+ rc = l1ctl_tx_dt_ind(trxcon->l1c, &dl_hdr, data, data_len, false);
break;
case L1SCHED_DT_OTHER:
if (lchan->type == L1SCHED_SCH) {
if (trxcon->fbsb_conf_sent)
return 0;
- rc = l1ctl_tx_fbsb_conf(trxcon->l1l, 0, &dl_hdr, sched->bsic);
+ rc = l1ctl_tx_fbsb_conf(trxcon->l1c, 0, &dl_hdr, sched->bsic);
break;
}
/* fall through */
@@ -209,12 +209,12 @@
switch (dt) {
case L1SCHED_DT_TRAFFIC:
case L1SCHED_DT_PACKET_DATA:
- rc = l1ctl_tx_dt_conf(trxcon->l1l, &dl_hdr, true);
+ rc = l1ctl_tx_dt_conf(trxcon->l1c, &dl_hdr, true);
data_len = lchan->prim->payload_len;
data = lchan->prim->payload;
break;
case L1SCHED_DT_SIGNALING:
- rc = l1ctl_tx_dt_conf(trxcon->l1l, &dl_hdr, false);
+ rc = l1ctl_tx_dt_conf(trxcon->l1c, &dl_hdr, false);
data_len = lchan->prim->payload_len;
data = lchan->prim->payload;
break;
@@ -224,7 +224,7 @@
rach = (struct l1sched_ts_prim_rach *)lchan->prim->payload;
- rc = l1ctl_tx_rach_conf(trxcon->l1l, trxcon->trx->band_arfcn, fn);
+ rc = l1ctl_tx_rach_conf(trxcon->l1c, trxcon->trx->band_arfcn, fn);
if (lchan->prim->type == L1SCHED_PRIM_RACH11) {
ra_buf[0] = (uint8_t)(rach->ra >> 3);
ra_buf[1] = (uint8_t)(rach->ra & 0x07);
@@ -331,13 +331,6 @@
trxcon, LOGL_DEBUG, NULL);
OSMO_ASSERT(trxcon->fi != NULL);
- /* Init L1CTL server */
- trxcon->l1l = l1ctl_link_init(trxcon, app_data.bind_socket);
- if (trxcon->l1l == NULL) {
- trxcon_inst_free(trxcon);
- return NULL;
- }
-
/* Init transceiver interface */
trxcon->trx = trx_if_open(trxcon,
app_data.trx_bind_ip,
@@ -348,8 +341,6 @@
return NULL;
}
- trxcon->l1l->priv = trxcon;
-
/* Init scheduler */
trxcon->sched = l1sched_alloc(trxcon, app_data.trx_fn_advance, trxcon);
if (trxcon->sched == NULL) {
@@ -366,8 +357,8 @@
if (trxcon->sched != NULL)
l1sched_free(trxcon->sched);
/* Close active connections */
- if (trxcon->l1l != NULL)
- l1ctl_link_shutdown(trxcon->l1l);
+ if (trxcon->l1c != NULL)
+ l1ctl_client_conn_close(trxcon->l1c);
if (trxcon->trx != NULL)
trx_if_close(trxcon->trx);
@@ -379,6 +370,32 @@
talloc_free(trxcon);
}
+static void l1ctl_conn_accept_cb(struct l1ctl_client *l1c)
+{
+ struct trxcon_inst *trxcon;
+
+ trxcon = trxcon_inst_alloc(l1c);
+ if (trxcon == NULL) {
+ l1ctl_client_conn_close(l1c);
+ return;
+ }
+
+ l1c->priv = trxcon;
+ trxcon->l1c = l1c;
+}
+
+static void l1ctl_conn_close_cb(struct l1ctl_client *l1c)
+{
+ struct trxcon_inst *trxcon = l1c->priv;
+
+ if (trxcon == NULL)
+ return;
+
+ /* l1c is free()ed by the caller */
+ trxcon->l1c = NULL;
+ trxcon_inst_free(trxcon);
+}
+
static void print_usage(const char *app)
{
printf("Usage: %s\n", app);
@@ -489,7 +506,8 @@
int main(int argc, char **argv)
{
- struct trxcon_inst *trxcon = NULL;
+ struct l1ctl_server_cfg server_cfg;
+ struct l1ctl_server server;
int rc = 0;
printf("%s", COPYRIGHT);
@@ -535,10 +553,20 @@
/* Register the trxcon state machine */
OSMO_ASSERT(osmo_fsm_register(&trxcon_fsm_def) == 0);
- /* Allocate the trxcon instance (only one for now) */
- trxcon = trxcon_inst_alloc(tall_trxcon_ctx);
- if (trxcon == NULL)
+ /* Start the L1CTL server */
+ server_cfg = (struct l1ctl_server_cfg) {
+ .sock_path = app_data.bind_socket,
+ .talloc_ctx = tall_trxcon_ctx,
+ .num_clients_max = 1, /* only one connection for now */
+ .conn_read_cb = &l1ctl_rx_cb,
+ .conn_accept_cb = &l1ctl_conn_accept_cb,
+ .conn_close_cb = &l1ctl_conn_close_cb,
+ };
+
+ if (l1ctl_server_start(&server, &server_cfg) != 0) {
+ rc = EXIT_FAILURE;
goto exit;
+ }
LOGP(DAPP, LOGL_NOTICE, "Init complete\n");
@@ -557,9 +585,7 @@
osmo_select_main(0);
exit:
- /* Release the trxcon instance */
- if (trxcon != NULL)
- trxcon_inst_free(trxcon);
+ l1ctl_server_shutdown(&server);
/* Deinitialize logging */
log_fini();
To view, visit change 28669. To unsubscribe, or for help writing mail filters, visit settings.