diff options
author | Alexander Couzens <lynxis@fe80.eu> | 2020-09-16 21:52:02 +0200 |
---|---|---|
committer | Alexander Couzens <lynxis@fe80.eu> | 2020-10-06 16:38:38 +0200 |
commit | 290d9030e9eece679197f5d85593a4aa8c8672c7 (patch) | |
tree | 4ba45cb8aef0f3db905ad85fdef4e8a83c355bbe /src/gprs_bssgp_pcu.cpp | |
parent | 0a369e560cef5967bdf47a7ee9b36bf98b418cc8 (diff) |
Use the new NS2 lib
Depends: Id7edb8feb96436ba170383fc62d43ceb16955d53 (libosmocore)
Depends: I2a9dcd14f4ad16211c0f6d98812ad4a13e910c2a (libosmocore)
Change-Id: Ib389925cf5c9f18951af6242c31ea70476218e9a
Diffstat (limited to 'src/gprs_bssgp_pcu.cpp')
-rw-r--r-- | src/gprs_bssgp_pcu.cpp | 232 |
1 files changed, 112 insertions, 120 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index d008d02c..67c07a21 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -30,6 +30,7 @@ extern "C" { #include <osmocom/gsm/protocol/gsm_23_003.h> + #include <osmocom/gprs/protocol/gsm_08_16.h> #include <osmocom/core/utils.h> #include "coding_scheme.h" } @@ -51,7 +52,6 @@ extern uint16_t spoof_mcc, spoof_mnc; extern bool spoof_mnc_3_digits; static void bvc_timeout(void *_priv); -static int gprs_ns_reconnect(struct gprs_nsvc *nsvc); static int parse_ra_cap(struct tlv_parsed *tp, MS_Radio_Access_capability_t *rac) { @@ -549,75 +549,91 @@ int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx) return 0; } -int gprs_bssgp_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, struct msgb *msg, uint16_t bvci) +void gprs_ns_prim_status_cb(struct osmo_gprs_ns2_prim *nsp) { - int rc = 0; - switch (event) { - case GPRS_NS_EVT_UNIT_DATA: - /* hand the message into the BSSGP implementation */ - rc = gprs_bssgp_pcu_rcvmsg(msg); - break; - default: - LOGP(DPCU, LOGL_NOTICE, "RLCMAC: Unknown event %u from NS\n", event); - rc = -EIO; - break; - } - return rc; -} - - -static int nsvc_signal_cb(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) -{ - struct ns_signal_data *nssd; - - if (subsys != SS_L_NS) - return -EINVAL; - - nssd = (struct ns_signal_data *)signal_data; - if (signal != S_SNS_CONFIGURED && nssd->nsvc != the_pcu.nsvc) { - LOGP(DPCU, LOGL_ERROR, "Signal received of unknown NSVC\n"); - return -EINVAL; - } - - switch (signal) { - case S_SNS_CONFIGURED: - the_pcu.bvc_sig_reset = 0; - the_pcu.bvc_reset = 0; - /* There's no NS-RESET / NS-UNBLOCK procedure on IP SNS based NS-VCs */ - the_pcu.nsvc_unblocked = 1; - LOGP(DPCU, LOGL_NOTICE, "NS-VC %d is unblocked.\n", the_pcu.nsvc->nsvci); - bvc_timeout(NULL); + switch (nsp->u.status.cause) { + case NS_AFF_CAUSE_SNS_CONFIGURED: + LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d SNS configured.\n", nsp->nsei); break; - case S_NS_UNBLOCK: + case NS_AFF_CAUSE_RECOVERY: + LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d became available\n", nsp->nsei); if (!the_pcu.nsvc_unblocked) { - the_pcu.nsvc_unblocked = 1; - LOGP(DPCU, LOGL_NOTICE, "NS-VC %d is unblocked.\n", - the_pcu.nsvc->nsvci); the_pcu.bvc_sig_reset = 0; the_pcu.bvc_reset = 0; - the_pcu.bvc_unblocked = 0; + the_pcu.nsvc_unblocked = 1; bvc_timeout(NULL); } break; - case S_NS_BLOCK: + case NS_AFF_CAUSE_FAILURE: + LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d became unavailable\n", nsp->nsei); if (the_pcu.nsvc_unblocked) { the_pcu.nsvc_unblocked = 0; osmo_timer_del(&the_pcu.bvc_timer); the_pcu.bvc_sig_reset = 0; the_pcu.bvc_reset = 0; the_pcu.bvc_unblocked = 0; - LOGP(DPCU, LOGL_NOTICE, "NS-VC is blocked.\n"); } break; - case S_NS_ALIVE_EXP: - LOGP(DPCU, LOGL_NOTICE, "Tns alive expired too often, " - "re-starting RESET procedure\n"); - gprs_ns_reconnect(nssd->nsvc); + default: + LOGP(DPCU, LOGL_NOTICE, + "NS: %s Unknown prim %d from NS\n", + get_value_string(osmo_prim_op_names, nsp->oph.operation), + nsp->oph.primitive); break; } +} - return 0; +/* called by the ns layer */ +int gprs_ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx) +{ + struct osmo_gprs_ns2_prim *nsp; + int rc = 0; + + if (oph->sap != SAP_NS) + return 0; + + nsp = container_of(oph, struct osmo_gprs_ns2_prim, oph); + + if (oph->operation != PRIM_OP_INDICATION) { + LOGP(DPCU, LOGL_NOTICE, "NS: %s Unknown prim %d from NS\n", + get_value_string(osmo_prim_op_names, oph->operation), + oph->operation); + return 0; + } + + switch (oph->primitive) { + case PRIM_NS_UNIT_DATA: + /* hand the message into the BSSGP implementation */ + /* add required msg fields for Gb layer */ + msgb_bssgph(oph->msg) = oph->msg->l3h; + msgb_bvci(oph->msg) = nsp->bvci; + msgb_nsei(oph->msg) = nsp->nsei; + rc = gprs_bssgp_pcu_rcvmsg(oph->msg); + break; + case PRIM_NS_STATUS: + gprs_ns_prim_status_cb(nsp); + break; + default: + LOGP(DPCU, LOGL_NOTICE, + "NS: %s Unknown prim %d from NS\n", + get_value_string(osmo_prim_op_names, oph->operation), + oph->primitive); + break; + } + + return rc; +} + +/* called by the bssgp layer to send NS PDUs */ +int gprs_gp_send_cb(void *ctx, struct msgb *msg) +{ + struct gprs_ns2_inst *nsi = (struct gprs_ns2_inst *) ctx; + struct osmo_gprs_ns2_prim nsp = {}; + nsp.nsei = msgb_nsei(msg); + nsp.bvci = msgb_bvci(msg); + osmo_prim_init(&nsp.oph, SAP_NS, PRIM_NS_UNIT_DATA, + PRIM_OP_REQUEST, msg); + return gprs_ns2_recv_prim(nsi, &nsp.oph); } static unsigned count_pdch(const struct gprs_rlcmac_bts *bts) @@ -904,77 +920,63 @@ static void bvc_timeout(void *_priv) osmo_timer_schedule(&the_pcu.bvc_timer, the_pcu.bts->fc_interval, 0); } -static int gprs_ns_reconnect(struct gprs_nsvc *nsvc) + +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_nsvc *nsvc2; + struct gprs_ns2_vc *nsvc; + struct gprs_ns2_vc_bind *bind; + int rc; - if (nsvc != the_pcu.nsvc) { - LOGP(DBSSGP, LOGL_ERROR, "NSVC is invalid\n"); - return -EBADF; + 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 1; } - if (the_pcu.bts->gb_dialect_sns) - nsvc2 = gprs_ns_nsip_connect_sns(bssgp_nsi, &nsvc->ip.bts_addr, nsvc->nsei, nsvc->nsvci); - else - nsvc2 = gprs_ns_nsip_connect(bssgp_nsi, &nsvc->ip.bts_addr, nsvc->nsei, nsvc->nsvci); - if (!nsvc2) { - LOGP(DBSSGP, LOGL_ERROR, "Failed to reconnect NSVC\n"); - return -EIO; + bts->nse = gprs_ns2_nse_by_nsei(bts->nsi, nsei); + if (!bts->nse) + bts->nse = gprs_ns2_create_nse(bts->nsi, nsei); + + if (!bts->nse) { + LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSE\n"); + return 1; } - return 0; + bts->nsei = nsei; + if (bts->gb_dialect_sns) { + rc = gprs_ns2_ip_connect_sns(bind, sgsn, nsei); + } else { + nsvc = gprs_ns2_ip_connect2(bind, sgsn, nsei, nsvci); + if (!nsvc) + rc = -1; + } + + if (rc) + LOGP(DBSSGP, LOGL_ERROR, "Failed to connect!\n"); + + return rc; } -/* create BSSGP/NS layer instances */ -struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, - uint16_t local_port, uint32_t sgsn_ip, - uint16_t sgsn_port, 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) { - 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 */ - if (!bts->gb_dialect_sns) { - bssgp_nsi->nsip.remote_port = sgsn_port; - bssgp_nsi->nsip.remote_ip = sgsn_ip; - } - bssgp_nsi->nsip.local_port = local_port; - rc = gprs_ns_nsip_listen(bssgp_nsi); - if (rc < 0) { - LOGP(DBSSGP, LOGL_ERROR, "Failed to create socket\n"); - gprs_ns_close(bssgp_nsi); - return NULL; - } - - dest.sin_family = AF_INET; - dest.sin_port = htons(sgsn_port); - dest.sin_addr.s_addr = htonl(sgsn_ip); - - if (bts->gb_dialect_sns) - the_pcu.nsvc = gprs_ns_nsip_connect_sns(bssgp_nsi, &dest, nsei, nsvci); - else - the_pcu.nsvc = gprs_ns_nsip_connect(bssgp_nsi, &dest, nsei, nsvci); - if (!the_pcu.nsvc) { - LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSVCt\n"); - gprs_ns_close(bssgp_nsi); - return NULL; - } - the_pcu.bctx = btsctx_alloc(bvci, nsei); if (!the_pcu.bctx) { LOGP(DBSSGP, LOGL_ERROR, "Failed to create BSSGP context\n"); - the_pcu.nsvc = NULL; - gprs_ns_close(bssgp_nsi); + the_pcu.bts->nse = NULL; return NULL; } the_pcu.bctx->ra_id.mcc = spoof_mcc ? : mcc; @@ -989,37 +991,27 @@ struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts the_pcu.bctx->ra_id.rac = rac; the_pcu.bctx->cell_id = cell_id; - osmo_signal_register_handler(SS_L_NS, nsvc_signal_cb, NULL); - - osmo_timer_setup(&the_pcu.bvc_timer, bvc_timeout, NULL); + osmo_timer_setup(&the_pcu.bvc_timer, bvc_timeout, bts); return &the_pcu; } -void gprs_bssgp_destroy(void) +void gprs_bssgp_destroy(struct gprs_rlcmac_bts *bts) { - struct gprs_ns_inst *nsi = bssgp_nsi; - if (!nsi) - return; - - bssgp_nsi = NULL; - osmo_timer_del(&the_pcu.bvc_timer); - osmo_signal_unregister_handler(SS_L_NS, nsvc_signal_cb, NULL); - - the_pcu.nsvc = NULL; - /* FIXME: blocking... */ the_pcu.nsvc_unblocked = 0; the_pcu.bvc_sig_reset = 0; the_pcu.bvc_reset = 0; the_pcu.bvc_unblocked = 0; - gprs_ns_destroy(nsi); - bssgp_bvc_ctx_free(the_pcu.bctx); the_pcu.bctx = NULL; + + gprs_ns2_free(bts->nsi); + bts->nsi = NULL; + bts->nse = NULL; } struct bssgp_bvc_ctx *gprs_bssgp_pcu_current_bctx(void) |