From 2458ccdec4ee59119afdb2ae5d13205788c42a6d Mon Sep 17 00:00:00 2001 From: Ivan Kluchnikov Date: Wed, 5 Sep 2018 17:40:07 +0300 Subject: hack: Send/receive data and control gb messages to/from different SGSN ports received during SNS configuration procedure This patch is committed for historical purposes and it is required a significant rewrite. Data and control ports numbers are hardcoded, but they should be extracted from SNS-CONFIG message from SGSN. Changes to support both SNS and static configuration are required. Change-Id: I2494544e54c5af80ccea16c45c5f270835f8f346 --- include/osmocom/gprs/gprs_ns.h | 5 ++ src/gb/gprs_bssgp_bss.c | 24 +++++----- src/gb/gprs_ns.c | 106 +++++++++++++++++++++++------------------ src/gb/gprs_ns_sns.c | 6 ++- 4 files changed, 81 insertions(+), 60 deletions(-) diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index febbde22..7698ca26 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -49,6 +49,9 @@ enum ns_timeout { #define NS_DESC_A(st) ((st) & NSE_S_ALIVE ? "ALIVE" : "DEAD") #define NS_DESC_R(st) ((st) & NSE_S_RESET ? "RESET" : "UNRESET") +#define GB_SIGN_PORT 42000 +#define GB_DATA_PORT 2100 + /*! Osmocom NS link layer types */ enum gprs_ns_ll { GPRS_NS_LL_UDP, /*!< NS/UDP/IP */ @@ -181,6 +184,8 @@ struct sockaddr_in; /* main function for higher layers (BSSGP) to send NS messages */ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg); +int gprs_ns_sendmsg_bss(struct gprs_ns_inst *nsi, struct msgb *msg, int port); + int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause); int gprs_ns_tx_block(struct gprs_nsvc *nsvc, uint8_t cause); diff --git a/src/gb/gprs_bssgp_bss.c b/src/gb/gprs_bssgp_bss.c index 487286c4..eeaf9193 100644 --- a/src/gb/gprs_bssgp_bss.c +++ b/src/gb/gprs_bssgp_bss.c @@ -69,7 +69,7 @@ int bssgp_tx_suspend(uint16_t nsei, uint32_t tlli, bssgp_msgb_tlli_put(msg, tlli); bssgp_msgb_ra_put(msg, ra_id); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT); } /*! GMM-RESUME.req (Chapter 10.3.9) */ @@ -91,7 +91,7 @@ int bssgp_tx_resume(uint16_t nsei, uint32_t tlli, msgb_tvlv_put(msg, BSSGP_IE_SUSPEND_REF_NR, 1, &suspend_ref); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT); } /*! Transmit RA-CAPABILITY-UPDATE (10.3.3) */ @@ -113,7 +113,7 @@ int bssgp_tx_ra_capa_upd(struct bssgp_bvc_ctx *bctx, uint32_t tlli, uint8_t tag) msgb_tvlv_put(msg, BSSGP_IE_TAG, 1, &tag); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT); } /* first common part of RADIO-STATUS */ @@ -141,7 +141,7 @@ static int common_tx_radio_status2(struct msgb *msg, uint8_t cause) msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, &cause); LOGPC(DBSSGP, LOGL_NOTICE, "CAUSE=%s\n", bssgp_cause_str(cause)); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT); } /*! Transmit RADIO-STATUS for TLLI (10.3.5) */ @@ -213,7 +213,7 @@ int bssgp_tx_flush_ll_ack(struct bssgp_bvc_ctx *bctx, uint32_t tlli, msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci_new); msgb_tvlv_put(msg, BSSGP_IE_NUM_OCT_AFF, 3, (uint8_t *) &_oct_aff); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_SIGN_PORT); } /*! Transmit LLC-DISCARDED (Chapter 10.4.3) */ @@ -239,7 +239,7 @@ int bssgp_tx_llc_discarded(struct bssgp_bvc_ctx *bctx, uint32_t tlli, msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci); msgb_tvlv_put(msg, BSSGP_IE_NUM_OCT_AFF, 3, ((uint8_t *) &_oct_aff) + 1); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_SIGN_PORT); } /*! Transmit a BVC-BLOCK message (Chapter 10.4.8) */ @@ -260,7 +260,7 @@ int bssgp_tx_bvc_block(struct bssgp_bvc_ctx *bctx, uint8_t cause) msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci); msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, &cause); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_SIGN_PORT); } /*! Transmit a BVC-UNBLOCK message (Chapter 10.4.10) */ @@ -279,7 +279,7 @@ int bssgp_tx_bvc_unblock(struct bssgp_bvc_ctx *bctx) msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_SIGN_PORT); } /*! Transmit a BVC-RESET message (Chapter 10.4.12) */ @@ -306,7 +306,7 @@ int bssgp_tx_bvc_reset(struct bssgp_bvc_ctx *bctx, uint16_t bvci, uint8_t cause) } /* Optional: Feature Bitmap */ - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_SIGN_PORT); } /*! Transmit a FLOW_CONTROL-BVC (Chapter 10.4.4) @@ -378,7 +378,7 @@ int bssgp_tx_fc_bvc(struct bssgp_bvc_ctx *bctx, uint8_t tag, sizeof(e_queue_delay), (uint8_t *) &e_queue_delay); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT); } /*! Transmit a FLOW_CONTROL-MS (Chapter 10.4.6) @@ -421,7 +421,7 @@ int bssgp_tx_fc_ms(struct bssgp_bvc_ctx *bctx, uint32_t tlli, uint8_t tag, msgb_tvlv_put(msg, BSSGP_IE_BUCKET_FULL_RATIO, 1, bucket_full_ratio); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT); } /*! RL-UL-UNITDATA.req (Chapter 10.2.2) @@ -467,7 +467,7 @@ int bssgp_tx_ul_ud(struct bssgp_bvc_ctx *bctx, uint32_t tlli, rate_ctr_inc(&bctx->ctrg->ctr[BSSGP_CTR_PKTS_OUT]); rate_ctr_add(&bctx->ctrg->ctr[BSSGP_CTR_BYTES_OUT], msg->len); - return gprs_ns_sendmsg(bssgp_nsi, msg); + return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT); } /* Parse a single GMM-PAGING.req to a given NSEI/NS-BVCI */ diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index dc693026..c5202433 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -259,8 +259,7 @@ static struct gprs_nsvc *nsvc_by_rem_addr(struct gprs_ns_inst *nsi, struct gprs_nsvc *nsvc; llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { if (nsvc->ip.bts_addr.sin_addr.s_addr == - sin->sin_addr.s_addr && - nsvc->ip.bts_addr.sin_port == sin->sin_port) + sin->sin_addr.s_addr) return nsvc; } return NULL; @@ -444,29 +443,16 @@ static int gprs_ns_tx_simple(struct gprs_nsvc *nsvc, uint8_t pdu_type) */ int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause) { - struct msgb *msg = gprs_ns_msgb_alloc(); - struct gprs_ns_hdr *nsh; - uint16_t nsvci = osmo_htons(nsvc->nsvci); - uint16_t nsei = osmo_htons(nsvc->nsei); - - log_set_context(LOG_CTX_GB_NSVC, nsvc); - - if (!msg) - return -ENOMEM; - - LOGP(DNS, LOGL_INFO, "NSEI=%u Tx NS RESET (NSVCI=%u, cause=%s)\n", - nsvc->nsei, nsvc->nsvci, gprs_ns_cause_str(cause)); - - msg->l2h = msgb_put(msg, sizeof(*nsh)); - nsh = (struct gprs_ns_hdr *) msg->l2h; - nsh->pdu_type = NS_PDUT_RESET; - - msgb_tvlv_put(msg, NS_IE_CAUSE, 1, &cause); - msgb_tvlv_put(msg, NS_IE_VCI, 2, (uint8_t *) &nsvci); - msgb_tvlv_put(msg, NS_IE_NSEI, 2, (uint8_t *) &nsei); - - return gprs_ns_tx(nsvc, msg); + ns_set_state(nsvc, NSE_S_BLOCKED | NSE_S_ALIVE); + ns_set_remote_state(nsvc, NSE_S_BLOCKED | NSE_S_ALIVE); + rate_ctr_inc(&(nsvc)->ctrg->ctr[NS_CTR_BLOCKED]); + LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS UNBLOCK ACK\n", nsvc->nsei); + /* mark NS-VC as unblocked + active */ + ns_set_state(nsvc, NSE_S_ALIVE); + ns_set_remote_state(nsvc, NSE_S_ALIVE); + ns_osmo_signal_dispatch(nsvc, S_NS_UNBLOCK, 0); + return 1; } /*! Transmit a NS-STATUS on a given NSVC @@ -592,6 +578,8 @@ int gprs_ns_tx_alive_ack(struct gprs_nsvc *nsvc) LOGP(DNS, LOGL_DEBUG, "NSEI=%u Tx NS ALIVE_ACK (NSVCI=%u)\n", nsvc->nsei, nsvc->nsvci); + nsvc->ip.bts_addr.sin_port = htons(GB_SIGN_PORT); + return gprs_ns_tx_simple(nsvc, NS_PDUT_ALIVE_ACK); } @@ -887,6 +875,51 @@ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) return gprs_ns_tx(nsvc, msg); } +int gprs_ns_sendmsg_bss(struct gprs_ns_inst *nsi, struct msgb *msg, int port) +{ + struct gprs_nsvc *nsvc; + struct gprs_ns_hdr *nsh; + uint16_t bvci = msgb_bvci(msg); + + nsvc = gprs_active_nsvc_by_nsei(nsi, msgb_nsei(msg)); + if (!nsvc) { + int rc; + if (gprs_nsvc_by_nsei(nsi, msgb_nsei(msg))) { + LOGP(DNS, LOGL_ERROR, + "All NS-VCs for NSEI %u are either dead or blocked!\n", + msgb_nsei(msg)); + rc = -EBUSY; + } else { + LOGP(DNS, LOGL_ERROR, "Unable to resolve NSEI %u " + "to NS-VC!\n", msgb_nsei(msg)); + rc = -EINVAL; + } + + msgb_free(msg); + return rc; + } + log_set_context(LOG_CTX_GB_NSVC, nsvc); + + msg->l2h = msgb_push(msg, sizeof(*nsh) + 3); + nsh = (struct gprs_ns_hdr *) msg->l2h; + if (!nsh) { + LOGP(DNS, LOGL_ERROR, "Not enough headroom for NS header\n"); + msgb_free(msg); + return -EIO; + } + + nsh->pdu_type = NS_PDUT_UNITDATA; + /* spare octet in data[0] */ + nsh->data[1] = bvci >> 8; + nsh->data[2] = bvci & 0xff; + + //TX BSSGP + nsvc->ip.bts_addr.sin_port = htons(port); + + return gprs_ns_tx(nsvc, msg); +} + + /* Section 9.2.10: receive side */ static int gprs_ns_rx_unitdata(struct gprs_nsvc *nsvc, struct msgb *msg) { @@ -1764,26 +1797,10 @@ int gprs_ns_nsip_listen(struct gprs_ns_inst *nsi) nsi->nsip.fd.cb = nsip_fd_cb; nsi->nsip.fd.data = nsi; - if (nsi->nsip.remote_ip && nsi->nsip.remote_port) { - /* connect to ensure only we only accept packets from the - * configured remote end/peer */ - snprintf(remote_str, sizeof(remote_str), "%s", inet_ntoa(remote)); - ret = - osmo_sock_init2_ofd(&nsi->nsip.fd, AF_INET, SOCK_DGRAM, - IPPROTO_UDP, inet_ntoa(in), - nsi->nsip.local_port, remote_str, - nsi->nsip.remote_port, OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT); - - LOGP(DNS, LOGL_NOTICE, - "Listening for nsip packets from %s:%u on %s:%u\n", - remote_str, nsi->nsip.remote_port, inet_ntoa(in), nsi->nsip.local_port); - } else { - /* Accept UDP packets from any source IP/Port */ - ret = osmo_sock_init_ofd(&nsi->nsip.fd, AF_INET, SOCK_DGRAM, - IPPROTO_UDP, inet_ntoa(in), nsi->nsip.local_port, OSMO_SOCK_F_BIND); + ret = osmo_sock_init_ofd(&nsi->nsip.fd, AF_INET, SOCK_DGRAM, + IPPROTO_UDP, inet_ntoa(in), nsi->nsip.local_port, OSMO_SOCK_F_BIND); - LOGP(DNS, LOGL_NOTICE, "Listening for nsip packets on %s:%u\n", inet_ntoa(in), nsi->nsip.local_port); - } + LOGP(DNS, LOGL_NOTICE, "Listening for nsip packets on %s:%u\n", inet_ntoa(in), nsi->nsip.local_port); if (ret < 0) return ret; @@ -1824,9 +1841,6 @@ int gprs_nsvc_reset(struct gprs_nsvc *nsvc, uint8_t cause) LOGP(DNS, LOGL_ERROR, "NSEI=%u, error resetting NS-VC\n", nsvc->nsei); } - /* Start Tns-reset */ - nsvc_start_timer(nsvc, NSVC_TIMER_TNS_RESET); - return rc; } diff --git a/src/gb/gprs_ns_sns.c b/src/gb/gprs_ns_sns.c index ddd641f8..ebc6d418 100644 --- a/src/gb/gprs_ns_sns.c +++ b/src/gb/gprs_ns_sns.c @@ -178,11 +178,13 @@ static void gprs_sns_st_config_sgsn(struct osmo_fsm_inst *fi, uint32_t event, vo } LOGPFSML(fi, LOGL_INFO, "Rx SNS-CONFIG: Remote IPv4 list now %u entries\n", gss->num_ip4_remote); + /* send CONFIG-ACK */ + gprs_ns_tx_sns_config_ack(gss->nsvc_hack, NULL); + if (event == GPRS_SNS_EV_CONFIG_END) { osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, 0, 0); } - /* send CONFIG-ACK */ - gprs_ns_tx_sns_config_ack(gss->nsvc_hack, NULL); + break; default: OSMO_ASSERT(0); -- cgit v1.2.3