mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-bsc.git
synced 2025-11-03 05:33:20 +00:00
ipaccess-config: Use own e1_input ipaccess driver
Since osmo-bsc.git creation from openbsc.git around 10 years ago, a reference was kept in osmo-bsc/ipaccess/ipaccess-config.c to ipa specific code in the ipaccess e1_input stack of libosmo-abis.git (ipaccess_fd_cb()). Back at that time that was already considered to be an ugly hack, as mentioned in include/osmocom/abis/ipaccess.h exporting that function. This was done because ipaccess-config is quite different in several aspects wrt to usual ipaccess based bts/osmo-bsc ipaccess lines: * nanoBTS acts as TCP server and ipaccess-client as TCP client. * TCP port 3006 is used instead of usual OML 3002. * IPA handshake is actually also different, since despite nanoBTS being the server it doesn't really trigger an IPA ID GET which need to answer. Instead, upon ipaccess-config connecting, it will send an IPA ID ACK and wait to receive an IP ID ACK itself before start transmitting OML to ipaccess-config. Due to all those differences, it really makes no sense to keep support for this setup in the more usual bts<->bsc Abis e1line ipaccess driver present in libosmo-abis.git. Instead, this patch adds a new ipaccess-config-e1-driver.c which implements a libosmo-abis e1_input line driver which works for this specific service. libosmo-abis.git src/input/ipaccess.c from Change-Id Idf241c8f2fdb86d090d4132a9b316b7236402232 is used as a base, further simplifying it by removing stuff not really needed like BTS/BSC role, tcp keepalive, tcp socket stats, etc. Related: SYS#7063 Related: OS#5755 Related: OS#5756 Change-Id: I4d26876ce7d75a78f03c4fa66233550baf4fa7d5
This commit is contained in:
@@ -41,6 +41,7 @@ abisip_find_SOURCES = \
|
||||
|
||||
ipaccess_config_SOURCES = \
|
||||
ipaccess-config.c \
|
||||
ipaccess-config-e1-driver.c \
|
||||
ipaccess-firmware.c \
|
||||
network_listen.c \
|
||||
stubs.c \
|
||||
|
||||
544
src/ipaccess/ipaccess-config-e1-driver.c
Normal file
544
src/ipaccess/ipaccess-config-e1-driver.c
Normal file
@@ -0,0 +1,544 @@
|
||||
/* OpenBSC Abis input driver for ip.access */
|
||||
|
||||
/* (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* (C) 2009-2021 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010 by Holger Hans Peter Freyther
|
||||
* (C) 2010 by On-Waves
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0+
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/macaddr.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/socket.h>
|
||||
#include <osmocom/core/backtrace.h>
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/core/signal.h>
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
#include <osmocom/gsm/protocol/ipaccess.h>
|
||||
#include <osmocom/gsm/ipa.h>
|
||||
#include <osmocom/netif/stream.h>
|
||||
#include <osmocom/netif/ipa.h>
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
#include <osmocom/abis/ipa.h>
|
||||
|
||||
/* default port at BTS for incoming connections */
|
||||
#define IPACCESS_BTS_LISTEN_OML_PORT 3006
|
||||
|
||||
/* global parameters of IPA input driver */
|
||||
struct ipaccess_config_proto_pars {
|
||||
uint8_t dscp;
|
||||
uint8_t priority;
|
||||
};
|
||||
struct ipaccess_config_pars {
|
||||
struct ipaccess_config_proto_pars oml;
|
||||
struct ipaccess_config_proto_pars rsl;
|
||||
char *connect_addr;
|
||||
};
|
||||
struct ipaccess_config_pars g_e1inp_ipaccess_config_pars;
|
||||
|
||||
static void *tall_ipa_ctx;
|
||||
|
||||
struct ipaccess_line {
|
||||
bool line_already_initialized;
|
||||
struct osmo_stream_cli *ipa_cli[NUM_E1_TS]; /* 0=OML, 1+N=TRX_N */
|
||||
};
|
||||
|
||||
static int e1inp_int_snd_event(struct e1inp_ts *ts, struct e1inp_sign_link *link, int evt)
|
||||
{
|
||||
struct input_signal_data isd;
|
||||
isd.line = ts->line;
|
||||
isd.ts_nr = ts->num;
|
||||
isd.link_type = link->type;
|
||||
isd.trx = link->trx;
|
||||
isd.tei = link->tei;
|
||||
isd.sapi = link->sapi;
|
||||
|
||||
/* report further upwards */
|
||||
osmo_signal_dispatch(SS_L_INPUT, evt, &isd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct e1inp_ts *ipaccess_line_ts(struct osmo_fd *bfd, struct e1inp_line *line)
|
||||
{
|
||||
if (bfd->priv_nr == E1INP_SIGN_OML)
|
||||
return e1inp_line_ipa_oml_ts(line);
|
||||
else
|
||||
return e1inp_line_ipa_rsl_ts(line, bfd->priv_nr - E1INP_SIGN_RSL);
|
||||
}
|
||||
|
||||
|
||||
static void _ipaccess_bts_down_cb(struct osmo_stream_cli *cli)
|
||||
{
|
||||
struct e1inp_ts *e1i_ts = osmo_stream_cli_get_data(cli);
|
||||
struct e1inp_line *line = e1i_ts->line;
|
||||
|
||||
if (line->ops->sign_link_down)
|
||||
line->ops->sign_link_down(line);
|
||||
}
|
||||
|
||||
/* See how ts->num is assigned in e1inp_line_create: line->ts[i].num = i+1;
|
||||
* As per e1inp_line_ipa_oml_ts(), first TS in line (ts->num=1) is OML.
|
||||
* As per e1inp_line_ipa_rsl_ts(), second TS in line (ts->num>=2) is RSL.
|
||||
*/
|
||||
static inline enum e1inp_sign_type ipaccess_e1i_ts_sign_type(const struct e1inp_ts *e1i_ts)
|
||||
{
|
||||
OSMO_ASSERT(e1i_ts->num != 0);
|
||||
if (e1i_ts->num == 1)
|
||||
return E1INP_SIGN_OML;
|
||||
return E1INP_SIGN_RSL;
|
||||
}
|
||||
|
||||
static inline unsigned int ipaccess_e1i_ts_trx_nr(const struct e1inp_ts *e1i_ts)
|
||||
{
|
||||
enum e1inp_sign_type sign_type = ipaccess_e1i_ts_sign_type(e1i_ts);
|
||||
if (sign_type == E1INP_SIGN_OML)
|
||||
return 0; /* OML uses trx_nr=0 */
|
||||
OSMO_ASSERT(sign_type == E1INP_SIGN_RSL);
|
||||
/* e1i_ts->num >= 2: */
|
||||
return e1i_ts->num - 2;
|
||||
}
|
||||
|
||||
static inline struct osmo_stream_cli *ipaccess_bts_e1i_ts_stream_cli(const struct e1inp_ts *e1i_ts)
|
||||
{
|
||||
OSMO_ASSERT(e1i_ts);
|
||||
struct ipaccess_line *il = e1i_ts->line->driver_data;
|
||||
OSMO_ASSERT(il);
|
||||
struct osmo_stream_cli *cli = il->ipa_cli[e1i_ts->num - 1];
|
||||
OSMO_ASSERT(cli);
|
||||
return cli;
|
||||
}
|
||||
|
||||
static void ipaccess_close(struct e1inp_sign_link *sign_link)
|
||||
{
|
||||
struct e1inp_ts *e1i_ts = sign_link->ts;
|
||||
struct osmo_fd *bfd = &e1i_ts->driver.ipaccess.fd;
|
||||
struct osmo_stream_cli *cli;
|
||||
|
||||
e1inp_int_snd_event(e1i_ts, sign_link, S_L_INP_TEI_DN);
|
||||
/* the first e1inp_sign_link_destroy call closes the socket. */
|
||||
|
||||
cli = ipaccess_bts_e1i_ts_stream_cli(e1i_ts);
|
||||
osmo_stream_cli_close(cli);
|
||||
bfd->fd = -1; /* Compatibility with older implementations */
|
||||
}
|
||||
|
||||
static bool e1i_ts_has_pending_tx_msgs(struct e1inp_ts *e1i_ts)
|
||||
{
|
||||
struct e1inp_sign_link *link;
|
||||
llist_for_each_entry(link, &e1i_ts->sign.sign_links, list) {
|
||||
if (!llist_empty(&link->tx_list))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ipaccess_bts_send_msg(struct e1inp_ts *e1i_ts,
|
||||
struct e1inp_sign_link *sign_link,
|
||||
struct osmo_stream_cli *cli,
|
||||
struct msgb *msg)
|
||||
{
|
||||
switch (sign_link->type) {
|
||||
case E1INP_SIGN_OML:
|
||||
case E1INP_SIGN_RSL:
|
||||
case E1INP_SIGN_OSMO:
|
||||
break;
|
||||
default:
|
||||
msgb_free(msg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msg->l2h = msg->data;
|
||||
ipa_prepend_header(msg, sign_link->tei);
|
||||
|
||||
LOGPITS(e1i_ts, DLMI, LOGL_DEBUG, "TX: %s\n", osmo_hexdump(msg->l2h, msgb_l2len(msg)));
|
||||
osmo_stream_cli_send(cli, msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* msg was enqueued in sign_link->tx_list.
|
||||
* Pop it from that list, submit it to osmo_stream_cli: */
|
||||
static int ts_want_write(struct e1inp_ts *e1i_ts)
|
||||
{
|
||||
int rc = 0;
|
||||
struct osmo_stream_cli *cli = ipaccess_bts_e1i_ts_stream_cli(e1i_ts);
|
||||
|
||||
/* get the next msg for this timeslot */
|
||||
while (e1i_ts_has_pending_tx_msgs(e1i_ts)) {
|
||||
struct e1inp_sign_link *sign_link = NULL;
|
||||
struct msgb *msg;
|
||||
msg = e1inp_tx_ts(e1i_ts, &sign_link);
|
||||
OSMO_ASSERT(msg);
|
||||
OSMO_ASSERT(sign_link);
|
||||
rc |= ipaccess_bts_send_msg(e1i_ts, sign_link, cli, msg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ipaccess_bts_handle_ccm(struct ipa_client_conn *link,
|
||||
struct ipaccess_unit *dev, struct msgb *msg)
|
||||
{
|
||||
struct ipaccess_head *hh = (struct ipaccess_head *) msg->data;
|
||||
|
||||
/* special handling for IPA CCM. */
|
||||
if (hh->proto != IPAC_PROTO_IPACCESS)
|
||||
return 0;
|
||||
|
||||
int ret = 0;
|
||||
uint8_t *data = msgb_l2(msg);
|
||||
int len = msgb_l2len(msg);
|
||||
OSMO_ASSERT(len > 0);
|
||||
uint8_t msg_type = *data;
|
||||
/* line might not exist if != bsc||bts */
|
||||
|
||||
/* ping, pong and acknowledgment cases. */
|
||||
ret = ipa_ccm_rcvmsg_bts_base(msg, link->ofd);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* this is a request for identification from the BSC. */
|
||||
if (msg_type == IPAC_MSGT_ID_GET) {
|
||||
struct msgb *rmsg;
|
||||
/* The ipaccess_unit dev holds generic identity for the whole
|
||||
* line, hence no trx_id. Patch ipaccess_unit during call to
|
||||
* ipa_ccm_make_id_resp_from_req() to identify this TRX: */
|
||||
int store_trx_nr = dev->trx_id;
|
||||
if (link->ofd->priv_nr >= E1INP_SIGN_RSL)
|
||||
dev->trx_id = link->ofd->priv_nr - E1INP_SIGN_RSL;
|
||||
else
|
||||
dev->trx_id = 0;
|
||||
LOGP(DLINP, LOGL_NOTICE, "received ID_GET for unit ID %u/%u/%u\n",
|
||||
dev->site_id, dev->bts_id, dev->trx_id);
|
||||
rmsg = ipa_ccm_make_id_resp_from_req(dev, data + 1, len - 1);
|
||||
dev->trx_id = store_trx_nr;
|
||||
if (!rmsg) {
|
||||
LOGP(DLINP, LOGL_ERROR, "Failed parsing ID_GET message.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ipa_send(link->ofd->fd, rmsg->data, rmsg->len);
|
||||
if (ret != rmsg->len) {
|
||||
LOGP(DLINP, LOGL_ERROR, "cannot send ID_RESP message. Reason: %s\n",
|
||||
strerror(errno));
|
||||
msgb_free(rmsg);
|
||||
goto err;
|
||||
}
|
||||
msgb_free(rmsg);
|
||||
|
||||
/* send ID_ACK. */
|
||||
ret = ipa_ccm_send_id_ack(link->ofd->fd);
|
||||
if (ret <= 0) {
|
||||
LOGP(DLINP, LOGL_ERROR, "cannot send ID_ACK message. Reason: %s\n",
|
||||
strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
err:
|
||||
ipa_client_conn_close(link);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct msgb *ipa_bts_id_ack(void)
|
||||
{
|
||||
struct msgb *nmsg2;
|
||||
nmsg2 = ipa_msg_alloc(0);
|
||||
if (!nmsg2)
|
||||
return NULL;
|
||||
msgb_v_put(nmsg2, IPAC_MSGT_ID_ACK);
|
||||
ipa_prepend_header(nmsg2, IPAC_PROTO_IPACCESS);
|
||||
return nmsg2;
|
||||
}
|
||||
|
||||
static void update_fd_settings(struct e1inp_line *line, int fd)
|
||||
{
|
||||
int ret;
|
||||
int val;
|
||||
|
||||
val = 1;
|
||||
ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
|
||||
if (ret < 0)
|
||||
LOGPIL(line, DLINP, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
/* Same as ipaccess_bts_handle_ccm(), but using an osmo_stream_cli as backend
|
||||
* instead of ipa_client_conn.
|
||||
* The old ipaccess_bts_handle_ccm() needs to be kept as it's a public API. */
|
||||
static int _ipaccess_bts_handle_ccm(struct osmo_stream_cli *cli,
|
||||
struct ipaccess_unit *dev, struct msgb *msg)
|
||||
{
|
||||
/* special handling for IPA CCM. */
|
||||
if (osmo_ipa_msgb_cb_proto(msg) != IPAC_PROTO_IPACCESS)
|
||||
return 0;
|
||||
|
||||
int ret = 0;
|
||||
const uint8_t *data = msgb_l2(msg);
|
||||
int len = msgb_l2len(msg);
|
||||
OSMO_ASSERT(len > 0);
|
||||
uint8_t msg_type = *data;
|
||||
struct e1inp_ts *e1i_ts = osmo_stream_cli_get_data(cli);
|
||||
/* line might not exist if != bsc||bts */
|
||||
|
||||
/* ping, pong and acknowledgment cases. */
|
||||
struct osmo_fd tmp_ofd = { .fd = osmo_stream_cli_get_fd(cli) };
|
||||
OSMO_ASSERT(tmp_ofd.fd >= 0);
|
||||
ret = ipa_ccm_rcvmsg_bts_base(msg, &tmp_ofd);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* this is a request for identification from the BSC. */
|
||||
if (msg_type == IPAC_MSGT_ID_GET) {
|
||||
struct msgb *rmsg;
|
||||
/* The ipaccess_unit dev holds generic identity for the whole
|
||||
* line, hence no trx_id. Patch ipaccess_unit during call to
|
||||
* ipa_ccm_make_id_resp_from_req() to identify this TRX: */
|
||||
int store_trx_nr = dev->trx_id;
|
||||
dev->trx_id = ipaccess_e1i_ts_trx_nr(e1i_ts);
|
||||
LOGP(DLINP, LOGL_NOTICE, "received ID_GET for unit ID %u/%u/%u\n",
|
||||
dev->site_id, dev->bts_id, dev->trx_id);
|
||||
rmsg = ipa_ccm_make_id_resp_from_req(dev, data + 1, len - 1);
|
||||
dev->trx_id = store_trx_nr;
|
||||
if (!rmsg) {
|
||||
LOGP(DLINP, LOGL_ERROR, "Failed parsing ID_GET message.\n");
|
||||
goto err;
|
||||
}
|
||||
osmo_stream_cli_send(cli, rmsg);
|
||||
|
||||
/* send ID_ACK. */
|
||||
rmsg = ipa_bts_id_ack();
|
||||
if (!rmsg) {
|
||||
LOGP(DLINP, LOGL_ERROR, "Failed allocating ID_ACK message.\n");
|
||||
goto err;
|
||||
}
|
||||
osmo_stream_cli_send(cli, rmsg);
|
||||
}
|
||||
return 1;
|
||||
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ipaccess_bts_read_cb(struct osmo_stream_cli *cli, int res, struct msgb *msg)
|
||||
{
|
||||
enum ipaccess_proto ipa_proto = osmo_ipa_msgb_cb_proto(msg);
|
||||
struct e1inp_ts *e1i_ts = osmo_stream_cli_get_data(cli);
|
||||
struct e1inp_line *line = e1i_ts->line;
|
||||
struct e1inp_sign_link *sign_link;
|
||||
int ret;
|
||||
|
||||
if (res <= 0) {
|
||||
LOGPITS(e1i_ts, DLINP, LOGL_NOTICE, "failed reading from socket: %d\n", res);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* special handling for IPA CCM. */
|
||||
if (ipa_proto == IPAC_PROTO_IPACCESS) {
|
||||
uint8_t msg_type = *(msg->l2h);
|
||||
/* this is a request for identification from the BSC. */
|
||||
if (msg_type == IPAC_MSGT_ID_GET) {
|
||||
if (!line->ops->sign_link_up) {
|
||||
LOGPITS(e1i_ts, DLINP, LOGL_NOTICE,
|
||||
"Unable to set signal link, closing socket.\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* core CCM handling */
|
||||
ret = _ipaccess_bts_handle_ccm(cli, line->ops->cfg.ipa.dev, msg);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
if (ret == 1 && ipa_proto == IPAC_PROTO_IPACCESS) {
|
||||
uint8_t msg_type = *(msg->l2h);
|
||||
if (msg_type == IPAC_MSGT_ID_GET) {
|
||||
enum e1inp_sign_type sign_type = ipaccess_e1i_ts_sign_type(e1i_ts);
|
||||
unsigned int trx_nr = ipaccess_e1i_ts_trx_nr(e1i_ts);
|
||||
sign_link = line->ops->sign_link_up(line->ops->cfg.ipa.dev,
|
||||
line, sign_type + trx_nr);
|
||||
if (sign_link == NULL) {
|
||||
LOGPITS(e1i_ts, DLINP, LOGL_NOTICE,
|
||||
"Unable to set signal link, closing socket.\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
msgb_free(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* look up for some existing signaling link. */
|
||||
sign_link = e1inp_lookup_sign_link(e1i_ts, ipa_proto, 0);
|
||||
if (sign_link == NULL) {
|
||||
LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "no matching signalling link for "
|
||||
"ipa_proto=0x%02x\n", ipa_proto);
|
||||
goto err;
|
||||
}
|
||||
msg->dst = sign_link;
|
||||
|
||||
/* XXX better use e1inp_ts_rx? */
|
||||
if (!line->ops->sign_link) {
|
||||
LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Fix your application, "
|
||||
"no action set for signalling messages.\n");
|
||||
goto err;
|
||||
}
|
||||
return line->ops->sign_link(msg);
|
||||
|
||||
err:
|
||||
msgb_free(msg);
|
||||
osmo_stream_cli_close(cli);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
static int ipaccess_bts_connect_cb(struct osmo_stream_cli *cli)
|
||||
{
|
||||
struct e1inp_ts *e1i_ts = osmo_stream_cli_get_data(cli);
|
||||
struct e1inp_line *line = e1i_ts->line;
|
||||
struct msgb *rmsg;
|
||||
|
||||
update_fd_settings(line, osmo_stream_cli_get_fd(cli));
|
||||
|
||||
/* send ID_ACK. */
|
||||
rmsg = ipa_bts_id_ack();
|
||||
if (!rmsg) {
|
||||
LOGP(DLINP, LOGL_ERROR, "Failed allocating ID_ACK message.\n");
|
||||
return 0;
|
||||
}
|
||||
osmo_stream_cli_send(cli, rmsg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipaccess_bts_disconnect_cb(struct osmo_stream_cli *cli)
|
||||
{
|
||||
_ipaccess_bts_down_cb(cli);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipaccess_line_update(struct e1inp_line *line)
|
||||
{
|
||||
int ret = -ENOENT;
|
||||
struct ipaccess_line *il;
|
||||
|
||||
if (!line->driver_data)
|
||||
line->driver_data = talloc_zero(line, struct ipaccess_line);
|
||||
|
||||
if (!line->driver_data) {
|
||||
LOGPIL(line, DLINP, LOGL_ERROR, "ipaccess: OOM in line update\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
il = line->driver_data;
|
||||
|
||||
/* We only initialize this line once. */
|
||||
if (il->line_already_initialized)
|
||||
return 0;
|
||||
|
||||
struct osmo_stream_cli *cli;
|
||||
struct e1inp_ts *e1i_ts = e1inp_line_ipa_oml_ts(line);
|
||||
char cli_name[128];
|
||||
|
||||
LOGPITS(e1i_ts, DLINP, LOGL_NOTICE, "enabling ipaccess BTS mode, "
|
||||
"OML connecting to %s:%u\n", g_e1inp_ipaccess_config_pars.connect_addr, IPACCESS_BTS_LISTEN_OML_PORT);
|
||||
|
||||
/* Drop previous line */
|
||||
if (il->ipa_cli[0]) {
|
||||
osmo_stream_cli_close(il->ipa_cli[0]);
|
||||
e1i_ts->driver.ipaccess.fd.fd = -1;
|
||||
osmo_stream_cli_destroy(il->ipa_cli[0]);
|
||||
il->ipa_cli[0] = NULL;
|
||||
}
|
||||
|
||||
e1inp_ts_config_sign(e1i_ts, line);
|
||||
|
||||
cli = osmo_stream_cli_create(tall_ipa_ctx);
|
||||
OSMO_ASSERT(cli);
|
||||
|
||||
snprintf(cli_name, sizeof(cli_name), "ts-%u-%u-oml", line->num, e1i_ts->num);
|
||||
osmo_stream_cli_set_name(cli, cli_name);
|
||||
osmo_stream_cli_set_data(cli, e1i_ts);
|
||||
osmo_stream_cli_set_addr(cli, g_e1inp_ipaccess_config_pars.connect_addr);
|
||||
osmo_stream_cli_set_port(cli, IPACCESS_BTS_LISTEN_OML_PORT);
|
||||
osmo_stream_cli_set_proto(cli, IPPROTO_TCP);
|
||||
osmo_stream_cli_set_nodelay(cli, true);
|
||||
osmo_stream_cli_set_priority(cli, g_e1inp_ipaccess_config_pars.oml.dscp);
|
||||
osmo_stream_cli_set_ip_dscp(cli, g_e1inp_ipaccess_config_pars.oml.priority);
|
||||
|
||||
/* Reconnect is handled by upper layers: */
|
||||
osmo_stream_cli_set_reconnect_timeout(cli, -1);
|
||||
|
||||
osmo_stream_cli_set_segmentation_cb(cli, osmo_ipa_segmentation_cb);
|
||||
osmo_stream_cli_set_connect_cb(cli, ipaccess_bts_connect_cb);
|
||||
osmo_stream_cli_set_disconnect_cb(cli, ipaccess_bts_disconnect_cb);
|
||||
osmo_stream_cli_set_read_cb2(cli, ipaccess_bts_read_cb);
|
||||
|
||||
if (osmo_stream_cli_open(cli)) {
|
||||
LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "cannot open OML BTS link: %s\n", strerror(errno));
|
||||
osmo_stream_cli_destroy(cli);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Compatibility with older ofd based implementation. osmo-bts accesses
|
||||
* this fd directly in get_signlink_remote_ip() and get_rsl_local_ip() */
|
||||
e1i_ts->driver.ipaccess.fd.fd = osmo_stream_cli_get_fd(cli);
|
||||
|
||||
il->ipa_cli[0] = cli;
|
||||
ret = 0;
|
||||
|
||||
il->line_already_initialized = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct e1inp_driver ipaccess_config_driver = {
|
||||
.name = "ipaccess-config",
|
||||
.want_write = ts_want_write,
|
||||
.line_update = ipaccess_line_update,
|
||||
.close = ipaccess_close,
|
||||
.default_delay = 0,
|
||||
.has_keepalive = 0,
|
||||
};
|
||||
|
||||
void e1inp_ipaccess_config_init(void *ctx)
|
||||
{
|
||||
tall_ipa_ctx = talloc_named_const(ctx, 1, "ipaccess-config");
|
||||
e1inp_driver_register(&ipaccess_config_driver);
|
||||
|
||||
g_e1inp_ipaccess_config_pars.connect_addr = talloc_strdup(tall_ipa_ctx, "127.0.0.1");
|
||||
}
|
||||
|
||||
void e1inp_ipaccess_config_set_connect_addr(const char *connect_addr)
|
||||
{
|
||||
osmo_talloc_replace_string(tall_ipa_ctx,
|
||||
&g_e1inp_ipaccess_config_pars.connect_addr,
|
||||
connect_addr);
|
||||
}
|
||||
@@ -79,53 +79,15 @@ static void *tall_ctx_config = NULL;
|
||||
static struct abis_nm_sw_desc *sw_load1 = NULL;
|
||||
static struct abis_nm_sw_desc *sw_load2 = NULL;
|
||||
|
||||
extern int ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what);
|
||||
extern struct e1inp_line_ops ipaccess_e1inp_line_ops;
|
||||
|
||||
/* Actively connect to a BTS. Currently used by ipaccess-config.c */
|
||||
static int ipaccess_connect(struct e1inp_line *line, struct sockaddr_in *sa)
|
||||
{
|
||||
struct e1inp_ts *e1i_ts = &line->ts[0];
|
||||
struct osmo_fd *bfd = &e1i_ts->driver.ipaccess.fd;
|
||||
int ret, on = 1;
|
||||
/* Functions from ipaccess-config-e1-driver.c: */
|
||||
extern void e1inp_ipaccess_config_init(void *ctx);
|
||||
extern void e1inp_ipaccess_config_set_connect_addr(const char *connect_addr);
|
||||
|
||||
bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
bfd->cb = ipaccess_fd_cb;
|
||||
bfd->when = OSMO_FD_READ | OSMO_FD_WRITE;
|
||||
bfd->data = line;
|
||||
bfd->priv_nr = E1INP_SIGN_OML;
|
||||
|
||||
if (bfd->fd < 0) {
|
||||
LOGP(DLINP, LOGL_ERROR, "could not create TCP socket.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
if (ret < 0) {
|
||||
LOGP(DLINP, LOGL_ERROR, "could not set socket option\n");
|
||||
close(bfd->fd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = connect(bfd->fd, (struct sockaddr *) sa, sizeof(*sa));
|
||||
if (ret < 0) {
|
||||
LOGP(DLINP, LOGL_ERROR, "could not connect socket\n");
|
||||
close(bfd->fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = osmo_fd_register(bfd);
|
||||
if (ret < 0) {
|
||||
LOGP(DLINP, LOGL_ERROR, "unable to register socket fd\n");
|
||||
close(bfd->fd);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
//return e1inp_line_register(line);
|
||||
}
|
||||
|
||||
/* configure pseudo E1 line in ip.access style and connect to BTS */
|
||||
static int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin)
|
||||
static int ia_config_connect(struct gsm_bts *bts, const char *bts_ip)
|
||||
{
|
||||
struct e1inp_line *line;
|
||||
struct e1inp_ts *sign_ts, *rsl_ts;
|
||||
@@ -135,13 +97,17 @@ static int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin)
|
||||
if (!line)
|
||||
return -ENOMEM;
|
||||
|
||||
line->driver = e1inp_driver_find("ipa");
|
||||
if (!line->driver) {
|
||||
fprintf(stderr, "cannot `ipa' driver, giving up.\n");
|
||||
e1inp_ipaccess_config_init(tall_bsc_ctx);
|
||||
e1inp_ipaccess_config_set_connect_addr(bts_ip);
|
||||
|
||||
line = e1inp_line_create(0, "ipaccess-config");
|
||||
if (!line) {
|
||||
fprintf(stderr, "cannot create line with `ipaccess-config' driver, giving up.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
e1inp_line_bind_ops(line, &ipaccess_e1inp_line_ops);
|
||||
e1_set_pcap_fd2(line, -1); /* Disable writing to pcap */
|
||||
e1inp_line_update(line);
|
||||
|
||||
sign_ts = e1inp_line_ipa_oml_ts(line);
|
||||
rsl_ts = e1inp_line_ipa_rsl_ts(line, 0);
|
||||
@@ -164,11 +130,7 @@ static int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin)
|
||||
bts->osmo_link = osmo_link;
|
||||
bts->c0->rsl_link_primary = rsl_link;
|
||||
|
||||
/* default port at BTS for incoming connections is 3006 */
|
||||
if (sin->sin_port == 0)
|
||||
sin->sin_port = htons(3006);
|
||||
|
||||
return ipaccess_connect(line, sin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1030,7 +992,6 @@ static const struct log_info log_info = {
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct gsm_bts *bts;
|
||||
struct sockaddr_in sin;
|
||||
char *bts_ip;
|
||||
int rc, option_index = 0, stream_id = 0xff;
|
||||
|
||||
@@ -1203,17 +1164,12 @@ int main(int argc, char **argv)
|
||||
if (!quiet)
|
||||
printf("Trying to connect to ip.access BTS %s...\n", bts_ip);
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
inet_aton(bts_ip, &sin.sin_addr);
|
||||
rc = ia_config_connect(bts, &sin);
|
||||
rc = ia_config_connect(bts, bts_ip);
|
||||
if (rc < 0) {
|
||||
perror("Error connecting to the BTS");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bts->oml_link->ts->sign.delay = 10;
|
||||
bts->c0->rsl_link_primary->ts->sign.delay = 10;
|
||||
while (1) {
|
||||
rc = osmo_select_main(0);
|
||||
if (rc < 0)
|
||||
|
||||
Reference in New Issue
Block a user