aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Couzens <lynxis@fe80.eu>2020-08-22 02:55:06 +0200
committerAlexander Couzens <lynxis@fe80.eu>2020-08-22 02:55:06 +0200
commitf50526e78aa09c4e6d1e38edd16f4ea63c6a0954 (patch)
tree93404d30283bdfe91307aaca33e4690912e61a40
parent801e1b4938ec3a71e0f0a04b8d198e49d406c0f4 (diff)
rework bssgp
-rw-r--r--src/gprs_bssgp_pcu.cpp54
-rw-r--r--src/gprs_bssgp_pcu.h16
-rw-r--r--src/pcu_l1_if.cpp78
-rw-r--r--tests/emu/pcu_emu.cpp6
4 files changed, 100 insertions, 54 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 154b1be4..deb16804 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -917,47 +917,33 @@ static int gprs_ns_reconnect(struct gprs_nsvc *nsvc)
return 0;
}
-/* create BSSGP/NS layer instances */
-struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts,
- struct osmo_sockaddr *local, struct osmo_sockaddr *sgsn,
- uint16_t nsei, uint16_t nsvci, uint16_t bvci,
- uint16_t mcc, uint16_t mnc, bool mnc_3_digits,
- uint16_t lac, uint16_t rac, uint16_t cell_id)
+int gprs_nsvc_create_and_connect(
+ struct gprs_rlcmac_bts *bts,
+ struct osmo_sockaddr *local, struct osmo_sockaddr *sgsn,
+ uint16_t nsei, uint16_t nsvci)
{
struct gprs_ns2_vc *nsvc;
struct gprs_ns2_vc_bind *bind;
- struct sockaddr_in dest;
int rc;
- /* if already created... return the current address */
- if (the_pcu.bctx)
- return &the_pcu;
-
- the_pcu.bts = bts;
-
- /* don't specify remote IP/port if SNS dialect is in use; Doing so would
- * issue a connect() on the socket, which prevents us to dynamically communicate
- * with any number of IP-SNS endpoints on the SGSN side */
rc = gprs_ns2_ip_bind(bts->nsi, local, 0, &bind);
if (rc < 0) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create socket\n");
gprs_ns2_free(bts->nsi);
- return NULL;
+ return 1;
}
gprs_ns2_bind_set_mode(bind, NS2_VC_MODE_ALIVE);
- the_pcu.bts->nse = gprs_ns2_nse_by_nsei(bts->nsi, nsei);
- if (!the_pcu.bts->nse)
- the_pcu.bts->nse = gprs_ns2_create_nse(bts->nsi, nsei);
+ bts->nse = gprs_ns2_nse_by_nsei(bts->nsi, nsei);
+ if (!bts->nse)
+ bts->nse = gprs_ns2_create_nse(bts->nsi, nsei);
- if (!the_pcu.bts->nse) {
+ if (!bts->nse) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSE\n");
- gprs_ns2_free(bts->nsi);
- return NULL;
+ return 1;
}
- the_pcu.bts->nsei = nsei;
-
+ bts->nsei = nsei;
if (bts->gb_dialect_sns) {
rc = gprs_ns2_ip_connect_sns(bind, sgsn, nsei);
} else {
@@ -968,15 +954,28 @@ struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts
if (rc) {
/* TODO: Could not connect */
- return NULL;
+ return 1;
}
+ return 0;
+}
+
+struct gprs_bssgp_pcu *gprs_bssgp_init(
+ struct gprs_rlcmac_bts *bts,
+ uint16_t nsei, uint16_t bvci,
+ uint16_t mcc, uint16_t mnc, bool mnc_3_digits,
+ uint16_t lac, uint16_t rac, uint16_t cell_id)
+{
+ /* if already created... return the current address */
+ if (the_pcu.bctx)
+ return &the_pcu;
+
+ the_pcu.bts = bts;
the_pcu.bctx = btsctx_alloc(bvci, nsei);
if (!the_pcu.bctx) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create BSSGP context\n");
the_pcu.bts->nse = NULL;
- gprs_ns2_free(bts->nsi);
return NULL;
}
the_pcu.bctx->ra_id.mcc = spoof_mcc ? : mcc;
@@ -992,7 +991,6 @@ struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts
the_pcu.bctx->cell_id = cell_id;
osmo_signal_register_handler(SS_L_NS, nsvc_signal_cb, bts);
-
osmo_timer_setup(&the_pcu.bvc_timer, bvc_timeout, bts);
return &the_pcu;
diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h
index 1e7a4d81..872512c4 100644
--- a/src/gprs_bssgp_pcu.h
+++ b/src/gprs_bssgp_pcu.h
@@ -75,12 +75,16 @@ struct gprs_bssgp_pcu {
struct tlv_parsed *tp);
};
-struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts,
- struct osmo_sockaddr *local, struct osmo_sockaddr *sgsn,
- uint16_t nsei, uint16_t nsvci, uint16_t bvci,
- uint16_t mcc, uint16_t mnc, bool mnc_3_digits,
- uint16_t lac, uint16_t rac, uint16_t cell_id);
-
+struct gprs_bssgp_pcu *gprs_bssgp_init(
+ struct gprs_rlcmac_bts *bts,
+ uint16_t nsei, uint16_t bvci,
+ uint16_t mcc, uint16_t mnc, bool mnc_3_digits,
+ uint16_t lac, uint16_t rac, uint16_t cell_id);
+
+int gprs_nsvc_create_and_connect(
+ struct gprs_rlcmac_bts *bts,
+ struct osmo_sockaddr *local, struct osmo_sockaddr *sgsn,
+ uint16_t nsei, uint16_t nsvci);
int gprs_bssgp_ns_cb(enum gprs_ns2_evt event, struct msgb *msg,
uint16_t nsei, uint16_t bvci);
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index 7911b6c9..fe610cb1 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -36,6 +36,7 @@ extern "C" {
#include <osmocom/core/gsmtap_util.h>
#include <osmocom/core/gsmtap.h>
#include <osmocom/core/bitvec.h>
+#include <osmocom/core/sockaddr_str.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/l1sap.h>
@@ -491,8 +492,10 @@ static int pcu_rx_info_ind(struct gsm_pcu_if_info_ind *info_ind)
struct gprs_bssgp_pcu *pcu;
struct gprs_rlcmac_pdch *pdch;
struct osmo_sockaddr local_sockaddr, remote_sockaddr;
+ struct osmo_sockaddr_str local;
struct in_addr ia;
int rc = 0;
+ int good_nsvc = 0;
unsigned int trx, ts;
int i;
@@ -566,31 +569,70 @@ bssgp_failed:
}
LOGP(DL1IF, LOGL_DEBUG, " initial_cs=%d\n", info_ind->initial_cs);
LOGP(DL1IF, LOGL_DEBUG, " initial_mcs=%d\n", info_ind->initial_mcs);
- LOGP(DL1IF, LOGL_DEBUG, " nsvci=%d\n", info_ind->nsvci[0]);
- LOGP(DL1IF, LOGL_DEBUG, " local_port=%d\n", info_ind->local_port[0]);
- LOGP(DL1IF, LOGL_DEBUG, " remote_port=%d\n", info_ind->remote_port[0]);
- ia.s_addr = htonl(info_ind->remote_ip[0]);
- LOGP(DL1IF, LOGL_DEBUG, " remote_ip=%s\n", inet_ntoa(ia));
- local_sockaddr.u.sin.sin_family = AF_INET;
- local_sockaddr.u.sin.sin_addr.s_addr = htonl(0);
- local_sockaddr.u.sin.sin_port = htons(info_ind->local_port[0]);
-
- remote_sockaddr.u.sin.sin_family = AF_INET;
- remote_sockaddr.u.sin.sin_addr.s_addr = htonl(info_ind->remote_ip[0]);
- remote_sockaddr.u.sin.sin_port = htons(info_ind->remote_port[0]);
-
- pcu = gprs_bssgp_create_and_connect(
+ pcu = gprs_bssgp_init(
bts,
- &local_sockaddr, &remote_sockaddr,
- info_ind->nsei, info_ind->nsvci[0], info_ind->bvci,
+ info_ind->nsei, info_ind->bvci,
info_ind->mcc, info_ind->mnc, info_ind->mnc_3_digits,
info_ind->lac, info_ind->rac, info_ind->cell_id);
if (!pcu) {
- LOGP(DL1IF, LOGL_NOTICE, "SGSN not available\n");
+ LOGP(DL1IF, LOGL_NOTICE, "Failed to init BSSGP\n");
goto bssgp_failed;
}
+ for (int i=0; i<2; i++) {
+ struct osmo_sockaddr_str sockstr;
+
+ switch (info_ind->address_family[i]) {
+ case IPPROTO_IPIP:
+ local_sockaddr.u.sin.sin_family = AF_INET;
+ local_sockaddr.u.sin.sin_addr.s_addr = INADDR_ANY;
+ local_sockaddr.u.sin.sin_port = info_ind->local_port[i];;
+
+ remote_sockaddr.u.sin.sin_family = AF_INET;
+ remote_sockaddr.u.sin.sin_addr = info_ind->remote_ip[i].ipv4;
+ remote_sockaddr.u.sin.sin_port = info_ind->remote_port[i];
+ break;
+ case IPPROTO_IPV6:
+ local_sockaddr.u.sin6.sin6_family = AF_INET6;
+ local_sockaddr.u.sin6.sin6_addr = in6addr_any;
+ local_sockaddr.u.sin6.sin6_port = info_ind->local_port[i];
+
+ remote_sockaddr.u.sin6.sin6_family = AF_INET6;
+ remote_sockaddr.u.sin6.sin6_addr = info_ind->remote_ip[i].ipv6;
+ remote_sockaddr.u.sin6.sin6_port = info_ind->remote_port[i];
+ break;
+ default:
+ continue;
+ }
+
+ LOGP(DL1IF, LOGL_DEBUG, " NS%d nsvci=%d\n", i, info_ind->nsvci[i]);
+ LOGP(DL1IF, LOGL_DEBUG, " NS%d local_port=%d\n", i, info_ind->local_port[i]);
+ LOGP(DL1IF, LOGL_DEBUG, " NS%d remote_port=%d\n", i, info_ind->remote_port[i]);
+
+ if (osmo_sockaddr_str_from_sockaddr(&sockstr, &remote_sockaddr.u.sas))
+ strcpy(sockstr.ip, "invalid");
+
+ LOGP(DL1IF, LOGL_DEBUG, " NS%d remote_ip=%s\n", i, sockstr.ip);
+ rc = gprs_nsvc_create_and_connect(bts,
+ &local_sockaddr, &remote_sockaddr,
+ info_ind->nsei, info_ind->nsvci[i]);
+ if (rc) {
+ LOGP(DL1IF, LOGL_ERROR, "Failed to create NSVC connection to %s:%d!\n",
+ sockstr.ip, sockstr.port);
+ continue;
+ }
+
+ good_nsvc++;
+ }
+
+ if (good_nsvc == 0) {
+ LOGP(DL1IF, LOGL_ERROR, "No NSVC available to connect to the SGSN!\n");
+ goto bssgp_failed;
+ }
+
+
+
bts->cs1 = !!(info_ind->flags & PCU_IF_FLAG_CS1);
bts->cs2 = !!(info_ind->flags & PCU_IF_FLAG_CS2);
bts->cs3 = !!(info_ind->flags & PCU_IF_FLAG_CS3);
@@ -654,7 +696,7 @@ bssgp_failed:
pcu_tx_act_req(trx, ts, 1);
pdch->enable();
}
- pdch->tsc = info_ind->trx[trx].tsc[ts];
+ pdch->tsc = info_ind->trx[trx].ts[ts].tsc;
LOGP(DL1IF, LOGL_INFO, "PDCH: trx=%d ts=%d\n",
trx, ts);
} else {
diff --git a/tests/emu/pcu_emu.cpp b/tests/emu/pcu_emu.cpp
index eb6d80df..8bad1d42 100644
--- a/tests/emu/pcu_emu.cpp
+++ b/tests/emu/pcu_emu.cpp
@@ -103,8 +103,10 @@ void create_and_connect_bssgp(struct gprs_rlcmac_bts *bts,
remote.u.sin.sin_addr.s_addr = htonl(sgsn_ip);
remote.u.sin.sin_port = htons(sgsn_port);
- pcu = gprs_bssgp_create_and_connect(bts, &local, &remote,
- 20, 20, 20, 901, 99, false, 1, 0, 0);
+ pcu = gprs_bssgp_init(bts, 20, 20, 901, 99, false, 1, 0, 0);
+ gprs_nsvc_create_and_connect(bts, &local, &remote,
+ 20, 20);
+
pcu->on_unblock_ack = bvci_unblocked;
pcu->on_dl_unit_data = bssgp_data;
}