fixeria has submitted this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/28669 )
Change subject: trxcon: rework L1CTL socket API to support multiple clients ......................................................................
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(-)
Approvals: Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve laforge: Looks good to me, but someone else must approve fixeria: Looks good to me, approved
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();