From zero-kelvin at gmx.de Thu Oct 24 21:42:00 2013 From: zero-kelvin at gmx.de (dexter) Date: Thu, 24 Oct 2013 23:42:00 +0200 Subject: UPDATE -- Osmocom Berlin User Group meeting -- NEXT MEETING In-Reply-To: <20130605121428.GA10030@nataraja.gnumonks.org> References: <502d01a9.mirider@mirider.augusta.de> <20120818115942.GV29525@prithivi.gnumonks.org> <51AF0097.10402@gmx.de> <20130605121428.GA10030@nataraja.gnumonks.org> Message-ID: <52699428.5020700@gmx.de> Hi All. It's time Again! This is the announcement for the next Osmocom Berlin meeting. Oct 30, 8pm @ CCC Berlin, Marienstr. 11, 10117 Berlin There is no formal presentation scheduled for this meeting. If you are interested to show up, feel free to do so. There is no registration required. The meeting is free as in "free beer", despite no actual free beer being around. I am looking forward to see you there! regards. Philipp From zero-kelvin at gmx.de Wed Oct 30 18:37:25 2013 From: zero-kelvin at gmx.de (dexter) Date: Wed, 30 Oct 2013 19:37:25 +0100 Subject: UPDATE -- Osmocom Berlin User Group meeting -- NEXT MEETING In-Reply-To: <20130605121428.GA10030@nataraja.gnumonks.org> References: <502d01a9.mirider@mirider.augusta.de> <20120818115942.GV29525@prithivi.gnumonks.org> <51AF0097.10402@gmx.de> <20130605121428.GA10030@nataraja.gnumonks.org> Message-ID: <527151E5.8050703@gmx.de> Hi All. Sorry, i might be some minits late today - i am on my way! regards. Philipp From buildtherobots at gmail.com Wed Oct 23 23:03:43 2013 From: buildtherobots at gmail.com (Daniel Fligg) Date: Thu, 24 Oct 2013 00:03:43 +0100 Subject: Hard reset NanoBTS after forgetting static IP Message-ID: I have come across a nanoBTS 165AU but since is used and not tested from the previous owner, I guess it has set a static IP. After turned on is booting (RED light) and then remains (ORANGE not flashing) even if the eth is connected to the router. Based on observation, constant blinking orange seems to indicate the layer 2 link isn't up (eg it's powered but Ethernet isn't connected). Solid orange is good. Once it's fully booted it seems to be solid orange with a very quick flash off once a second seems to indicate it's trying to find the BSC > At the moment I am trying with ipaccess-find and BtsInstaller to find in on my LAN . > Unfortunately it is not answering and is not even getting an IP from the router by the DHCP daemon. > > ipaccess-find / btsinstaller only ever seem to find my BSCs when the machine they're running on is on the same subnet. The easiest way to track down a rogue bts is to connect it directly to a spare network port in the pc and then run wireshark on it. On boot my BTS sends a number of dhcp inform requests broadcasting it's IP and then starts blasting packets at the BSC address. Hope this helps, -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.chemeris at gmail.com Sun Oct 6 20:58:57 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sun, 6 Oct 2013 22:58:57 +0200 Subject: [PATCH 02/20] Add header file of PH-/MPH-/TCH-SAP interface to common part of osmo-bts In-Reply-To: <1379592710-4811-2-git-send-email-jolly@eversberg.eu> References: <1379592710-4811-1-git-send-email-jolly@eversberg.eu> <1379592710-4811-2-git-send-email-jolly@eversberg.eu> Message-ID: It would be great to add pointers to the exact parts of the GSM standard which describe all this, but otherwise the patch looks good to me from the code structure perspective. On Thu, Sep 19, 2013 at 2:11 PM, Andreas Eversberg wrote: > Instead of handling primitives directly at layer 1 specific code, > osmo-bts handles primitives at common code. > > When all primitive are moved, the l1sap interface will: > - receive PH-DATA indications and forward them to layer 2. > - check for RF link loss and notify BSC. > - receive TCH indications and forward them via RTP. > - receive PH-RTS indications and send PH-DATA requests with content > according to its logical channel. > - receive TCH-RTS indications and send TCH requests with content > received via RTP or loopback from TCH indications. > - send MPH-INFO requests to activate, deactivate and modify logical > channels and handle their confirms. > - receive MPH-INFO indications with measurements from tranceiver. > - forward received and transmitted PH-DATA to GSMTAP. > --- > include/osmo-bts/Makefile.am | 3 +- > include/osmo-bts/l1sap.h | 71 ++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 73 insertions(+), 1 deletion(-) > create mode 100644 include/osmo-bts/l1sap.h > > diff --git a/include/osmo-bts/Makefile.am b/include/osmo-bts/Makefile.am > index 456d416..d8c0002 100644 > --- a/include/osmo-bts/Makefile.am > +++ b/include/osmo-bts/Makefile.am > @@ -1,2 +1,3 @@ > noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h logging.h measurement.h \ > - oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h > + oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h \ > + pcuif_proto.h l1sap.h > diff --git a/include/osmo-bts/l1sap.h b/include/osmo-bts/l1sap.h > new file mode 100644 > index 0000000..a1dc303 > --- /dev/null > +++ b/include/osmo-bts/l1sap.h > @@ -0,0 +1,71 @@ > +#ifndef L1SAP_H > +#define L1SAP_H > + > +/* timeslot and subslot from chan_nr */ > +#define L1SAP_CHAN2TS(chan_nr) (chan_nr & 7) > +#define L1SAP_CHAN2SS_TCHH(chan_nr) ((chan_nr >> 3) & 1) > +#define L1SAP_CHAN2SS_SDCCH4(chan_nr) ((chan_nr >> 3) & 3) > +#define L1SAP_CHAN2SS_SDCCH8(chan_nr) ((chan_nr >> 3) & 7) > + > +/* logical channel from chan_nr + link_id */ > +#define L1SAP_IS_LINK_SACCH(link_id) ((link_id & 0xC0) == 0x40) > +#define L1SAP_IS_CHAN_TCHF(chan_nr) ((chan_nr & 0xf8) == 0x08) > +#define L1SAP_IS_CHAN_TCHH(chan_nr) ((chan_nr & 0xf0) == 0x10) > +#define L1SAP_IS_CHAN_SDCCH4(chan_nr) ((chan_nr & 0xe0) == 0x20) > +#define L1SAP_IS_CHAN_SDCCH8(chan_nr) ((chan_nr & 0xc0) == 0x40) > +#define L1SAP_IS_CHAN_BCCH(chan_nr) ((chan_nr & 0xf8) == 0x80) > +#define L1SAP_IS_CHAN_RACH(chan_nr) ((chan_nr & 0xf8) == 0x88) > +#define L1SAP_IS_CHAN_AGCH_PCH(chan_nr) ((chan_nr & 0xf8) == 0x90) > + > +/* rach type from ra */ > +#define L1SAP_IS_PACKET_RACH(ra) ((ra & 0xf0) == 0x70) > + > +/* CCCH block from frame number */ > +#define L1SAP_FN2CCCHBLOCK(fn) ((fn % 51) / 5 - 1) > + > +/* PTCH layout from frame number */ > +#define L1SAP_FN2MACBLOCK(fn) ((fn % 52) / 4) > +#define L1SAP_FN2PTCCHBLOCK(fn) ((fn / 52) & 7) > +#define L1SAP_IS_PTCCH(fn) ((fn % 52) == 12) > + > +/* subslot from any chan_nr */ > +static inline uint8_t l1sap_chan2ss(uint8_t chan_nr) > +{ > + if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) > + return L1SAP_CHAN2SS_SDCCH8(chan_nr); > + if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) > + return L1SAP_CHAN2SS_SDCCH4(chan_nr); > + if (L1SAP_IS_CHAN_TCHH(chan_nr)) > + return L1SAP_CHAN2SS_TCHH(chan_nr); > + return 0; > +} > + > + > +/* allocate a msgb containing a osmo_phsap_prim + optional l2 data */ > +struct msgb *l1sap_msgb_alloc(unsigned int l2_len); > + > +/* any L1 prim received from bts model */ > +int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); > + > +/* pcu (socket interface) sends us a data request primitive */ > +int l1sap_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn, > + uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len); > + > +/* call-back function for incoming RTP */ > +void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl, > + unsigned int rtp_pl_len); > + > +/* channel control */ > +int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr); > +int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr); > +int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr); > +int l1sap_chan_modify(struct gsm_bts_trx *trx, uint8_t chan_nr); > + > +extern const struct value_string gsmtap_sapi_names[]; > +extern struct gsmtap_inst *gsmtap; > +extern uint32_t gsmtap_sapi_mask; > +extern uint8_t gsmtap_sapi_acch; > + > +#define msgb_l1sap_prim(msg) ((struct osmo_phsap_prim *)(msg)->l1h) > + > +#endif /* L1SAP_H */ > -- > 1.8.1.5 > > -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From alexander.chemeris at gmail.com Sun Oct 6 20:56:15 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sun, 6 Oct 2013 22:56:15 +0200 Subject: [PATCH 03/20] Add BCCH message to PH-/MPH-/TCH-SAP interface In-Reply-To: <1379592710-4811-3-git-send-email-jolly@eversberg.eu> References: <1379592710-4811-1-git-send-email-jolly@eversberg.eu> <1379592710-4811-3-git-send-email-jolly@eversberg.eu> Message-ID: Looks good to me from the code structure perspective. On Thu, Sep 19, 2013 at 2:11 PM, Andreas Eversberg wrote: > This first part moves BCCH message primitives from osmo-bts-sysmo to common > part. A new file "common/l1sap.c" is introduced to implement handling of > layer 1 messages from/to BTS model. > --- > include/osmo-bts/bts_model.h | 2 + > src/common/Makefile.am | 2 +- > src/common/l1sap.c | 150 ++++++++++++++++++++++++++++++++++++++ > src/osmo-bts-sysmo/l1_if.c | 167 +++++++++++++++++++++++++++++++++++++++---- > tests/stubs.c | 2 + > 5 files changed, 310 insertions(+), 13 deletions(-) > create mode 100644 src/common/l1sap.c > > diff --git a/include/osmo-bts/bts_model.h b/include/osmo-bts/bts_model.h > index bfa6bd8..f6545cc 100644 > --- a/include/osmo-bts/bts_model.h > +++ b/include/osmo-bts/bts_model.h > @@ -43,4 +43,6 @@ int bts_model_vty_init(struct gsm_bts *bts); > void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts); > void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx); > > +int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); > + > #endif > diff --git a/src/common/Makefile.am b/src/common/Makefile.am > index b2f6f8e..1c6ff9e 100644 > --- a/src/common/Makefile.am > +++ b/src/common/Makefile.am > @@ -5,4 +5,4 @@ LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS) > noinst_LIBRARIES = libbts.a > libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \ > rsl.c vty.c paging.c measurement.c amr.c lchan.c \ > - load_indication.c pcu_sock.c > + load_indication.c pcu_sock.c l1sap.c > diff --git a/src/common/l1sap.c b/src/common/l1sap.c > new file mode 100644 > index 0000000..f4f3246 > --- /dev/null > +++ b/src/common/l1sap.c > @@ -0,0 +1,150 @@ > +/* L1 SAP primitives */ > + > +/* (C) 2011 by Harald Welte > + * (C) 2013 by Andreas Eversberg > + * > + * All Rights Reserved > + * > + * 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 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 . > + * > + */ > + > +#include > +#include > +#include > +#include > + > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); > + > +static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = { > + 0x03, 0x03, 0x01, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, > + 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, > + 0x2B, 0x2B, 0x2B > +}; > + > +/* allocate a msgb containing a osmo_phsap_prim + optional l2 data > + * in order to wrap femtobts header arround l2 data, there must be enough space > + * in front and behind data pointer */ > +struct msgb *l1sap_msgb_alloc(unsigned int l2_len) > +{ > + struct msgb *msg = msgb_alloc_headroom(512, 128, "l1sap_prim"); > + > + if (!msg) > + return NULL; > + > + msg->l1h = msgb_put(msg, sizeof(struct osmo_phsap_prim)); > + > + return msg; > +} > + > +/* PH-RTS-IND prim recevied from bts model */ > +static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx, > + struct osmo_phsap_prim *l1sap, struct ph_data_param *rts_ind) > +{ > + struct msgb *msg = l1sap->oph.msg; > + struct gsm_time g_time; > + uint8_t chan_nr, link_id; > + uint8_t tn; > + uint32_t fn; > + uint8_t *p, *si; > + > + chan_nr = rts_ind->chan_nr; > + link_id = rts_ind->link_id; > + fn = rts_ind->fn; > + tn = L1SAP_CHAN2TS(chan_nr); > + > + gsm_fn2gsmtime(&g_time, fn); > + > + DEBUGP(DL1P, "Rx PH-RTS.ind %02u/%02u/%02u chan_nr=%d link_id=%d\n", > + g_time.t1, g_time.t2, g_time.t3, chan_nr, link_id); > + > + /* reuse PH-RTS.ind for PH-DATA.req */ > + if (!msg) { > + LOGP(DL1P, LOGL_FATAL, "RTS without msg to be reused. Please " > + "fix!\n"); > + abort(); > + } > + msgb_trim(msg, sizeof(*l1sap)); > + osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, PRIM_OP_REQUEST, > + msg); > + msg->l2h = msg->l1h + sizeof(*l1sap); > + > + if (L1SAP_IS_CHAN_BCCH(chan_nr)) { > + p = msgb_put(msg, GSM_MACBLOCK_LEN); > + /* get them from bts->si_buf[] */ > + si = bts_sysinfo_get(trx->bts, &g_time); > + if (si) > + memcpy(p, si, GSM_MACBLOCK_LEN); > + else > + memcpy(p, fill_frame, GSM_MACBLOCK_LEN); > + } > + > + DEBUGP(DL1P, "Tx PH-DATA.req %02u/%02u/%02u chan_nr=%d link_id=%d\n", > + g_time.t1, g_time.t2, g_time.t3, chan_nr, link_id); > + > + l1sap_down(trx, l1sap); > + > + /* don't free, because we forwarded data */ > + return 1; > +} > + > +/* any L1 prim received from bts model */ > +int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) > +{ > + struct msgb *msg = l1sap->oph.msg; > + int rc = 0; > + > + switch (OSMO_PRIM_HDR(&l1sap->oph)) { > + case OSMO_PRIM(PRIM_PH_RTS, PRIM_OP_INDICATION): > + rc = l1sap_ph_rts_ind(trx, l1sap, &l1sap->u.data); > + break; > + default: > + LOGP(DL1P, LOGL_NOTICE, "unknown prim %d op %d\n", > + l1sap->oph.primitive, l1sap->oph.operation); > + break; > + } > + > + /* Special return value '1' means: do not free */ > + if (rc != 1) > + msgb_free(msg); > + > + return rc; > +} > + > +/* any L1 prim sent to bts model */ > +static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) > +{ > + return bts_model_l1sap_down(trx, l1sap); > +} > + > diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c > index e16bb49..93b4de7 100644 > --- a/src/osmo-bts-sysmo/l1_if.c > +++ b/src/osmo-bts-sysmo/l1_if.c > @@ -47,6 +47,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -366,8 +367,135 @@ static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = { > 0x2B, 0x2B, 0x2B > }; > > +static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, > + struct osmo_phsap_prim *l1sap) > +{ > + struct femtol1_hdl *fl1 = trx_femtol1_hdl(trx); > + uint32_t u32Fn; > + uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi; > + uint8_t chan_nr, link_id; > + GsmL1_Prim_t *l1p; > + int len; > + > + if (!msg) { > + LOGP(DL1C, LOGL_FATAL, "PH-DATA.req without msg. " > + "Please fix!\n"); > + abort(); > + } > + chan_nr = l1sap->u.data.chan_nr; > + link_id = l1sap->u.data.link_id; > + u32Fn = l1sap->u.data.fn; > + u8Tn = L1SAP_CHAN2TS(chan_nr); > + subCh = 0x1f; > + if (L1SAP_IS_CHAN_BCCH(chan_nr)) { > + sapi = GsmL1_Sapi_Bcch; > + } else { > + LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d " > + "chan_nr %d link_id %d\n", l1sap->oph.primitive, > + l1sap->oph.operation, chan_nr, link_id); > + return -EINVAL; > + } > + > + /* pull and trim msg to start of payload */ > + msgb_pull(msg, sizeof(*l1sap)); > + len = msg->len; > + msgb_trim(msg, 0); > + > + /* convert l1sap message to GsmL1 primitive, keep payload */ > + if (len) { > + /* data request */ > + GsmL1_PhDataReq_t *data_req; > + GsmL1_MsgUnitParam_t *msu_param; > + uint8_t *temp; > + > + /* wrap zeroed l1p structure arrount payload > + * this must be done in three steps, since the actual > + * payload is not at the end but inside the l1p structure. */ > + temp = l1p->u.phDataReq.msgUnitParam.u8Buffer; > + msgb_push(msg, temp - (uint8_t *)l1p); > + memset(msg->data, 0, msg->len); > + msgb_put(msg, len); > + memset(msg->tail, 0, sizeof(*l1p) - msg->len); > + msgb_put(msg, sizeof(*l1p) - msg->len); > + msg->l1h = msg->data; > + > + l1p = msgb_l1prim(msg); > + l1p->id = GsmL1_PrimId_PhDataReq; > + data_req = &l1p->u.phDataReq; > + data_req->hLayer1 = fl1->hLayer1; > + data_req->u8Tn = u8Tn; > + data_req->u32Fn = u32Fn; > + data_req->sapi = sapi; > + data_req->subCh = subCh; > + data_req->u8BlockNbr = u8BlockNbr; > + msu_param = &data_req->msgUnitParam; > + msu_param->u8Size = len; > + } else { > + /* empty frame */ > + GsmL1_PhEmptyFrameReq_t *empty_req; > + > + /* put l1p structure */ > + msgb_put(msg, sizeof(*l1p)); > + memset(msg->data, 0, msg->len); > + msg->l1h = msg->data; > + > + l1p = msgb_l1prim(msg); > + l1p->id = GsmL1_PrimId_PhEmptyFrameReq; > + empty_req = &l1p->u.phEmptyFrameReq; > + empty_req->hLayer1 = fl1->hLayer1; > + empty_req->u8Tn = u8Tn; > + empty_req->u32Fn = u32Fn; > + empty_req->sapi = sapi; > + empty_req->subCh = subCh; > + empty_req->u8BlockNbr = u8BlockNbr; > + } > + > + /* send message to DSP's queue */ > + osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], msg); > + > + return 0; > +} > + > +/* primitive from common part */ > +int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) > +{ > + struct msgb *msg = l1sap->oph.msg; > + int rc = 0; > + > + switch (OSMO_PRIM_HDR(&l1sap->oph)) { > + case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): > + rc = ph_data_req(trx, msg, l1sap); > + break; > + default: > + LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d\n", > + l1sap->oph.primitive, l1sap->oph.operation); > + rc = -EINVAL; > + } > + > + if (rc) > + msgb_free(msg); > + return rc; > +} > + > +static uint8_t chan_nr_by_sapi(enum gsm_phys_chan_config pchan, > + GsmL1_Sapi_t sapi, GsmL1_SubCh_t subCh, > + uint8_t u8Tn, uint32_t u32Fn) > +{ > + uint8_t cbits = 0; > + switch (sapi) { > + case GsmL1_Sapi_Bcch: > + cbits = 0x10; > + break; > + default: > + return 0; > + } > + > + return (cbits << 3) | u8Tn; > +} > + > static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, > - GsmL1_PhReadyToSendInd_t *rts_ind) > + GsmL1_PhReadyToSendInd_t *rts_ind, > + struct msgb *l1p_msg) > { > struct gsm_bts_trx *trx = fl1->priv; > struct gsm_bts *bts = trx->bts; > @@ -379,9 +507,31 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, > struct gsm_lchan *lchan; > struct gsm_time g_time; > uint32_t t3p; > - uint8_t *si; > struct osmo_phsap_prim pp; > int rc; > + struct osmo_phsap_prim *l1sap; > + uint8_t chan_nr, link_id; > + uint32_t fn; > + > + > + /* check if primitive should be handled by common part */ > + chan_nr = chan_nr_by_sapi(trx->ts[rts_ind->u8Tn].pchan, rts_ind->sapi, > + rts_ind->subCh, rts_ind->u8Tn, rts_ind->u32Fn); > + if (chan_nr) { > + fn = rts_ind->u32Fn; > + link_id = 0; > + rc = msgb_trim(l1p_msg, sizeof(*l1sap)); > + if (rc < 0) > + MSGB_ABORT(l1p_msg, "No room for primitive\n"); > + l1sap = msgb_l1sap_prim(l1p_msg); > + osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_RTS, > + PRIM_OP_INDICATION, l1p_msg); > + l1sap->u.data.link_id = link_id; > + l1sap->u.data.chan_nr = chan_nr; > + l1sap->u.data.fn = fn; > + > + return l1sap_up(trx, l1sap); > + } > > gsm_fn2gsmtime(&g_time, rts_ind->u32Fn); > > @@ -460,14 +610,6 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, > msu_param->u8Buffer[2] = (g_time.t1 << 7) | (g_time.t2 << 2) | (t3p >> 1); > msu_param->u8Buffer[3] = (t3p & 1); > break; > - case GsmL1_Sapi_Bcch: > - /* get them from bts->si_buf[] */ > - si = bts_sysinfo_get(bts, &g_time); > - if (si) > - memcpy(msu_param->u8Buffer, si, GSM_MACBLOCK_LEN); > - else > - memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN); > - break; > case GsmL1_Sapi_Sacch: > /* resolve the L2 entity using rts_ind->hLayer2 */ > lchan = l1if_hLayer_to_lchan(trx, rts_ind->hLayer2); > @@ -555,6 +697,7 @@ tx: > /* transmit */ > osmo_wqueue_enqueue(&fl1->write_q[MQ_L1_WRITE], resp_msg); > > + msgb_free(l1p_msg); > return 0; > > empty_frame: > @@ -885,8 +1028,8 @@ static int l1if_handle_ind(struct femtol1_hdl *fl1, struct msgb *msg) > case GsmL1_PrimId_PhConnectInd: > break; > case GsmL1_PrimId_PhReadyToSendInd: > - rc = handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd); > - break; > + return handle_ph_readytosend_ind(fl1, &l1p->u.phReadyToSendInd, > + msg); > case GsmL1_PrimId_PhDataInd: > rc = handle_ph_data_ind(fl1, &l1p->u.phDataInd, msg); > break; > diff --git a/tests/stubs.c b/tests/stubs.c > index c46bb4a..64b30c0 100644 > --- a/tests/stubs.c > +++ b/tests/stubs.c > @@ -39,6 +39,8 @@ int bts_model_rsl_mode_modify(struct gsm_lchan *lchan) > { return 0; } > void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl, > unsigned int rtp_pl_len) {} > +int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) > +{ return 0; } > > int l1if_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn, > uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len) > -- > 1.8.1.5 > > -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From alexander.chemeris at gmail.com Sun Oct 6 20:48:53 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sun, 6 Oct 2013 22:48:53 +0200 Subject: [PATCH 04/20] Add RACH message to PH-/MPH-/TCH-SAP interface In-Reply-To: <1379592710-4811-4-git-send-email-jolly@eversberg.eu> References: <1379592710-4811-1-git-send-email-jolly@eversberg.eu> <1379592710-4811-4-git-send-email-jolly@eversberg.eu> Message-ID: On Thu, Sep 19, 2013 at 2:11 PM, Andreas Eversberg wrote: > + lc = &trx->ts[0].lchan[4].lapdm_ch; I would recommend to move "trx->ts[0].lchan[4].lapdm_ch" to a macros and document why do we refer to TS0, lchan 4 here (some references to the would be helpful). Otherwise this patch looks good to me from the code structure perspective. -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From alexander.chemeris at gmail.com Sun Oct 6 20:59:58 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sun, 6 Oct 2013 22:59:58 +0200 Subject: [PATCH 05/20] Add PCH/AGCH message to PH-/MPH-/TCH-SAP interface In-Reply-To: <1379592710-4811-5-git-send-email-jolly@eversberg.eu> References: <1379592710-4811-1-git-send-email-jolly@eversberg.eu> <1379592710-4811-5-git-send-email-jolly@eversberg.eu> Message-ID: Looks good to me from the code structure perspective. On Thu, Sep 19, 2013 at 2:11 PM, Andreas Eversberg wrote: > This part moves PCH and AGCH message primitives from osmo-bts-sysmo to > common part. > --- > src/common/l1sap.c | 17 +++++++++++++++++ > src/osmo-bts-sysmo/l1_if.c | 28 ++++++++++++---------------- > 2 files changed, 29 insertions(+), 16 deletions(-) > > diff --git a/src/common/l1sap.c b/src/common/l1sap.c > index 996a589..16e1af8 100644 > --- a/src/common/l1sap.c > +++ b/src/common/l1sap.c > @@ -108,6 +108,23 @@ static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx, > memcpy(p, si, GSM_MACBLOCK_LEN); > else > memcpy(p, fill_frame, GSM_MACBLOCK_LEN); > + } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { > + p = msgb_put(msg, GSM_MACBLOCK_LEN); > + if (L1SAP_FN2CCCHBLOCK(fn) >= 1) { > + /* PCH */ > + struct gsm_bts_role_bts *btsb = trx->bts->role; > + paging_gen_msg(btsb->paging_state, p, &g_time); > + } else { > + /* AGCH */ > + /* special queue of messages from IMM ASS CMD */ > + struct msgb *amsg = bts_agch_dequeue(trx->bts); > + if (!amsg) > + memcpy(p, fill_frame, GSM_MACBLOCK_LEN); > + else { > + memcpy(p, amsg->data, amsg->len); > + msgb_free(amsg); > + } > + } > } > > DEBUGP(DL1P, "Tx PH-DATA.req %02u/%02u/%02u chan_nr=%d link_id=%d\n", > diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c > index 874ec15..511b466 100644 > --- a/src/osmo-bts-sysmo/l1_if.c > +++ b/src/osmo-bts-sysmo/l1_if.c > @@ -389,6 +389,14 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg, > subCh = 0x1f; > if (L1SAP_IS_CHAN_BCCH(chan_nr)) { > sapi = GsmL1_Sapi_Bcch; > + } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { > + /* The sapi depends on DSP configuration, not > + * on the actual SYSTEM INFORMATION 3. */ > + u8BlockNbr = L1SAP_FN2CCCHBLOCK(u32Fn); > + if (u8BlockNbr >= 1) > + sapi = GsmL1_Sapi_Pch; > + else > + sapi = GsmL1_Sapi_Agch; > } else { > LOGP(DL1C, LOGL_NOTICE, "unknown prim %d op %d " > "chan_nr %d link_id %d\n", l1sap->oph.primitive, > @@ -486,6 +494,10 @@ static uint8_t chan_nr_by_sapi(enum gsm_phys_chan_config pchan, > case GsmL1_Sapi_Bcch: > cbits = 0x10; > break; > + case GsmL1_Sapi_Agch: > + case GsmL1_Sapi_Pch: > + cbits = 0x12; > + break; > default: > return 0; > } > @@ -499,7 +511,6 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, > { > struct gsm_bts_trx *trx = fl1->priv; > struct gsm_bts *bts = trx->bts; > - struct gsm_bts_role_bts *btsb = bts->role; > struct msgb *resp_msg; > GsmL1_PhDataReq_t *data_req; > GsmL1_MsgUnitParam_t *msu_param; > @@ -647,21 +658,6 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1, > msgb_free(pp.oph.msg); > } > break; > - case GsmL1_Sapi_Agch: > - /* special queue of messages from IMM ASS CMD */ > - { > - struct msgb *msg = bts_agch_dequeue(bts); > - if (!msg) > - memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN); > - else { > - memcpy(msu_param->u8Buffer, msg->data, msg->len); > - msgb_free(msg); > - } > - } > - break; > - case GsmL1_Sapi_Pch: > - rc = paging_gen_msg(btsb->paging_state, msu_param->u8Buffer, &g_time); > - break; > case GsmL1_Sapi_TchF: > case GsmL1_Sapi_TchH: > /* only hit in case we have a RTP underflow, as real TCH > -- > 1.8.1.5 > > -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From alexander.chemeris at gmail.com Sun Oct 6 20:57:35 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sun, 6 Oct 2013 22:57:35 +0200 Subject: [PATCH 01/20] sysmo-bts: Use correct boundaries of L1 msg when forwarding to L1 proxy In-Reply-To: <1379592710-4811-1-git-send-email-jolly@eversberg.eu> References: <1379592710-4811-1-git-send-email-jolly@eversberg.eu> Message-ID: Good catch. Using msg->head is a fragile business. On Thu, Sep 19, 2013 at 2:11 PM, Andreas Eversberg wrote: > In case of a headroom in a message, the 'head' pointer will not point to > the actual data. > --- > src/osmo-bts-sysmo/l1_transp_fwd.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/src/osmo-bts-sysmo/l1_transp_fwd.c b/src/osmo-bts-sysmo/l1_transp_fwd.c > index 5050705..87c230b 100644 > --- a/src/osmo-bts-sysmo/l1_transp_fwd.c > +++ b/src/osmo-bts-sysmo/l1_transp_fwd.c > @@ -95,7 +95,7 @@ static int fwd_read_cb(struct osmo_fd *ofd) > static int prim_write_cb(struct osmo_fd *ofd, struct msgb *msg) > { > /* write to the fd */ > - return write(ofd->fd, msg->head, msg->len); > + return write(ofd->fd, msg->l1h, msgb_l1len(msg)); > } > > int l1if_transport_open(int q, struct femtol1_hdl *fl1h) > -- > 1.8.1.5 > > -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From jerlbeck at sysmocom.de Tue Oct 1 11:26:42 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 1 Oct 2013 13:26:42 +0200 Subject: [PATCH] bsc: Add control command to set timezone Message-ID: <1380626803-32530-1-git-send-email-jerlbeck@sysmocom.de> This adds a per BTS control command 'timezone' which expects a value of the format ',,' or 'off' to set the value of bts->tz. It has the same functionality like the existing VTY command 'timezone' in network/bts. Sponsored-by: On-Waves ehf Ticket: OW#978 --- openbsc/src/osmo-bsc/osmo_bsc_ctrl.c | 113 ++++++++++++++++++++++++++++++++++ openbsc/tests/ctrl_test_runner.py | 26 ++++++++ 2 files changed, 139 insertions(+) diff --git a/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c b/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c index 39859d6..42f4672 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c @@ -376,6 +376,116 @@ err: return 1; } +CTRL_CMD_DEFINE(bts_timezone, "timezone"); +static int get_bts_timezone(struct ctrl_cmd *cmd, void *data) +{ + struct gsm_bts *bts = (struct gsm_bts *) cmd->node; + if (!bts) { + cmd->reply = "bts not found."; + return CTRL_CMD_ERROR; + } + + if (bts->tz.override) + cmd->reply = talloc_asprintf(cmd, "%d,%d,%d", + bts->tz.hr, bts->tz.mn, bts->tz.dst); + else + cmd->reply = talloc_asprintf(cmd, "off"); + + if (!cmd->reply) { + cmd->reply = "OOM"; + return CTRL_CMD_ERROR; + } + + return CTRL_CMD_REPLY; +} + +static int set_bts_timezone(struct ctrl_cmd *cmd, void *data) +{ + char *saveptr, *hourstr, *minstr, *dststr, *tmp = 0; + int override; + struct gsm_bts *bts = (struct gsm_bts *) cmd->node; + if (!bts) { + cmd->reply = "bts not found."; + return CTRL_CMD_ERROR; + } + + tmp = talloc_strdup(cmd, cmd->value); + if (!tmp) + goto oom; + + hourstr = strtok_r(tmp, ",", &saveptr); + minstr = strtok_r(NULL, ",", &saveptr); + dststr = strtok_r(NULL, ",", &saveptr); + + override = 0; + + if (hourstr != NULL) + override = strcasecmp(hourstr, "off") != 0; + + bts->tz.override = override; + + if (override) { + bts->tz.hr = hourstr ? atol(hourstr) : 0; + bts->tz.mn = minstr ? atol(minstr) : 0; + bts->tz.dst = dststr ? atol(dststr) : 0; + } + + talloc_free(tmp); + tmp = NULL; + + return get_bts_timezone(cmd, data); + +oom: + cmd->reply = "OOM"; + return CTRL_CMD_ERROR; +} + +static int verify_bts_timezone(struct ctrl_cmd *cmd, const char *value, void *data) +{ + char *saveptr, *hourstr, *minstr, *dststr, *tmp; + time_t tstamp; + int valid; + int override, tz_hours, tz_mins, tz_dst; + + tmp = talloc_strdup(cmd, value); + if (!tmp) + return 1; + + hourstr = strtok_r(tmp, ",", &saveptr); + minstr = strtok_r(NULL, ",", &saveptr); + dststr = strtok_r(NULL, ",", &saveptr); + + if (hourstr == NULL) + goto err; + + override = strcasecmp(hourstr, "off") != 0; + + if (! override) + return 0; + + if (minstr == NULL || dststr == NULL) + goto err; + + tz_hours = atol(hourstr); + tz_mins = atol(minstr); + tz_dst = atol(dststr); + + talloc_free(tmp); + tmp = NULL; + + if ((tz_hours < -19) || (tz_hours > 19) || + (tz_mins < 0) || (tz_mins >= 60) || (tz_mins % 15 != 0) || + (tz_dst < 0) || (tz_dst > 2)) + goto err; + + return 0; + +err: + talloc_free(tmp); + cmd->reply = talloc_strdup(cmd, "The format is ,, or 'off' where -19 <= hours <= 19, mins in {0, 15, 30, 45}, and 0 <= dst <= 2"); + return 1; +} + CTRL_CMD_DEFINE(bts_rf_state, "rf_state"); static int get_bts_rf_state(struct ctrl_cmd *cmd, void *data) { @@ -495,6 +605,9 @@ int bsc_ctrl_cmds_install(struct gsm_network *net) rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_loc); if (rc) goto end; + rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_timezone); + if (rc) + goto end; rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_rf_lock); if (rc) goto end; diff --git a/openbsc/tests/ctrl_test_runner.py b/openbsc/tests/ctrl_test_runner.py index dfdec40..306722b 100644 --- a/openbsc/tests/ctrl_test_runner.py +++ b/openbsc/tests/ctrl_test_runner.py @@ -201,6 +201,32 @@ class TestCtrlBSC(TestCtrlBase): self.assertEquals(r['var'], 'bts.0.rf_state') self.assertEquals(r['value'], 'inoperational,unlocked,on') + def testTimezone(self): + r = self.do_get('bts.0.timezone') + self.assertEquals(r['mtype'], 'GET_REPLY') + self.assertEquals(r['var'], 'bts.0.timezone') + self.assertEquals(r['value'], 'off') + + r = self.do_set('bts.0.timezone', '-2,15,2') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'bts.0.timezone') + self.assertEquals(r['value'], '-2,15,2') + + r = self.do_get('bts.0.timezone') + self.assertEquals(r['mtype'], 'GET_REPLY') + self.assertEquals(r['var'], 'bts.0.timezone') + self.assertEquals(r['value'], '-2,15,2') + + r = self.do_set('bts.0.timezone', 'off') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'bts.0.timezone') + self.assertEquals(r['value'], 'off') + + r = self.do_get('bts.0.timezone') + self.assertEquals(r['mtype'], 'GET_REPLY') + self.assertEquals(r['var'], 'bts.0.timezone') + self.assertEquals(r['value'], 'off') + def add_bsc_test(suite, workdir): if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc/osmo-bsc")): print("Skipping the BSC test") -- 1.7.9.5 From holger at freyther.de Tue Oct 1 15:18:37 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 1 Oct 2013 17:18:37 +0200 Subject: [PATCH] bsc: Add control command to set timezone In-Reply-To: <1380626803-32530-1-git-send-email-jerlbeck@sysmocom.de> References: <1380626803-32530-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <20131001151837.GA6056@xiaoyu.lan> On Tue, Oct 01, 2013 at 01:26:42PM +0200, Jacob Erlbeck wrote: Dear Jacob, thank you for the patch. > + struct gsm_bts *bts = (struct gsm_bts *) cmd->node; > + if (!bts) { I added an empty line between the two > + if (! override) > + return 0; I removed the extrap space and added a talloc_free(tmp); > + > + r = self.do_set('bts.0.timezone', '-2,15,2') > + self.assertEquals(r['mtype'], 'SET_REPLY') > + self.assertEquals(r['var'], 'bts.0.timezone') > + self.assertEquals(r['value'], '-2,15,2') I added two commands with invalid input.. one with longer input (where the extra data is just ignored) and one with a shorter one. applying it now and push it to master (then backport) From peter at stuge.se Tue Oct 1 21:00:32 2013 From: peter at stuge.se (Peter Stuge) Date: Tue, 1 Oct 2013 23:00:32 +0200 Subject: [PATCH] bsc: Add control command to set timezone In-Reply-To: <1380626803-32530-1-git-send-email-jerlbeck@sysmocom.de> References: <1380626803-32530-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <20131001210032.5203.qmail@stuge.se> Jacob Erlbeck wrote: > + if ((tz_hours < -19) || (tz_hours > 19) || > + (tz_mins < 0) || (tz_mins >= 60) || (tz_mins % 15 != 0) || > + (tz_dst < 0) || (tz_dst > 2)) > + goto err; No need for all these parentheses, but oh well. More importantly - are you sure that daylight savings is only ever 0, 1 or 2 hours? I seem to remember that this isn't true for some odd place, but unfortunately I don't remember where, so this would need a bit of research.. :\ //Peter From jerlbeck at sysmocom.de Wed Oct 2 08:22:55 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Wed, 02 Oct 2013 10:22:55 +0200 Subject: [PATCH] bsc: Add control command to set timezone In-Reply-To: <20131001210032.5203.qmail@stuge.se> References: <1380626803-32530-1-git-send-email-jerlbeck@sysmocom.de> <20131001210032.5203.qmail@stuge.se> Message-ID: <524BD7DF.7040403@sysmocom.de> On 10/01/2013 11:00 PM, Peter Stuge wrote: > Jacob Erlbeck wrote: >> + if ((tz_hours < -19) || (tz_hours > 19) || >> + (tz_mins < 0) || (tz_mins >= 60) || (tz_mins % 15 != 0) || >> + (tz_dst < 0) || (tz_dst > 2)) >> + goto err; > > No need for all these parentheses, but oh well. It's at least consistent to the style already present in that file. > > More importantly - are you sure that daylight savings is only ever 0, > 1 or 2 hours? I seem to remember that this isn't true for some odd > place, but unfortunately I don't remember where, so this would need > a bit of research.. :\ That reflects the possible values for the "Daylight Saving Time" information element being described in 3GPP TS 24.008, 10.5.3.12. So even if there were countries with e.g. 3 hours DST we couldn't encode it: Daylight Saving Time value (octet 3) Bits 2 1 0 0 No adjustment for Daylight Saving Time 0 1 +1 hour adjustment for Daylight Saving Time 1 0 +2 hours adjustment for Daylight Saving Time 1 1 Reserved (Quoted from Table 10.5.97a/3GPP TS 24.008) Jacob From peter at stuge.se Wed Oct 2 10:15:06 2013 From: peter at stuge.se (Peter Stuge) Date: Wed, 2 Oct 2013 12:15:06 +0200 Subject: [PATCH] bsc: Add control command to set timezone In-Reply-To: <524BD7DF.7040403@sysmocom.de> References: <1380626803-32530-1-git-send-email-jerlbeck@sysmocom.de> <20131001210032.5203.qmail@stuge.se> <524BD7DF.7040403@sysmocom.de> Message-ID: <20131002101506.29589.qmail@stuge.se> Jacob Erlbeck wrote: > > are you sure that daylight savings is only ever 0, 1 or 2 hours? > > That reflects the possible values for the "Daylight Saving Time" > information element being described in 3GPP TS 24.008, 10.5.3.12. Ah - thanks for the clarification! //Peter From maicon.kist at inf.ufrgs.br Thu Oct 3 19:59:02 2013 From: maicon.kist at inf.ufrgs.br (Maicon Kist) Date: Thu, 3 Oct 2013 16:59:02 -0300 Subject: How use TCAP instead of DTAP? Message-ID: <0D465FF4-1FE7-4958-9C71-5E521B75E762@inf.ufrgs.br> Hi list, I want to integrate the OpenBSC with the Mobicents gateway. However, OpenBSC encapsulates the GSM MAP protocol in a DTAP header, while Mobicents expects a TCAP. The question is: Is possible to use the TCAP protocol in OpenBSC ? PS: Currently I am working with the USSD in OpenBSC. I performed some changes in the code and now we implemented the USSD request,facility and release-complete messages. In other words, now we are able to implement menus in USSD operations. Best Regards From alexander.chemeris at gmail.com Fri Oct 4 00:42:23 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 02:42:23 +0200 Subject: [PATCH 0/6] Four minor fixes, "subscriber create" and subscriber's info formatting. Message-ID: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> This patch set is mostly minor fixes and clean ups, with the exception of the last two patches ("subscriber create" VTY command and a standard way for printing a subscriber's info). I would appreciate merging this patches to master, as I'm working onmore code which depends on them. Alexander Chemeris (6): Fix copy-paste error in console output in db_test. Fix typo ',' -> ';' at the end of a line. Fix typo in console output: "PEROIDOC" -> "PERIODIC". Slight clean up of the code in gsm340_rx_tpdu() and a fix for an unlikely, but possible memory leak there. Add "subscriber create" VTY command. Introduce a standard way for printing a subscriber's info. openbsc/include/openbsc/gsm_subscriber.h | 4 ++++ openbsc/src/libmsc/db.c | 2 +- openbsc/src/libmsc/gsm_04_08.c | 2 +- openbsc/src/libmsc/gsm_04_11.c | 7 ++++--- openbsc/src/libmsc/vty_interface_layer3.c | 27 +++++++++++++++++++++++++++ openbsc/tests/db/db_test.c | 2 +- 6 files changed, 38 insertions(+), 6 deletions(-) -- 1.7.9.5 From alexander.chemeris at gmail.com Fri Oct 4 00:42:24 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 02:42:24 +0200 Subject: [PATCH 1/6] Fix copy-paste error in console output in db_test. In-Reply-To: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1380847349-22891-2-git-send-email-Alexander.Chemeris@gmail.com> --- openbsc/tests/db/db_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index c0ee618..c3beee2 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -54,7 +54,7 @@ static struct gsm_network dummy_net; printf("names do not match in %s:%d '%s' '%s'\n", \ __FUNCTION__, __LINE__, original->name, copy->name); \ if (strcmp(original->extension, copy->extension) != 0) \ - printf("names do not match in %s:%d '%s' '%s'\n", \ + printf("Extensions do not match in %s:%d '%s' '%s'\n", \ __FUNCTION__, __LINE__, original->extension, copy->extension); \ int main() -- 1.7.9.5 From alexander.chemeris at gmail.com Fri Oct 4 00:42:25 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 02:42:25 +0200 Subject: [PATCH 2/6] Fix typo ',' -> ';' at the end of a line. In-Reply-To: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1380847349-22891-3-git-send-email-Alexander.Chemeris@gmail.com> Funny, this is a correct C expression and doesn't change execution, thus it stayed unnoticed for quite a while. --- openbsc/src/libmsc/db.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 4e20e23..12d60bb 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -996,7 +996,7 @@ int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char imei[GSM_IM dbi_result result; strncpy(subscriber->equipment.imei, imei, - sizeof(subscriber->equipment.imei)-1), + sizeof(subscriber->equipment.imei)-1); result = dbi_conn_queryf(conn, "INSERT OR IGNORE INTO Equipment " -- 1.7.9.5 From alexander.chemeris at gmail.com Fri Oct 4 00:42:26 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 02:42:26 +0200 Subject: [PATCH 3/6] Fix typo in console output: "PEROIDOC" -> "PERIODIC". In-Reply-To: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1380847349-22891-4-git-send-email-Alexander.Chemeris@gmail.com> --- openbsc/src/libmsc/gsm_04_08.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index cd31f69..f771b02 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -513,7 +513,7 @@ static const char *lupd_name(uint8_t type) case GSM48_LUPD_NORMAL: return "NORMAL"; case GSM48_LUPD_PERIODIC: - return "PEROIDOC"; + return "PERIODIC"; case GSM48_LUPD_IMSI_ATT: return "IMSI ATTACH"; default: -- 1.7.9.5 From alexander.chemeris at gmail.com Fri Oct 4 00:42:27 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 02:42:27 +0200 Subject: [PATCH 4/6] Slight clean up of the code in gsm340_rx_tpdu() and a fix for an unlikely, but possible memory leak there. In-Reply-To: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1380847349-22891-5-git-send-email-Alexander.Chemeris@gmail.com> --- openbsc/src/libmsc/gsm_04_11.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c index 2fc250b..e554b74 100644 --- a/openbsc/src/libmsc/gsm_04_11.c +++ b/openbsc/src/libmsc/gsm_04_11.c @@ -337,8 +337,8 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme); if (sms_alphabet == 0xffffffff) { - sms_free(gsms); - return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER; + rc = GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER; + goto out; } switch (sms_vpf) { @@ -359,7 +359,8 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m default: LOGP(DLSMS, LOGL_NOTICE, "SMS Validity period not implemented: 0x%02x\n", sms_vpf); - return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER; + rc = GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER; + goto out; } gsms->user_data_len = *smsp++; if (gsms->user_data_len) { -- 1.7.9.5 From alexander.chemeris at gmail.com Fri Oct 4 00:42:28 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 02:42:28 +0200 Subject: [PATCH 5/6] Add "subscriber create" VTY command. In-Reply-To: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1380847349-22891-6-git-send-email-Alexander.Chemeris@gmail.com> It may be useful in production, but it's really required for VTY testing of subscriber related commands. --- openbsc/src/libmsc/vty_interface_layer3.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c index 8dc2812..dd657fb 100644 --- a/openbsc/src/libmsc/vty_interface_layer3.c +++ b/openbsc/src/libmsc/vty_interface_layer3.c @@ -210,6 +210,32 @@ DEFUN(show_subscr, return CMD_SUCCESS; } +DEFUN(subscriber_create, + subscriber_create_cmd, + "subscriber create imsi ID", + "Operations on a Subscriber\n" \ + "Create new subscriber\n" \ + "Identify the subscriber by his IMSI\n" \ + "Identifier for the subscriber\n") +{ + struct gsm_network *gsmnet = gsmnet_from_vty(vty); + struct gsm_subscriber *subscr; + + subscr = db_create_subscriber(gsmnet, argv[0]); + if (!subscr) { + vty_out(vty, "%% No subscriber created for IMSI %s%s", + argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + /* Show info about the created subscriber. */ + subscr_dump_full_vty(vty, subscr, 0); + + subscr_put(subscr); + + return CMD_SUCCESS; +} + DEFUN(subscriber_send_pending_sms, subscriber_send_pending_sms_cmd, "subscriber " SUBSCR_TYPES " ID sms pending-send", @@ -934,6 +960,7 @@ int bsc_vty_init_extra(void) install_element_ve(&sms_send_pend_cmd); + install_element_ve(&subscriber_create_cmd); install_element_ve(&subscriber_send_sms_cmd); install_element_ve(&subscriber_silent_sms_cmd); install_element_ve(&subscriber_silent_call_start_cmd); -- 1.7.9.5 From holger at freyther.de Fri Oct 4 06:22:40 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Fri, 4 Oct 2013 08:22:40 +0200 Subject: [PATCH 5/6] Add "subscriber create" VTY command. In-Reply-To: <1380847349-22891-6-git-send-email-Alexander.Chemeris@gmail.com> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> <1380847349-22891-6-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <20131004062240.GF11013@xiaoyu.lan> On Fri, Oct 04, 2013 at 02:42:28AM +0200, Alexander Chemeris wrote: > It may be useful in production, but it's really required for VTY testing of > subscriber related commands. Hi, nice patch. Please create a VTY unit test for this. holger From alexander.chemeris at gmail.com Fri Oct 4 10:34:31 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 06:34:31 -0400 Subject: [PATCH 5/6] Add "subscriber create" VTY command. In-Reply-To: <20131004062240.GF11013@xiaoyu.lan> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> <1380847349-22891-6-git-send-email-Alexander.Chemeris@gmail.com> <20131004062240.GF11013@xiaoyu.lan> Message-ID: On Fri, Oct 4, 2013 at 2:22 AM, Holger Hans Peter Freyther wrote: > > On Fri, Oct 04, 2013 at 02:42:28AM +0200, Alexander Chemeris wrote: > > It may be useful in production, but it's really required for VTY testing of > > subscriber related commands. > > nice patch. Please create a VTY unit test for this. Yeah, I was thinking about that, but haven't come up with a good set of things to do. What would you propose to test in the VTY test here? The only thing I could think of is issuing "subscriber create" and then "show subscriber" and checking that they show the same. Btw, what do you think about having "subscriber show" command as a alias for "show subscriber" command? -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From holger at freyther.de Fri Oct 4 11:25:24 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Fri, 4 Oct 2013 13:25:24 +0200 Subject: [PATCH 5/6] Add "subscriber create" VTY command. In-Reply-To: References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> <1380847349-22891-6-git-send-email-Alexander.Chemeris@gmail.com> <20131004062240.GF11013@xiaoyu.lan> Message-ID: <20131004112524.GI11013@xiaoyu.lan> On Fri, Oct 04, 2013 at 06:34:31AM -0400, Alexander Chemeris wrote: > Yeah, I was thinking about that, but haven't come up with a good set > of things to do. What would you propose to test in the VTY test here? > The only thing I could think of is issuing "subscriber create" and > then "show subscriber" and checking that they show the same. yes, that is all. show subscriber imsi 12345.. see that it fails, create the subscriber, do the show again and see it is working. From alexander.chemeris at gmail.com Fri Oct 4 12:41:07 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 14:41:07 +0200 Subject: [PATCH 5/6] Add "subscriber create" VTY command. In-Reply-To: <20131004112524.GI11013@xiaoyu.lan> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> <1380847349-22891-6-git-send-email-Alexander.Chemeris@gmail.com> <20131004062240.GF11013@xiaoyu.lan> <20131004112524.GI11013@xiaoyu.lan> Message-ID: On Fri, Oct 4, 2013 at 1:25 PM, Holger Hans Peter Freyther wrote: > On Fri, Oct 04, 2013 at 06:34:31AM -0400, Alexander Chemeris wrote: > >> Yeah, I was thinking about that, but haven't come up with a good set >> of things to do. What would you propose to test in the VTY test here? >> The only thing I could think of is issuing "subscriber create" and >> then "show subscriber" and checking that they show the same. > > yes, that is all. show subscriber imsi 12345.. see that it fails, > create the subscriber, do the show again and see it is working. Ok, sounds good, I'll do that. -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From alexander.chemeris at gmail.com Fri Oct 4 00:42:29 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 02:42:29 +0200 Subject: [PATCH 6/6] Introduce a standard way for printing a subscriber's info. In-Reply-To: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1380847349-22891-7-git-send-email-Alexander.Chemeris@gmail.com> The intention is to standardize subscriber identification output in log files. At this moment we sometimes identify subscriber by id, sometimes by extension, sometimes by IMSI and sometimes do not idenify at all. This makes log analysis hard or impossible. This patch doesn't touch actual log output, as it's a separate thing and requires consideration before checking in. --- openbsc/include/openbsc/gsm_subscriber.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index 78f9710..f21b3e6 100644 --- a/openbsc/include/openbsc/gsm_subscriber.h +++ b/openbsc/include/openbsc/gsm_subscriber.h @@ -15,6 +15,10 @@ #define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001 #define tmsi_from_string(str) strtoul(str, NULL, 10) +#define GSM_SUBS_FMT_STR "IMSI %s (id %llu, ext %s%s%s)" +#define GSM_SUBS_FMT_VAL(x) (x)->imsi, (x)->id, (x)->extension, \ + strlen((x)->name)?", name ":"", strlen((x)->name)?(x)->name:"" + struct vty; struct gsm_equipment { -- 1.7.9.5 From holger at freyther.de Fri Oct 4 06:17:17 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Fri, 4 Oct 2013 08:17:17 +0200 Subject: [PATCH 6/6] Introduce a standard way for printing a subscriber's info. In-Reply-To: <1380847349-22891-7-git-send-email-Alexander.Chemeris@gmail.com> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> <1380847349-22891-7-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <20131004061717.GE11013@xiaoyu.lan> On Fri, Oct 04, 2013 at 02:42:29AM +0200, Alexander Chemeris wrote: > This patch doesn't touch actual log output, as it's a separate thing and > requires consideration before checking in. I will merge this once there is an user. From alexander.chemeris at gmail.com Fri Oct 4 10:48:36 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 12:48:36 +0200 Subject: [PATCH 6/6] Introduce a standard way for printing a subscriber's info. In-Reply-To: <20131004061717.GE11013@xiaoyu.lan> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> <1380847349-22891-7-git-send-email-Alexander.Chemeris@gmail.com> <20131004061717.GE11013@xiaoyu.lan> Message-ID: On Fri, Oct 4, 2013 at 8:17 AM, Holger Hans Peter Freyther wrote: > On Fri, Oct 04, 2013 at 02:42:29AM +0200, Alexander Chemeris wrote: > >> This patch doesn't touch actual log output, as it's a separate thing and >> requires consideration before checking in. > > I will merge this once there is an user. Ok, I'll re-submit this as a part of another series of patches. I wanted to get some review before I start using this widely. -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From vamposdecampos at gmail.com Fri Oct 4 06:58:20 2013 From: vamposdecampos at gmail.com (Alex Badea) Date: Fri, 4 Oct 2013 09:58:20 +0300 Subject: [PATCH 6/6] Introduce a standard way for printing a subscriber's info. In-Reply-To: <1380847349-22891-7-git-send-email-Alexander.Chemeris@gmail.com> References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> <1380847349-22891-7-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: Hi, Two cents: On Fri, Oct 4, 2013 at 3:42 AM, Alexander Chemeris wrote: > +#define GSM_SUBS_FMT_STR "IMSI %s (id %llu, ext %s%s%s)" > +#define GSM_SUBS_FMT_VAL(x) (x)->imsi, (x)->id, (x)->extension, \ > + strlen((x)->name)?", name ":"", strlen((x)->name)?(x)->name:"" Checking for an empty string might be done by testing *s or s[0] instead of strlen(s). Also the second check for an empty string is superfluous, since it'll print the same either way. So one might write that as: #define GSM_SUBS_FMT_VAL(x) (x)->imsi, (x)->id, (x)->extension, \ (x)->name[0] ? ", name " : "", (x)->name Cheers, Alex From alexander.chemeris at gmail.com Fri Oct 4 10:46:40 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 12:46:40 +0200 Subject: [PATCH 6/6] Introduce a standard way for printing a subscriber's info. In-Reply-To: References: <1380847349-22891-1-git-send-email-Alexander.Chemeris@gmail.com> <1380847349-22891-7-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: Alex, On Fri, Oct 4, 2013 at 8:58 AM, Alex Badea wrote: > On Fri, Oct 4, 2013 at 3:42 AM, Alexander Chemeris > wrote: >> +#define GSM_SUBS_FMT_STR "IMSI %s (id %llu, ext %s%s%s)" >> +#define GSM_SUBS_FMT_VAL(x) (x)->imsi, (x)->id, (x)->extension, \ >> + strlen((x)->name)?", name ":"", strlen((x)->name)?(x)->name:"" > > Checking for an empty string might be done by testing *s or s[0] > instead of strlen(s). I was thinking about this and decided for strlen(), because it's more human readable. But on the second look I think s[0] is not too bad. Thank you for bringing this up. > Also the second check for an empty string is superfluous, since it'll > print the same either way. Good catch, thanks. > So one might write that as: > > #define GSM_SUBS_FMT_VAL(x) (x)->imsi, (x)->id, (x)->extension, \ > (x)->name[0] ? ", name " : "", (x)->name I'll use this for the second iteration of the patch. -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From dchardware at gmail.com Fri Oct 4 11:32:07 2013 From: dchardware at gmail.com (Sipos Csaba) Date: Fri, 4 Oct 2013 13:32:07 +0200 Subject: E1 card oscillator replace, timing accuracy problem In-Reply-To: References: Message-ID: <384569425.20131004133207@freemail.hu> Hi Guys, I am working with Nokia InSite and MetroSite units and now it is obvious, that I have a timing accuracy problem with my E1 dahdi card. According to "dahdi_test" I have a magnitude worse accuracy compared to the GSM specs. I can measure 99.995% accuracy compared to the required 99.99975%. MY question is what can I do about it? My first idea was to replace the oscillator on the card, which by default has a 20ppm oscillator on it. I was able to find some 10ppm oscillators but they are not matching the required frequency (8.192MHz). It would be nice to hear some ideas about how can I solve this issue. Thanks! BR, Csaba From alexander.chemeris at gmail.com Fri Oct 4 21:54:17 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 4 Oct 2013 23:54:17 +0200 Subject: [PATCH] Add "subscriber create" VTY command. Message-ID: <1380923657-9269-1-git-send-email-Alexander.Chemeris@gmail.com> It may be useful in production, but it's really required for VTY testing of subscriber related commands. --- openbsc/src/libmsc/vty_interface_layer3.c | 27 +++++++++++++++++++++++++++ openbsc/tests/vty_test_runner.py | 16 ++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c index 19c78ea..acb4af7 100644 --- a/openbsc/src/libmsc/vty_interface_layer3.c +++ b/openbsc/src/libmsc/vty_interface_layer3.c @@ -218,6 +218,32 @@ DEFUN(show_subscr, return CMD_SUCCESS; } +DEFUN(subscriber_create, + subscriber_create_cmd, + "subscriber create imsi ID", + "Operations on a Subscriber\n" \ + "Create new subscriber\n" \ + "Identify the subscriber by his IMSI\n" \ + "Identifier for the subscriber\n") +{ + struct gsm_network *gsmnet = gsmnet_from_vty(vty); + struct gsm_subscriber *subscr; + + subscr = db_create_subscriber(gsmnet, argv[0]); + if (!subscr) { + vty_out(vty, "%% No subscriber created for IMSI %s%s", + argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + /* Show info about the created subscriber. */ + subscr_dump_full_vty(vty, subscr, 0); + + subscr_put(subscr); + + return CMD_SUCCESS; +} + DEFUN(subscriber_send_pending_sms, subscriber_send_pending_sms_cmd, "subscriber " SUBSCR_TYPES " ID sms pending-send", @@ -949,6 +975,7 @@ int bsc_vty_init_extra(void) install_element_ve(&sms_send_pend_cmd); + install_element_ve(&subscriber_create_cmd); install_element_ve(&subscriber_send_sms_cmd); install_element_ve(&subscriber_silent_sms_cmd); install_element_ve(&subscriber_silent_call_start_cmd); diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 3bb7bd8..0bd7972 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -215,6 +215,22 @@ class TestVTYNITB(TestVTYGenericBSC): if classNum != 10: self.assertEquals(res.find("rach access-control-class " + str(classNum) + " barred"), -1) + def testSubscriberCreate(self): + self.vty.enable() + + imsi = "204300854013739" + + # Initially we don't have this subscriber + self.vty.verify('show subscriber imsi '+imsi, ['% No subscriber found for imsi '+imsi]) + + # Lets create one + res = self.vty.command('subscriber create imsi '+imsi) + self.assert_(res.find(" IMSI: "+imsi) > 0) + + # Now we have it + res = self.vty.command('show subscriber imsi '+imsi) + self.assert_(res.find(" IMSI: "+imsi) > 0) + class TestVTYBSC(TestVTYGenericBSC): def vty_command(self): -- 1.7.9.5 From alexander.chemeris at gmail.com Sat Oct 5 10:16:07 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sat, 5 Oct 2013 12:16:07 +0200 Subject: [PATCH] db: Add more tests for retrieving subscribers from a DB and avoid NULL dereference when something goes wrong in tests. Message-ID: <1380968167-12568-1-git-send-email-Alexander.Chemeris@gmail.com> --- openbsc/tests/db/db_test.c | 95 ++++++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index c3beee2..a4259ab 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -26,39 +26,52 @@ #include #include #include +#include static struct gsm_network dummy_net; #define SUBSCR_PUT(sub) \ - sub->net = &dummy_net; \ - subscr_put(sub); + if (sub) { \ + sub->net = &dummy_net; \ + subscr_put(sub); \ + } #define COMPARE(original, copy) \ - if (original->id != copy->id) \ - printf("Ids do not match in %s:%d %llu %llu\n", \ - __FUNCTION__, __LINE__, original->id, copy->id); \ - if (original->lac != copy->lac) \ - printf("LAC do not match in %s:%d %d %d\n", \ - __FUNCTION__, __LINE__, original->lac, copy->lac); \ - if (original->authorized != copy->authorized) \ - printf("Authorize do not match in %s:%d %d %d\n", \ - __FUNCTION__, __LINE__, original->authorized, \ - copy->authorized); \ - if (strcmp(original->imsi, copy->imsi) != 0) \ - printf("IMSIs do not match in %s:%d '%s' '%s'\n", \ - __FUNCTION__, __LINE__, original->imsi, copy->imsi); \ - if (original->tmsi != copy->tmsi) \ - printf("TMSIs do not match in %s:%d '%u' '%u'\n", \ - __FUNCTION__, __LINE__, original->tmsi, copy->tmsi); \ - if (strcmp(original->name, copy->name) != 0) \ - printf("names do not match in %s:%d '%s' '%s'\n", \ - __FUNCTION__, __LINE__, original->name, copy->name); \ - if (strcmp(original->extension, copy->extension) != 0) \ - printf("Extensions do not match in %s:%d '%s' '%s'\n", \ - __FUNCTION__, __LINE__, original->extension, copy->extension); \ + if (!original) \ + printf("NULL original in %s:%d\n", \ + __FUNCTION__, __LINE__); \ + if (!copy) \ + printf("NULL copy in %s:%d\n", \ + __FUNCTION__, __LINE__); \ + if (original && copy) { \ + if (original->id != copy->id) \ + printf("Ids do not match in %s:%d %llu %llu\n", \ + __FUNCTION__, __LINE__, original->id, copy->id); \ + if (original->lac != copy->lac) \ + printf("LAC do not match in %s:%d %d %d\n", \ + __FUNCTION__, __LINE__, original->lac, copy->lac); \ + if (original->authorized != copy->authorized) \ + printf("Authorize do not match in %s:%d %d %d\n", \ + __FUNCTION__, __LINE__, original->authorized, \ + copy->authorized); \ + if (strcmp(original->imsi, copy->imsi) != 0) \ + printf("IMSIs do not match in %s:%d '%s' '%s'\n", \ + __FUNCTION__, __LINE__, original->imsi, copy->imsi); \ + if (original->tmsi != copy->tmsi) \ + printf("TMSIs do not match in %s:%d '%u' '%u'\n", \ + __FUNCTION__, __LINE__, original->tmsi, copy->tmsi); \ + if (strcmp(original->name, copy->name) != 0) \ + printf("names do not match in %s:%d '%s' '%s'\n", \ + __FUNCTION__, __LINE__, original->name, copy->name); \ + if (strcmp(original->extension, copy->extension) != 0) \ + printf("Extensions do not match in %s:%d '%s' '%s'\n", \ + __FUNCTION__, __LINE__, original->extension, copy->extension); \ + } int main() { + char scratch_str[256]; + printf("Testing subscriber database code.\n"); osmo_init_logging(&log_info); @@ -91,10 +104,25 @@ int main() db_subscriber_alloc_tmsi(alice); alice->lac=42; db_sync_subscriber(alice); + /* Get by TMSI */ + snprintf(scratch_str, sizeof(scratch_str), "%"PRIu32, alice->tmsi); + alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_TMSI, scratch_str); + COMPARE(alice, alice_db); + SUBSCR_PUT(alice_db); + /* Get by IMSI */ alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice_imsi); COMPARE(alice, alice_db); - SUBSCR_PUT(alice); SUBSCR_PUT(alice_db); + /* Get by id */ + snprintf(scratch_str, sizeof(scratch_str), "%llu", alice->id); + alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_ID, scratch_str); + COMPARE(alice, alice_db); + SUBSCR_PUT(alice_db); + /* Get by extension */ + alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_EXTENSION, alice->extension); + COMPARE(alice, alice_db); + SUBSCR_PUT(alice_db); + SUBSCR_PUT(alice); alice_imsi = "9993245423445"; alice = db_create_subscriber(NULL, alice_imsi); @@ -103,10 +131,25 @@ int main() db_sync_subscriber(alice); db_subscriber_assoc_imei(alice, "1234567890"); db_subscriber_assoc_imei(alice, "6543560920"); + /* Get by TMSI */ + snprintf(scratch_str, sizeof(scratch_str), "%"PRIu32, alice->tmsi); + alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_TMSI, scratch_str); + COMPARE(alice, alice_db); + SUBSCR_PUT(alice_db); + /* Get by IMSI */ alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice_imsi); COMPARE(alice, alice_db); - SUBSCR_PUT(alice); SUBSCR_PUT(alice_db); + /* Get by id */ + snprintf(scratch_str, sizeof(scratch_str), "%llu", alice->id); + alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_ID, scratch_str); + COMPARE(alice, alice_db); + SUBSCR_PUT(alice_db); + /* Get by extension */ + alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_EXTENSION, alice->extension); + COMPARE(alice, alice_db); + SUBSCR_PUT(alice_db); + SUBSCR_PUT(alice); db_fini(); -- 1.7.9.5 From holger at freyther.de Sun Oct 6 11:41:26 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 6 Oct 2013 13:41:26 +0200 Subject: [PATCH] db: Add more tests for retrieving subscribers from a DB and avoid NULL dereference when something goes wrong in tests. In-Reply-To: <1380968167-12568-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1380968167-12568-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <20131006114126.GT27613@xiaoyu.lan> On Sat, Oct 05, 2013 at 12:16:07PM +0200, Alexander Chemeris wrote: > #define SUBSCR_PUT(sub) \ > - sub->net = &dummy_net; \ > - subscr_put(sub); > + if (sub) { \ > + sub->net = &dummy_net; \ > + subscr_put(sub); \ > + } I don't like this semantic change. Either the tests expects a valid subscriber or it doesn't. It is not a "maybe" this query will result in a look up. From alexander.chemeris at gmail.com Sun Oct 6 12:34:59 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sun, 6 Oct 2013 14:34:59 +0200 Subject: [PATCH] db: Add more tests for retrieving subscribers from a DB and avoid NULL dereference when something goes wrong in tests. In-Reply-To: <20131006114126.GT27613@xiaoyu.lan> References: <1380968167-12568-1-git-send-email-Alexander.Chemeris@gmail.com> <20131006114126.GT27613@xiaoyu.lan> Message-ID: On Sun, Oct 6, 2013 at 1:41 PM, Holger Hans Peter Freyther wrote: > On Sat, Oct 05, 2013 at 12:16:07PM +0200, Alexander Chemeris wrote: >> #define SUBSCR_PUT(sub) \ >> - sub->net = &dummy_net; \ >> - subscr_put(sub); >> + if (sub) { \ >> + sub->net = &dummy_net; \ >> + subscr_put(sub); \ >> + } > > I don't like this semantic change. Either the tests expects a valid > subscriber or it doesn't. It is not a "maybe" this query will result > in a look up. My changes are to avoid _segfault_ when something goes wrong. Test will still fail, because it will print info about NULL original or copy, and comparison with the proper output will fail. I decided to do it that way, because it makes the code of the test itself looking clean. Otherwise we have to put this "if(sub)" to every test, which looks ugly. But if you prefer some other way - please go ahead, I don't really care about this. I just tried to keep the clean look. -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From alexander.chemeris at gmail.com Sat Oct 5 11:00:48 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sat, 5 Oct 2013 13:00:48 +0200 Subject: [PATCH] sms_queue, smpp: Refactor MO SUBMIT code to make further changes easier. Message-ID: <1380970848-12958-1-git-send-email-Alexander.Chemeris@gmail.com> This is required to implement normal prefix/regexp routing in addition to the current "if unroutable" model. --- openbsc/src/libmsc/gsm_04_11.c | 63 +++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c index e554b74..7e8ede8 100644 --- a/openbsc/src/libmsc/gsm_04_11.c +++ b/openbsc/src/libmsc/gsm_04_11.c @@ -279,6 +279,39 @@ static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms) return msg->len - old_msg_len; } +static int sms_queue_try_deliver(struct gsm_subscriber_connection *conn, + struct msgb *msg, struct gsm_sms *gsms) +{ + /* determine gsms->receiver based on dialled number */ + gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dst.addr); + if (!gsms->receiver) { + rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED; + goto out; + } + + switch (sms_mti) { + case GSM340_SMS_SUBMIT_MS2SC: + /* MS is submitting a SMS */ + rc = gsm340_rx_sms_submit(msg, gsms); + break; + case GSM340_SMS_COMMAND_MS2SC: + case GSM340_SMS_DELIVER_REP_MS2SC: + LOGP(DLSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti); + rc = GSM411_RP_CAUSE_IE_NOTEXIST; + break; + default: + LOGP(DLSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti); + rc = GSM411_RP_CAUSE_IE_NOTEXIST; + break; + } + + if (!rc && !gsms->receiver) + rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED; + +out: + return rc; +} + /* process an incoming TPDU (called from RP-DATA) * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *msg) @@ -393,44 +426,22 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m /* FIXME: This looks very wrong */ send_signal(0, NULL, gsms, 0); - /* determine gsms->receiver based on dialled number */ - gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dst.addr); - if (!gsms->receiver) { + rc = sms_queue_try_deliver(conn, msg, gsms); + if (rc == GSM411_RP_CAUSE_MO_NUM_UNASSIGNED) { #ifdef BUILD_SMPP rc = smpp_try_deliver(gsms, conn); - if (rc == 1) { - rc = 1; /* cause 1: unknown subscriber */ + if (rc == GSM411_RP_CAUSE_MO_NUM_UNASSIGNED) { osmo_counter_inc(conn->bts->network->stats.sms.no_receiver); } else if (rc < 0) { - rc = 21; /* cause 21: short message transfer rejected */ + rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED; /* FIXME: handle the error somehow? */ } #else - rc = 1; /* cause 1: unknown subscriber */ osmo_counter_inc(conn->bts->network->stats.sms.no_receiver); #endif goto out; } - switch (sms_mti) { - case GSM340_SMS_SUBMIT_MS2SC: - /* MS is submitting a SMS */ - rc = gsm340_rx_sms_submit(msg, gsms); - break; - case GSM340_SMS_COMMAND_MS2SC: - case GSM340_SMS_DELIVER_REP_MS2SC: - LOGP(DLSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti); - rc = GSM411_RP_CAUSE_IE_NOTEXIST; - break; - default: - LOGP(DLSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti); - rc = GSM411_RP_CAUSE_IE_NOTEXIST; - break; - } - - if (!rc && !gsms->receiver) - rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED; - out: sms_free(gsms); -- 1.7.9.5 From alexander.huemer at xx.vu Sun Oct 6 19:55:09 2013 From: alexander.huemer at xx.vu (Alexander Huemer) Date: Sun, 6 Oct 2013 21:55:09 +0200 Subject: [PATCH] ussd: Fix text of RELEASE COMPLETE Message-ID: <1381089309-31991-1-git-send-email-alexander.huemer@xx.vu> Before the assigned value (0xFF) was truncated, reg->text[0] is of type char. A corresponding test for the same value in openbsc could only fail. --- src/gsm/gsm0480.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index 92a62dc..dbacefc 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -234,7 +234,7 @@ static int parse_ussd(const struct gsm48_hdr *hdr, uint16_t len, struct ussd_req case GSM0480_MTYPE_RELEASE_COMPLETE: LOGP(0, LOGL_DEBUG, "USS Release Complete\n"); /* could also parse out the optional Cause/Facility data */ - req->text[0] = 0xFF; + req->text[0] = '\0'; break; case GSM0480_MTYPE_REGISTER: case GSM0480_MTYPE_FACILITY: -- 1.8.3.2 From alexander.chemeris at gmail.com Sun Oct 6 20:01:26 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sun, 6 Oct 2013 22:01:26 +0200 Subject: [PATCH] ussd: Fix text of RELEASE COMPLETE In-Reply-To: <1381089309-31991-1-git-send-email-alexander.huemer@xx.vu> References: <1381089309-31991-1-git-send-email-alexander.huemer@xx.vu> Message-ID: On Sun, Oct 6, 2013 at 9:55 PM, Alexander Huemer wrote: > LOGP(0, LOGL_DEBUG, "USS Release Complete\n"); Should this be "USSD" instead of "USS" as well? -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From alexander.huemer at xx.vu Sun Oct 6 20:04:23 2013 From: alexander.huemer at xx.vu (Alexander Huemer) Date: Sun, 6 Oct 2013 22:04:23 +0200 Subject: [PATCH] ussd: Fix text of RELEASE COMPLETE In-Reply-To: References: <1381089309-31991-1-git-send-email-alexander.huemer@xx.vu> Message-ID: <20131006200423.GB32308@yade.xx.vu> On Sun, Oct 06, 2013 at 10:01:26PM +0200, Alexander Chemeris wrote: > On Sun, Oct 6, 2013 at 9:55 PM, Alexander Huemer wrote: > > LOGP(0, LOGL_DEBUG, "USS Release Complete\n"); > > Should this be "USSD" instead of "USS" as well? I don't know. Opinions? Kind regards, -Alex From holger at freyther.de Tue Oct 8 09:27:49 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 8 Oct 2013 11:27:49 +0200 Subject: [PATCH] ussd: Fix text of RELEASE COMPLETE In-Reply-To: <1381089309-31991-1-git-send-email-alexander.huemer@xx.vu> References: <1381089309-31991-1-git-send-email-alexander.huemer@xx.vu> Message-ID: <20131008092749.GA6194@xiaoyu.lan> On Sun, Oct 06, 2013 at 09:55:09PM +0200, Alexander Huemer wrote: > Before the assigned value (0xFF) was truncated, reg->text[0] is of > type char. A corresponding test for the same value in openbsc could > only fail. Can you please explain? signed char a = 0xFF; signed char b = 0xFF; a == b => true. Even if the numerical is not the one, one expected? > - req->text[0] = 0xFF; > + req->text[0] = '\0'; but yes, we can null terminate it. From alexander.huemer at xx.vu Tue Oct 8 09:51:42 2013 From: alexander.huemer at xx.vu (Alexander Huemer) Date: Tue, 8 Oct 2013 11:51:42 +0200 Subject: [PATCH] ussd: Fix text of RELEASE COMPLETE In-Reply-To: <20131008092749.GA6194@xiaoyu.lan> References: <1381089309-31991-1-git-send-email-alexander.huemer@xx.vu> <20131008092749.GA6194@xiaoyu.lan> Message-ID: <20131008095142.GD1401@yade.xx.vu> On Tue, Oct 08, 2013 at 11:27:49AM +0200, Holger Hans Peter Freyther wrote: > On Sun, Oct 06, 2013 at 09:55:09PM +0200, Alexander Huemer wrote: > > Before the assigned value (0xFF) was truncated, reg->text[0] is of > > type char. A corresponding test for the same value in openbsc could > > only fail. > > Can you please explain? char is an signed 8bit type, so the maximum value is 0x7F. Well, at least usually. As I read, ANSI C does not dictate whether a variable declared as 'char' is signed or unsigned, gcc though defaults to signed. Excerpt from limits.h: [...] # define SCHAR_MAX 127 [...] # ifdef __CHAR_UNSIGNED__ (this is not the case normally) [...] # define CHAR_MAX SCHAR_MAX [...] Example program: int main(void) { char c = 0xFF; if (c == 0xFF) return 0; return 1; } gcc gives a hint when -Wtype-limits is used. $ gcc -Wtype-limits main.c $ ./a.out main.c: In function ?main?: main.c:5:2: warning: comparison is always false due to limited range of data type [-Wtype-limits] $ > signed char a = 0xFF; > signed char b = 0xFF; > > a == b => true. Even if the numerical is not the one, one expected? This is true because _both_ variables got the same truncated literal. Kind regards, -Alex From noselasd at fiane.dyndns.org Tue Oct 8 19:36:20 2013 From: noselasd at fiane.dyndns.org (noselasd at fiane.dyndns.org) Date: Tue, 08 Oct 2013 21:36:20 +0200 Subject: [PATCH] ussd: Fix text of RELEASE COMPLETE In-Reply-To: <20131008095142.GD1401@yade.xx.vu> References: <1381089309-31991-1-git-send-email-alexander.huemer@xx.vu> <20131008092749.GA6194@xiaoyu.lan> <20131008095142.GD1401@yade.xx.vu> Message-ID: <52545EB4.8000009@fiane.dyndns.org> On 10/08/2013 11:51 AM, Alexander Huemer wrote: > On Tue, Oct 08, 2013 at 11:27:49AM +0200, Holger Hans Peter Freyther wrote: >> On Sun, Oct 06, 2013 at 09:55:09PM +0200, Alexander Huemer wrote: >>> Before the assigned value (0xFF) was truncated, reg->text[0] is of >>> type char. A corresponding test for the same value in openbsc could >>> only fail. >> >> Can you please explain? > > char is an signed 8bit type, so the maximum value is 0x7F. Well, at > least usually. As I read, ANSI C does not dictate whether a variable > declared as 'char' is signed or unsigned, gcc though defaults to signed. > Excerpt from limits.h: > > [...] > # define SCHAR_MAX 127 > [...] > # ifdef __CHAR_UNSIGNED__ (this is not the case normally) > [...] > # define CHAR_MAX SCHAR_MAX > [...] > > Example program: > > int main(void) > { > char c = 0xFF; > > if (c == 0xFF) > return 0; > > return 1; > } And this is because: char c = 0xff; c == 0xff; ^^ ^^ | an int | promoted to int and sign extended in this expression So it's really -1 == 255 c == (char)0xff; would be ok though From alexander.huemer at xx.vu Tue Oct 15 09:44:04 2013 From: alexander.huemer at xx.vu (Alexander Huemer) Date: Tue, 15 Oct 2013 11:44:04 +0200 Subject: [PATCH] ussd: Fix text of RELEASE COMPLETE In-Reply-To: <20131008095142.GD1401@yade.xx.vu> References: <1381089309-31991-1-git-send-email-alexander.huemer@xx.vu> <20131008092749.GA6194@xiaoyu.lan> <20131008095142.GD1401@yade.xx.vu> Message-ID: <20131015094404.GB1359@yade.xx.vu> On Tue, Oct 08, 2013 at 11:51:42AM +0200, Alexander Huemer wrote: > On Tue, Oct 08, 2013 at 11:27:49AM +0200, Holger Hans Peter Freyther wrote: > > On Sun, Oct 06, 2013 at 09:55:09PM +0200, Alexander Huemer wrote: > > > Before the assigned value (0xFF) was truncated, reg->text[0] is of > > > type char. A corresponding test for the same value in openbsc could > > > only fail. > > > > Can you please explain? > > char is an signed 8bit type, so the maximum value is 0x7F. Well, at > least usually. As I read, ANSI C does not dictate whether a variable > declared as 'char' is signed or unsigned, gcc though defaults to signed. > Excerpt from limits.h: > > [...] > # define SCHAR_MAX 127 > [...] > # ifdef __CHAR_UNSIGNED__ (this is not the case normally) > [...] > # define CHAR_MAX SCHAR_MAX > [...] > > Example program: > > int main(void) > { > char c = 0xFF; > > if (c == 0xFF) > return 0; > > return 1; > } > > gcc gives a hint when -Wtype-limits is used. > > $ gcc -Wtype-limits main.c > $ ./a.out > main.c: In function ?main?: > main.c:5:2: warning: comparison is always false due to limited range of > data type [-Wtype-limits] > $ > > > signed char a = 0xFF; > > signed char b = 0xFF; > > > > a == b => true. Even if the numerical is not the one, one expected? > > This is true because _both_ variables got the same truncated literal. A week has passed since the last comment on this (and my other) patch. What is the current state? Are the two patches rejected because they do not make sense? Should I modify anything? Will they be merged at some point in the future? Kind regards, -Alex From holger at freyther.de Tue Oct 15 09:49:59 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 15 Oct 2013 11:49:59 +0200 Subject: [PATCH] ussd: Fix text of RELEASE COMPLETE In-Reply-To: <20131015094404.GB1359@yade.xx.vu> References: <1381089309-31991-1-git-send-email-alexander.huemer@xx.vu> <20131008092749.GA6194@xiaoyu.lan> <20131008095142.GD1401@yade.xx.vu> <20131015094404.GB1359@yade.xx.vu> Message-ID: <20131015094959.GA20451@xiaoyu.lan> On Tue, Oct 15, 2013 at 11:44:04AM +0200, Alexander Huemer wrote: > A week has passed since the last comment on this (and my other) patch. > What is the current state? Are the two patches rejected because they do > not make sense? Should I modify anything? Will they be merged at some > point in the future? Thanks, I will merge them. From alexander.huemer at xx.vu Sun Oct 6 19:59:28 2013 From: alexander.huemer at xx.vu (Alexander Huemer) Date: Sun, 6 Oct 2013 21:59:28 +0200 Subject: [PATCH] ussd: Fix test for RELEASE COMPLETE Message-ID: <1381089568-14527-1-git-send-email-alexander.huemer@xx.vu> A correcsponding change in libosmocore sets text[0] to '\0'. The test for 0xFF could never have been true. --- openbsc/src/libmsc/ussd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/libmsc/ussd.c b/openbsc/src/libmsc/ussd.c index 76ee101..b413c83 100644 --- a/openbsc/src/libmsc/ussd.c +++ b/openbsc/src/libmsc/ussd.c @@ -51,7 +51,7 @@ int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg) memset(&req, 0, sizeof(req)); gh = msgb_l3(msg); rc = gsm0480_decode_ussd_request(gh, msgb_l3len(msg), &req); - if (req.text[0] == 0xFF) /* Release-Complete */ + if (req.text[0] == '\0') /* Release-Complete */ return 0; if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)req.text)) { -- 1.8.3.2 From holger at freyther.de Tue Oct 8 09:28:21 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 8 Oct 2013 11:28:21 +0200 Subject: [PATCH] ussd: Fix test for RELEASE COMPLETE In-Reply-To: <1381089568-14527-1-git-send-email-alexander.huemer@xx.vu> References: <1381089568-14527-1-git-send-email-alexander.huemer@xx.vu> Message-ID: <20131008092821.GB6194@xiaoyu.lan> On Sun, Oct 06, 2013 at 09:59:28PM +0200, Alexander Huemer wrote: > - if (req.text[0] == 0xFF) /* Release-Complete */ > + if (req.text[0] == '\0') /* Release-Complete */ > return 0; as we can't assume to use the latest libosmocore, what about checking for both? From alexander.huemer at xx.vu Tue Oct 8 09:59:09 2013 From: alexander.huemer at xx.vu (Alexander Huemer) Date: Tue, 8 Oct 2013 11:59:09 +0200 Subject: [PATCH] ussd: Fix test for RELEASE COMPLETE In-Reply-To: <20131008092821.GB6194@xiaoyu.lan> References: <1381089568-14527-1-git-send-email-alexander.huemer@xx.vu> <20131008092821.GB6194@xiaoyu.lan> Message-ID: <20131008095909.GE1401@yade.xx.vu> On Tue, Oct 08, 2013 at 11:28:21AM +0200, Holger Hans Peter Freyther wrote: > On Sun, Oct 06, 2013 at 09:59:28PM +0200, Alexander Huemer wrote: > > > - if (req.text[0] == 0xFF) /* Release-Complete */ > > + if (req.text[0] == '\0') /* Release-Complete */ > > return 0; > > as we can't assume to use the latest libosmocore, what about checking > for both? Well, as I see it the test against 0xFF is not true under any circumstances, as long as the code is not intentionally compiled with -funsigned-char. If there is an undesired behavior change because of this code change, it's a bug. What's your opinion? Kind regards, -Alex From holger at freyther.de Tue Oct 8 10:49:56 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 8 Oct 2013 12:49:56 +0200 Subject: [PATCH] ussd: Fix test for RELEASE COMPLETE In-Reply-To: <20131008095909.GE1401@yade.xx.vu> References: <1381089568-14527-1-git-send-email-alexander.huemer@xx.vu> <20131008092821.GB6194@xiaoyu.lan> <20131008095909.GE1401@yade.xx.vu> Message-ID: <20131008104956.GG6194@xiaoyu.lan> On Tue, Oct 08, 2013 at 11:59:09AM +0200, Alexander Huemer wrote: Dear Alexander, > Well, as I see it the test against 0xFF is not true under any > circumstances, as long as the code is not intentionally compiled with > -funsigned-char. If there is an undesired behavior change because of > this code change, it's a bug. What's your opinion? well, I agree that it is not nice and we can/should change it to a plain null termination. What I doubt that it is currently a problem or can you present a smoking gun? int main(int argc, char **argv) { signed char a = 0xFF; signed char b = 0xFF; if (a == b) printf("THE SAME\n"); return 0; } PS: some ABIs.. e.g. ARM ones.. char will be unsigned. From alexander.huemer at xx.vu Tue Oct 8 11:16:40 2013 From: alexander.huemer at xx.vu (Alexander Huemer) Date: Tue, 8 Oct 2013 13:16:40 +0200 Subject: [PATCH] ussd: Fix test for RELEASE COMPLETE In-Reply-To: <20131008104956.GG6194@xiaoyu.lan> References: <1381089568-14527-1-git-send-email-alexander.huemer@xx.vu> <20131008092821.GB6194@xiaoyu.lan> <20131008095909.GE1401@yade.xx.vu> <20131008104956.GG6194@xiaoyu.lan> Message-ID: <20131008111640.GF1401@yade.xx.vu> On Tue, Oct 08, 2013 at 12:49:56PM +0200, Holger Hans Peter Freyther wrote: > On Tue, Oct 08, 2013 at 11:59:09AM +0200, Alexander Huemer wrote: > > Dear Alexander, > > > Well, as I see it the test against 0xFF is not true under any > > circumstances, as long as the code is not intentionally compiled with > > -funsigned-char. If there is an undesired behavior change because of > > this code change, it's a bug. What's your opinion? > > well, I agree that it is not nice and we can/should change it to a > plain null termination. What I doubt that it is currently a problem > or can you present a smoking gun? No smoking gun that I know of. It's just that the interaction between the piece of code in libosmocore and the piece in openbsc cannot work as the author intended. > int main(int argc, char **argv) > { > signed char a = 0xFF; > signed char b = 0xFF; > > if (a == b) > printf("THE SAME\n"); > return 0; > } Yes, that works of course, but I think my example program better illustrates the current situation in libosmocore and openbsc. In libosmocore a value is assigned which is truncated, in openbsc a comparison is made again that same value and this test returns false, though the intension was to return true. > PS: some ABIs.. e.g. ARM ones.. char will be unsigned. I only tested the patches on x86_64, but '\0' should be safe on all architectures. Kind regards, -Alex From alexander.chemeris at gmail.com Sun Oct 6 21:35:39 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sun, 6 Oct 2013 23:35:39 +0200 Subject: [PATCH] abis: Consistent usage of LOGP/DEBUGP at the "RSL CONNECT NACK" log output. Message-ID: <1381095339-25756-1-git-send-email-Alexander.Chemeris@gmail.com> --- openbsc/src/libbsc/abis_nm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openbsc/src/libbsc/abis_nm.c b/openbsc/src/libbsc/abis_nm.c index a2e9f0d..62176b7 100644 --- a/openbsc/src/libbsc/abis_nm.c +++ b/openbsc/src/libbsc/abis_nm.c @@ -2438,10 +2438,10 @@ static int abis_nm_rx_ipacc(struct msgb *msg) case NM_MT_IPACC_RSL_CONNECT_NACK: LOGP(DNM, LOGL_ERROR, "RSL CONNECT NACK "); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - DEBUGPC(DNM, " CAUSE=%s\n", + LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else - DEBUGPC(DNM, "\n"); + LOGPC(DNM, LOGL_ERROR, "\n"); break; case NM_MT_IPACC_SET_NVATTR_ACK: DEBUGPC(DNM, "SET NVATTR ACK\n"); -- 1.7.9.5 From alexander.chemeris at gmail.com Tue Oct 8 01:17:28 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 8 Oct 2013 03:17:28 +0200 Subject: [PATCH 0/5] SMPP and other SMS fixes Message-ID: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> This patchset solves the issue with the wrong sender address for inbound SMPP SMS messages. It then further cleans up DB structure to remove 'receiver_id' field from the sms table. The only issue with this code is that it somehow breaks channel_test test, because it depended on some fragile linker behavior. The last patch in the series fixes compilation of the test, but the test asserts. I hope the test author will find a more proper way to implement it, but at this moment I propose to disable it. Alexander Chemeris (4): bsc: Allow subscr_put() to be called with subscr->net=NULL. sms: Add a function to update DB scheme v3 to v4. msc: Do not store received id in the SMS database. This is a hack to fix channel_test.c compilation. Holger Hans Peter Freyther (1): sms: Kill the sms->sender and use addr/ton/npi throughout the code openbsc/include/openbsc/gsm_data.h | 1 - openbsc/src/libbsc/gsm_subscriber_base.c | 2 +- openbsc/src/libmsc/db.c | 257 ++++++++++++++++++++++++------ openbsc/src/libmsc/gsm_04_11.c | 9 +- openbsc/src/libmsc/smpp_openbsc.c | 5 +- openbsc/tests/channel/Makefile.am | 4 +- openbsc/tests/channel/channel_test.c | 12 -- 7 files changed, 215 insertions(+), 75 deletions(-) -- 1.7.9.5 From alexander.chemeris at gmail.com Tue Oct 8 01:17:29 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 8 Oct 2013 03:17:29 +0200 Subject: [PATCH 1/5] bsc: Allow subscr_put() to be called with subscr->net=NULL. In-Reply-To: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1381195053-10325-2-git-send-email-Alexander.Chemeris@gmail.com> This is useful for tests and is required for the v3 -> v4 DB convertion code. --- openbsc/src/libbsc/gsm_subscriber_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/libbsc/gsm_subscriber_base.c b/openbsc/src/libbsc/gsm_subscriber_base.c index 747a699..9ea0584 100644 --- a/openbsc/src/libbsc/gsm_subscriber_base.c +++ b/openbsc/src/libbsc/gsm_subscriber_base.c @@ -85,7 +85,7 @@ struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr) subscr->use_count--; DEBUGP(DREF, "subscr %s usage decreased usage to: %d\n", subscr->extension, subscr->use_count); - if (subscr->use_count <= 0 && !subscr->net->keep_subscr) + if (subscr->use_count <= 0 && (!subscr->net || !subscr->net->keep_subscr)) subscr_free(subscr); return NULL; } -- 1.7.9.5 From holger at freyther.de Tue Oct 8 09:52:58 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 8 Oct 2013 11:52:58 +0200 Subject: [PATCH 1/5] bsc: Allow subscr_put() to be called with subscr->net=NULL. In-Reply-To: <1381195053-10325-2-git-send-email-Alexander.Chemeris@gmail.com> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> <1381195053-10325-2-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <20131008095258.GC6194@xiaoyu.lan> On Tue, Oct 08, 2013 at 03:17:29AM +0200, Alexander Chemeris wrote: > - if (subscr->use_count <= 0 && !subscr->net->keep_subscr) > + if (subscr->use_count <= 0 && (!subscr->net || !subscr->net->keep_subscr)) okay, that is a difficult one. I posted my first patch to remove the network from the db code. So maybe we expose subscr_free and the db code (and test code) will just directly free the subscriber (or abort when the use_count != 1)? What do you think? From alexander.chemeris at gmail.com Tue Oct 8 01:17:30 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 8 Oct 2013 03:17:30 +0200 Subject: [PATCH 2/5] sms: Kill the sms->sender and use addr/ton/npi throughout the code In-Reply-To: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1381195053-10325-3-git-send-email-Alexander.Chemeris@gmail.com> From: Holger Hans Peter Freyther This is an incompatible database schema change. Store the type of the address in the database for both the sender and the receiver. Currently it is possible to use SMPP to store a SMS and the NPI and TON will be lost on the delivery of the SMS. The schema is changed to make the delivery always use the right NPI/TON. This patch is not ready for the master branch as there is no upgrade path for the HLR yet. --- openbsc/include/openbsc/gsm_data.h | 1 - openbsc/src/libmsc/db.c | 56 ++++++++++++++++++++++++------------ openbsc/src/libmsc/gsm_04_11.c | 9 ++---- openbsc/src/libmsc/smpp_openbsc.c | 5 ++-- 4 files changed, 42 insertions(+), 29 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 8741505..45b5784 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -302,7 +302,6 @@ struct gsm_sms_addr { struct gsm_sms { unsigned long long id; - struct gsm_subscriber *sender; struct gsm_subscriber *receiver; struct gsm_sms_addr src, dst; enum gsm_sms_source_id source; diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 9a8cd88..8f76324 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -42,7 +42,7 @@ static char *db_basename = NULL; static char *db_dirname = NULL; static dbi_conn conn; -#define SCHEMA_REVISION "3" +#define SCHEMA_REVISION "50000000" static char *create_stmts[] = { "CREATE TABLE IF NOT EXISTS Meta (" @@ -95,7 +95,6 @@ static char *create_stmts[] = { "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "sent TIMESTAMP, " - "sender_id INTEGER NOT NULL, " "receiver_id INTEGER NOT NULL, " "deliver_attempts INTEGER NOT NULL DEFAULT 0, " /* data directly copied/derived from SMS */ @@ -105,7 +104,12 @@ static char *create_stmts[] = { "protocol_id INTEGER NOT NULL, " "data_coding_scheme INTEGER NOT NULL, " "ud_hdr_ind INTEGER NOT NULL, " - "dest_addr TEXT, " + "src_addr TEXT NOT NULL, " + "src_ton INTEGER NOT NULL, " + "src_npi INTEGER NOT NULL, " + "dest_addr TEXT NOT NULL, " + "dest_ton INTEGER NOT NULL, " + "dest_npi INTEGER NOT NULL, " "user_data BLOB, " /* TP-UD */ /* additional data, interpreted from SMS */ "header BLOB, " /* UD Header */ @@ -1096,7 +1100,7 @@ int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char imei[GSM_IM int db_sms_store(struct gsm_sms *sms) { dbi_result result; - char *q_text, *q_daddr; + char *q_text, *q_daddr, *q_saddr; unsigned char *q_udata; char *validity_timestamp = "2222-2-2"; @@ -1104,25 +1108,35 @@ int db_sms_store(struct gsm_sms *sms) dbi_conn_quote_string_copy(conn, (char *)sms->text, &q_text); dbi_conn_quote_string_copy(conn, (char *)sms->dst.addr, &q_daddr); + dbi_conn_quote_string_copy(conn, (char *)sms->src.addr, &q_saddr); dbi_conn_quote_binary_copy(conn, sms->user_data, sms->user_data_len, &q_udata); + /* FIXME: correct validity period */ result = dbi_conn_queryf(conn, "INSERT INTO SMS " - "(created, sender_id, receiver_id, valid_until, " + "(created, receiver_id, valid_until, " "reply_path_req, status_rep_req, protocol_id, " - "data_coding_scheme, ud_hdr_ind, dest_addr, " - "user_data, text) VALUES " - "(datetime('now'), %llu, %llu, %u, " - "%u, %u, %u, %u, %u, %s, %s, %s)", - sms->sender->id, + "data_coding_scheme, ud_hdr_ind, " + "user_data, text, " + "dest_addr, dest_ton, dest_npi, " + "src_addr, src_ton, src_npi) VALUES " + "(datetime('now'), %llu, %u, " + "%u, %u, %u, " + "%u, %u, " + "%s, %s, " + "%s, %u, %u, " + "%s, %u, %u)", sms->receiver ? sms->receiver->id : 0, validity_timestamp, sms->reply_path_req, sms->status_rep_req, sms->protocol_id, sms->data_coding_scheme, sms->ud_hdr_ind, - q_daddr, q_udata, q_text); + q_udata, q_text, + q_daddr, sms->dst.ton, sms->dst.npi, + q_saddr, sms->src.ton, sms->src.npi); free(q_text); - free(q_daddr); free(q_udata); + free(q_daddr); + free(q_saddr); if (!result) return -EIO; @@ -1134,8 +1148,8 @@ int db_sms_store(struct gsm_sms *sms) static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result result) { struct gsm_sms *sms = sms_alloc(); - long long unsigned int sender_id, receiver_id; - const char *text, *daddr; + long long unsigned int receiver_id; + const char *text, *daddr, *saddr; const unsigned char *user_data; if (!sms) @@ -1143,10 +1157,6 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul sms->id = dbi_result_get_ulonglong(result, "id"); - sender_id = dbi_result_get_ulonglong(result, "sender_id"); - sms->sender = subscr_get_by_id(net, sender_id); - strncpy(sms->src.addr, sms->sender->extension, sizeof(sms->src.addr)-1); - receiver_id = dbi_result_get_ulonglong(result, "receiver_id"); sms->receiver = subscr_get_by_id(net, receiver_id); @@ -1160,12 +1170,22 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul "data_coding_scheme"); /* sms->msg_ref is temporary and not stored in DB */ + sms->dst.npi = dbi_result_get_uint(result, "dest_npi"); + sms->dst.ton = dbi_result_get_uint(result, "dest_ton"); daddr = dbi_result_get_string(result, "dest_addr"); if (daddr) { strncpy(sms->dst.addr, daddr, sizeof(sms->dst.addr)); sms->dst.addr[sizeof(sms->dst.addr)-1] = '\0'; } + sms->src.npi = dbi_result_get_uint(result, "src_npi"); + sms->src.ton = dbi_result_get_uint(result, "src_ton"); + saddr = dbi_result_get_string(result, "src_addr"); + if (saddr) { + strncpy(sms->src.addr, saddr, sizeof(sms->src.addr)); + sms->src.addr[sizeof(sms->src.addr)-1] = '\0'; + } + sms->user_data_len = dbi_result_get_field_length(result, "user_data"); user_data = dbi_result_get_binary(result, "user_data"); if (sms->user_data_len > sizeof(sms->user_data)) diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c index e554b74..96da04b 100644 --- a/openbsc/src/libmsc/gsm_04_11.c +++ b/openbsc/src/libmsc/gsm_04_11.c @@ -73,8 +73,6 @@ struct gsm_sms *sms_alloc(void) void sms_free(struct gsm_sms *sms) { /* drop references to subscriber structure */ - if (sms->sender) - subscr_put(sms->sender); if (sms->receiver) subscr_put(sms->receiver); #ifdef BUILD_SMPP @@ -97,8 +95,7 @@ struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, sms->receiver = subscr_get(receiver); strncpy(sms->text, text, sizeof(sms->text)-1); - sms->sender = subscr_get(sender); - strncpy(sms->src.addr, sms->sender->extension, sizeof(sms->src.addr)-1); + strncpy(sms->src.addr, sender->extension, sizeof(sms->src.addr)-1); sms->reply_path_req = 0; sms->status_rep_req = 0; sms->ud_hdr_ind = 0; @@ -377,12 +374,10 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m } } - gsms->sender = subscr_get(conn->subscr); - LOGP(DLSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, " "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, " "UserDataLength: 0x%02x, UserData: \"%s\"\n", - subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref, + subscr_name(conn->subscr), sms_mti, sms_vpf, gsms->msg_ref, gsms->protocol_id, gsms->data_coding_scheme, gsms->dst.addr, gsms->user_data_len, sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text : diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c index 9d2183a..078fecc 100644 --- a/openbsc/src/libmsc/smpp_openbsc.c +++ b/openbsc/src/libmsc/smpp_openbsc.c @@ -131,7 +131,6 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net, strncpy(sms->dst.addr, dest->extension, sizeof(sms->dst.addr)-1); /* fill in the source address */ - sms->sender = subscr_get_by_id(net, 1); sms->src.ton = submit->source_addr_ton; sms->src.npi = submit->source_addr_npi; strncpy(sms->src.addr, (char *)submit->source_addr, sizeof(sms->src.addr)-1); @@ -473,13 +472,13 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms, deliver.source_addr_npi = NPI_Land_Mobile_E212; snprintf((char *)deliver.source_addr, sizeof(deliver.source_addr), "%s", - sms->sender->imsi); + conn->subscr->imsi); } else { deliver.source_addr_ton = TON_Network_Specific; deliver.source_addr_npi = NPI_ISDN_E163_E164; snprintf((char *)deliver.source_addr, sizeof(deliver.source_addr), "%s", - sms->sender->extension); + conn->subscr->extension); } deliver.dest_addr_ton = sms->dst.ton; -- 1.7.9.5 From alexander.chemeris at gmail.com Tue Oct 8 01:17:31 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 8 Oct 2013 03:17:31 +0200 Subject: [PATCH 3/5] sms: Add a function to update DB scheme v3 to v4. In-Reply-To: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1381195053-10325-4-git-send-email-Alexander.Chemeris@gmail.com> The v4 DB scheme removes sender ID from the DB and stores individual values instead (sender addr, ton, npi). To convert an old DB to the new format we have to read all values from the old table and re-add them to the new one. --- openbsc/src/libmsc/db.c | 199 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 170 insertions(+), 29 deletions(-) diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 8f76324..d60f73e 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -41,8 +41,36 @@ static char *db_basename = NULL; static char *db_dirname = NULL; static dbi_conn conn; - -#define SCHEMA_REVISION "50000000" +static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result result); + +#define SCHEMA_REVISION "4" + +#define SMS_TABLE_CREATE_STMT \ + "CREATE TABLE IF NOT EXISTS SMS (" \ + /* metadata, not part of sms */ \ + "id INTEGER PRIMARY KEY AUTOINCREMENT, " \ + "created TIMESTAMP NOT NULL, " \ + "sent TIMESTAMP, " \ + "receiver_id INTEGER NOT NULL, " \ + "deliver_attempts INTEGER NOT NULL DEFAULT 0, " \ + /* data directly copied/derived from SMS */ \ + "valid_until TIMESTAMP, " \ + "reply_path_req INTEGER NOT NULL, " \ + "status_rep_req INTEGER NOT NULL, " \ + "protocol_id INTEGER NOT NULL, " \ + "data_coding_scheme INTEGER NOT NULL, " \ + "ud_hdr_ind INTEGER NOT NULL, " \ + "src_addr TEXT NOT NULL, " \ + "src_ton INTEGER NOT NULL, " \ + "src_npi INTEGER NOT NULL, " \ + "dest_addr TEXT NOT NULL, " \ + "dest_ton INTEGER NOT NULL, " \ + "dest_npi INTEGER NOT NULL, " \ + "user_data BLOB, " /* TP-UD */ \ + /* additional data, interpreted from SMS */ \ + "header BLOB, " /* UD Header */ \ + "text TEXT " /* decoded UD after UDH */ \ + ")" static char *create_stmts[] = { "CREATE TABLE IF NOT EXISTS Meta (" @@ -90,31 +118,7 @@ static char *create_stmts[] = { "equipment_id NUMERIC NOT NULL, " "UNIQUE (subscriber_id, equipment_id) " ")", - "CREATE TABLE IF NOT EXISTS SMS (" - /* metadata, not part of sms */ - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "created TIMESTAMP NOT NULL, " - "sent TIMESTAMP, " - "receiver_id INTEGER NOT NULL, " - "deliver_attempts INTEGER NOT NULL DEFAULT 0, " - /* data directly copied/derived from SMS */ - "valid_until TIMESTAMP, " - "reply_path_req INTEGER NOT NULL, " - "status_rep_req INTEGER NOT NULL, " - "protocol_id INTEGER NOT NULL, " - "data_coding_scheme INTEGER NOT NULL, " - "ud_hdr_ind INTEGER NOT NULL, " - "src_addr TEXT NOT NULL, " - "src_ton INTEGER NOT NULL, " - "src_npi INTEGER NOT NULL, " - "dest_addr TEXT NOT NULL, " - "dest_ton INTEGER NOT NULL, " - "dest_npi INTEGER NOT NULL, " - "user_data BLOB, " /* TP-UD */ - /* additional data, interpreted from SMS */ - "header BLOB, " /* UD Header */ - "text TEXT " /* decoded UD after UDH */ - ")", + SMS_TABLE_CREATE_STMT, "CREATE TABLE IF NOT EXISTS VLR (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " @@ -175,7 +179,7 @@ static int update_db_revision_2(void) "TIMESTAMP DEFAULT NULL"); if (!result) { LOGP(DDB, LOGL_ERROR, - "Failed to alter table Subscriber (upgrade vom rev 2).\n"); + "Failed to alter table Subscriber (upgrade from rev 2).\n"); return -EINVAL; } dbi_result_free(result); @@ -186,7 +190,138 @@ static int update_db_revision_2(void) "WHERE key = 'revision'"); if (!result) { LOGP(DDB, LOGL_ERROR, - "Failed set new revision (upgrade vom rev 2).\n"); + "Failed to update DB schema revision (upgrade from rev 2).\n"); + return -EINVAL; + } + dbi_result_free(result); + + return 0; +} + + +static struct gsm_sms *sms_from_result_v3(dbi_result result) +{ + struct gsm_sms *sms = sms_alloc(); + long long unsigned int sender_id; + struct gsm_subscriber *sender; + const char *text, *daddr; + const unsigned char *user_data; + char buf[32]; + + if (!sms) + return NULL; + + sms->id = dbi_result_get_ulonglong(result, "id"); + + sender_id = dbi_result_get_ulonglong(result, "sender_id"); + sprintf(buf, "%llu", sender_id); + sender = db_get_subscriber(NULL, GSM_SUBSCRIBER_ID, buf); + strncpy(sms->src.addr, sender->extension, sizeof(sms->src.addr)-1); + subscr_put(sender); + + sms->receiver = NULL; + + /* FIXME: validity */ + /* FIXME: those should all be get_uchar, but sqlite3 is braindead */ + sms->reply_path_req = dbi_result_get_uint(result, "reply_path_req"); + sms->status_rep_req = dbi_result_get_uint(result, "status_rep_req"); + sms->ud_hdr_ind = dbi_result_get_uint(result, "ud_hdr_ind"); + sms->protocol_id = dbi_result_get_uint(result, "protocol_id"); + sms->data_coding_scheme = dbi_result_get_uint(result, + "data_coding_scheme"); + /* sms->msg_ref is temporary and not stored in DB */ + + daddr = dbi_result_get_string(result, "dest_addr"); + if (daddr) { + strncpy(sms->dst.addr, daddr, sizeof(sms->dst.addr)); + sms->dst.addr[sizeof(sms->dst.addr)-1] = '\0'; + } + + sms->user_data_len = dbi_result_get_field_length(result, "user_data"); + user_data = dbi_result_get_binary(result, "user_data"); + if (sms->user_data_len > sizeof(sms->user_data)) + sms->user_data_len = (uint8_t) sizeof(sms->user_data); + memcpy(sms->user_data, user_data, sms->user_data_len); + + text = dbi_result_get_string(result, "text"); + if (text) { + strncpy(sms->text, text, sizeof(sms->text)); + sms->text[sizeof(sms->text)-1] = '\0'; + } + return sms; +} + +static int update_db_revision_3(void) +{ + dbi_result result; + struct gsm_sms *sms; + + /* Rename old SMS table to be able create a new one */ + result = dbi_conn_query(conn, + "ALTER TABLE SMS " + "RENAME TO SMS_3"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to rename the old SMS table (upgrade from rev 3).\n"); + return -EINVAL; + } + dbi_result_free(result); + + /* Create new SMS table with all the bells and whistles! */ + result = dbi_conn_query(conn, + SMS_TABLE_CREATE_STMT); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to create a new SMS table (upgrade from rev 3).\n"); + return -EINVAL; + } + dbi_result_free(result); + + /* Cycle through old messages and convert them to the new format */ + result = dbi_conn_queryf(conn, + "SELECT * FROM SMS_3"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed fetch messages from the old SMS table (upgrade from rev 3).\n"); + return -EINVAL; + } + while (dbi_result_next_row(result)) { + sms = sms_from_result_v3(result); + if (db_sms_store(sms) != 0) { + LOGP(DDB, LOGL_ERROR, "Failed to store message to the new SMS table(upgrade from rev 3).\n"); + } + sms_free(sms); + } + dbi_result_free(result); + + /* Mark SMS_3 table for removal */ + result = dbi_conn_query(conn, + "DROP TABLE SMS_3"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to drop the old SMS table (upgrade from rev 3).\n"); + return -EINVAL; + } + dbi_result_free(result); + + /* Shrink DB file size by actually wiping out SMS_3 table data */ + result = dbi_conn_query(conn, + "VACUUM"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed VACUUM after droping the old SMS table (upgrade from rev 3).\n"); + return -EINVAL; + } + dbi_result_free(result); + + /* We're done. Bump DB Meta revision to 4 */ + result = dbi_conn_query(conn, + "UPDATE Meta " + "SET value = '4' " + "WHERE key = 'revision'"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to update DB schema revision (upgrade from rev 3).\n"); return -EINVAL; } dbi_result_free(result); @@ -219,6 +354,12 @@ static int check_db_revision(void) dbi_result_free(result); return -EINVAL; } + } else if (!strcmp(rev_s, "3")) { + if (update_db_revision_3()) { + LOGP(DDB, LOGL_FATAL, "Failed to update database from schema revision '%s'.\n", rev_s); + dbi_result_free(result); + return -EINVAL; + } } else if (!strcmp(rev_s, SCHEMA_REVISION)) { /* everything is fine */ } else { -- 1.7.9.5 From holger at freyther.de Tue Oct 8 10:01:55 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 8 Oct 2013 12:01:55 +0200 Subject: [PATCH 3/5] sms: Add a function to update DB scheme v3 to v4. In-Reply-To: <1381195053-10325-4-git-send-email-Alexander.Chemeris@gmail.com> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> <1381195053-10325-4-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <20131008100155.GD6194@xiaoyu.lan> On Tue, Oct 08, 2013 at 03:17:31AM +0200, Alexander Chemeris wrote: > The v4 DB scheme removes sender ID from the DB and stores individual values instead (sender addr, ton, npi). To convert an old DB to the new format we have to read all values from the old table and re-add them to the new one. we need to squash this with the previous commit and you should add line wrapping to your text as well. > +#define SMS_TABLE_CREATE_STMT \ Can you propose an alternative to move this out of the array? > - "Failed to alter table Subscriber (upgrade vom rev 2).\n"); > + "Failed to alter table Subscriber (upgrade from rev 2).\n"); haha, german and with a typo. :) > + /* Rename old SMS table to be able create a new one */ > + result = dbi_conn_query(conn, > + "ALTER TABLE SMS " > + "RENAME TO SMS_3"); Okay, that is easier than adding a new column, populating it, removing the old one, changing the constraints. It is at the cost of having an additional parser routine. > + /* Mark SMS_3 table for removal */ How is it marked? ;) > + } else if (!strcmp(rev_s, "3")) { > + if (update_db_revision_3()) { FAILURE reading it is odd, but this is how update_db_revision_2 is doing it.. you just copied it. From alexander.chemeris at gmail.com Tue Oct 8 10:30:19 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 8 Oct 2013 12:30:19 +0200 Subject: [PATCH 3/5] sms: Add a function to update DB scheme v3 to v4. In-Reply-To: <20131008100155.GD6194@xiaoyu.lan> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> <1381195053-10325-4-git-send-email-Alexander.Chemeris@gmail.com> <20131008100155.GD6194@xiaoyu.lan> Message-ID: On Tue, Oct 8, 2013 at 12:01 PM, Holger Hans Peter Freyther wrote: > On Tue, Oct 08, 2013 at 03:17:31AM +0200, Alexander Chemeris wrote: >> The v4 DB scheme removes sender ID from the DB and stores individual values instead (sender addr, ton, npi). To convert an old DB to the new format we have to read all values from the old table and re-add them to the new one. > > > we need to squash this with the previous commit and you should add > line wrapping to your text as well. Squashing will remove your copyright on the code, so I avoided that. I don't see an issue with having two separate commits. >> +#define SMS_TABLE_CREATE_STMT \ > > Can you propose an alternative to move this out of the array? Frankly speaking, I would move _all_ these statements to separate #defines, to make the code clearer. And no, I don't see a better way to do that. >> + /* Rename old SMS table to be able create a new one */ >> + result = dbi_conn_query(conn, >> + "ALTER TABLE SMS " >> + "RENAME TO SMS_3"); > > Okay, that is easier than adding a new column, populating it, removing > the old one, changing the constraints. It is at the cost of having an > additional parser routine. The thin is that in SQLite you can't remove a column. So this is the only possible way. >> + /* Mark SMS_3 table for removal */ > > How is it marked? ;) It's not actually removed from the file. VACUUM is needed to actually remove the data. Thus "marked". >> + } else if (!strcmp(rev_s, "3")) { >> + if (update_db_revision_3()) { > FAILURE > > reading it is odd, but this is how update_db_revision_2 is doing > it.. you just copied it. Yes, I didn't want to change the code style. -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From alexander.chemeris at gmail.com Tue Oct 8 01:17:32 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 8 Oct 2013 03:17:32 +0200 Subject: [PATCH 4/5] msc: Do not store received id in the SMS database. In-Reply-To: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1381195053-10325-5-git-send-email-Alexander.Chemeris@gmail.com> That was a bad idea from the very beginning. A visible result of this is a wrong SMS routing when you change subscriber extensions, while having queued SMS. It's also a very wrong thing from the code layering perspective. I think the next logical step should be to remove "receiver" pointer from the gsm_sms structure into a structure, special for the internal SMS queue. --- openbsc/src/libmsc/db.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index d60f73e..2c77538 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -51,7 +51,6 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul "id INTEGER PRIMARY KEY AUTOINCREMENT, " \ "created TIMESTAMP NOT NULL, " \ "sent TIMESTAMP, " \ - "receiver_id INTEGER NOT NULL, " \ "deliver_attempts INTEGER NOT NULL DEFAULT 0, " \ /* data directly copied/derived from SMS */ \ "valid_until TIMESTAMP, " \ @@ -1256,19 +1255,19 @@ int db_sms_store(struct gsm_sms *sms) /* FIXME: correct validity period */ result = dbi_conn_queryf(conn, "INSERT INTO SMS " - "(created, receiver_id, valid_until, " + "(created, valid_until, " "reply_path_req, status_rep_req, protocol_id, " "data_coding_scheme, ud_hdr_ind, " "user_data, text, " "dest_addr, dest_ton, dest_npi, " "src_addr, src_ton, src_npi) VALUES " - "(datetime('now'), %llu, %u, " + "(datetime('now'), %u, " "%u, %u, %u, " "%u, %u, " "%s, %s, " "%s, %u, %u, " "%s, %u, %u)", - sms->receiver ? sms->receiver->id : 0, validity_timestamp, + validity_timestamp, sms->reply_path_req, sms->status_rep_req, sms->protocol_id, sms->data_coding_scheme, sms->ud_hdr_ind, q_udata, q_text, @@ -1289,7 +1288,6 @@ int db_sms_store(struct gsm_sms *sms) static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result result) { struct gsm_sms *sms = sms_alloc(); - long long unsigned int receiver_id; const char *text, *daddr, *saddr; const unsigned char *user_data; @@ -1298,9 +1296,6 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul sms->id = dbi_result_get_ulonglong(result, "id"); - receiver_id = dbi_result_get_ulonglong(result, "receiver_id"); - sms->receiver = subscr_get_by_id(net, receiver_id); - /* FIXME: validity */ /* FIXME: those should all be get_uchar, but sqlite3 is braindead */ sms->reply_path_req = dbi_result_get_uint(result, "reply_path_req"); @@ -1318,6 +1313,7 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul strncpy(sms->dst.addr, daddr, sizeof(sms->dst.addr)); sms->dst.addr[sizeof(sms->dst.addr)-1] = '\0'; } + sms->receiver = subscr_get_by_extension(net, sms->dst.addr); sms->src.npi = dbi_result_get_uint(result, "src_npi"); sms->src.ton = dbi_result_get_uint(result, "src_ton"); @@ -1372,7 +1368,7 @@ struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long mi result = dbi_conn_queryf(conn, "SELECT SMS.* " "FROM SMS JOIN Subscriber ON " - "SMS.receiver_id = Subscriber.id " + "SMS.dest_addr = Subscriber.extension " "WHERE SMS.id >= %llu AND SMS.sent IS NULL " "AND Subscriber.lac > 0 " "ORDER BY SMS.id LIMIT 1", @@ -1402,10 +1398,10 @@ struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, result = dbi_conn_queryf(conn, "SELECT SMS.* " "FROM SMS JOIN Subscriber ON " - "SMS.receiver_id = Subscriber.id " - "WHERE SMS.receiver_id >= %llu AND SMS.sent IS NULL " + "SMS.dest_addr = Subscriber.extension " + "WHERE Subscriber.id >= %llu AND SMS.sent IS NULL " "AND Subscriber.lac > 0 AND SMS.deliver_attempts < %u " - "ORDER BY SMS.receiver_id, SMS.id LIMIT 1", + "ORDER BY Subscriber.id, SMS.id LIMIT 1", min_subscr_id, failed); if (!result) return NULL; @@ -1431,8 +1427,8 @@ struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr) result = dbi_conn_queryf(conn, "SELECT SMS.* " "FROM SMS JOIN Subscriber ON " - "SMS.receiver_id = Subscriber.id " - "WHERE SMS.receiver_id = %llu AND SMS.sent IS NULL " + "SMS.dest_addr = Subscriber.extension " + "WHERE Subscriber.id = %llu AND SMS.sent IS NULL " "AND Subscriber.lac > 0 " "ORDER BY SMS.id LIMIT 1", subscr->id); -- 1.7.9.5 From holger at freyther.de Tue Oct 8 10:03:01 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 8 Oct 2013 12:03:01 +0200 Subject: [PATCH 4/5] msc: Do not store received id in the SMS database. In-Reply-To: <1381195053-10325-5-git-send-email-Alexander.Chemeris@gmail.com> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> <1381195053-10325-5-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <20131008100301.GE6194@xiaoyu.lan> On Tue, Oct 08, 2013 at 03:17:32AM +0200, Alexander Chemeris wrote: > That was a bad idea from the very beginning. A visible result of this is a wrong > SMS routing when you change subscriber extensions, while having queued SMS. It's > also a very wrong thing from the code layering perspective. > > I think the next logical step should be to remove "receiver" pointer from > the gsm_sms structure into a structure, special for the internal SMS queue. how much extra effort is it to remove ->receiver right now? From alexander.chemeris at gmail.com Tue Oct 8 10:08:13 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 8 Oct 2013 12:08:13 +0200 Subject: [PATCH 4/5] msc: Do not store received id in the SMS database. In-Reply-To: <20131008100301.GE6194@xiaoyu.lan> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> <1381195053-10325-5-git-send-email-Alexander.Chemeris@gmail.com> <20131008100301.GE6194@xiaoyu.lan> Message-ID: On Tue, Oct 8, 2013 at 12:03 PM, Holger Hans Peter Freyther wrote: > On Tue, Oct 08, 2013 at 03:17:32AM +0200, Alexander Chemeris wrote: >> That was a bad idea from the very beginning. A visible result of this is a wrong >> SMS routing when you change subscriber extensions, while having queued SMS. It's >> also a very wrong thing from the code layering perspective. >> >> I think the next logical step should be to remove "receiver" pointer from >> the gsm_sms structure into a structure, special for the internal SMS queue. > > how much extra effort is it to remove ->receiver right now? We should create a new structure, new functions to create/free/populate it, and translate sms_queue.c to using it. I think about a day of work for me. A bit more, than I could afford right now, unfortunately. :( May be a good task for someone who wants to contribute and doesn't know where to start. -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From alexander.chemeris at gmail.com Sun Oct 13 16:36:56 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sun, 13 Oct 2013 20:36:56 +0400 Subject: [PATCH 4/5] msc: Do not store received id in the SMS database. In-Reply-To: References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> <1381195053-10325-5-git-send-email-Alexander.Chemeris@gmail.com> <20131008100301.GE6194@xiaoyu.lan> Message-ID: On Tue, Oct 8, 2013 at 2:08 PM, Alexander Chemeris wrote: > > On Tue, Oct 8, 2013 at 12:03 PM, Holger Hans Peter Freyther > wrote: > > On Tue, Oct 08, 2013 at 03:17:32AM +0200, Alexander Chemeris wrote: > >> That was a bad idea from the very beginning. A visible result of this is a wrong > >> SMS routing when you change subscriber extensions, while having queued SMS. It's > >> also a very wrong thing from the code layering perspective. > >> > >> I think the next logical step should be to remove "receiver" pointer from > >> the gsm_sms structure into a structure, special for the internal SMS queue. > > > > how much extra effort is it to remove ->receiver right now? > > We should create a new structure, new functions to > create/free/populate it, and translate sms_queue.c to using it. I looked into the code more closely and actually we already have a gsm_sms_pending structure in the SMS queue implementation, which also holds a pointer to the receiver subscriber. So the task is trivial from the architecture perspective - just move from using the pointer in the gsm_sms structure to using the pointer in gsm_sms_pending structure. But this requires careful thought and thus still quite time consuming. On the similar venue, I'm thinking about delivering SMS to SMPP over unstable links (e.g. satellite), where the link may be inaccessible for non-negligible amounts of time. To make this usable, we need a queue in front of the SMPP interface. I see two options - introducing a dedicated queue for SMPP and modifying existing sms_queue to support delivery not only to local subscribers, but to SMPP and other future transports as well. I would be glad to know opinions on this. -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From alexander.chemeris at gmail.com Tue Oct 8 01:17:33 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 8 Oct 2013 03:17:33 +0200 Subject: [PATCH 5/5] This is a hack to fix channel_test.c compilation. In-Reply-To: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <1381195053-10325-6-git-send-email-Alexander.Chemeris@gmail.com> The test fails, though, because we have removed a mock up version of paging_request(). I'm not sure how to properly fix the test, as the way it used to work is a pure hack. --- openbsc/tests/channel/Makefile.am | 4 +++- openbsc/tests/channel/channel_test.c | 12 ------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/openbsc/tests/channel/Makefile.am b/openbsc/tests/channel/Makefile.am index 89f015a..a626ccf 100644 --- a/openbsc/tests/channel/Makefile.am +++ b/openbsc/tests/channel/Makefile.am @@ -8,5 +8,7 @@ noinst_PROGRAMS = channel_test channel_test_SOURCES = channel_test.c channel_test_LDADD = -ldl $(LIBOSMOCORE_LIBS) \ $(top_builddir)/src/libcommon/libcommon.a \ + $(top_builddir)/src/libmsc/libmsc.a \ + $(top_builddir)/src/libtrau/libtrau.a \ $(top_builddir)/src/libbsc/libbsc.a \ - $(top_builddir)/src/libmsc/libmsc.a -ldbi $(LIBOSMOGSM_LIBS) + -ldbi $(LIBOSMOGSM_LIBS) $(LIBOSMOABIS_LIBS) diff --git a/openbsc/tests/channel/channel_test.c b/openbsc/tests/channel/channel_test.c index ab0d9eb..0d50b08 100644 --- a/openbsc/tests/channel/channel_test.c +++ b/openbsc/tests/channel/channel_test.c @@ -45,12 +45,6 @@ static int subscr_cb(unsigned int hook, unsigned int event, struct msgb *msg, vo return 0; } -/* mock object for testing, directly invoke the cb... maybe later through the timer */ -void paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscriber, int type, gsm_cbfn *cbfn, void *data) -{ - cbfn(101, 200, (void*)0x1323L, &s_conn, data); -} - int main(int argc, char **argv) { @@ -83,13 +77,7 @@ int main(int argc, char **argv) return EXIT_SUCCESS; } -void _abis_nm_sendmsg() {} -void sms_alloc() {} -void gsm_net_update_ctype(struct gsm_network *network) {} -void gsm48_secure_channel() {} -void paging_request_stop() {} void vty_out() {} -void* connection_for_subscr(void) { abort(); return NULL; } struct tlv_definition nm_att_tlvdef; -- 1.7.9.5 From holger at freyther.de Tue Oct 8 10:05:03 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 8 Oct 2013 12:05:03 +0200 Subject: [PATCH 5/5] This is a hack to fix channel_test.c compilation. In-Reply-To: <1381195053-10325-6-git-send-email-Alexander.Chemeris@gmail.com> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> <1381195053-10325-6-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: <20131008100503.GF6194@xiaoyu.lan> On Tue, Oct 08, 2013 at 03:17:33AM +0200, Alexander Chemeris wrote: > The test fails, though, because we have removed a mock up version of paging_request(). > I'm not sure how to properly fix the test, as the way it used to work is a pure hack. Can you elaborate when this patch will become necessary? From looking at your patches I don't see where it would be the case. thanks holger From alexander.chemeris at gmail.com Tue Oct 8 10:35:10 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 8 Oct 2013 12:35:10 +0200 Subject: [PATCH 5/5] This is a hack to fix channel_test.c compilation. In-Reply-To: <20131008100503.GF6194@xiaoyu.lan> References: <1381195053-10325-1-git-send-email-Alexander.Chemeris@gmail.com> <1381195053-10325-6-git-send-email-Alexander.Chemeris@gmail.com> <20131008100503.GF6194@xiaoyu.lan> Message-ID: On Tue, Oct 8, 2013 at 12:05 PM, Holger Hans Peter Freyther wrote: > On Tue, Oct 08, 2013 at 03:17:33AM +0200, Alexander Chemeris wrote: >> The test fails, though, because we have removed a mock up version of paging_request(). >> I'm not sure how to properly fix the test, as the way it used to work is a pure hack. > > Can you elaborate when this patch will become necessary? From looking > at your patches I don't see where it would be the case. I don't see why it should break either, but it does. Actually I don't understand how it worked before. Mock up version of paging_request() should be conflicting with the built-in function of the same name (this is what happens now). But for some reason, it didn't conflict before. -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From holger at freyther.de Tue Oct 8 09:44:54 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 8 Oct 2013 11:44:54 +0200 Subject: [PATCH] db: Remove the struct gsm_network from the database layer Message-ID: <1381225494-13436-1-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther The database code should not know about the network. Move the setting of the network pointer into the subscriber layer. --- openbsc/include/openbsc/db.h | 6 ++---- openbsc/include/openbsc/gsm_subscriber.h | 2 ++ openbsc/src/libmsc/db.c | 9 +++------ openbsc/src/libmsc/gsm_04_08.c | 4 ++-- openbsc/src/libmsc/gsm_subscriber.c | 25 +++++++++++++++++++++---- openbsc/src/libmsc/vty_interface_layer3.c | 2 +- openbsc/tests/db/db_test.c | 12 ++++++------ 7 files changed, 37 insertions(+), 23 deletions(-) diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h index 25c2aea..a89c22d 100644 --- a/openbsc/include/openbsc/db.h +++ b/openbsc/include/openbsc/db.h @@ -35,10 +35,8 @@ int db_prepare(void); int db_fini(void); /* subscriber management */ -struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, - char *imsi); -struct gsm_subscriber *db_get_subscriber(struct gsm_network *net, - enum gsm_subscriber_field field, +struct gsm_subscriber *db_create_subscriber(const char *imsi); +struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field, const char *subscr); int db_sync_subscriber(struct gsm_subscriber *subscriber); int db_subscriber_expire(void *priv, void (*callback)(void *priv, long long unsigned int id)); diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index 6b577b0..7aae4c3 100644 --- a/openbsc/include/openbsc/gsm_subscriber.h +++ b/openbsc/include/openbsc/gsm_subscriber.h @@ -73,6 +73,8 @@ enum gsm_subscriber_update_reason { struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr); struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr); +struct gsm_subscriber *subscr_create_subscriber(struct gsm_network *net, + const char *imsi); struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net, uint32_t tmsi); struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net, diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 9a8cd88..d179c4e 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -315,13 +315,13 @@ int db_fini(void) return 0; } -struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi) +struct gsm_subscriber *db_create_subscriber(const char *imsi) { dbi_result result; struct gsm_subscriber *subscr; /* Is this subscriber known in the db? */ - subscr = db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi); + subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, imsi); if (subscr) { result = dbi_conn_queryf(conn, "UPDATE Subscriber set updated = datetime('now') " @@ -346,7 +346,6 @@ struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi) ); if (!result) LOGP(DDB, LOGL_ERROR, "Failed to create Subscriber by IMSI.\n"); - subscr->net = net; subscr->id = dbi_conn_sequence_last(conn, NULL); strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1); dbi_result_free(result); @@ -645,8 +644,7 @@ static void db_set_from_query(struct gsm_subscriber *subscr, dbi_conn result) } #define BASE_QUERY "SELECT * FROM Subscriber " -struct gsm_subscriber *db_get_subscriber(struct gsm_network *net, - enum gsm_subscriber_field field, +struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field, const char *id) { dbi_result result; @@ -704,7 +702,6 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net, } subscr = subscr_alloc(); - subscr->net = net; subscr->id = dbi_result_get_ulonglong(result, "id"); db_set_from_query(subscr, result); diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index a299590..c41443e 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -474,7 +474,7 @@ static int mm_rx_id_resp(struct gsm_subscriber_connection *conn, struct msgb *ms if (!conn->subscr) { conn->subscr = subscr_get_by_imsi(net, mi_string); if (!conn->subscr) - conn->subscr = db_create_subscriber(net, mi_string); + conn->subscr = subscr_create_subscriber(net, mi_string); } if (conn->loc_operation) conn->loc_operation->waiting_for_imsi = 0; @@ -586,7 +586,7 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb /* look up subscriber based on IMSI, create if not found */ subscr = subscr_get_by_imsi(bts->network, mi_string); if (!subscr) { - subscr = db_create_subscriber(bts->network, mi_string); + subscr = subscr_create_subscriber(bts->network, mi_string); } break; case GSM_MI_TYPE_TMSI: diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c index 5ace8f6..bc6f3cf 100644 --- a/openbsc/src/libmsc/gsm_subscriber.c +++ b/openbsc/src/libmsc/gsm_subscriber.c @@ -78,6 +78,15 @@ enum { REQ_STATE_DISPATCHED, }; +static struct gsm_subscriber *get_subscriber(struct gsm_network *net, + int type, const char *ident) +{ + struct gsm_subscriber *subscr = db_get_subscriber(type, ident); + if (subscr) + subscr->net = net; + return subscr; +} + /* * We got the channel assigned and can now hand this channel * over to one of our callbacks. @@ -266,6 +275,14 @@ void subscr_put_channel(struct gsm_subscriber *subscr) subscr_send_paging_request(subscr); } +struct gsm_subscriber *subscr_create_subscriber(struct gsm_network *net, + const char *imsi) +{ + struct gsm_subscriber *subscr = db_create_subscriber(imsi); + if (subscr) + subscr->net = net; + return subscr; +} struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net, uint32_t tmsi) @@ -280,7 +297,7 @@ struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net, } sprintf(tmsi_string, "%u", tmsi); - return db_get_subscriber(net, GSM_SUBSCRIBER_TMSI, tmsi_string); + return get_subscriber(net, GSM_SUBSCRIBER_TMSI, tmsi_string); } struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net, @@ -293,7 +310,7 @@ struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net, return subscr_get(subscr); } - return db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi); + return get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi); } struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net, @@ -306,7 +323,7 @@ struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net, return subscr_get(subscr); } - return db_get_subscriber(net, GSM_SUBSCRIBER_EXTENSION, ext); + return get_subscriber(net, GSM_SUBSCRIBER_EXTENSION, ext); } struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net, @@ -321,7 +338,7 @@ struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net, return subscr_get(subscr); } - return db_get_subscriber(net, GSM_SUBSCRIBER_ID, buf); + return get_subscriber(net, GSM_SUBSCRIBER_ID, buf); } int subscr_update_expire_lu(struct gsm_subscriber *s, struct gsm_bts *bts) diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c index acb4af7..e0324d6 100644 --- a/openbsc/src/libmsc/vty_interface_layer3.c +++ b/openbsc/src/libmsc/vty_interface_layer3.c @@ -229,7 +229,7 @@ DEFUN(subscriber_create, struct gsm_network *gsmnet = gsmnet_from_vty(vty); struct gsm_subscriber *subscr; - subscr = db_create_subscriber(gsmnet, argv[0]); + subscr = subscr_create_subscriber(gsmnet, argv[0]); if (!subscr) { vty_out(vty, "%% No subscriber created for IMSI %s%s", argv[0], VTY_NEWLINE); diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index c3beee2..3c5de90 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -78,32 +78,32 @@ int main() struct gsm_subscriber *alice_db; char *alice_imsi = "3243245432345"; - alice = db_create_subscriber(NULL, alice_imsi); + alice = db_create_subscriber(alice_imsi); db_sync_subscriber(alice); - alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice->imsi); + alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice->imsi); COMPARE(alice, alice_db); SUBSCR_PUT(alice_db); SUBSCR_PUT(alice); alice_imsi = "3693245423445"; - alice = db_create_subscriber(NULL, alice_imsi); + alice = db_create_subscriber(alice_imsi); db_subscriber_assoc_imei(alice, "1234567890"); db_subscriber_alloc_tmsi(alice); alice->lac=42; db_sync_subscriber(alice); - alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice_imsi); + alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice_imsi); COMPARE(alice, alice_db); SUBSCR_PUT(alice); SUBSCR_PUT(alice_db); alice_imsi = "9993245423445"; - alice = db_create_subscriber(NULL, alice_imsi); + alice = db_create_subscriber(alice_imsi); db_subscriber_alloc_tmsi(alice); alice->lac=42; db_sync_subscriber(alice); db_subscriber_assoc_imei(alice, "1234567890"); db_subscriber_assoc_imei(alice, "6543560920"); - alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice_imsi); + alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice_imsi); COMPARE(alice, alice_db); SUBSCR_PUT(alice); SUBSCR_PUT(alice_db); -- 1.8.4.rc3 From peter at stuge.se Thu Oct 10 23:56:34 2013 From: peter at stuge.se (Peter Stuge) Date: Fri, 11 Oct 2013 01:56:34 +0200 Subject: [PATCH] db: Remove the struct gsm_network from the database layer In-Reply-To: <1381225494-13436-1-git-send-email-holger@freyther.de> References: <1381225494-13436-1-git-send-email-holger@freyther.de> Message-ID: <20131010235634.10287.qmail@stuge.se> Holger Hans Peter Freyther wrote: > The database code should not know about the network. Hmm. Does HLR/VLR matter? Ie. are all subscribers in the database neccessarily in the current network? //Peter From alexander.chemeris at gmail.com Fri Oct 11 05:01:04 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 11 Oct 2013 09:01:04 +0400 Subject: [PATCH] db: Remove the struct gsm_network from the database layer In-Reply-To: <1381225494-13436-1-git-send-email-holger@freyther.de> References: <1381225494-13436-1-git-send-email-holger@freyther.de> Message-ID: I looked at the patch and it looks sane to me. On Tue, Oct 8, 2013 at 1:44 PM, Holger Hans Peter Freyther wrote: > From: Holger Hans Peter Freyther > > The database code should not know about the network. Move the > setting of the network pointer into the subscriber layer. > --- > openbsc/include/openbsc/db.h | 6 ++---- > openbsc/include/openbsc/gsm_subscriber.h | 2 ++ > openbsc/src/libmsc/db.c | 9 +++------ > openbsc/src/libmsc/gsm_04_08.c | 4 ++-- > openbsc/src/libmsc/gsm_subscriber.c | 25 +++++++++++++++++++++---- > openbsc/src/libmsc/vty_interface_layer3.c | 2 +- > openbsc/tests/db/db_test.c | 12 ++++++------ > 7 files changed, 37 insertions(+), 23 deletions(-) > > diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h > index 25c2aea..a89c22d 100644 > --- a/openbsc/include/openbsc/db.h > +++ b/openbsc/include/openbsc/db.h > @@ -35,10 +35,8 @@ int db_prepare(void); > int db_fini(void); > > /* subscriber management */ > -struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, > - char *imsi); > -struct gsm_subscriber *db_get_subscriber(struct gsm_network *net, > - enum gsm_subscriber_field field, > +struct gsm_subscriber *db_create_subscriber(const char *imsi); > +struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field, > const char *subscr); > int db_sync_subscriber(struct gsm_subscriber *subscriber); > int db_subscriber_expire(void *priv, void (*callback)(void *priv, long long unsigned int id)); > diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h > index 6b577b0..7aae4c3 100644 > --- a/openbsc/include/openbsc/gsm_subscriber.h > +++ b/openbsc/include/openbsc/gsm_subscriber.h > @@ -73,6 +73,8 @@ enum gsm_subscriber_update_reason { > > struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr); > struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr); > +struct gsm_subscriber *subscr_create_subscriber(struct gsm_network *net, > + const char *imsi); > struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net, > uint32_t tmsi); > struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net, > diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c > index 9a8cd88..d179c4e 100644 > --- a/openbsc/src/libmsc/db.c > +++ b/openbsc/src/libmsc/db.c > @@ -315,13 +315,13 @@ int db_fini(void) > return 0; > } > > -struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi) > +struct gsm_subscriber *db_create_subscriber(const char *imsi) > { > dbi_result result; > struct gsm_subscriber *subscr; > > /* Is this subscriber known in the db? */ > - subscr = db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi); > + subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, imsi); > if (subscr) { > result = dbi_conn_queryf(conn, > "UPDATE Subscriber set updated = datetime('now') " > @@ -346,7 +346,6 @@ struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi) > ); > if (!result) > LOGP(DDB, LOGL_ERROR, "Failed to create Subscriber by IMSI.\n"); > - subscr->net = net; > subscr->id = dbi_conn_sequence_last(conn, NULL); > strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1); > dbi_result_free(result); > @@ -645,8 +644,7 @@ static void db_set_from_query(struct gsm_subscriber *subscr, dbi_conn result) > } > > #define BASE_QUERY "SELECT * FROM Subscriber " > -struct gsm_subscriber *db_get_subscriber(struct gsm_network *net, > - enum gsm_subscriber_field field, > +struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field, > const char *id) > { > dbi_result result; > @@ -704,7 +702,6 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net, > } > > subscr = subscr_alloc(); > - subscr->net = net; > subscr->id = dbi_result_get_ulonglong(result, "id"); > > db_set_from_query(subscr, result); > diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c > index a299590..c41443e 100644 > --- a/openbsc/src/libmsc/gsm_04_08.c > +++ b/openbsc/src/libmsc/gsm_04_08.c > @@ -474,7 +474,7 @@ static int mm_rx_id_resp(struct gsm_subscriber_connection *conn, struct msgb *ms > if (!conn->subscr) { > conn->subscr = subscr_get_by_imsi(net, mi_string); > if (!conn->subscr) > - conn->subscr = db_create_subscriber(net, mi_string); > + conn->subscr = subscr_create_subscriber(net, mi_string); > } > if (conn->loc_operation) > conn->loc_operation->waiting_for_imsi = 0; > @@ -586,7 +586,7 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb > /* look up subscriber based on IMSI, create if not found */ > subscr = subscr_get_by_imsi(bts->network, mi_string); > if (!subscr) { > - subscr = db_create_subscriber(bts->network, mi_string); > + subscr = subscr_create_subscriber(bts->network, mi_string); > } > break; > case GSM_MI_TYPE_TMSI: > diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c > index 5ace8f6..bc6f3cf 100644 > --- a/openbsc/src/libmsc/gsm_subscriber.c > +++ b/openbsc/src/libmsc/gsm_subscriber.c > @@ -78,6 +78,15 @@ enum { > REQ_STATE_DISPATCHED, > }; > > +static struct gsm_subscriber *get_subscriber(struct gsm_network *net, > + int type, const char *ident) > +{ > + struct gsm_subscriber *subscr = db_get_subscriber(type, ident); > + if (subscr) > + subscr->net = net; > + return subscr; > +} > + > /* > * We got the channel assigned and can now hand this channel > * over to one of our callbacks. > @@ -266,6 +275,14 @@ void subscr_put_channel(struct gsm_subscriber *subscr) > subscr_send_paging_request(subscr); > } > > +struct gsm_subscriber *subscr_create_subscriber(struct gsm_network *net, > + const char *imsi) > +{ > + struct gsm_subscriber *subscr = db_create_subscriber(imsi); > + if (subscr) > + subscr->net = net; > + return subscr; > +} > > struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net, > uint32_t tmsi) > @@ -280,7 +297,7 @@ struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net, > } > > sprintf(tmsi_string, "%u", tmsi); > - return db_get_subscriber(net, GSM_SUBSCRIBER_TMSI, tmsi_string); > + return get_subscriber(net, GSM_SUBSCRIBER_TMSI, tmsi_string); > } > > struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net, > @@ -293,7 +310,7 @@ struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net, > return subscr_get(subscr); > } > > - return db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi); > + return get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi); > } > > struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net, > @@ -306,7 +323,7 @@ struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net, > return subscr_get(subscr); > } > > - return db_get_subscriber(net, GSM_SUBSCRIBER_EXTENSION, ext); > + return get_subscriber(net, GSM_SUBSCRIBER_EXTENSION, ext); > } > > struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net, > @@ -321,7 +338,7 @@ struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net, > return subscr_get(subscr); > } > > - return db_get_subscriber(net, GSM_SUBSCRIBER_ID, buf); > + return get_subscriber(net, GSM_SUBSCRIBER_ID, buf); > } > > int subscr_update_expire_lu(struct gsm_subscriber *s, struct gsm_bts *bts) > diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c > index acb4af7..e0324d6 100644 > --- a/openbsc/src/libmsc/vty_interface_layer3.c > +++ b/openbsc/src/libmsc/vty_interface_layer3.c > @@ -229,7 +229,7 @@ DEFUN(subscriber_create, > struct gsm_network *gsmnet = gsmnet_from_vty(vty); > struct gsm_subscriber *subscr; > > - subscr = db_create_subscriber(gsmnet, argv[0]); > + subscr = subscr_create_subscriber(gsmnet, argv[0]); > if (!subscr) { > vty_out(vty, "%% No subscriber created for IMSI %s%s", > argv[0], VTY_NEWLINE); > diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c > index c3beee2..3c5de90 100644 > --- a/openbsc/tests/db/db_test.c > +++ b/openbsc/tests/db/db_test.c > @@ -78,32 +78,32 @@ int main() > struct gsm_subscriber *alice_db; > > char *alice_imsi = "3243245432345"; > - alice = db_create_subscriber(NULL, alice_imsi); > + alice = db_create_subscriber(alice_imsi); > db_sync_subscriber(alice); > - alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice->imsi); > + alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice->imsi); > COMPARE(alice, alice_db); > SUBSCR_PUT(alice_db); > SUBSCR_PUT(alice); > > alice_imsi = "3693245423445"; > - alice = db_create_subscriber(NULL, alice_imsi); > + alice = db_create_subscriber(alice_imsi); > db_subscriber_assoc_imei(alice, "1234567890"); > db_subscriber_alloc_tmsi(alice); > alice->lac=42; > db_sync_subscriber(alice); > - alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice_imsi); > + alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice_imsi); > COMPARE(alice, alice_db); > SUBSCR_PUT(alice); > SUBSCR_PUT(alice_db); > > alice_imsi = "9993245423445"; > - alice = db_create_subscriber(NULL, alice_imsi); > + alice = db_create_subscriber(alice_imsi); > db_subscriber_alloc_tmsi(alice); > alice->lac=42; > db_sync_subscriber(alice); > db_subscriber_assoc_imei(alice, "1234567890"); > db_subscriber_assoc_imei(alice, "6543560920"); > - alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice_imsi); > + alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice_imsi); > COMPARE(alice, alice_db); > SUBSCR_PUT(alice); > SUBSCR_PUT(alice_db); > -- > 1.8.4.rc3 > > -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From jerlbeck at sysmocom.de Tue Oct 8 10:04:41 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 8 Oct 2013 12:04:41 +0200 Subject: [PATCH 1/7] msgb: Add may_alias attribute to struct libgb_msgb_cb Message-ID: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> This explicitely allows aliasing of this struct to avoid the warning shown below. Note, that this warning isn't show when '-fno-strict-aliasing' is used. Addresses: gb/gprs_ns_test.c:85:54: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] --- include/osmocom/gprs/gprs_msgb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osmocom/gprs/gprs_msgb.h b/include/osmocom/gprs/gprs_msgb.h index f4c8554..e277696 100644 --- a/include/osmocom/gprs/gprs_msgb.h +++ b/include/osmocom/gprs/gprs_msgb.h @@ -16,7 +16,7 @@ struct libgb_msgb_cb { /* Identifier of a MS (inside BTS), equal to 'struct sgsn_mm_ctx' */ uint32_t tlli; -} __attribute__((packed)); +} __attribute__((packed, may_alias)); #define LIBGB_MSGB_CB(__msgb) ((struct libgb_msgb_cb *)&((__msgb)->cb[0])) #define msgb_tlli(__x) LIBGB_MSGB_CB(__x)->tlli #define msgb_nsei(__x) LIBGB_MSGB_CB(__x)->nsei -- 1.7.9.5 From jerlbeck at sysmocom.de Tue Oct 8 10:04:42 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 8 Oct 2013 12:04:42 +0200 Subject: [PATCH 2/7] tests: Fix warnings In-Reply-To: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> References: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381226687-12783-2-git-send-email-jerlbeck@sysmocom.de> This fixes warnings that are raised by missing includes, missing casts, missing return statements, using printf %lu with uint64_t, and unused symbols. --- tests/auth/milenage_test.c | 4 +++- tests/conv/conv_test.c | 2 ++ tests/sms/sms_test.c | 4 +--- tests/smscb/smscb_test.c | 1 + tests/timer/timer_test.c | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/auth/milenage_test.c b/tests/auth/milenage_test.c index 7c996f0..0223764 100644 --- a/tests/auth/milenage_test.c +++ b/tests/auth/milenage_test.c @@ -7,6 +7,8 @@ #include #include +int milenage_opc_gen(uint8_t *opc, const uint8_t *k, const uint8_t *op); + static void dump_auth_vec(struct osmo_auth_vector *vec) { printf("RAND:\t%s\n", osmo_hexdump(vec->rand, sizeof(vec->rand))); @@ -88,7 +90,7 @@ int main(int argc, char **argv) if (rc < 0) { printf("AUTS failed\n"); } else { - printf("AUTS success: SEQ.MS = %lu\n", test_aud.u.umts.sqn); + printf("AUTS success: SEQ.MS = %llu\n", (unsigned long long)test_aud.u.umts.sqn); } opc_test(&test_aud); diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index ab651d4..d9440f9 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -347,6 +347,8 @@ ubit_to_sbit(sbit_t *dst, ubit_t *src, int n) dst[i] = src[i] ? -127 : 127; } +static void sbit_to_ubit(ubit_t *dst, sbit_t *src, int n) __attribute__((unused)); + static void sbit_to_ubit(ubit_t *dst, sbit_t *src, int n) { diff --git a/tests/sms/sms_test.c b/tests/sms/sms_test.c index a79d454..896e134 100644 --- a/tests/sms/sms_test.c +++ b/tests/sms/sms_test.c @@ -266,18 +266,15 @@ static void test_gen_oa(void) int main(int argc, char** argv) { printf("SMS testing\n"); - struct msgb *msg; uint8_t i; uint16_t buffer_size; uint8_t octet_length; int octets_written; uint8_t computed_octet_length; uint8_t septet_length; - uint8_t gsm_septet_length; uint8_t coded[256]; uint8_t tmp[160]; uint8_t septet_data[256]; - uint8_t ud_header[6]; int nchars; char result[256]; @@ -320,6 +317,7 @@ int main(int argc, char** argv) /* Test: encode multiple SMS */ int number_of_septets = gsm_septet_encode(septet_data, (const char *) test_multiple_encode[0].input); + (void) number_of_septets; /* SMS part 1 */ memset(tmp, 0x42, sizeof(tmp)); diff --git a/tests/smscb/smscb_test.c b/tests/smscb/smscb_test.c index e10e12d..5925f69 100644 --- a/tests/smscb/smscb_test.c +++ b/tests/smscb/smscb_test.c @@ -21,6 +21,7 @@ #include #include +#include static uint8_t smscb_msg[] = { 0x40, 0x10, 0x05, 0x0d, 0x01, 0x11 }; diff --git a/tests/timer/timer_test.c b/tests/timer/timer_test.c index bb9a177..b746ace 100644 --- a/tests/timer/timer_test.c +++ b/tests/timer/timer_test.c @@ -115,7 +115,7 @@ static void secondary_timer_fired(void *data) timersub(¤t, &v->stop, &res); if (timercmp(&res, &precision, >)) { fprintf(stderr, "ERROR: timer %p has expired too late!\n", - v->timer); + (void *)&(v->timer)); too_late++; } -- 1.7.9.5 From jerlbeck at sysmocom.de Tue Oct 8 10:04:43 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 8 Oct 2013 12:04:43 +0200 Subject: [PATCH 3/7] tests/gb: Add test for GPRS NS protocol In-Reply-To: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> References: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381226687-12783-3-git-send-email-jerlbeck@sysmocom.de> This tests the connection establishment by directly calling gprs_ns_rcvmsg() and printing the resulting messages and the NS-VC list. --- tests/Makefile.am | 7 +- tests/gb/gprs_ns_test.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++ tests/gb/gprs_ns_test.ok | 124 +++++++++++++++++++++++ tests/testsuite.at | 6 ++ 4 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 tests/gb/gprs_ns_test.c create mode 100644 tests/gb/gprs_ns_test.ok diff --git a/tests/Makefile.am b/tests/Makefile.am index ecb2b6c..1bb26ce 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,7 +4,8 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \ smscb/smscb_test bits/bitrev_test a5/a5_test \ conv/conv_test auth/milenage_test lapd/lapd_test \ gsm0808/gsm0808_test gsm0408/gsm0408_test \ - gb/bssgp_fc_test logging/logging_test fr/fr_test \ + gb/bssgp_fc_test gb/gprs_ns_test \ + logging/logging_test fr/fr_test \ loggingrb/loggingrb_test strrb/strrb_test \ vty/vty_test @@ -51,6 +52,9 @@ ussd_ussd_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gs gb_bssgp_fc_test_SOURCES = gb/bssgp_fc_test.c gb_bssgp_fc_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gb/libosmogb.la +gb_gprs_ns_test_SOURCES = gb/gprs_ns_test.c +gb_gprs_ns_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_DL) + logging_logging_test_SOURCES = logging/logging_test.c logging_logging_test_LDADD = $(top_builddir)/src/libosmocore.la @@ -92,6 +96,7 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \ lapd/lapd_test.ok gsm0408/gsm0408_test.ok \ gsm0808/gsm0808_test.ok gb/bssgp_fc_tests.err \ gb/bssgp_fc_tests.ok gb/bssgp_fc_tests.sh \ + gb/gprs_ns_test.ok \ msgfile/msgfile_test.ok msgfile/msgconfig.cfg \ logging/logging_test.ok logging/logging_test.err \ fr/fr_test.ok loggingrb/logging_test.ok \ diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c new file mode 100644 index 0000000..7423ff9 --- /dev/null +++ b/tests/gb/gprs_ns_test.c @@ -0,0 +1,247 @@ +/* test routines for NS connection handling + * (C) 2013 by Sysmocom GmbH + * Author: Jacob Erlbeck + */ + +#undef _GNU_SOURCE +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* GPRS Network Service, PDU type: NS_RESET, + * Cause: O&M intervention, NS VCI: 0x1122, NSEI 0x1122 + */ +static const unsigned char gprs_ns_reset[12] = { + 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22, + 0x04, 0x82, 0x11, 0x22 +}; + +/* GPRS Network Service, PDU type: NS_RESET, + * Cause: O&M intervention, NS VCI: 0x3344, NSEI 0x1122 + */ +static const unsigned char gprs_ns_reset_vci2[12] = { + 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x33, 0x44, + 0x04, 0x82, 0x11, 0x22 +}; + +/* GPRS Network Service, PDU type: NS_RESET, + * Cause: O&M intervention, NS VCI: 0x1122, NSEI 0x3344 + */ +static const unsigned char gprs_ns_reset_nsei2[12] = { + 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22, + 0x04, 0x82, 0x33, 0x44 +}; + +/* GPRS Network Service, PDU type: NS_ALIVE */ +static const unsigned char gprs_ns_alive[1] = { + 0x0a +}; + +/* GPRS Network Service, PDU type: NS_STATUS, + * Cause: PDU not compatible with the protocol state + * PDU: NS_ALIVE + */ +static const unsigned char gprs_ns_status_invalid_alive[7] = { + 0x08, 0x00, 0x81, 0x0a, 0x02, 0x81, 0x0a +}; + +/* GPRS Network Service, PDU type: NS_ALIVE_ACK */ +static const unsigned char gprs_ns_alive_ack[1] = { + 0x0b +}; + +/* GPRS Network Service, PDU type: NS_UNBLOCK */ +static const unsigned char gprs_ns_unblock[1] = { + 0x06 +}; + + +/* GPRS Network Service, PDU type: NS_STATUS, + * Cause: PDU not compatible with the protocol state + * PDU: NS_RESET_ACK, NS VCI: 0x1122, NSEI 0x1122 + */ +static const unsigned char gprs_ns_status_invalid_reset_ack[15] = { + 0x08, 0x00, 0x81, 0x0a, 0x02, 0x89, 0x03, 0x01, + 0x82, 0x11, 0x22, 0x04, 0x82, 0x11, 0x22 +}; + +/* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0 */ +static const unsigned char gprs_bssgp_reset[22] = { + 0x00, 0x00, 0x00, 0x00, 0x22, 0x04, 0x82, 0x4a, + 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x10, 0x20, + 0x30, 0x40, 0x50, 0x60, 0x10, 0x00 +}; + +int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, + struct sockaddr_in *saddr, enum gprs_ns_ll ll); + +/* override */ +int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, + struct msgb *msg, uint16_t bvci) +{ + printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n", + event, msgb_bssgp_len(msg), bvci, + osmo_hexdump(msgb_bssgph(msg), msgb_bssgp_len(msg))); + return 0; +} + +/* override */ +ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen) +{ + typedef ssize_t (*sendto_t)(int, const void *, size_t, int, + const struct sockaddr *, socklen_t); + static sendto_t real_sendto = NULL; + + if (!real_sendto) + real_sendto = dlsym(RTLD_NEXT, "sendto"); + + if (sockfd != 0xdead && ((struct sockaddr_in *)dest_addr)->sin_addr.s_addr != htonl(0x01020304)) + return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen); + + printf("RESPONSE, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + + return len; +} + +static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len) +{ + struct msgb *msg; + int ret; + if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) { + fprintf(stderr, "message too long: %d\n", data_len); + return -1; + } + + msg = gprs_ns_msgb_alloc(); + memmove(msg->data, data, data_len); + msg->l2h = msg->data; + msgb_put(msg, data_len); + + printf("PROCESSING %s from 0x%08x:%d\n%s\n\n", + text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port), + osmo_hexdump(data, data_len)); + + ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP); + + printf("result (%s) = %d\n\n", text, ret); + + msgb_free(msg); + + return ret; +} + +static void gprs_dump_nsi(struct gprs_ns_inst *nsi) +{ + struct gprs_nsvc *nsvc; + + printf("Current NS-VCIs:\n"); + llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { + struct sockaddr_in *peer = &(nsvc->ip.bts_addr); + printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d\n", + nsvc->nsvci, nsvc->nsei, + ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port) + ); + } + printf("\n"); +} + +static void test_ns() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in peer[4] = {{0},}; + + peer[0].sin_family = AF_INET; + peer[0].sin_port = htons(1111); + peer[0].sin_addr.s_addr = htonl(0x01020304); + peer[1].sin_family = AF_INET; + peer[1].sin_port = htons(2222); + peer[1].sin_addr.s_addr = htonl(0x01020304); + peer[2].sin_family = AF_INET; + peer[2].sin_port = htons(3333); + peer[2].sin_addr.s_addr = htonl(0x01020304); + peer[3].sin_family = AF_INET; + peer[3].sin_port = htons(4444); + peer[3].sin_addr.s_addr = htonl(0x01020304); + + gprs_process_message(nsi, "RESET", &peer[0], + gprs_ns_reset, sizeof(gprs_ns_reset)); + gprs_dump_nsi(nsi); + gprs_process_message(nsi, "ALIVE", &peer[0], + gprs_ns_alive, sizeof(gprs_ns_alive)); + gprs_process_message(nsi, "UNBLOCK", &peer[0], + gprs_ns_unblock, sizeof(gprs_ns_unblock)); + gprs_process_message(nsi, "BSSGP RESET", &peer[0], + gprs_bssgp_reset, sizeof(gprs_bssgp_reset)); + + printf("--- Peer port changes, RESET, message remains unchanged ---\n\n"); + + gprs_process_message(nsi, "RESET", &peer[1], + gprs_ns_reset, sizeof(gprs_ns_reset)); + gprs_dump_nsi(nsi); + + printf("--- Peer port changes, RESET, VCI changes ---\n\n"); + + gprs_process_message(nsi, "RESET", &peer[2], + gprs_ns_reset_vci2, sizeof(gprs_ns_reset_vci2)); + gprs_dump_nsi(nsi); + + printf("--- Peer port changes, RESET, NSEI changes ---\n\n"); + + gprs_process_message(nsi, "RESET", &peer[3], + gprs_ns_reset_nsei2, sizeof(gprs_ns_reset_nsei2)); + gprs_dump_nsi(nsi); + + printf("--- Peer port 3333, RESET, VCI is changed back ---\n\n"); + + gprs_process_message(nsi, "RESET", &peer[2], + gprs_ns_reset, sizeof(gprs_ns_reset)); + gprs_dump_nsi(nsi); + + printf("--- Peer port 4444, RESET, NSEI is changed back ---\n\n"); + + gprs_process_message(nsi, "RESET", &peer[3], + gprs_ns_reset, sizeof(gprs_ns_reset)); + gprs_dump_nsi(nsi); + + gprs_ns_destroy(nsi); + nsi = NULL; +} + + +int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx) +{ + return -1; +} + +static struct log_info info = {}; + +int main(int argc, char **argv) +{ + osmo_init_logging(&info); + log_set_use_color(osmo_stderr_target, 0); + log_set_print_filename(osmo_stderr_target, 0); + + printf("===== NS protocol test START\n"); + test_ns(); + printf("===== NS protocol test END\n\n"); + + exit(EXIT_SUCCESS); +} diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok new file mode 100644 index 0000000..4a44907 --- /dev/null +++ b/tests/gb/gprs_ns_test.ok @@ -0,0 +1,124 @@ +===== NS protocol test START +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 11 22 04 82 11 22 + +RESPONSE, msg length 1 +0a + +RESPONSE, msg length 9 +03 01 82 11 22 04 82 11 22 + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1122, NSEI 0x1122, peer 0x01020304:1111 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +RESPONSE, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +RESPONSE, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING BSSGP RESET from 0x01020304:1111 +00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +CALLBACK, event 0, msg length 18, bvci 0x0000 +22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = 0 + +--- Peer port changes, RESET, message remains unchanged --- + +PROCESSING RESET from 0x01020304:2222 +02 00 81 01 01 82 11 22 04 82 11 22 + +RESPONSE, msg length 1 +0a + +RESPONSE, msg length 9 +03 01 82 11 22 04 82 11 22 + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1122, NSEI 0x1122, peer 0x01020304:2222 + +--- Peer port changes, RESET, VCI changes --- + +PROCESSING RESET from 0x01020304:3333 +02 00 81 01 01 82 33 44 04 82 11 22 + +RESPONSE, msg length 1 +0a + +RESPONSE, msg length 9 +03 01 82 33 44 04 82 11 22 + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333 + +--- Peer port changes, RESET, NSEI changes --- + +PROCESSING RESET from 0x01020304:4444 +02 00 81 01 01 82 11 22 04 82 33 44 + +RESPONSE, msg length 1 +0a + +RESPONSE, msg length 9 +03 01 82 11 22 04 82 33 44 + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 + VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333 + +--- Peer port 3333, RESET, VCI is changed back --- + +PROCESSING RESET from 0x01020304:3333 +02 00 81 01 01 82 11 22 04 82 11 22 + +RESPONSE, msg length 1 +0a + +RESPONSE, msg length 9 +03 01 82 11 22 04 82 11 22 + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 + VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 + +--- Peer port 4444, RESET, NSEI is changed back --- + +PROCESSING RESET from 0x01020304:4444 +02 00 81 01 01 82 11 22 04 82 11 22 + +RESPONSE, msg length 1 +0a + +RESPONSE, msg length 9 +03 01 82 11 22 04 82 11 22 + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444 + VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 + +===== NS protocol test END + diff --git a/tests/testsuite.at b/tests/testsuite.at index 97d0adc..0685832 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -106,6 +106,12 @@ cat $abs_srcdir/vty/vty_test.ok > expout AT_CHECK([$abs_top_builddir/tests/vty/vty_test], [0], [expout], [ignore]) AT_CLEANUP +AT_SETUP([gprs-ns]) +AT_KEYWORDS([gprs-ns]) +cat $abs_srcdir/gb/gprs_ns_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/gb/gprs_ns_test], [0], [expout], [ignore]) +AT_CLEANUP + AT_SETUP([bssgp-fc]) AT_KEYWORDS([bssgp-fc]) cat $abs_srcdir/gb/bssgp_fc_tests.ok > expout -- 1.7.9.5 From jerlbeck at sysmocom.de Tue Oct 8 10:04:44 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 8 Oct 2013 12:04:44 +0200 Subject: [PATCH 4/7] gb: Separate nsvc creation from NS message processing In-Reply-To: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> References: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381226687-12783-4-git-send-email-jerlbeck@sysmocom.de> This patch refactors gprs_ns_rcvmsg() by moving the parts relevant to the NS messages into the new functions gprs_ns_vc_create() (nsvc object creation) and gprs_ns_process_msg() (main NS automaton). These do not contain code that directly depends on the link layer (they call other functions that still do). This reduces the gprs_ns_rcvmsg() function to calling these two functions and optionally setting up the link layer specific fields of the nsvc. --- include/osmocom/gprs/gprs_ns.h | 9 ++ src/gb/gprs_ns.c | 193 ++++++++++++++++++++++++++++------------ 2 files changed, 146 insertions(+), 56 deletions(-) diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index 8ca5a88..c709312 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -49,6 +49,15 @@ enum gprs_ns_evt { GPRS_NS_EVT_UNIT_DATA, }; +/*! \brief Osmocom NS VC create status */ +enum gprs_ns_cs { + GPRS_NS_CS_CREATED, /*!< A NSVC object has been created */ + GPRS_NS_CS_FOUND, /*!< A NSVC object has been found */ + GPRS_NS_CS_REJECTED, /*!< Rejected and answered message */ + GPRS_NS_CS_SKIPPED, /*!< Skipped message */ + GPRS_NS_CS_ERROR, /*!< Failed to process message */ +}; + struct gprs_nsvc; /*! \brief Osmocom GPRS callback function type */ typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 5620b3a..e41c118 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -730,6 +730,13 @@ static int gprs_ns_rx_block(struct gprs_nsvc *nsvc, struct msgb *msg) return gprs_ns_tx_simple(nsvc, NS_PDUT_BLOCK_ACK); } +int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, + struct gprs_nsvc *fallback_nsvc, + struct gprs_nsvc **new_nsvc); + +int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg, + struct gprs_nsvc *nsvc); + /*! \brief Receive incoming NS message from underlying transport layer * \param nsi NS instance to which the data belongs * \param[in] msg message buffer containing newly-received data @@ -743,72 +750,146 @@ static int gprs_ns_rx_block(struct gprs_nsvc *nsvc, struct msgb *msg) int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, struct sockaddr_in *saddr, enum gprs_ns_ll ll) { - struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; struct gprs_nsvc *nsvc; int rc = 0; /* look up the NSVC based on source address */ nsvc = nsvc_by_rem_addr(nsi, saddr); + if (!nsvc) { - struct tlv_parsed tp; - uint16_t nsei; - if (nsh->pdu_type == NS_PDUT_STATUS) { - LOGP(DNS, LOGL_INFO, "Ignoring NS STATUS from %s:%u " - "for non-existing NS-VC\n", - inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port)); - return 0; - } - /* Only the RESET procedure creates a new NSVC */ - if (nsh->pdu_type != NS_PDUT_RESET) { - /* Since we have no NSVC, we have to use a fake */ - nsvc = nsi->unknown_nsvc; - log_set_context(GPRS_CTX_NSVC, nsvc); - LOGP(DNS, LOGL_INFO, "Rejecting NS PDU type 0x%0x " - "from %s:%u for non-existing NS-VC\n", - nsh->pdu_type, inet_ntoa(saddr->sin_addr), - ntohs(saddr->sin_port)); - nsvc->nsvci = nsvc->nsei = 0xfffe; - nsvc->ip.bts_addr = *saddr; - nsvc->state = NSE_S_ALIVE; + struct gprs_nsvc *fallback_nsvc; + + fallback_nsvc = nsi->unknown_nsvc; + log_set_context(GPRS_CTX_NSVC, fallback_nsvc); + fallback_nsvc->ip.bts_addr = *saddr; + fallback_nsvc->ll = ll; + + rc = gprs_ns_vc_create(nsi, msg, fallback_nsvc, &nsvc); + + switch (rc) { + case GPRS_NS_CS_CREATED: + case GPRS_NS_CS_FOUND: nsvc->ll = ll; -#if 0 - return gprs_ns_tx_reset(nsvc, NS_CAUSE_PDU_INCOMP_PSTATE); -#else - return gprs_ns_tx_status(nsvc, - NS_CAUSE_PDU_INCOMP_PSTATE, 0, - msg); -#endif - } - rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, - msgb_l2len(msg) - sizeof(*nsh), 0, 0); - if (rc < 0) { - LOGP(DNS, LOGL_ERROR, "Rx NS RESET Error %d during " - "TLV Parse\n", rc); + break; + case GPRS_NS_CS_SKIPPED: + case GPRS_NS_CS_REJECTED: + break; + default: return rc; } - if (!TLVP_PRESENT(&tp, NS_IE_CAUSE) || - !TLVP_PRESENT(&tp, NS_IE_VCI) || - !TLVP_PRESENT(&tp, NS_IE_NSEI)) { - LOGP(DNS, LOGL_ERROR, "NS RESET Missing mandatory IE\n"); - gprs_ns_tx_status(nsvc, NS_CAUSE_MISSING_ESSENT_IE, 0, - msg); - return -EINVAL; - } - nsei = ntohs(*(uint16_t *)TLVP_VAL(&tp, NS_IE_NSEI)); - /* Check if we already know this NSEI, the remote end might - * simply have changed addresses, or it is a SGSN */ - nsvc = gprs_nsvc_by_nsei(nsi, nsei); - if (!nsvc) { - nsvc = gprs_nsvc_create(nsi, 0xffff); - nsvc->ll = ll; - log_set_context(GPRS_CTX_NSVC, nsvc); - LOGP(DNS, LOGL_INFO, "Creating NS-VC for BSS at %s:%u\n", - inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port)); - } - /* Update the remote peer IP address/port */ + + rc = 0; + } + + if (nsvc) { nsvc->ip.bts_addr = *saddr; - } else - msgb_nsei(msg) = nsvc->nsei; + rc = gprs_ns_process_msg(nsi, msg, nsvc); + } + + return rc; +} + +const char *gprs_ns_format_peer(struct gprs_nsvc *nsvc) +{ + static char buf[80]; + snprintf(buf, sizeof(buf), "%s:%u", + inet_ntoa(nsvc->ip.bts_addr.sin_addr), + ntohs(nsvc->ip.bts_addr.sin_port)); + + return buf; +} + +/*! \brief Create/get NS-VC independently from underlying transport layer + * \param nsi NS instance to which the data belongs + * \param[in] msg message buffer containing newly-received data + * \param[in] fallback_nsvc is used to send error messages back to the peer + * \param[out] new_nsvc contains a pointer to a NS-VC object if one has + * been created or found + * \returns < 0 in case of error, GPRS_NS_CS_SKIPPED if a message has been + * skipped, GPRS_NS_CS_REJECTED if a message has been rejected and + * answered accordingly, GPRS_NS_CS_CREATED if a new NS-VC object + * has been created and registered, and GPRS_NS_CS_FOUND if an + * existing NS-VC object has been found with the same NSEI. + * + * This contains the initial NS automaton state (NS-VC not yet attached). + */ +int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, + struct gprs_nsvc *fallback_nsvc, + struct gprs_nsvc **new_nsvc) +{ + struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *)msg->l2h; + struct gprs_nsvc *existing_nsvc; + + struct tlv_parsed tp; + uint16_t nsei; + + int rc; + + if (nsh->pdu_type == NS_PDUT_STATUS) { + LOGP(DNS, LOGL_INFO, "Ignoring NS STATUS from %s " + "for non-existing NS-VC\n", + gprs_ns_format_peer(fallback_nsvc)); + return GPRS_NS_CS_SKIPPED; + } + /* Only the RESET procedure creates a new NSVC */ + if (nsh->pdu_type != NS_PDUT_RESET) { + /* Since we have no NSVC, we have to use a fake */ + log_set_context(GPRS_CTX_NSVC, fallback_nsvc); + LOGP(DNS, LOGL_INFO, "Rejecting NS PDU type 0x%0x " + "from %s for non-existing NS-VC\n", + nsh->pdu_type, gprs_ns_format_peer(fallback_nsvc)); + fallback_nsvc->nsvci = fallback_nsvc->nsei = 0xfffe; + fallback_nsvc->state = NSE_S_ALIVE; + + return gprs_ns_tx_status(fallback_nsvc, + NS_CAUSE_PDU_INCOMP_PSTATE, 0, msg); + } + rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, + msgb_l2len(msg) - sizeof(*nsh), 0, 0); + if (rc < 0) { + LOGP(DNS, LOGL_ERROR, "Rx NS RESET Error %d during " + "TLV Parse\n", rc); + return rc; + } + if (!TLVP_PRESENT(&tp, NS_IE_CAUSE) || + !TLVP_PRESENT(&tp, NS_IE_VCI) || !TLVP_PRESENT(&tp, NS_IE_NSEI)) { + LOGP(DNS, LOGL_ERROR, "NS RESET Missing mandatory IE\n"); + gprs_ns_tx_status(fallback_nsvc, NS_CAUSE_MISSING_ESSENT_IE, 0, + msg); + return -EINVAL; + } + nsei = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI)); + /* Check if we already know this NSEI, the remote end might + * simply have changed addresses, or it is a SGSN */ + existing_nsvc = gprs_nsvc_by_nsei(nsi, nsei); + if (!existing_nsvc) { + *new_nsvc = gprs_nsvc_create(nsi, 0xffff); + log_set_context(GPRS_CTX_NSVC, *new_nsvc); + LOGP(DNS, LOGL_INFO, "Creating NS-VC for BSS at %s\n", + gprs_ns_format_peer(fallback_nsvc)); + + return GPRS_NS_CS_CREATED; + } + + *new_nsvc = existing_nsvc; + return GPRS_NS_CS_FOUND; +} + +/*! \brief Process NS message independently from underlying transport layer + * \param nsi NS instance to which the data belongs + * \param[in] msg message buffer containing newly-received data + * \param[in] nsvc refers to the virtual connection + * \returns 0 in case of success, < 0 in case of error + * + * This contains the main NS automaton. + */ +int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg, + struct gprs_nsvc *nsvc) +{ + struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; + int rc = 0; + + msgb_nsei(msg) = nsvc->nsei; log_set_context(GPRS_CTX_NSVC, nsvc); -- 1.7.9.5 From jerlbeck at sysmocom.de Tue Oct 8 10:04:45 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 8 Oct 2013 12:04:45 +0200 Subject: [PATCH 5/7] gb: Fix NS-RESET response message order In-Reply-To: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> References: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381226687-12783-5-git-send-email-jerlbeck@sysmocom.de> According to 3GPP TS 08.16, 7.3 "Reset procedure" the entity receiving a NS-RESET PDU responds with a NS-RESET-ACK and 'then' starts the test procedure which essentially means, that a NS-ALIVE gets sent and a timer is started. Currently the NS-ALIVE is sent before the NS-RESET-ACK. This patch fixes the implementation by reversing the order in which these messages are sent. --- src/gb/gprs_ns.c | 12 +++++++----- tests/gb/gprs_ns_test.ok | 36 ++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index e41c118..bba75bc 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -684,15 +684,17 @@ static int gprs_ns_rx_reset(struct gprs_nsvc *nsvc, struct msgb *msg) nsvc->nsei = ntohs(*nsei); nsvc->nsvci = ntohs(*nsvci); - /* start the test procedure */ - gprs_ns_tx_simple(nsvc, NS_PDUT_ALIVE); - nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST); - /* inform interested parties about the fact that this NSVC * has received RESET */ ns_osmo_signal_dispatch(nsvc, S_NS_RESET, *cause); - return gprs_ns_tx_reset_ack(nsvc); + rc = gprs_ns_tx_reset_ack(nsvc); + + /* start the test procedure */ + gprs_ns_tx_simple(nsvc, NS_PDUT_ALIVE); + nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST); + + return rc; } static int gprs_ns_rx_block(struct gprs_nsvc *nsvc, struct msgb *msg) diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 4a44907..049b5e6 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -2,12 +2,12 @@ PROCESSING RESET from 0x01020304:1111 02 00 81 01 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 -0a - RESPONSE, msg length 9 03 01 82 11 22 04 82 11 22 +RESPONSE, msg length 1 +0a + result (RESET) = 9 Current NS-VCIs: @@ -42,12 +42,12 @@ result (BSSGP RESET) = 0 PROCESSING RESET from 0x01020304:2222 02 00 81 01 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 -0a - RESPONSE, msg length 9 03 01 82 11 22 04 82 11 22 +RESPONSE, msg length 1 +0a + result (RESET) = 9 Current NS-VCIs: @@ -58,12 +58,12 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:3333 02 00 81 01 01 82 33 44 04 82 11 22 -RESPONSE, msg length 1 -0a - RESPONSE, msg length 9 03 01 82 33 44 04 82 11 22 +RESPONSE, msg length 1 +0a + result (RESET) = 9 Current NS-VCIs: @@ -74,12 +74,12 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:4444 02 00 81 01 01 82 11 22 04 82 33 44 -RESPONSE, msg length 1 -0a - RESPONSE, msg length 9 03 01 82 11 22 04 82 33 44 +RESPONSE, msg length 1 +0a + result (RESET) = 9 Current NS-VCIs: @@ -91,12 +91,12 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:3333 02 00 81 01 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 -0a - RESPONSE, msg length 9 03 01 82 11 22 04 82 11 22 +RESPONSE, msg length 1 +0a + result (RESET) = 9 Current NS-VCIs: @@ -108,12 +108,12 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:4444 02 00 81 01 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 -0a - RESPONSE, msg length 9 03 01 82 11 22 04 82 11 22 +RESPONSE, msg length 1 +0a + result (RESET) = 9 Current NS-VCIs: -- 1.7.9.5 From jerlbeck at sysmocom.de Tue Oct 8 10:04:46 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 8 Oct 2013 12:04:46 +0200 Subject: [PATCH 6/7] gb: Use the NS-VCI to find an existing NS-VC In-Reply-To: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> References: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381226687-12783-6-git-send-email-jerlbeck@sysmocom.de> Currently when a NS-RESET is recevied over a link that has not yet been associated with a NS-VC, the NSEI is used to find an existing NS-VC. If one is found, the reset procedure is initiated. This behaviour is not conformant with 3GPP TS 08.16 (see chapter 4.2.3) which allows to use several NS-VC between two endpoints in parallel. The patch changes the implementation to use the NSVCI instead of the NSEI to search for an existing NS-VC object. --- src/gb/gprs_ns.c | 8 ++++---- tests/gb/gprs_ns_test.ok | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index bba75bc..4414bd5 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -823,7 +823,7 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, struct gprs_nsvc *existing_nsvc; struct tlv_parsed tp; - uint16_t nsei; + uint16_t nsvci; int rc; @@ -860,10 +860,10 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, msg); return -EINVAL; } - nsei = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI)); - /* Check if we already know this NSEI, the remote end might + nsvci = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_VCI)); + /* Check if we already know this NSVCI, the remote end might * simply have changed addresses, or it is a SGSN */ - existing_nsvc = gprs_nsvc_by_nsei(nsi, nsei); + existing_nsvc = gprs_nsvc_by_nsvci(nsi, nsvci); if (!existing_nsvc) { *new_nsvc = gprs_nsvc_create(nsi, 0xffff); log_set_context(GPRS_CTX_NSVC, *new_nsvc); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 049b5e6..578b905 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -68,6 +68,7 @@ result (RESET) = 9 Current NS-VCIs: VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333 + VCI 0x1122, NSEI 0x1122, peer 0x01020304:2222 --- Peer port changes, RESET, NSEI changes --- @@ -83,8 +84,8 @@ RESPONSE, msg length 1 result (RESET) = 9 Current NS-VCIs: - VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333 + VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 --- Peer port 3333, RESET, VCI is changed back --- @@ -100,8 +101,8 @@ RESPONSE, msg length 1 result (RESET) = 9 Current NS-VCIs: - VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 + VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 --- Peer port 4444, RESET, NSEI is changed back --- @@ -117,8 +118,8 @@ RESPONSE, msg length 1 result (RESET) = 9 Current NS-VCIs: - VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444 VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 + VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444 ===== NS protocol test END -- 1.7.9.5 From jerlbeck at sysmocom.de Tue Oct 8 10:04:47 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 8 Oct 2013 12:04:47 +0200 Subject: [PATCH 7/7] gb: Fix gprs_ns_rx_reset to not create NS-VC duplicates In-Reply-To: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> References: <1381226687-12783-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381226687-12783-7-git-send-email-jerlbeck@sysmocom.de> Under special circumstances receiving a NS-RESET leads to duplicated NS-VC entries. This patch changes gprs_ns_rx_reset() to check for this case and to eventually delete the old entry. This happens when the source port of a NS-VC changes to a new one that has already been used by another NS-VC. --- include/osmocom/gprs/gprs_ns.h | 3 +++ src/gb/gprs_ns.c | 45 +++++++++++++++++++++++++++++++--------- tests/gb/gprs_ns_test.ok | 2 -- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index c709312..562894a 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -117,8 +117,11 @@ struct gprs_nsvc { enum nsvc_timer_mode timer_mode; int alive_retries; + int dup_deletion_ctr; + unsigned int remote_end_is_sgsn:1; unsigned int persistent:1; + unsigned int nsvci_is_valid:1; struct rate_ctr_group *ctrg; diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 4414bd5..8bd1df2 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -83,6 +83,8 @@ #include "common_vty.h" +const char *gprs_ns_format_peer(struct gprs_nsvc *nsvc); + static const struct tlv_definition ns_att_tlvdef = { .def = { [NS_IE_CAUSE] = { TLV_TYPE_TvLV, 0 }, @@ -651,8 +653,8 @@ static int gprs_ns_rx_reset(struct gprs_nsvc *nsvc, struct msgb *msg) { struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; struct tlv_parsed tp; - uint8_t *cause; - uint16_t *nsvci, *nsei; + uint8_t cause; + uint16_t nsvci, nsei; int rc; rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, @@ -671,22 +673,45 @@ static int gprs_ns_rx_reset(struct gprs_nsvc *nsvc, struct msgb *msg) return -EINVAL; } - cause = (uint8_t *) TLVP_VAL(&tp, NS_IE_CAUSE); - nsvci = (uint16_t *) TLVP_VAL(&tp, NS_IE_VCI); - nsei = (uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI); + cause = *(uint8_t *) TLVP_VAL(&tp, NS_IE_CAUSE); + nsvci = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_VCI)); + nsei = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI)); + + LOGP(DNS, LOGL_INFO, "NSVCI=%u%s Rx NS RESET (NSEI=%u, NSVCI=%u, cause=%s)\n", + nsvc->nsvci, nsvc->nsvci_is_valid ? "" : "(invalid)", + nsei, nsvci, gprs_ns_cause_str(cause)); - LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS RESET (NSVCI=%u, cause=%s)\n", - nsvc->nsvci, nsvc->nsei, gprs_ns_cause_str(*cause)); + if (nsvc->nsvci_is_valid && nsvc->nsvci != nsvci) { + /* NS-VCI has changed */ + struct gprs_nsvc *other_nsvc; + other_nsvc = gprs_nsvc_by_nsvci(nsvc->nsi, nsvci); + + if (other_nsvc) { + /* The NS-VCI is already used by this NS-VC */ + + char *old_peer = strdup(gprs_ns_format_peer(other_nsvc)); + LOGP(DNS, LOGL_INFO, + "NS-VC changed link (NSVCI=%u) from %s to %s\n", + nsvci, old_peer, gprs_ns_format_peer(nsvc)); + free(old_peer); + + nsvc->dup_deletion_ctr = 1 + other_nsvc->dup_deletion_ctr; + + /* Delete the 'old' object */ + gprs_nsvc_delete(other_nsvc); + } + } /* Mark NS-VC as blocked and alive */ nsvc->state = NSE_S_BLOCKED | NSE_S_ALIVE; - nsvc->nsei = ntohs(*nsei); - nsvc->nsvci = ntohs(*nsvci); + nsvc->nsei = nsei; + nsvc->nsvci = nsvci; + nsvc->nsvci_is_valid = 1; /* inform interested parties about the fact that this NSVC * has received RESET */ - ns_osmo_signal_dispatch(nsvc, S_NS_RESET, *cause); + ns_osmo_signal_dispatch(nsvc, S_NS_RESET, cause); rc = gprs_ns_tx_reset_ack(nsvc); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 578b905..7416f15 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -102,7 +102,6 @@ result (RESET) = 9 Current NS-VCIs: VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 - VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 --- Peer port 4444, RESET, NSEI is changed back --- @@ -118,7 +117,6 @@ RESPONSE, msg length 1 result (RESET) = 9 Current NS-VCIs: - VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444 ===== NS protocol test END -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 9 09:27:04 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Wed, 9 Oct 2013 11:27:04 +0200 Subject: [PATCH 1/2] tests/gb: Show invoked signals in test output In-Reply-To: <1381226687-12783-7-git-send-email-jerlbeck@sysmocom.de> References: <1381226687-12783-7-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381310825-26453-1-git-send-email-jerlbeck@sysmocom.de> Register an osmo signal handler to print a short notice about every SS_L_NS signal that is generated while processing the tests. Sponsored-by: On-Waves ehf --- include/osmocom/gprs/gprs_ns.h | 3 +++ src/gb/libosmogb.map | 1 + tests/gb/gprs_ns_test.c | 46 +++++++++++++++++++++++++++++++++++++++- tests/gb/gprs_ns_test.ok | 7 ++++++ 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index c709312..d16068b 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -176,6 +176,9 @@ void gprs_nsvc_reset(struct gprs_nsvc *nsvc, uint8_t cause); /* Add NS-specific VTY stuff */ int gprs_ns_vty_init(struct gprs_ns_inst *nsi); +/* Resturn peer info as string (NOTE: the buffer is allocated statically) */ +const char *gprs_ns_format_peer(struct gprs_nsvc *nsvc); + #define NS_ALLOC_SIZE 2048 #define NS_ALLOC_HEADROOM 20 static inline struct msgb *gprs_ns_msgb_alloc(void) diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map index 7af085c..0270db8 100644 --- a/src/gb/libosmogb.map +++ b/src/gb/libosmogb.map @@ -54,6 +54,7 @@ gprs_ns_tx_reset; gprs_ns_tx_status; gprs_ns_tx_unblock; gprs_ns_vty_init; +gprs_ns_format_peer; gprs_nsvc_create; gprs_nsvc_delete; diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index d07cc3d..d41fccb 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -20,11 +20,11 @@ #include #include #include +#include #include #include #include - /* GPRS Network Service, PDU type: NS_RESET, * Cause: O&M intervention, NS VCI: 0x1122, NSEI 0x1122 */ @@ -121,6 +121,49 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, return len; } +/* Signal handler for signals from NS layer */ +static int test_signal(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct ns_signal_data *nssd = signal_data; + + if (subsys != SS_L_NS) + return 0; + + switch (signal) { + case S_NS_RESET: + printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + + case S_NS_ALIVE_EXP: + printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + + case S_NS_BLOCK: + printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + + case S_NS_UNBLOCK: + printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + + default: + printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal, + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + } + return 0; +} + static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len) { struct msgb *msg; @@ -238,6 +281,7 @@ int main(int argc, char **argv) osmo_init_logging(&info); log_set_use_color(osmo_stderr_target, 0); log_set_print_filename(osmo_stderr_target, 0); + osmo_signal_register_handler(SS_L_NS, &test_signal, NULL); printf("===== NS protocol test START\n"); test_ns(); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 578b905..01b1bc9 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -2,6 +2,7 @@ PROCESSING RESET from 0x01020304:1111 02 00 81 01 01 82 11 22 04 82 11 22 +==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:1111 RESPONSE, msg length 9 03 01 82 11 22 04 82 11 22 @@ -24,6 +25,7 @@ result (ALIVE) = 1 PROCESSING UNBLOCK from 0x01020304:1111 06 +==> got signal NS_UNBLOCK, NS-VC 0x1122/1.2.3.4:1111 RESPONSE, msg length 1 07 @@ -42,6 +44,7 @@ result (BSSGP RESET) = 0 PROCESSING RESET from 0x01020304:2222 02 00 81 01 01 82 11 22 04 82 11 22 +==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:2222 RESPONSE, msg length 9 03 01 82 11 22 04 82 11 22 @@ -58,6 +61,7 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:3333 02 00 81 01 01 82 33 44 04 82 11 22 +==> got signal NS_RESET, NS-VC 0x3344/1.2.3.4:3333 RESPONSE, msg length 9 03 01 82 33 44 04 82 11 22 @@ -75,6 +79,7 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:4444 02 00 81 01 01 82 11 22 04 82 33 44 +==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:4444 RESPONSE, msg length 9 03 01 82 11 22 04 82 33 44 @@ -92,6 +97,7 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:3333 02 00 81 01 01 82 11 22 04 82 11 22 +==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:3333 RESPONSE, msg length 9 03 01 82 11 22 04 82 11 22 @@ -109,6 +115,7 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:4444 02 00 81 01 01 82 11 22 04 82 11 22 +==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:4444 RESPONSE, msg length 9 03 01 82 11 22 04 82 11 22 -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 9 09:27:05 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Wed, 9 Oct 2013 11:27:05 +0200 Subject: [PATCH 2/2] gb: Fix gprs_ns_rx_reset to not create NS-VC duplicates In-Reply-To: <1381310825-26453-1-git-send-email-jerlbeck@sysmocom.de> References: <1381226687-12783-7-git-send-email-jerlbeck@sysmocom.de> <1381310825-26453-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381310825-26453-2-git-send-email-jerlbeck@sysmocom.de> Under special circumstances (see below) receiving a NS-RESET leads to duplicated NS-VC entries. This patch changes gprs_ns_rx_reset() to check for this case and to eventually delete the old entry. A new counter NS_CTR_REPLACED is incremented each time when the NS-VC object is replaced. A new signal S_NS_REPLACED is added which gets dispatched in this case, too. This happens when the source port of a NS-VC changes to a new one that has already been used by another NS-VC. --- include/osmocom/gprs/gprs_ns.h | 3 ++ src/gb/gprs_ns.c | 83 ++++++++++++++++++++++++++++++++-------- tests/gb/gprs_ns_test.c | 9 +++++ tests/gb/gprs_ns_test.ok | 3 +- 4 files changed, 79 insertions(+), 19 deletions(-) diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index d16068b..cfcf8e2 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -119,6 +119,7 @@ struct gprs_nsvc { unsigned int remote_end_is_sgsn:1; unsigned int persistent:1; + unsigned int nsvci_is_valid:1; struct rate_ctr_group *ctrg; @@ -191,10 +192,12 @@ enum signal_ns { S_NS_BLOCK, S_NS_UNBLOCK, S_NS_ALIVE_EXP, /* Tns-alive expired more than N times */ + S_NS_REPLACED, /* nsvc object is replaced (sets old_nsvc) */ }; struct ns_signal_data { struct gprs_nsvc *nsvc; + struct gprs_nsvc *old_nsvc; uint8_t cause; }; diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index b5f91c4..03f39ef 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -100,15 +100,17 @@ enum ns_ctr { NS_CTR_BYTES_OUT, NS_CTR_BLOCKED, NS_CTR_DEAD, + NS_CTR_REPLACED, }; static const struct rate_ctr_desc nsvc_ctr_description[] = { - { "packets.in", "Packets at NS Level ( In)" }, - { "packets.out","Packets at NS Level (Out)" }, - { "bytes.in", "Bytes at NS Level ( In)" }, - { "bytes.out", "Bytes at NS Level (Out)" }, - { "blocked", "NS-VC Block count " }, - { "dead", "NS-VC gone dead count " }, + { "packets.in", "Packets at NS Level ( In)" }, + { "packets.out","Packets at NS Level (Out)" }, + { "bytes.in", "Bytes at NS Level ( In)" }, + { "bytes.out", "Bytes at NS Level (Out)" }, + { "blocked", "NS-VC Block count " }, + { "dead", "NS-VC gone dead count " }, + { "replaced", "NS-VC replaced other count" }, }; static const struct rate_ctr_group_desc nsvc_ctrg_desc = { @@ -198,7 +200,7 @@ void gprs_nsvc_delete(struct gprs_nsvc *nsvc) static void ns_osmo_signal_dispatch(struct gprs_nsvc *nsvc, unsigned int signal, uint8_t cause) { - struct ns_signal_data nssd; + struct ns_signal_data nssd = {0}; nssd.nsvc = nsvc; nssd.cause = cause; @@ -206,6 +208,16 @@ static void ns_osmo_signal_dispatch(struct gprs_nsvc *nsvc, unsigned int signal, osmo_signal_dispatch(SS_L_NS, signal, &nssd); } +static void ns_osmo_signal_dispatch_replaced(struct gprs_nsvc *nsvc, struct gprs_nsvc *old_nsvc) +{ + struct ns_signal_data nssd = {0}; + + nssd.nsvc = nsvc; + nssd.old_nsvc = old_nsvc; + + osmo_signal_dispatch(SS_L_NS, S_NS_REPLACED, &nssd); +} + /* Section 10.3.2, Table 13 */ static const struct value_string ns_cause_str[] = { { NS_CAUSE_TRANSIT_FAIL, "Transit network failure" }, @@ -651,8 +663,9 @@ static int gprs_ns_rx_reset(struct gprs_nsvc *nsvc, struct msgb *msg) { struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; struct tlv_parsed tp; - uint8_t *cause; - uint16_t *nsvci, *nsei; + uint8_t cause; + uint16_t nsvci, nsei; + struct gprs_nsvc *other_nsvc = NULL; int rc; rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, @@ -671,22 +684,58 @@ static int gprs_ns_rx_reset(struct gprs_nsvc *nsvc, struct msgb *msg) return -EINVAL; } - cause = (uint8_t *) TLVP_VAL(&tp, NS_IE_CAUSE); - nsvci = (uint16_t *) TLVP_VAL(&tp, NS_IE_VCI); - nsei = (uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI); + cause = *(uint8_t *) TLVP_VAL(&tp, NS_IE_CAUSE); + nsvci = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_VCI)); + nsei = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI)); + + LOGP(DNS, LOGL_INFO, "NSVCI=%u%s Rx NS RESET (NSEI=%u, NSVCI=%u, cause=%s)\n", + nsvc->nsvci, nsvc->nsvci_is_valid ? "" : "(invalid)", + nsei, nsvci, gprs_ns_cause_str(cause)); - LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS RESET (NSVCI=%u, cause=%s)\n", - nsvc->nsvci, nsvc->nsei, gprs_ns_cause_str(*cause)); + if (nsvc->nsvci_is_valid && nsvc->nsvci != nsvci) { + /* NS-VCI has changed */ + other_nsvc = gprs_nsvc_by_nsvci(nsvc->nsi, nsvci); + + if (other_nsvc) { + /* The NS-VCI is already used by this NS-VC */ + + struct rate_ctr_group *tmp_ctrg; + char *old_peer = + talloc_strdup(nsvc, gprs_ns_format_peer(other_nsvc)); + + LOGP(DNS, LOGL_INFO, + "NS-VC changed link (NSVCI=%u) from %s to %s\n", + nsvci, old_peer, gprs_ns_format_peer(nsvc)); + + talloc_free(old_peer); + + /* Exchange the counters */ + tmp_ctrg = nsvc->ctrg; + nsvc->ctrg = talloc_move(nsvc, &other_nsvc->ctrg); + other_nsvc->ctrg = talloc_move(other_nsvc, &tmp_ctrg); + + rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_REPLACED]); + } + } /* Mark NS-VC as blocked and alive */ nsvc->state = NSE_S_BLOCKED | NSE_S_ALIVE; - nsvc->nsei = ntohs(*nsei); - nsvc->nsvci = ntohs(*nsvci); + nsvc->nsei = nsei; + nsvc->nsvci = nsvci; + nsvc->nsvci_is_valid = 1; + + if (other_nsvc) { + ns_osmo_signal_dispatch_replaced(nsvc, other_nsvc); + + /* Delete the 'old' object */ + gprs_nsvc_delete(other_nsvc); + other_nsvc = NULL; + } /* inform interested parties about the fact that this NSVC * has received RESET */ - ns_osmo_signal_dispatch(nsvc, S_NS_RESET, *cause); + ns_osmo_signal_dispatch(nsvc, S_NS_RESET, cause); rc = gprs_ns_tx_reset_ack(nsvc); diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index d41fccb..67e2eb9 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -155,6 +155,15 @@ static int test_signal(unsigned int subsys, unsigned int signal, gprs_ns_format_peer(nssd->nsvc)); break; + case S_NS_REPLACED: + printf("==> got signal NS_REPLACED: 0x%04x/%s", + nssd->old_nsvc->nsvci, + gprs_ns_format_peer(nssd->old_nsvc)); + printf(" -> 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + default: printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal, nssd->nsvc->nsvci, diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 01b1bc9..cc9e76c 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -97,6 +97,7 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:3333 02 00 81 01 01 82 11 22 04 82 11 22 +==> got signal NS_REPLACED: 0x1122/1.2.3.4:4444 -> 0x1122/1.2.3.4:3333 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:3333 RESPONSE, msg length 9 03 01 82 11 22 04 82 11 22 @@ -108,7 +109,6 @@ result (RESET) = 9 Current NS-VCIs: VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 - VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 --- Peer port 4444, RESET, NSEI is changed back --- @@ -125,7 +125,6 @@ RESPONSE, msg length 1 result (RESET) = 9 Current NS-VCIs: - VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444 ===== NS protocol test END -- 1.7.9.5 From holger at freyther.de Wed Oct 9 13:35:28 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Wed, 9 Oct 2013 15:35:28 +0200 Subject: [PATCH 2/2] gb: Fix gprs_ns_rx_reset to not create NS-VC duplicates In-Reply-To: <1381310825-26453-2-git-send-email-jerlbeck@sysmocom.de> References: <1381226687-12783-7-git-send-email-jerlbeck@sysmocom.de> <1381310825-26453-1-git-send-email-jerlbeck@sysmocom.de> <1381310825-26453-2-git-send-email-jerlbeck@sysmocom.de> Message-ID: <20131009133528.GS6194@xiaoyu.lan> On Wed, Oct 09, 2013 at 11:27:05AM +0200, Jacob Erlbeck wrote: Hi, > This happens when the source port of a NS-VC changes to a new one > that has already been used by another NS-VC. these two patches looks good (minor style/indent issue with the switch/case in the previous patch). We have a semantic change now (deleting nsvc's) and we have ABI changes. So what I would like to do is to merge your changes, bump the SO_VERSION, make a release and then make gbpoxy/OpenBSC depend on the latest libosmocore release. I think we have some more API changes coming up? holger From jerlbeck at sysmocom.de Wed Oct 9 13:41:07 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Wed, 09 Oct 2013 15:41:07 +0200 Subject: [PATCH 2/2] gb: Fix gprs_ns_rx_reset to not create NS-VC duplicates In-Reply-To: <20131009133528.GS6194@xiaoyu.lan> References: <1381226687-12783-7-git-send-email-jerlbeck@sysmocom.de> <1381310825-26453-1-git-send-email-jerlbeck@sysmocom.de> <1381310825-26453-2-git-send-email-jerlbeck@sysmocom.de> <20131009133528.GS6194@xiaoyu.lan> Message-ID: <52555CF3.20200@sysmocom.de> Hi, On 10/09/2013 03:35 PM, Holger Hans Peter Freyther wrote: > We have a semantic change now > (deleting nsvc's) and we have ABI changes. So what I would like > to do is to merge your changes, bump the SO_VERSION, make a release > and then make gbpoxy/OpenBSC depend on the latest libosmocore > release. > > I think we have some more API changes coming up? If we address the usage of NSEI instead of NSVCI at the BSSGP layer we'll probably have. Jacob From ciaby at autistici.org Fri Oct 11 04:12:50 2013 From: ciaby at autistici.org (Ciaby) Date: Thu, 10 Oct 2013 23:12:50 -0500 Subject: token based authentication Message-ID: <52577AC2.7060306@autistici.org> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 Hi everyone, we (Rhizomatica.org) are currently setting up a OpenBSC-based network in Oaxaca, Mexico. I've been looking into the code and found the token-based authentication which was used at the HAR2009 (I still remember receiving that SMS) :) I understand that each phone will get an SMS and then disconnect from the network. What is the API to confirm the token and activate the account? I vaguely remember a web interface at the time, but I could be wrong... Thanks a lot! Ciaby -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iF4EAREKAAYFAlJXerwACgkQC30ZhxNccpFbuAEAjJN+DEjz5rlYBbYJeBw2884e SuSvNHud+XfcDJL0IaYBAJFFIJbEG6XtdTADCt4lyvdaRcbTDn0B2f9NZEod8kJU =KqiR -----END PGP SIGNATURE----- From ciaby at autistici.org Fri Oct 11 04:19:01 2013 From: ciaby at autistici.org (Ciaby) Date: Thu, 10 Oct 2013 23:19:01 -0500 Subject: token based authentication In-Reply-To: <52577AC2.7060306@autistici.org> References: <52577AC2.7060306@autistici.org> Message-ID: <52577C35.4040301@autistici.org> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 On 10/10/2013 11:12 PM, Ciaby wrote: > Hi everyone, we (Rhizomatica.org) are currently setting up a > OpenBSC-based network in Oaxaca, Mexico. I've been looking into the > code and found the token-based authentication which was used at the > HAR2009 (I still remember receiving that SMS) :) I understand that > each phone will get an SMS and then disconnect from the network. > What is the API to confirm the token and activate the account? I > vaguely remember a web interface at the time, but I could be > wrong... Thanks a lot! Ok, I can just reply to myself... I just looked at the code, apparently the user is created, a number is assigned, it sends an sms to the user and then sets authorized=0. We can just set it back to 1 and activate it. Sorry for the spam, I should have looked at the code first :) Cheers Ciaby -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iF4EAREKAAYFAlJXfC0ACgkQC30ZhxNccpEaVAEAk9Dcto4VfwAc37qX5Gg7YhM5 YgjFfmFRPzRNIN73ECwBAK9oWnEKcqOOGLUcgDBNuKfN3qnwuUCOXJB+okzIn2WM =XjJ3 -----END PGP SIGNATURE----- From alexander.chemeris at gmail.com Fri Oct 11 04:34:49 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 11 Oct 2013 08:34:49 +0400 Subject: token based authentication In-Reply-To: <52577AC2.7060306@autistici.org> References: <52577AC2.7060306@autistici.org> Message-ID: Ciaby, I believe it directly accessed the hlr.sqlite3 database. Or, more likely, synchronized with it once in a while (like every 30 min). The only thing this web-interface should do is to set "authorized" bit in the DB and (optionally) update user's extension number. On Fri, Oct 11, 2013 at 8:12 AM, Ciaby wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA512 > > Hi everyone, > we (Rhizomatica.org) are currently setting up a OpenBSC-based network > in Oaxaca, Mexico. I've been looking into the code and found the > token-based authentication which was used at the HAR2009 (I still > remember receiving that SMS) :) > I understand that each phone will get an SMS and then disconnect from > the network. What is the API to confirm the token and activate the > account? I vaguely remember a web interface at the time, but I could > be wrong... > Thanks a lot! > > Ciaby > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.11 (GNU/Linux) > Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ > > iF4EAREKAAYFAlJXerwACgkQC30ZhxNccpFbuAEAjJN+DEjz5rlYBbYJeBw2884e > SuSvNHud+XfcDJL0IaYBAJFFIJbEG6XtdTADCt4lyvdaRcbTDn0B2f9NZEod8kJU > =KqiR > -----END PGP SIGNATURE----- > -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From peter at stuge.se Fri Oct 11 05:20:14 2013 From: peter at stuge.se (Peter Stuge) Date: Fri, 11 Oct 2013 07:20:14 +0200 Subject: token based authentication In-Reply-To: References: <52577AC2.7060306@autistici.org> Message-ID: <20131011052014.1563.qmail@stuge.se> Alexander Chemeris wrote: > I believe it directly accessed the hlr.sqlite3 database. Don't do that. Script around the VTY so that changes take effect immediately and all internal state is updated correctly. //Peter From alexander.chemeris at gmail.com Fri Oct 11 05:53:56 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 11 Oct 2013 09:53:56 +0400 Subject: token based authentication In-Reply-To: <20131011052014.1563.qmail@stuge.se> References: <52577AC2.7060306@autistici.org> <20131011052014.1563.qmail@stuge.se> Message-ID: On Fri, Oct 11, 2013 at 9:20 AM, Peter Stuge wrote: > Alexander Chemeris wrote: >> I believe it directly accessed the hlr.sqlite3 database. > > Don't do that. Script around the VTY so that changes take effect > immediately and all internal state is updated correctly. Yes, good idea. -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From jerlbeck at sysmocom.de Fri Oct 11 20:23:12 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Fri, 11 Oct 2013 22:23:12 +0200 Subject: [PATCH 1/2] gbproxy: Add test program to test gbproxy message handling Message-ID: <1381522993-30535-1-git-send-email-jerlbeck@sysmocom.de> This program tests the gbproxy implementation by passing NS messages to a modified gbproxy that dumps the resulting messages, signals, and state. It focusses on testing abnormal situations like port changes. Ticket: OW#874 Sponsored-by: On-Waves ehf --- openbsc/configure.ac | 1 + openbsc/include/openbsc/gb_proxy.h | 1 + openbsc/src/gprs/gb_proxy.c | 23 ++ openbsc/tests/Makefile.am | 2 +- openbsc/tests/gbproxy/Makefile.am | 18 ++ openbsc/tests/gbproxy/gbproxy_test.c | 403 +++++++++++++++++++++++++++++++++ openbsc/tests/gbproxy/gbproxy_test.ok | 357 +++++++++++++++++++++++++++++ openbsc/tests/testsuite.at | 6 + 8 files changed, 810 insertions(+), 1 deletion(-) create mode 100644 openbsc/tests/gbproxy/Makefile.am create mode 100644 openbsc/tests/gbproxy/gbproxy_test.c create mode 100644 openbsc/tests/gbproxy/gbproxy_test.ok diff --git a/openbsc/configure.ac b/openbsc/configure.ac index ddd15e3..531efcf 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -162,6 +162,7 @@ AC_OUTPUT( tests/bsc-nat-trie/Makefile tests/mgcp/Makefile tests/gprs/Makefile + tests/gbproxy/Makefile tests/si/Makefile tests/abis/Makefile tests/smpp/Makefile diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 2c8ddb3..56b1b3d 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -35,4 +35,5 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, /* Reset all persistent NS-VC's */ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi); +int gbprox_dump_peers(FILE *stream, int indent); #endif diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index b99c455..3a9fe81 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -658,6 +658,29 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, return 0; } +int gbprox_dump_peers(FILE *stream, int indent) +{ + struct gbprox_peer *peer; + struct gprs_ra_id raid; + int rc; + + fprintf(stream, "%*sPeers:\n", indent, ""); + llist_for_each_entry(peer, &gbprox_bts_peers, list) { + gsm48_parse_ra(&raid, peer->ra); + + rc = fprintf(stream, "%*s NSEI %u, BVCI %u, %sblocked, " + "RAC %u-%u-%u-%u\n", + indent, "", + peer->nsvc->nsei, peer->bvci, + peer->blocked ? "" : "not ", + raid.mcc, raid.mnc, raid.lac, raid.rac); + + if (rc < 0) + return rc; + } + + return 0; +} #include diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am index ed21fc3..7f51bfa 100644 --- a/openbsc/tests/Makefile.am +++ b/openbsc/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = gsm0408 db channel mgcp gprs si abis +SUBDIRS = gsm0408 db channel mgcp gprs si abis gbproxy if BUILD_NAT SUBDIRS += bsc-nat bsc-nat-trie diff --git a/openbsc/tests/gbproxy/Makefile.am b/openbsc/tests/gbproxy/Makefile.am new file mode 100644 index 0000000..1323d44 --- /dev/null +++ b/openbsc/tests/gbproxy/Makefile.am @@ -0,0 +1,18 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) +AM_LDFLAGS = $(COVERAGE_LDFLAGS) + +EXTRA_DIST = gbproxy_test.ok + +noinst_PROGRAMS = gbproxy_test + +gbproxy_test_SOURCES = gbproxy_test.c +gbproxy_test_LDADD = \ + $(top_builddir)/src/gprs/gb_proxy.o \ + $(top_builddir)/src/libcommon/libcommon.a \ + $(top_builddir)/src/libbsc/libbsc.a \ + $(top_builddir)/src/libtrau/libtrau.a \ + $(LIBOSMOCORE_LIBS) $(LIBOSMOGB_LIBS) \ + $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \ + $(LIBOSMOABIS_LIBS) \ + -lrt diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c new file mode 100644 index 0000000..22183f4 --- /dev/null +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -0,0 +1,403 @@ +/* test routines for gbproxy + * send NS messages to the gbproxy and dumps what happens + * (C) 2013 by sysmocom s.f.m.c. GmbH + * Author: Jacob Erlbeck + */ + +#undef _GNU_SOURCE +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define REMOTE_BSS_ADDR 0x01020304 +#define REMOTE_SGSN_ADDR 0x05060708 + +#define SGSN_NSEI 0xfffe + +struct gbproxy_config gbcfg; + +static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len); + +static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + enum ns_cause cause, uint16_t nsvci, uint16_t nsei) +{ + /* GPRS Network Service, PDU type: NS_RESET, + */ + unsigned char msg[12] = { + 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22, + 0x04, 0x82, 0x11, 0x22 + }; + + msg[3] = cause; + msg[6] = nsvci / 256; + msg[7] = nsvci % 256; + msg[10] = nsei / 256; + msg[11] = nsei % 256; + + gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg)); +} + +static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_ALIVE */ + unsigned char msg[1] = { + 0x0a + }; + + gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg)); +} + +static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_ALIVE_ACK */ + unsigned char msg[1] = { + 0x0b + }; + + gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_UNBLOCK */ + unsigned char msg[1] = { + 0x06 + }; + + gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unitdata(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsbvci, + const unsigned char *bssgp_msg, size_t bssgp_msg_size) +{ + /* GPRS Network Service, PDU type: NS_UNITDATA */ + unsigned char msg[4096] = { + 0x00, 0x00, 0x00, 0x00 + }; + + OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4); + + msg[2] = nsbvci / 256; + msg[3] = nsbvci % 256; + memcpy(msg + 4, bssgp_msg, bssgp_msg_size); + + gprs_process_message(nsi, "UNITDATA", src_addr, msg, bssgp_msg_size + 4); +} + +static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t bvci) +{ + /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0 + * BSSGP RESET */ + unsigned char msg[22] = { + 0x22, 0x04, 0x82, 0x4a, + 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x10, 0x20, + 0x30, 0x40, 0x50, 0x60, 0x10, 0x00 + }; + + msg[3] = bvci / 256; + msg[4] = bvci % 256; + + send_ns_unitdata(nsi, src_addr, 0, msg, sizeof(msg)); +} + +static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsvci, uint16_t nsei) +{ + printf("Setup NS-VC: remote 0x%08x:%d, " + "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n", + ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port), + nsvci, nsvci, nsei, nsei); + + send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei); + send_ns_alive(nsi, src_addr); + send_ns_unblock(nsi, src_addr); + send_ns_alive_ack(nsi, src_addr); +} + +static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t bvci) +{ + printf("Setup BSSGP: remote 0x%08x:%d, " + "BVCI 0x%04x(%d)\n\n", + ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port), + bvci, bvci); + + send_bssgp_reset(nsi, src_addr, bvci); +} + +int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, + struct sockaddr_in *saddr, enum gprs_ns_ll ll); + +/* override */ +int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, + struct msgb *msg, uint16_t bvci) +{ + printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n", + event, msgb_bssgp_len(msg), bvci, + osmo_hexdump(msgb_bssgph(msg), msgb_bssgp_len(msg))); + + switch (event) { + case GPRS_NS_EVT_UNIT_DATA: + return gbprox_rcvmsg(msg, nsvc, bvci); + default: + break; + } + return 0; +} + +/* override */ +ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen) +{ + typedef ssize_t (*sendto_t)(int, const void *, size_t, int, + const struct sockaddr *, socklen_t); + static sendto_t real_sendto = NULL; + uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr); + + if (!real_sendto) + real_sendto = dlsym(RTLD_NEXT, "sendto"); + + if (dest_host == REMOTE_BSS_ADDR) + printf("MESSAGE to BSS, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + else if (dest_host == REMOTE_SGSN_ADDR) + printf("MESSAGE to SGSN, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + else + return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen); + + return len; +} + +/* override */ +int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) +{ + uint16_t bvci = msgb_bvci(msg); + uint16_t nsei = msgb_nsei(msg); + + unsigned char *buf = msg->data; + size_t len = msg->len; + + if (nsei == SGSN_NSEI) + printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, msg length %d\n%s\n\n", + bvci, len, osmo_hexdump(buf, len)); + else + printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, msg length %d\n%s\n\n", + bvci, len, osmo_hexdump(buf, len)); + + return 0; +} + +/* Signal handler for signals from NS layer */ +static int test_signal(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct ns_signal_data *nssd = signal_data; + int rc; + + if (subsys != SS_L_NS) + return 0; + + switch (signal) { + case S_NS_RESET: + printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + + case S_NS_ALIVE_EXP: + printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + + case S_NS_BLOCK: + printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + + case S_NS_UNBLOCK: + printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + + case S_NS_REPLACED: + printf("==> got signal NS_REPLACED: 0x%04x/%s", + nssd->old_nsvc->nsvci, + gprs_ns_format_peer(nssd->old_nsvc)); + printf(" -> 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + + default: + printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal, + nssd->nsvc->nsvci, + gprs_ns_format_peer(nssd->nsvc)); + break; + } + printf("\n"); + rc = gbprox_signal(subsys, signal, handler_data, signal_data); + + switch (signal) { + case S_NS_REPLACED: + /* invalidate NSVCI */ + nssd->old_nsvc->nsvci = 0xfffe; + nssd->old_nsvc->nsvci_is_valid = 0; + break; + + default: + break; + } + return rc; +} + +static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len) +{ + struct msgb *msg; + int ret; + if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) { + fprintf(stderr, "message too long: %d\n", data_len); + return -1; + } + + msg = gprs_ns_msgb_alloc(); + memmove(msg->data, data, data_len); + msg->l2h = msg->data; + msgb_put(msg, data_len); + + printf("PROCESSING %s from 0x%08x:%d\n%s\n\n", + text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port), + osmo_hexdump(data, data_len)); + + ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP); + + printf("result (%s) = %d\n\n", text, ret); + + msgb_free(msg); + + return ret; +} + +static void gprs_dump_nsi(struct gprs_ns_inst *nsi) +{ + struct gprs_nsvc *nsvc; + + printf("Current NS-VCIs:\n"); + llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { + struct sockaddr_in *peer = &(nsvc->ip.bts_addr); + printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d\n", + nsvc->nsvci, nsvc->nsei, + ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port) + ); + } + printf("\n"); +} + +static void test_gbproxy() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in bss_peer[4] = {{0},}; + + bssgp_nsi = nsi; + gbcfg.nsi = bssgp_nsi; + gbcfg.nsip_sgsn_nsei = SGSN_NSEI; + + bss_peer[0].sin_family = AF_INET; + bss_peer[0].sin_port = htons(1111); + bss_peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + bss_peer[1].sin_family = AF_INET; + bss_peer[1].sin_port = htons(2222); + bss_peer[1].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + bss_peer[2].sin_family = AF_INET; + bss_peer[2].sin_port = htons(3333); + bss_peer[2].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + bss_peer[3].sin_family = AF_INET; + bss_peer[3].sin_port = htons(4444); + bss_peer[3].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + + printf("--- Initialise BSS 1 ---\n\n"); + + setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); + setup_bssgp(nsi, &bss_peer[0], 0x1002); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Initialise BSS 2 ---\n\n"); + + setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000); + setup_bssgp(nsi, &bss_peer[1], 0x2002); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Move BSS 1 to new port ---\n\n"); + + setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Move BSS 2 to former BSS 1 port ---\n\n"); + + setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Move BSS 1 to current BSS 2 port ---\n\n"); + + setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Move BSS 2 to new port ---\n\n"); + + setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Move BSS 2 to former BSS 1 port ---\n\n"); + + setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + gprs_ns_destroy(nsi); + nsi = NULL; +} + + +static struct log_info info = {}; + +int main(int argc, char **argv) +{ + osmo_init_logging(&info); + log_set_use_color(osmo_stderr_target, 0); + log_set_print_filename(osmo_stderr_target, 0); + osmo_signal_register_handler(SS_L_NS, &test_signal, NULL); + + printf("===== NS protocol test START\n"); + test_gbproxy(); + printf("===== NS protocol test END\n\n"); + + exit(EXIT_SUCCESS); +} diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok new file mode 100644 index 0000000..da4158d --- /dev/null +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -0,0 +1,357 @@ +===== NS protocol test START +--- Initialise BSS 1 --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098) + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (UNITDATA) = 0 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + +Peers: + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Initialise BSS 2 --- + +Setup NS-VC: remote 0x01020304:2222, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:2222 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:2222 + +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:2222 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:2222 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:2222 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:2222 +0b + +result (ALIVE_ACK) = 0 + +Setup BSSGP: remote 0x01020304:2222, BVCI 0x2002(8194) + +PROCESSING UNITDATA from 0x01020304:2222 +00 00 00 00 22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (UNITDATA) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 1 to new port --- + +Setup NS-VC: remote 0x01020304:3333, NSVCI 0x1001(4097), NSEI 0x1000(4096) + +PROCESSING RESET from 0x01020304:3333 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:3333 + +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:3333 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:3333 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:3333 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:3333 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 2 to former BSS 1 port --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 1 to current BSS 2 port --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 2 to new port --- + +Setup NS-VC: remote 0x01020304:4444, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:4444 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:4444 + +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:4444 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:4444 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:4444 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:4444 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:4444 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 2 to former BSS 1 port --- + +Setup NS-VC: remote 0x01020304:3333, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:3333 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_REPLACED: 0x2001/1.2.3.4:4444 -> 0x2001/1.2.3.4:3333 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:3333 + +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:3333 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:3333 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:3333 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:3333 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 +===== NS protocol test END + diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index 27225a8..76110f5 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -75,3 +75,9 @@ AT_CHECK([test "$enable_bsc_test" != no || exit 77]) cat $abs_srcdir/bsc/bsc_test.ok > expout AT_CHECK([$abs_top_builddir/tests/bsc/bsc_test], [], [expout], [ignore]) AT_CLEANUP + +AT_SETUP([gbproxy]) +AT_KEYWORDS([gbproxy]) +cat $abs_srcdir/gbproxy/gbproxy_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/gbproxy/gbproxy_test], [], [expout], [ignore]) +AT_CLEANUP -- 1.7.9.5 From jerlbeck at sysmocom.de Fri Oct 11 20:23:13 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Fri, 11 Oct 2013 22:23:13 +0200 Subject: [PATCH 2/2] gbproxy: Handle S_NS_REPLACED signal In-Reply-To: <1381522993-30535-1-git-send-email-jerlbeck@sysmocom.de> References: <1381522993-30535-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381522993-30535-2-git-send-email-jerlbeck@sysmocom.de> The signal is dispatched when a NS-VC object is replaced by another one (with the same NS-VCI) for some reason. This patch changes the gbproxy's signal handler to update the peer object accordingly in this case. This happens when the source port of a NS-VC changes to a new one that has already been used by another NS-VC. The patch is needed for (and relies on) the changes introduced by libosmocore's commit 'gb: Fix gprs_ns_rx_reset to not create NS-VC duplicates'. Ticket: OW#874 Sponsored-by: On-Waves ehf --- openbsc/src/gprs/gb_proxy.c | 35 +++++++++++++++++++++++++++++++++ openbsc/tests/gbproxy/gbproxy_test.ok | 1 - 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 3a9fe81..f6b27ae 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -603,6 +603,41 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, if (subsys != SS_L_NS) return 0; + if (signal == S_NS_REPLACED) { + /* The old nsvc object is no longer used and will be replaced + * by a new one. */ + struct gbprox_peer *replaced_peer; + + peer = peer_by_nsvc(nssd->old_nsvc); + if (!peer) { + LOGP(DGPRS, LOGL_NOTICE, "signal REPLACED for unknown peer " + "NSEI=%u/NSVCI=%u\n", + nssd->old_nsvc->nsei, nssd->old_nsvc->nsvci); + return 0; + } + if (peer->nsvc->nsei != nsvc->nsei) { + LOGP(DGPRS, LOGL_ERROR, + "old and new NSEI of a peer don't match (%u -> %u), " + "NSVCI=%u\n", + peer->nsvc->nsei, nsvc->nsei, nsvc->nsvci); + } + replaced_peer = peer_by_nsvc(nsvc); + if (replaced_peer) { + /* This peer has used the nsvc object before. Since + * that is going to be used for another peer, this peer + * is going to be removed. */ + LOGP(DGPRS, LOGL_NOTICE, "going to remove peer with BVCI=%u\n", + replaced_peer->bvci); + peer_free(replaced_peer); + } + + LOGP(DGPRS, LOGL_NOTICE, "going to replace the NS-VC object " + "for peer NSEI=%u/NSVCI=%u\n", nsvc->nsei, nsvc->nsvci); + + peer->nsvc = nsvc; + return 0; + } + if (signal == S_NS_RESET && nsvc->nsei == gbcfg.nsip_sgsn_nsei) { /* We have received a NS-RESET from the NSEI and NSVC * of the SGSN. This might happen with SGSN that start diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index da4158d..17478ad 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -352,6 +352,5 @@ Current NS-VCIs: Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 - NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 ===== NS protocol test END -- 1.7.9.5 From jerlbeck at sysmocom.de Tue Oct 15 10:00:26 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 15 Oct 2013 12:00:26 +0200 Subject: [PATCH 1/2] gbproxy: Add test program to test gbproxy message handling In-Reply-To: <1381522993-30535-1-git-send-email-jerlbeck@sysmocom.de> References: <1381522993-30535-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381831227-16630-1-git-send-email-jerlbeck@sysmocom.de> This program tests the gbproxy implementation by passing NS messages to a modified gbproxy that dumps the resulting messages, signals, and state. It focusses on testing abnormal situations like port changes. Ticket: OW#874 Sponsored-by: On-Waves ehf --- openbsc/configure.ac | 1 + openbsc/include/openbsc/gb_proxy.h | 1 + openbsc/src/gprs/gb_proxy.c | 23 ++ openbsc/tests/Makefile.am | 2 +- openbsc/tests/gbproxy/Makefile.am | 18 ++ openbsc/tests/gbproxy/gbproxy_test.c | 409 +++++++++++++++++++++++++++++++++ openbsc/tests/gbproxy/gbproxy_test.ok | 359 +++++++++++++++++++++++++++++ openbsc/tests/testsuite.at | 6 + 8 files changed, 818 insertions(+), 1 deletion(-) create mode 100644 openbsc/tests/gbproxy/Makefile.am create mode 100644 openbsc/tests/gbproxy/gbproxy_test.c create mode 100644 openbsc/tests/gbproxy/gbproxy_test.ok diff --git a/openbsc/configure.ac b/openbsc/configure.ac index ddd15e3..531efcf 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -162,6 +162,7 @@ AC_OUTPUT( tests/bsc-nat-trie/Makefile tests/mgcp/Makefile tests/gprs/Makefile + tests/gbproxy/Makefile tests/si/Makefile tests/abis/Makefile tests/smpp/Makefile diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 2c8ddb3..56b1b3d 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -35,4 +35,5 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, /* Reset all persistent NS-VC's */ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi); +int gbprox_dump_peers(FILE *stream, int indent); #endif diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index b99c455..3a9fe81 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -658,6 +658,29 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, return 0; } +int gbprox_dump_peers(FILE *stream, int indent) +{ + struct gbprox_peer *peer; + struct gprs_ra_id raid; + int rc; + + fprintf(stream, "%*sPeers:\n", indent, ""); + llist_for_each_entry(peer, &gbprox_bts_peers, list) { + gsm48_parse_ra(&raid, peer->ra); + + rc = fprintf(stream, "%*s NSEI %u, BVCI %u, %sblocked, " + "RAC %u-%u-%u-%u\n", + indent, "", + peer->nsvc->nsei, peer->bvci, + peer->blocked ? "" : "not ", + raid.mcc, raid.mnc, raid.lac, raid.rac); + + if (rc < 0) + return rc; + } + + return 0; +} #include diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am index ed21fc3..7f51bfa 100644 --- a/openbsc/tests/Makefile.am +++ b/openbsc/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = gsm0408 db channel mgcp gprs si abis +SUBDIRS = gsm0408 db channel mgcp gprs si abis gbproxy if BUILD_NAT SUBDIRS += bsc-nat bsc-nat-trie diff --git a/openbsc/tests/gbproxy/Makefile.am b/openbsc/tests/gbproxy/Makefile.am new file mode 100644 index 0000000..1323d44 --- /dev/null +++ b/openbsc/tests/gbproxy/Makefile.am @@ -0,0 +1,18 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) +AM_LDFLAGS = $(COVERAGE_LDFLAGS) + +EXTRA_DIST = gbproxy_test.ok + +noinst_PROGRAMS = gbproxy_test + +gbproxy_test_SOURCES = gbproxy_test.c +gbproxy_test_LDADD = \ + $(top_builddir)/src/gprs/gb_proxy.o \ + $(top_builddir)/src/libcommon/libcommon.a \ + $(top_builddir)/src/libbsc/libbsc.a \ + $(top_builddir)/src/libtrau/libtrau.a \ + $(LIBOSMOCORE_LIBS) $(LIBOSMOGB_LIBS) \ + $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \ + $(LIBOSMOABIS_LIBS) \ + -lrt diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c new file mode 100644 index 0000000..e497dcc --- /dev/null +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -0,0 +1,409 @@ +/* test routines for gbproxy + * send NS messages to the gbproxy and dumps what happens + * (C) 2013 by sysmocom s.f.m.c. GmbH + * Author: Jacob Erlbeck + */ + +#undef _GNU_SOURCE +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define REMOTE_BSS_ADDR 0x01020304 +#define REMOTE_SGSN_ADDR 0x05060708 + +#define SGSN_NSEI 0xfffe + +struct gbproxy_config gbcfg; + +static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len); + +static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + enum ns_cause cause, uint16_t nsvci, uint16_t nsei) +{ + /* GPRS Network Service, PDU type: NS_RESET, + */ + unsigned char msg[12] = { + 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22, + 0x04, 0x82, 0x11, 0x22 + }; + + msg[3] = cause; + msg[6] = nsvci / 256; + msg[7] = nsvci % 256; + msg[10] = nsei / 256; + msg[11] = nsei % 256; + + gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg)); +} + +static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_ALIVE */ + unsigned char msg[1] = { + 0x0a + }; + + gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg)); +} + +static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_ALIVE_ACK */ + unsigned char msg[1] = { + 0x0b + }; + + gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_UNBLOCK */ + unsigned char msg[1] = { + 0x06 + }; + + gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unitdata(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsbvci, + const unsigned char *bssgp_msg, size_t bssgp_msg_size) +{ + /* GPRS Network Service, PDU type: NS_UNITDATA */ + unsigned char msg[4096] = { + 0x00, 0x00, 0x00, 0x00 + }; + + OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4); + + msg[2] = nsbvci / 256; + msg[3] = nsbvci % 256; + memcpy(msg + 4, bssgp_msg, bssgp_msg_size); + + gprs_process_message(nsi, "UNITDATA", src_addr, msg, bssgp_msg_size + 4); +} + +static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t bvci) +{ + /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0 + * BSSGP RESET */ + unsigned char msg[22] = { + 0x22, 0x04, 0x82, 0x4a, + 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x10, 0x20, + 0x30, 0x40, 0x50, 0x60, 0x10, 0x00 + }; + + msg[3] = bvci / 256; + msg[4] = bvci % 256; + + send_ns_unitdata(nsi, src_addr, 0, msg, sizeof(msg)); +} + +static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsvci, uint16_t nsei) +{ + printf("Setup NS-VC: remote 0x%08x:%d, " + "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n", + ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port), + nsvci, nsvci, nsei, nsei); + + send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei); + send_ns_alive(nsi, src_addr); + send_ns_unblock(nsi, src_addr); + send_ns_alive_ack(nsi, src_addr); +} + +static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t bvci) +{ + printf("Setup BSSGP: remote 0x%08x:%d, " + "BVCI 0x%04x(%d)\n\n", + ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port), + bvci, bvci); + + send_bssgp_reset(nsi, src_addr, bvci); +} + +int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, + struct sockaddr_in *saddr, enum gprs_ns_ll ll); + +/* override */ +int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, + struct msgb *msg, uint16_t bvci) +{ + printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n", + event, msgb_bssgp_len(msg), bvci, + osmo_hexdump(msgb_bssgph(msg), msgb_bssgp_len(msg))); + + switch (event) { + case GPRS_NS_EVT_UNIT_DATA: + return gbprox_rcvmsg(msg, nsvc, bvci); + default: + break; + } + return 0; +} + +/* override */ +ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen) +{ + typedef ssize_t (*sendto_t)(int, const void *, size_t, int, + const struct sockaddr *, socklen_t); + static sendto_t real_sendto = NULL; + uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr); + + if (!real_sendto) + real_sendto = dlsym(RTLD_NEXT, "sendto"); + + if (dest_host == REMOTE_BSS_ADDR) + printf("MESSAGE to BSS, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + else if (dest_host == REMOTE_SGSN_ADDR) + printf("MESSAGE to SGSN, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + else + return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen); + + return len; +} + +/* override */ +int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) +{ + uint16_t bvci = msgb_bvci(msg); + uint16_t nsei = msgb_nsei(msg); + + unsigned char *buf = msg->data; + size_t len = msg->len; + + if (nsei == SGSN_NSEI) + printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, msg length %d\n%s\n\n", + bvci, len, osmo_hexdump(buf, len)); + else + printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, msg length %d\n%s\n\n", + bvci, len, osmo_hexdump(buf, len)); + + return 0; +} + +static void dump_rate_ctr_group(FILE *stream, const char *prefix, + struct rate_ctr_group *ctrg) +{ + unsigned int i; + + for (i = 0; i < ctrg->desc->num_ctr; i++) { + struct rate_ctr *ctr = &ctrg->ctr[i]; + if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.')) + fprintf(stream, " %s%s: %llu%s", + prefix, ctrg->desc->ctr_desc[i].description, + (long long)ctr->current, + "\n"); + }; +} + +/* Signal handler for signals from NS layer */ +static int test_signal(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct ns_signal_data *nssd = signal_data; + int rc; + + if (subsys != SS_L_NS) + return 0; + + switch (signal) { + case S_NS_RESET: + printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_ll_str(nssd->nsvc)); + break; + + case S_NS_ALIVE_EXP: + printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_ll_str(nssd->nsvc)); + break; + + case S_NS_BLOCK: + printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_ll_str(nssd->nsvc)); + break; + + case S_NS_UNBLOCK: + printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n", + nssd->nsvc->nsvci, + gprs_ns_ll_str(nssd->nsvc)); + break; + + case S_NS_REPLACED: + printf("==> got signal NS_REPLACED: 0x%04x/%s", + nssd->nsvc->nsvci, + gprs_ns_ll_str(nssd->nsvc)); + printf(" -> 0x%04x/%s\n", + nssd->old_nsvc->nsvci, + gprs_ns_ll_str(nssd->old_nsvc)); + break; + + default: + printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal, + nssd->nsvc->nsvci, + gprs_ns_ll_str(nssd->nsvc)); + break; + } + printf("\n"); + rc = gbprox_signal(subsys, signal, handler_data, signal_data); + return rc; +} + +static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len) +{ + struct msgb *msg; + int ret; + if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) { + fprintf(stderr, "message too long: %d\n", data_len); + return -1; + } + + msg = gprs_ns_msgb_alloc(); + memmove(msg->data, data, data_len); + msg->l2h = msg->data; + msgb_put(msg, data_len); + + printf("PROCESSING %s from 0x%08x:%d\n%s\n\n", + text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port), + osmo_hexdump(data, data_len)); + + ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP); + + printf("result (%s) = %d\n\n", text, ret); + + msgb_free(msg); + + return ret; +} + +static void gprs_dump_nsi(struct gprs_ns_inst *nsi) +{ + struct gprs_nsvc *nsvc; + + printf("Current NS-VCIs:\n"); + llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { + struct sockaddr_in *peer = &(nsvc->ip.bts_addr); + printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d\n", + nsvc->nsvci, nsvc->nsei, + ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port) + ); + dump_rate_ctr_group(stdout, " ", nsvc->ctrg); + } + printf("\n"); +} + +static void test_gbproxy() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in bss_peer[4] = {{0},}; + + bssgp_nsi = nsi; + gbcfg.nsi = bssgp_nsi; + gbcfg.nsip_sgsn_nsei = SGSN_NSEI; + + bss_peer[0].sin_family = AF_INET; + bss_peer[0].sin_port = htons(1111); + bss_peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + bss_peer[1].sin_family = AF_INET; + bss_peer[1].sin_port = htons(2222); + bss_peer[1].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + bss_peer[2].sin_family = AF_INET; + bss_peer[2].sin_port = htons(3333); + bss_peer[2].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + bss_peer[3].sin_family = AF_INET; + bss_peer[3].sin_port = htons(4444); + bss_peer[3].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + + printf("--- Initialise BSS 1 ---\n\n"); + + setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); + setup_bssgp(nsi, &bss_peer[0], 0x1002); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Initialise BSS 2 ---\n\n"); + + setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000); + setup_bssgp(nsi, &bss_peer[1], 0x2002); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Move BSS 1 to new port ---\n\n"); + + setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Move BSS 2 to former BSS 1 port ---\n\n"); + + setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Move BSS 1 to current BSS 2 port ---\n\n"); + + setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Move BSS 2 to new port ---\n\n"); + + setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Move BSS 2 to former BSS 1 port ---\n\n"); + + setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + gprs_ns_destroy(nsi); + nsi = NULL; +} + + +static struct log_info info = {}; + +int main(int argc, char **argv) +{ + osmo_init_logging(&info); + log_set_use_color(osmo_stderr_target, 0); + log_set_print_filename(osmo_stderr_target, 0); + osmo_signal_register_handler(SS_L_NS, &test_signal, NULL); + + printf("===== NS protocol test START\n"); + test_gbproxy(); + printf("===== NS protocol test END\n\n"); + + exit(EXIT_SUCCESS); +} diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok new file mode 100644 index 0000000..0835921 --- /dev/null +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -0,0 +1,359 @@ +===== NS protocol test START +--- Initialise BSS 1 --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098) + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (UNITDATA) = 0 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + +Peers: + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Initialise BSS 2 --- + +Setup NS-VC: remote 0x01020304:2222, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:2222 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:2222 + +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:2222 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:2222 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:2222 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:2222 +0b + +result (ALIVE_ACK) = 0 + +Setup BSSGP: remote 0x01020304:2222, BVCI 0x2002(8194) + +PROCESSING UNITDATA from 0x01020304:2222 +00 00 00 00 22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (UNITDATA) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 1 to new port --- + +Setup NS-VC: remote 0x01020304:3333, NSVCI 0x1001(4097), NSEI 0x1000(4096) + +PROCESSING RESET from 0x01020304:3333 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:3333 + +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:3333 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:3333 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:3333 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:3333 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 2 to former BSS 1 port --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 1 to current BSS 2 port --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 2 to new port --- + +Setup NS-VC: remote 0x01020304:4444, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:4444 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:4444 + +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:4444 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:4444 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:4444 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:4444 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:4444 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 2 to former BSS 1 port --- + +Setup NS-VC: remote 0x01020304:3333, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:3333 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_REPLACED: 0x2001/1.2.3.4:4444 -> 0x1001/1.2.3.4:3333 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:3333 + +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:3333 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:3333 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:3333 + +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:3333 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x00000000:0 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +===== NS protocol test END + diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index 27225a8..76110f5 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -75,3 +75,9 @@ AT_CHECK([test "$enable_bsc_test" != no || exit 77]) cat $abs_srcdir/bsc/bsc_test.ok > expout AT_CHECK([$abs_top_builddir/tests/bsc/bsc_test], [], [expout], [ignore]) AT_CLEANUP + +AT_SETUP([gbproxy]) +AT_KEYWORDS([gbproxy]) +cat $abs_srcdir/gbproxy/gbproxy_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/gbproxy/gbproxy_test], [], [expout], [ignore]) +AT_CLEANUP -- 1.7.9.5 From jerlbeck at sysmocom.de Tue Oct 15 10:00:27 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 15 Oct 2013 12:00:27 +0200 Subject: [PATCH 2/2] gbproxy: Replace NS-VC references by NSEI In-Reply-To: <1381831227-16630-1-git-send-email-jerlbeck@sysmocom.de> References: <1381522993-30535-1-git-send-email-jerlbeck@sysmocom.de> <1381831227-16630-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381831227-16630-2-git-send-email-jerlbeck@sysmocom.de> Currently in most places in gb_proxy.c a reference to a NS-VC object is used where the peer is meant instead. The patch changes this by using the NSEI instead in these cases. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 2 +- openbsc/src/gprs/gb_proxy.c | 124 ++++++++++++++++++---------------- openbsc/src/gprs/gb_proxy_main.c | 2 +- openbsc/tests/gbproxy/gbproxy_test.c | 2 +- 4 files changed, 67 insertions(+), 63 deletions(-) diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 56b1b3d..26c1f6a 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -27,7 +27,7 @@ int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg); /* gb_proxy.c */ /* Main input function for Gb proxy */ -int gbprox_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci); +int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t nsvci); int gbprox_signal(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data); diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 3a9fe81..157ce10 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -42,8 +42,8 @@ struct gbprox_peer { struct llist_head list; - /* NS-VC over which we send/receive data to this BVC */ - struct gprs_nsvc *nsvc; + /* NSEI of the peer entity */ + uint16_t nsei; /* BVCI used for Point-to-Point to this peer */ uint16_t bvci; @@ -67,11 +67,12 @@ static struct gbprox_peer *peer_by_bvci(uint16_t bvci) return NULL; } -static struct gbprox_peer *peer_by_nsvc(struct gprs_nsvc *nsvc) +/* Find the gbprox_peer by its NSEI */ +static struct gbprox_peer *peer_by_nsei(uint16_t nsei) { struct gbprox_peer *peer; llist_for_each_entry(peer, &gbprox_bts_peers, list) { - if (peer->nsvc == nsvc) + if (peer->nsei == nsei) return peer; } return NULL; @@ -194,10 +195,10 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer, struct msgb *msg = msgb_copy(old_msg, "msgb_relay2peer"); DEBUGP(DGPRS, "NSEI=%u proxying SGSN->BSS (NS_BVCI=%u, NSEI=%u)\n", - msgb_nsei(msg), ns_bvci, peer->nsvc->nsei); + msgb_nsei(msg), ns_bvci, peer->nsei); msgb_bvci(msg) = ns_bvci; - msgb_nsei(msg) = peer->nsvc->nsei; + msgb_nsei(msg) = peer->nsei; /* Strip the old NS header, it will be replaced with a new one */ strip_ns_hdr(msg); @@ -252,7 +253,7 @@ int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx) } /* Receive an incoming signalling message from a BSS-side NS-VC */ -static int gbprox_rx_sig_from_bss(struct msgb *msg, struct gprs_nsvc *nsvc, +static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci) { struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); @@ -264,7 +265,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, struct gprs_nsvc *nsvc, if (ns_bvci != 0 && ns_bvci != 1) { LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u BVCI=%u is not signalling\n", - nsvc->nsei, ns_bvci); + nsei, ns_bvci); return -EINVAL; } @@ -273,7 +274,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, struct gprs_nsvc *nsvc, if (pdu_type == BSSGP_PDUT_UL_UNITDATA || pdu_type == BSSGP_PDUT_DL_UNITDATA) { LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u UNITDATA not allowed in " - "signalling\n", nsvc->nsei); + "signalling\n", nsei); return -EINVAL; } @@ -289,16 +290,16 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, struct gprs_nsvc *nsvc, * the correct BSSGP */ if (!TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA)) goto err_mand_ie; - from_peer = peer_by_nsvc(nsvc); + from_peer = peer_by_nsei(nsei); if (!from_peer) goto err_no_peer; memcpy(from_peer->ra, TLVP_VAL(&tp, BSSGP_IE_ROUTEING_AREA), sizeof(from_peer->ra)); gsm48_parse_ra(&raid, from_peer->ra); LOGP(DGPRS, LOGL_INFO, "NSEI=%u BSSGP SUSPEND/RESUME " - "RAC snooping: RAC %u-%u-%u-%u behind BVCI=%u, " - "NSVCI=%u\n",nsvc->nsei, raid.mcc, raid.mnc, raid.lac, - raid.rac , from_peer->bvci, nsvc->nsvci); + "RAC snooping: RAC %u-%u-%u-%u behind BVCI=%u\n", + nsei, raid.mcc, raid.mnc, raid.lac, + raid.rac , from_peer->bvci); /* FIXME: This only supports one BSS per RA */ break; case BSSGP_PDUT_BVC_RESET: @@ -308,23 +309,22 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, struct gprs_nsvc *nsvc, if (TLVP_PRESENT(&tp, BSSGP_IE_BVCI)) { uint16_t bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); LOGP(DGPRS, LOGL_INFO, "NSEI=%u Rx BVC RESET (BVCI=%u)\n", - nsvc->nsei, bvci); + nsei, bvci); if (bvci == 0) { /* FIXME: only do this if SGSN is alive! */ LOGP(DGPRS, LOGL_INFO, "NSEI=%u Tx fake " - "BVC RESET ACK of BVCI=0\n", nsvc->nsei); + "BVC RESET ACK of BVCI=0\n", nsei); return bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_RESET_ACK, - nsvc->nsei, 0, ns_bvci); + nsei, 0, ns_bvci); } from_peer = peer_by_bvci(bvci); if (!from_peer) { /* if a PTP-BVC is reset, and we don't know that * PTP-BVCI yet, we should allocate a new peer */ LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for " - "BVCI=%u via NSVCI=%u/NSEI=%u\n", bvci, - nsvc->nsvci, nsvc->nsei); + "BVCI=%u via NSEI=%u\n", bvci, nsei); from_peer = peer_alloc(bvci); - from_peer->nsvc = nsvc; + from_peer->nsei = nsei; } if (TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID)) { struct gprs_ra_id raid; @@ -337,7 +337,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, struct gprs_nsvc *nsvc, sizeof(from_peer->ra)); gsm48_parse_ra(&raid, from_peer->ra); LOGP(DGPRS, LOGL_INFO, "NSEI=%u/BVCI=%u " - "Cell ID %u-%u-%u-%u\n", nsvc->nsei, + "Cell ID %u-%u-%u-%u\n", nsei, bvci, raid.mcc, raid.mnc, raid.lac, raid.rac); } @@ -350,22 +350,22 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, struct gprs_nsvc *nsvc, return gbprox_relay2sgsn(msg, ns_bvci); err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on RAC\n", - nsvc->nsei); + nsei); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) missing mandatory RA IE\n", - nsvc->nsei); + nsei); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } /* Receive paging request from SGSN, we need to relay to proper BSS */ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, - struct gprs_nsvc *nsvc, uint16_t ns_bvci) + uint32_t nsei, uint16_t ns_bvci) { struct gbprox_peer *peer = NULL; LOGP(DGPRS, LOGL_INFO, "NSEI=%u(SGSN) BSSGP PAGING ", - nsvc->nsei); + nsei); if (TLVP_PRESENT(tp, BSSGP_IE_BVCI)) { uint16_t bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI)); LOGPC(DGPRS, LOGL_INFO, "routing by BVCI to peer BVCI=%u\n", @@ -383,7 +383,7 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, if (!peer) { LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP PAGING: " - "unable to route, missing IE\n", nsvc->nsei); + "unable to route, missing IE\n", nsei); return -EINVAL; } return gbprox_relay2peer(msg, peer, ns_bvci); @@ -391,7 +391,7 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, /* Receive an incoming BVC-RESET message from the SGSN */ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, - struct gprs_nsvc *nsvc, uint16_t ns_bvci) + uint32_t nsei, uint16_t ns_bvci) { struct gbprox_peer *peer; uint16_t ptp_bvci; @@ -408,7 +408,7 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, peer = peer_by_bvci(ptp_bvci); if (!peer) { LOGP(DGPRS, LOGL_ERROR, "NSEI=%u BVCI=%u: Cannot find BSS\n", - nsvc->nsei, ptp_bvci); + nsei, ptp_bvci); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); } @@ -426,7 +426,7 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, } /* Receive an incoming signalling message from the SGSN-side NS-VC */ -static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc, +static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, uint16_t ns_bvci) { struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); @@ -439,7 +439,7 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc, if (ns_bvci != 0 && ns_bvci != 1) { LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u(SGSN) BVCI=%u is not " - "signalling\n", nsvc->nsei, ns_bvci); + "signalling\n", nsei, ns_bvci); /* FIXME: Send proper error message */ return -EINVAL; } @@ -449,7 +449,7 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc, if (pdu_type == BSSGP_PDUT_UL_UNITDATA || pdu_type == BSSGP_PDUT_DL_UNITDATA) { LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u(SGSN) UNITDATA not allowed in " - "signalling\n", nsvc->nsei); + "signalling\n", nsei); return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); } @@ -457,7 +457,7 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc, switch (pdu_type) { case BSSGP_PDUT_BVC_RESET: - rc = rx_reset_from_sgsn(msg, &tp, nsvc, ns_bvci); + rc = rx_reset_from_sgsn(msg, &tp, nsei, ns_bvci); break; case BSSGP_PDUT_FLUSH_LL: case BSSGP_PDUT_BVC_RESET_ACK: @@ -470,12 +470,12 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc, case BSSGP_PDUT_PAGING_PS: case BSSGP_PDUT_PAGING_CS: /* process the paging request (LAC/RAC lookup) */ - rc = gbprox_rx_paging(msg, &tp, nsvc, ns_bvci); + rc = gbprox_rx_paging(msg, &tp, nsei, ns_bvci); break; case BSSGP_PDUT_STATUS: /* Some exception has occurred */ LOGP(DGPRS, LOGL_NOTICE, - "NSEI=%u(SGSN) BSSGP STATUS ", nsvc->nsei); + "NSEI=%u(SGSN) BSSGP STATUS ", nsei); if (!TLVP_PRESENT(&tp, BSSGP_IE_CAUSE)) { LOGPC(DGPRS, LOGL_NOTICE, "\n"); goto err_mand_ie; @@ -510,7 +510,7 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc, bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI)); if (bvci == 0) { LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u(SGSN) BSSGP " - "%sBLOCK_ACK for signalling BVCI ?!?\n", nsvc->nsei, + "%sBLOCK_ACK for signalling BVCI ?!?\n", nsei, pdu_type == BSSGP_PDUT_BVC_UNBLOCK_ACK ? "UN":""); /* should we send STATUS ? */ } else { @@ -521,7 +521,7 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc, break; case BSSGP_PDUT_SGSN_INVOKE_TRACE: LOGP(DGPRS, LOGL_ERROR, - "NSEI=%u(SGSN) BSSGP INVOKE TRACE not supported\n",nsvc->nsei); + "NSEI=%u(SGSN) BSSGP INVOKE TRACE not supported\n",nsei); rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, msg); break; default: @@ -534,44 +534,45 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, struct gprs_nsvc *nsvc, return rc; err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) missing mandatory IE\n", - nsvc->nsei); + nsei); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) cannot find peer based on RAC\n", - nsvc->nsei); + nsei); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); } /* Main input function for Gb proxy */ -int gbprox_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci) +int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t nsvci) { int rc; struct gbprox_peer *peer; + int remote_end_is_sgsn = nsei == gbcfg.nsip_sgsn_nsei; /* Only BVCI=0 messages need special treatment */ if (ns_bvci == 0 || ns_bvci == 1) { - if (nsvc->remote_end_is_sgsn) - rc = gbprox_rx_sig_from_sgsn(msg, nsvc, ns_bvci); + if (remote_end_is_sgsn) + rc = gbprox_rx_sig_from_sgsn(msg, nsei, ns_bvci); else - rc = gbprox_rx_sig_from_bss(msg, nsvc, ns_bvci); + rc = gbprox_rx_sig_from_bss(msg, nsei, ns_bvci); } else { /* All other BVCI are PTP and thus can be simply forwarded */ - if (!nsvc->remote_end_is_sgsn) { + if (!remote_end_is_sgsn) return gbprox_relay2sgsn(msg, ns_bvci); - } + /* else: SGSN -> BSS direction */ peer = peer_by_bvci(ns_bvci); if (!peer) { LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for " "BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, - nsvc->nsvci, nsvc->nsei); + nsvci, nsei); peer = peer_alloc(ns_bvci); - peer->nsvc = nsvc; + peer->nsei = nsei; } if (peer->blocked) { LOGP(DGPRS, LOGL_NOTICE, "Dropping PDU for " "blocked BVCI=%u via NSVC=%u/NSEI=%u\n", - ns_bvci, nsvc->nsvci, nsvc->nsei); + ns_bvci, nsvci, nsei); return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, NULL, msg); } rc = gbprox_relay2peer(msg, peer, ns_bvci); @@ -620,7 +621,7 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, if (!nsvc->remote_end_is_sgsn) { /* from BSS to SGSN */ - peer = peer_by_nsvc(nsvc); + peer = peer_by_nsei(nsvc->nsei); if (!peer) { LOGP(DGPRS, LOGL_NOTICE, "signal %u for unknown peer " "NSEI=%u/NSVCI=%u\n", signal, nsvc->nsei, @@ -640,17 +641,25 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, break; } } else { - /* iterate over all BTS peers and send the respective PDU */ - llist_for_each_entry(peer, &gbprox_bts_peers, list) { + /* Forward this message to all NS-VC to BSS */ + struct gprs_ns_inst *nsi = gbcfg.nsi; + struct gprs_nsvc *next_nsvc; + + llist_for_each_entry(next_nsvc, &nsi->gprs_nsvcs, list) { + if (next_nsvc->remote_end_is_sgsn) + continue; + + /* Note that the following does not start the full + * procedures including timer based retransmissions. */ switch (signal) { case S_NS_RESET: - gprs_ns_tx_reset(peer->nsvc, nssd->cause); + gprs_ns_tx_reset(next_nsvc, nssd->cause); break; case S_NS_BLOCK: - gprs_ns_tx_block(peer->nsvc, nssd->cause); + gprs_ns_tx_block(next_nsvc, nssd->cause); break; case S_NS_UNBLOCK: - gprs_ns_tx_unblock(peer->nsvc); + gprs_ns_tx_unblock(next_nsvc); break; } } @@ -671,7 +680,7 @@ int gbprox_dump_peers(FILE *stream, int indent) rc = fprintf(stream, "%*s NSEI %u, BVCI %u, %sblocked, " "RAC %u-%u-%u-%u\n", indent, "", - peer->nsvc->nsei, peer->bvci, + peer->nsei, peer->bvci, peer->blocked ? "" : "not ", raid.mcc, raid.mnc, raid.lac, raid.rac); @@ -690,18 +699,13 @@ gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy", struct gbprox_peer *peer; llist_for_each_entry(peer, &gbprox_bts_peers, list) { - struct gprs_nsvc *nsvc = peer->nsvc; struct gprs_ra_id raid; gsm48_parse_ra(&raid, peer->ra); - vty_out(vty, "NSEI %5u, NS-VC %5u, PTP-BVCI %5u, " + vty_out(vty, "NSEI %5u, PTP-BVCI %5u, " "RAC %u-%u-%u-%u", - nsvc->nsei, nsvc->nsvci, peer->bvci, + peer->nsei, peer->bvci, raid.mcc, raid.mnc, raid.lac, raid.rac); - if (nsvc->ll == GPRS_NS_LL_UDP || nsvc->ll == GPRS_NS_LL_FR_GRE) - vty_out(vty, " %s:%u", - inet_ntoa(nsvc->ip.bts_addr.sin_addr), - ntohs(nsvc->ip.bts_addr.sin_port)); if (peer->blocked) vty_out(vty, " [BVC-BLOCKED]"); diff --git a/openbsc/src/gprs/gb_proxy_main.c b/openbsc/src/gprs/gb_proxy_main.c index b5b11fd..ff2e14b 100644 --- a/openbsc/src/gprs/gb_proxy_main.c +++ b/openbsc/src/gprs/gb_proxy_main.c @@ -80,7 +80,7 @@ static int proxy_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, switch (event) { case GPRS_NS_EVT_UNIT_DATA: - rc = gbprox_rcvmsg(msg, nsvc, bvci); + rc = gbprox_rcvmsg(msg, nsvc->nsei, bvci, nsvc->nsvci); break; default: LOGP(DGPRS, LOGL_ERROR, "SGSN: Unknown event %u from NS\n", event); diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index e497dcc..23dc850 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -160,7 +160,7 @@ int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, switch (event) { case GPRS_NS_EVT_UNIT_DATA: - return gbprox_rcvmsg(msg, nsvc, bvci); + return gbprox_rcvmsg(msg, nsvc->nsei, bvci, nsvc->nsvci); default: break; } -- 1.7.9.5 From jerlbeck at sysmocom.de Mon Oct 14 10:03:54 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Mon, 14 Oct 2013 12:03:54 +0200 Subject: [PATCH] gb: When sending on a NS-VC group use the first active NS-VC Message-ID: <1381745034-16815-1-git-send-email-jerlbeck@sysmocom.de> Currently this first NS-VC with a matching NSEI is always used to send a UNITDATA message via gprs_ns_sendmsg(). If the NS-VC found is either dead or blocked, an error is returned. This patch changes to code to skip blocked or dead NS-VCs while searching and return the error if no usable NS-VC is found. This makes it possible to have several NS-VCs per connection group. Sponsored-by: On-Waves ehf --- src/gb/gprs_ns.c | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index b5f91c4..7801b29 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -136,7 +136,7 @@ struct gprs_nsvc *gprs_nsvc_by_nsvci(struct gprs_ns_inst *nsi, uint16_t nsvci) /*! \brief Lookup struct gprs_nsvc based on NSEI * \param[in] nsi NS instance in which to search * \param[in] nsei NSEI to be searched - * \returns gprs_nsvc of respective NSEI + * \returns first gprs_nsvc of respective NSEI */ struct gprs_nsvc *gprs_nsvc_by_nsei(struct gprs_ns_inst *nsi, uint16_t nsei) { @@ -148,6 +148,20 @@ struct gprs_nsvc *gprs_nsvc_by_nsei(struct gprs_ns_inst *nsi, uint16_t nsei) return NULL; } +static struct gprs_nsvc *gprs_active_nsvc_by_nsei(struct gprs_ns_inst *nsi, + uint16_t nsei) +{ + struct gprs_nsvc *nsvc; + llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { + if (nsvc->nsei == nsei) { + if (nsvc->state & NSE_S_BLOCKED || + !(nsvc->state & NSE_S_ALIVE)) + return nsvc; + } + } + return NULL; +} + /* Lookup struct gprs_nsvc based on remote peer socket addr */ static struct gprs_nsvc *nsvc_by_rem_addr(struct gprs_ns_inst *nsi, struct sockaddr_in *sin) @@ -559,27 +573,24 @@ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) struct gprs_ns_hdr *nsh; uint16_t bvci = msgb_bvci(msg); - nsvc = gprs_nsvc_by_nsei(nsi, msgb_nsei(msg)); + nsvc = gprs_active_nsvc_by_nsei(nsi, msgb_nsei(msg)); if (!nsvc) { - LOGP(DNS, LOGL_ERROR, "Unable to resolve NSEI %u " - "to NS-VC!\n", msgb_nsei(msg)); - msgb_free(msg); - return -EINVAL; - } - log_set_context(GPRS_CTX_NSVC, 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; + } - if (!(nsvc->state & NSE_S_ALIVE)) { - LOGP(DNS, LOGL_ERROR, "NSEI=%u is not alive, cannot send\n", - nsvc->nsei); msgb_free(msg); - return -EBUSY; - } - if (nsvc->state & NSE_S_BLOCKED) { - LOGP(DNS, LOGL_ERROR, "NSEI=%u is blocked, cannot send\n", - nsvc->nsei); - msgb_free(msg); - return -EBUSY; + return rc; } + log_set_context(GPRS_CTX_NSVC, nsvc); msg->l2h = msgb_push(msg, sizeof(*nsh) + 3); nsh = (struct gprs_ns_hdr *) msg->l2h; -- 1.7.9.5 From jerlbeck at sysmocom.de Thu Oct 17 10:05:57 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 17 Oct 2013 12:05:57 +0200 Subject: [PATCH 1/2] gb: Test sending messages to SGSN In-Reply-To: <1381745034-16815-1-git-send-email-jerlbeck@sysmocom.de> References: <1381745034-16815-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382004358-17724-1-git-send-email-jerlbeck@sysmocom.de> This adds tests for the gprs_ns_sendmsg() function. For this it merges back functions from the gbproxy test. Sponsored-by: On-Waves ehf --- tests/gb/gprs_ns_test.c | 314 ++++++++++++++++++++++++++++++++++++++++++---- tests/gb/gprs_ns_test.ok | 141 +++++++++++++++++---- 2 files changed, 402 insertions(+), 53 deletions(-) diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index d7b769d..0921b61 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -26,6 +26,152 @@ #include #include +#define REMOTE_BSS_ADDR 0x01020304 +#define REMOTE_SGSN_ADDR 0x05060708 + +#define SGSN_NSEI 0x0100 + +static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, + struct sockaddr_in *peer, const unsigned char* data, + size_t data_len); + +static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + enum ns_cause cause, uint16_t nsvci, uint16_t nsei) +{ + /* GPRS Network Service, PDU type: NS_RESET, + */ + unsigned char msg[12] = { + 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22, + 0x04, 0x82, 0x11, 0x22 + }; + + msg[3] = cause; + msg[6] = nsvci / 256; + msg[7] = nsvci % 256; + msg[10] = nsei / 256; + msg[11] = nsei % 256; + + gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg)); +} + +static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsvci, uint16_t nsei) +{ + /* GPRS Network Service, PDU type: NS_RESET_ACK, + */ + unsigned char msg[9] = { + 0x03, 0x01, 0x82, 0x11, 0x22, + 0x04, 0x82, 0x11, 0x22 + }; + + msg[3] = nsvci / 256; + msg[4] = nsvci % 256; + msg[7] = nsei / 256; + msg[8] = nsei % 256; + + gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_ALIVE */ + unsigned char msg[1] = { + 0x0a + }; + + gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg)); +} + +static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_ALIVE_ACK */ + unsigned char msg[1] = { + 0x0b + }; + + gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_UNBLOCK */ + unsigned char msg[1] = { + 0x06 + }; + + gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */ + unsigned char msg[1] = { + 0x07 + }; + + gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unitdata(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsbvci, + const unsigned char *bssgp_msg, size_t bssgp_msg_size) +{ + /* GPRS Network Service, PDU type: NS_UNITDATA */ + unsigned char msg[4096] = { + 0x00, 0x00, 0x00, 0x00 + }; + + OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4); + + msg[2] = nsbvci / 256; + msg[3] = nsbvci % 256; + memcpy(msg + 4, bssgp_msg, bssgp_msg_size); + + gprs_process_message(nsi, "UNITDATA", src_addr, msg, bssgp_msg_size + 4); +} + +static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t bvci) +{ + /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0 + * BSSGP RESET */ + unsigned char msg[22] = { + 0x22, 0x04, 0x82, 0x4a, + 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x10, 0x20, + 0x30, 0x40, 0x50, 0x60, 0x10, 0x00 + }; + + msg[3] = bvci / 256; + msg[4] = bvci % 256; + + send_ns_unitdata(nsi, src_addr, 0, msg, sizeof(msg)); +} + +static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsvci, uint16_t nsei) +{ + printf("Setup NS-VC: remote 0x%08x:%d, " + "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n", + ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port), + nsvci, nsvci, nsei, nsei); + + send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei); + send_ns_alive(nsi, src_addr); + send_ns_unblock(nsi, src_addr); + send_ns_alive_ack(nsi, src_addr); +} + +static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t bvci) +{ + printf("Setup BSSGP: remote 0x%08x:%d, " + "BVCI 0x%04x(%d)\n\n", + ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port), + bvci, bvci); + + send_bssgp_reset(nsi, src_addr, bvci); +} + /* GPRS Network Service, PDU type: NS_RESET, * Cause: O&M intervention, NS VCI: 0x1122, NSEI 0x1122 */ @@ -110,18 +256,45 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, typedef ssize_t (*sendto_t)(int, const void *, size_t, int, const struct sockaddr *, socklen_t); static sendto_t real_sendto = NULL; + uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr); if (!real_sendto) real_sendto = dlsym(RTLD_NEXT, "sendto"); - if (((struct sockaddr_in *)dest_addr)->sin_addr.s_addr != htonl(0x01020304)) + if (dest_host == REMOTE_BSS_ADDR) + printf("MESSAGE to BSS, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + else if (dest_host == REMOTE_SGSN_ADDR) + printf("MESSAGE to SGSN, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + else return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen); - printf("RESPONSE, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); - return len; } +/* override */ +int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) +{ + typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg); + static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL; + uint16_t bvci = msgb_bvci(msg); + uint16_t nsei = msgb_nsei(msg); + + unsigned char *buf = msg->data; + size_t len = msg->len; + + if (!real_gprs_ns_sendmsg) + real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg"); + + if (nsei == SGSN_NSEI) + printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, msg length %d\n%s\n\n", + bvci, len, osmo_hexdump(buf, len)); + else + printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, msg length %d\n%s\n\n", + bvci, len, osmo_hexdump(buf, len)); + + return real_gprs_ns_sendmsg(nsi, msg); +} + static void dump_rate_ctr_group(FILE *stream, const char *prefix, struct rate_ctr_group *ctrg) { @@ -217,6 +390,34 @@ static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, stru return ret; } +static int gprs_send_message(struct gprs_ns_inst *nsi, const char *text, + uint16_t nsei, uint16_t bvci, + const unsigned char* data, size_t data_len) +{ + struct msgb *msg; + int ret; + if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) { + fprintf(stderr, "message too long: %d\n", data_len); + return -1; + } + + msg = gprs_ns_msgb_alloc(); + memmove(msg->data, data, data_len); + msg->l2h = msg->data; + msgb_put(msg, data_len); + + msgb_nsei(msg) = nsei; + msgb_bvci(msg) = bvci; + + printf("SENDING %s to NSEI 0x%04x, BVCI 0x%04x\n", text, nsei, bvci); + + ret = gprs_ns_sendmsg(nsi, msg); + + printf("result (%s) = %d\n\n", text, ret); + + return ret; +} + static void gprs_dump_nsi(struct gprs_ns_inst *nsi) { struct gprs_nsvc *nsvc; @@ -224,71 +425,70 @@ static void gprs_dump_nsi(struct gprs_ns_inst *nsi) printf("Current NS-VCIs:\n"); llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { struct sockaddr_in *peer = &(nsvc->ip.bts_addr); - printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d\n", + printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n", nsvc->nsvci, nsvc->nsei, - ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port) + ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port), + nsvc->state & NSE_S_BLOCKED ? ", blocked" : "", + nsvc->state & NSE_S_ALIVE ? "" : ", dead" ); dump_rate_ctr_group(stdout, " ", nsvc->ctrg); } printf("\n"); } -static void test_ns() +static void test_bss_port_changes() { struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); struct sockaddr_in peer[4] = {{0},}; + struct sockaddr_in sgsn_peer= {0}; + + sgsn_peer.sin_family = AF_INET; + sgsn_peer.sin_port = htons(32000); + sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR); peer[0].sin_family = AF_INET; peer[0].sin_port = htons(1111); - peer[0].sin_addr.s_addr = htonl(0x01020304); + peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); peer[1].sin_family = AF_INET; peer[1].sin_port = htons(2222); - peer[1].sin_addr.s_addr = htonl(0x01020304); + peer[1].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); peer[2].sin_family = AF_INET; peer[2].sin_port = htons(3333); - peer[2].sin_addr.s_addr = htonl(0x01020304); + peer[2].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); peer[3].sin_family = AF_INET; peer[3].sin_port = htons(4444); - peer[3].sin_addr.s_addr = htonl(0x01020304); + peer[3].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); - gprs_process_message(nsi, "RESET", &peer[0], - gprs_ns_reset, sizeof(gprs_ns_reset)); + printf("--- Setup, send BSSGP RESET ---\n\n"); + + setup_ns(nsi, &peer[0], 0x1122, 0x1122); gprs_dump_nsi(nsi); - gprs_process_message(nsi, "ALIVE", &peer[0], - gprs_ns_alive, sizeof(gprs_ns_alive)); - gprs_process_message(nsi, "UNBLOCK", &peer[0], - gprs_ns_unblock, sizeof(gprs_ns_unblock)); gprs_process_message(nsi, "BSSGP RESET", &peer[0], gprs_bssgp_reset, sizeof(gprs_bssgp_reset)); printf("--- Peer port changes, RESET, message remains unchanged ---\n\n"); - gprs_process_message(nsi, "RESET", &peer[1], - gprs_ns_reset, sizeof(gprs_ns_reset)); + send_ns_reset(nsi, &peer[1], NS_CAUSE_OM_INTERVENTION, 0x1122, 0x1122); gprs_dump_nsi(nsi); printf("--- Peer port changes, RESET, VCI changes ---\n\n"); - gprs_process_message(nsi, "RESET", &peer[2], - gprs_ns_reset_vci2, sizeof(gprs_ns_reset_vci2)); + send_ns_reset(nsi, &peer[2], NS_CAUSE_OM_INTERVENTION, 0x3344, 0x1122); gprs_dump_nsi(nsi); printf("--- Peer port changes, RESET, NSEI changes ---\n\n"); - gprs_process_message(nsi, "RESET", &peer[3], - gprs_ns_reset_nsei2, sizeof(gprs_ns_reset_nsei2)); + send_ns_reset(nsi, &peer[3], NS_CAUSE_OM_INTERVENTION, 0x1122, 0x3344); gprs_dump_nsi(nsi); printf("--- Peer port 3333, RESET, VCI is changed back ---\n\n"); - gprs_process_message(nsi, "RESET", &peer[2], - gprs_ns_reset, sizeof(gprs_ns_reset)); + send_ns_reset(nsi, &peer[2], NS_CAUSE_OM_INTERVENTION, 0x1122, 0x1122); gprs_dump_nsi(nsi); printf("--- Peer port 4444, RESET, NSEI is changed back ---\n\n"); - gprs_process_message(nsi, "RESET", &peer[3], - gprs_ns_reset, sizeof(gprs_ns_reset)); + send_ns_reset(nsi, &peer[3], NS_CAUSE_OM_INTERVENTION, 0x1122, 0x1122); gprs_dump_nsi(nsi); gprs_ns_destroy(nsi); @@ -296,6 +496,65 @@ static void test_ns() } +static void test_sgsn_output() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in sgsn_peer= {0}; + + sgsn_peer.sin_family = AF_INET; + sgsn_peer.sin_port = htons(32000); + sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR); + + gprs_dump_nsi(nsi); + + printf("--- Send message to SGSN ---\n\n"); + + gprs_send_message(nsi, "BSSGP RESET", SGSN_NSEI, 0, + gprs_bssgp_reset+4, sizeof(gprs_bssgp_reset)-4); + + printf("--- Setup dead connection to SGSN ---\n\n"); + + gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1); + gprs_dump_nsi(nsi); + + printf("--- Send message to SGSN ---\n\n"); + + gprs_send_message(nsi, "BSSGP RESET", SGSN_NSEI, 0, + gprs_bssgp_reset+4, sizeof(gprs_bssgp_reset)-4); + + printf("--- Make connection to SGSN alive ---\n\n"); + + send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); + send_ns_alive_ack(nsi, &sgsn_peer); + gprs_dump_nsi(nsi); + + printf("--- Send message to SGSN ---\n\n"); + + gprs_send_message(nsi, "BSSGP RESET", SGSN_NSEI, 0, + gprs_bssgp_reset+4, sizeof(gprs_bssgp_reset)-4); + + printf("--- Unblock connection to SGSN ---\n\n"); + + send_ns_unblock_ack(nsi, &sgsn_peer); + send_ns_alive(nsi, &sgsn_peer); + gprs_dump_nsi(nsi); + + printf("--- Send message to SGSN ---\n\n"); + + gprs_send_message(nsi, "BSSGP RESET", SGSN_NSEI, 0, + gprs_bssgp_reset+4, sizeof(gprs_bssgp_reset)-4); + + printf("--- Send empty message with BVCI to SGSN ---\n\n"); + + gprs_send_message(nsi, "[empty]", SGSN_NSEI, 0x0102, + gprs_bssgp_reset, 0); + + + gprs_ns_destroy(nsi); + nsi = NULL; +} + + int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx) { return -1; @@ -311,7 +570,8 @@ int main(int argc, char **argv) osmo_signal_register_handler(SS_L_NS, &test_signal, NULL); printf("===== NS protocol test START\n"); - test_ns(); + test_bss_port_changes(); + test_sgsn_output(); printf("===== NS protocol test END\n\n"); exit(EXIT_SUCCESS); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 7be84ef..7366278 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -1,23 +1,24 @@ ===== NS protocol test START +--- Setup, send BSSGB RESET --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1122(4386), NSEI 0x1122(4386) + PROCESSING RESET from 0x01020304:1111 02 00 81 01 01 82 11 22 04 82 11 22 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:1111 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 -Current NS-VCIs: - VCI 0x1122, NSEI 0x1122, peer 0x01020304:1111 - PROCESSING ALIVE from 0x01020304:1111 0a -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0b result (ALIVE) = 1 @@ -26,11 +27,19 @@ PROCESSING UNBLOCK from 0x01020304:1111 06 ==> got signal NS_UNBLOCK, NS-VC 0x1122/1.2.3.4:1111 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 07 result (UNBLOCK) = 1 +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x1122, NSEI 0x1122, peer 0x01020304:1111 + PROCESSING BSSGP RESET from 0x01020304:1111 00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 @@ -45,16 +54,16 @@ PROCESSING RESET from 0x01020304:2222 02 00 81 01 01 82 11 22 04 82 11 22 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:2222 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 Current NS-VCIs: - VCI 0x1122, NSEI 0x1122, peer 0x01020304:2222 + VCI 0x1122, NSEI 0x1122, peer 0x01020304:2222, blocked --- Peer port changes, RESET, VCI changes --- @@ -62,17 +71,17 @@ PROCESSING RESET from 0x01020304:3333 02 00 81 01 01 82 33 44 04 82 11 22 ==> got signal NS_RESET, NS-VC 0x3344/1.2.3.4:3333 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 33 44 04 82 11 22 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 Current NS-VCIs: - VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333 - VCI 0x1122, NSEI 0x1122, peer 0x01020304:2222 + VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333, blocked + VCI 0x1122, NSEI 0x1122, peer 0x01020304:2222, blocked --- Peer port changes, RESET, NSEI changes --- @@ -80,17 +89,17 @@ PROCESSING RESET from 0x01020304:4444 02 00 81 01 01 82 11 22 04 82 33 44 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:4444 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 11 22 04 82 33 44 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 Current NS-VCIs: - VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333 - VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 + VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333, blocked + VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444, blocked NS-VC changed NSEI : 1 --- Peer port 3333, RESET, VCI is changed back --- @@ -100,17 +109,17 @@ PROCESSING RESET from 0x01020304:3333 ==> got signal NS_REPLACED: 0x1122/1.2.3.4:4444 -> 0x3344/1.2.3.4:3333 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:3333 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 Current NS-VCIs: - VCI 0x3344, NSEI 0x1122, peer 0x00000000:0 - VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 + VCI 0x3344, NSEI 0x1122, peer 0x00000000:0, blocked + VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333, blocked NS-VC replaced other count: 1 NS-VC changed NSEI : 2 @@ -120,19 +129,99 @@ PROCESSING RESET from 0x01020304:4444 02 00 81 01 01 82 11 22 04 82 11 22 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:4444 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 Current NS-VCIs: - VCI 0x3344, NSEI 0x1122, peer 0x00000000:0 - VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444 + VCI 0x3344, NSEI 0x1122, peer 0x00000000:0, blocked + VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444, blocked + NS-VC replaced other count: 1 + NS-VC changed NSEI : 2 + +--- Send message to SGSN --- + +SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 +22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = -22 + +--- Setup blocked connection to SGSN --- + +MESSAGE to SGSN, msg length 12 +02 00 81 01 01 82 01 01 04 82 01 00 + +PROCESSING RESET_ACK from 0x05060708:32000 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET_ACK) = 1 + +PROCESSING ALIVE_ACK from 0x05060708:32000 +0b + +MESSAGE to SGSN, msg length 1 +06 + +result (ALIVE_ACK) = 1 + +--- Send message to SGSN --- + +SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 +22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +MESSAGE to SGSN, msg length 22 +00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = 22 + +--- Unblock connection to SGSN --- + +PROCESSING UNBLOCK_ACK from 0x05060708:32000 +07 + +==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000 +result (UNBLOCK_ACK) = 0 + +PROCESSING ALIVE from 0x05060708:32000 +0a + +MESSAGE to SGSN, msg length 1 +0b + +result (ALIVE) = 1 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + VCI 0x3344, NSEI 0x1122, peer 0x00000000:0, blocked + VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444, blocked NS-VC replaced other count: 1 NS-VC changed NSEI : 2 +--- Send message to SGSN --- + +SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 +22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = -16 + +--- Send empty message with BVCI to SGSN --- + +SENDING [empty] to NSEI 0x0100, BVCI 0x0102 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0102, msg length 0 + + +result ([empty]) = -16 + ===== NS protocol test END -- 1.7.9.5 From jerlbeck at sysmocom.de Thu Oct 17 10:05:58 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 17 Oct 2013 12:05:58 +0200 Subject: [PATCH 2/2] gb: Fix gprs_active_nsvc_by_nsei() In-Reply-To: <1382004358-17724-1-git-send-email-jerlbeck@sysmocom.de> References: <1381745034-16815-1-git-send-email-jerlbeck@sysmocom.de> <1382004358-17724-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382004358-17724-2-git-send-email-jerlbeck@sysmocom.de> The state matching condition is inverted. This is corrected by this fix. Sponsored-by: On-Waves ehf --- src/gb/gprs_ns.c | 4 ++-- tests/gb/gprs_ns_test.ok | 42 ++++++++++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index bdc7ae3..6a35ad3 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -158,8 +158,8 @@ static struct gprs_nsvc *gprs_active_nsvc_by_nsei(struct gprs_ns_inst *nsi, struct gprs_nsvc *nsvc; llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { if (nsvc->nsei == nsei) { - if (nsvc->state & NSE_S_BLOCKED || - !(nsvc->state & NSE_S_ALIVE)) + if (!(nsvc->state & NSE_S_BLOCKED) && + nsvc->state & NSE_S_ALIVE) return nsvc; } } diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 7366278..424d681 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -1,5 +1,5 @@ ===== NS protocol test START ---- Setup, send BSSGB RESET --- +--- Setup, send BSSGP RESET --- Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1122(4386), NSEI 0x1122(4386) @@ -143,6 +143,8 @@ Current NS-VCIs: NS-VC replaced other count: 1 NS-VC changed NSEI : 2 +Current NS-VCIs: + --- Send message to SGSN --- SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 @@ -151,11 +153,24 @@ NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 result (BSSGP RESET) = -22 ---- Setup blocked connection to SGSN --- +--- Setup dead connection to SGSN --- MESSAGE to SGSN, msg length 12 02 00 81 01 01 82 01 01 04 82 01 00 +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked, dead + +--- Send message to SGSN --- + +SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 +22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = -16 + +--- Make connection to SGSN alive --- + PROCESSING RESET_ACK from 0x05060708:32000 03 01 82 01 01 04 82 01 00 @@ -172,16 +187,17 @@ MESSAGE to SGSN, msg length 1 result (ALIVE_ACK) = 1 +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked + NS-VC Block count : 1 + --- Send message to SGSN --- SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 -MESSAGE to SGSN, msg length 22 -00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 - -result (BSSGP RESET) = 22 +result (BSSGP RESET) = -16 --- Unblock connection to SGSN --- @@ -202,10 +218,6 @@ result (ALIVE) = 1 Current NS-VCIs: VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 NS-VC Block count : 1 - VCI 0x3344, NSEI 0x1122, peer 0x00000000:0, blocked - VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444, blocked - NS-VC replaced other count: 1 - NS-VC changed NSEI : 2 --- Send message to SGSN --- @@ -213,7 +225,10 @@ SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 -result (BSSGP RESET) = -16 +MESSAGE to SGSN, msg length 22 +00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = 22 --- Send empty message with BVCI to SGSN --- @@ -221,7 +236,10 @@ SENDING [empty] to NSEI 0x0100, BVCI 0x0102 NS UNITDATA MESSAGE to SGSN, BVCI 0x0102, msg length 0 -result ([empty]) = -16 +MESSAGE to SGSN, msg length 4 +00 00 01 02 + +result ([empty]) = 4 ===== NS protocol test END -- 1.7.9.5 From jerlbeck at sysmocom.de Thu Oct 17 11:58:34 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 17 Oct 2013 13:58:34 +0200 Subject: [PATCH 1/2] gb: Test sending messages to the SGSN In-Reply-To: <1382004358-17724-1-git-send-email-jerlbeck@sysmocom.de> References: <1382004358-17724-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382011115-15392-1-git-send-email-jerlbeck@sysmocom.de> This adds tests for the gprs_ns_sendmsg() function. For this it merges back functions from the gbproxy test. Sponsored-by: On-Waves ehf --- tests/gb/gprs_ns_test.c | 312 ++++++++++++++++++++++++++++++++++++++++++---- tests/gb/gprs_ns_test.ok | 159 +++++++++++++++++++---- 2 files changed, 418 insertions(+), 53 deletions(-) diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index d7b769d..38c7d1f 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -26,6 +26,155 @@ #include #include +#define REMOTE_BSS_ADDR 0x01020304 +#define REMOTE_SGSN_ADDR 0x05060708 + +#define SGSN_NSEI 0x0100 + +static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, + struct sockaddr_in *peer, const unsigned char* data, + size_t data_len); + +static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + enum ns_cause cause, uint16_t nsvci, uint16_t nsei) +{ + /* GPRS Network Service, PDU type: NS_RESET, + */ + unsigned char msg[12] = { + 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22, + 0x04, 0x82, 0x11, 0x22 + }; + + msg[3] = cause; + msg[6] = nsvci / 256; + msg[7] = nsvci % 256; + msg[10] = nsei / 256; + msg[11] = nsei % 256; + + gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg)); +} + +static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsvci, uint16_t nsei) +{ + /* GPRS Network Service, PDU type: NS_RESET_ACK, + */ + unsigned char msg[9] = { + 0x03, 0x01, 0x82, 0x11, 0x22, + 0x04, 0x82, 0x11, 0x22 + }; + + msg[3] = nsvci / 256; + msg[4] = nsvci % 256; + msg[7] = nsei / 256; + msg[8] = nsei % 256; + + gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_ALIVE */ + unsigned char msg[1] = { + 0x0a + }; + + gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg)); +} + +static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_ALIVE_ACK */ + unsigned char msg[1] = { + 0x0b + }; + + gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_UNBLOCK */ + unsigned char msg[1] = { + 0x06 + }; + + gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */ + unsigned char msg[1] = { + 0x07 + }; + + gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unitdata(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsbvci, + const unsigned char *bssgp_msg, size_t bssgp_msg_size) +{ + /* GPRS Network Service, PDU type: NS_UNITDATA */ + unsigned char msg[4096] = { + 0x00, 0x00, 0x00, 0x00 + }; + + OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4); + + msg[2] = nsbvci / 256; + msg[3] = nsbvci % 256; + memcpy(msg + 4, bssgp_msg, bssgp_msg_size); + + gprs_process_message(nsi, "UNITDATA", src_addr, msg, bssgp_msg_size + 4); +} + +static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t bvci) +{ + /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0 + * BSSGP RESET */ + unsigned char msg[22] = { + 0x22, 0x04, 0x82, 0x4a, + 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x10, 0x20, + 0x30, 0x40, 0x50, 0x60, 0x10, 0x00 + }; + + msg[3] = bvci / 256; + msg[4] = bvci % 256; + + send_ns_unitdata(nsi, src_addr, 0, msg, sizeof(msg)); +} + +static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsvci, uint16_t nsei) +{ + printf("Setup NS-VC: remote 0x%08x:%d, " + "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n", + ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port), + nsvci, nsvci, nsei, nsei); + + send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei); + send_ns_alive(nsi, src_addr); + send_ns_unblock(nsi, src_addr); + send_ns_alive_ack(nsi, src_addr); +} + +static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t bvci) __attribute__((__unused__)); + +static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t bvci) +{ + printf("Setup BSSGP: remote 0x%08x:%d, " + "BVCI 0x%04x(%d)\n\n", + ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port), + bvci, bvci); + + send_bssgp_reset(nsi, src_addr, bvci); +} + /* GPRS Network Service, PDU type: NS_RESET, * Cause: O&M intervention, NS VCI: 0x1122, NSEI 0x1122 */ @@ -110,18 +259,45 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, typedef ssize_t (*sendto_t)(int, const void *, size_t, int, const struct sockaddr *, socklen_t); static sendto_t real_sendto = NULL; + uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr); if (!real_sendto) real_sendto = dlsym(RTLD_NEXT, "sendto"); - if (((struct sockaddr_in *)dest_addr)->sin_addr.s_addr != htonl(0x01020304)) + if (dest_host == REMOTE_BSS_ADDR) + printf("MESSAGE to BSS, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + else if (dest_host == REMOTE_SGSN_ADDR) + printf("MESSAGE to SGSN, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + else return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen); - printf("RESPONSE, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); - return len; } +/* override */ +int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) +{ + typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg); + static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL; + uint16_t bvci = msgb_bvci(msg); + uint16_t nsei = msgb_nsei(msg); + + unsigned char *buf = msg->data; + size_t len = msg->len; + + if (!real_gprs_ns_sendmsg) + real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg"); + + if (nsei == SGSN_NSEI) + printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, msg length %d\n%s\n\n", + bvci, len, osmo_hexdump(buf, len)); + else + printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, msg length %d\n%s\n\n", + bvci, len, osmo_hexdump(buf, len)); + + return real_gprs_ns_sendmsg(nsi, msg); +} + static void dump_rate_ctr_group(FILE *stream, const char *prefix, struct rate_ctr_group *ctrg) { @@ -217,6 +393,34 @@ static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, stru return ret; } +static int gprs_send_message(struct gprs_ns_inst *nsi, const char *text, + uint16_t nsei, uint16_t bvci, + const unsigned char* data, size_t data_len) +{ + struct msgb *msg; + int ret; + if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) { + fprintf(stderr, "message too long: %d\n", data_len); + return -1; + } + + msg = gprs_ns_msgb_alloc(); + memmove(msg->data, data, data_len); + msg->l2h = msg->data; + msgb_put(msg, data_len); + + msgb_nsei(msg) = nsei; + msgb_bvci(msg) = bvci; + + printf("SENDING %s to NSEI 0x%04x, BVCI 0x%04x\n", text, nsei, bvci); + + ret = gprs_ns_sendmsg(nsi, msg); + + printf("result (%s) = %d\n\n", text, ret); + + return ret; +} + static void gprs_dump_nsi(struct gprs_ns_inst *nsi) { struct gprs_nsvc *nsvc; @@ -224,71 +428,65 @@ static void gprs_dump_nsi(struct gprs_ns_inst *nsi) printf("Current NS-VCIs:\n"); llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { struct sockaddr_in *peer = &(nsvc->ip.bts_addr); - printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d\n", + printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n", nsvc->nsvci, nsvc->nsei, - ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port) + ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port), + nsvc->state & NSE_S_BLOCKED ? ", blocked" : "", + nsvc->state & NSE_S_ALIVE ? "" : ", dead" ); dump_rate_ctr_group(stdout, " ", nsvc->ctrg); } printf("\n"); } -static void test_ns() +static void test_bss_port_changes() { struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); struct sockaddr_in peer[4] = {{0},}; peer[0].sin_family = AF_INET; peer[0].sin_port = htons(1111); - peer[0].sin_addr.s_addr = htonl(0x01020304); + peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); peer[1].sin_family = AF_INET; peer[1].sin_port = htons(2222); - peer[1].sin_addr.s_addr = htonl(0x01020304); + peer[1].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); peer[2].sin_family = AF_INET; peer[2].sin_port = htons(3333); - peer[2].sin_addr.s_addr = htonl(0x01020304); + peer[2].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); peer[3].sin_family = AF_INET; peer[3].sin_port = htons(4444); - peer[3].sin_addr.s_addr = htonl(0x01020304); + peer[3].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); - gprs_process_message(nsi, "RESET", &peer[0], - gprs_ns_reset, sizeof(gprs_ns_reset)); + printf("--- Setup, send BSSGP RESET ---\n\n"); + + setup_ns(nsi, &peer[0], 0x1122, 0x1122); gprs_dump_nsi(nsi); - gprs_process_message(nsi, "ALIVE", &peer[0], - gprs_ns_alive, sizeof(gprs_ns_alive)); - gprs_process_message(nsi, "UNBLOCK", &peer[0], - gprs_ns_unblock, sizeof(gprs_ns_unblock)); gprs_process_message(nsi, "BSSGP RESET", &peer[0], gprs_bssgp_reset, sizeof(gprs_bssgp_reset)); printf("--- Peer port changes, RESET, message remains unchanged ---\n\n"); - gprs_process_message(nsi, "RESET", &peer[1], - gprs_ns_reset, sizeof(gprs_ns_reset)); + send_ns_reset(nsi, &peer[1], NS_CAUSE_OM_INTERVENTION, 0x1122, 0x1122); gprs_dump_nsi(nsi); printf("--- Peer port changes, RESET, VCI changes ---\n\n"); - gprs_process_message(nsi, "RESET", &peer[2], - gprs_ns_reset_vci2, sizeof(gprs_ns_reset_vci2)); + send_ns_reset(nsi, &peer[2], NS_CAUSE_OM_INTERVENTION, 0x3344, 0x1122); gprs_dump_nsi(nsi); printf("--- Peer port changes, RESET, NSEI changes ---\n\n"); - gprs_process_message(nsi, "RESET", &peer[3], - gprs_ns_reset_nsei2, sizeof(gprs_ns_reset_nsei2)); + send_ns_reset(nsi, &peer[3], NS_CAUSE_OM_INTERVENTION, 0x1122, 0x3344); gprs_dump_nsi(nsi); printf("--- Peer port 3333, RESET, VCI is changed back ---\n\n"); - gprs_process_message(nsi, "RESET", &peer[2], - gprs_ns_reset, sizeof(gprs_ns_reset)); + send_ns_reset(nsi, &peer[2], NS_CAUSE_OM_INTERVENTION, 0x1122, 0x1122); gprs_dump_nsi(nsi); printf("--- Peer port 4444, RESET, NSEI is changed back ---\n\n"); - gprs_process_message(nsi, "RESET", &peer[3], - gprs_ns_reset, sizeof(gprs_ns_reset)); + send_ns_reset(nsi, &peer[3], NS_CAUSE_OM_INTERVENTION, 0x1122, 0x1122); gprs_dump_nsi(nsi); gprs_ns_destroy(nsi); @@ -296,6 +494,65 @@ static void test_ns() } +static void test_sgsn_output() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in sgsn_peer= {0}; + + sgsn_peer.sin_family = AF_INET; + sgsn_peer.sin_port = htons(32000); + sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR); + + gprs_dump_nsi(nsi); + + printf("--- Send message to SGSN ---\n\n"); + + gprs_send_message(nsi, "BSSGP RESET", SGSN_NSEI, 0, + gprs_bssgp_reset+4, sizeof(gprs_bssgp_reset)-4); + + printf("--- Setup dead connection to SGSN ---\n\n"); + + gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1); + gprs_dump_nsi(nsi); + + printf("--- Send message to SGSN ---\n\n"); + + gprs_send_message(nsi, "BSSGP RESET", SGSN_NSEI, 0, + gprs_bssgp_reset+4, sizeof(gprs_bssgp_reset)-4); + + printf("--- Make connection to SGSN alive ---\n\n"); + + send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); + send_ns_alive_ack(nsi, &sgsn_peer); + gprs_dump_nsi(nsi); + + printf("--- Send message to SGSN ---\n\n"); + + gprs_send_message(nsi, "BSSGP RESET", SGSN_NSEI, 0, + gprs_bssgp_reset+4, sizeof(gprs_bssgp_reset)-4); + + printf("--- Unblock connection to SGSN ---\n\n"); + + send_ns_unblock_ack(nsi, &sgsn_peer); + send_ns_alive(nsi, &sgsn_peer); + gprs_dump_nsi(nsi); + + printf("--- Send message to SGSN ---\n\n"); + + gprs_send_message(nsi, "BSSGP RESET", SGSN_NSEI, 0, + gprs_bssgp_reset+4, sizeof(gprs_bssgp_reset)-4); + + printf("--- Send empty message with BVCI to SGSN ---\n\n"); + + gprs_send_message(nsi, "[empty]", SGSN_NSEI, 0x0102, + gprs_bssgp_reset, 0); + + + gprs_ns_destroy(nsi); + nsi = NULL; +} + + int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx) { return -1; @@ -311,7 +568,8 @@ int main(int argc, char **argv) osmo_signal_register_handler(SS_L_NS, &test_signal, NULL); printf("===== NS protocol test START\n"); - test_ns(); + test_bss_port_changes(); + test_sgsn_output(); printf("===== NS protocol test END\n\n"); exit(EXIT_SUCCESS); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 7be84ef..5dc1e92 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -1,23 +1,24 @@ ===== NS protocol test START +--- Setup, send BSSGP RESET --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1122(4386), NSEI 0x1122(4386) + PROCESSING RESET from 0x01020304:1111 02 00 81 01 01 82 11 22 04 82 11 22 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:1111 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 -Current NS-VCIs: - VCI 0x1122, NSEI 0x1122, peer 0x01020304:1111 - PROCESSING ALIVE from 0x01020304:1111 0a -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0b result (ALIVE) = 1 @@ -26,11 +27,19 @@ PROCESSING UNBLOCK from 0x01020304:1111 06 ==> got signal NS_UNBLOCK, NS-VC 0x1122/1.2.3.4:1111 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 07 result (UNBLOCK) = 1 +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x1122, NSEI 0x1122, peer 0x01020304:1111 + PROCESSING BSSGP RESET from 0x01020304:1111 00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 @@ -45,16 +54,16 @@ PROCESSING RESET from 0x01020304:2222 02 00 81 01 01 82 11 22 04 82 11 22 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:2222 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 Current NS-VCIs: - VCI 0x1122, NSEI 0x1122, peer 0x01020304:2222 + VCI 0x1122, NSEI 0x1122, peer 0x01020304:2222, blocked --- Peer port changes, RESET, VCI changes --- @@ -62,17 +71,17 @@ PROCESSING RESET from 0x01020304:3333 02 00 81 01 01 82 33 44 04 82 11 22 ==> got signal NS_RESET, NS-VC 0x3344/1.2.3.4:3333 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 33 44 04 82 11 22 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 Current NS-VCIs: - VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333 - VCI 0x1122, NSEI 0x1122, peer 0x01020304:2222 + VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333, blocked + VCI 0x1122, NSEI 0x1122, peer 0x01020304:2222, blocked --- Peer port changes, RESET, NSEI changes --- @@ -80,17 +89,17 @@ PROCESSING RESET from 0x01020304:4444 02 00 81 01 01 82 11 22 04 82 33 44 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:4444 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 11 22 04 82 33 44 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 Current NS-VCIs: - VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333 - VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 + VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333, blocked + VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444, blocked NS-VC changed NSEI : 1 --- Peer port 3333, RESET, VCI is changed back --- @@ -100,17 +109,17 @@ PROCESSING RESET from 0x01020304:3333 ==> got signal NS_REPLACED: 0x1122/1.2.3.4:4444 -> 0x3344/1.2.3.4:3333 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:3333 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 Current NS-VCIs: - VCI 0x3344, NSEI 0x1122, peer 0x00000000:0 - VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 + VCI 0x3344, NSEI 0x1122, peer 0x00000000:0, blocked + VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333, blocked NS-VC replaced other count: 1 NS-VC changed NSEI : 2 @@ -120,19 +129,117 @@ PROCESSING RESET from 0x01020304:4444 02 00 81 01 01 82 11 22 04 82 11 22 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:4444 -RESPONSE, msg length 9 +MESSAGE to BSS, msg length 9 03 01 82 11 22 04 82 11 22 -RESPONSE, msg length 1 +MESSAGE to BSS, msg length 1 0a result (RESET) = 9 Current NS-VCIs: - VCI 0x3344, NSEI 0x1122, peer 0x00000000:0 - VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444 + VCI 0x3344, NSEI 0x1122, peer 0x00000000:0, blocked + VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444, blocked NS-VC replaced other count: 1 NS-VC changed NSEI : 2 +Current NS-VCIs: + +--- Send message to SGSN --- + +SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 +22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = -22 + +--- Setup dead connection to SGSN --- + +MESSAGE to SGSN, msg length 12 +02 00 81 01 01 82 01 01 04 82 01 00 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked, dead + +--- Send message to SGSN --- + +SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 +22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +MESSAGE to SGSN, msg length 22 +00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = 22 + +--- Make connection to SGSN alive --- + +PROCESSING RESET_ACK from 0x05060708:32000 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET_ACK) = 1 + +PROCESSING ALIVE_ACK from 0x05060708:32000 +0b + +MESSAGE to SGSN, msg length 1 +06 + +result (ALIVE_ACK) = 1 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked + NS-VC Block count : 1 + +--- Send message to SGSN --- + +SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 +22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +MESSAGE to SGSN, msg length 22 +00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = 22 + +--- Unblock connection to SGSN --- + +PROCESSING UNBLOCK_ACK from 0x05060708:32000 +07 + +==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000 +result (UNBLOCK_ACK) = 0 + +PROCESSING ALIVE from 0x05060708:32000 +0a + +MESSAGE to SGSN, msg length 1 +0b + +result (ALIVE) = 1 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +--- Send message to SGSN --- + +SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 +22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = -16 + +--- Send empty message with BVCI to SGSN --- + +SENDING [empty] to NSEI 0x0100, BVCI 0x0102 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0102, msg length 0 + + +result ([empty]) = -16 + ===== NS protocol test END -- 1.7.9.5 From jerlbeck at sysmocom.de Thu Oct 17 11:58:35 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 17 Oct 2013 13:58:35 +0200 Subject: [PATCH 2/2] gb: Fix gprs_active_nsvc_by_nsei() In-Reply-To: <1382011115-15392-1-git-send-email-jerlbeck@sysmocom.de> References: <1382004358-17724-1-git-send-email-jerlbeck@sysmocom.de> <1382011115-15392-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382011115-15392-2-git-send-email-jerlbeck@sysmocom.de> The state matching condition is inverted. This is corrected by this fix. Sponsored-by: On-Waves ehf --- src/gb/gprs_ns.c | 4 ++-- tests/gb/gprs_ns_test.ok | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index bdc7ae3..6a35ad3 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -158,8 +158,8 @@ static struct gprs_nsvc *gprs_active_nsvc_by_nsei(struct gprs_ns_inst *nsi, struct gprs_nsvc *nsvc; llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { if (nsvc->nsei == nsei) { - if (nsvc->state & NSE_S_BLOCKED || - !(nsvc->state & NSE_S_ALIVE)) + if (!(nsvc->state & NSE_S_BLOCKED) && + nsvc->state & NSE_S_ALIVE) return nsvc; } } diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 5dc1e92..424d681 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -167,10 +167,7 @@ SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 -MESSAGE to SGSN, msg length 22 -00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 - -result (BSSGP RESET) = 22 +result (BSSGP RESET) = -16 --- Make connection to SGSN alive --- @@ -200,10 +197,7 @@ SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 -MESSAGE to SGSN, msg length 22 -00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 - -result (BSSGP RESET) = 22 +result (BSSGP RESET) = -16 --- Unblock connection to SGSN --- @@ -231,7 +225,10 @@ SENDING BSSGP RESET to NSEI 0x0100, BVCI 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 -result (BSSGP RESET) = -16 +MESSAGE to SGSN, msg length 22 +00 00 00 00 22 04 82 4a 2e 07 81 08 08 88 10 20 30 40 50 60 10 00 + +result (BSSGP RESET) = 22 --- Send empty message with BVCI to SGSN --- @@ -239,7 +236,10 @@ SENDING [empty] to NSEI 0x0100, BVCI 0x0102 NS UNITDATA MESSAGE to SGSN, BVCI 0x0102, msg length 0 -result ([empty]) = -16 +MESSAGE to SGSN, msg length 4 +00 00 01 02 + +result ([empty]) = 4 ===== NS protocol test END -- 1.7.9.5 From jerlbeck at sysmocom.de Mon Oct 14 20:06:47 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Mon, 14 Oct 2013 22:06:47 +0200 Subject: [PATCH 1/2] gb: Add functions to access the LL part of the NS-VC objects Message-ID: <1381781208-20484-1-git-send-email-jerlbeck@sysmocom.de> Adds the functions gprs_ns_ll_copy() and gprs_ns_ll_clear(). Renames gprs_ns_format_peer() to gprs_ns_ll_str(). All of these functions uniformly access the link layer part within the NS-VC objects. Sponsored-by: On-Waves ehf --- include/osmocom/gprs/gprs_ns.h | 8 +++++++- src/gb/gprs_ns.c | 42 +++++++++++++++++++++++++++++++++++----- src/gb/libosmogb.map | 4 +++- tests/gb/gprs_ns_test.c | 10 +++++----- 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index d16068b..7b0ec92 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -177,7 +177,13 @@ void gprs_nsvc_reset(struct gprs_nsvc *nsvc, uint8_t cause); int gprs_ns_vty_init(struct gprs_ns_inst *nsi); /* Resturn peer info as string (NOTE: the buffer is allocated statically) */ -const char *gprs_ns_format_peer(struct gprs_nsvc *nsvc); +const char *gprs_ns_ll_str(struct gprs_nsvc *nsvc); + +/* Copy the link layer info from other into nsvc */ +void gprs_ns_ll_copy(struct gprs_nsvc *nsvc, struct gprs_nsvc *other); + +/* Clear the link layer info (will never match a real link then) */ +void gprs_ns_ll_clear(struct gprs_nsvc *nsvc); #define NS_ALLOC_SIZE 2048 #define NS_ALLOC_HEADROOM 20 diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 7801b29..61a96d7 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -802,7 +802,7 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, return rc; } -const char *gprs_ns_format_peer(struct gprs_nsvc *nsvc) +const char *gprs_ns_ll_str(struct gprs_nsvc *nsvc) { static char buf[80]; snprintf(buf, sizeof(buf), "%s:%u", @@ -812,6 +812,38 @@ const char *gprs_ns_format_peer(struct gprs_nsvc *nsvc) return buf; } +void gprs_ns_ll_copy(struct gprs_nsvc *nsvc, struct gprs_nsvc *other) +{ + nsvc->ll = other->ll; + + switch (nsvc->ll) { + case GPRS_NS_LL_UDP: + nsvc->ip = other->ip; + break; + case GPRS_NS_LL_FR_GRE: + nsvc->frgre = other->frgre; + break; + default: + break; + } +} + +void gprs_ns_ll_clear(struct gprs_nsvc *nsvc) +{ + switch (nsvc->ll) { + case GPRS_NS_LL_UDP: + nsvc->ip.bts_addr.sin_addr.s_addr = INADDR_ANY; + nsvc->ip.bts_addr.sin_port = 0; + break; + case GPRS_NS_LL_FR_GRE: + nsvc->frgre.bts_addr.sin_addr.s_addr = INADDR_ANY; + nsvc->frgre.bts_addr.sin_port = 0; + break; + default: + break; + } +} + /*! \brief Create/get NS-VC independently from underlying transport layer * \param nsi NS instance to which the data belongs * \param[in] msg message buffer containing newly-received data @@ -841,7 +873,7 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, if (nsh->pdu_type == NS_PDUT_STATUS) { LOGP(DNS, LOGL_INFO, "Ignoring NS STATUS from %s " "for non-existing NS-VC\n", - gprs_ns_format_peer(fallback_nsvc)); + gprs_ns_ll_str(fallback_nsvc)); return GPRS_NS_CS_SKIPPED; } @@ -851,7 +883,7 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, log_set_context(GPRS_CTX_NSVC, fallback_nsvc); LOGP(DNS, LOGL_INFO, "Rejecting NS PDU type 0x%0x " "from %s for non-existing NS-VC\n", - nsh->pdu_type, gprs_ns_format_peer(fallback_nsvc)); + nsh->pdu_type, gprs_ns_ll_str(fallback_nsvc)); fallback_nsvc->nsvci = fallback_nsvc->nsei = 0xfffe; fallback_nsvc->state = NSE_S_ALIVE; @@ -859,7 +891,7 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, NS_CAUSE_PDU_INCOMP_PSTATE, 0, msg); if (rc < 0) { LOGP(DNS, LOGL_ERROR, "TX failed (%d) to peer %s\n", - rc, gprs_ns_format_peer(fallback_nsvc)); + rc, gprs_ns_ll_str(fallback_nsvc)); return rc; } return GPRS_NS_CS_REJECTED; @@ -887,7 +919,7 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, *new_nsvc = gprs_nsvc_create(nsi, 0xffff); log_set_context(GPRS_CTX_NSVC, *new_nsvc); LOGP(DNS, LOGL_INFO, "Creating NS-VC for BSS at %s\n", - gprs_ns_format_peer(fallback_nsvc)); + gprs_ns_ll_str(fallback_nsvc)); return GPRS_NS_CS_CREATED; } diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map index 0270db8..a21a7ac 100644 --- a/src/gb/libosmogb.map +++ b/src/gb/libosmogb.map @@ -54,7 +54,9 @@ gprs_ns_tx_reset; gprs_ns_tx_status; gprs_ns_tx_unblock; gprs_ns_vty_init; -gprs_ns_format_peer; +gprs_ns_ll_str; +gprs_ns_ll_copy; +gprs_ns_ll_clear; gprs_nsvc_create; gprs_nsvc_delete; diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index c4fc228..1474fd4 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -134,31 +134,31 @@ static int test_signal(unsigned int subsys, unsigned int signal, case S_NS_RESET: printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n", nssd->nsvc->nsvci, - gprs_ns_format_peer(nssd->nsvc)); + gprs_ns_ll_str(nssd->nsvc)); break; case S_NS_ALIVE_EXP: printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n", nssd->nsvc->nsvci, - gprs_ns_format_peer(nssd->nsvc)); + gprs_ns_ll_str(nssd->nsvc)); break; case S_NS_BLOCK: printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n", nssd->nsvc->nsvci, - gprs_ns_format_peer(nssd->nsvc)); + gprs_ns_ll_str(nssd->nsvc)); break; case S_NS_UNBLOCK: printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n", nssd->nsvc->nsvci, - gprs_ns_format_peer(nssd->nsvc)); + gprs_ns_ll_str(nssd->nsvc)); break; default: printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal, nssd->nsvc->nsvci, - gprs_ns_format_peer(nssd->nsvc)); + gprs_ns_ll_str(nssd->nsvc)); break; } -- 1.7.9.5 From jerlbeck at sysmocom.de Mon Oct 14 20:06:48 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Mon, 14 Oct 2013 22:06:48 +0200 Subject: [PATCH 2/2] gb: Fix gprs_ns_rx_reset to not create NS-VC duplicates In-Reply-To: <1381781208-20484-1-git-send-email-jerlbeck@sysmocom.de> References: <1381781208-20484-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1381781208-20484-2-git-send-email-jerlbeck@sysmocom.de> Under special circumstances (see below) receiving a NS-RESET leads to duplicated NS-VC entries. This happens when the source port of a NS-VC changes to a new one that has already been used by another NS-VC. This patch changes gprs_ns_rx_reset() to check for this case and to use the existing NS-VC object. The NS-VC object that was associated with the source address before is detached from this source but kept in the NS-VC list so that it can be reattached when a correspondent NS-RESET is received later on. Meanwhile it will have a cleared link layer address which will not match a real link info. A new counter NS_CTR_REPLACED is incremented each time when the NS-VC object is replacing another one. A new signal S_NS_REPLACED is added which gets dispatched in this case, too. Another new counter NS_CTR_NSEI_CHG is incremented each time when the NSEI of a NS-VC object (with fixed NSVCI) changes. Ticket: OW#874 Sponsored-by: On-Waves ehf --- include/osmocom/gprs/gprs_ns.h | 3 + src/gb/gprs_ns.c | 226 +++++++++++++++++++++++++++------------- tests/gb/gprs_ns_test.c | 28 ++++- tests/gb/gprs_ns_test.ok | 10 +- 4 files changed, 190 insertions(+), 77 deletions(-) diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index 7b0ec92..b28c58d 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -119,6 +119,7 @@ struct gprs_nsvc { unsigned int remote_end_is_sgsn:1; unsigned int persistent:1; + unsigned int nsvci_is_valid:1; struct rate_ctr_group *ctrg; @@ -197,10 +198,12 @@ enum signal_ns { S_NS_BLOCK, S_NS_UNBLOCK, S_NS_ALIVE_EXP, /* Tns-alive expired more than N times */ + S_NS_REPLACED, /* nsvc object is replaced (sets old_nsvc) */ }; struct ns_signal_data { struct gprs_nsvc *nsvc; + struct gprs_nsvc *old_nsvc; uint8_t cause; }; diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 61a96d7..b403ca9 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -83,6 +83,9 @@ #include "common_vty.h" +void gprs_ns_ll_copy(struct gprs_nsvc *nsvc, struct gprs_nsvc *other); +void gprs_ns_ll_clear(struct gprs_nsvc *nsvc); + static const struct tlv_definition ns_att_tlvdef = { .def = { [NS_IE_CAUSE] = { TLV_TYPE_TvLV, 0 }, @@ -100,15 +103,19 @@ enum ns_ctr { NS_CTR_BYTES_OUT, NS_CTR_BLOCKED, NS_CTR_DEAD, + NS_CTR_REPLACED, + NS_CTR_NSEI_CHG, }; static const struct rate_ctr_desc nsvc_ctr_description[] = { - { "packets.in", "Packets at NS Level ( In)" }, - { "packets.out","Packets at NS Level (Out)" }, - { "bytes.in", "Bytes at NS Level ( In)" }, - { "bytes.out", "Bytes at NS Level (Out)" }, - { "blocked", "NS-VC Block count " }, - { "dead", "NS-VC gone dead count " }, + { "packets.in", "Packets at NS Level ( In)" }, + { "packets.out","Packets at NS Level (Out)" }, + { "bytes.in", "Bytes at NS Level ( In)" }, + { "bytes.out", "Bytes at NS Level (Out)" }, + { "blocked", "NS-VC Block count " }, + { "dead", "NS-VC gone dead count " }, + { "replaced", "NS-VC replaced other count" }, + { "nsei-chg", "NS-VC changed NSEI " }, }; static const struct rate_ctr_group_desc nsvc_ctrg_desc = { @@ -212,7 +219,7 @@ void gprs_nsvc_delete(struct gprs_nsvc *nsvc) static void ns_osmo_signal_dispatch(struct gprs_nsvc *nsvc, unsigned int signal, uint8_t cause) { - struct ns_signal_data nssd; + struct ns_signal_data nssd = {0}; nssd.nsvc = nsvc; nssd.cause = cause; @@ -220,6 +227,16 @@ static void ns_osmo_signal_dispatch(struct gprs_nsvc *nsvc, unsigned int signal, osmo_signal_dispatch(SS_L_NS, signal, &nssd); } +static void ns_osmo_signal_dispatch_replaced(struct gprs_nsvc *nsvc, struct gprs_nsvc *old_nsvc) +{ + struct ns_signal_data nssd = {0}; + + nssd.nsvc = nsvc; + nssd.old_nsvc = old_nsvc; + + osmo_signal_dispatch(SS_L_NS, S_NS_REPLACED, &nssd); +} + /* Section 10.3.2, Table 13 */ static const struct value_string ns_cause_str[] = { { NS_CAUSE_TRANSIT_FAIL, "Transit network failure" }, @@ -658,19 +675,20 @@ static int gprs_ns_rx_status(struct gprs_nsvc *nsvc, struct msgb *msg) } /* Section 7.3 */ -static int gprs_ns_rx_reset(struct gprs_nsvc *nsvc, struct msgb *msg) +static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) { struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; struct tlv_parsed tp; - uint8_t *cause; - uint16_t *nsvci, *nsei; + uint8_t cause; + uint16_t nsvci, nsei; + struct gprs_nsvc *other_nsvc = NULL; int rc; rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, msgb_l2len(msg) - sizeof(*nsh), 0, 0); if (rc < 0) { LOGP(DNS, LOGL_ERROR, "NSEI=%u Rx NS RESET " - "Error during TLV Parse\n", nsvc->nsei); + "Error during TLV Parse\n", (*nsvc)->nsei); return rc; } @@ -678,32 +696,84 @@ static int gprs_ns_rx_reset(struct gprs_nsvc *nsvc, struct msgb *msg) !TLVP_PRESENT(&tp, NS_IE_VCI) || !TLVP_PRESENT(&tp, NS_IE_NSEI)) { LOGP(DNS, LOGL_ERROR, "NS RESET Missing mandatory IE\n"); - gprs_ns_tx_status(nsvc, NS_CAUSE_MISSING_ESSENT_IE, 0, msg); + gprs_ns_tx_status((*nsvc), NS_CAUSE_MISSING_ESSENT_IE, 0, msg); return -EINVAL; } - cause = (uint8_t *) TLVP_VAL(&tp, NS_IE_CAUSE); - nsvci = (uint16_t *) TLVP_VAL(&tp, NS_IE_VCI); - nsei = (uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI); + cause = *(uint8_t *) TLVP_VAL(&tp, NS_IE_CAUSE); + nsvci = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_VCI)); + nsei = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI)); + + LOGP(DNS, LOGL_INFO, "NSVCI=%u%s Rx NS RESET (NSEI=%u, NSVCI=%u, cause=%s)\n", + (*nsvc)->nsvci, (*nsvc)->nsvci_is_valid ? "" : "(invalid)", + nsei, nsvci, gprs_ns_cause_str(cause)); + + if ((*nsvc)->nsvci_is_valid && (*nsvc)->nsvci != nsvci) { + /* NS-VCI has changed */ + other_nsvc = gprs_nsvc_by_nsvci((*nsvc)->nsi, nsvci); + + if (other_nsvc) { + /* The NS-VCI is already used by this NS-VC */ + + struct gprs_nsvc *tmp_nsvc; + char *old_peer; + + /* Exchange the NS-VC objects */ + tmp_nsvc = *nsvc; + *nsvc = other_nsvc; + other_nsvc = tmp_nsvc; - LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS RESET (NSVCI=%u, cause=%s)\n", - nsvc->nsvci, nsvc->nsei, gprs_ns_cause_str(*cause)); + /* Do logging */ + old_peer = talloc_strdup(other_nsvc, + gprs_ns_ll_str(other_nsvc)); + LOGP(DNS, LOGL_INFO, + "NS-VC changed link (NSVCI=%u) from %s to %s\n", + nsvci, old_peer, gprs_ns_ll_str(*nsvc)); + + talloc_free(old_peer); + + /* Do statistics */ + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_REPLACED]); + } + } /* Mark NS-VC as blocked and alive */ - nsvc->state = NSE_S_BLOCKED | NSE_S_ALIVE; + (*nsvc)->state = NSE_S_BLOCKED | NSE_S_ALIVE; + + if (other_nsvc) { + /* Check NSEI */ + if ((*nsvc)->nsei != nsei) { + LOGP(DNS, LOGL_NOTICE, + "NS-VC changed NSEI (NSVCI=%u) from %u to %u\n", + nsvci, (*nsvc)->nsei, nsei); + + /* Override old NSEI */ + (*nsvc)->nsei = nsei; + + /* Do statistics */ + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_NSEI_CHG]); + } - nsvc->nsei = ntohs(*nsei); - nsvc->nsvci = ntohs(*nsvci); + ns_osmo_signal_dispatch_replaced(*nsvc, other_nsvc); + + /* Update the ll info fields */ + gprs_ns_ll_copy(*nsvc, other_nsvc); + gprs_ns_ll_clear(other_nsvc); + } else { + (*nsvc)->nsei = nsei; + (*nsvc)->nsvci = nsvci; + (*nsvc)->nsvci_is_valid = 1; + } /* inform interested parties about the fact that this NSVC * has received RESET */ - ns_osmo_signal_dispatch(nsvc, S_NS_RESET, *cause); + ns_osmo_signal_dispatch(*nsvc, S_NS_RESET, cause); - rc = gprs_ns_tx_reset_ack(nsvc); + rc = gprs_ns_tx_reset_ack(*nsvc); /* start the test procedure */ - gprs_ns_tx_simple(nsvc, NS_PDUT_ALIVE); - nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST); + gprs_ns_tx_simple((*nsvc), NS_PDUT_ALIVE); + nsvc_start_timer((*nsvc), NSVC_TIMER_TNS_TEST); return rc; } @@ -748,7 +818,7 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, struct gprs_nsvc **new_nsvc); int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg, - struct gprs_nsvc *nsvc); + struct gprs_nsvc **nsvc); /*! \brief Receive incoming NS message from underlying transport layer * \param nsi NS instance to which the data belongs @@ -779,25 +849,14 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, rc = gprs_ns_vc_create(nsi, msg, fallback_nsvc, &nsvc); - switch (rc) { - case GPRS_NS_CS_CREATED: - case GPRS_NS_CS_FOUND: - nsvc->ll = ll; - break; - case GPRS_NS_CS_SKIPPED: - case GPRS_NS_CS_REJECTED: - break; - default: + if (rc < 0) return rc; - } rc = 0; } - if (nsvc) { - nsvc->ip.bts_addr = *saddr; - rc = gprs_ns_process_msg(nsi, msg, nsvc); - } + if (nsvc) + rc = gprs_ns_process_msg(nsi, msg, &nsvc); return rc; } @@ -848,6 +907,7 @@ void gprs_ns_ll_clear(struct gprs_nsvc *nsvc) * \param nsi NS instance to which the data belongs * \param[in] msg message buffer containing newly-received data * \param[in] fallback_nsvc is used to send error messages back to the peer + * and to initialise the ll info of a created NS-VC object * \param[out] new_nsvc contains a pointer to a NS-VC object if one has * been created or found * \returns < 0 in case of error, GPRS_NS_CS_SKIPPED if a message has been @@ -867,6 +927,7 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, struct tlv_parsed tp; uint16_t nsvci; + uint16_t nsei; int rc; @@ -912,43 +973,60 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, return -EINVAL; } nsvci = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_VCI)); + nsei = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI)); /* Check if we already know this NSVCI, the remote end might * simply have changed addresses, or it is a SGSN */ existing_nsvc = gprs_nsvc_by_nsvci(nsi, nsvci); if (!existing_nsvc) { *new_nsvc = gprs_nsvc_create(nsi, 0xffff); log_set_context(GPRS_CTX_NSVC, *new_nsvc); + gprs_ns_ll_copy(*new_nsvc, fallback_nsvc); LOGP(DNS, LOGL_INFO, "Creating NS-VC for BSS at %s\n", gprs_ns_ll_str(fallback_nsvc)); return GPRS_NS_CS_CREATED; } + /* Check NSEI */ + if (existing_nsvc->nsei != nsei) { + LOGP(DNS, LOGL_NOTICE, + "NS-VC changed NSEI (NSVCI=%u) from %u to %u\n", + nsvci, existing_nsvc->nsei, nsei); + + /* Override old NSEI */ + existing_nsvc->nsei = nsei; + + /* Do statistics */ + rate_ctr_inc(&existing_nsvc->ctrg->ctr[NS_CTR_NSEI_CHG]); + } + *new_nsvc = existing_nsvc; + gprs_ns_ll_copy(*new_nsvc, fallback_nsvc); return GPRS_NS_CS_FOUND; } /*! \brief Process NS message independently from underlying transport layer * \param nsi NS instance to which the data belongs * \param[in] msg message buffer containing newly-received data - * \param[in] nsvc refers to the virtual connection + * \param[inout] nsvc refers to the virtual connection, may be modified when + * processing a NS_RESET * \returns 0 in case of success, < 0 in case of error * * This contains the main NS automaton. */ int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg, - struct gprs_nsvc *nsvc) + struct gprs_nsvc **nsvc) { struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; int rc = 0; - msgb_nsei(msg) = nsvc->nsei; + msgb_nsei(msg) = (*nsvc)->nsei; - log_set_context(GPRS_CTX_NSVC, nsvc); + log_set_context(GPRS_CTX_NSVC, (*nsvc)); /* Increment number of Incoming bytes */ - rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_PKTS_IN]); - rate_ctr_add(&nsvc->ctrg->ctr[NS_CTR_BYTES_IN], msgb_l2len(msg)); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_PKTS_IN]); + rate_ctr_add(&(*nsvc)->ctrg->ctr[NS_CTR_BYTES_IN], msgb_l2len(msg)); switch (nsh->pdu_type) { case NS_PDUT_ALIVE: @@ -956,69 +1034,69 @@ int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg, * NS-ALIVE out of the blue, we might have been re-started * and should send a NS-RESET to make sure everything recovers * fine. */ - if (nsvc->state == NSE_S_BLOCKED) - rc = gprs_ns_tx_reset(nsvc, NS_CAUSE_PDU_INCOMP_PSTATE); + if ((*nsvc)->state == NSE_S_BLOCKED) + rc = gprs_ns_tx_reset((*nsvc), NS_CAUSE_PDU_INCOMP_PSTATE); else - rc = gprs_ns_tx_alive_ack(nsvc); + rc = gprs_ns_tx_alive_ack(*nsvc); break; case NS_PDUT_ALIVE_ACK: /* stop Tns-alive and start Tns-test */ - nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST); - if (nsvc->remote_end_is_sgsn) { + nsvc_start_timer((*nsvc), NSVC_TIMER_TNS_TEST); + if ((*nsvc)->remote_end_is_sgsn) { /* FIXME: this should be one level higher */ - if (nsvc->state & NSE_S_BLOCKED) - rc = gprs_ns_tx_unblock(nsvc); + if ((*nsvc)->state & NSE_S_BLOCKED) + rc = gprs_ns_tx_unblock(*nsvc); } break; case NS_PDUT_UNITDATA: /* actual user data */ - rc = gprs_ns_rx_unitdata(nsvc, msg); + rc = gprs_ns_rx_unitdata((*nsvc), msg); break; case NS_PDUT_STATUS: - rc = gprs_ns_rx_status(nsvc, msg); + rc = gprs_ns_rx_status((*nsvc), msg); break; case NS_PDUT_RESET: rc = gprs_ns_rx_reset(nsvc, msg); break; case NS_PDUT_RESET_ACK: - LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS RESET ACK\n", nsvc->nsei); + LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS RESET ACK\n", (*nsvc)->nsei); /* mark NS-VC as blocked + active */ - nsvc->state = NSE_S_BLOCKED | NSE_S_ALIVE; - nsvc->remote_state = NSE_S_BLOCKED | NSE_S_ALIVE; - rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_BLOCKED]); - if (nsvc->persistent || nsvc->remote_end_is_sgsn) { + (*nsvc)->state = NSE_S_BLOCKED | NSE_S_ALIVE; + (*nsvc)->remote_state = NSE_S_BLOCKED | NSE_S_ALIVE; + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_BLOCKED]); + if ((*nsvc)->persistent || (*nsvc)->remote_end_is_sgsn) { /* stop RESET timer */ - osmo_timer_del(&nsvc->timer); + osmo_timer_del(&(*nsvc)->timer); } /* Initiate TEST proc.: Send ALIVE and start timer */ - rc = gprs_ns_tx_simple(nsvc, NS_PDUT_ALIVE); - nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST); + rc = gprs_ns_tx_simple((*nsvc), NS_PDUT_ALIVE); + nsvc_start_timer((*nsvc), NSVC_TIMER_TNS_TEST); break; case NS_PDUT_UNBLOCK: /* Section 7.2: unblocking procedure */ - LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS UNBLOCK\n", nsvc->nsei); - nsvc->state &= ~NSE_S_BLOCKED; - ns_osmo_signal_dispatch(nsvc, S_NS_UNBLOCK, 0); - rc = gprs_ns_tx_simple(nsvc, NS_PDUT_UNBLOCK_ACK); + LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS UNBLOCK\n", (*nsvc)->nsei); + (*nsvc)->state &= ~NSE_S_BLOCKED; + ns_osmo_signal_dispatch((*nsvc), S_NS_UNBLOCK, 0); + rc = gprs_ns_tx_simple((*nsvc), NS_PDUT_UNBLOCK_ACK); break; case NS_PDUT_UNBLOCK_ACK: - LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS UNBLOCK ACK\n", nsvc->nsei); + LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS UNBLOCK ACK\n", (*nsvc)->nsei); /* mark NS-VC as unblocked + active */ - nsvc->state = NSE_S_ALIVE; - nsvc->remote_state = NSE_S_ALIVE; - ns_osmo_signal_dispatch(nsvc, S_NS_UNBLOCK, 0); + (*nsvc)->state = NSE_S_ALIVE; + (*nsvc)->remote_state = NSE_S_ALIVE; + ns_osmo_signal_dispatch((*nsvc), S_NS_UNBLOCK, 0); break; case NS_PDUT_BLOCK: - rc = gprs_ns_rx_block(nsvc, msg); + rc = gprs_ns_rx_block((*nsvc), msg); break; case NS_PDUT_BLOCK_ACK: - LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS BLOCK ACK\n", nsvc->nsei); + LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS BLOCK ACK\n", (*nsvc)->nsei); /* mark remote NS-VC as blocked + active */ - nsvc->remote_state = NSE_S_BLOCKED | NSE_S_ALIVE; + (*nsvc)->remote_state = NSE_S_BLOCKED | NSE_S_ALIVE; break; default: LOGP(DNS, LOGL_NOTICE, "NSEI=%u Rx Unknown NS PDU type 0x%02x\n", - nsvc->nsei, nsh->pdu_type); + (*nsvc)->nsei, nsh->pdu_type); rc = -EINVAL; break; } diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index 1474fd4..d7b769d 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -113,7 +114,7 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, if (!real_sendto) real_sendto = dlsym(RTLD_NEXT, "sendto"); - if (sockfd != 0xdead && ((struct sockaddr_in *)dest_addr)->sin_addr.s_addr != htonl(0x01020304)) + if (((struct sockaddr_in *)dest_addr)->sin_addr.s_addr != htonl(0x01020304)) return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen); printf("RESPONSE, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); @@ -121,6 +122,21 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, return len; } +static void dump_rate_ctr_group(FILE *stream, const char *prefix, + struct rate_ctr_group *ctrg) +{ + unsigned int i; + + for (i = 0; i < ctrg->desc->num_ctr; i++) { + struct rate_ctr *ctr = &ctrg->ctr[i]; + if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.')) + fprintf(stream, " %s%s: %llu%s", + prefix, ctrg->desc->ctr_desc[i].description, + (long long)ctr->current, + "\n"); + }; +} + /* Signal handler for signals from NS layer */ static int test_signal(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) @@ -155,6 +171,15 @@ static int test_signal(unsigned int subsys, unsigned int signal, gprs_ns_ll_str(nssd->nsvc)); break; + case S_NS_REPLACED: + printf("==> got signal NS_REPLACED: 0x%04x/%s", + nssd->nsvc->nsvci, + gprs_ns_ll_str(nssd->nsvc)); + printf(" -> 0x%04x/%s\n", + nssd->old_nsvc->nsvci, + gprs_ns_ll_str(nssd->old_nsvc)); + break; + default: printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal, nssd->nsvc->nsvci, @@ -203,6 +228,7 @@ static void gprs_dump_nsi(struct gprs_ns_inst *nsi) nsvc->nsvci, nsvc->nsei, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port) ); + dump_rate_ctr_group(stdout, " ", nsvc->ctrg); } printf("\n"); } diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 01b1bc9..7be84ef 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -91,12 +91,14 @@ result (RESET) = 9 Current NS-VCIs: VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333 VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 + NS-VC changed NSEI : 1 --- Peer port 3333, RESET, VCI is changed back --- PROCESSING RESET from 0x01020304:3333 02 00 81 01 01 82 11 22 04 82 11 22 +==> got signal NS_REPLACED: 0x1122/1.2.3.4:4444 -> 0x3344/1.2.3.4:3333 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:3333 RESPONSE, msg length 9 03 01 82 11 22 04 82 11 22 @@ -107,8 +109,10 @@ RESPONSE, msg length 1 result (RESET) = 9 Current NS-VCIs: + VCI 0x3344, NSEI 0x1122, peer 0x00000000:0 VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 - VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444 + NS-VC replaced other count: 1 + NS-VC changed NSEI : 2 --- Peer port 4444, RESET, NSEI is changed back --- @@ -125,8 +129,10 @@ RESPONSE, msg length 1 result (RESET) = 9 Current NS-VCIs: - VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333 + VCI 0x3344, NSEI 0x1122, peer 0x00000000:0 VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444 + NS-VC replaced other count: 1 + NS-VC changed NSEI : 2 ===== NS protocol test END -- 1.7.9.5 From robert.light at gmx.de Thu Oct 17 19:05:58 2013 From: robert.light at gmx.de (Robert Light) Date: Thu, 17 Oct 2013 21:05:58 +0200 (CEST) Subject: OpenBSC LCR compile problems Message-ID: An HTML attachment was scrubbed... URL: From kluchnikovi at gmail.com Fri Oct 18 08:37:42 2013 From: kluchnikovi at gmail.com (Ivan Kluchnikov) Date: Fri, 18 Oct 2013 12:37:42 +0400 Subject: [PATCH 1/2] Added new auth policy blacklist. Message-ID: <1382085463-32326-1-git-send-email-kluchnikovi@gmail.com> In this mode by default we set authorized = 1 for all new subscribers. BSC accepts all MS, except subscribers not authorized in DB. All subscribers with authorized = 0 are part of the blacklist and not accepted. --- openbsc/include/openbsc/gsm_data.h | 1 + openbsc/src/libbsc/bsc_vty.c | 5 +++-- openbsc/src/libcommon/gsm_data.c | 1 + openbsc/src/libmsc/gsm_04_08.c | 2 ++ openbsc/src/libmsc/gsm_subscriber.c | 8 +++++++- 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 8741505..71a878d 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -194,6 +194,7 @@ enum gsm_auth_policy { GSM_AUTH_POLICY_CLOSED, /* only subscribers authorized in DB */ GSM_AUTH_POLICY_ACCEPT_ALL, /* accept everyone, even if not authorized in DB */ GSM_AUTH_POLICY_TOKEN, /* accept first, send token per sms, then revoke authorization */ + GSM_AUTH_POLICY_BLACKLIST /* accept everyone, except subscribers not authorized in DB */ }; #define GSM_T3101_DEFAULT 10 diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 5d03b2a..e3cb917 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -1214,12 +1214,13 @@ DEFUN(cfg_net_name_long, DEFUN(cfg_net_auth_policy, cfg_net_auth_policy_cmd, - "auth policy (closed|accept-all|token)", + "auth policy (closed|accept-all|token|blacklist)", "Authentication (not cryptographic)\n" "Set the GSM network authentication policy\n" "Require the MS to be activated in HLR\n" "Accept all MS, whether in HLR or not\n" - "Use SMS-token based authentication\n") + "Use SMS-token based authentication\n" + "Accept all MS, except not authorized in HLR\n") { enum gsm_auth_policy policy = gsm_auth_policy_parse(argv[0]); struct gsm_network *gsmnet = gsmnet_from_vty(vty); diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index 5f7e32e..4c2d8e7 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -256,6 +256,7 @@ static const struct value_string auth_policy_names[] = { { GSM_AUTH_POLICY_CLOSED, "closed" }, { GSM_AUTH_POLICY_ACCEPT_ALL, "accept-all" }, { GSM_AUTH_POLICY_TOKEN, "token" }, + { GSM_AUTH_POLICY_BLACKLIST, "blacklist"}, { 0, NULL } }; diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index c41443e..addacda 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -241,6 +241,8 @@ static int authorize_subscriber(struct gsm_loc_updating_operation *loc, return (subscriber->flags & GSM_SUBSCRIBER_FIRST_CONTACT); case GSM_AUTH_POLICY_ACCEPT_ALL: return 1; + case GSM_AUTH_POLICY_BLACKLIST: + return subscriber->authorized; default: return 0; } diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c index bc6f3cf..d417b9f 100644 --- a/openbsc/src/libmsc/gsm_subscriber.c +++ b/openbsc/src/libmsc/gsm_subscriber.c @@ -279,8 +279,14 @@ struct gsm_subscriber *subscr_create_subscriber(struct gsm_network *net, const char *imsi) { struct gsm_subscriber *subscr = db_create_subscriber(imsi); - if (subscr) + if (subscr) { subscr->net = net; + if (subscr->net->auth_policy == GSM_AUTH_POLICY_BLACKLIST) { + subscr->authorized = 1; + db_sync_subscriber(subscr); + } + } + return subscr; } -- 1.7.9.5 From kluchnikovi at gmail.com Fri Oct 18 08:37:43 2013 From: kluchnikovi at gmail.com (Ivan Kluchnikov) Date: Fri, 18 Oct 2013 12:37:43 +0400 Subject: [PATCH 2/2] Added test for "auth policy" VTY command. In-Reply-To: <1382085463-32326-1-git-send-email-kluchnikovi@gmail.com> References: <1382085463-32326-1-git-send-email-kluchnikovi@gmail.com> Message-ID: <1382085463-32326-2-git-send-email-kluchnikovi@gmail.com> --- openbsc/tests/vty_test_runner.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 0bd7972..baa89ba 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -231,6 +231,42 @@ class TestVTYNITB(TestVTYGenericBSC): res = self.vty.command('show subscriber imsi '+imsi) self.assert_(res.find(" IMSI: "+imsi) > 0) + def testAuthPolicy (self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("network") + + # Test invalid input + self.vty.verify("auth policy", ['% Command incomplete.']) + + # Enable auth policy closed + self.vty.verify("auth policy closed", ['']) + + # Verify settings + res = self.vty.command("write terminal") + self.assert_(res.find("auth policy closed") > 0) + + # Enable auth policy accept-all + self.vty.verify("auth policy accept-all", ['']) + + # Verify settings + res = self.vty.command("write terminal") + self.assert_(res.find("auth policy accept-all") > 0) + + # Enable auth policy token + self.vty.verify("auth policy token", ['']) + + # Verify settings + res = self.vty.command("write terminal") + self.assert_(res.find("auth policy token") > 0) + + # Enable auth policy blacklist + self.vty.verify("auth policy blacklist", ['']) + + # Verify settings + res = self.vty.command("write terminal") + self.assert_(res.find("auth policy blacklist") > 0) + class TestVTYBSC(TestVTYGenericBSC): def vty_command(self): -- 1.7.9.5 From holger at freyther.de Fri Oct 18 13:14:06 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Fri, 18 Oct 2013 15:14:06 +0200 Subject: [PATCH 1/2] Added new auth policy blacklist. In-Reply-To: <1382085463-32326-1-git-send-email-kluchnikovi@gmail.com> References: <1382085463-32326-1-git-send-email-kluchnikovi@gmail.com> Message-ID: <20131018131406.GK6133@xiaoyu.lan> On Fri, Oct 18, 2013 at 12:37:42PM +0400, Ivan Kluchnikov wrote: Dear Ivan, case GSM_AUTH_POLICY_CLOSED: return subscriber->authorized == GSM_SUBSCRIBER_AUTH_AUTHORIZED; ... > return (subscriber->flags & GSM_SUBSCRIBER_FIRST_CONTACT); > case GSM_AUTH_POLICY_ACCEPT_ALL: > return 1; > + case GSM_AUTH_POLICY_BLACKLIST: > + return subscriber->authorized; return subscriber->authorized != GSM_SUBSCRIBER_AUTH_BLACKLIST; then you can omit this code. > + if (subscr) { > subscr->net = net; > + if (subscr->net->auth_policy == GSM_AUTH_POLICY_BLACKLIST) { > + subscr->authorized = 1; The benefit is that moving from closed to black-list works without changing the database content. If you move from black-list to closed.. all your blacklisted subscribers are suddenly allowed. holger From holger at freyther.de Fri Oct 18 20:36:46 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Fri, 18 Oct 2013 22:36:46 +0200 Subject: [PATCH 1/2] Added new auth policy blacklist. In-Reply-To: <20131018131406.GK6133@xiaoyu.lan> References: <1382085463-32326-1-git-send-email-kluchnikovi@gmail.com> <20131018131406.GK6133@xiaoyu.lan> Message-ID: <20131018203646.GH27176@xiaoyu.lan> On Fri, Oct 18, 2013 at 03:14:06PM +0200, Holger Hans Peter Freyther wrote: > The benefit is that moving from closed to black-list works without changing > the database content. If you move from black-list to closed.. all your blacklisted > subscribers are suddenly allowed. or after thinking more about it.. what is the point of ACCEPT_ALL. We can just have the blacklist mode replace it? > From alexander.chemeris at gmail.com Fri Oct 18 20:46:50 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sat, 19 Oct 2013 00:46:50 +0400 Subject: [PATCH 1/2] Added new auth policy blacklist. In-Reply-To: <20131018203646.GH27176@xiaoyu.lan> References: <1382085463-32326-1-git-send-email-kluchnikovi@gmail.com> <20131018131406.GK6133@xiaoyu.lan> <20131018203646.GH27176@xiaoyu.lan> Message-ID: On Sat, Oct 19, 2013 at 12:36 AM, Holger Hans Peter Freyther wrote: > On Fri, Oct 18, 2013 at 03:14:06PM +0200, Holger Hans Peter Freyther wrote: > >> The benefit is that moving from closed to black-list works without changing >> the database content. If you move from black-list to closed.. all your blacklisted >> subscribers are suddenly allowed. > > or after thinking more about it.. what is the point of ACCEPT_ALL. We can > just have the blacklist mode replace it? Well, ACCEPT_ALL is accept all - a different thing :) I would rather rename BLACKLIST to ACCEPT_NEW and make it default instead of ACCEPT_ALL. It will give better experience to a random OsmoNITB user (user in terms of an NITB operator, not in terms of a subscriber). -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From holger at freyther.de Thu Oct 24 06:38:59 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 24 Oct 2013 08:38:59 +0200 Subject: [PATCH 1/2] Added new auth policy blacklist. In-Reply-To: References: <1382085463-32326-1-git-send-email-kluchnikovi@gmail.com> <20131018131406.GK6133@xiaoyu.lan> <20131018203646.GH27176@xiaoyu.lan> Message-ID: <20131024063859.GD30417@xiaoyu.lan> On Sat, Oct 19, 2013 at 12:46:50AM +0400, Alexander Chemeris wrote: > Well, ACCEPT_ALL is accept all - a different thing :) yes it is. But what does ACCEPT_NEW (blacklist) take away from ACCEPT_ALL? My argument is that ACCEPT_NEW is the better "ACCEPT" > > I would rather rename BLACKLIST to ACCEPT_NEW and make it default > instead of ACCEPT_ALL. It will give better experience to a random > OsmoNITB user (user in terms of an NITB operator, not in terms of a > subscriber). Well, closed should be the default. We want to minizime the interference people can cause by default. From jerlbeck at sysmocom.de Fri Oct 18 11:04:47 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Fri, 18 Oct 2013 13:04:47 +0200 Subject: [PATCH 1/3] gbproxy: Extended test program to simulate SGSN, too Message-ID: <1382094289-5561-1-git-send-email-jerlbeck@sysmocom.de> This adds a simulation of the SGSN side of the Gbproxy. The VC is set up correctly and several combinations of BSSGP messages are sent. Sponsored-by: On-Waves ehf --- openbsc/tests/gbproxy/gbproxy_test.c | 168 ++++++++++- openbsc/tests/gbproxy/gbproxy_test.ok | 502 ++++++++++++++++++++++++++++++--- 2 files changed, 627 insertions(+), 43 deletions(-) diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 0b4521f..93fdbe0 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -32,11 +32,13 @@ #define REMOTE_BSS_ADDR 0x01020304 #define REMOTE_SGSN_ADDR 0x05060708 -#define SGSN_NSEI 0xfffe +#define SGSN_NSEI 0x0100 struct gbproxy_config gbcfg; -static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len); +static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, + struct sockaddr_in *peer, const unsigned char* data, + size_t data_len); static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, enum ns_cause cause, uint16_t nsvci, uint16_t nsei) @@ -57,6 +59,24 @@ static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg)); } +static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, + uint16_t nsvci, uint16_t nsei) +{ + /* GPRS Network Service, PDU type: NS_RESET_ACK, + */ + unsigned char msg[9] = { + 0x03, 0x01, 0x82, 0x11, 0x22, + 0x04, 0x82, 0x11, 0x22 + }; + + msg[3] = nsvci / 256; + msg[4] = nsvci % 256; + msg[7] = nsei / 256; + msg[8] = nsei % 256; + + gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg)); +} + static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) { /* GPRS Network Service, PDU type: NS_ALIVE */ @@ -87,8 +107,18 @@ static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_ad gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg)); } -static void send_ns_unitdata(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, - uint16_t nsbvci, +static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr) +{ + /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */ + unsigned char msg[1] = { + 0x07 + }; + + gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg)); +} + +static void send_ns_unitdata(struct gprs_ns_inst *nsi, const char *text, + struct sockaddr_in *src_addr, uint16_t nsbvci, const unsigned char *bssgp_msg, size_t bssgp_msg_size) { /* GPRS Network Service, PDU type: NS_UNITDATA */ @@ -102,7 +132,7 @@ static void send_ns_unitdata(struct gprs_ns_inst *nsi, struct sockaddr_in *src_a msg[3] = nsbvci % 256; memcpy(msg + 4, bssgp_msg, bssgp_msg_size); - gprs_process_message(nsi, "UNITDATA", src_addr, msg, bssgp_msg_size + 4); + gprs_process_message(nsi, text ? text : "UNITDATA", src_addr, msg, bssgp_msg_size + 4); } static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, @@ -119,7 +149,23 @@ static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_a msg[3] = bvci / 256; msg[4] = bvci % 256; - send_ns_unitdata(nsi, src_addr, 0, msg, sizeof(msg)); + send_ns_unitdata(nsi, "BVC_RESET", src_addr, 0, msg, sizeof(msg)); +} + +static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi, + struct sockaddr_in *src_addr, uint16_t bvci) +{ + /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0 + * BSSGP RESET_ACK */ + static unsigned char msg[5] = { + 0x23, 0x04, 0x82, 0x00, + 0x00 + }; + + msg[3] = bvci / 256; + msg[4] = bvci % 256; + + send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg)); } static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, @@ -175,14 +221,19 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *, socklen_t); static sendto_t real_sendto = NULL; uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr); + int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port); if (!real_sendto) real_sendto = dlsym(RTLD_NEXT, "sendto"); if (dest_host == REMOTE_BSS_ADDR) - printf("MESSAGE to BSS, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + printf("MESSAGE to BSS at 0x%08x:%d, msg length %d\n%s\n\n", + dest_host, dest_port, + len, osmo_hexdump(buf, len)); else if (dest_host == REMOTE_SGSN_ADDR) - printf("MESSAGE to SGSN, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len)); + printf("MESSAGE to SGSN at 0x%08x:%d, msg length %d\n%s\n\n", + dest_host, dest_port, + len, osmo_hexdump(buf, len)); else return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen); @@ -192,12 +243,17 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, /* override */ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) { + typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg); + static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL; uint16_t bvci = msgb_bvci(msg); uint16_t nsei = msgb_nsei(msg); unsigned char *buf = msg->data; size_t len = msg->len; + if (!real_gprs_ns_sendmsg) + real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg"); + if (nsei == SGSN_NSEI) printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, msg length %d\n%s\n\n", bvci, len, osmo_hexdump(buf, len)); @@ -205,7 +261,7 @@ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg) printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, msg length %d\n%s\n\n", bvci, len, osmo_hexdump(buf, len)); - return 0; + return real_gprs_ns_sendmsg(nsi, msg); } static void dump_rate_ctr_group(FILE *stream, const char *prefix, @@ -312,9 +368,11 @@ static void gprs_dump_nsi(struct gprs_ns_inst *nsi) printf("Current NS-VCIs:\n"); llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { struct sockaddr_in *peer = &(nsvc->ip.bts_addr); - printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d\n", + printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n", nsvc->nsvci, nsvc->nsei, - ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port) + ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port), + nsvc->state & NSE_S_BLOCKED ? ", blocked" : "", + nsvc->state & NSE_S_ALIVE ? "" : ", dead" ); dump_rate_ctr_group(stdout, " ", nsvc->ctrg); } @@ -325,11 +383,16 @@ static void test_gbproxy() { struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); struct sockaddr_in bss_peer[4] = {{0},}; + struct sockaddr_in sgsn_peer= {0}; bssgp_nsi = nsi; gbcfg.nsi = bssgp_nsi; gbcfg.nsip_sgsn_nsei = SGSN_NSEI; + sgsn_peer.sin_family = AF_INET; + sgsn_peer.sin_port = htons(32000); + sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR); + bss_peer[0].sin_family = AF_INET; bss_peer[0].sin_port = htons(1111); bss_peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); @@ -343,6 +406,15 @@ static void test_gbproxy() bss_peer[3].sin_port = htons(4444); bss_peer[3].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + printf("--- Initialise SGSN ---\n\n"); + + gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1); + send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); + send_ns_alive_ack(nsi, &sgsn_peer); + send_ns_unblock_ack(nsi, &sgsn_peer); + send_ns_alive(nsi, &sgsn_peer); + gprs_dump_nsi(nsi); + printf("--- Initialise BSS 1 ---\n\n"); setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); @@ -350,6 +422,8 @@ static void test_gbproxy() gprs_dump_nsi(nsi); gbprox_dump_peers(stdout, 0); + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); + printf("--- Initialise BSS 2 ---\n\n"); setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000); @@ -357,6 +431,8 @@ static void test_gbproxy() gprs_dump_nsi(nsi); gbprox_dump_peers(stdout, 0); + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002); + printf("--- Move BSS 1 to new port ---\n\n"); setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000); @@ -387,6 +463,76 @@ static void test_gbproxy() gprs_dump_nsi(nsi); gbprox_dump_peers(stdout, 0); + printf("--- Move BSS 1 to original BSS 1 port ---\n\n"); + + setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + printf("--- Reset BSS 1 with a new BVCI ---\n\n"); + + setup_bssgp(nsi, &bss_peer[0], 0x1012); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012); + + printf("--- Reset BSS 1 with the old BVCI ---\n\n"); + + setup_bssgp(nsi, &bss_peer[0], 0x1002); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); + + printf("--- Reset BSS 1 with the old BVCI again ---\n\n"); + + setup_bssgp(nsi, &bss_peer[0], 0x1002); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); + + printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0); + + printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0); + + printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0); + + printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0); + + printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0); + + printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0); + + printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n"); + + setup_bssgp(nsi, &bss_peer[2], 0x1002); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); + + printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0); + + printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0); + gprs_ns_destroy(nsi); nsi = NULL; } diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index 0835921..b8920ac 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -1,4 +1,44 @@ ===== NS protocol test START +--- Initialise SGSN --- + +MESSAGE to SGSN at 0x05060708:32000, msg length 12 +02 00 81 01 01 82 01 01 04 82 01 00 + +PROCESSING RESET_ACK from 0x05060708:32000 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 1 +0a + +result (RESET_ACK) = 1 + +PROCESSING ALIVE_ACK from 0x05060708:32000 +0b + +MESSAGE to SGSN at 0x05060708:32000, msg length 1 +06 + +result (ALIVE_ACK) = 1 + +PROCESSING UNBLOCK_ACK from 0x05060708:32000 +07 + +==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000 + +result (UNBLOCK_ACK) = 0 + +PROCESSING ALIVE from 0x05060708:32000 +0a + +MESSAGE to SGSN at 0x05060708:32000, msg length 1 +0b + +result (ALIVE) = 1 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + --- Initialise BSS 1 --- Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096) @@ -8,10 +48,10 @@ PROCESSING RESET from 0x01020304:1111 ==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 -MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:1111, msg length 9 03 01 82 10 01 04 82 10 00 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0a result (RESET) = 9 @@ -19,7 +59,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:1111 0a -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0b result (ALIVE) = 1 @@ -29,7 +69,7 @@ PROCESSING UNBLOCK from 0x01020304:1111 ==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 07 result (UNBLOCK) = 1 @@ -41,7 +81,7 @@ result (ALIVE_ACK) = 0 Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098) -PROCESSING UNITDATA from 0x01020304:1111 +PROCESSING BVC_RESET from 0x01020304:1111 00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 CALLBACK, event 0, msg length 22, bvci 0x0000 @@ -50,13 +90,32 @@ CALLBACK, event 0, msg length 22, bvci 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 -result (UNITDATA) = 0 +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 Current NS-VCIs: VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 Peers: NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 + --- Initialise BSS 2 --- Setup NS-VC: remote 0x01020304:2222, NSVCI 0x2001(8193), NSEI 0x2000(8192) @@ -66,10 +125,10 @@ PROCESSING RESET from 0x01020304:2222 ==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:2222 -MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:2222, msg length 9 03 01 82 20 01 04 82 20 00 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:2222, msg length 1 0a result (RESET) = 9 @@ -77,7 +136,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:2222 0a -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:2222, msg length 1 0b result (ALIVE) = 1 @@ -87,7 +146,7 @@ PROCESSING UNBLOCK from 0x01020304:2222 ==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:2222 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:2222, msg length 1 07 result (UNBLOCK) = 1 @@ -99,7 +158,7 @@ result (ALIVE_ACK) = 0 Setup BSSGP: remote 0x01020304:2222, BVCI 0x2002(8194) -PROCESSING UNITDATA from 0x01020304:2222 +PROCESSING BVC_RESET from 0x01020304:2222 00 00 00 00 22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 CALLBACK, event 0, msg length 22, bvci 0x0000 @@ -108,15 +167,34 @@ CALLBACK, event 0, msg length 22, bvci 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 -result (UNITDATA) = 0 +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 20 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 20 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 20 02 + +MESSAGE to BSS at 0x01020304:2222, msg length 9 +00 00 00 00 23 04 82 20 02 + +result (BVC_RESET_ACK) = 9 + --- Move BSS 1 to new port --- Setup NS-VC: remote 0x01020304:3333, NSVCI 0x1001(4097), NSEI 0x1000(4096) @@ -126,10 +204,10 @@ PROCESSING RESET from 0x01020304:3333 ==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:3333 -MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:3333, msg length 9 03 01 82 10 01 04 82 10 00 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 0a result (RESET) = 9 @@ -137,7 +215,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:3333 0a -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 0b result (ALIVE) = 1 @@ -147,7 +225,7 @@ PROCESSING UNBLOCK from 0x01020304:3333 ==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:3333 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 07 result (UNBLOCK) = 1 @@ -160,6 +238,8 @@ result (ALIVE_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 @@ -173,10 +253,10 @@ PROCESSING RESET from 0x01020304:1111 ==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 -MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:1111, msg length 9 03 01 82 20 01 04 82 20 00 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0a result (RESET) = 9 @@ -184,7 +264,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:1111 0a -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0b result (ALIVE) = 1 @@ -194,7 +274,7 @@ PROCESSING UNBLOCK from 0x01020304:1111 ==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 07 result (UNBLOCK) = 1 @@ -207,6 +287,8 @@ result (ALIVE_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 @@ -220,10 +302,10 @@ PROCESSING RESET from 0x01020304:1111 ==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 -MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:1111, msg length 9 03 01 82 20 01 04 82 20 00 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0a result (RESET) = 9 @@ -231,7 +313,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:1111 0a -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0b result (ALIVE) = 1 @@ -241,7 +323,7 @@ PROCESSING UNBLOCK from 0x01020304:1111 ==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 07 result (UNBLOCK) = 1 @@ -254,6 +336,8 @@ result (ALIVE_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 @@ -267,10 +351,10 @@ PROCESSING RESET from 0x01020304:4444 ==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:4444 -MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:4444, msg length 9 03 01 82 20 01 04 82 20 00 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:4444, msg length 1 0a result (RESET) = 9 @@ -278,7 +362,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:4444 0a -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:4444, msg length 1 0b result (ALIVE) = 1 @@ -288,7 +372,7 @@ PROCESSING UNBLOCK from 0x01020304:4444 ==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:4444 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:4444, msg length 1 07 result (UNBLOCK) = 1 @@ -301,6 +385,8 @@ result (ALIVE_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:4444 VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 @@ -316,10 +402,10 @@ PROCESSING RESET from 0x01020304:3333 ==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:3333 -MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:3333, msg length 9 03 01 82 20 01 04 82 20 00 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 0a result (RESET) = 9 @@ -327,7 +413,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:3333 0a -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 0b result (ALIVE) = 1 @@ -337,7 +423,7 @@ PROCESSING UNBLOCK from 0x01020304:3333 ==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:3333 -MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 07 result (UNBLOCK) = 1 @@ -351,9 +437,361 @@ Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 NS-VC replaced other count: 1 VCI 0x1001, NSEI 0x1000, peer 0x00000000:0 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 1 to original BSS 1 port --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Reset BSS 1 with a new BVCI --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1012(4114) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 10 12 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 12 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 12 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 12 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 12 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 12 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 12 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 12 + +result (BVC_RESET_ACK) = 9 + +--- Reset BSS 1 with the old BVCI --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 + +--- Reset BSS 1 with the old BVCI again --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 + +--- Send message from BSS 1 to SGSN, BVCI 0x1012 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1012, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + +--- Send message from SGSN to BSS 1, BVCI 0x1012 --- + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x1012, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + +--- Send message from BSS 1 to SGSN, BVCI 0x1002 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1012, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + +--- Send message from SGSN to BSS 1, BVCI 0x1002 --- + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x1012, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + +--- Send message from BSS 2 to SGSN, BVCI 0x2002 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 20 02 + +CALLBACK, event 0, msg length 0, bvci 0x2002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x2002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 20 02 + +result (UNITDATA) = 4 + +--- Send message from SGSN to BSS 2, BVCI 0x2002 --- + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 20 02 + +CALLBACK, event 0, msg length 0, bvci 0x2002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x2002, msg length 0 + + +MESSAGE to BSS at 0x01020304:3333, msg length 4 +00 00 20 02 + +result (UNITDATA) = 4 + +--- Reset BSS 1 with the old BVCI on BSS2's link --- + +Setup BSSGP: remote 0x01020304:3333, BVCI 0x1002(4098) + +PROCESSING BVC_RESET from 0x01020304:3333 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 + +--- Send message from BSS 1 to SGSN, BVCI 0x1002 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1012, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + +--- Send message from SGSN to BSS 1, BVCI 0x1002 --- + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x1012, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + ===== NS protocol test END -- 1.7.9.5 From jerlbeck at sysmocom.de Fri Oct 18 11:04:48 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Fri, 18 Oct 2013 13:04:48 +0200 Subject: [PATCH 2/3] gbproxy: Fix warning and log message In-Reply-To: <1382094289-5561-1-git-send-email-jerlbeck@sysmocom.de> References: <1382094289-5561-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382094289-5561-2-git-send-email-jerlbeck@sysmocom.de> Add the unused attribute to peer_free() that isn't used currently. Change 'RAC' to 'NSEI' in the log message, since the latter has been examined before the log message is generated. Sponsored-by: On-Waves ehf --- openbsc/src/gprs/gb_proxy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 157ce10..bfa6e94 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -114,6 +114,7 @@ static struct gbprox_peer *peer_alloc(uint16_t bvci) return peer; } +static void peer_free(struct gbprox_peer *peer) __attribute__((__unused__)); static void peer_free(struct gbprox_peer *peer) { llist_del(&peer->list); @@ -349,7 +350,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, * SGSN */ return gbprox_relay2sgsn(msg, ns_bvci); err_no_peer: - LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on RAC\n", + LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on NSEI\n", nsei); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); err_mand_ie: -- 1.7.9.5 From jerlbeck at sysmocom.de Fri Oct 18 11:04:49 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Fri, 18 Oct 2013 13:04:49 +0200 Subject: [PATCH 3/3] gbproxy: Add global and per peer counters In-Reply-To: <1382094289-5561-1-git-send-email-jerlbeck@sysmocom.de> References: <1382094289-5561-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382094289-5561-3-git-send-email-jerlbeck@sysmocom.de> This adds counters that are incremented when errors are detected. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 2 +- openbsc/src/gprs/gb_proxy.c | 160 +++++++++++++++++++++++++++++++-- openbsc/tests/gbproxy/gbproxy_test.c | 24 ++--- openbsc/tests/gbproxy/gbproxy_test.ok | 2 + 4 files changed, 170 insertions(+), 18 deletions(-) diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 26c1f6a..82e47d5 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -35,5 +35,5 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, /* Reset all persistent NS-VC's */ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi); -int gbprox_dump_peers(FILE *stream, int indent); +int gbprox_dump_peers(FILE *stream, int indent, int verbose); #endif diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index bfa6e94..df42989 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -39,6 +40,75 @@ #include #include +enum gbprox_global_ctr { + GBPROX_GLOB_CTR_INV_BVCI, + GBPROX_GLOB_CTR_INV_LAC, + GBPROX_GLOB_CTR_INV_RAC, + GBPROX_GLOB_CTR_INV_NSEI, + GBPROX_GLOB_CTR_PROTO_ERR_BSS, + GBPROX_GLOB_CTR_PROTO_ERR_SGSN, + GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS, + GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN, + GBPROX_GLOB_CTR_RESTART_RESET_SGSN, + GBPROX_GLOB_CTR_TX_ERR_SGSN, + GBPROX_GLOB_CTR_OTHER_ERR, +}; + +static const struct rate_ctr_desc global_ctr_description[] = { + { "inv-bvci", "Invalid BVC Identifier " }, + { "inv-lac", "Invalid Location Area Code " }, + { "inv-rac", "Invalid Routing Area Code " }, + { "inv-nsei", "No BVC established for NSEI " }, + { "proto-err.bss", "BSSGP protocol error (BSS )" }, + { "proto-err.sgsn", "BSSGP protocol error (SGSN)" }, + { "not-supp.bss", "Feature not supported (BSS )" }, + { "not-supp.sgsn", "Feature not supported (SGSN)" }, + { "restart.sgsn", "Restarted RESET procedure (SGSN)" }, + { "tx-err.sgsn", "NS Transmission error (SGSN)" }, + { "error", "Other error " }, +}; + +static const struct rate_ctr_group_desc global_ctrg_desc = { + .group_name_prefix = "gbproxy.global", + .group_description = "GBProxy Global Statistics", + .num_ctr = ARRAY_SIZE(global_ctr_description), + .ctr_desc = global_ctr_description, +}; + +static struct rate_ctr_group *global_ctrg = NULL; + +static struct rate_ctr_group *get_global_ctrg() +{ + if (global_ctrg) + return global_ctrg; + + global_ctrg = rate_ctr_group_alloc(tall_bsc_ctx, &global_ctrg_desc, 0); + return global_ctrg; +} + +enum gbprox_peer_ctr { + GBPROX_PEER_CTR_BLOCKED, + GBPROX_PEER_CTR_UNBLOCKED, + GBPROX_PEER_CTR_DROPPED, + GBPROX_PEER_CTR_INV_NSEI, + GBPROX_PEER_CTR_TX_ERR, +}; + +static const struct rate_ctr_desc peer_ctr_description[] = { + { "blocked", "BVC Block " }, + { "unblocked", "BVC Unblock " }, + { "dropped", "BVC blocked, dropped packet " }, + { "inv-nsei", "NSEI mismatch " }, + { "tx-err", "NS Transmission error " }, +}; + +static const struct rate_ctr_group_desc peer_ctrg_desc = { + .group_name_prefix = "gbproxy.peer", + .group_description = "GBProxy Peer Statistics", + .num_ctr = ARRAY_SIZE(peer_ctr_description), + .ctr_desc = peer_ctr_description, +}; + struct gbprox_peer { struct llist_head list; @@ -51,6 +121,9 @@ struct gbprox_peer { /* Routeing Area that this peer is part of (raw 04.08 encoding) */ uint8_t ra[6]; + + /* Counter */ + struct rate_ctr_group *ctrg; }; /* Linked list of all Gb peers (except SGSN) */ @@ -100,6 +173,19 @@ static struct gbprox_peer *peer_by_lac(const uint8_t *la) return NULL; } +static int check_peer_nsei(struct gbprox_peer *peer, uint16_t nsei) +{ + if (peer->nsei != nsei) { + LOGP(DGPRS, LOGL_NOTICE, "Peer entry doesn't match current NSEI " + "BVCI=%u via NSEI=%u (expected NSEI=%u)\n", + peer->bvci, nsei, peer->nsei); + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_INV_NSEI]); + return 1; + } + + return 0; +} + static struct gbprox_peer *peer_alloc(uint16_t bvci) { struct gbprox_peer *peer; @@ -109,6 +195,8 @@ static struct gbprox_peer *peer_alloc(uint16_t bvci) return NULL; peer->bvci = bvci; + peer->ctrg = rate_ctr_group_alloc(peer, &peer_ctrg_desc, bvci); + llist_add(&peer->list, &gbprox_bts_peers); return peer; @@ -175,6 +263,7 @@ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci) /* create a copy of the message so the old one can * be free()d safely when we return from gbprox_rcvmsg() */ struct msgb *msg = msgb_copy(old_msg, "msgb_relay2sgsn"); + int rc; DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n", msgb_nsei(msg), ns_bvci, gbcfg.nsip_sgsn_nsei); @@ -184,7 +273,11 @@ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci) strip_ns_hdr(msg); - return gprs_ns_sendmsg(bssgp_nsi, msg); + rc = gprs_ns_sendmsg(bssgp_nsi, msg); + if (rc < 0) + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_TX_ERR_SGSN]); + + return rc; } /* feed a message down the NS-VC associated with the specified peer */ @@ -194,6 +287,7 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer, /* create a copy of the message so the old one can * be free()d safely when we return from gbprox_rcvmsg() */ struct msgb *msg = msgb_copy(old_msg, "msgb_relay2peer"); + int rc; DEBUGP(DGPRS, "NSEI=%u proxying SGSN->BSS (NS_BVCI=%u, NSEI=%u)\n", msgb_nsei(msg), ns_bvci, peer->nsei); @@ -204,7 +298,11 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer, /* Strip the old NS header, it will be replaced with a new one */ strip_ns_hdr(msg); - return gprs_ns_sendmsg(bssgp_nsi, msg); + rc = gprs_ns_sendmsg(bssgp_nsi, msg); + if (rc < 0) + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_TX_ERR]); + + return rc; } static int block_unblock_peer(uint16_t ptp_bvci, uint8_t pdu_type) @@ -215,15 +313,18 @@ static int block_unblock_peer(uint16_t ptp_bvci, uint8_t pdu_type) if (!peer) { LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n", ptp_bvci); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_BVCI]); return -ENOENT; } switch (pdu_type) { case BSSGP_PDUT_BVC_BLOCK_ACK: peer->blocked = 1; + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_BLOCKED]); break; case BSSGP_PDUT_BVC_UNBLOCK_ACK: peer->blocked = 0; + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_UNBLOCKED]); break; default: break; @@ -242,6 +343,7 @@ static int gbprox_relay2bvci(struct msgb *msg, uint16_t ptp_bvci, if (!peer) { LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n", ptp_bvci); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_BVCI]); return -ENOENT; } @@ -327,6 +429,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, from_peer = peer_alloc(bvci); from_peer->nsei = nsei; } + check_peer_nsei(from_peer, nsei); if (TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID)) { struct gprs_ra_id raid; /* We have a Cell Identifier present in this @@ -352,10 +455,12 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on NSEI\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_NSEI]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) missing mandatory RA IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_PROTO_ERR_BSS]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } @@ -364,6 +469,7 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, uint32_t nsei, uint16_t ns_bvci) { struct gbprox_peer *peer = NULL; + int errctr = GBPROX_GLOB_CTR_PROTO_ERR_SGSN; LOGP(DGPRS, LOGL_INFO, "NSEI=%u(SGSN) BSSGP PAGING ", nsei); @@ -371,20 +477,24 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, uint16_t bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI)); LOGPC(DGPRS, LOGL_INFO, "routing by BVCI to peer BVCI=%u\n", bvci); + errctr = GBPROX_GLOB_CTR_OTHER_ERR; } else if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) { peer = peer_by_rac(TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA)); LOGPC(DGPRS, LOGL_INFO, "routing by RAC to peer BVCI=%u\n", peer ? peer->bvci : -1); + errctr = GBPROX_GLOB_CTR_INV_RAC; } else if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) { peer = peer_by_lac(TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA)); LOGPC(DGPRS, LOGL_INFO, "routing by LAC to peer BVCI=%u\n", peer ? peer->bvci : -1); + errctr = GBPROX_GLOB_CTR_INV_LAC; } else LOGPC(DGPRS, LOGL_INFO, "\n"); if (!peer) { LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP PAGING: " "unable to route, missing IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[errctr]); return -EINVAL; } return gbprox_relay2peer(msg, peer, ns_bvci); @@ -398,6 +508,8 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, uint16_t ptp_bvci; if (!TLVP_PRESENT(tp, BSSGP_IE_BVCI)) { + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } @@ -410,6 +522,8 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, if (!peer) { LOGP(DGPRS, LOGL_ERROR, "NSEI=%u BVCI=%u: Cannot find BSS\n", nsei, ptp_bvci); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_INV_BVCI]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); } @@ -514,6 +628,8 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, "%sBLOCK_ACK for signalling BVCI ?!?\n", nsei, pdu_type == BSSGP_PDUT_BVC_UNBLOCK_ACK ? "UN":""); /* should we send STATUS ? */ + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_INV_BVCI]); } else { /* Mark BVC as (un)blocked */ block_unblock_peer(bvci, pdu_type); @@ -523,11 +639,15 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, case BSSGP_PDUT_SGSN_INVOKE_TRACE: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP INVOKE TRACE not supported\n",nsei); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN]); rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, msg); break; default: LOGP(DGPRS, LOGL_NOTICE, "BSSGP PDU type 0x%02x unknown\n", pdu_type); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); break; } @@ -536,10 +656,13 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) missing mandatory IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) cannot find peer based on RAC\n", nsei); + rate_ctr_inc(&get_global_ctrg()-> ctr[GBPROX_GLOB_CTR_INV_RAC]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); } @@ -557,12 +680,16 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns else rc = gbprox_rx_sig_from_bss(msg, nsei, ns_bvci); } else { + peer = peer_by_bvci(ns_bvci); + /* All other BVCI are PTP and thus can be simply forwarded */ - if (!remote_end_is_sgsn) + if (!remote_end_is_sgsn) { + if (peer) + check_peer_nsei(peer, nsei); return gbprox_relay2sgsn(msg, ns_bvci); + } /* else: SGSN -> BSS direction */ - peer = peer_by_bvci(ns_bvci); if (!peer) { LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for " "BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, @@ -574,6 +701,7 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns LOGP(DGPRS, LOGL_NOTICE, "Dropping PDU for " "blocked BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, nsvci, nsei); + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_DROPPED]); return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, NULL, msg); } rc = gbprox_relay2peer(msg, peer, ns_bvci); @@ -616,6 +744,8 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, if (signal == S_NS_ALIVE_EXP && nsvc->remote_end_is_sgsn) { LOGP(DGPRS, LOGL_NOTICE, "Tns alive expired too often, " "re-starting RESET procedure\n"); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_RESTART_RESET_SGSN]); gprs_ns_nsip_connect(nsvc->nsi, &nsvc->ip.bts_addr, nsvc->nsei, nsvc->nsvci); } @@ -668,10 +798,12 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, return 0; } -int gbprox_dump_peers(FILE *stream, int indent) +int gbprox_dump_peers(FILE *stream, int indent, int verbose) { struct gbprox_peer *peer; struct gprs_ra_id raid; + unsigned int i; + const struct rate_ctr_group_desc *desc; int rc; fprintf(stream, "%*sPeers:\n", indent, ""); @@ -687,6 +819,24 @@ int gbprox_dump_peers(FILE *stream, int indent) if (rc < 0) return rc; + + if (!verbose) + continue; + + desc = peer->ctrg->desc; + + for (i = 0; i < desc->num_ctr; i++) { + struct rate_ctr *ctr = &peer->ctrg->ctr[i]; + if (ctr->current) { + rc = fprintf(stream, "%*s %s: %llu\n", + indent, "", + desc->ctr_desc[i].description, + (long long)ctr->current); + + if (rc < 0) + return rc; + } + } } return 0; diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 93fdbe0..21ee723 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -420,7 +420,7 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); @@ -429,7 +429,7 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000); setup_bssgp(nsi, &bss_peer[1], 0x2002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002); @@ -437,43 +437,43 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Move BSS 2 to former BSS 1 port ---\n\n"); setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Move BSS 1 to current BSS 2 port ---\n\n"); setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Move BSS 2 to new port ---\n\n"); setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Move BSS 2 to former BSS 1 port ---\n\n"); setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Move BSS 1 to original BSS 1 port ---\n\n"); setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Reset BSS 1 with a new BVCI ---\n\n"); setup_bssgp(nsi, &bss_peer[0], 0x1012); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012); @@ -481,7 +481,7 @@ static void test_gbproxy() setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); @@ -489,7 +489,7 @@ static void test_gbproxy() setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); @@ -521,7 +521,7 @@ static void test_gbproxy() setup_bssgp(nsi, &bss_peer[2], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index b8920ac..e4b7aba 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -746,7 +746,9 @@ Current NS-VCIs: Peers: NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 PROCESSING BVC_RESET_ACK from 0x05060708:32000 00 00 00 00 23 04 82 10 02 -- 1.7.9.5 From jerlbeck at sysmocom.de Fri Oct 18 12:34:55 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Fri, 18 Oct 2013 14:34:55 +0200 Subject: [PATCH] gbproxy: Add global and per peer counters In-Reply-To: <1382094289-5561-3-git-send-email-jerlbeck@sysmocom.de> References: <1382094289-5561-3-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382099695-20101-1-git-send-email-jerlbeck@sysmocom.de> This adds counters that are incremented when errors are detected. It also modifies the VTY command 'show gbproxy' so that 'show gbproxy stats' shows the counters. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 2 +- openbsc/src/gprs/gb_proxy.c | 171 +++++++++++++++++++++++++++++++-- openbsc/tests/gbproxy/gbproxy_test.c | 24 ++--- openbsc/tests/gbproxy/gbproxy_test.ok | 2 + 4 files changed, 180 insertions(+), 19 deletions(-) diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 26c1f6a..82e47d5 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -35,5 +35,5 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, /* Reset all persistent NS-VC's */ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi); -int gbprox_dump_peers(FILE *stream, int indent); +int gbprox_dump_peers(FILE *stream, int indent, int verbose); #endif diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index bfa6e94..ddc9e0a 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -31,6 +31,9 @@ #include #include +#include + +#include #include #include @@ -39,6 +42,75 @@ #include #include +enum gbprox_global_ctr { + GBPROX_GLOB_CTR_INV_BVCI, + GBPROX_GLOB_CTR_INV_LAC, + GBPROX_GLOB_CTR_INV_RAC, + GBPROX_GLOB_CTR_INV_NSEI, + GBPROX_GLOB_CTR_PROTO_ERR_BSS, + GBPROX_GLOB_CTR_PROTO_ERR_SGSN, + GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS, + GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN, + GBPROX_GLOB_CTR_RESTART_RESET_SGSN, + GBPROX_GLOB_CTR_TX_ERR_SGSN, + GBPROX_GLOB_CTR_OTHER_ERR, +}; + +static const struct rate_ctr_desc global_ctr_description[] = { + { "inv-bvci", "Invalid BVC Identifier " }, + { "inv-lac", "Invalid Location Area Code " }, + { "inv-rac", "Invalid Routing Area Code " }, + { "inv-nsei", "No BVC established for NSEI " }, + { "proto-err.bss", "BSSGP protocol error (BSS )" }, + { "proto-err.sgsn", "BSSGP protocol error (SGSN)" }, + { "not-supp.bss", "Feature not supported (BSS )" }, + { "not-supp.sgsn", "Feature not supported (SGSN)" }, + { "restart.sgsn", "Restarted RESET procedure (SGSN)" }, + { "tx-err.sgsn", "NS Transmission error (SGSN)" }, + { "error", "Other error " }, +}; + +static const struct rate_ctr_group_desc global_ctrg_desc = { + .group_name_prefix = "gbproxy.global", + .group_description = "GBProxy Global Statistics", + .num_ctr = ARRAY_SIZE(global_ctr_description), + .ctr_desc = global_ctr_description, +}; + +static struct rate_ctr_group *global_ctrg = NULL; + +static struct rate_ctr_group *get_global_ctrg() +{ + if (global_ctrg) + return global_ctrg; + + global_ctrg = rate_ctr_group_alloc(tall_bsc_ctx, &global_ctrg_desc, 0); + return global_ctrg; +} + +enum gbprox_peer_ctr { + GBPROX_PEER_CTR_BLOCKED, + GBPROX_PEER_CTR_UNBLOCKED, + GBPROX_PEER_CTR_DROPPED, + GBPROX_PEER_CTR_INV_NSEI, + GBPROX_PEER_CTR_TX_ERR, +}; + +static const struct rate_ctr_desc peer_ctr_description[] = { + { "blocked", "BVC Block " }, + { "unblocked", "BVC Unblock " }, + { "dropped", "BVC blocked, dropped packet " }, + { "inv-nsei", "NSEI mismatch " }, + { "tx-err", "NS Transmission error " }, +}; + +static const struct rate_ctr_group_desc peer_ctrg_desc = { + .group_name_prefix = "gbproxy.peer", + .group_description = "GBProxy Peer Statistics", + .num_ctr = ARRAY_SIZE(peer_ctr_description), + .ctr_desc = peer_ctr_description, +}; + struct gbprox_peer { struct llist_head list; @@ -51,6 +123,9 @@ struct gbprox_peer { /* Routeing Area that this peer is part of (raw 04.08 encoding) */ uint8_t ra[6]; + + /* Counter */ + struct rate_ctr_group *ctrg; }; /* Linked list of all Gb peers (except SGSN) */ @@ -100,6 +175,19 @@ static struct gbprox_peer *peer_by_lac(const uint8_t *la) return NULL; } +static int check_peer_nsei(struct gbprox_peer *peer, uint16_t nsei) +{ + if (peer->nsei != nsei) { + LOGP(DGPRS, LOGL_NOTICE, "Peer entry doesn't match current NSEI " + "BVCI=%u via NSEI=%u (expected NSEI=%u)\n", + peer->bvci, nsei, peer->nsei); + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_INV_NSEI]); + return 1; + } + + return 0; +} + static struct gbprox_peer *peer_alloc(uint16_t bvci) { struct gbprox_peer *peer; @@ -109,6 +197,8 @@ static struct gbprox_peer *peer_alloc(uint16_t bvci) return NULL; peer->bvci = bvci; + peer->ctrg = rate_ctr_group_alloc(peer, &peer_ctrg_desc, bvci); + llist_add(&peer->list, &gbprox_bts_peers); return peer; @@ -175,6 +265,7 @@ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci) /* create a copy of the message so the old one can * be free()d safely when we return from gbprox_rcvmsg() */ struct msgb *msg = msgb_copy(old_msg, "msgb_relay2sgsn"); + int rc; DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n", msgb_nsei(msg), ns_bvci, gbcfg.nsip_sgsn_nsei); @@ -184,7 +275,11 @@ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci) strip_ns_hdr(msg); - return gprs_ns_sendmsg(bssgp_nsi, msg); + rc = gprs_ns_sendmsg(bssgp_nsi, msg); + if (rc < 0) + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_TX_ERR_SGSN]); + + return rc; } /* feed a message down the NS-VC associated with the specified peer */ @@ -194,6 +289,7 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer, /* create a copy of the message so the old one can * be free()d safely when we return from gbprox_rcvmsg() */ struct msgb *msg = msgb_copy(old_msg, "msgb_relay2peer"); + int rc; DEBUGP(DGPRS, "NSEI=%u proxying SGSN->BSS (NS_BVCI=%u, NSEI=%u)\n", msgb_nsei(msg), ns_bvci, peer->nsei); @@ -204,7 +300,11 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer, /* Strip the old NS header, it will be replaced with a new one */ strip_ns_hdr(msg); - return gprs_ns_sendmsg(bssgp_nsi, msg); + rc = gprs_ns_sendmsg(bssgp_nsi, msg); + if (rc < 0) + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_TX_ERR]); + + return rc; } static int block_unblock_peer(uint16_t ptp_bvci, uint8_t pdu_type) @@ -215,15 +315,18 @@ static int block_unblock_peer(uint16_t ptp_bvci, uint8_t pdu_type) if (!peer) { LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n", ptp_bvci); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_BVCI]); return -ENOENT; } switch (pdu_type) { case BSSGP_PDUT_BVC_BLOCK_ACK: peer->blocked = 1; + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_BLOCKED]); break; case BSSGP_PDUT_BVC_UNBLOCK_ACK: peer->blocked = 0; + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_UNBLOCKED]); break; default: break; @@ -242,6 +345,7 @@ static int gbprox_relay2bvci(struct msgb *msg, uint16_t ptp_bvci, if (!peer) { LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n", ptp_bvci); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_BVCI]); return -ENOENT; } @@ -327,6 +431,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, from_peer = peer_alloc(bvci); from_peer->nsei = nsei; } + check_peer_nsei(from_peer, nsei); if (TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID)) { struct gprs_ra_id raid; /* We have a Cell Identifier present in this @@ -352,10 +457,12 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on NSEI\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_NSEI]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) missing mandatory RA IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_PROTO_ERR_BSS]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } @@ -364,6 +471,7 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, uint32_t nsei, uint16_t ns_bvci) { struct gbprox_peer *peer = NULL; + int errctr = GBPROX_GLOB_CTR_PROTO_ERR_SGSN; LOGP(DGPRS, LOGL_INFO, "NSEI=%u(SGSN) BSSGP PAGING ", nsei); @@ -371,20 +479,24 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, uint16_t bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI)); LOGPC(DGPRS, LOGL_INFO, "routing by BVCI to peer BVCI=%u\n", bvci); + errctr = GBPROX_GLOB_CTR_OTHER_ERR; } else if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) { peer = peer_by_rac(TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA)); LOGPC(DGPRS, LOGL_INFO, "routing by RAC to peer BVCI=%u\n", peer ? peer->bvci : -1); + errctr = GBPROX_GLOB_CTR_INV_RAC; } else if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) { peer = peer_by_lac(TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA)); LOGPC(DGPRS, LOGL_INFO, "routing by LAC to peer BVCI=%u\n", peer ? peer->bvci : -1); + errctr = GBPROX_GLOB_CTR_INV_LAC; } else LOGPC(DGPRS, LOGL_INFO, "\n"); if (!peer) { LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP PAGING: " "unable to route, missing IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[errctr]); return -EINVAL; } return gbprox_relay2peer(msg, peer, ns_bvci); @@ -398,6 +510,8 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, uint16_t ptp_bvci; if (!TLVP_PRESENT(tp, BSSGP_IE_BVCI)) { + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } @@ -410,6 +524,8 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, if (!peer) { LOGP(DGPRS, LOGL_ERROR, "NSEI=%u BVCI=%u: Cannot find BSS\n", nsei, ptp_bvci); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_INV_BVCI]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); } @@ -514,6 +630,8 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, "%sBLOCK_ACK for signalling BVCI ?!?\n", nsei, pdu_type == BSSGP_PDUT_BVC_UNBLOCK_ACK ? "UN":""); /* should we send STATUS ? */ + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_INV_BVCI]); } else { /* Mark BVC as (un)blocked */ block_unblock_peer(bvci, pdu_type); @@ -523,11 +641,15 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, case BSSGP_PDUT_SGSN_INVOKE_TRACE: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP INVOKE TRACE not supported\n",nsei); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN]); rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, msg); break; default: LOGP(DGPRS, LOGL_NOTICE, "BSSGP PDU type 0x%02x unknown\n", pdu_type); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); break; } @@ -536,10 +658,13 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) missing mandatory IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) cannot find peer based on RAC\n", nsei); + rate_ctr_inc(&get_global_ctrg()-> ctr[GBPROX_GLOB_CTR_INV_RAC]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); } @@ -557,12 +682,16 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns else rc = gbprox_rx_sig_from_bss(msg, nsei, ns_bvci); } else { + peer = peer_by_bvci(ns_bvci); + /* All other BVCI are PTP and thus can be simply forwarded */ - if (!remote_end_is_sgsn) + if (!remote_end_is_sgsn) { + if (peer) + check_peer_nsei(peer, nsei); return gbprox_relay2sgsn(msg, ns_bvci); + } /* else: SGSN -> BSS direction */ - peer = peer_by_bvci(ns_bvci); if (!peer) { LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for " "BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, @@ -574,6 +703,7 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns LOGP(DGPRS, LOGL_NOTICE, "Dropping PDU for " "blocked BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, nsvci, nsei); + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_DROPPED]); return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, NULL, msg); } rc = gbprox_relay2peer(msg, peer, ns_bvci); @@ -616,6 +746,8 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, if (signal == S_NS_ALIVE_EXP && nsvc->remote_end_is_sgsn) { LOGP(DGPRS, LOGL_NOTICE, "Tns alive expired too often, " "re-starting RESET procedure\n"); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_RESTART_RESET_SGSN]); gprs_ns_nsip_connect(nsvc->nsi, &nsvc->ip.bts_addr, nsvc->nsei, nsvc->nsvci); } @@ -668,10 +800,12 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, return 0; } -int gbprox_dump_peers(FILE *stream, int indent) +int gbprox_dump_peers(FILE *stream, int indent, int verbose) { struct gbprox_peer *peer; struct gprs_ra_id raid; + unsigned int i; + const struct rate_ctr_group_desc *desc; int rc; fprintf(stream, "%*sPeers:\n", indent, ""); @@ -687,6 +821,24 @@ int gbprox_dump_peers(FILE *stream, int indent) if (rc < 0) return rc; + + if (!verbose) + continue; + + desc = peer->ctrg->desc; + + for (i = 0; i < desc->num_ctr; i++) { + struct rate_ctr *ctr = &peer->ctrg->ctr[i]; + if (ctr->current) { + rc = fprintf(stream, "%*s %s: %llu\n", + indent, "", + desc->ctr_desc[i].description, + (long long)ctr->current); + + if (rc < 0) + return rc; + } + } } return 0; @@ -694,10 +846,14 @@ int gbprox_dump_peers(FILE *stream, int indent) #include -gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy", +gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", SHOW_STR "Display information about the Gb proxy") { struct gbprox_peer *peer; + int show_stats = argc >= 1; + + if (show_stats) + vty_out_rate_ctr_group(vty, "", get_global_ctrg()); llist_for_each_entry(peer, &gbprox_bts_peers, list) { struct gprs_ra_id raid; @@ -711,6 +867,9 @@ gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy", vty_out(vty, " [BVC-BLOCKED]"); vty_out(vty, "%s", VTY_NEWLINE); + + if (show_stats) + vty_out_rate_ctr_group(vty, " ", peer->ctrg); } return CMD_SUCCESS; } diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 93fdbe0..21ee723 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -420,7 +420,7 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); @@ -429,7 +429,7 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000); setup_bssgp(nsi, &bss_peer[1], 0x2002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002); @@ -437,43 +437,43 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Move BSS 2 to former BSS 1 port ---\n\n"); setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Move BSS 1 to current BSS 2 port ---\n\n"); setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Move BSS 2 to new port ---\n\n"); setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Move BSS 2 to former BSS 1 port ---\n\n"); setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Move BSS 1 to original BSS 1 port ---\n\n"); setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); printf("--- Reset BSS 1 with a new BVCI ---\n\n"); setup_bssgp(nsi, &bss_peer[0], 0x1012); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012); @@ -481,7 +481,7 @@ static void test_gbproxy() setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); @@ -489,7 +489,7 @@ static void test_gbproxy() setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); @@ -521,7 +521,7 @@ static void test_gbproxy() setup_bssgp(nsi, &bss_peer[2], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1); send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index b8920ac..e4b7aba 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -746,7 +746,9 @@ Current NS-VCIs: Peers: NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 PROCESSING BVC_RESET_ACK from 0x05060708:32000 00 00 00 00 23 04 82 10 02 -- 1.7.9.5 From jerlbeck at sysmocom.de Fri Oct 18 20:12:16 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Fri, 18 Oct 2013 22:12:16 +0200 Subject: [PATCH 1/2] gbproxy: Test invalid BVCI from SGSN Message-ID: <1382127137-12656-1-git-send-email-jerlbeck@sysmocom.de> This adds a test with a UNITDATA SGSN message that is addressed to an invalid (unknown) BVCI. The test shows, that the message is echoed to the SGSN. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 1 + openbsc/src/gprs/gb_proxy.c | 36 ++++++++++++++++++++++++++++++++- openbsc/tests/gbproxy/gbproxy_test.c | 8 ++++++++ openbsc/tests/gbproxy/gbproxy_test.ok | 18 +++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 82e47d5..7b14a09 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -35,5 +35,6 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, /* Reset all persistent NS-VC's */ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi); +int gbprox_dump_global(FILE *stream, int indent, int verbose); int gbprox_dump_peers(FILE *stream, int indent, int verbose); #endif diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index ddc9e0a..a25a9f5 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -800,6 +800,37 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, return 0; } +int gbprox_dump_global(FILE *stream, int indent, int verbose) +{ + unsigned int i; + const struct rate_ctr_group_desc *desc; + int rc; + + rc = fprintf(stream, "%*sGbproxy global:\n", indent, ""); + if (rc < 0) + return rc; + + if (!verbose) + return 0; + + desc = get_global_ctrg()->desc; + + for (i = 0; i < desc->num_ctr; i++) { + struct rate_ctr *ctr = &get_global_ctrg()->ctr[i]; + if (ctr->current) { + rc = fprintf(stream, "%*s %s: %llu\n", + indent, "", + desc->ctr_desc[i].description, + (long long)ctr->current); + + if (rc < 0) + return rc; + } + } + + return 0; +} + int gbprox_dump_peers(FILE *stream, int indent, int verbose) { struct gbprox_peer *peer; @@ -808,7 +839,10 @@ int gbprox_dump_peers(FILE *stream, int indent, int verbose) const struct rate_ctr_group_desc *desc; int rc; - fprintf(stream, "%*sPeers:\n", indent, ""); + rc = fprintf(stream, "%*sPeers:\n", indent, ""); + if (rc < 0) + return rc; + llist_for_each_entry(peer, &gbprox_bts_peers, list) { gsm48_parse_ra(&raid, peer->ra); diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 21ee723..e1e6587 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -523,6 +523,8 @@ static void test_gbproxy() gprs_dump_nsi(nsi); gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_global(stdout, 0, 1); + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n"); @@ -533,6 +535,12 @@ static void test_gbproxy() send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0); + printf("--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---\n\n"); + + send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0); + + gbprox_dump_global(stdout, 0, 1); + gprs_ns_destroy(nsi); nsi = NULL; } diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index e4b7aba..fcde39f 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -749,6 +749,7 @@ Peers: NSEI mismatch : 1 NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 NSEI mismatch : 1 +Gbproxy global: PROCESSING BVC_RESET_ACK from 0x05060708:32000 00 00 00 00 23 04 82 10 02 @@ -795,5 +796,22 @@ MESSAGE to BSS at 0x01020304:1111, msg length 4 result (UNITDATA) = 4 +--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) --- + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 ff + +CALLBACK, event 0, msg length 0, bvci 0x10ff + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x10ff, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 10 ff + +result (UNITDATA) = 4 + +Gbproxy global: ===== NS protocol test END -- 1.7.9.5 From jerlbeck at sysmocom.de Fri Oct 18 20:12:17 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Fri, 18 Oct 2013 22:12:17 +0200 Subject: [PATCH 2/2] gbproxy: Reject SGSN UNITDATA messages with an invalid BVCI In-Reply-To: <1382127137-12656-1-git-send-email-jerlbeck@sysmocom.de> References: <1382127137-12656-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382127137-12656-2-git-send-email-jerlbeck@sysmocom.de> Currently such messages lead to a creation of a new peer with the SGSN's NSEI, which results in echoing the message back to the SGSN. This patch modifies this by sending a STATUS response (invalid BVCI) instead back to the SGSN. Sponsored-by: On-Waves ehf --- openbsc/src/gprs/gb_proxy.c | 12 +++++++----- openbsc/tests/gbproxy/gbproxy_test.ok | 11 ++++++----- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index a25a9f5..dea6e3f 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -693,11 +693,13 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns /* else: SGSN -> BSS direction */ if (!peer) { - LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for " - "BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, - nsvci, nsei); - peer = peer_alloc(ns_bvci); - peer->nsei = nsei; + LOGP(DGPRS, LOGL_INFO, "Didn't find peer for " + "BVCI=%u for message from NSVC=%u/NSEI=%u (SGSN)\n", + ns_bvci, nsvci, nsei); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_INV_BVCI]); + return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, + &ns_bvci, msg); } if (peer->blocked) { LOGP(DGPRS, LOGL_NOTICE, "Dropping PDU for " diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index fcde39f..35d97e7 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -804,14 +804,15 @@ PROCESSING UNITDATA from 0x05060708:32000 CALLBACK, event 0, msg length 0, bvci 0x10ff -NS UNITDATA MESSAGE to SGSN, BVCI 0x10ff, msg length 0 +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 10 +41 07 81 05 04 82 10 ff 15 80 +MESSAGE to SGSN at 0x05060708:32000, msg length 14 +00 00 00 00 41 07 81 05 04 82 10 ff 15 80 -MESSAGE to SGSN at 0x05060708:32000, msg length 4 -00 00 10 ff - -result (UNITDATA) = 4 +result (UNITDATA) = 14 Gbproxy global: + Invalid BVC Identifier : 1 ===== NS protocol test END -- 1.7.9.5 From jijo123789 at gmail.com Mon Oct 21 09:25:43 2013 From: jijo123789 at gmail.com (Joe Ge) Date: Mon, 21 Oct 2013 14:55:43 +0530 Subject: OpenBSC with USRP2 : rsl.c error Message-ID: Hi all, I know this problem has been dealt previously in a minor variation but please help me out here. I'm trying to configure OpenBSC using the USRP N210 device and followed the same network from scratch installation. I got up to the part where sysmobts gives the error and corrected it by editing the makefile. But unlike others my 'make' command is giving me an error in the rsl.c file. make[2]: Entering directory `/home/prabu/OpenBSC-OpenBTS/osmo-bts/src/common' CC rsl.o rsl.c:140:2: warning: #warning merge lchan_lookup with OpenBSC [-Wcpp] rsl.c: In function ?rsl_rx_chan_activ?: rsl.c:779:53: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? rsl.c:783:15: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? rsl.c: In function ?rsl_rx_mode_modif?: rsl.c:1028:53: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? rsl.c:1032:15: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? make[2]: *** [rsl.o] Error 1 make[2]: Leaving directory `/home/prabu/OpenBSC-OpenBTS/osmo-bts/src/common' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/home/prabu/OpenBSC-OpenBTS/osmo-bts/src' make: *** [all-recursive] Error 1 Can someone please help me out in what this error deals with. Or people who successfully completed the installation could tell me what they did differently Regards, Jijo -------------- next part -------------- An HTML attachment was scrubbed... URL: From maiconkist at gmail.com Tue Oct 22 13:00:41 2013 From: maiconkist at gmail.com (Maicon Kist) Date: Tue, 22 Oct 2013 11:00:41 -0200 Subject: OpenBSC with USRP2 : rsl.c error In-Reply-To: References: Message-ID: <57E35571-2301-4D23-9252-5AD1D36CF320@gmail.com> Hi, try to use the following branches: openbsc with branch jolly/testing osmo-bts with branch jolly/trx (master didn't compile) Best Regards, --- roses are #FF0000 violets are #0000FF On 21/10/2013, at 07:25, Joe Ge wrote: > Hi all, > > I know this problem has been dealt previously in a minor variation but please help me out here. > I'm trying to configure OpenBSC using the USRP N210 device and followed the same network from scratch installation. > I got up to the part where sysmobts gives the error and corrected it by editing the makefile. > But unlike others my 'make' command is giving me an error in the rsl.c file. > > make[2]: Entering directory `/home/prabu/OpenBSC-OpenBTS/osmo-bts/src/common' > CC rsl.o > rsl.c:140:2: warning: #warning merge lchan_lookup with OpenBSC [-Wcpp] > rsl.c: In function ?rsl_rx_chan_activ?: > rsl.c:779:53: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? > rsl.c:783:15: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? > rsl.c: In function ?rsl_rx_mode_modif?: > rsl.c:1028:53: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? > rsl.c:1032:15: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? > make[2]: *** [rsl.o] Error 1 > make[2]: Leaving directory `/home/prabu/OpenBSC-OpenBTS/osmo-bts/src/common' > make[1]: *** [all-recursive] Error 1 > make[1]: Leaving directory `/home/prabu/OpenBSC-OpenBTS/osmo-bts/src' > make: *** [all-recursive] Error 1 > > Can someone please help me out in what this error deals with. Or people who successfully completed the installation could tell me what they did differently > > > Regards, > Jijo -------------- next part -------------- An HTML attachment was scrubbed... URL: From maicon.kist at inf.ufrgs.br Tue Oct 22 13:08:38 2013 From: maicon.kist at inf.ufrgs.br (Maicon Kist) Date: Tue, 22 Oct 2013 11:08:38 -0200 Subject: OpenBSC with USRP2 : rsl.c error In-Reply-To: References: Message-ID: <0EC56D29-3DB3-40CC-8918-4895F4851CB1@inf.ufrgs.br> Hi, try to use the following branches: openbsc with branch jolly/testing osmo-bts with branch jolly/trx (master didn't compile) Best Regards, On 21/10/2013, at 07:25, Joe Ge wrote: > Hi all, > > I know this problem has been dealt previously in a minor variation but please help me out here. > I'm trying to configure OpenBSC using the USRP N210 device and followed the same network from scratch installation. > I got up to the part where sysmobts gives the error and corrected it by editing the makefile. > But unlike others my 'make' command is giving me an error in the rsl.c file. > > make[2]: Entering directory `/home/prabu/OpenBSC-OpenBTS/osmo-bts/src/common' > CC rsl.o > rsl.c:140:2: warning: #warning merge lchan_lookup with OpenBSC [-Wcpp] > rsl.c: In function ?rsl_rx_chan_activ?: > rsl.c:779:53: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? > rsl.c:783:15: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? > rsl.c: In function ?rsl_rx_mode_modif?: > rsl.c:1028:53: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? > rsl.c:1032:15: error: ?struct gsm_lchan? has no member named ?mr_bts_lv? > make[2]: *** [rsl.o] Error 1 > make[2]: Leaving directory `/home/prabu/OpenBSC-OpenBTS/osmo-bts/src/common' > make[1]: *** [all-recursive] Error 1 > make[1]: Leaving directory `/home/prabu/OpenBSC-OpenBTS/osmo-bts/src' > make: *** [all-recursive] Error 1 > > Can someone please help me out in what this error deals with. Or people who successfully completed the installation could tell me what they did differently > > > Regards, > Jijo From jerlbeck at sysmocom.de Tue Oct 22 10:22:39 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 22 Oct 2013 12:22:39 +0200 Subject: [PATCH 1/3] gb/vty: Perform NS-VC operations based on NS-VCI Message-ID: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> This adds a 'nsvc nsvci <0-65535> (block|unblock|reset)' vty command. It selects the NS-VC based on the nsvci instead of using the first with a matching NSEI, like it is done when the 'nsei' keyword is used instead. Sponsored-by: On-Waves ehf --- src/gb/gprs_ns_vty.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/gb/gprs_ns_vty.c b/src/gb/gprs_ns_vty.c index a2e7beb..f33fd0b 100644 --- a/src/gb/gprs_ns_vty.c +++ b/src/gb/gprs_ns_vty.c @@ -499,21 +499,29 @@ DEFUN(cfg_frgre_enable, cfg_frgre_enable_cmd, } DEFUN(nsvc_nsei, nsvc_nsei_cmd, - "nsvc nsei <0-65535> (block|unblock|reset)", + "nsvc (nsei|nsvci) <0-65535> (block|unblock|reset)", "Perform an operation on a NSVC\n" "NSEI to identify NS-VC Identifier (NS-VCI)\n" + "NS-VC Identifier (NS-VCI)\n" "The NSEI\n" "Initiate BLOCK procedure\n" "Initiate UNBLOCK procedure\n" "Initiate RESET procedure\n") { - uint16_t nsvci = atoi(argv[0]); - const char *operation = argv[1]; + const char *id_type = argv[0]; + uint16_t id = atoi(argv[1]); + const char *operation = argv[2]; struct gprs_nsvc *nsvc; - nsvc = gprs_nsvc_by_nsei(vty_nsi, nsvci); + if (!strcmp(id_type, "nsei")) + nsvc = gprs_nsvc_by_nsei(vty_nsi, id); + else if (!strcmp(id_type, "nsvci")) + nsvc = gprs_nsvc_by_nsvci(vty_nsi, id); + else + return CMD_WARNING; + if (!nsvc) { - vty_out(vty, "No such NSVCI (%u)%s", nsvci, VTY_NEWLINE); + vty_out(vty, "No such %s (%u)%s", id_type, id, VTY_NEWLINE); return CMD_WARNING; } -- 1.7.9.5 From jerlbeck at sysmocom.de Tue Oct 22 10:22:40 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 22 Oct 2013 12:22:40 +0200 Subject: [PATCH 2/3] gb: Add test case for SGSN->BSS RESET procedures In-Reply-To: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382437361-23284-2-git-send-email-jerlbeck@sysmocom.de> Add a test handling proper and mismatching RESETs. The latter may occur, when ports change within a NS-VC without the SGSN getting notice. The current implementation doesn't handle this correctly in all cases, especially concerning GSM 08.16, 7.3.1. Sponsored-by: On-Waves ehf --- tests/gb/gprs_ns_test.c | 157 +++++++++++++++++++++ tests/gb/gprs_ns_test.ok | 344 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 501 insertions(+) diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index 38c7d1f..df7f18b 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -493,6 +493,156 @@ static void test_bss_port_changes() nsi = NULL; } +static void test_bss_reset_ack() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in peer[4] = {{0},}; + struct gprs_nsvc *nsvc; + struct sockaddr_in *nse[4]; + int rc; + + peer[0].sin_family = AF_INET; + peer[0].sin_port = htons(1111); + peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + peer[1].sin_family = AF_INET; + peer[1].sin_port = htons(2222); + peer[1].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + peer[2].sin_family = AF_INET; + peer[2].sin_port = htons(3333); + peer[2].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + peer[3].sin_family = AF_INET; + peer[3].sin_port = htons(4444); + peer[3].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + + nse[0] = &peer[0]; + nse[1] = &peer[1]; + + printf("--- Setup VC 1 BSS -> SGSN ---\n\n"); + + setup_ns(nsi, nse[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- Setup VC 2 BSS -> SGSN ---\n\n"); + + setup_ns(nsi, nse[1], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + + printf("--- Setup VC 1 SGSN -> BSS ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x1001); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, nse[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- Exchange NSEI 1 + 2 links ---\n\n"); + + nse[1] = &peer[0]; + nse[0] = &peer[1]; + + printf("--- Setup VC 2 SGSN -> BSS (hits NSEI 1) ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x2001); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, nse[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- Setup VC 2 SGSN -> BSS (hits NSEI 2) ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x2001); + rc = gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + if (rc < 0) + printf("Failed to send RESET to %s\n\n", gprs_ns_ll_str(nsvc)); + else { + send_ns_reset_ack(nsi, nse[1], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + } + + printf("--- Setup VC 1 SGSN -> BSS (hits NSEI 1) ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x1001); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, nse[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- Setup VC 2 BSS -> SGSN ---\n\n"); + + setup_ns(nsi, nse[1], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 5th paragraph. */ + + printf("--- Unexpected RESET_ACK VC 1, BSS -> SGSN ---\n\n"); + + send_ns_reset_ack(nsi, nse[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 4th paragraph. */ + + printf("--- RESET_ACK with invalid NSEI, BSS -> SGSN ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x1001); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, nse[0], 0x1001, 0xf000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 4th paragraph. */ + + printf("--- RESET_ACK with invalid NSVCI, BSS -> SGSN ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x1001); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, nse[0], 0xf001, 0x1000); + gprs_dump_nsi(nsi); + + gprs_ns_destroy(nsi); + nsi = NULL; +} + + +static void test_sgsn_reset() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in sgsn_peer= {0}; + + sgsn_peer.sin_family = AF_INET; + sgsn_peer.sin_port = htons(32000); + sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR); + + gprs_dump_nsi(nsi); + + printf("--- Setup SGSN connection, BSS -> SGSN ---\n\n"); + + gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1); + send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); + send_ns_alive_ack(nsi, &sgsn_peer); + send_ns_unblock_ack(nsi, &sgsn_peer); + gprs_dump_nsi(nsi); + + printf("--- RESET, SGSN -> BSS ---\n\n"); + + send_ns_reset(nsi, &sgsn_peer, NS_CAUSE_OM_INTERVENTION, + SGSN_NSEI+1, SGSN_NSEI); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 3rd paragraph. */ + + printf("--- RESET with invalid NSEI, SGSN -> BSS ---\n\n"); + + send_ns_reset(nsi, &sgsn_peer, NS_CAUSE_OM_INTERVENTION, + SGSN_NSEI+1, 0xf000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 2nd paragraph. */ + + printf("--- RESET with invalid NSVCI, SGSN -> BSS ---\n\n"); + + send_ns_reset(nsi, &sgsn_peer, NS_CAUSE_OM_INTERVENTION, + 0xf001, SGSN_NSEI); + gprs_dump_nsi(nsi); + + gprs_ns_destroy(nsi); + nsi = NULL; +} static void test_sgsn_output() { @@ -567,8 +717,15 @@ int main(int argc, char **argv) log_set_print_filename(osmo_stderr_target, 0); osmo_signal_register_handler(SS_L_NS, &test_signal, NULL); + log_set_print_filename(osmo_stderr_target, 0); + log_set_log_level(osmo_stderr_target, LOGL_INFO); + + setlinebuf(stdout); + printf("===== NS protocol test START\n"); test_bss_port_changes(); + test_bss_reset_ack(); + test_sgsn_reset(); test_sgsn_output(); printf("===== NS protocol test END\n\n"); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 424d681..ddd0b00 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -143,6 +143,350 @@ Current NS-VCIs: NS-VC replaced other count: 1 NS-VC changed NSEI : 2 +--- Setup VC 1 BSS -> SGSN --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + +--- Setup VC 2 BSS -> SGSN --- + +Setup NS-VC: remote 0x01020304:2222, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:2222 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:2222 +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:2222 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:2222 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:2222 +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:2222 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + +--- Setup VC 1 SGSN -> BSS --- + +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 10 01 04 82 10 00 + +PROCESSING RESET_ACK from 0x01020304:1111 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + NS-VC Block count : 1 + +--- Exchange NSEI 1 + 2 links --- + +--- Setup VC 2 SGSN -> BSS (hits NSEI 1) --- + +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 20 01 04 82 20 00 + +PROCESSING RESET_ACK from 0x01020304:2222 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked + NS-VC Block count : 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + NS-VC Block count : 1 + +--- Setup VC 2 SGSN -> BSS (hits NSEI 2) --- + +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 20 01 04 82 20 00 + +PROCESSING RESET_ACK from 0x01020304:1111 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked + NS-VC Block count : 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + NS-VC Block count : 2 + +--- Setup VC 1 SGSN -> BSS (hits NSEI 1) --- + +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 10 01 04 82 10 00 + +PROCESSING RESET_ACK from 0x01020304:2222 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked + NS-VC Block count : 2 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + NS-VC Block count : 2 + +--- Setup VC 2 BSS -> SGSN --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_REPLACED: 0x2001/1.2.3.4:2222 -> 0x1001/1.2.3.4:1111 +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x00000000:0, blocked + NS-VC Block count : 2 + +--- Unexpected RESET_ACK VC 1, BSS -> SGSN --- + +PROCESSING RESET_ACK from 0x01020304:2222 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 15 +08 00 81 0a 02 89 03 01 82 10 01 04 82 10 00 + +result (RESET_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x00000000:0, blocked + NS-VC Block count : 2 + +--- RESET_ACK with invalid NSEI, BSS -> SGSN --- + +PROCESSING RESET_ACK from 0x01020304:2222 +03 01 82 10 01 04 82 f0 00 + +MESSAGE to BSS, msg length 15 +08 00 81 0a 02 89 03 01 82 10 01 04 82 f0 00 + +result (RESET_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x00000000:0, blocked + NS-VC Block count : 2 + +--- RESET_ACK with invalid NSVCI, BSS -> SGSN --- + +PROCESSING RESET_ACK from 0x01020304:2222 +03 01 82 f0 01 04 82 10 00 + +MESSAGE to BSS, msg length 15 +08 00 81 0a 02 89 03 01 82 f0 01 04 82 10 00 + +result (RESET_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x00000000:0, blocked + NS-VC Block count : 2 + +Current NS-VCIs: + +--- Setup SGSN connection, BSS -> SGSN --- + +MESSAGE to SGSN, msg length 12 +02 00 81 01 01 82 01 01 04 82 01 00 + +PROCESSING RESET_ACK from 0x05060708:32000 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET_ACK) = 1 + +PROCESSING ALIVE_ACK from 0x05060708:32000 +0b + +MESSAGE to SGSN, msg length 1 +06 + +result (ALIVE_ACK) = 1 + +PROCESSING UNBLOCK_ACK from 0x05060708:32000 +07 + +==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000 +result (UNBLOCK_ACK) = 0 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +--- RESET, SGSN -> BSS --- + +PROCESSING RESET from 0x05060708:32000 +02 00 81 01 01 82 01 01 04 82 01 00 + +==> got signal NS_RESET, NS-VC 0x0101/5.6.7.8:32000 +MESSAGE to SGSN, msg length 9 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked + NS-VC Block count : 1 + +--- RESET with invalid NSEI, SGSN -> BSS --- + +PROCESSING RESET from 0x05060708:32000 +02 00 81 01 01 82 01 01 04 82 f0 00 + +==> got signal NS_RESET, NS-VC 0x0101/5.6.7.8:32000 +MESSAGE to SGSN, msg length 9 +03 01 82 01 01 04 82 f0 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x0101, NSEI 0xf000, peer 0x05060708:32000, blocked + NS-VC Block count : 1 + +--- RESET with invalid NSVCI, SGSN -> BSS --- + +PROCESSING RESET from 0x05060708:32000 +02 00 81 01 01 82 f0 01 04 82 01 00 + +==> got signal NS_RESET, NS-VC 0xf001/5.6.7.8:32000 +MESSAGE to SGSN, msg length 9 +03 01 82 f0 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0xf001, NSEI 0x0100, peer 0x05060708:32000, blocked + NS-VC Block count : 1 + Current NS-VCIs: --- Send message to SGSN --- -- 1.7.9.5 From holger at freyther.de Thu Oct 24 05:35:58 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 24 Oct 2013 07:35:58 +0200 Subject: [PATCH 2/3] gb: Add test case for SGSN->BSS RESET procedures In-Reply-To: <1382437361-23284-2-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> <1382437361-23284-2-git-send-email-jerlbeck@sysmocom.de> Message-ID: <20131024053558.GB30417@xiaoyu.lan> On Tue, Oct 22, 2013 at 12:22:40PM +0200, Jacob Erlbeck wrote: Dear Jacob, > + setlinebuf(stdout); out of curiosity, why is this needed? From jerlbeck at sysmocom.de Thu Oct 24 07:37:57 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 09:37:57 +0200 Subject: [PATCH 2/3] gb: Add test case for SGSN->BSS RESET procedures In-Reply-To: <20131024053558.GB30417@xiaoyu.lan> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> <1382437361-23284-2-git-send-email-jerlbeck@sysmocom.de> <20131024053558.GB30417@xiaoyu.lan> Message-ID: <5268CE55.5040808@sysmocom.de> On 10/24/2013 07:35 AM, Holger Hans Peter Freyther wrote: > On Tue, Oct 22, 2013 at 12:22:40PM +0200, Jacob Erlbeck wrote: >> + setlinebuf(stdout); > > out of curiosity, why is this needed? > To have a sensible relation between stderr and stdout lines, e.g. when calling something like: ./tests/gbproxy/gbproxy_test 2>&1 | less or writing the output to a file. Since by default stderr is unbuffered and stdout is (possibly) block buffered when not writing to tty. You'd get chunks of stderr and stdout blobs in this case. See setlinebuf(3) for details. Jacob From jerlbeck at sysmocom.de Tue Oct 22 10:22:41 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 22 Oct 2013 12:22:41 +0200 Subject: [PATCH 3/3] gb: Fix NS RESET/RESET_ACK abnormal cases In-Reply-To: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382437361-23284-3-git-send-email-jerlbeck@sysmocom.de> This changes the implementations for the reception of RESET and RESET_ACK to be compatible with 3GPP TS 08.16, 7.3.1: - Just send a RESET_ACK with correct values back to the SGSN when a RESET with an invalid NSVCI or NSEI has been received. - Check RESET_ACK for matching NSEI and NSVCI. - Ignore unexpected RESET_ACKs. In addition, use RESET_ACK from a BSS to update the BSS source address based on the NSVCI to be tolerant with changing UDP source addresses/ports. Sponsored-by: On-Waves ehf --- include/osmocom/gprs/gprs_ns.h | 5 + src/gb/gprs_ns.c | 259 +++++++++++++++++++++++++++++++++------- tests/gb/gprs_ns_test.c | 6 + tests/gb/gprs_ns_test.ok | 104 +++++++--------- 4 files changed, 269 insertions(+), 105 deletions(-) diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index b28c58d..296800e 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -36,6 +36,7 @@ enum ns_timeout { #define NSE_S_BLOCKED 0x0001 #define NSE_S_ALIVE 0x0002 +#define NSE_S_RESET 0x0004 /*! \brief Osmocom NS link layer types */ enum gprs_ns_ll { @@ -199,12 +200,16 @@ enum signal_ns { S_NS_UNBLOCK, S_NS_ALIVE_EXP, /* Tns-alive expired more than N times */ S_NS_REPLACED, /* nsvc object is replaced (sets old_nsvc) */ + S_NS_MISMATCH, /* got an unexpected IE (sets msg, pdu_type, ie_type) */ }; struct ns_signal_data { struct gprs_nsvc *nsvc; struct gprs_nsvc *old_nsvc; uint8_t cause; + uint8_t pdu_type; + uint8_t ie_type; + struct msgb *msg; }; void gprs_ns_set_log_ss(int ss); diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 6a35ad3..b50a700 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -102,6 +102,8 @@ enum ns_ctr { NS_CTR_DEAD, NS_CTR_REPLACED, NS_CTR_NSEI_CHG, + NS_CTR_INV_VCI, + NS_CTR_INV_NSEI, }; static const struct rate_ctr_desc nsvc_ctr_description[] = { @@ -113,6 +115,8 @@ static const struct rate_ctr_desc nsvc_ctr_description[] = { { "dead", "NS-VC gone dead count " }, { "replaced", "NS-VC replaced other count" }, { "nsei-chg", "NS-VC changed NSEI " }, + { "inv-nsvci", "NS-VCI was invalid count " }, + { "inv-nsei", "NSEI was invalid count " }, }; static const struct rate_ctr_group_desc nsvc_ctrg_desc = { @@ -190,6 +194,7 @@ struct gprs_nsvc *gprs_nsvc_create(struct gprs_ns_inst *nsi, uint16_t nsvci) nsvc = talloc_zero(nsi, struct gprs_nsvc); nsvc->nsvci = nsvci; + nsvc->nsvci_is_valid = 1; /* before RESET procedure: BLOCKED and DEAD */ nsvc->state = NSE_S_BLOCKED; nsvc->nsi = nsi; @@ -224,6 +229,20 @@ static void ns_osmo_signal_dispatch(struct gprs_nsvc *nsvc, unsigned int signal, osmo_signal_dispatch(SS_L_NS, signal, &nssd); } +static void ns_osmo_signal_dispatch_mismatch(struct gprs_nsvc *nsvc, + struct msgb *msg, + uint8_t pdu_type, uint8_t ie_type) +{ + struct ns_signal_data nssd = {0}; + + nssd.nsvc = nsvc; + nssd.pdu_type = pdu_type; + nssd.ie_type = ie_type; + nssd.msg = msg; + + osmo_signal_dispatch(SS_L_NS, S_NS_MISMATCH, &nssd); +} + static void ns_osmo_signal_dispatch_replaced(struct gprs_nsvc *nsvc, struct gprs_nsvc *old_nsvc) { struct ns_signal_data nssd = {0}; @@ -322,6 +341,8 @@ int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause) LOGP(DNS, LOGL_INFO, "NSEI=%u Tx NS RESET (NSVCI=%u, cause=%s)\n", nsvc->nsei, nsvc->nsvci, gprs_ns_cause_str(cause)); + nsvc->state |= NSE_S_RESET; + msg->l2h = msgb_put(msg, sizeof(*nsh)); nsh = (struct gprs_ns_hdr *) msg->l2h; nsh->pdu_type = NS_PDUT_RESET; @@ -671,6 +692,49 @@ static int gprs_ns_rx_status(struct gprs_nsvc *nsvc, struct msgb *msg) return 0; } +/* Replace a nsvc object with another based on NSVCI. + * This function replaces looks for a NSVC with the given NSVCI and replaces it + * if possible and necessary. If replaced, the former value of *nsvc is + * returned in *old_nsvc. + * \return != 0 if *nsvc points to a matching NSVC. + */ +static int gprs_nsvc_replace_if_found(uint16_t nsvci, + struct gprs_nsvc **nsvc, + struct gprs_nsvc **old_nsvc) +{ + struct gprs_nsvc *matching_nsvc; + + if ((*nsvc)->nsvci == nsvci) { + *old_nsvc = NULL; + return 1; + } + + matching_nsvc = gprs_nsvc_by_nsvci((*nsvc)->nsi, nsvci); + + if (!matching_nsvc) + return 0; + + /* The NS-VCI is already used by this NS-VC */ + + char *old_peer; + + /* Exchange the NS-VC objects */ + *old_nsvc = *nsvc; + *nsvc = matching_nsvc; + + /* Do logging */ + old_peer = talloc_strdup(*old_nsvc, gprs_ns_ll_str(*old_nsvc)); + LOGP(DNS, LOGL_INFO, "NS-VC changed link (NSVCI=%u) from %s to %s\n", + nsvci, old_peer, gprs_ns_ll_str(*nsvc)); + + talloc_free(old_peer); + + /* Do statistics */ + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_REPLACED]); + + return 1; +} + /* Section 7.3 */ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) { @@ -678,7 +742,7 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) struct tlv_parsed tp; uint8_t cause; uint16_t nsvci, nsei; - struct gprs_nsvc *other_nsvc = NULL; + struct gprs_nsvc *orig_nsvc = NULL; int rc; rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, @@ -705,39 +769,42 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) (*nsvc)->nsvci, (*nsvc)->nsvci_is_valid ? "" : "(invalid)", nsei, nsvci, gprs_ns_cause_str(cause)); - if ((*nsvc)->nsvci_is_valid && (*nsvc)->nsvci != nsvci) { - /* NS-VCI has changed */ - other_nsvc = gprs_nsvc_by_nsvci((*nsvc)->nsi, nsvci); - - if (other_nsvc) { - /* The NS-VCI is already used by this NS-VC */ - - struct gprs_nsvc *tmp_nsvc; - char *old_peer; - - /* Exchange the NS-VC objects */ - tmp_nsvc = *nsvc; - *nsvc = other_nsvc; - other_nsvc = tmp_nsvc; - - /* Do logging */ - old_peer = talloc_strdup(other_nsvc, - gprs_ns_ll_str(other_nsvc)); - LOGP(DNS, LOGL_INFO, - "NS-VC changed link (NSVCI=%u) from %s to %s\n", - nsvci, old_peer, gprs_ns_ll_str(*nsvc)); - - talloc_free(old_peer); - - /* Do statistics */ - rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_REPLACED]); + if (!(*nsvc)->nsvci_is_valid) { + /* It's a new uninitialised NS-VC, nothing to check here */ + } else if ((*nsvc)->nsvci != nsvci) { + if ((*nsvc)->remote_end_is_sgsn) { + /* The incoming RESET doesn't match the NSVCI. Send an + * appropriate RESET_ACK and ignore the RESET. + * See 3GPP TS 08.16, 7.3.1, 2nd paragraph. + */ + ns_osmo_signal_dispatch_mismatch(*nsvc, msg, + NS_PDUT_RESET, + NS_IE_VCI); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_VCI]); + gprs_ns_tx_reset_ack(*nsvc); + return 0; } + + /* NS-VCI has changed */ + gprs_nsvc_replace_if_found(nsvci, nsvc, &orig_nsvc); + + } else if ((*nsvc)->nsei != nsei) { + /* The incoming RESET doesn't match the NSEI. Send an + * appropriate RESET_ACK and ignore the RESET. + * See 3GPP TS 08.16, 7.3.1, 3rd paragraph. + */ + ns_osmo_signal_dispatch_mismatch(*nsvc, msg, + NS_PDUT_RESET, + NS_IE_NSEI); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_NSEI]); + gprs_ns_tx_reset_ack(*nsvc); + return 0; } /* Mark NS-VC as blocked and alive */ (*nsvc)->state = NSE_S_BLOCKED | NSE_S_ALIVE; - if (other_nsvc) { + if (orig_nsvc) { /* Check NSEI */ if ((*nsvc)->nsei != nsei) { LOGP(DNS, LOGL_NOTICE, @@ -751,11 +818,11 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_NSEI_CHG]); } - ns_osmo_signal_dispatch_replaced(*nsvc, other_nsvc); + ns_osmo_signal_dispatch_replaced(*nsvc, orig_nsvc); /* Update the ll info fields */ - gprs_ns_ll_copy(*nsvc, other_nsvc); - gprs_ns_ll_clear(other_nsvc); + gprs_ns_ll_copy(*nsvc, orig_nsvc); + gprs_ns_ll_clear(orig_nsvc); } else { (*nsvc)->nsei = nsei; (*nsvc)->nsvci = nsvci; @@ -775,6 +842,121 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) return rc; } +static int gprs_ns_rx_reset_ack(struct gprs_nsvc **nsvc, struct msgb *msg) +{ + struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; + struct tlv_parsed tp; + uint16_t nsvci, nsei; + struct gprs_nsvc *orig_nsvc = NULL; + int rc; + + rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, + msgb_l2len(msg) - sizeof(*nsh), 0, 0); + if (rc < 0) { + LOGP(DNS, LOGL_ERROR, "NSEI=%u Rx NS RESET ACK " + "Error during TLV Parse\n", (*nsvc)->nsei); + return rc; + } + + if (!TLVP_PRESENT(&tp, NS_IE_VCI) || + !TLVP_PRESENT(&tp, NS_IE_NSEI)) { + LOGP(DNS, LOGL_ERROR, "NS RESET ACK Missing mandatory IE\n"); + gprs_ns_tx_status(*nsvc, NS_CAUSE_MISSING_ESSENT_IE, 0, msg); + return -EINVAL; + } + + nsvci = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_VCI)); + nsei = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI)); + + LOGP(DNS, LOGL_INFO, "NSVCI=%u%s Rx NS RESET ACK (NSEI=%u, NSVCI=%u)\n", + (*nsvc)->nsvci, (*nsvc)->nsvci_is_valid ? "" : "(invalid)", + nsei, nsvci); + + if (!((*nsvc)->state & NSE_S_RESET)) { + /* Not waiting for a RESET_ACK on this NS-VC, ignore it. + * See 3GPP TS 08.16, 7.3.1, 5th paragraph. + */ + LOGP(DNS, LOGL_ERROR, + "NS RESET ACK Discarding unexpected message for " + "NS-VCI %d from SGSN NSEI=%d\n", + nsvci, nsei); + return 0; + } + + if (!(*nsvc)->nsvci_is_valid) { + LOGP(DNS, LOGL_NOTICE, + "NS RESET ACK Uninitialised NS-VC (%u) for " + "NS-VCI %d, NSEI=%d from %s\n", + (*nsvc)->nsvci, nsvci, nsei, gprs_ns_ll_str(*nsvc)); + return -EINVAL; + } + + if ((*nsvc)->nsvci != nsvci) { + /* NS-VCI has changed */ + + /* if !0, use another NSVC object that matches the NSVCI */ + int use_other_nsvc; + + /* Only do this with BSS peers */ + use_other_nsvc = !(*nsvc)->remote_end_is_sgsn; + + if (use_other_nsvc) + /* Update *nsvc to point to the right NSVC object */ + use_other_nsvc = gprs_nsvc_replace_if_found(nsvci, nsvc, + &orig_nsvc); + + if (!use_other_nsvc) { + /* The incoming RESET_ACK doesn't match the NSVCI. + * See 3GPP TS 08.16, 7.3.1, 4th paragraph. + */ + ns_osmo_signal_dispatch_mismatch(*nsvc, msg, + NS_PDUT_RESET_ACK, + NS_IE_VCI); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_VCI]); + LOGP(DNS, LOGL_ERROR, + "NS RESET ACK Unknown NS-VCI %d (%s NSEI=%d) " + "from %s\n", + nsvci, + (*nsvc)->remote_end_is_sgsn ? "SGSN" : "BSS", + nsei, gprs_ns_ll_str(*nsvc)); + return -EINVAL; + } + + /* Notify others */ + ns_osmo_signal_dispatch_replaced(*nsvc, orig_nsvc); + + /* Update the ll info fields */ + gprs_ns_ll_copy(*nsvc, orig_nsvc); + gprs_ns_ll_clear(orig_nsvc); + } else if ((*nsvc)->nsei != nsei) { + /* The incoming RESET_ACK doesn't match the NSEI. + * See 3GPP TS 08.16, 7.3.1, 4th paragraph. + */ + ns_osmo_signal_dispatch_mismatch(*nsvc, msg, + NS_PDUT_RESET_ACK, + NS_IE_NSEI); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_NSEI]); + LOGP(DNS, LOGL_ERROR, + "NS RESET ACK Unknown NSEI %d (NS-VCI=%u) from %s\n", + nsei, nsvci, gprs_ns_ll_str(*nsvc)); + return -EINVAL; + } + + /* Mark NS-VC as blocked and alive */ + (*nsvc)->state = NSE_S_BLOCKED | NSE_S_ALIVE; + (*nsvc)->remote_state = NSE_S_BLOCKED | NSE_S_ALIVE; + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_BLOCKED]); + if ((*nsvc)->persistent || (*nsvc)->remote_end_is_sgsn) { + /* stop RESET timer */ + osmo_timer_del(&(*nsvc)->timer); + } + /* Initiate TEST proc.: Send ALIVE and start timer */ + rc = gprs_ns_tx_simple(*nsvc, NS_PDUT_ALIVE); + nsvc_start_timer(*nsvc, NSVC_TIMER_TNS_TEST); + + return rc; +} + static int gprs_ns_rx_block(struct gprs_nsvc *nsvc, struct msgb *msg) { struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; @@ -943,6 +1125,7 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, "from %s for non-existing NS-VC\n", nsh->pdu_type, gprs_ns_ll_str(fallback_nsvc)); fallback_nsvc->nsvci = fallback_nsvc->nsei = 0xfffe; + fallback_nsvc->nsvci_is_valid = 0; fallback_nsvc->state = NSE_S_ALIVE; rc = gprs_ns_tx_status(fallback_nsvc, @@ -1056,18 +1239,7 @@ int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg, rc = gprs_ns_rx_reset(nsvc, msg); break; case NS_PDUT_RESET_ACK: - LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS RESET ACK\n", (*nsvc)->nsei); - /* mark NS-VC as blocked + active */ - (*nsvc)->state = NSE_S_BLOCKED | NSE_S_ALIVE; - (*nsvc)->remote_state = NSE_S_BLOCKED | NSE_S_ALIVE; - rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_BLOCKED]); - if ((*nsvc)->persistent || (*nsvc)->remote_end_is_sgsn) { - /* stop RESET timer */ - osmo_timer_del(&(*nsvc)->timer); - } - /* Initiate TEST proc.: Send ALIVE and start timer */ - rc = gprs_ns_tx_simple(*nsvc, NS_PDUT_ALIVE); - nsvc_start_timer(*nsvc, NSVC_TIMER_TNS_TEST); + rc = gprs_ns_rx_reset_ack(nsvc, msg); break; case NS_PDUT_UNBLOCK: /* Section 7.2: unblocking procedure */ @@ -1322,6 +1494,7 @@ struct gprs_nsvc *gprs_ns_nsip_connect(struct gprs_ns_inst *nsi, nsvc->ip.bts_addr = *dest; nsvc->nsei = nsei; nsvc->nsvci = nsvci; + nsvc->nsvci_is_valid = 1; nsvc->remote_end_is_sgsn = 1; gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION); diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index df7f18b..d2d2825 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -356,6 +356,12 @@ static int test_signal(unsigned int subsys, unsigned int signal, gprs_ns_ll_str(nssd->old_nsvc)); break; + case S_NS_MISMATCH: + printf("==> got signal NS_MISMATCH: 0x%04x/%s pdu=%d, ie=%d\n", + nssd->nsvc->nsvci, gprs_ns_ll_str(nssd->nsvc), + nssd->pdu_type, nssd->ie_type); + break; + default: printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal, nssd->nsvc->nsvci, diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index ddd0b00..b3c3236 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -254,35 +254,21 @@ MESSAGE to BSS, msg length 12 PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 10 01 04 82 10 00 +==> got signal NS_REPLACED: 0x1001/1.2.3.4:1111 -> 0x2001/1.2.3.4:2222 MESSAGE to BSS, msg length 1 0a result (RESET_ACK) = 1 Current NS-VCIs: - VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked - NS-VC Block count : 1 - VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked - NS-VC Block count : 1 + VCI 0x2001, NSEI 0x2000, peer 0x00000000:0 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 2 + NS-VC replaced other count: 1 --- Setup VC 2 SGSN -> BSS (hits NSEI 2) --- -MESSAGE to BSS, msg length 12 -02 00 81 01 01 82 20 01 04 82 20 00 - -PROCESSING RESET_ACK from 0x01020304:1111 -03 01 82 20 01 04 82 20 00 - -MESSAGE to BSS, msg length 1 -0a - -result (RESET_ACK) = 1 - -Current NS-VCIs: - VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked - NS-VC Block count : 1 - VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked - NS-VC Block count : 2 +Failed to send RESET to 0.0.0.0:0 --- Setup VC 1 SGSN -> BSS (hits NSEI 1) --- @@ -298,10 +284,10 @@ MESSAGE to BSS, msg length 1 result (RESET_ACK) = 1 Current NS-VCIs: - VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked - NS-VC Block count : 2 - VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked - NS-VC Block count : 2 + VCI 0x2001, NSEI 0x2000, peer 0x00000000:0 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 3 + NS-VC replaced other count: 1 --- Setup VC 2 BSS -> SGSN --- @@ -310,7 +296,6 @@ Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192) PROCESSING RESET from 0x01020304:1111 02 00 81 01 01 82 20 01 04 82 20 00 -==> got signal NS_REPLACED: 0x2001/1.2.3.4:2222 -> 0x1001/1.2.3.4:1111 ==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 MESSAGE to BSS, msg length 9 03 01 82 20 01 04 82 20 00 @@ -344,61 +329,59 @@ result (ALIVE_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 3 NS-VC replaced other count: 1 - VCI 0x1001, NSEI 0x1000, peer 0x00000000:0, blocked - NS-VC Block count : 2 --- Unexpected RESET_ACK VC 1, BSS -> SGSN --- PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 10 01 04 82 10 00 -MESSAGE to BSS, msg length 15 -08 00 81 0a 02 89 03 01 82 10 01 04 82 10 00 - result (RESET_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 3 NS-VC replaced other count: 1 - VCI 0x1001, NSEI 0x1000, peer 0x00000000:0, blocked - NS-VC Block count : 2 --- RESET_ACK with invalid NSEI, BSS -> SGSN --- +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 10 01 04 82 10 00 + PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 10 01 04 82 f0 00 -MESSAGE to BSS, msg length 15 -08 00 81 0a 02 89 03 01 82 10 01 04 82 f0 00 - -result (RESET_ACK) = 0 +==> got signal NS_MISMATCH: 0x1001/1.2.3.4:2222 pdu=3, ie=4 +result (RESET_ACK) = -22 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 3 NS-VC replaced other count: 1 - VCI 0x1001, NSEI 0x1000, peer 0x00000000:0, blocked - NS-VC Block count : 2 + NSEI was invalid count : 1 --- RESET_ACK with invalid NSVCI, BSS -> SGSN --- +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 10 01 04 82 10 00 + PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 f0 01 04 82 10 00 -MESSAGE to BSS, msg length 15 -08 00 81 0a 02 89 03 01 82 f0 01 04 82 10 00 - -result (RESET_ACK) = 0 +==> got signal NS_MISMATCH: 0x1001/1.2.3.4:2222 pdu=3, ie=1 +result (RESET_ACK) = -22 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 3 NS-VC replaced other count: 1 - VCI 0x1001, NSEI 0x1000, peer 0x00000000:0, blocked - NS-VC Block count : 2 + NS-VCI was invalid count : 1 + NSEI was invalid count : 1 Current NS-VCIs: @@ -456,36 +439,33 @@ Current NS-VCIs: PROCESSING RESET from 0x05060708:32000 02 00 81 01 01 82 01 01 04 82 f0 00 -==> got signal NS_RESET, NS-VC 0x0101/5.6.7.8:32000 +==> got signal NS_MISMATCH: 0x0101/5.6.7.8:32000 pdu=2, ie=4 MESSAGE to SGSN, msg length 9 -03 01 82 01 01 04 82 f0 00 - -MESSAGE to SGSN, msg length 1 -0a +03 01 82 01 01 04 82 01 00 -result (RESET) = 9 +result (RESET) = 0 Current NS-VCIs: - VCI 0x0101, NSEI 0xf000, peer 0x05060708:32000, blocked + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked NS-VC Block count : 1 + NSEI was invalid count : 1 --- RESET with invalid NSVCI, SGSN -> BSS --- PROCESSING RESET from 0x05060708:32000 02 00 81 01 01 82 f0 01 04 82 01 00 -==> got signal NS_RESET, NS-VC 0xf001/5.6.7.8:32000 +==> got signal NS_MISMATCH: 0x0101/5.6.7.8:32000 pdu=2, ie=1 MESSAGE to SGSN, msg length 9 -03 01 82 f0 01 04 82 01 00 - -MESSAGE to SGSN, msg length 1 -0a +03 01 82 01 01 04 82 01 00 -result (RESET) = 9 +result (RESET) = 0 Current NS-VCIs: - VCI 0xf001, NSEI 0x0100, peer 0x05060708:32000, blocked + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked NS-VC Block count : 1 + NS-VCI was invalid count : 1 + NSEI was invalid count : 1 Current NS-VCIs: -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 23:33:19 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 01:33:19 +0200 Subject: [PATCH 1/7] gb/vty: Perform NS-VC operations based on NS-VCI In-Reply-To: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> This adds a 'nsvc nsvci <0-65535> (block|unblock|reset)' vty command. It selects the NS-VC based on the nsvci instead of using the first with a matching NSEI, like it is done when the 'nsei' keyword is used instead. Sponsored-by: On-Waves ehf --- src/gb/gprs_ns_vty.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/gb/gprs_ns_vty.c b/src/gb/gprs_ns_vty.c index a2e7beb..f33fd0b 100644 --- a/src/gb/gprs_ns_vty.c +++ b/src/gb/gprs_ns_vty.c @@ -499,21 +499,29 @@ DEFUN(cfg_frgre_enable, cfg_frgre_enable_cmd, } DEFUN(nsvc_nsei, nsvc_nsei_cmd, - "nsvc nsei <0-65535> (block|unblock|reset)", + "nsvc (nsei|nsvci) <0-65535> (block|unblock|reset)", "Perform an operation on a NSVC\n" "NSEI to identify NS-VC Identifier (NS-VCI)\n" + "NS-VC Identifier (NS-VCI)\n" "The NSEI\n" "Initiate BLOCK procedure\n" "Initiate UNBLOCK procedure\n" "Initiate RESET procedure\n") { - uint16_t nsvci = atoi(argv[0]); - const char *operation = argv[1]; + const char *id_type = argv[0]; + uint16_t id = atoi(argv[1]); + const char *operation = argv[2]; struct gprs_nsvc *nsvc; - nsvc = gprs_nsvc_by_nsei(vty_nsi, nsvci); + if (!strcmp(id_type, "nsei")) + nsvc = gprs_nsvc_by_nsei(vty_nsi, id); + else if (!strcmp(id_type, "nsvci")) + nsvc = gprs_nsvc_by_nsvci(vty_nsi, id); + else + return CMD_WARNING; + if (!nsvc) { - vty_out(vty, "No such NSVCI (%u)%s", nsvci, VTY_NEWLINE); + vty_out(vty, "No such %s (%u)%s", id_type, id, VTY_NEWLINE); return CMD_WARNING; } -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 23:33:20 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 01:33:20 +0200 Subject: [PATCH 2/7] gb/vty: Fix the VTY node string for L_NS_NODE In-Reply-To: <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382571205-24793-2-git-send-email-jerlbeck@sysmocom.de> Use 'config-ns' instead of plain 'ns' and append a blank after the '#' to make the vty python test script work. Sponsored-by: On-Waves ehf --- src/gb/gprs_ns_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gb/gprs_ns_vty.c b/src/gb/gprs_ns_vty.c index f33fd0b..73277f8 100644 --- a/src/gb/gprs_ns_vty.c +++ b/src/gb/gprs_ns_vty.c @@ -71,7 +71,7 @@ static void log_set_nsvc_filter(struct log_target *target, static struct cmd_node ns_node = { L_NS_NODE, - "%s(ns)#", + "%s(config-ns)# ", 1, }; -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 23:33:21 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 01:33:21 +0200 Subject: [PATCH 3/7] gb: Fix gprs_nsvc_delete() to free ctr group In-Reply-To: <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382571205-24793-3-git-send-email-jerlbeck@sysmocom.de> This fixes a SEGV error that happens the next time the statistics are updated. Addresses: Program terminated with signal 11, Segmentation fault. #0 0xb7711fa5 in rate_ctr_group_intv (grp=) at rate_ctr.c:107 107 for (i = 0; i < grp->desc->num_ctr; i++) { #0 0xb7711fa5 in rate_ctr_group_intv (grp=) at rate_ctr.c:107 #1 rate_ctr_timer_cb (data=0x0) at rate_ctr.c:129 #2 0xb770ec59 in osmo_timers_update () at timer.c:243 #3 0xb770ef7a in osmo_select_main (polling=0) at select.c:133 #4 0x08049987 in main (argc=3, argv=0xbfba8084) at gb_proxy_main.c:306 Sponsored-by: On-Waves ehf --- src/gb/gprs_ns.c | 1 + tests/gb/gprs_ns_test.c | 41 ++++++++++++++++++++++ tests/gb/gprs_ns_test.ok | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 6a35ad3..a4a6376 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -210,6 +210,7 @@ void gprs_nsvc_delete(struct gprs_nsvc *nsvc) if (osmo_timer_pending(&nsvc->timer)) osmo_timer_del(&nsvc->timer); llist_del(&nsvc->list); + rate_ctr_group_free(nsvc->ctrg); talloc_free(nsvc); } diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index 38c7d1f..74eb701 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -439,6 +440,45 @@ static void gprs_dump_nsi(struct gprs_ns_inst *nsi) printf("\n"); } +static void test_nsvc() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in peer[1] = {{0},}; + struct gprs_nsvc *nsvc; + int i; + + peer[0].sin_family = AF_INET; + peer[0].sin_port = htons(1111); + peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + + for (i=0; i<4; ++i) { + printf("--- Create via RESET (round %d) ---\n\n", i); + + send_ns_reset(nsi, &peer[0], NS_CAUSE_OM_INTERVENTION, + 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- Delete nsvc object (round %d)---\n\n", i); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x1001); + OSMO_ASSERT(nsvc != NULL); + gprs_nsvc_delete(nsvc); + + gprs_dump_nsi(nsi); + } + + gprs_ns_destroy(nsi); + nsi = NULL; + + printf("--- Process timers ---\n\n"); + /* wait for rate_ctr_timer expiry */ + usleep(1100000); + /* ensure termination */ + alarm(2); + osmo_timers_update(); + alarm(0); +} + static void test_bss_port_changes() { struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); @@ -568,6 +608,7 @@ int main(int argc, char **argv) osmo_signal_register_handler(SS_L_NS, &test_signal, NULL); printf("===== NS protocol test START\n"); + test_nsvc(); test_bss_port_changes(); test_sgsn_output(); printf("===== NS protocol test END\n\n"); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 424d681..b5d578a 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -1,4 +1,90 @@ ===== NS protocol test START +--- Create via RESET (round 0) --- + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + +--- Delete nsvc object (round 0)--- + +Current NS-VCIs: + +--- Create via RESET (round 1) --- + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + +--- Delete nsvc object (round 1)--- + +Current NS-VCIs: + +--- Create via RESET (round 2) --- + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + +--- Delete nsvc object (round 2)--- + +Current NS-VCIs: + +--- Create via RESET (round 3) --- + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + +--- Delete nsvc object (round 3)--- + +Current NS-VCIs: + +--- Process timers --- + --- Setup, send BSSGP RESET --- Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1122(4386), NSEI 0x1122(4386) -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 23:33:22 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 01:33:22 +0200 Subject: [PATCH 4/7] gb: Add test cases for NS RESET procedures In-Reply-To: <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382571205-24793-4-git-send-email-jerlbeck@sysmocom.de> Add a test handling proper and mismatching RESETs. The latter may occur, when ports change within a NS-VC without the SGSN getting notice. This tests for the behavior of the NS protocol stack for RESET and RESET_ACK messages which changing/invalid NSEI and NSVCI like it is being described in 3GPP TS 08.16, 7.3.1. Sponsored-by: On-Waves ehf --- tests/gb/gprs_ns_test.c | 218 +++++++++++++++++++++ tests/gb/gprs_ns_test.ok | 485 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 703 insertions(+) diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index 74eb701..3d0293e 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -533,6 +533,217 @@ static void test_bss_port_changes() nsi = NULL; } +static void test_bss_reset_ack() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in peer[4] = {{0},}; + struct gprs_nsvc *nsvc; + struct sockaddr_in *nse[4]; + int rc; + + peer[0].sin_family = AF_INET; + peer[0].sin_port = htons(1111); + peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + peer[1].sin_family = AF_INET; + peer[1].sin_port = htons(2222); + peer[1].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + peer[2].sin_family = AF_INET; + peer[2].sin_port = htons(3333); + peer[2].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + peer[3].sin_family = AF_INET; + peer[3].sin_port = htons(4444); + peer[3].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + + nse[0] = &peer[0]; + nse[1] = &peer[1]; + + printf("--- Setup VC 1 BSS -> SGSN ---\n\n"); + + setup_ns(nsi, nse[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- Setup VC 2 BSS -> SGSN ---\n\n"); + + setup_ns(nsi, nse[1], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + + printf("--- Setup VC 1 SGSN -> BSS ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x1001); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, nse[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- Exchange NSEI 1 + 2 links ---\n\n"); + + nse[1] = &peer[0]; + nse[0] = &peer[1]; + + printf("--- Setup VC 2 SGSN -> BSS (hits NSEI 1) ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x2001); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, nse[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- Setup VC 2 SGSN -> BSS (hits NSEI 2) ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x2001); + rc = gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + if (rc < 0) + printf("Failed to send RESET to %s\n\n", gprs_ns_ll_str(nsvc)); + else { + send_ns_reset_ack(nsi, nse[1], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + } + + printf("--- Setup VC 1 SGSN -> BSS (hits NSEI 1) ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x1001); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, nse[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- Setup VC 2 BSS -> SGSN ---\n\n"); + + setup_ns(nsi, nse[1], 0x2001, 0x2000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 3rd paragraph. */ + /* This is not rejected because the NSEI has been + * assigned dynamically and not by configuration. + * This is not strictly spec conformant. */ + + printf("--- RESET with invalid NSEI, BSS -> SGSN ---\n\n"); + + send_ns_reset(nsi, nse[0], NS_CAUSE_OM_INTERVENTION, + 0x1001, 0xf000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 2nd paragraph. */ + /* This is not rejected because the NSEI has been + * assigned dynamically and not by configuration. + * This is not strictly spec conformant. */ + + printf("--- RESET with invalid NSVCI, BSS -> SGSN ---\n\n"); + + send_ns_reset(nsi, nse[0], NS_CAUSE_OM_INTERVENTION, + 0xf001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- RESET with old NSEI, NSVCI, BSS -> SGSN ---\n\n"); + + send_ns_reset(nsi, nse[0], NS_CAUSE_OM_INTERVENTION, + 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 5th paragraph. */ + + printf("--- Unexpected RESET_ACK VC 1, BSS -> SGSN ---\n\n"); + + send_ns_reset_ack(nsi, nse[0], 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 4th paragraph. */ + + printf("--- RESET_ACK with invalid NSEI, BSS -> SGSN ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x1001); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, nse[0], 0x1001, 0xf000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 4th paragraph. */ + + printf("--- RESET_ACK with invalid NSVCI, BSS -> SGSN ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x1001); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, nse[0], 0xf001, 0x1000); + gprs_dump_nsi(nsi); + + gprs_ns_destroy(nsi); + nsi = NULL; +} + + +static void test_sgsn_reset() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in sgsn_peer= {0}; + struct gprs_nsvc *nsvc; + + sgsn_peer.sin_family = AF_INET; + sgsn_peer.sin_port = htons(32000); + sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR); + + gprs_dump_nsi(nsi); + + printf("--- Setup SGSN connection, BSS -> SGSN ---\n\n"); + + gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1); + send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); + send_ns_alive_ack(nsi, &sgsn_peer); + send_ns_unblock_ack(nsi, &sgsn_peer); + gprs_dump_nsi(nsi); + + printf("--- RESET, SGSN -> BSS ---\n\n"); + + send_ns_reset(nsi, &sgsn_peer, NS_CAUSE_OM_INTERVENTION, + SGSN_NSEI+1, SGSN_NSEI); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 3rd paragraph. */ + + printf("--- RESET with invalid NSEI, SGSN -> BSS ---\n\n"); + + send_ns_reset(nsi, &sgsn_peer, NS_CAUSE_OM_INTERVENTION, + SGSN_NSEI+1, 0xf000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 2nd paragraph. */ + + printf("--- RESET with invalid NSVCI, SGSN -> BSS ---\n\n"); + + send_ns_reset(nsi, &sgsn_peer, NS_CAUSE_OM_INTERVENTION, + 0xf001, SGSN_NSEI); + gprs_dump_nsi(nsi); + + printf("--- RESET, SGSN -> BSS ---\n\n"); + + send_ns_reset(nsi, &sgsn_peer, NS_CAUSE_OM_INTERVENTION, + SGSN_NSEI+1, SGSN_NSEI); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 5th paragraph. */ + + printf("--- Unexpected RESET_ACK VC 1, BSS -> SGSN ---\n\n"); + + send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 4th paragraph. */ + + printf("--- RESET_ACK with invalid NSEI, BSS -> SGSN ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, SGSN_NSEI+1); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, 0xe000); + gprs_dump_nsi(nsi); + + /* Test 3GPP TS 08.16, 7.3.1, 4th paragraph. */ + + printf("--- RESET_ACK with invalid NSVCI, BSS -> SGSN ---\n\n"); + + nsvc = gprs_nsvc_by_nsvci(nsi, SGSN_NSEI+1); + gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION); + send_ns_reset_ack(nsi, &sgsn_peer, 0xe001, SGSN_NSEI); + gprs_dump_nsi(nsi); + + + gprs_ns_destroy(nsi); + nsi = NULL; +} static void test_sgsn_output() { @@ -607,9 +818,16 @@ int main(int argc, char **argv) log_set_print_filename(osmo_stderr_target, 0); osmo_signal_register_handler(SS_L_NS, &test_signal, NULL); + log_set_print_filename(osmo_stderr_target, 0); + log_set_log_level(osmo_stderr_target, LOGL_INFO); + + setlinebuf(stdout); + printf("===== NS protocol test START\n"); test_nsvc(); test_bss_port_changes(); + test_bss_reset_ack(); + test_sgsn_reset(); test_sgsn_output(); printf("===== NS protocol test END\n\n"); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index b5d578a..96fbd38 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -229,6 +229,491 @@ Current NS-VCIs: NS-VC replaced other count: 1 NS-VC changed NSEI : 2 +--- Setup VC 1 BSS -> SGSN --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + +--- Setup VC 2 BSS -> SGSN --- + +Setup NS-VC: remote 0x01020304:2222, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:2222 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:2222 +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:2222 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:2222 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:2222 +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:2222 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + +--- Setup VC 1 SGSN -> BSS --- + +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 10 01 04 82 10 00 + +PROCESSING RESET_ACK from 0x01020304:1111 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + NS-VC Block count : 1 + +--- Exchange NSEI 1 + 2 links --- + +--- Setup VC 2 SGSN -> BSS (hits NSEI 1) --- + +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 20 01 04 82 20 00 + +PROCESSING RESET_ACK from 0x01020304:2222 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked + NS-VC Block count : 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + NS-VC Block count : 1 + +--- Setup VC 2 SGSN -> BSS (hits NSEI 2) --- + +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 20 01 04 82 20 00 + +PROCESSING RESET_ACK from 0x01020304:1111 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked + NS-VC Block count : 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + NS-VC Block count : 2 + +--- Setup VC 1 SGSN -> BSS (hits NSEI 1) --- + +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 10 01 04 82 10 00 + +PROCESSING RESET_ACK from 0x01020304:2222 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked + NS-VC Block count : 2 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + NS-VC Block count : 2 + +--- Setup VC 2 BSS -> SGSN --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_REPLACED: 0x2001/1.2.3.4:2222 -> 0x1001/1.2.3.4:1111 +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 +MESSAGE to BSS, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x00000000:0, blocked + NS-VC Block count : 2 + +--- RESET with invalid NSEI, BSS -> SGSN --- + +PROCESSING RESET from 0x01020304:2222 +02 00 81 01 01 82 10 01 04 82 f0 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:2222 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 f0 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0xf000, peer 0x01020304:2222, blocked + NS-VC Block count : 2 + NS-VC changed NSEI : 1 + +--- RESET with invalid NSVCI, BSS -> SGSN --- + +PROCESSING RESET from 0x01020304:2222 +02 00 81 01 01 82 f0 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0xf001/1.2.3.4:2222 +MESSAGE to BSS, msg length 9 +03 01 82 f0 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0xf001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 2 + NS-VC changed NSEI : 1 + +--- RESET with old NSEI, NSVCI, BSS -> SGSN --- + +PROCESSING RESET from 0x01020304:2222 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:2222 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 2 + NS-VC changed NSEI : 1 + +--- Unexpected RESET_ACK VC 1, BSS -> SGSN --- + +PROCESSING RESET_ACK from 0x01020304:2222 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 3 + NS-VC changed NSEI : 1 + +--- RESET_ACK with invalid NSEI, BSS -> SGSN --- + +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 10 01 04 82 10 00 + +PROCESSING RESET_ACK from 0x01020304:2222 +03 01 82 10 01 04 82 f0 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 4 + NS-VC changed NSEI : 1 + +--- RESET_ACK with invalid NSVCI, BSS -> SGSN --- + +MESSAGE to BSS, msg length 12 +02 00 81 01 01 82 10 01 04 82 10 00 + +PROCESSING RESET_ACK from 0x01020304:2222 +03 01 82 f0 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC Block count : 2 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 5 + NS-VC changed NSEI : 1 + +Current NS-VCIs: + +--- Setup SGSN connection, BSS -> SGSN --- + +MESSAGE to SGSN, msg length 12 +02 00 81 01 01 82 01 01 04 82 01 00 + +PROCESSING RESET_ACK from 0x05060708:32000 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET_ACK) = 1 + +PROCESSING ALIVE_ACK from 0x05060708:32000 +0b + +MESSAGE to SGSN, msg length 1 +06 + +result (ALIVE_ACK) = 1 + +PROCESSING UNBLOCK_ACK from 0x05060708:32000 +07 + +==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000 +result (UNBLOCK_ACK) = 0 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +--- RESET, SGSN -> BSS --- + +PROCESSING RESET from 0x05060708:32000 +02 00 81 01 01 82 01 01 04 82 01 00 + +==> got signal NS_RESET, NS-VC 0x0101/5.6.7.8:32000 +MESSAGE to SGSN, msg length 9 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked + NS-VC Block count : 1 + +--- RESET with invalid NSEI, SGSN -> BSS --- + +PROCESSING RESET from 0x05060708:32000 +02 00 81 01 01 82 01 01 04 82 f0 00 + +==> got signal NS_RESET, NS-VC 0x0101/5.6.7.8:32000 +MESSAGE to SGSN, msg length 9 +03 01 82 01 01 04 82 f0 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x0101, NSEI 0xf000, peer 0x05060708:32000, blocked + NS-VC Block count : 1 + +--- RESET with invalid NSVCI, SGSN -> BSS --- + +PROCESSING RESET from 0x05060708:32000 +02 00 81 01 01 82 f0 01 04 82 01 00 + +==> got signal NS_RESET, NS-VC 0xf001/5.6.7.8:32000 +MESSAGE to SGSN, msg length 9 +03 01 82 f0 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0xf001, NSEI 0x0100, peer 0x05060708:32000, blocked + NS-VC Block count : 1 + +--- RESET, SGSN -> BSS --- + +PROCESSING RESET from 0x05060708:32000 +02 00 81 01 01 82 01 01 04 82 01 00 + +==> got signal NS_RESET, NS-VC 0x0101/5.6.7.8:32000 +MESSAGE to SGSN, msg length 9 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked + NS-VC Block count : 1 + +--- Unexpected RESET_ACK VC 1, BSS -> SGSN --- + +PROCESSING RESET_ACK from 0x05060708:32000 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked + NS-VC Block count : 2 + +--- RESET_ACK with invalid NSEI, BSS -> SGSN --- + +MESSAGE to SGSN, msg length 12 +02 00 81 01 01 82 01 01 04 82 01 00 + +PROCESSING RESET_ACK from 0x05060708:32000 +03 01 82 01 01 04 82 e0 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked + NS-VC Block count : 3 + +--- RESET_ACK with invalid NSVCI, BSS -> SGSN --- + +MESSAGE to SGSN, msg length 12 +02 00 81 01 01 82 01 01 04 82 01 00 + +PROCESSING RESET_ACK from 0x05060708:32000 +03 01 82 e0 01 04 82 01 00 + +MESSAGE to SGSN, msg length 1 +0a + +result (RESET_ACK) = 1 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked + NS-VC Block count : 4 + Current NS-VCIs: --- Send message to SGSN --- -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 23:33:23 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 01:33:23 +0200 Subject: [PATCH 5/7] gb: Fix NS RESET/RESET_ACK abnormal cases In-Reply-To: <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382571205-24793-5-git-send-email-jerlbeck@sysmocom.de> This changes the implementations for the reception of RESET and RESET_ACK to be compatible with 3GPP TS 08.16, 7.3.1: - Just send a RESET_ACK with correct values back to the SGSN when a RESET with an invalid NSVCI or NSEI has been received. - Check RESET_ACK for matching NSEI and NSVCI. - Ignore unexpected RESET_ACKs. In addition, use RESET_ACK from a BSS to update the BSS source address based on the NSVCI to be tolerant with changing UDP source addresses/ports. Sponsored-by: On-Waves ehf --- include/osmocom/gprs/gprs_ns.h | 5 + src/gb/gprs_ns.c | 271 +++++++++++++++++++++++++++++++--------- tests/gb/gprs_ns_test.c | 6 + tests/gb/gprs_ns_test.ok | 169 ++++++++++--------------- 4 files changed, 294 insertions(+), 157 deletions(-) diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index b28c58d..296800e 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -36,6 +36,7 @@ enum ns_timeout { #define NSE_S_BLOCKED 0x0001 #define NSE_S_ALIVE 0x0002 +#define NSE_S_RESET 0x0004 /*! \brief Osmocom NS link layer types */ enum gprs_ns_ll { @@ -199,12 +200,16 @@ enum signal_ns { S_NS_UNBLOCK, S_NS_ALIVE_EXP, /* Tns-alive expired more than N times */ S_NS_REPLACED, /* nsvc object is replaced (sets old_nsvc) */ + S_NS_MISMATCH, /* got an unexpected IE (sets msg, pdu_type, ie_type) */ }; struct ns_signal_data { struct gprs_nsvc *nsvc; struct gprs_nsvc *old_nsvc; uint8_t cause; + uint8_t pdu_type; + uint8_t ie_type; + struct msgb *msg; }; void gprs_ns_set_log_ss(int ss); diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index a4a6376..a597c2c 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -102,6 +102,8 @@ enum ns_ctr { NS_CTR_DEAD, NS_CTR_REPLACED, NS_CTR_NSEI_CHG, + NS_CTR_INV_VCI, + NS_CTR_INV_NSEI, }; static const struct rate_ctr_desc nsvc_ctr_description[] = { @@ -113,6 +115,8 @@ static const struct rate_ctr_desc nsvc_ctr_description[] = { { "dead", "NS-VC gone dead count " }, { "replaced", "NS-VC replaced other count" }, { "nsei-chg", "NS-VC changed NSEI " }, + { "inv-nsvci", "NS-VCI was invalid count " }, + { "inv-nsei", "NSEI was invalid count " }, }; static const struct rate_ctr_group_desc nsvc_ctrg_desc = { @@ -225,6 +229,20 @@ static void ns_osmo_signal_dispatch(struct gprs_nsvc *nsvc, unsigned int signal, osmo_signal_dispatch(SS_L_NS, signal, &nssd); } +static void ns_osmo_signal_dispatch_mismatch(struct gprs_nsvc *nsvc, + struct msgb *msg, + uint8_t pdu_type, uint8_t ie_type) +{ + struct ns_signal_data nssd = {0}; + + nssd.nsvc = nsvc; + nssd.pdu_type = pdu_type; + nssd.ie_type = ie_type; + nssd.msg = msg; + + osmo_signal_dispatch(SS_L_NS, S_NS_MISMATCH, &nssd); +} + static void ns_osmo_signal_dispatch_replaced(struct gprs_nsvc *nsvc, struct gprs_nsvc *old_nsvc) { struct ns_signal_data nssd = {0}; @@ -323,6 +341,8 @@ int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause) LOGP(DNS, LOGL_INFO, "NSEI=%u Tx NS RESET (NSVCI=%u, cause=%s)\n", nsvc->nsei, nsvc->nsvci, gprs_ns_cause_str(cause)); + nsvc->state |= NSE_S_RESET; + msg->l2h = msgb_put(msg, sizeof(*nsh)); nsh = (struct gprs_ns_hdr *) msg->l2h; nsh->pdu_type = NS_PDUT_RESET; @@ -672,6 +692,49 @@ static int gprs_ns_rx_status(struct gprs_nsvc *nsvc, struct msgb *msg) return 0; } +/* Replace a nsvc object with another based on NSVCI. + * This function replaces looks for a NSVC with the given NSVCI and replaces it + * if possible and necessary. If replaced, the former value of *nsvc is + * returned in *old_nsvc. + * \return != 0 if *nsvc points to a matching NSVC. + */ +static int gprs_nsvc_replace_if_found(uint16_t nsvci, + struct gprs_nsvc **nsvc, + struct gprs_nsvc **old_nsvc) +{ + struct gprs_nsvc *matching_nsvc; + + if ((*nsvc)->nsvci == nsvci) { + *old_nsvc = NULL; + return 1; + } + + matching_nsvc = gprs_nsvc_by_nsvci((*nsvc)->nsi, nsvci); + + if (!matching_nsvc) + return 0; + + /* The NS-VCI is already used by this NS-VC */ + + char *old_peer; + + /* Exchange the NS-VC objects */ + *old_nsvc = *nsvc; + *nsvc = matching_nsvc; + + /* Do logging */ + old_peer = talloc_strdup(*old_nsvc, gprs_ns_ll_str(*old_nsvc)); + LOGP(DNS, LOGL_INFO, "NS-VC changed link (NSVCI=%u) from %s to %s\n", + nsvci, old_peer, gprs_ns_ll_str(*nsvc)); + + talloc_free(old_peer); + + /* Do statistics */ + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_REPLACED]); + + return 1; +} + /* Section 7.3 */ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) { @@ -679,7 +742,7 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) struct tlv_parsed tp; uint8_t cause; uint16_t nsvci, nsei; - struct gprs_nsvc *other_nsvc = NULL; + struct gprs_nsvc *orig_nsvc = NULL; int rc; rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, @@ -706,57 +769,47 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) (*nsvc)->nsvci, (*nsvc)->nsvci_is_valid ? "" : "(invalid)", nsei, nsvci, gprs_ns_cause_str(cause)); - if ((*nsvc)->nsvci_is_valid && (*nsvc)->nsvci != nsvci) { - /* NS-VCI has changed */ - other_nsvc = gprs_nsvc_by_nsvci((*nsvc)->nsi, nsvci); - - if (other_nsvc) { - /* The NS-VCI is already used by this NS-VC */ - - struct gprs_nsvc *tmp_nsvc; - char *old_peer; - - /* Exchange the NS-VC objects */ - tmp_nsvc = *nsvc; - *nsvc = other_nsvc; - other_nsvc = tmp_nsvc; - - /* Do logging */ - old_peer = talloc_strdup(other_nsvc, - gprs_ns_ll_str(other_nsvc)); - LOGP(DNS, LOGL_INFO, - "NS-VC changed link (NSVCI=%u) from %s to %s\n", - nsvci, old_peer, gprs_ns_ll_str(*nsvc)); - - talloc_free(old_peer); - - /* Do statistics */ - rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_REPLACED]); + if (!(*nsvc)->nsvci_is_valid) { + /* It's a new uninitialised NS-VC, nothing to check here */ + } else if ((*nsvc)->nsvci != nsvci) { + if ((*nsvc)->remote_end_is_sgsn) { + /* The incoming RESET doesn't match the NSVCI. Send an + * appropriate RESET_ACK and ignore the RESET. + * See 3GPP TS 08.16, 7.3.1, 2nd paragraph. + */ + ns_osmo_signal_dispatch_mismatch(*nsvc, msg, + NS_PDUT_RESET, + NS_IE_VCI); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_VCI]); + gprs_ns_tx_reset_ack(*nsvc); + return 0; } + + /* NS-VCI has changed */ + gprs_nsvc_replace_if_found(nsvci, nsvc, &orig_nsvc); + + } else if ((*nsvc)->nsei != nsei) { + /* The incoming RESET doesn't match the NSEI. Send an + * appropriate RESET_ACK and ignore the RESET. + * See 3GPP TS 08.16, 7.3.1, 3rd paragraph. + */ + ns_osmo_signal_dispatch_mismatch(*nsvc, msg, + NS_PDUT_RESET, + NS_IE_NSEI); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_NSEI]); + gprs_ns_tx_reset_ack(*nsvc); + return 0; } /* Mark NS-VC as blocked and alive */ (*nsvc)->state = NSE_S_BLOCKED | NSE_S_ALIVE; - if (other_nsvc) { - /* Check NSEI */ - if ((*nsvc)->nsei != nsei) { - LOGP(DNS, LOGL_NOTICE, - "NS-VC changed NSEI (NSVCI=%u) from %u to %u\n", - nsvci, (*nsvc)->nsei, nsei); - - /* Override old NSEI */ - (*nsvc)->nsei = nsei; - - /* Do statistics */ - rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_NSEI_CHG]); - } - - ns_osmo_signal_dispatch_replaced(*nsvc, other_nsvc); + if (orig_nsvc) { + ns_osmo_signal_dispatch_replaced(*nsvc, orig_nsvc); /* Update the ll info fields */ - gprs_ns_ll_copy(*nsvc, other_nsvc); - gprs_ns_ll_clear(other_nsvc); + gprs_ns_ll_copy(*nsvc, orig_nsvc); + gprs_ns_ll_clear(orig_nsvc); } else { (*nsvc)->nsei = nsei; (*nsvc)->nsvci = nsvci; @@ -776,6 +829,121 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) return rc; } +static int gprs_ns_rx_reset_ack(struct gprs_nsvc **nsvc, struct msgb *msg) +{ + struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; + struct tlv_parsed tp; + uint16_t nsvci, nsei; + struct gprs_nsvc *orig_nsvc = NULL; + int rc; + + rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, + msgb_l2len(msg) - sizeof(*nsh), 0, 0); + if (rc < 0) { + LOGP(DNS, LOGL_ERROR, "NSEI=%u Rx NS RESET ACK " + "Error during TLV Parse\n", (*nsvc)->nsei); + return rc; + } + + if (!TLVP_PRESENT(&tp, NS_IE_VCI) || + !TLVP_PRESENT(&tp, NS_IE_NSEI)) { + LOGP(DNS, LOGL_ERROR, "NS RESET ACK Missing mandatory IE\n"); + gprs_ns_tx_status(*nsvc, NS_CAUSE_MISSING_ESSENT_IE, 0, msg); + return -EINVAL; + } + + nsvci = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_VCI)); + nsei = ntohs(*(uint16_t *) TLVP_VAL(&tp, NS_IE_NSEI)); + + LOGP(DNS, LOGL_INFO, "NSVCI=%u%s Rx NS RESET ACK (NSEI=%u, NSVCI=%u)\n", + (*nsvc)->nsvci, (*nsvc)->nsvci_is_valid ? "" : "(invalid)", + nsei, nsvci); + + if (!((*nsvc)->state & NSE_S_RESET)) { + /* Not waiting for a RESET_ACK on this NS-VC, ignore it. + * See 3GPP TS 08.16, 7.3.1, 5th paragraph. + */ + LOGP(DNS, LOGL_ERROR, + "NS RESET ACK Discarding unexpected message for " + "NS-VCI %d from SGSN NSEI=%d\n", + nsvci, nsei); + return 0; + } + + if (!(*nsvc)->nsvci_is_valid) { + LOGP(DNS, LOGL_NOTICE, + "NS RESET ACK Uninitialised NS-VC (%u) for " + "NS-VCI %d, NSEI=%d from %s\n", + (*nsvc)->nsvci, nsvci, nsei, gprs_ns_ll_str(*nsvc)); + return -EINVAL; + } + + if ((*nsvc)->nsvci != nsvci) { + /* NS-VCI has changed */ + + /* if !0, use another NSVC object that matches the NSVCI */ + int use_other_nsvc; + + /* Only do this with BSS peers */ + use_other_nsvc = !(*nsvc)->remote_end_is_sgsn; + + if (use_other_nsvc) + /* Update *nsvc to point to the right NSVC object */ + use_other_nsvc = gprs_nsvc_replace_if_found(nsvci, nsvc, + &orig_nsvc); + + if (!use_other_nsvc) { + /* The incoming RESET_ACK doesn't match the NSVCI. + * See 3GPP TS 08.16, 7.3.1, 4th paragraph. + */ + ns_osmo_signal_dispatch_mismatch(*nsvc, msg, + NS_PDUT_RESET_ACK, + NS_IE_VCI); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_VCI]); + LOGP(DNS, LOGL_ERROR, + "NS RESET ACK Unknown NS-VCI %d (%s NSEI=%d) " + "from %s\n", + nsvci, + (*nsvc)->remote_end_is_sgsn ? "SGSN" : "BSS", + nsei, gprs_ns_ll_str(*nsvc)); + return -EINVAL; + } + + /* Notify others */ + ns_osmo_signal_dispatch_replaced(*nsvc, orig_nsvc); + + /* Update the ll info fields */ + gprs_ns_ll_copy(*nsvc, orig_nsvc); + gprs_ns_ll_clear(orig_nsvc); + } else if ((*nsvc)->nsei != nsei) { + /* The incoming RESET_ACK doesn't match the NSEI. + * See 3GPP TS 08.16, 7.3.1, 4th paragraph. + */ + ns_osmo_signal_dispatch_mismatch(*nsvc, msg, + NS_PDUT_RESET_ACK, + NS_IE_NSEI); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_NSEI]); + LOGP(DNS, LOGL_ERROR, + "NS RESET ACK Unknown NSEI %d (NS-VCI=%u) from %s\n", + nsei, nsvci, gprs_ns_ll_str(*nsvc)); + return -EINVAL; + } + + /* Mark NS-VC as blocked and alive */ + (*nsvc)->state = NSE_S_BLOCKED | NSE_S_ALIVE; + (*nsvc)->remote_state = NSE_S_BLOCKED | NSE_S_ALIVE; + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_BLOCKED]); + if ((*nsvc)->persistent || (*nsvc)->remote_end_is_sgsn) { + /* stop RESET timer */ + osmo_timer_del(&(*nsvc)->timer); + } + /* Initiate TEST proc.: Send ALIVE and start timer */ + rc = gprs_ns_tx_simple(*nsvc, NS_PDUT_ALIVE); + nsvc_start_timer(*nsvc, NSVC_TIMER_TNS_TEST); + + return rc; +} + static int gprs_ns_rx_block(struct gprs_nsvc *nsvc, struct msgb *msg) { struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h; @@ -944,6 +1112,7 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, "from %s for non-existing NS-VC\n", nsh->pdu_type, gprs_ns_ll_str(fallback_nsvc)); fallback_nsvc->nsvci = fallback_nsvc->nsei = 0xfffe; + fallback_nsvc->nsvci_is_valid = 0; fallback_nsvc->state = NSE_S_ALIVE; rc = gprs_ns_tx_status(fallback_nsvc, @@ -1057,18 +1226,7 @@ int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg, rc = gprs_ns_rx_reset(nsvc, msg); break; case NS_PDUT_RESET_ACK: - LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS RESET ACK\n", (*nsvc)->nsei); - /* mark NS-VC as blocked + active */ - (*nsvc)->state = NSE_S_BLOCKED | NSE_S_ALIVE; - (*nsvc)->remote_state = NSE_S_BLOCKED | NSE_S_ALIVE; - rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_BLOCKED]); - if ((*nsvc)->persistent || (*nsvc)->remote_end_is_sgsn) { - /* stop RESET timer */ - osmo_timer_del(&(*nsvc)->timer); - } - /* Initiate TEST proc.: Send ALIVE and start timer */ - rc = gprs_ns_tx_simple(*nsvc, NS_PDUT_ALIVE); - nsvc_start_timer(*nsvc, NSVC_TIMER_TNS_TEST); + rc = gprs_ns_rx_reset_ack(nsvc, msg); break; case NS_PDUT_UNBLOCK: /* Section 7.2: unblocking procedure */ @@ -1323,6 +1481,7 @@ struct gprs_nsvc *gprs_ns_nsip_connect(struct gprs_ns_inst *nsi, nsvc->ip.bts_addr = *dest; nsvc->nsei = nsei; nsvc->nsvci = nsvci; + nsvc->nsvci_is_valid = 1; nsvc->remote_end_is_sgsn = 1; gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION); diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index 3d0293e..546c20a 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -357,6 +357,12 @@ static int test_signal(unsigned int subsys, unsigned int signal, gprs_ns_ll_str(nssd->old_nsvc)); break; + case S_NS_MISMATCH: + printf("==> got signal NS_MISMATCH: 0x%04x/%s pdu=%d, ie=%d\n", + nssd->nsvc->nsvci, gprs_ns_ll_str(nssd->nsvc), + nssd->pdu_type, nssd->ie_type); + break; + default: printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal, nssd->nsvc->nsvci, diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 96fbd38..a882488 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -196,7 +196,7 @@ PROCESSING RESET from 0x01020304:3333 ==> got signal NS_REPLACED: 0x1122/1.2.3.4:4444 -> 0x3344/1.2.3.4:3333 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:3333 MESSAGE to BSS, msg length 9 -03 01 82 11 22 04 82 11 22 +03 01 82 11 22 04 82 33 44 MESSAGE to BSS, msg length 1 0a @@ -205,9 +205,9 @@ result (RESET) = 9 Current NS-VCIs: VCI 0x3344, NSEI 0x1122, peer 0x00000000:0, blocked - VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333, blocked + VCI 0x1122, NSEI 0x3344, peer 0x01020304:3333, blocked NS-VC replaced other count: 1 - NS-VC changed NSEI : 2 + NS-VC changed NSEI : 1 --- Peer port 4444, RESET, NSEI is changed back --- @@ -340,35 +340,21 @@ MESSAGE to BSS, msg length 12 PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 10 01 04 82 10 00 +==> got signal NS_REPLACED: 0x1001/1.2.3.4:1111 -> 0x2001/1.2.3.4:2222 MESSAGE to BSS, msg length 1 0a result (RESET_ACK) = 1 Current NS-VCIs: - VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked - NS-VC Block count : 1 - VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked - NS-VC Block count : 1 + VCI 0x2001, NSEI 0x2000, peer 0x00000000:0 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 2 + NS-VC replaced other count: 1 --- Setup VC 2 SGSN -> BSS (hits NSEI 2) --- -MESSAGE to BSS, msg length 12 -02 00 81 01 01 82 20 01 04 82 20 00 - -PROCESSING RESET_ACK from 0x01020304:1111 -03 01 82 20 01 04 82 20 00 - -MESSAGE to BSS, msg length 1 -0a - -result (RESET_ACK) = 1 - -Current NS-VCIs: - VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked - NS-VC Block count : 1 - VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked - NS-VC Block count : 2 +Failed to send RESET to 0.0.0.0:0 --- Setup VC 1 SGSN -> BSS (hits NSEI 1) --- @@ -384,10 +370,10 @@ MESSAGE to BSS, msg length 1 result (RESET_ACK) = 1 Current NS-VCIs: - VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222, blocked - NS-VC Block count : 2 - VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked - NS-VC Block count : 2 + VCI 0x2001, NSEI 0x2000, peer 0x00000000:0 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 3 + NS-VC replaced other count: 1 --- Setup VC 2 BSS -> SGSN --- @@ -396,7 +382,6 @@ Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192) PROCESSING RESET from 0x01020304:1111 02 00 81 01 01 82 20 01 04 82 20 00 -==> got signal NS_REPLACED: 0x2001/1.2.3.4:2222 -> 0x1001/1.2.3.4:1111 ==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 MESSAGE to BSS, msg length 9 03 01 82 20 01 04 82 20 00 @@ -430,32 +415,27 @@ result (ALIVE_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 3 NS-VC replaced other count: 1 - VCI 0x1001, NSEI 0x1000, peer 0x00000000:0, blocked - NS-VC Block count : 2 --- RESET with invalid NSEI, BSS -> SGSN --- PROCESSING RESET from 0x01020304:2222 02 00 81 01 01 82 10 01 04 82 f0 00 -==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:2222 +==> got signal NS_MISMATCH: 0x1001/1.2.3.4:2222 pdu=2, ie=4 MESSAGE to BSS, msg length 9 -03 01 82 10 01 04 82 f0 00 +03 01 82 10 01 04 82 10 00 -MESSAGE to BSS, msg length 1 -0a - -result (RESET) = 9 +result (RESET) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 3 NS-VC replaced other count: 1 - VCI 0x1001, NSEI 0xf000, peer 0x01020304:2222, blocked - NS-VC Block count : 2 - NS-VC changed NSEI : 1 + NSEI was invalid count : 1 --- RESET with invalid NSVCI, BSS -> SGSN --- @@ -473,11 +453,10 @@ result (RESET) = 9 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 - NS-VC replaced other count: 1 VCI 0xf001, NSEI 0x1000, peer 0x01020304:2222, blocked - NS-VC Block count : 2 - NS-VC changed NSEI : 1 + NS-VC Block count : 3 + NS-VC replaced other count: 1 + NSEI was invalid count : 1 --- RESET with old NSEI, NSVCI, BSS -> SGSN --- @@ -495,29 +474,24 @@ result (RESET) = 9 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 - NS-VC replaced other count: 1 VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked - NS-VC Block count : 2 - NS-VC changed NSEI : 1 + NS-VC Block count : 3 + NS-VC replaced other count: 1 + NSEI was invalid count : 1 --- Unexpected RESET_ACK VC 1, BSS -> SGSN --- PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 10 01 04 82 10 00 -MESSAGE to BSS, msg length 1 -0a - -result (RESET_ACK) = 1 +result (RESET_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 - NS-VC replaced other count: 1 VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked NS-VC Block count : 3 - NS-VC changed NSEI : 1 + NS-VC replaced other count: 1 + NSEI was invalid count : 1 --- RESET_ACK with invalid NSEI, BSS -> SGSN --- @@ -527,18 +501,15 @@ MESSAGE to BSS, msg length 12 PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 10 01 04 82 f0 00 -MESSAGE to BSS, msg length 1 -0a - -result (RESET_ACK) = 1 +==> got signal NS_MISMATCH: 0x1001/1.2.3.4:2222 pdu=3, ie=4 +result (RESET_ACK) = -22 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 - NS-VC replaced other count: 1 VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked - NS-VC Block count : 4 - NS-VC changed NSEI : 1 + NS-VC Block count : 3 + NS-VC replaced other count: 1 + NSEI was invalid count : 2 --- RESET_ACK with invalid NSVCI, BSS -> SGSN --- @@ -548,18 +519,16 @@ MESSAGE to BSS, msg length 12 PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 f0 01 04 82 10 00 -MESSAGE to BSS, msg length 1 -0a - -result (RESET_ACK) = 1 +==> got signal NS_MISMATCH: 0x1001/1.2.3.4:2222 pdu=3, ie=1 +result (RESET_ACK) = -22 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - NS-VC Block count : 2 - NS-VC replaced other count: 1 VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked - NS-VC Block count : 5 - NS-VC changed NSEI : 1 + NS-VC Block count : 3 + NS-VC replaced other count: 1 + NS-VCI was invalid count : 1 + NSEI was invalid count : 2 Current NS-VCIs: @@ -617,36 +586,33 @@ Current NS-VCIs: PROCESSING RESET from 0x05060708:32000 02 00 81 01 01 82 01 01 04 82 f0 00 -==> got signal NS_RESET, NS-VC 0x0101/5.6.7.8:32000 +==> got signal NS_MISMATCH: 0x0101/5.6.7.8:32000 pdu=2, ie=4 MESSAGE to SGSN, msg length 9 -03 01 82 01 01 04 82 f0 00 - -MESSAGE to SGSN, msg length 1 -0a +03 01 82 01 01 04 82 01 00 -result (RESET) = 9 +result (RESET) = 0 Current NS-VCIs: - VCI 0x0101, NSEI 0xf000, peer 0x05060708:32000, blocked + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked NS-VC Block count : 1 + NSEI was invalid count : 1 --- RESET with invalid NSVCI, SGSN -> BSS --- PROCESSING RESET from 0x05060708:32000 02 00 81 01 01 82 f0 01 04 82 01 00 -==> got signal NS_RESET, NS-VC 0xf001/5.6.7.8:32000 +==> got signal NS_MISMATCH: 0x0101/5.6.7.8:32000 pdu=2, ie=1 MESSAGE to SGSN, msg length 9 -03 01 82 f0 01 04 82 01 00 - -MESSAGE to SGSN, msg length 1 -0a +03 01 82 01 01 04 82 01 00 -result (RESET) = 9 +result (RESET) = 0 Current NS-VCIs: - VCI 0xf001, NSEI 0x0100, peer 0x05060708:32000, blocked + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked NS-VC Block count : 1 + NS-VCI was invalid count : 1 + NSEI was invalid count : 1 --- RESET, SGSN -> BSS --- @@ -665,20 +631,21 @@ result (RESET) = 9 Current NS-VCIs: VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked NS-VC Block count : 1 + NS-VCI was invalid count : 1 + NSEI was invalid count : 1 --- Unexpected RESET_ACK VC 1, BSS -> SGSN --- PROCESSING RESET_ACK from 0x05060708:32000 03 01 82 01 01 04 82 01 00 -MESSAGE to SGSN, msg length 1 -0a - -result (RESET_ACK) = 1 +result (RESET_ACK) = 0 Current NS-VCIs: VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked - NS-VC Block count : 2 + NS-VC Block count : 1 + NS-VCI was invalid count : 1 + NSEI was invalid count : 1 --- RESET_ACK with invalid NSEI, BSS -> SGSN --- @@ -688,14 +655,14 @@ MESSAGE to SGSN, msg length 12 PROCESSING RESET_ACK from 0x05060708:32000 03 01 82 01 01 04 82 e0 00 -MESSAGE to SGSN, msg length 1 -0a - -result (RESET_ACK) = 1 +==> got signal NS_MISMATCH: 0x0101/5.6.7.8:32000 pdu=3, ie=4 +result (RESET_ACK) = -22 Current NS-VCIs: VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked - NS-VC Block count : 3 + NS-VC Block count : 1 + NS-VCI was invalid count : 1 + NSEI was invalid count : 2 --- RESET_ACK with invalid NSVCI, BSS -> SGSN --- @@ -705,14 +672,14 @@ MESSAGE to SGSN, msg length 12 PROCESSING RESET_ACK from 0x05060708:32000 03 01 82 e0 01 04 82 01 00 -MESSAGE to SGSN, msg length 1 -0a - -result (RESET_ACK) = 1 +==> got signal NS_MISMATCH: 0x0101/5.6.7.8:32000 pdu=3, ie=1 +result (RESET_ACK) = -22 Current NS-VCIs: VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000, blocked - NS-VC Block count : 4 + NS-VC Block count : 1 + NS-VCI was invalid count : 2 + NSEI was invalid count : 2 Current NS-VCIs: -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 23:33:24 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 01:33:24 +0200 Subject: [PATCH 6/7] gb: Fix RESET handling with changing NSEI In-Reply-To: <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382571205-24793-6-git-send-email-jerlbeck@sysmocom.de> This modifies the NS stack's behavior to accept RESET and RESET_ACK NSEI changes for NS-VC dynamically created by RESET messages from BSSes. This feature is not used for NS-VC configured via VTY or NS-VC to a SGSN. Sponsored-by: On-Waves ehf --- src/gb/gprs_ns.c | 68 +++++++++++++++++++++++++++------------------- tests/gb/gprs_ns_test.ok | 49 ++++++++++++++++++--------------- 2 files changed, 67 insertions(+), 50 deletions(-) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index a597c2c..043a66c 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -114,7 +114,7 @@ static const struct rate_ctr_desc nsvc_ctr_description[] = { { "blocked", "NS-VC Block count " }, { "dead", "NS-VC gone dead count " }, { "replaced", "NS-VC replaced other count" }, - { "nsei-chg", "NS-VC changed NSEI " }, + { "nsei-chg", "NS-VC changed NSEI count " }, { "inv-nsvci", "NS-VCI was invalid count " }, { "inv-nsei", "NSEI was invalid count " }, }; @@ -769,10 +769,8 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) (*nsvc)->nsvci, (*nsvc)->nsvci_is_valid ? "" : "(invalid)", nsei, nsvci, gprs_ns_cause_str(cause)); - if (!(*nsvc)->nsvci_is_valid) { - /* It's a new uninitialised NS-VC, nothing to check here */ - } else if ((*nsvc)->nsvci != nsvci) { - if ((*nsvc)->remote_end_is_sgsn) { + if ((*nsvc)->nsvci_is_valid && (*nsvc)->nsvci != nsvci) { + if ((*nsvc)->persistent || (*nsvc)->remote_end_is_sgsn) { /* The incoming RESET doesn't match the NSVCI. Send an * appropriate RESET_ACK and ignore the RESET. * See 3GPP TS 08.16, 7.3.1, 2nd paragraph. @@ -787,18 +785,25 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) /* NS-VCI has changed */ gprs_nsvc_replace_if_found(nsvci, nsvc, &orig_nsvc); + } - } else if ((*nsvc)->nsei != nsei) { - /* The incoming RESET doesn't match the NSEI. Send an - * appropriate RESET_ACK and ignore the RESET. - * See 3GPP TS 08.16, 7.3.1, 3rd paragraph. - */ - ns_osmo_signal_dispatch_mismatch(*nsvc, msg, - NS_PDUT_RESET, - NS_IE_NSEI); - rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_NSEI]); - gprs_ns_tx_reset_ack(*nsvc); - return 0; + if ((*nsvc)->nsvci_is_valid && (*nsvc)->nsei != nsei) { + if ((*nsvc)->persistent || (*nsvc)->remote_end_is_sgsn) { + /* The incoming RESET doesn't match the NSEI. Send an + * appropriate RESET_ACK and ignore the RESET. + * See 3GPP TS 08.16, 7.3.1, 3rd paragraph. + */ + ns_osmo_signal_dispatch_mismatch(*nsvc, msg, + NS_PDUT_RESET, + NS_IE_NSEI); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_NSEI]); + gprs_ns_tx_reset_ack(*nsvc); + return 0; + } + + /* NSEI has changed */ + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_NSEI_CHG]); + (*nsvc)->nsei = nsei; } /* Mark NS-VC as blocked and alive */ @@ -885,7 +890,8 @@ static int gprs_ns_rx_reset_ack(struct gprs_nsvc **nsvc, struct msgb *msg) int use_other_nsvc; /* Only do this with BSS peers */ - use_other_nsvc = !(*nsvc)->remote_end_is_sgsn; + use_other_nsvc = !(*nsvc)->remote_end_is_sgsn && + !(*nsvc)->persistent; if (use_other_nsvc) /* Update *nsvc to point to the right NSVC object */ @@ -916,17 +922,23 @@ static int gprs_ns_rx_reset_ack(struct gprs_nsvc **nsvc, struct msgb *msg) gprs_ns_ll_copy(*nsvc, orig_nsvc); gprs_ns_ll_clear(orig_nsvc); } else if ((*nsvc)->nsei != nsei) { - /* The incoming RESET_ACK doesn't match the NSEI. - * See 3GPP TS 08.16, 7.3.1, 4th paragraph. - */ - ns_osmo_signal_dispatch_mismatch(*nsvc, msg, - NS_PDUT_RESET_ACK, - NS_IE_NSEI); - rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_NSEI]); - LOGP(DNS, LOGL_ERROR, - "NS RESET ACK Unknown NSEI %d (NS-VCI=%u) from %s\n", - nsei, nsvci, gprs_ns_ll_str(*nsvc)); - return -EINVAL; + if ((*nsvc)->persistent || (*nsvc)->remote_end_is_sgsn) { + /* The incoming RESET_ACK doesn't match the NSEI. + * See 3GPP TS 08.16, 7.3.1, 4th paragraph. + */ + ns_osmo_signal_dispatch_mismatch(*nsvc, msg, + NS_PDUT_RESET_ACK, + NS_IE_NSEI); + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_INV_NSEI]); + LOGP(DNS, LOGL_ERROR, + "NS RESET ACK Unknown NSEI %d (NS-VCI=%u) from %s\n", + nsei, nsvci, gprs_ns_ll_str(*nsvc)); + return -EINVAL; + } + + /* NSEI has changed */ + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_NSEI_CHG]); + (*nsvc)->nsei = nsei; } /* Mark NS-VC as blocked and alive */ diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index a882488..5f90d03 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -186,7 +186,7 @@ result (RESET) = 9 Current NS-VCIs: VCI 0x3344, NSEI 0x1122, peer 0x01020304:3333, blocked VCI 0x1122, NSEI 0x3344, peer 0x01020304:4444, blocked - NS-VC changed NSEI : 1 + NS-VC changed NSEI count : 1 --- Peer port 3333, RESET, VCI is changed back --- @@ -196,7 +196,7 @@ PROCESSING RESET from 0x01020304:3333 ==> got signal NS_REPLACED: 0x1122/1.2.3.4:4444 -> 0x3344/1.2.3.4:3333 ==> got signal NS_RESET, NS-VC 0x1122/1.2.3.4:3333 MESSAGE to BSS, msg length 9 -03 01 82 11 22 04 82 33 44 +03 01 82 11 22 04 82 11 22 MESSAGE to BSS, msg length 1 0a @@ -205,9 +205,9 @@ result (RESET) = 9 Current NS-VCIs: VCI 0x3344, NSEI 0x1122, peer 0x00000000:0, blocked - VCI 0x1122, NSEI 0x3344, peer 0x01020304:3333, blocked + VCI 0x1122, NSEI 0x1122, peer 0x01020304:3333, blocked NS-VC replaced other count: 1 - NS-VC changed NSEI : 1 + NS-VC changed NSEI count : 2 --- Peer port 4444, RESET, NSEI is changed back --- @@ -227,7 +227,7 @@ Current NS-VCIs: VCI 0x3344, NSEI 0x1122, peer 0x00000000:0, blocked VCI 0x1122, NSEI 0x1122, peer 0x01020304:4444, blocked NS-VC replaced other count: 1 - NS-VC changed NSEI : 2 + NS-VC changed NSEI count : 2 --- Setup VC 1 BSS -> SGSN --- @@ -424,18 +424,21 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:2222 02 00 81 01 01 82 10 01 04 82 f0 00 -==> got signal NS_MISMATCH: 0x1001/1.2.3.4:2222 pdu=2, ie=4 +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:2222 MESSAGE to BSS, msg length 9 -03 01 82 10 01 04 82 10 00 +03 01 82 10 01 04 82 f0 00 -result (RESET) = 0 +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked + VCI 0x1001, NSEI 0xf000, peer 0x01020304:2222, blocked NS-VC Block count : 3 NS-VC replaced other count: 1 - NSEI was invalid count : 1 + NS-VC changed NSEI count : 1 --- RESET with invalid NSVCI, BSS -> SGSN --- @@ -456,7 +459,7 @@ Current NS-VCIs: VCI 0xf001, NSEI 0x1000, peer 0x01020304:2222, blocked NS-VC Block count : 3 NS-VC replaced other count: 1 - NSEI was invalid count : 1 + NS-VC changed NSEI count : 2 --- RESET with old NSEI, NSVCI, BSS -> SGSN --- @@ -477,7 +480,7 @@ Current NS-VCIs: VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked NS-VC Block count : 3 NS-VC replaced other count: 1 - NSEI was invalid count : 1 + NS-VC changed NSEI count : 2 --- Unexpected RESET_ACK VC 1, BSS -> SGSN --- @@ -491,7 +494,7 @@ Current NS-VCIs: VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked NS-VC Block count : 3 NS-VC replaced other count: 1 - NSEI was invalid count : 1 + NS-VC changed NSEI count : 2 --- RESET_ACK with invalid NSEI, BSS -> SGSN --- @@ -501,20 +504,22 @@ MESSAGE to BSS, msg length 12 PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 10 01 04 82 f0 00 -==> got signal NS_MISMATCH: 0x1001/1.2.3.4:2222 pdu=3, ie=4 -result (RESET_ACK) = -22 +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked - NS-VC Block count : 3 + VCI 0x1001, NSEI 0xf000, peer 0x01020304:2222, blocked + NS-VC Block count : 4 NS-VC replaced other count: 1 - NSEI was invalid count : 2 + NS-VC changed NSEI count : 3 --- RESET_ACK with invalid NSVCI, BSS -> SGSN --- MESSAGE to BSS, msg length 12 -02 00 81 01 01 82 10 01 04 82 10 00 +02 00 81 01 01 82 10 01 04 82 f0 00 PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 f0 01 04 82 10 00 @@ -524,11 +529,11 @@ result (RESET_ACK) = -22 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked - NS-VC Block count : 3 + VCI 0x1001, NSEI 0xf000, peer 0x01020304:2222, blocked + NS-VC Block count : 4 NS-VC replaced other count: 1 + NS-VC changed NSEI count : 3 NS-VCI was invalid count : 1 - NSEI was invalid count : 2 Current NS-VCIs: -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 23:33:25 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 01:33:25 +0200 Subject: [PATCH 7/7] gb: Create new NSVC object instead of patching the NSVCI In-Reply-To: <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382571205-24793-7-git-send-email-jerlbeck@sysmocom.de> When a RESET is received on the same link with a different NSVCI from a BSS on a dynamically created NS connection do not patch the nsvc object but create a new one instead. Thus the NSVCI is never modified at a nsvc object after the NS-VC has been established. Sponsored-by: On-Waves ehf --- src/gb/gprs_ns.c | 16 ++++++++++++---- tests/gb/gprs_ns_test.c | 5 +++-- tests/gb/gprs_ns_test.ok | 35 +++++++++++++++++++++++++---------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 043a66c..1754501 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -729,9 +729,6 @@ static int gprs_nsvc_replace_if_found(uint16_t nsvci, talloc_free(old_peer); - /* Do statistics */ - rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_REPLACED]); - return 1; } @@ -784,7 +781,16 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) } /* NS-VCI has changed */ - gprs_nsvc_replace_if_found(nsvci, nsvc, &orig_nsvc); + if (!gprs_nsvc_replace_if_found(nsvci, nsvc, &orig_nsvc)) { + LOGP(DNS, LOGL_INFO, "Creating NS-VC %d replacing %d " + "at %s\n", + nsvci, (*nsvc)->nsvci, + gprs_ns_ll_str(*nsvc)); + orig_nsvc = *nsvc; + *nsvc = gprs_nsvc_create((*nsvc)->nsi, nsvci); + (*nsvc)->nsvci_is_valid = 1; + (*nsvc)->nsei = nsei; + } } if ((*nsvc)->nsvci_is_valid && (*nsvc)->nsei != nsei) { @@ -810,6 +816,7 @@ static int gprs_ns_rx_reset(struct gprs_nsvc **nsvc, struct msgb *msg) (*nsvc)->state = NSE_S_BLOCKED | NSE_S_ALIVE; if (orig_nsvc) { + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_REPLACED]); ns_osmo_signal_dispatch_replaced(*nsvc, orig_nsvc); /* Update the ll info fields */ @@ -916,6 +923,7 @@ static int gprs_ns_rx_reset_ack(struct gprs_nsvc **nsvc, struct msgb *msg) } /* Notify others */ + rate_ctr_inc(&(*nsvc)->ctrg->ctr[NS_CTR_REPLACED]); ns_osmo_signal_dispatch_replaced(*nsvc, orig_nsvc); /* Update the ll info fields */ diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index 546c20a..c88792c 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -435,11 +435,12 @@ static void gprs_dump_nsi(struct gprs_ns_inst *nsi) printf("Current NS-VCIs:\n"); llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { struct sockaddr_in *peer = &(nsvc->ip.bts_addr); - printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n", + printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s%s\n", nsvc->nsvci, nsvc->nsei, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port), nsvc->state & NSE_S_BLOCKED ? ", blocked" : "", - nsvc->state & NSE_S_ALIVE ? "" : ", dead" + nsvc->state & NSE_S_ALIVE ? "" : ", dead", + nsvc->nsvci_is_valid ? "" : ", invalid VCI" ); dump_rate_ctr_group(stdout, " ", nsvc->ctrg); } diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 5f90d03..8a61450 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -445,6 +445,7 @@ Current NS-VCIs: PROCESSING RESET from 0x01020304:2222 02 00 81 01 01 82 f0 01 04 82 10 00 +==> got signal NS_REPLACED: 0xf001/0.0.0.0:0 -> 0x1001/1.2.3.4:2222 ==> got signal NS_RESET, NS-VC 0xf001/1.2.3.4:2222 MESSAGE to BSS, msg length 9 03 01 82 f0 01 04 82 10 00 @@ -455,17 +456,20 @@ MESSAGE to BSS, msg length 1 result (RESET) = 9 Current NS-VCIs: - VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 VCI 0xf001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC replaced other count: 1 + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + VCI 0x1001, NSEI 0xf000, peer 0x00000000:0, blocked NS-VC Block count : 3 NS-VC replaced other count: 1 - NS-VC changed NSEI count : 2 + NS-VC changed NSEI count : 1 --- RESET with old NSEI, NSVCI, BSS -> SGSN --- PROCESSING RESET from 0x01020304:2222 02 00 81 01 01 82 10 01 04 82 10 00 +==> got signal NS_REPLACED: 0x1001/0.0.0.0:0 -> 0xf001/1.2.3.4:2222 ==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:2222 MESSAGE to BSS, msg length 9 03 01 82 10 01 04 82 10 00 @@ -476,10 +480,12 @@ MESSAGE to BSS, msg length 1 result (RESET) = 9 Current NS-VCIs: + VCI 0xf001, NSEI 0x1000, peer 0x00000000:0, blocked + NS-VC replaced other count: 1 VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked NS-VC Block count : 3 - NS-VC replaced other count: 1 + NS-VC replaced other count: 2 NS-VC changed NSEI count : 2 --- Unexpected RESET_ACK VC 1, BSS -> SGSN --- @@ -490,10 +496,12 @@ PROCESSING RESET_ACK from 0x01020304:2222 result (RESET_ACK) = 0 Current NS-VCIs: + VCI 0xf001, NSEI 0x1000, peer 0x00000000:0, blocked + NS-VC replaced other count: 1 VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 VCI 0x1001, NSEI 0x1000, peer 0x01020304:2222, blocked NS-VC Block count : 3 - NS-VC replaced other count: 1 + NS-VC replaced other count: 2 NS-VC changed NSEI count : 2 --- RESET_ACK with invalid NSEI, BSS -> SGSN --- @@ -510,10 +518,12 @@ MESSAGE to BSS, msg length 1 result (RESET_ACK) = 1 Current NS-VCIs: + VCI 0xf001, NSEI 0x1000, peer 0x00000000:0, blocked + NS-VC replaced other count: 1 VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 VCI 0x1001, NSEI 0xf000, peer 0x01020304:2222, blocked NS-VC Block count : 4 - NS-VC replaced other count: 1 + NS-VC replaced other count: 2 NS-VC changed NSEI count : 3 --- RESET_ACK with invalid NSVCI, BSS -> SGSN --- @@ -524,16 +534,21 @@ MESSAGE to BSS, msg length 12 PROCESSING RESET_ACK from 0x01020304:2222 03 01 82 f0 01 04 82 10 00 -==> got signal NS_MISMATCH: 0x1001/1.2.3.4:2222 pdu=3, ie=1 -result (RESET_ACK) = -22 +==> got signal NS_REPLACED: 0xf001/0.0.0.0:0 -> 0x1001/1.2.3.4:2222 +MESSAGE to BSS, msg length 1 +0a + +result (RESET_ACK) = 1 Current NS-VCIs: + VCI 0xf001, NSEI 0x1000, peer 0x01020304:2222, blocked + NS-VC Block count : 1 + NS-VC replaced other count: 2 VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 - VCI 0x1001, NSEI 0xf000, peer 0x01020304:2222, blocked + VCI 0x1001, NSEI 0xf000, peer 0x00000000:0, blocked NS-VC Block count : 4 - NS-VC replaced other count: 1 + NS-VC replaced other count: 2 NS-VC changed NSEI count : 3 - NS-VCI was invalid count : 1 Current NS-VCIs: -- 1.7.9.5 From holger at freyther.de Thu Oct 24 07:48:10 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 24 Oct 2013 09:48:10 +0200 Subject: [PATCH 1/7] gb/vty: Perform NS-VC operations based on NS-VCI In-Reply-To: <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <20131024074810.GB17434@xiaoyu.lan> On Thu, Oct 24, 2013 at 01:33:19AM +0200, Jacob Erlbeck wrote: Hi, I had just merged all your previous changes. How is this patchset different to the one posted on tuesday? I see that patch 1 has some minor modifications in the print statement and two more patches were added? holger From jerlbeck at sysmocom.de Thu Oct 24 07:56:07 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 09:56:07 +0200 Subject: [PATCH 1/7] gb/vty: Perform NS-VC operations based on NS-VCI In-Reply-To: <20131024074810.GB17434@xiaoyu.lan> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> <1382571205-24793-1-git-send-email-jerlbeck@sysmocom.de> <20131024074810.GB17434@xiaoyu.lan> Message-ID: <5268D297.6090506@sysmocom.de> On 10/24/2013 09:48 AM, Holger Hans Peter Freyther wrote: > On Thu, Oct 24, 2013 at 01:33:19AM +0200, Jacob Erlbeck wrote: > I had just merged all your previous changes. How is this patchset > different to the one posted on tuesday? I see that patch 1 has > some minor modifications in the print statement and two more patches > were added? I've slightly reordered them, merged the two commits extending the RESET test and separated the RESET fixes into spec-related and relaxed handling of NSEI changes. Jacob From holger at freyther.de Thu Oct 24 05:31:56 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 24 Oct 2013 07:31:56 +0200 Subject: [PATCH 1/3] gb/vty: Perform NS-VC operations based on NS-VCI In-Reply-To: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> References: <1382437361-23284-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <20131024053156.GA30417@xiaoyu.lan> On Tue, Oct 22, 2013 at 12:22:39PM +0200, Jacob Erlbeck wrote: Good Morning Jacob! as usual, the patch looks good! > - nsvc = gprs_nsvc_by_nsei(vty_nsi, nsvci); > + if (!strcmp(id_type, "nsei")) > + nsvc = gprs_nsvc_by_nsei(vty_nsi, id); > + else if (!strcmp(id_type, "nsvci")) > + nsvc = gprs_nsvc_by_nsvci(vty_nsi, id); > + else > + return CMD_WARNING; the VTY will make sure that id_type is either nsei or nsvc. So we can omit the else path. In case you want to keep the else path. I think we should a vty_out with a warning that the given id_type does not exist. I will modify this locally. From jerlbeck at sysmocom.de Tue Oct 22 12:52:27 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 22 Oct 2013 14:52:27 +0200 Subject: [PATCH] gb/vty: Fix the VTY node string for L_NS_NODE Message-ID: <1382446347-27263-1-git-send-email-jerlbeck@sysmocom.de> Use 'config-ns' instead of plain 'ns' and append a blank after the '#' to make the vty python test script work. Sponsored-by: On-Waves ehf --- src/gb/gprs_ns_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gb/gprs_ns_vty.c b/src/gb/gprs_ns_vty.c index f33fd0b..73277f8 100644 --- a/src/gb/gprs_ns_vty.c +++ b/src/gb/gprs_ns_vty.c @@ -71,7 +71,7 @@ static void log_set_nsvc_filter(struct log_target *target, static struct cmd_node ns_node = { L_NS_NODE, - "%s(ns)#", + "%s(config-ns)# ", 1, }; -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 08:59:17 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Wed, 23 Oct 2013 10:59:17 +0200 Subject: [PATCH] gb: Fix gprs_nsvc_delete() to free ctr group Message-ID: <1382518757-17924-1-git-send-email-jerlbeck@sysmocom.de> This fixes a SEGV error that happens the next time the statistics are updated. Addresses: Program terminated with signal 11, Segmentation fault. #0 0xb7711fa5 in rate_ctr_group_intv (grp=) at rate_ctr.c:107 107 for (i = 0; i < grp->desc->num_ctr; i++) { #0 0xb7711fa5 in rate_ctr_group_intv (grp=) at rate_ctr.c:107 #1 rate_ctr_timer_cb (data=0x0) at rate_ctr.c:129 #2 0xb770ec59 in osmo_timers_update () at timer.c:243 #3 0xb770ef7a in osmo_select_main (polling=0) at select.c:133 #4 0x08049987 in main (argc=3, argv=0xbfba8084) at gb_proxy_main.c:306 Sponsored-by: On-Waves ehf --- src/gb/gprs_ns.c | 1 + tests/gb/gprs_ns_test.c | 43 +++++++++++++++++++++++ tests/gb/gprs_ns_test.ok | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index b50a700..d71707b 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -215,6 +215,7 @@ void gprs_nsvc_delete(struct gprs_nsvc *nsvc) if (osmo_timer_pending(&nsvc->timer)) osmo_timer_del(&nsvc->timer); llist_del(&nsvc->list); + rate_ctr_group_free(nsvc->ctrg); talloc_free(nsvc); } diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index d2d2825..f8a1f27 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -445,6 +446,45 @@ static void gprs_dump_nsi(struct gprs_ns_inst *nsi) printf("\n"); } +static void test_nsvc() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in peer[1] = {{0},}; + struct gprs_nsvc *nsvc; + int i; + + peer[0].sin_family = AF_INET; + peer[0].sin_port = htons(1111); + peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + + for (i=0; i<4; ++i) { + printf("--- Create via RESET (round %d) ---\n\n", i); + + send_ns_reset(nsi, &peer[0], NS_CAUSE_OM_INTERVENTION, + 0x1001, 0x1000); + gprs_dump_nsi(nsi); + + printf("--- Delete nsvc object (round %d)---\n\n", i); + + nsvc = gprs_nsvc_by_nsvci(nsi, 0x1001); + OSMO_ASSERT(nsvc != NULL); + gprs_nsvc_delete(nsvc); + + gprs_dump_nsi(nsi); + } + + gprs_ns_destroy(nsi); + nsi = NULL; + + printf("--- Process timers ---\n\n"); + /* wait for rate_ctr_timer expiry */ + usleep(1100000); + /* ensure termination */ + alarm(2); + osmo_timers_update(); + alarm(0); +} + static void test_bss_port_changes() { struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); @@ -726,9 +766,12 @@ int main(int argc, char **argv) log_set_print_filename(osmo_stderr_target, 0); log_set_log_level(osmo_stderr_target, LOGL_INFO); + rate_ctr_init(NULL); + setlinebuf(stdout); printf("===== NS protocol test START\n"); + test_nsvc(); test_bss_port_changes(); test_bss_reset_ack(); test_sgsn_reset(); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index b3c3236..1566824 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -1,4 +1,90 @@ ===== NS protocol test START +--- Create via RESET (round 0) --- + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + +--- Delete nsvc object (round 0)--- + +Current NS-VCIs: + +--- Create via RESET (round 1) --- + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + +--- Delete nsvc object (round 1)--- + +Current NS-VCIs: + +--- Create via RESET (round 2) --- + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + +--- Delete nsvc object (round 2)--- + +Current NS-VCIs: + +--- Create via RESET (round 3) --- + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 +MESSAGE to BSS, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS, msg length 1 +0a + +result (RESET) = 9 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111, blocked + +--- Delete nsvc object (round 3)--- + +Current NS-VCIs: + +--- Process timers --- + --- Setup, send BSSGP RESET --- Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1122(4386), NSEI 0x1122(4386) -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 09:24:14 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Wed, 23 Oct 2013 11:24:14 +0200 Subject: [PATCH 1/5] vty: Fix whitespace in test script Message-ID: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> Expands leading tabs and removes trailing whitespace. Sponsored-by: On-Waves ehf --- openbsc/src/gprs/gb_proxy.c | 1 - openbsc/tests/vty_test_runner.py | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index dea6e3f..d075578 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -204,7 +204,6 @@ static struct gbprox_peer *peer_alloc(uint16_t bvci) return peer; } -static void peer_free(struct gbprox_peer *peer) __attribute__((__unused__)); static void peer_free(struct gbprox_peer *peer) { llist_del(&peer->list); diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 0bd7972..09352b8 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -72,7 +72,7 @@ class TestVTYGenericBSC(TestVTYBase): try: self.checkForEndAndExit() except BaseException as e: - sys.stderr.write('Expected and ignored failure: %s\n' % (str(e))) + sys.stderr.write('Expected and ignored failure: %s\n' % (str(e))) def _testConfigNetworkTree(self): self.vty.enable() @@ -118,7 +118,7 @@ class TestVTYNITB(TestVTYGenericBSC): return (4242, "./src/osmo-nitb/osmo-nitb", "OpenBSC", "nitb") def testConfigNetworkTree(self): - self._testConfigNetworkTree() + self._testConfigNetworkTree() def checkForSmpp(self): """SMPP is not always enabled, check if it is""" @@ -137,10 +137,10 @@ class TestVTYNITB(TestVTYGenericBSC): if self.checkForSmpp(): self.assertEquals(self.vty.node(), 'config') - self.assertTrue(self.vty.verify('smpp', [''])) - self.assertEquals(self.vty.node(), 'config-smpp') - self.ignoredCheckForEndAndExit() - self.assertTrue(self.vty.verify("exit", [''])) + self.assertTrue(self.vty.verify('smpp', [''])) + self.assertEquals(self.vty.node(), 'config-smpp') + self.ignoredCheckForEndAndExit() + self.assertTrue(self.vty.verify("exit", [''])) self.assertEquals(self.vty.node(), 'config') self.assertTrue(self.vty.verify("exit", [''])) @@ -241,7 +241,7 @@ class TestVTYBSC(TestVTYGenericBSC): return (4242, "./src/osmo-bsc/osmo-bsc", "OsmoBSC", "bsc") def testConfigNetworkTree(self): - self._testConfigNetworkTree() + self._testConfigNetworkTree() def testVtyTree(self): self.vty.enable() -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 09:24:15 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Wed, 23 Oct 2013 11:24:15 +0200 Subject: [PATCH 2/5] gbproxy: Add basic VTY tests In-Reply-To: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> References: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382520258-30733-2-git-send-email-jerlbeck@sysmocom.de> This checks for the ns and gbproxy config nodes and show commands. Sponsored-by: On-Waves ehf --- openbsc/tests/vty_test_runner.py | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 09352b8..e040cac 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -495,6 +495,38 @@ class TestVTYNAT(TestVTYGenericBSC): res = self.vty.verify("show ussd-connection", ['The USSD side channel provider is not connected and not authorized.']) self.assertTrue(res) +class TestVTYGbproxy(TestVTYGenericBSC): + + def vty_command(self): + return ["./src/gprs/osmo-gbproxy", "-c", + "doc/examples/osmo-gbproxy/osmo-gbproxy.cfg"] + + def vty_app(self): + return (4246, "./src/gprs/osmo-gbproxy", "OsmoGbProxy", "bsc") + + def testVtyTree(self): + self.vty.enable() + self.assertTrue(self.vty.verify('configure terminal', [''])) + self.assertEquals(self.vty.node(), 'config') + self.ignoredCheckForEndAndExit() + self.assertTrue(self.vty.verify('ns', [''])) + self.assertEquals(self.vty.node(), 'config-ns') + self.checkForEndAndExit() + self.assertTrue(self.vty.verify('exit', [''])) + self.assertEquals(self.vty.node(), 'config') + self.assertTrue(self.vty.verify('gbproxy', [''])) + self.assertEquals(self.vty.node(), 'config-gbproxy') + self.checkForEndAndExit() + self.assertTrue(self.vty.verify('exit', [''])) + self.assertEquals(self.vty.node(), 'config') + + def testVtyShow(self): + res = self.vty.command("show ns") + self.assert_(res.find('Encapsulation NS-UDP-IP') >= 0) + + res = self.vty.command("show gbproxy stats") + self.assert_(res.find('GBProxy Global Statistics') >= 0) + def add_nat_test(suite, workdir): if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc_nat/osmo-bsc_nat")): print("Skipping the NAT test") @@ -509,6 +541,13 @@ def add_bsc_test(suite, workdir): test = unittest.TestLoader().loadTestsFromTestCase(TestVTYBSC) suite.addTest(test) +def add_gbproxy_test(suite, workdir): + if not os.path.isfile(os.path.join(workdir, "src/gprs/osmo-gbproxy")): + print("Skipping the Gb-Proxy test") + return + test = unittest.TestLoader().loadTestsFromTestCase(TestVTYGbproxy) + suite.addTest(test) + if __name__ == '__main__': import argparse import sys @@ -541,5 +580,6 @@ if __name__ == '__main__': suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestVTYNITB)) add_bsc_test(suite, workdir) add_nat_test(suite, workdir) + add_gbproxy_test(suite, workdir) res = unittest.TextTestRunner(verbosity=verbose_level).run(suite) sys.exit(len(res.errors) + len(res.failures)) -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 09:24:16 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Wed, 23 Oct 2013 11:24:16 +0200 Subject: [PATCH 3/5] gbproxy: Fix rate counter group leak in peer_free() In-Reply-To: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> References: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382520258-30733-3-git-send-email-jerlbeck@sysmocom.de> This also frees the counter group pointed to by peer->ctrg when the peer gets freed. Sponsored-by: On-Waves ehf --- openbsc/src/gprs/gb_proxy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index d075578..d5872a9 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -206,6 +206,7 @@ static struct gbprox_peer *peer_alloc(uint16_t bvci) static void peer_free(struct gbprox_peer *peer) { + rate_ctr_group_free(peer->ctrg); llist_del(&peer->list); talloc_free(peer); } -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 09:24:17 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Wed, 23 Oct 2013 11:24:17 +0200 Subject: [PATCH 4/5] gbproxy: Add a command to delete peers from the GBProxy In-Reply-To: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> References: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382520258-30733-4-git-send-email-jerlbeck@sysmocom.de> From: Holger Hans Peter Freyther This just deletes the peer entry based on NSEI and BVCI. The NS-VC are not touched. --- openbsc/include/openbsc/gb_proxy.h | 1 + openbsc/src/gprs/gb_proxy.c | 26 +++++++++++++++++++++++++- openbsc/src/gprs/gb_proxy_vty.c | 2 ++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 7b14a09..e51dd47 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -17,6 +17,7 @@ struct gbproxy_config { extern struct gbproxy_config gbcfg; extern struct cmd_element show_gbproxy_cmd; +extern struct cmd_element delete_gb_cmd; /* gb_proxy_vty .c */ diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index d5872a9..a7640f0 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -1,7 +1,8 @@ /* NS-over-IP proxy */ /* (C) 2010 by Harald Welte - * (C) 2010 by On-Waves + * (C) 2010-2013 by On-Waves + * (C) 2013 by Holger Hans Peter Freyther * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -909,3 +910,26 @@ gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", } return CMD_SUCCESS; } + +gDEFUN(delete_gb, delete_gb_cmd, + "delete-gbproxy-peer <0-65534> bvci <0-65534>", + "Delete a GBProxy peer by NSEI and BVCI\n" + "NSEI number\n" + "BVCI\n" + "BVCI number\n") +{ + struct gbprox_peer *peer, *tmp; + const uint16_t nsei = atoi(argv[0]); + const uint16_t bvci = atoi(argv[1]); + + llist_for_each_entry_safe(peer, tmp, &gbprox_bts_peers, list) { + if (peer->bvci != bvci) + continue; + if (peer->nsei != nsei) + continue; + + peer_free(peer); + } + + return CMD_SUCCESS; +} diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c index 63546d3..176ea65 100644 --- a/openbsc/src/gprs/gb_proxy_vty.c +++ b/openbsc/src/gprs/gb_proxy_vty.c @@ -80,6 +80,8 @@ int gbproxy_vty_init(void) { install_element_ve(&show_gbproxy_cmd); + install_element(ENABLE_NODE, &delete_gb_cmd); + install_element(CONFIG_NODE, &cfg_gbproxy_cmd); install_node(&gbproxy_node, config_write_gbproxy); bsc_install_default(GBPROXY_NODE); -- 1.7.9.5 From jerlbeck at sysmocom.de Wed Oct 23 09:24:18 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Wed, 23 Oct 2013 11:24:18 +0200 Subject: [PATCH 5/5] gbproxy/vty: Enhance delete-gbproxy-peer command In-Reply-To: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> References: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382520258-30733-5-git-send-email-jerlbeck@sysmocom.de> This adds the option to delete all BVC peers and/or NS_VC with a given NSEI with a single command. Static (configured) NS-VC are not affected. In addition, all connections for this NSEI that can be deleted by this command can be listed without deleting them. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 3 +- openbsc/src/gprs/gb_proxy.c | 155 +++++++++++++++++++++++++++++++----- openbsc/src/gprs/gb_proxy_vty.c | 3 +- openbsc/tests/vty_test_runner.py | 10 +++ 4 files changed, 147 insertions(+), 24 deletions(-) diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index e51dd47..c2c9092 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -17,7 +17,8 @@ struct gbproxy_config { extern struct gbproxy_config gbcfg; extern struct cmd_element show_gbproxy_cmd; -extern struct cmd_element delete_gb_cmd; +extern struct cmd_element delete_gb_bvci_cmd; +extern struct cmd_element delete_gb_nsei_cmd; /* gb_proxy_vty .c */ diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index a7640f0..7897baf 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -881,8 +881,63 @@ int gbprox_dump_peers(FILE *stream, int indent, int verbose) return 0; } +static int gbprox_cleanup_peers(uint16_t nsei, uint16_t bvci) +{ + int counter = 0; + struct gbprox_peer *peer, *tmp; + + llist_for_each_entry_safe(peer, tmp, &gbprox_bts_peers, list) { + if (peer->nsei != nsei) + continue; + if (bvci && peer->bvci != bvci) + continue; + + peer_free(peer); + counter += 1; + } + + return counter; +} + +static int gbprox_cleanup_nsvcs_by_nsei(uint16_t nsei) +{ + int counter = 0; + struct gprs_ns_inst *nsi = gbcfg.nsi; + struct gprs_nsvc *nsvc, *nsvc2; + + /* delete all matching NSVCs and clear their timers */ + llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) { + if (nsvc->nsei != nsei) + continue; + + /* skip explicitely configured connections */ + if (nsvc->persistent) + continue; + + gprs_nsvc_delete(nsvc); + counter += 1; + } + + return counter; +} + #include +static void gbprox_vty_print_peer(struct vty *vty, struct gbprox_peer *peer) +{ + struct gprs_ra_id raid; + gsm48_parse_ra(&raid, peer->ra); + + vty_out(vty, "NSEI %5u, PTP-BVCI %5u, " + "RAC %u-%u-%u-%u", + peer->nsei, peer->bvci, + raid.mcc, raid.mnc, raid.lac, raid.rac); + if (peer->blocked) + vty_out(vty, " [BVC-BLOCKED]"); + + vty_out(vty, "%s", VTY_NEWLINE); +} + gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", SHOW_STR "Display information about the Gb proxy") { @@ -893,17 +948,7 @@ gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", vty_out_rate_ctr_group(vty, "", get_global_ctrg()); llist_for_each_entry(peer, &gbprox_bts_peers, list) { - struct gprs_ra_id raid; - gsm48_parse_ra(&raid, peer->ra); - - vty_out(vty, "NSEI %5u, PTP-BVCI %5u, " - "RAC %u-%u-%u-%u", - peer->nsei, peer->bvci, - raid.mcc, raid.mnc, raid.lac, raid.rac); - if (peer->blocked) - vty_out(vty, " [BVC-BLOCKED]"); - - vty_out(vty, "%s", VTY_NEWLINE); + gbprox_vty_print_peer(vty, peer); if (show_stats) vty_out_rate_ctr_group(vty, " ", peer->ctrg); @@ -911,24 +956,90 @@ gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", return CMD_SUCCESS; } -gDEFUN(delete_gb, delete_gb_cmd, - "delete-gbproxy-peer <0-65534> bvci <0-65534>", - "Delete a GBProxy peer by NSEI and BVCI\n" +gDEFUN(delete_gb_bvci, delete_gb_bvci_cmd, + "delete-gbproxy-peer <0-65534> bvci <2-65534>", + "Delete a GBProxy peer by NSEI and optionally BVCI\n" "NSEI number\n" - "BVCI\n" + "Only delete peer with a matching BVCI\n" "BVCI number\n") { - struct gbprox_peer *peer, *tmp; const uint16_t nsei = atoi(argv[0]); const uint16_t bvci = atoi(argv[1]); + int counter; - llist_for_each_entry_safe(peer, tmp, &gbprox_bts_peers, list) { - if (peer->bvci != bvci) - continue; - if (peer->nsei != nsei) - continue; + counter = gbprox_cleanup_peers(nsei, bvci); - peer_free(peer); + if (counter == 0) { + vty_out(vty, "BVC not found%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +gDEFUN(delete_gb_nsei, delete_gb_nsei_cmd, + "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all|show)", + "Delete a GBProxy peer by NSEI and optionally BVCI\n" + "NSEI number\n" + "Only delete BSSGP connections (BVC)\n" + "Only delete dynamic NS connections (NS-VC)\n" + "Delete BVC and dynamic NS connections\n" + "Show all BVC and dynamic NS connections (don't delete)\n" + ) +{ + const uint16_t nsei = atoi(argv[0]); + const char *mode = argv[1]; + int delete_bvc = 0; + int delete_nsvc = 0; + int counter; + + if (strcmp(mode, "bvc-only") == 0) + delete_bvc = 1; + else if (strcmp(mode, "nsvc-only") == 0) + delete_nsvc = 1; + else if (strcmp(mode, "all") == 0) + delete_bvc = delete_nsvc = 1; + else { + struct gbprox_peer *peer; + struct gprs_ns_inst *nsi = gbcfg.nsi; + struct gprs_nsvc *nsvc; + + counter = 0; + llist_for_each_entry(peer, &gbprox_bts_peers, list) { + if (peer->nsei != nsei) + continue; + + vty_out(vty, "BVC: "); + gbprox_vty_print_peer(vty, peer); + counter += 1; + } + vty_out(vty, "Found %d BVC%s", counter, VTY_NEWLINE); + + counter = 0; + llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { + if (nsvc->nsei != nsei) + continue; + if (nsvc->persistent) + continue; + + vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, remote %s%s", + nsvc->nsei, nsvc->nsvci, + gprs_ns_ll_str(nsvc), VTY_NEWLINE); + counter += 1; + } + vty_out(vty, "Found %d NS-VC%s", counter, VTY_NEWLINE); + + return CMD_SUCCESS; + } + + if (delete_bvc) { + counter = gbprox_cleanup_peers(nsei, 0); + vty_out(vty, "Deleted %d BVC%s", counter, VTY_NEWLINE); + } + + if (delete_nsvc) { + counter = gbprox_cleanup_nsvcs_by_nsei(nsei); + vty_out(vty, "Deleted %d NS-VC%s", counter, VTY_NEWLINE); } return CMD_SUCCESS; diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c index 176ea65..82d49ca 100644 --- a/openbsc/src/gprs/gb_proxy_vty.c +++ b/openbsc/src/gprs/gb_proxy_vty.c @@ -80,7 +80,8 @@ int gbproxy_vty_init(void) { install_element_ve(&show_gbproxy_cmd); - install_element(ENABLE_NODE, &delete_gb_cmd); + install_element(ENABLE_NODE, &delete_gb_bvci_cmd); + install_element(ENABLE_NODE, &delete_gb_nsei_cmd); install_element(CONFIG_NODE, &cfg_gbproxy_cmd); install_node(&gbproxy_node, config_write_gbproxy); diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index e040cac..b5f39fe 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -527,6 +527,16 @@ class TestVTYGbproxy(TestVTYGenericBSC): res = self.vty.command("show gbproxy stats") self.assert_(res.find('GBProxy Global Statistics') >= 0) + def testVtyDeletePeer(self): + self.vty.enable() + self.assertTrue(self.vty.verify('delete-gbproxy-peer 9999 bvci 7777', ['BVC not found'])) + res = self.vty.command("delete-gbproxy-peer 9999 show") + self.assert_(res.find('Found 0 BVC') >= 0) + self.assert_(res.find('Found 0 NS-VC') >= 0) + res = self.vty.command("delete-gbproxy-peer 9999 all") + self.assert_(res.find('Deleted 0 BVC') >= 0) + self.assert_(res.find('Deleted 0 NS-VC') >= 0) + def add_nat_test(suite, workdir): if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc_nat/osmo-bsc_nat")): print("Skipping the NAT test") -- 1.7.9.5 From holger at freyther.de Thu Oct 24 06:28:55 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 24 Oct 2013 08:28:55 +0200 Subject: [PATCH 5/5] gbproxy/vty: Enhance delete-gbproxy-peer command In-Reply-To: <1382520258-30733-5-git-send-email-jerlbeck@sysmocom.de> References: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> <1382520258-30733-5-git-send-email-jerlbeck@sysmocom.de> Message-ID: <20131024062855.GC30417@xiaoyu.lan> On Wed, Oct 23, 2013 at 11:24:18AM +0200, Jacob Erlbeck wrote: All patches look fine but the semantic is odd here > +gDEFUN(delete_gb_bvci, delete_gb_bvci_cmd, > + "delete-gbproxy-peer <0-65534> bvci <2-65534>", > + "Delete a GBProxy peer by NSEI and optionally BVCI\n" > "NSEI number\n" > - "BVCI\n" > + "Only delete peer with a matching BVCI\n" > "BVCI number\n") delete-gbproxy-peer 1 bvci 3 show. Better either improve the existing show command or create a new one. :) From jerlbeck at sysmocom.de Thu Oct 24 07:48:21 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 09:48:21 +0200 Subject: [PATCH 5/5] gbproxy/vty: Enhance delete-gbproxy-peer command In-Reply-To: <20131024062855.GC30417@xiaoyu.lan> References: <1382520258-30733-1-git-send-email-jerlbeck@sysmocom.de> <1382520258-30733-5-git-send-email-jerlbeck@sysmocom.de> <20131024062855.GC30417@xiaoyu.lan> Message-ID: <5268D0C5.60707@sysmocom.de> Hi, On 10/24/2013 08:28 AM, Holger Hans Peter Freyther wrote: > On Wed, Oct 23, 2013 at 11:24:18AM +0200, Jacob Erlbeck wrote: > > All patches look fine but the semantic is odd here > >> +gDEFUN(delete_gb_bvci, delete_gb_bvci_cmd, >> + "delete-gbproxy-peer <0-65534> bvci <2-65534>", >> + "Delete a GBProxy peer by NSEI and optionally BVCI\n" >> "NSEI number\n" >> - "BVCI\n" >> + "Only delete peer with a matching BVCI\n" >> "BVCI number\n") > > > delete-gbproxy-peer 1 bvci 3 show. Better either improve the > existing show command or create a new one. :) I expected this remark ;-) I'm not really happy with this either. I had something in mind like a dry-run option. I decided against an additional show command since this 'show' is tightly coupled to the peer selection of the 'delete-gbproxy-peer'. That's less obvious, when a different command is used. What do you think about an optional final '[dry-run]' instead of the 'show'? Jacob From jerlbeck at sysmocom.de Thu Oct 24 10:48:23 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 12:48:23 +0200 Subject: [PATCH] gbproxy/vty: Enhance delete-gbproxy-peer command In-Reply-To: <1382520258-30733-5-git-send-email-jerlbeck@sysmocom.de> References: <1382520258-30733-5-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382611703-17122-1-git-send-email-jerlbeck@sysmocom.de> This adds the option to delete all BVC peers and/or NS_VC with a given NSEI with a single command. Static (configured) NS-VC are not affected. In addition, all connections for this NSEI that can be deleted by this command can be listed without deleting them by appending 'dry-run' to the command. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 3 +- openbsc/src/gprs/gb_proxy.c | 135 ++++++++++++++++++++++++++++++------ openbsc/src/gprs/gb_proxy_vty.c | 3 +- openbsc/tests/vty_test_runner.py | 16 +++++ 4 files changed, 133 insertions(+), 24 deletions(-) diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index e51dd47..c2c9092 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -17,7 +17,8 @@ struct gbproxy_config { extern struct gbproxy_config gbcfg; extern struct cmd_element show_gbproxy_cmd; -extern struct cmd_element delete_gb_cmd; +extern struct cmd_element delete_gb_bvci_cmd; +extern struct cmd_element delete_gb_nsei_cmd; /* gb_proxy_vty .c */ diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index a7640f0..6f7d1c3 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -881,8 +881,41 @@ int gbprox_dump_peers(FILE *stream, int indent, int verbose) return 0; } +static int gbprox_cleanup_peers(uint16_t nsei, uint16_t bvci) +{ + int counter = 0; + struct gbprox_peer *peer, *tmp; + + llist_for_each_entry_safe(peer, tmp, &gbprox_bts_peers, list) { + if (peer->nsei != nsei) + continue; + if (bvci && peer->bvci != bvci) + continue; + + peer_free(peer); + counter += 1; + } + + return counter; +} + #include +static void gbprox_vty_print_peer(struct vty *vty, struct gbprox_peer *peer) +{ + struct gprs_ra_id raid; + gsm48_parse_ra(&raid, peer->ra); + + vty_out(vty, "NSEI %5u, PTP-BVCI %5u, " + "RAC %u-%u-%u-%u", + peer->nsei, peer->bvci, + raid.mcc, raid.mnc, raid.lac, raid.rac); + if (peer->blocked) + vty_out(vty, " [BVC-BLOCKED]"); + + vty_out(vty, "%s", VTY_NEWLINE); +} + gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", SHOW_STR "Display information about the Gb proxy") { @@ -893,17 +926,7 @@ gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", vty_out_rate_ctr_group(vty, "", get_global_ctrg()); llist_for_each_entry(peer, &gbprox_bts_peers, list) { - struct gprs_ra_id raid; - gsm48_parse_ra(&raid, peer->ra); - - vty_out(vty, "NSEI %5u, PTP-BVCI %5u, " - "RAC %u-%u-%u-%u", - peer->nsei, peer->bvci, - raid.mcc, raid.mnc, raid.lac, raid.rac); - if (peer->blocked) - vty_out(vty, " [BVC-BLOCKED]"); - - vty_out(vty, "%s", VTY_NEWLINE); + gbprox_vty_print_peer(vty, peer); if (show_stats) vty_out_rate_ctr_group(vty, " ", peer->ctrg); @@ -911,24 +934,92 @@ gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", return CMD_SUCCESS; } -gDEFUN(delete_gb, delete_gb_cmd, - "delete-gbproxy-peer <0-65534> bvci <0-65534>", - "Delete a GBProxy peer by NSEI and BVCI\n" +gDEFUN(delete_gb_bvci, delete_gb_bvci_cmd, + "delete-gbproxy-peer <0-65534> bvci <2-65534>", + "Delete a GBProxy peer by NSEI and optionally BVCI\n" "NSEI number\n" - "BVCI\n" + "Only delete peer with a matching BVCI\n" "BVCI number\n") { - struct gbprox_peer *peer, *tmp; const uint16_t nsei = atoi(argv[0]); const uint16_t bvci = atoi(argv[1]); + int counter; - llist_for_each_entry_safe(peer, tmp, &gbprox_bts_peers, list) { - if (peer->bvci != bvci) - continue; - if (peer->nsei != nsei) - continue; + counter = gbprox_cleanup_peers(nsei, bvci); - peer_free(peer); + if (counter == 0) { + vty_out(vty, "BVC not found%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +gDEFUN(delete_gb_nsei, delete_gb_nsei_cmd, + "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]", + "Delete a GBProxy peer by NSEI and optionally BVCI\n" + "NSEI number\n" + "Only delete BSSGP connections (BVC)\n" + "Only delete dynamic NS connections (NS-VC)\n" + "Delete BVC and dynamic NS connections\n" + "Show what would be deleted instead of actually deleting\n" + ) +{ + const uint16_t nsei = atoi(argv[0]); + const char *mode = argv[1]; + int dry_run = argc > 2; + int delete_bvc = 0; + int delete_nsvc = 0; + int counter; + + if (strcmp(mode, "only-bvc") == 0) + delete_bvc = 1; + else if (strcmp(mode, "only-nsvc") == 0) + delete_nsvc = 1; + else + delete_bvc = delete_nsvc = 1; + + if (delete_bvc) { + if (!dry_run) + counter = gbprox_cleanup_peers(nsei, 0); + else { + struct gbprox_peer *peer; + counter = 0; + llist_for_each_entry(peer, &gbprox_bts_peers, list) { + if (peer->nsei != nsei) + continue; + + vty_out(vty, "BVC: "); + gbprox_vty_print_peer(vty, peer); + counter += 1; + } + } + vty_out(vty, "%sDeleted %d BVC%s", + dry_run ? "Not " : "", counter, VTY_NEWLINE); + } + + if (delete_nsvc) { + struct gprs_ns_inst *nsi = gbcfg.nsi; + struct gprs_nsvc *nsvc, *nsvc2; + + counter = 0; + llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) { + if (nsvc->nsei != nsei) + continue; + if (nsvc->persistent) + continue; + + if (!dry_run) + gprs_nsvc_delete(nsvc); + else + vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, " + "remote %s%s", + nsvc->nsei, nsvc->nsvci, + gprs_ns_ll_str(nsvc), VTY_NEWLINE); + counter += 1; + } + vty_out(vty, "%sDeleted %d NS-VC%s", + dry_run ? "Not " : "", counter, VTY_NEWLINE); } return CMD_SUCCESS; diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c index 176ea65..82d49ca 100644 --- a/openbsc/src/gprs/gb_proxy_vty.c +++ b/openbsc/src/gprs/gb_proxy_vty.c @@ -80,7 +80,8 @@ int gbproxy_vty_init(void) { install_element_ve(&show_gbproxy_cmd); - install_element(ENABLE_NODE, &delete_gb_cmd); + install_element(ENABLE_NODE, &delete_gb_bvci_cmd); + install_element(ENABLE_NODE, &delete_gb_nsei_cmd); install_element(CONFIG_NODE, &cfg_gbproxy_cmd); install_node(&gbproxy_node, config_write_gbproxy); diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index e040cac..18cf688 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -527,6 +527,22 @@ class TestVTYGbproxy(TestVTYGenericBSC): res = self.vty.command("show gbproxy stats") self.assert_(res.find('GBProxy Global Statistics') >= 0) + def testVtyDeletePeer(self): + self.vty.enable() + self.assertTrue(self.vty.verify('delete-gbproxy-peer 9999 bvci 7777', ['BVC not found'])) + res = self.vty.command("delete-gbproxy-peer 9999 all dry-run") + self.assert_(res.find('Not Deleted 0 BVC') >= 0) + self.assert_(res.find('Not Deleted 0 NS-VC') >= 0) + res = self.vty.command("delete-gbproxy-peer 9999 only-bvc dry-run") + self.assert_(res.find('Not Deleted 0 BVC') >= 0) + self.assert_(res.find('Not Deleted 0 NS-VC') < 0) + res = self.vty.command("delete-gbproxy-peer 9999 only-nsvc dry-run") + self.assert_(res.find('Not Deleted 0 BVC') < 0) + self.assert_(res.find('Not Deleted 0 NS-VC') >= 0) + res = self.vty.command("delete-gbproxy-peer 9999 all") + self.assert_(res.find('Deleted 0 BVC') >= 0) + self.assert_(res.find('Deleted 0 NS-VC') >= 0) + def add_nat_test(suite, workdir): if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc_nat/osmo-bsc_nat")): print("Skipping the NAT test") -- 1.7.9.5 From holger at freyther.de Thu Oct 24 14:23:48 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 24 Oct 2013 16:23:48 +0200 Subject: [PATCH] gbproxy/vty: Enhance delete-gbproxy-peer command In-Reply-To: <1382611703-17122-1-git-send-email-jerlbeck@sysmocom.de> References: <1382520258-30733-5-git-send-email-jerlbeck@sysmocom.de> <1382611703-17122-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <20131024142348.GC4342@xiaoyu.lan> On Thu, Oct 24, 2013 at 12:48:23PM +0200, Jacob Erlbeck wrote: > + llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) { > + if (nsvc->nsei != nsei) > + continue; > + if (nsvc->persistent) > + continue; > + > + if (!dry_run) > + gprs_nsvc_delete(nsvc); > + else > + vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, " > + "remote %s%s", > + nsvc->nsei, nsvc->nsvci, > + gprs_ns_ll_str(nsvc), VTY_NEWLINE); > + counter += 1; > + } > + vty_out(vty, "%sDeleted %d NS-VC%s", > + dry_run ? "Not " : "", counter, VTY_NEWLINE); ahhh, now I understand! Good solution! Going to review it again. From clovnrian at gmail.com Wed Oct 23 19:44:27 2013 From: clovnrian at gmail.com (clovnrian at gmail.com) Date: Wed, 23 Oct 2013 21:44:27 +0200 Subject: OsmocomBB without hardware phone Message-ID: <5268271B.2030809@gmail.com> Hi, I am trying to modify osmocomBB to work without the phone as layer 1. My goal is that application will using socket to communicate with BTS (modified BTS which can send and receive message throught sockets). I analyzed the osmocomBB code and I found that I'll have to modify osmocon.c (host/osmocon/osmocon.c) file. This file is interface between serial communication and layer2. If I am right, I have to do this changes: 1. Delete functions handle the serial interface 2. Add new tool server to dnload structure 3. Creating new tool server for L1 interface (UNIX socket or IP socket with GSMTAP) 4. Add callback function for reading from layer2 socket and forward this messages to L1 socket interface. Simplified I have to listen and forward packets from BTS to layer2 socket and from L2 to L1. Do I think in right direction or I am wrong and it will need more modifications? Best regards, Miroslav Babjak -------------- next part -------------- An HTML attachment was scrubbed... URL: From 246tnt at gmail.com Wed Oct 23 20:44:30 2013 From: 246tnt at gmail.com (Sylvain Munaut) Date: Wed, 23 Oct 2013 22:44:30 +0200 Subject: OsmocomBB without hardware phone In-Reply-To: <5268271B.2030809@gmail.com> References: <5268271B.2030809@gmail.com> Message-ID: Hi, > Do I think in right direction or I am wrong and it will need more > modifications? You should just implement a virtual layer 1 that uses the same interface as osmocon and present it to the 'mobile' application. No need to modify anything. osmocon is full of stuff you won't need, it's much easier to start from scratch and implement something new that implements the L1CTL protocol that goes over serial. Cheers, Sylvain From clovnrian at gmail.com Thu Oct 24 20:14:51 2013 From: clovnrian at gmail.com (clovnrian at gmail.com) Date: Thu, 24 Oct 2013 22:14:51 +0200 Subject: OsmocomBB without hardware phone In-Reply-To: References: <5268271B.2030809@gmail.com> Message-ID: <52697FBB.8040500@gmail.com> Hi, thanks for quick answer and advice. I looked for l1ctl in sources files and I found it in src/host/layer23/src/common. I quickly looked at the main.c file in this directory and it looks quite simple if I use the l1l2_interface and l1ctl. We'll see how it goes. The L1 interface is only one part from what I want to do. The second part will be harder. I want to implement a GPRS stack to the 'mobile' application. I know that osmocomBB hasn't GPRS support and I have to build it from scratch. I found some topics about it in mailing list. It says that i can use the GPRS parts from another projects. SNDCP from OsmoSGSN and RLC/MAC message encoding and parsing from osmo-pcu. Is that true? Can you give me some hints to start? Best regards, Miroslav Babj?k Dne 23.10.2013 22:44, Sylvain Munaut napsal(a): > Hi, > >> Do I think in right direction or I am wrong and it will need more >> modifications? > You should just implement a virtual layer 1 that uses the same > interface as osmocon and present it to the 'mobile' application. No > need to modify anything. > > osmocon is full of stuff you won't need, it's much easier to start > from scratch and implement something new that implements the L1CTL > protocol that goes over serial. > > Cheers, > > Sylvain -------------- next part -------------- An HTML attachment was scrubbed... URL: From jerlbeck at sysmocom.de Thu Oct 24 10:48:55 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 12:48:55 +0200 Subject: [PATCH 1/2] gbproxy: Add test for NSEI and NSVCI changes Message-ID: <1382611736-17163-1-git-send-email-jerlbeck@sysmocom.de> This checks the behavior of the gbproxy when the BSS peer changes the NSEI and the NSVCI. It also tests BVC_RESET and other UNITDATA messages after these changes between BSS and SGSN and vice versa (via the gbproxy). Ticket: OW#874 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 1 + openbsc/src/gprs/gb_proxy.c | 11 + openbsc/tests/gbproxy/gbproxy_test.c | 153 ++++++- openbsc/tests/gbproxy/gbproxy_test.ok | 705 ++++++++++++++++++++++++++++++++- 4 files changed, 866 insertions(+), 4 deletions(-) diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index c2c9092..4d189a6 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -39,4 +39,5 @@ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi); int gbprox_dump_global(FILE *stream, int indent, int verbose); int gbprox_dump_peers(FILE *stream, int indent, int verbose); +void gbprox_reset(); #endif diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 6f7d1c3..f008b3e 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -881,6 +881,17 @@ int gbprox_dump_peers(FILE *stream, int indent, int verbose) return 0; } +void gbprox_reset() +{ + struct gbprox_peer *peer, *tmp; + + llist_for_each_entry_safe(peer, tmp, &gbprox_bts_peers, list) + peer_free(peer); + + rate_ctr_group_free(global_ctrg); + global_ctrg = NULL; +} + static int gbprox_cleanup_peers(uint16_t nsei, uint16_t bvci) { int counter = 0; diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index e1e6587..d32ac83 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -543,6 +543,147 @@ static void test_gbproxy() gprs_ns_destroy(nsi); nsi = NULL; + gbprox_reset(); +} + +static void test_gbproxy_ident_changes() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in bss_peer[1] = {{0},}; + struct sockaddr_in sgsn_peer= {0}; + uint16_t nsei[2] = {0x1000, 0x2000}; + uint16_t nsvci[2] = {0x1001, 0x2001}; + uint16_t bvci[4] = {0x1002, 0x2002, 0x3002, 0x4002}; + + bssgp_nsi = nsi; + gbcfg.nsi = bssgp_nsi; + gbcfg.nsip_sgsn_nsei = SGSN_NSEI; + + sgsn_peer.sin_family = AF_INET; + sgsn_peer.sin_port = htons(32000); + sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR); + + bss_peer[0].sin_family = AF_INET; + bss_peer[0].sin_port = htons(1111); + bss_peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + + printf("--- Initialise SGSN ---\n\n"); + + gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1); + send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); + send_ns_alive_ack(nsi, &sgsn_peer); + send_ns_unblock_ack(nsi, &sgsn_peer); + send_ns_alive(nsi, &sgsn_peer); + gprs_dump_nsi(nsi); + + printf("--- Initialise BSS 1 ---\n\n"); + + setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[0]); + gprs_dump_nsi(nsi); + + printf("--- Setup BVCI 1 ---\n\n"); + + setup_bssgp(nsi, &bss_peer[0], bvci[0]); + send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]); + gbprox_dump_peers(stdout, 0, 1); + + printf("--- Setup BVCI 2 ---\n\n"); + + setup_bssgp(nsi, &bss_peer[0], bvci[1]); + send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]); + gbprox_dump_peers(stdout, 0, 1); + + printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0); + send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0); + + printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0); + send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0); + + printf("--- Change NSEI ---\n\n"); + + setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[1]); + gprs_dump_nsi(nsi); + + printf("--- Setup BVCI 1 ---\n\n"); + + setup_bssgp(nsi, &bss_peer[0], bvci[0]); + send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]); + gbprox_dump_peers(stdout, 0, 1); + + printf("--- Setup BVCI 3 ---\n\n"); + + setup_bssgp(nsi, &bss_peer[0], bvci[2]); + send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]); + gbprox_dump_peers(stdout, 0, 1); + + printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0); + send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0); + + printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 " + " (should fail) ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0); + gbprox_dump_peers(stdout, 0, 1); + send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0); + gbprox_dump_peers(stdout, 0, 1); + + printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0); + send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0); + + printf("--- Change NSVCI ---\n\n"); + + setup_ns(nsi, &bss_peer[0], nsvci[1], nsei[1]); + gprs_dump_nsi(nsi); + + printf("--- Setup BVCI 1 ---\n\n"); + + setup_bssgp(nsi, &bss_peer[0], bvci[0]); + send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]); + gbprox_dump_peers(stdout, 0, 1); + + printf("--- Setup BVCI 4 ---\n\n"); + + setup_bssgp(nsi, &bss_peer[0], bvci[3]); + send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]); + gbprox_dump_peers(stdout, 0, 1); + + printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0); + send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0); + + printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 " + " (should fail) ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0); + gbprox_dump_peers(stdout, 0, 1); + send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0); + gbprox_dump_peers(stdout, 0, 1); + + printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0); + send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0); + + printf("--- Send message from BSS 1 to SGSN and back, BVCI 4 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0); + send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0); + + gbprox_dump_global(stdout, 0, 1); + gbprox_dump_peers(stdout, 0, 1); + + gprs_ns_destroy(nsi); + nsi = NULL; + gbprox_reset(); } @@ -555,9 +696,17 @@ int main(int argc, char **argv) log_set_print_filename(osmo_stderr_target, 0); osmo_signal_register_handler(SS_L_NS, &test_signal, NULL); - printf("===== NS protocol test START\n"); + log_set_print_filename(osmo_stderr_target, 0); + log_set_log_level(osmo_stderr_target, LOGL_INFO); + + rate_ctr_init(NULL); + + setlinebuf(stdout); + + printf("===== GbProxy test START\n"); test_gbproxy(); - printf("===== NS protocol test END\n\n"); + test_gbproxy_ident_changes(); + printf("===== GbProxy test END\n\n"); exit(EXIT_SUCCESS); } diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index 35d97e7..b21f58a 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -1,4 +1,4 @@ -===== NS protocol test START +===== GbProxy test START --- Initialise SGSN --- MESSAGE to SGSN at 0x05060708:32000, msg length 12 @@ -814,5 +814,706 @@ result (UNITDATA) = 14 Gbproxy global: Invalid BVC Identifier : 1 -===== NS protocol test END +--- Initialise SGSN --- + +MESSAGE to SGSN at 0x05060708:32000, msg length 12 +02 00 81 01 01 82 01 01 04 82 01 00 + +PROCESSING RESET_ACK from 0x05060708:32000 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 1 +0a + +result (RESET_ACK) = 1 + +PROCESSING ALIVE_ACK from 0x05060708:32000 +0b + +MESSAGE to SGSN at 0x05060708:32000, msg length 1 +06 + +result (ALIVE_ACK) = 1 + +PROCESSING UNBLOCK_ACK from 0x05060708:32000 +07 + +==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000 + +result (UNBLOCK_ACK) = 0 + +PROCESSING ALIVE from 0x05060708:32000 +0a + +MESSAGE to SGSN at 0x05060708:32000, msg length 1 +0b + +result (ALIVE) = 1 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +--- Initialise BSS 1 --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +--- Setup BVCI 1 --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 + +Peers: + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Setup BVCI 2 --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x2002(8194) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 20 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 20 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 20 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 20 02 + +result (BVC_RESET_ACK) = 9 + +Peers: + NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Send message from BSS 1 to SGSN and back, BVCI 1 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 02 + +CALLBACK, event 0, msg length 0, bvci 0x1002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 10 02 + +result (UNITDATA) = 4 + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 02 + +CALLBACK, event 0, msg length 0, bvci 0x1002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 10 02 + +result (UNITDATA) = 4 + +--- Send message from BSS 1 to SGSN and back, BVCI 2 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 20 02 + +CALLBACK, event 0, msg length 0, bvci 0x2002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x2002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 20 02 + +result (UNITDATA) = 4 + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 20 02 + +CALLBACK, event 0, msg length 0, bvci 0x2002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x2002, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 20 02 + +result (UNITDATA) = 4 + +--- Change NSEI --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 20 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +03 01 82 10 01 04 82 20 00 + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC changed NSEI count : 1 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +--- Setup BVCI 1 --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +result (BVC_RESET_ACK) = -22 + +Peers: + NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 + NS Transmission error : 1 +--- Setup BVCI 3 --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x3002(12290) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 30 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 30 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 30 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 30 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 30 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 30 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 30 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 30 02 + +result (BVC_RESET_ACK) = 9 + +Peers: + NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 + NS Transmission error : 1 +--- Send message from BSS 1 to SGSN and back, BVCI 1 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 02 + +CALLBACK, event 0, msg length 0, bvci 0x1002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 10 02 + +result (UNITDATA) = 4 + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 02 + +CALLBACK, event 0, msg length 0, bvci 0x1002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 0 + + +result (UNITDATA) = -22 + +--- Send message from BSS 1 to SGSN and back, BVCI 2 (should fail) --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 20 02 + +CALLBACK, event 0, msg length 0, bvci 0x2002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x2002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 20 02 + +result (UNITDATA) = 4 + +Peers: + NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 2 + NS Transmission error : 2 +PROCESSING UNITDATA from 0x05060708:32000 +00 00 20 02 + +CALLBACK, event 0, msg length 0, bvci 0x2002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x2002, msg length 0 + + +result (UNITDATA) = -22 + +Peers: + NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 + NS Transmission error : 1 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 2 + NS Transmission error : 2 +--- Send message from BSS 1 to SGSN and back, BVCI 3 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 30 02 + +CALLBACK, event 0, msg length 0, bvci 0x3002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x3002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 30 02 + +result (UNITDATA) = 4 + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 30 02 + +CALLBACK, event 0, msg length 0, bvci 0x3002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x3002, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 30 02 + +result (UNITDATA) = 4 + +--- Change NSVCI --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 20 01 04 82 20 00 + +==> got signal NS_REPLACED: 0x2001/0.0.0.0:0 -> 0x1001/1.2.3.4:1111 + +==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +03 01 82 20 01 04 82 20 00 + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x2000, peer 0x00000000:0 + NS-VC changed NSEI count : 1 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +--- Setup BVCI 1 --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +result (BVC_RESET_ACK) = -22 + +Peers: + NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 + NS Transmission error : 1 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 3 + NS Transmission error : 3 +--- Setup BVCI 4 --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x4002(16386) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 40 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 40 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 40 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 40 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 40 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 40 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 40 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 40 02 + +result (BVC_RESET_ACK) = 9 + +Peers: + NSEI 8192, BVCI 16386, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 + NS Transmission error : 1 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 3 + NS Transmission error : 3 +--- Send message from BSS 1 to SGSN and back, BVCI 1 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 02 + +CALLBACK, event 0, msg length 0, bvci 0x1002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 10 02 + +result (UNITDATA) = 4 + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 02 + +CALLBACK, event 0, msg length 0, bvci 0x1002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 0 + + +result (UNITDATA) = -22 + +--- Send message from BSS 1 to SGSN and back, BVCI 2 (should fail) --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 20 02 + +CALLBACK, event 0, msg length 0, bvci 0x2002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x2002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 20 02 + +result (UNITDATA) = 4 + +Peers: + NSEI 8192, BVCI 16386, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 2 + NS Transmission error : 1 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 4 + NS Transmission error : 4 +PROCESSING UNITDATA from 0x05060708:32000 +00 00 20 02 + +CALLBACK, event 0, msg length 0, bvci 0x2002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x2002, msg length 0 + + +result (UNITDATA) = -22 + +Peers: + NSEI 8192, BVCI 16386, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 2 + NS Transmission error : 2 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 4 + NS Transmission error : 4 +--- Send message from BSS 1 to SGSN and back, BVCI 3 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 30 02 + +CALLBACK, event 0, msg length 0, bvci 0x3002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x3002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 30 02 + +result (UNITDATA) = 4 + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 30 02 + +CALLBACK, event 0, msg length 0, bvci 0x3002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x3002, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 30 02 + +result (UNITDATA) = 4 + +--- Send message from BSS 1 to SGSN and back, BVCI 4 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 40 02 + +CALLBACK, event 0, msg length 0, bvci 0x4002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x4002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 40 02 + +result (UNITDATA) = 4 + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 40 02 + +CALLBACK, event 0, msg length 0, bvci 0x4002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x4002, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 40 02 + +result (UNITDATA) = 4 + +Gbproxy global: +Peers: + NSEI 8192, BVCI 16386, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 2 + NS Transmission error : 2 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 4 + NS Transmission error : 4 +===== GbProxy test END -- 1.7.9.5 From jerlbeck at sysmocom.de Thu Oct 24 10:48:56 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 24 Oct 2013 12:48:56 +0200 Subject: [PATCH 2/2] gbproxy: Fix handling of NSEI changes In-Reply-To: <1382611736-17163-1-git-send-email-jerlbeck@sysmocom.de> References: <1382611736-17163-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382611736-17163-2-git-send-email-jerlbeck@sysmocom.de> The gbproxy looses NSEI changes on BVC_RESET and then tries to send later messages to the wrong (not longer existing) destination. This patch fixes this by updating the peer's nsei field on BVC_RESET. Ticket: OW#874 Sponsored-by: On-Waves ehf --- openbsc/src/gprs/gb_proxy.c | 9 +++-- openbsc/tests/gbproxy/gbproxy_test.ok | 65 +++++++++++++++++---------------- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index f008b3e..f900158 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -183,10 +183,10 @@ static int check_peer_nsei(struct gbprox_peer *peer, uint16_t nsei) "BVCI=%u via NSEI=%u (expected NSEI=%u)\n", peer->bvci, nsei, peer->nsei); rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_INV_NSEI]); - return 1; + return 0; } - return 0; + return 1; } static struct gbprox_peer *peer_alloc(uint16_t bvci) @@ -432,7 +432,10 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, from_peer = peer_alloc(bvci); from_peer->nsei = nsei; } - check_peer_nsei(from_peer, nsei); + + if (!check_peer_nsei(from_peer, nsei)) + from_peer->nsei = nsei; + if (TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID)) { struct gprs_ra_id raid; /* We have a Cell Identifier present in this diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index b21f58a..0942ca3 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -747,7 +747,7 @@ Peers: NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI mismatch : 1 - NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 NSEI mismatch : 1 Gbproxy global: PROCESSING BVC_RESET_ACK from 0x05060708:32000 @@ -759,7 +759,7 @@ CALLBACK, event 0, msg length 5, bvci 0x0000 NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 23 04 82 10 02 -MESSAGE to BSS at 0x01020304:1111, msg length 9 +MESSAGE to BSS at 0x01020304:3333, msg length 9 00 00 00 00 23 04 82 10 02 result (BVC_RESET_ACK) = 9 @@ -1101,13 +1101,15 @@ CALLBACK, event 0, msg length 5, bvci 0x0000 NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 23 04 82 10 02 -result (BVC_RESET_ACK) = -22 +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 Peers: NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 - NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 NSEI mismatch : 1 - NS Transmission error : 1 --- Setup BVCI 3 --- Setup BSSGP: remote 0x01020304:1111, BVCI 0x3002(12290) @@ -1143,9 +1145,8 @@ result (BVC_RESET_ACK) = 9 Peers: NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 - NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 NSEI mismatch : 1 - NS Transmission error : 1 --- Send message from BSS 1 to SGSN and back, BVCI 1 --- PROCESSING UNITDATA from 0x01020304:1111 @@ -1171,7 +1172,10 @@ CALLBACK, event 0, msg length 0, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 0 -result (UNITDATA) = -22 +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 10 02 + +result (UNITDATA) = 4 --- Send message from BSS 1 to SGSN and back, BVCI 2 (should fail) --- @@ -1193,9 +1197,8 @@ Peers: NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI mismatch : 1 - NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 - NSEI mismatch : 2 - NS Transmission error : 2 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 PROCESSING UNITDATA from 0x05060708:32000 00 00 20 02 @@ -1212,9 +1215,8 @@ Peers: NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI mismatch : 1 NS Transmission error : 1 - NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 - NSEI mismatch : 2 - NS Transmission error : 2 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 --- Send message from BSS 1 to SGSN and back, BVCI 3 --- PROCESSING UNITDATA from 0x01020304:1111 @@ -1322,16 +1324,18 @@ CALLBACK, event 0, msg length 5, bvci 0x0000 NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 23 04 82 10 02 -result (BVC_RESET_ACK) = -22 +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 Peers: NSEI 8192, BVCI 12290, not blocked, RAC 10-32-16464-96 NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI mismatch : 1 NS Transmission error : 1 - NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 - NSEI mismatch : 3 - NS Transmission error : 3 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 --- Setup BVCI 4 --- Setup BSSGP: remote 0x01020304:1111, BVCI 0x4002(16386) @@ -1370,9 +1374,8 @@ Peers: NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI mismatch : 1 NS Transmission error : 1 - NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 - NSEI mismatch : 3 - NS Transmission error : 3 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 --- Send message from BSS 1 to SGSN and back, BVCI 1 --- PROCESSING UNITDATA from 0x01020304:1111 @@ -1398,7 +1401,10 @@ CALLBACK, event 0, msg length 0, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 0 -result (UNITDATA) = -22 +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 10 02 + +result (UNITDATA) = 4 --- Send message from BSS 1 to SGSN and back, BVCI 2 (should fail) --- @@ -1422,9 +1428,8 @@ Peers: NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI mismatch : 2 NS Transmission error : 1 - NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 - NSEI mismatch : 4 - NS Transmission error : 4 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 PROCESSING UNITDATA from 0x05060708:32000 00 00 20 02 @@ -1442,9 +1447,8 @@ Peers: NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI mismatch : 2 NS Transmission error : 2 - NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 - NSEI mismatch : 4 - NS Transmission error : 4 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 --- Send message from BSS 1 to SGSN and back, BVCI 3 --- PROCESSING UNITDATA from 0x01020304:1111 @@ -1512,8 +1516,7 @@ Peers: NSEI 4096, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI mismatch : 2 NS Transmission error : 2 - NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 - NSEI mismatch : 4 - NS Transmission error : 4 + NSEI 8192, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 ===== GbProxy test END -- 1.7.9.5 From hulds at gmx.net Fri Oct 25 11:14:30 2013 From: hulds at gmx.net (hulds at gmx.net) Date: Fri, 25 Oct 2013 13:14:30 +0200 Subject: osmo-nitb openbsc sms via commandline problem. Message-ID: <526A5296.4020903@gmx.net> Hi, When sending sms via openbsc commandline the sms gets extra data added to its tail. The coversion from text to PDU results in the converted data + garbage, this data is posted to the 'sms' database 'user-data' field, and then sent. in the 'sms' database you can verify that a short sms text results in long user-data phone to phone sms works without problems. Henry From dchardware at gmail.com Sun Oct 27 10:46:47 2013 From: dchardware at gmail.com (Sipos Csaba) Date: Sun, 27 Oct 2013 11:46:47 +0100 Subject: OpenBSC + LCR + Asterisk = half sided calls in one direction In-Reply-To: References: Message-ID: <236165582.20131027114647@freemail.hu> Hi, I am setting up openbsc with LCR and Asterisk to provide external connectivity for the GSM clients, and I encountered and interesting problem. If the GSM phone initiates a voice call towards a SIP phone it works perfectly, the voice goes both ways, the quality is OK, everything is fine. But when the SIP phones initiates a voice call towards the GSM phone, only the SIP phone can hear the voice of the GSM phone, and not the other way around (half sided call). The connection setup works both ways just fine. The GSM and the SIP phone can also call the asterisk test numbers, and even can do echo test just fine. The two GSM phones can call each other too without any problem. Does somebody has any idea what could go wrong? Config: E1 based Nokia BTS with DAHDI card and TCH/F FR codec. The SIP phone uses Alaw, LCR also set to use Alaw. The LCR is bridged to Asterisk, interface.conf: [GSM] gsm-bs tones yes earlyb no bridge ast [ast] remote asterisk context from-lcr earlyb no tones yes bridge GSM routing.conf is completely empty. Astrisk SIP.conf: [general] context=incoming disallow=all allow=alaw allow=ulaw allow=gsm transport=udp udpbindaddr=0.0.0.0 tcpenable=no tcpbindaddr=0.0.0.0 tlsenable=no tlsbindaddr=0.0.0.0 [5010] type=friend username=5010 secret=123456 dtmfmode=rfc2833 callerid="5010" <5010> host=dynamic canreinvite=no context=myphones Asterisk extensions.conf [general] static=yes writeprotect=no clearglobalvars=no [globals] ; Global variables goes here [incoming] ; Nothing should land here yet, but every context should end in ; a Hangup(), so we do that. exten => s,1,Hangup() [myphones] ; When we dial something from the phones we just added in ; sip.conf, Asterisk will look for a matching extension here, ; in this context. ; SIP phone exten => 5010,1,Dial(SIP/5010) exten => 5010,n,Hangup() ; Another SIp phone ;exten => 1001,1,Dial(SIP/1001) ;exten => 1001,n,Hangup() ; GSM phone 1 exten => 12346,1,Dial(LCR/ast/${EXTEN:0},60) exten => 12346,n,Hangup() ; GSM phone 2 exten => 12345,1,Dial(LCR/ast/${EXTEN:0},60) exten => 12345,n,Hangup() ; Testing extension exten => 201,1,Answer() exten => 201,n,Playback(levan_polka.mp3) exten => 201,n,Hangup() ; Echo-test, it is good to test if we have sound in both directions. ; The call is answered exten => 202,1,Answer() ; Welcome message is played exten => 202,n,Playback(dir-welcome) ; Play information about the echo test exten => 202,n,Playback(demo-echotest) ; Do the echo test, end with the # key exten => 202,n,Echo() ; Plays information that the echo test is done exten => 202,n,Playback(demo-echodone) ; Goodbye message is played exten => 202,n,Playback(vm-goodbye) ; Hangup() ends the call, hangs up the line exten => 202,n,Hangup() [from-lcr] include => myphones exten => _X.,1,Dial(LCR/ast/${EXTEN:0},60) exten => 5010,1,Dial(SIP/5010) exten => 5010,n,Hangup() BR, Csaba From peter at stuge.se Sun Oct 27 13:38:59 2013 From: peter at stuge.se (Peter Stuge) Date: Sun, 27 Oct 2013 14:38:59 +0100 Subject: OpenBSC + LCR + Asterisk = half sided calls in one direction In-Reply-To: <236165582.20131027114647@freemail.hu> References: <236165582.20131027114647@freemail.hu> Message-ID: <20131027133859.18069.qmail@stuge.se> Sipos Csaba wrote: > I am setting up openbsc with LCR and Asterisk to provide external > connectivity for the GSM clients, and I encountered and interesting > problem. I'd suggest to make LCR use SIP for communcation with Asterisk. See http://stuge.se/lcr.txt for a minimal example of LCR configuration. Since you're using bridging you might also want to try rtp-bridge between GSM and SIP, which could allow GSM phones and SIP phones to negotiate codec directly, avoiding any transcoding. (But maybe it only works with Abis over IP and not over ISDN? I'm not sure.) > But when the SIP phones initiates a voice call towards the GSM phone, > only the SIP phone can hear the voice of the GSM phone, and not the > other way around (half sided call). You can of course continue to debug the LCR-Asterisk module but I would suggest moving to SIP since I think working with SIP on both legs makes debugging a bit easier. //Peter From jerlbeck at sysmocom.de Mon Oct 28 12:29:10 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Mon, 28 Oct 2013 13:29:10 +0100 Subject: [PATCH 1/2] grps: Add test for NS messages that shall be ignored Message-ID: <1382963351-30404-1-git-send-email-jerlbeck@sysmocom.de> Several messages shall not be answered when a RESET hasn't been received on a NS-VC: - NS_RESET_ACK (see 3GPP TS 08.16, 7.3.1) - NS_ALIVE_ACK (see 3GPP TS 08.16, 7.4.1) - NS_STATUS (see 3GPP TS 08.16, 7.5.1) Sponsored-by: On-Waves ehf --- tests/gb/gprs_ns_test.c | 28 ++++++++++++++++++++++++++++ tests/gb/gprs_ns_test.ok | 27 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/tests/gb/gprs_ns_test.c b/tests/gb/gprs_ns_test.c index c88792c..c90d752 100644 --- a/tests/gb/gprs_ns_test.c +++ b/tests/gb/gprs_ns_test.c @@ -486,6 +486,33 @@ static void test_nsvc() alarm(0); } +static void test_ignored_messages() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in peer[1] = {{0},}; + + peer[0].sin_family = AF_INET; + peer[0].sin_port = htons(1111); + peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + + printf("--- Send unexpected NS STATUS (should not be answered)---\n\n"); + /* Do not respond, see 3GPP TS 08.16, 7.5.1 */ + gprs_process_message(nsi, "STATUS", &peer[0], + gprs_ns_status_invalid_alive, + sizeof(gprs_ns_status_invalid_alive)); + + printf("--- Send unexpected NS ALIVE ACK (should not be answered)---\n\n"); + /* Ignore this, see 3GPP TS 08.16, 7.4.1 */ + send_ns_alive_ack(nsi, &peer[0]); + + printf("--- Send unexpected NS RESET ACK (should not be answered)---\n\n"); + /* Ignore this, see 3GPP TS 08.16, 7.3.1 */ + send_ns_reset_ack(nsi, &peer[0], 0xe001, 0xe000); + + gprs_ns_destroy(nsi); + nsi = NULL; +} + static void test_bss_port_changes() { struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); @@ -832,6 +859,7 @@ int main(int argc, char **argv) printf("===== NS protocol test START\n"); test_nsvc(); + test_ignored_messages(); test_bss_port_changes(); test_bss_reset_ack(); test_sgsn_reset(); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 8a61450..23c9e5f 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -85,6 +85,33 @@ Current NS-VCIs: --- Process timers --- +--- Send unexpected NS STATUS (should not be answered)--- + +PROCESSING STATUS from 0x01020304:1111 +08 00 81 0a 02 81 0a + +result (STATUS) = 0 + +--- Send unexpected NS ALIVE ACK (should not be answered)--- + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +MESSAGE to BSS, msg length 7 +08 00 81 0a 02 81 0b + +result (ALIVE_ACK) = 0 + +--- Send unexpected NS RESET ACK (should not be answered)--- + +PROCESSING RESET_ACK from 0x01020304:1111 +03 01 82 e0 01 04 82 e0 00 + +MESSAGE to BSS, msg length 15 +08 00 81 0a 02 89 03 01 82 e0 01 04 82 e0 00 + +result (RESET_ACK) = 0 + --- Setup, send BSSGP RESET --- Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1122(4386), NSEI 0x1122(4386) -- 1.7.9.5 From jerlbeck at sysmocom.de Mon Oct 28 12:29:11 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Mon, 28 Oct 2013 13:29:11 +0100 Subject: [PATCH 2/2] gprs: Ignore NS RESET_ACK and ALIVE_ACK without RESET In-Reply-To: <1382963351-30404-1-git-send-email-jerlbeck@sysmocom.de> References: <1382963351-30404-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1382963351-30404-2-git-send-email-jerlbeck@sysmocom.de> Currently those messages are answered by a NS_STATUS message when received on an uninitialised (no NS_RESET hat been seen yet) NS_VC which violates GPP TS 08.16 7.3.1 and 7.4.1. This patch adds checks to gprs_ns_vc_create() and eventually returns before the error NS_STATUS message is generated. Sponsored-by: On-Waves ehf --- src/gb/gprs_ns.c | 17 +++++++++++++++++ tests/gb/gprs_ns_test.ok | 6 ------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 0e9156a..55535ad 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -1127,12 +1127,29 @@ int gprs_ns_vc_create(struct gprs_ns_inst *nsi, struct msgb *msg, int rc; if (nsh->pdu_type == NS_PDUT_STATUS) { + /* Do not respond, see 3GPP TS 08.16, 7.5.1 */ LOGP(DNS, LOGL_INFO, "Ignoring NS STATUS from %s " "for non-existing NS-VC\n", gprs_ns_ll_str(fallback_nsvc)); return GPRS_NS_CS_SKIPPED; } + if (nsh->pdu_type == NS_PDUT_ALIVE_ACK) { + /* Ignore this, see 3GPP TS 08.16, 7.4.1 */ + LOGP(DNS, LOGL_INFO, "Ignoring NS ALIVE ACK from %s " + "for non-existing NS-VC\n", + gprs_ns_ll_str(fallback_nsvc)); + return GPRS_NS_CS_SKIPPED; + } + + if (nsh->pdu_type == NS_PDUT_RESET_ACK) { + /* Ignore this, see 3GPP TS 08.16, 7.3.1 */ + LOGP(DNS, LOGL_INFO, "Ignoring NS RESET ACK from %s " + "for non-existing NS-VC\n", + gprs_ns_ll_str(fallback_nsvc)); + return GPRS_NS_CS_SKIPPED; + } + /* Only the RESET procedure creates a new NSVC */ if (nsh->pdu_type != NS_PDUT_RESET) { /* Since we have no NSVC, we have to use a fake */ diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 23c9e5f..13d5f36 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -97,9 +97,6 @@ result (STATUS) = 0 PROCESSING ALIVE_ACK from 0x01020304:1111 0b -MESSAGE to BSS, msg length 7 -08 00 81 0a 02 81 0b - result (ALIVE_ACK) = 0 --- Send unexpected NS RESET ACK (should not be answered)--- @@ -107,9 +104,6 @@ result (ALIVE_ACK) = 0 PROCESSING RESET_ACK from 0x01020304:1111 03 01 82 e0 01 04 82 e0 00 -MESSAGE to BSS, msg length 15 -08 00 81 0a 02 89 03 01 82 e0 01 04 82 e0 00 - result (RESET_ACK) = 0 --- Setup, send BSSGP RESET --- -- 1.7.9.5 From dchardware at gmail.com Mon Oct 28 19:57:35 2013 From: dchardware at gmail.com (Sipos Csaba) Date: Mon, 28 Oct 2013 20:57:35 +0100 Subject: OpenBSC + LCR + Asterisk = half sided calls in one In-Reply-To: References: Message-ID: <07106293.20131028205735@freemail.hu> Hey Peter, > I'd suggest to make LCR use SIP for communcation with Asterisk. See > http://stuge.se/lcr.txt for a minimal example of LCR configuration. Do you have some more example configuration files for the Asterisk end of the SIP trunk? > Since you're using bridging you might also want to try rtp-bridge > between GSM and SIP, which could allow GSM phones and SIP phones to > negotiate codec directly, avoiding any transcoding. (But maybe it > only works with Abis over IP and not over ISDN? I'm not sure.) I am almost sure that RTP bridge can only be used with IP based BTSes which I don't have. My units are connecting via E1 dahdi. > You can of course continue to debug the LCR-Asterisk module but I > would suggest moving to SIP since I think working with SIP on both > legs makes debugging a bit easier. My problem is that I made test calls an analyzed the logs at both LCR and Asterisk end, and there is no difference between a good and a half sided call. First, I forced the GSM phones to use TCH/F FR only, then I forced LCR and Asterisk SIP clients to use Alaw only (SIP clients are not supporting any GSM codec). Transcoding obviously happens between TCH/F FR and Alaw, but how on earth is possible that the direction of the call can affect that this transcoding is going to be a success or not? If its a transcoding failure it shouldn't work in any direction. If its a call routing problem, then the call shouldn't make its way to the called party. But none of this is what happens. So I really don't know where to look, or how to debug this problem. BR, Csaba From peter at stuge.se Mon Oct 28 20:35:45 2013 From: peter at stuge.se (Peter Stuge) Date: Mon, 28 Oct 2013 21:35:45 +0100 Subject: OpenBSC + LCR + Asterisk = half sided calls in one In-Reply-To: <07106293.20131028205735@freemail.hu> References: <07106293.20131028205735@freemail.hu> Message-ID: <20131028203545.27731.qmail@stuge.se> Sipos Csaba wrote: > > I'd suggest to make LCR use SIP for communcation with Asterisk. See > > http://stuge.se/lcr.txt for a minimal example of LCR configuration. > > Do you have some more example configuration files for the Asterisk end > of the SIP trunk? I think you have to be able to configure Asterisk on your own, and if you aren't then probably the OpenBSC mailing list is not a very good place to ask for help. > I am almost sure that RTP bridge can only be used with IP based BTSes Yes, that makes sense. > My problem is that I made test calls an analyzed the logs at both LCR > and Asterisk end, and there is no difference between a good and a half > sided call. I believe that using SIP would make available more information. But of course a solid understanding of SIP is required to use it. //Peter From cleb at defcon-3.net Tue Oct 29 02:51:52 2013 From: cleb at defcon-3.net (Caleb Pal) Date: Mon, 28 Oct 2013 19:51:52 -0700 Subject: Nokia Insite OpenBSC Segfault Message-ID: <001801ced451$d2c09900$7841cb00$@net> Hello, I decided to connect my Nokia inSite 1900MHz E1 BTS that has been sitting for a while. Shortly after I start OpenBSC, it crashes. I have attached my configuration files as well as the result from gdb. I am using a Dahdi with a TE122P set to E1 mode. openbsc.cfg ! ! OpenBSC configuration saved from vty ! ! password foo ! line vty no login ! e1_input e1_line 0 driver dahdi network network country code 905 mobile network code 1 short name TNET long name TEST timer t3101 10 timer t3113 60 bts 0 type nokia_site band GSM1900 cell_identity 1 location_area_code 1 base_station_id_code 63 training_sequence_code 7 oml e1 line 0 timeslot 1 sub-slot full oml e1 tei 1 trx 0 arfcn 518 max_power_red 24 rsl e1 line 0 timeslot 2 sub-slot full rsl e1 tei 1 timeslot 0 phys_chan_config CCCH+SDCCH4 e1 line 0 timeslot 6 sub-slot full timeslot 1 phys_chan_config TCH/F e1 line 0 timeslot 6 sub-slot 1 timeslot 2 phys_chan_config TCH/F e1 line 0 timeslot 6 sub-slot 2 timeslot 3 phys_chan_config TCH/F e1 line 0 timeslot 6 sub-slot 3 timeslot 4 phys_chan_config TCH/F e1 line 0 timeslot 7 sub-slot 0 timeslot 5 phys_chan_config TCH/F e1 line 0 timeslot 7 sub-slot 1 timeslot 6 phys_chan_config TCH/F e1 line 0 timeslot 7 sub-slot 2 timeslot 7 phys_chan_config TCH/F e1 line 0 timeslot 7 sub-slot 3 DAHDI system.conf # Dahdi Configuration File # # This file is parsed by the Dahdi Configurator, dahdi_cfg # # Global data # # E1 Configuration (Jumper set on card) # # span=1,0,0,ccs,hdb3,crc4 # # bchan=1-31 # # # Zone stuff loadzone = us defaultzone = us Output from gdb: root at openbsc-2:/opt/openbsc/openbsc/src# gdb ./osmo-nitb/osmo-nitb GNU gdb (GDB) 7.4.1-debian Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu". For bug reporting instructions, please see: ... Reading symbols from /opt/openbsc/openbsc/src/osmo-nitb/osmo-nitb...done. (gdb) run Starting program: /opt/openbsc/openbsc/src/osmo-nitb/osmo-nitb [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/i386-linux-gnu/i686/cmov/libthread_db.so.1". <0018> input/lapd.c:212 LAPD Allocating SAP for SAPI=62 / TEI=1 <0018> input/lapd.c:223 k=1 N200=3 N201=260 T200=1.0 T203=10.0 <0018> input/lapd.c:485 LAPD DL-ESTABLISH request TEI=1 SAPI=62 DB: Database initialized. DB: Database prepared. <001d> sms_queue.c:220 Attempting to send 20 SMS <0018> input/lapd.c:624 LAPD DL-ESTABLISH confirm TEI=1 SAPI=62 <0005> bts_nokia_site.c:58 bootstrapping OML for BTS 0 <0005> bts_nokia_site.c:1679 ABIS_OM_MDISC_FOM <0005> bts_nokia_site.c:1507 (0x81) NOKIA_BTS_ACK <0005> bts_nokia_site.c:1539 ACK = 1 <0018> input/lapd.c:513 LAPD DL-RELEASE request TEI=1 SAPI=62 <0018> input/lapd.c:628 LAPD DL-RELEASE confirm TEI=1 SAPI=62 Program received signal SIGSEGV, Segmentation fault. 0xb7f96f00 in lapd_send_i (line=line at entry=1609, lctx=, lctx=) at lapd_core.c:1803 1803 if (!dl->tx_hist[h].msg) { (gdb) bt full #0 0xb7f96f00 in lapd_send_i (line=line at entry=1609, lctx=, lctx=) at lapd_core.c:1803 dl = 0x8157510 k = 1 '\001' msg = length = left = rc = nctx = {dl = 0x8157510, n201 = -1208330011, cr = 219 '\333', sapi = 200 '\310', tei = 245 '\365', lpd = 183 '\267', format = 254 '\376', p_f = 255 '\377', n_send = 255 '\377', n_recv = 255 '\377', s_u = 3 '\003', length = -1208330011, more = 62 '>'} #1 0xb7f99ac3 in lapd_rx_i (lctx=0xbffff9b4, msg=0x815d708) at lapd_core.c:1609 dl = 0x8157510 ns = 0 '\000' length = rc = #2 lapd_ph_data_ind (msg=msg at entry=0x815d708, lctx=lctx at entry=0xbffff9b4) at lapd_core.c:1644 rc = #3 0xb7f4aafa in lapd_receive (li=0x81333f8, msg=msg at entry=0x815d708, error=error at entry=0xbffffa2c) at input/lapd.c:461 i = 4 lctx = {dl = 0x8157510, n201 = 260, cr = 0 '\000', sapi = 62 '>', tei = 1 '\001', lpd = 0 '\000', format = 1 '\001', p_f = 0 '\000', n_send = 0 '\000', n_recv = 1 '\001', s_u = 0 '\000', length = 12, more = 0 '\000'} rc = 135476652 sap = teip = 0x815d708 #4 0xb7f426e6 in e1inp_rx_ts_lapd (e1i_ts=e1i_ts at entry=0x8133ad4, msg=msg at entry=0x815d708) at e1_input.c:556 sapi = 62 tei = 1 ret = 0 error = 0 #5 0xb7f460ee in handle_ts1_read (bfd=0x8134040) at input/dahdi.c:190 line = msg = 0x815d708 ret = 18 ts_nr = e1i_ts = 0x8133ad4 #6 dahdi_fd_cb (bfd=0x8134040, what=1) at input/dahdi.c:376 line = ts_nr = idx = e1i_ts = rc = 0 ---Type to continue, or q to quit--- #7 0xb7f5a7e2 in osmo_select_main (polling=polling at entry=0) at select.c:158 flags = ufd = 0x8134040 tmp = 0x81345c8 readset = {__fds_bits = {0 }} writeset = {__fds_bits = {0 }} exceptset = {__fds_bits = {0 }} work = 1 rc = no_time = {tv_sec = 0, tv_usec = 0} #8 0x0804d481 in main (argc=1, argv=0xbffffd84) at bsc_hack.c:346 rc = (gdb) list 1798 } 1799 1800 h = do_mod(dl->v_send, dl->range_hist); 1801 1802 /* if we have no tx_hist yet, we create it */ 1803 if (!dl->tx_hist[h].msg) { 1804 /* Get next message into send-buffer, if any */ 1805 if (!dl->send_buffer) { 1806 next_message: 1807 dl->send_out = 0; (gdb) Regards, Caleb From holger at freyther.de Tue Oct 29 07:32:51 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 29 Oct 2013 08:32:51 +0100 Subject: Nokia Insite OpenBSC Segfault In-Reply-To: <001801ced451$d2c09900$7841cb00$@net> References: <001801ced451$d2c09900$7841cb00$@net> Message-ID: <20131029073251.GO15067@xiaoyu.lan> On Mon, Oct 28, 2013 at 07:51:52PM -0700, Caleb Pal wrote: > Program received signal SIGSEGV, Segmentation fault. > 0xb7f96f00 in lapd_send_i (line=line at entry=1609, lctx= variable: Unhandled dwarf expression opcode 0xfa>, > lctx=) > at lapd_core.c:1803 > 1803 if (!dl->tx_hist[h].msg) { use after free. Please see the mailinglist archive[1][2] for discussions about it. Bugfixes welcome! kind regards holger [1] http://lists.osmocom.org/pipermail/openbsc/2013-June/004682.html [2] http://lists.osmocom.org/pipermail/openbsc/2013-July/004691.html From dchardware at gmail.com Tue Oct 29 09:28:05 2013 From: dchardware at gmail.com (Sipos Csaba) Date: Tue, 29 Oct 2013 10:28:05 +0100 Subject: Nokia Insite OpenBSC Segfault In-Reply-To: References: Message-ID: <773996068.20131029102805@freemail.hu> Hi Caleb, The segfault is introduced with this patch: http://cgit.osmocom.org/libosmocore/commit/?id=f5a079f739c57d8be7c59149fd45475c402a45fc Is is not really a bugfix, but if you just comment out the following part from lapd_core.c added by the above patch and recompile openbsc, it will help: dl->tx_hist = NULL; The problem is probably related to the RESET function, because Nokia units are being reset during the initialization phase, and bootstrapped after that. The reason for this is if this reset is not concluded, then the BTS will not apply certain configuration parameters (e.g. change in ARFCN, transmit power, timeslot configuration). I strongly suggest you anyway, to start with TCF/F FR configuration, and if you see major alarm "BCF operation degraded: difference between PCM and BTS clock", it means that your E1 card is not able to provide accurate enough timing for the BTS. According to Nokia, you need +-5Hz accuracy on the E1 to meet the timing requirements, but even then at least 20-25 minutes of operation is needed for the BTS clock to be synced and the alarm goes away. Usually DAHDI or other E1 cards clock are not precise enough but don't worry: even with the alarm you can make pretty good quality phone calls, but remember: if you experience severe call quality degradation, or the phones cannot camp, or they loosing the network all the time, it is going to be a timing related problem. Anyway, do you have the Nokia InSite manager software? If not just write me a mail and I can help with that. You definitely going to need that and an LMP cable to do the initial setup, before you can get started with OpenBSC. BR, Csaba From dchardware at gmail.com Tue Oct 29 10:33:45 2013 From: dchardware at gmail.com (Sipos Csaba) Date: Tue, 29 Oct 2013 11:33:45 +0100 Subject: New handover algorithm with Nokia BTS In-Reply-To: References: Message-ID: <1775378469.20131029113345@freemail.hu> I just wanted to ask before I spend a lot of time with it. Does the new HO algorithm also works with non-IP based BTSes like Nokia metro or insite? Or at least in theory it should work? Because the handover is not working with the current algo for Nokia, I want to give the new one a try. Csaba From jerlbeck at sysmocom.de Tue Oct 29 08:30:30 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 29 Oct 2013 09:30:30 +0100 Subject: [PATCH 1/2] vty: Use vty_install_default() instead of bsc_install_default() Message-ID: <1383035431-17978-1-git-send-email-jerlbeck@sysmocom.de> Remove ournode_exit_cmd, ournode_end_cmd, and bsc_install_default() since this functionality is provided by the current libosmocore. Replace calls to bsc_install_default() by call to vty_install_default() with the following semantic patch: @rule1@ expression N; @@ - bsc_install_default(N); + vty_install_default(N); Ticket: OW#952 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/vty.h | 4 --- openbsc/src/gprs/gb_proxy_vty.c | 2 +- openbsc/src/gprs/sgsn_vty.c | 2 +- openbsc/src/libbsc/abis_nm_vty.c | 2 +- openbsc/src/libbsc/abis_om2000_vty.c | 2 +- openbsc/src/libbsc/bsc_vty.c | 8 +++--- openbsc/src/libcommon/common_vty.c | 44 ----------------------------- openbsc/src/libmgcp/mgcp_vty.c | 4 +-- openbsc/src/libmsc/smpp_vty.c | 5 ++-- openbsc/src/libmsc/vty_interface_layer3.c | 2 +- openbsc/src/osmo-bsc/osmo_bsc_vty.c | 4 +-- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 6 ++-- 12 files changed, 18 insertions(+), 67 deletions(-) diff --git a/openbsc/include/openbsc/vty.h b/openbsc/include/openbsc/vty.h index f74516a..9e07eb7 100644 --- a/openbsc/include/openbsc/vty.h +++ b/openbsc/include/openbsc/vty.h @@ -14,8 +14,6 @@ struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base); extern struct cmd_element cfg_description_cmd; extern struct cmd_element cfg_no_description_cmd; -extern struct cmd_element ournode_exit_cmd; -extern struct cmd_element ournode_end_cmd; enum bsc_vty_node { GSMNET_NODE = _LAST_OSMOVTY_NODE + 1, @@ -42,8 +40,6 @@ enum bsc_vty_node { extern int bsc_vty_is_config_node(struct vty *vty, int node); extern void bsc_replace_string(void *ctx, char **dst, const char *newstr); -void bsc_install_default(enum node_type node); - struct log_info; int bsc_vty_init(const struct log_info *cat); int bsc_vty_init_extra(void); diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c index 82d49ca..2de0d3b 100644 --- a/openbsc/src/gprs/gb_proxy_vty.c +++ b/openbsc/src/gprs/gb_proxy_vty.c @@ -85,7 +85,7 @@ int gbproxy_vty_init(void) install_element(CONFIG_NODE, &cfg_gbproxy_cmd); install_node(&gbproxy_node, config_write_gbproxy); - bsc_install_default(GBPROXY_NODE); + vty_install_default(GBPROXY_NODE); install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd); return 0; diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c index 8106b7d..5fb7145 100644 --- a/openbsc/src/gprs/sgsn_vty.c +++ b/openbsc/src/gprs/sgsn_vty.c @@ -418,7 +418,7 @@ int sgsn_vty_init(void) install_element(CONFIG_NODE, &cfg_sgsn_cmd); install_node(&sgsn_node, config_write_sgsn); - bsc_install_default(SGSN_NODE); + vty_install_default(SGSN_NODE); install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd); install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd); //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd); diff --git a/openbsc/src/libbsc/abis_nm_vty.c b/openbsc/src/libbsc/abis_nm_vty.c index 5db667d..a14e5c2 100644 --- a/openbsc/src/libbsc/abis_nm_vty.c +++ b/openbsc/src/libbsc/abis_nm_vty.c @@ -183,7 +183,7 @@ int abis_nm_vty_init(void) install_element(ENABLE_NODE, &oml_classnum_inst_cmd); install_node(&oml_node, dummy_config_write); - bsc_install_default(OML_NODE); + vty_install_default(OML_NODE); install_element(OML_NODE, &oml_chg_adm_state_cmd); install_element(OML_NODE, &oml_opstart_cmd); diff --git a/openbsc/src/libbsc/abis_om2000_vty.c b/openbsc/src/libbsc/abis_om2000_vty.c index eb8f4d5..8325e29 100644 --- a/openbsc/src/libbsc/abis_om2000_vty.c +++ b/openbsc/src/libbsc/abis_om2000_vty.c @@ -445,7 +445,7 @@ int abis_om2k_vty_init(void) install_element(ENABLE_NODE, &om2k_classnum_inst_cmd); install_node(&om2k_node, dummy_config_write); - bsc_install_default(OM2K_NODE); + vty_install_default(OM2K_NODE); install_element(OM2K_NODE, &om2k_reset_cmd); install_element(OM2K_NODE, &om2k_start_cmd); install_element(OM2K_NODE, &om2k_status_cmd); diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 5d03b2a..5a9976b 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -3101,7 +3101,7 @@ int bsc_vty_init(const struct log_info *cat) install_element(CONFIG_NODE, &cfg_net_cmd); install_node(&net_node, config_write_net); - bsc_install_default(GSMNET_NODE); + vty_install_default(GSMNET_NODE); install_element(GSMNET_NODE, &cfg_net_ncc_cmd); install_element(GSMNET_NODE, &cfg_net_mnc_cmd); install_element(GSMNET_NODE, &cfg_net_name_short_cmd); @@ -3137,7 +3137,7 @@ int bsc_vty_init(const struct log_info *cat) install_element(GSMNET_NODE, &cfg_bts_cmd); install_node(&bts_node, config_write_bts); - bsc_install_default(BTS_NODE); + vty_install_default(BTS_NODE); install_element(BTS_NODE, &cfg_bts_type_cmd); install_element(BTS_NODE, &cfg_description_cmd); install_element(BTS_NODE, &cfg_no_description_cmd); @@ -3199,7 +3199,7 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_trx_cmd); install_node(&trx_node, dummy_config_write); - bsc_install_default(TRX_NODE); + vty_install_default(TRX_NODE); install_element(TRX_NODE, &cfg_trx_arfcn_cmd); install_element(TRX_NODE, &cfg_description_cmd); install_element(TRX_NODE, &cfg_no_description_cmd); @@ -3211,7 +3211,7 @@ int bsc_vty_init(const struct log_info *cat) install_element(TRX_NODE, &cfg_ts_cmd); install_node(&ts_node, dummy_config_write); - bsc_install_default(TS_NODE); + vty_install_default(TS_NODE); install_element(TS_NODE, &cfg_ts_pchan_cmd); install_element(TS_NODE, &cfg_ts_pchan_compat_cmd); install_element(TS_NODE, &cfg_ts_tsc_cmd); diff --git a/openbsc/src/libcommon/common_vty.c b/openbsc/src/libcommon/common_vty.c index 0bf43b0..3f8f16f 100644 --- a/openbsc/src/libcommon/common_vty.c +++ b/openbsc/src/libcommon/common_vty.c @@ -118,40 +118,6 @@ enum node_type bsc_vty_go_parent(struct vty *vty) return vty->node; } -/* Down vty node level. */ -gDEFUN(ournode_exit, - ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n") -{ - bsc_vty_go_parent (vty); - return CMD_SUCCESS; -} - -/* End of configuration. */ -gDEFUN(ournode_end, - ournode_end_cmd, "end", "End current mode and change to enable mode.") -{ - enum node_type last_node = CONFIG_NODE; - - if (vty->node > ENABLE_NODE) { - /* Repeatedly call go_parent until a top node is reached. */ - while (vty->node > CONFIG_NODE) { - if (vty->node == last_node) { - /* Ensure termination, this shouldn't happen. */ - break; - } - last_node = vty->node; - bsc_vty_go_parent(vty); - } - - vty_config_unlock(vty); - if (vty->node > ENABLE_NODE) - vty->node = ENABLE_NODE; - vty->index = NULL; - vty->index_sub = NULL; - } - return CMD_SUCCESS; -} - int bsc_vty_is_config_node(struct vty *vty, int node) { switch (node) { @@ -174,13 +140,3 @@ void bsc_replace_string(void *ctx, char **dst, const char *newstr) talloc_free(*dst); *dst = talloc_strdup(ctx, newstr); } - -void bsc_install_default(enum node_type node) -{ - install_default (node); - - if (node > CONFIG_NODE) { - install_element(node, &ournode_exit_cmd); - install_element(node, &ournode_end_cmd); - } -} diff --git a/openbsc/src/libmgcp/mgcp_vty.c b/openbsc/src/libmgcp/mgcp_vty.c index 9421f4f..3c239d8 100644 --- a/openbsc/src/libmgcp/mgcp_vty.c +++ b/openbsc/src/libmgcp/mgcp_vty.c @@ -786,7 +786,7 @@ int mgcp_vty_init(void) install_element(CONFIG_NODE, &cfg_mgcp_cmd); install_node(&mgcp_node, config_write_mgcp); - bsc_install_default(MGCP_NODE); + vty_install_default(MGCP_NODE); install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd); install_element(MGCP_NODE, &cfg_mgcp_bts_ip_cmd); install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd); @@ -818,7 +818,7 @@ int mgcp_vty_init(void) install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd); install_node(&trunk_node, config_write_trunk); - bsc_install_default(TRUNK_NODE); + vty_install_default(TRUNK_NODE); install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd); install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd); install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old); diff --git a/openbsc/src/libmsc/smpp_vty.c b/openbsc/src/libmsc/smpp_vty.c index bf503f5..75427a9 100644 --- a/openbsc/src/libmsc/smpp_vty.c +++ b/openbsc/src/libmsc/smpp_vty.c @@ -509,7 +509,7 @@ static int config_write_esme(struct vty *v) int smpp_vty_init(void) { install_node(&smpp_node, config_write_smpp); - bsc_install_default(SMPP_NODE); + vty_install_default(SMPP_NODE); install_element(CONFIG_NODE, &cfg_smpp_cmd); install_element(SMPP_NODE, &cfg_smpp_port_cmd); @@ -519,7 +519,7 @@ int smpp_vty_init(void) install_element(SMPP_NODE, &cfg_no_esme_cmd); install_node(&esme_node, config_write_esme); - bsc_install_default(SMPP_ESME_NODE); + vty_install_default(SMPP_ESME_NODE); install_element(SMPP_ESME_NODE, &cfg_esme_passwd_cmd); install_element(SMPP_ESME_NODE, &cfg_esme_no_passwd_cmd); install_element(SMPP_ESME_NODE, &cfg_esme_route_pfx_cmd); @@ -532,7 +532,6 @@ int smpp_vty_init(void) install_element(SMPP_ESME_NODE, &cfg_esme_no_osmo_ext_cmd); install_element(SMPP_ESME_NODE, &cfg_esme_dcs_transp_cmd); install_element(SMPP_ESME_NODE, &cfg_esme_no_dcs_transp_cmd); - install_element(SMPP_ESME_NODE, &ournode_exit_cmd); install_element_ve(&show_esme_cmd); diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c index e0324d6..7869d5b 100644 --- a/openbsc/src/libmsc/vty_interface_layer3.c +++ b/openbsc/src/libmsc/vty_interface_layer3.c @@ -1002,7 +1002,7 @@ int bsc_vty_init_extra(void) install_element(CONFIG_NODE, &cfg_mncc_int_cmd); install_node(&mncc_int_node, config_write_mncc_int); - bsc_install_default(MNCC_INT_NODE); + vty_install_default(MNCC_INT_NODE); install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd); install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd); diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c index fceaa4a..4fac8ea 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c @@ -676,7 +676,7 @@ int bsc_vty_init_extra(void) install_element(CONFIG_NODE, &cfg_net_bsc_cmd); install_node(&bsc_node, config_write_bsc); - bsc_install_default(BSC_NODE); + vty_install_default(BSC_NODE); install_element(BSC_NODE, &cfg_net_bsc_mid_call_text_cmd); install_element(BSC_NODE, &cfg_net_bsc_mid_call_timeout_cmd); install_element(BSC_NODE, &cfg_net_rf_socket_cmd); @@ -686,7 +686,7 @@ int bsc_vty_init_extra(void) install_element(BSC_NODE, &cfg_net_bsc_no_missing_msc_text_cmd); install_node(&msc_node, config_write_msc); - bsc_install_default(MSC_NODE); + vty_install_default(MSC_NODE); install_element(MSC_NODE, &cfg_net_bsc_token_cmd); install_element(MSC_NODE, &cfg_net_bsc_ncc_cmd); install_element(MSC_NODE, &cfg_net_bsc_mcc_cmd); diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 72a6801..8dea34e 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -1192,7 +1192,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) /* nat group */ install_element(CONFIG_NODE, &cfg_nat_cmd); install_node(&nat_node, config_write_nat); - bsc_install_default(NAT_NODE); + vty_install_default(NAT_NODE); install_element(NAT_NODE, &cfg_nat_msc_ip_cmd); install_element(NAT_NODE, &cfg_nat_msc_port_cmd); install_element(NAT_NODE, &cfg_nat_auth_time_cmd); @@ -1233,14 +1233,14 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element(NAT_NODE, &cfg_nat_pgroup_cmd); install_element(NAT_NODE, &cfg_nat_no_pgroup_cmd); install_node(&pgroup_node, config_write_pgroup); - bsc_install_default(PGROUP_NODE); + vty_install_default(PGROUP_NODE); install_element(PGROUP_NODE, &cfg_pgroup_lac_cmd); install_element(PGROUP_NODE, &cfg_pgroup_no_lac_cmd); /* BSC subgroups */ install_element(NAT_NODE, &cfg_bsc_cmd); install_node(&bsc_node, config_write_bsc); - bsc_install_default(NAT_BSC_NODE); + vty_install_default(NAT_BSC_NODE); install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_lac_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_no_lac_cmd); -- 1.7.9.5 From jerlbeck at sysmocom.de Tue Oct 29 08:30:31 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 29 Oct 2013 09:30:31 +0100 Subject: [PATCH 2/2] vty: Enable the end/exit test for libosmocore nodes In-Reply-To: <1383035431-17978-1-git-send-email-jerlbeck@sysmocom.de> References: <1383035431-17978-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1383035431-17978-2-git-send-email-jerlbeck@sysmocom.de> This patch replaces the calls to ignoredCheckForEndAndExit by calls to checkForEndAndExit to test the libosmocore nodes, too. The former method is removed. Sponsored-by: On-Waves ehf --- openbsc/tests/vty_test_runner.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 18cf688..45b0c06 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -67,18 +67,11 @@ class TestVTYGenericBSC(TestVTYBase): self.assert_(res.find(' end\r') > 0) #print 'found "end"\n' - def ignoredCheckForEndAndExit(self): - sys.stderr.write('Going to ignore the next assertion(s) due to known bugs\n') - try: - self.checkForEndAndExit() - except BaseException as e: - sys.stderr.write('Expected and ignored failure: %s\n' % (str(e))) - def _testConfigNetworkTree(self): self.vty.enable() self.assertTrue(self.vty.verify("configure terminal",[''])) self.assertEquals(self.vty.node(), 'config') - self.ignoredCheckForEndAndExit() + self.checkForEndAndExit() self.assertTrue(self.vty.verify("network",[''])) self.assertEquals(self.vty.node(), 'config-net') self.checkForEndAndExit() @@ -129,7 +122,7 @@ class TestVTYNITB(TestVTYGenericBSC): self.vty.enable() self.assertTrue(self.vty.verify("configure terminal", [''])) self.assertEquals(self.vty.node(), 'config') - self.ignoredCheckForEndAndExit() + self.checkForEndAndExit() self.assertTrue(self.vty.verify('mncc-int', [''])) self.assertEquals(self.vty.node(), 'config-mncc-int') self.checkForEndAndExit() @@ -139,7 +132,7 @@ class TestVTYNITB(TestVTYGenericBSC): self.assertEquals(self.vty.node(), 'config') self.assertTrue(self.vty.verify('smpp', [''])) self.assertEquals(self.vty.node(), 'config-smpp') - self.ignoredCheckForEndAndExit() + self.checkForEndAndExit() self.assertTrue(self.vty.verify("exit", [''])) self.assertEquals(self.vty.node(), 'config') @@ -247,7 +240,7 @@ class TestVTYBSC(TestVTYGenericBSC): self.vty.enable() self.assertTrue(self.vty.verify("configure terminal", [''])) self.assertEquals(self.vty.node(), 'config') - self.ignoredCheckForEndAndExit() + self.checkForEndAndExit() self.assertTrue(self.vty.verify("msc 0", [''])) self.assertEquals(self.vty.node(), 'config-msc') self.checkForEndAndExit() @@ -378,7 +371,7 @@ class TestVTYNAT(TestVTYGenericBSC): self.vty.enable() self.assertTrue(self.vty.verify('configure terminal', [''])) self.assertEquals(self.vty.node(), 'config') - self.ignoredCheckForEndAndExit() + self.checkForEndAndExit() self.assertTrue(self.vty.verify('mgcp', [''])) self.assertEquals(self.vty.node(), 'config-mgcp') self.checkForEndAndExit() @@ -508,7 +501,7 @@ class TestVTYGbproxy(TestVTYGenericBSC): self.vty.enable() self.assertTrue(self.vty.verify('configure terminal', [''])) self.assertEquals(self.vty.node(), 'config') - self.ignoredCheckForEndAndExit() + self.checkForEndAndExit() self.assertTrue(self.vty.verify('ns', [''])) self.assertEquals(self.vty.node(), 'config-ns') self.checkForEndAndExit() -- 1.7.9.5 From dchardware at gmail.com Tue Oct 29 15:59:32 2013 From: dchardware at gmail.com (Sipos Csaba) Date: Tue, 29 Oct 2013 16:59:32 +0100 Subject: Abis RSL and channel allocation issue In-Reply-To: References: Message-ID: <411407237.20131029165932@freemail.hu> I am more and more sure that the my failing handover situation has a deeper root cause and it is not actually the handover which is failing, but there should be a channel allocation problem. And there it is. The following log is made during the send of an SMS to the mobile from the BSC CLI: Tue Oct 29 15:06:15 2013 <001e> sms_queue.c:220 Attempting to send 20 SMS Tue Oct 29 15:06:15 2013 <0000> chan_alloc.c:457 (bts=0,trx=0,ts=0,ss=1) starting release sequence Tue Oct 29 15:06:15 2013 <0000> abis_rsl.c:892 (bts=0,trx=0,ts=0,ss=1) RSL RLL RELEASE REQ (link_id=0x03, reason=1) Tue Oct 29 15:06:15 2013 <0003> gsm_04_08_utils.c:231 Sending Channel Release: Chan: Number: 1 Type: 1 Tue Oct 29 15:06:15 2013 <0004> abis_rsl.c:634 (bts=0,trx=0,ts=0,ss=1) DEACTivate SACCH CMD Tue Oct 29 15:06:15 2013 <0004> abis_rsl.c:1070 (bts=0,trx=0,ts=0,ss=1): MEAS RES for inactive channel Tue Oct 29 15:06:15 2013 <001a> input/dahdi.c:320 send returns -1 instead of 160 Tue Oct 29 15:06:15 2013 <001a> input/dahdi.c:320 send returns -1 instead of 160 Tue Oct 29 15:06:15 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=1) SAPI=0 RELEASE INDICATION Tue Oct 29 15:06:15 2013 <0004> abis_rsl.c:1628 (bts=0,trx=0,ts=0,ss=1) waiting for SAPI=3 to be released. Tue Oct 29 15:06:21 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=1) SAPI=3 Tue Oct 29 15:06:21 2013 <0000> abis_rsl.c:1599 (bts=0,trx=0,ts=0,ss=1) ERROR INDICATION cause=Timer T200 expired (N200+1) times Tue Oct 29 15:06:21 2013 <0004> abis_rsl.c:680 (bts=0,trx=0,ts=0,ss=1) RF Channel Release CMD due error 1 Tue Oct 29 15:06:21 2013 <0004> abis_rsl.c:634 (bts=0,trx=0,ts=0,ss=1) DEACTivate SACCH CMD Tue Oct 29 15:06:21 2013 <0000> abis_rsl.c:892 (bts=0,trx=0,ts=0,ss=1) RSL RLL RELEASE REQ (link_id=0x03, reason=1) Tue Oct 29 15:06:21 2013 <0004> abis_rsl.c:732 (bts=0,trx=0,ts=0,ss=1) RF CHANNEL RELEASE ACK Tue Oct 29 15:06:23 2013 <0004> abis_rsl.c:649 (bts=0,trx=0,ts=0,ss=1) is back in operation. As you can see, although SAPI=3 was requested to be release, we never got any RELEASE INDICATION for that. And after some time, the radio link will be disconnected with T200 timeout. I tried to send another SMS the same way like above, and get a more interesting log: Tue Oct 29 15:54:45 2013 <001e> sms_queue.c:220 Attempting to send 20 SMS Tue Oct 29 15:54:46 2013 <0000> chan_alloc.c:457 (bts=0,trx=0,ts=0,ss=1) starting release sequence Tue Oct 29 15:54:46 2013 <0000> abis_rsl.c:892 (bts=0,trx=0,ts=0,ss=1) RSL RLL RELEASE REQ (link_id=0x03, reason=1) Tue Oct 29 15:54:46 2013 <0003> gsm_04_08_utils.c:231 Sending Channel Release: Chan: Number: 1 Type: 1 Tue Oct 29 15:54:46 2013 <0004> abis_rsl.c:634 (bts=0,trx=0,ts=0,ss=1) DEACTivate SACCH CMD Tue Oct 29 15:54:46 2013 <001a> input/dahdi.c:320 send returns -1 instead of 160 Tue Oct 29 15:54:46 2013 <001a> input/dahdi.c:320 send returns -1 instead of 160 Tue Oct 29 15:54:46 2013 <0004> abis_rsl.c:1070 (bts=0,trx=0,ts=0,ss=1): MEAS RES for inactive channel Tue Oct 29 15:54:46 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=1) SAPI=0 RELEASE INDICATION Tue Oct 29 15:54:46 2013 <0004> abis_rsl.c:1628 (bts=0,trx=0,ts=0,ss=1) waiting for SAPI=3 to be released. ... Tue Oct 29 16:00:46 2013 <0004> abis_rsl.c:1467 (bts=0,trx=0,ts=0,ss=2) Activating ARFCN(885) SS(2) lctype SDCCH r=LOCATION_UPDATE ra=0x08 ta=0 Tue Oct 29 16:00:46 2013 <0004> abis_rsl.c:1169 (bts=0,trx=0,ts=0,ss=2) CHANNEL ACTIVATE ACK As you can see, SAPI=3 again not getting released properly, but this time there is not even a T200 timeout and the SACCH channel got stuck, never released. The last two line is the periodic LA update, and you can see that it uses ss=2, because the BSC thinks that ss=1 is still in use. This is the very same issue I noticed with the handover: Fri Jul 26 12:45:29 2013 <000c> handover_decision.c:203 (bts=0,trx=0,ts=2): Cell on ARFCN 123 is better: Fri Jul 26 12:45:29 2013 <000c> handover_logic.c:96 (old_lchan on BTS 0, new BTS 1) Starting handover Fri Jul 26 12:45:29 2013 <0004> abis_rsl.c:1165 (bts=1,trx=0,ts=2,ss=0) CHANNEL ACTIVATE ACK Fri Jul 26 12:45:29 2013 <000c> handover_logic.c:204 handover activate ack, send HO Command Fri Jul 26 12:45:29 2013 <0004> abis_rsl.c:1138 (bts=1,trx=0,ts=2,ss=0) HANDOVER DETECT access delay = 0 Fri Jul 26 12:45:29 2013 <0000> abis_rsl.c:1621 (bts=1,trx=0,ts=2,ss=0) SAPI=0 ESTABLISH INDICATION Fri Jul 26 12:45:29 2013 <0000> abis_rsl.c:1621 (bts=1,trx=0,ts=2,ss=0) SAPI=0 DATA INDICATION Fri Jul 26 12:45:29 2013 <0003> bsc_api.c:515 HANDOVER COMPLETE cause = Normal event Fri Jul 26 12:45:29 2013 <000c> handover_logic.c:261 Subscriber 244153333330126 HO from BTS 0->1 on ARFCN 885->123 Fri Jul 26 12:45:29 2013 <0000> chan_alloc.c:405 (bts=0,trx=0,ts=2,ss=0) starting release sequence Fri Jul 26 12:45:29 2013 <0000> abis_rsl.c:891 (bts=0,trx=0,ts=2,ss=0) RSL RLL RELEASE REQ (link_id=0x00, reason=1) Fri Jul 26 12:45:29 2013 <0004> abis_rsl.c:1069 (bts=0,trx=0,ts=2,ss=0): MEAS RES for inactive channel Fri Jul 26 12:45:30 2013 <0004> abis_rsl.c:1069 (bts=0,trx=0,ts=2,ss=0): MEAS RES for inactive channel Fri Jul 26 12:45:30 2013 <0004> abis_rsl.c:1069 (bts=0,trx=0,ts=2,ss=0): MEAS RES for inactive channel ...... Fri Jul 26 12:45:40 2013 <0004> abis_rsl.c:1069 (bts=0,trx=0,ts=2,ss=0): MEAS RES for inactive channel Fri Jul 26 12:45:42 2013 <0004> abis_rsl.c:1069 (bts=0,trx=0,ts=2,ss=0): MEAS RES for inactive channel Fri Jul 26 12:45:43 2013 <0004> abis_rsl.c:1069 (bts=0,trx=0,ts=2,ss=0): MEAS RES for inactive channel Fri Jul 26 12:45:44 2013 <0004> abis_rsl.c:1069 (bts=0,trx=0,ts=2,ss=0): MEAS RES for inactive channel Fri Jul 26 12:45:44 2013 <0004> abis_rsl.c:988 (bts=0,trx=0,ts=2,ss=0) CONNECTION FAIL: RELEASING CAUSE=0x01(Radio Link Failure)  Fri Jul 26 12:45:44 2013 <0004> abis_rsl.c:679 (bts=0,trx=0,ts=2,ss=0) RF Channel Release CMD due error 1 Fri Jul 26 12:45:44 2013 <0004> abis_rsl.c:633 (bts=0,trx=0,ts=2,ss=0) DEACTivate SACCH CMD Fri Jul 26 12:45:44 2013 <0000> abis_rsl.c:891 (bts=0,trx=0,ts=2,ss=0) RSL RLL RELEASE REQ (link_id=0x40, reason=1) Fri Jul 26 12:45:44 2013 <0004> abis_rsl.c:1069 (bts=0,trx=0,ts=2,ss=0): MEAS RES for inactive channel Fri Jul 26 12:45:44 2013 <0004> abis_rsl.c:731 (bts=0,trx=0,ts=2,ss=0) RF CHANNEL RELEASE ACK Fri Jul 26 12:45:46 2013 <0004> abis_rsl.c:648 (bts=0,trx=0,ts=2,ss=0) is back in operation. As you can see, from the BSC point of view the handover was successful, but it was not able to release the old channel, we never got any RELEASE INDICATION. This is why we get the Radio Link Failure eventually, because the phone is not there anymore, but the channel yet not closed. Because the release of the old channel is not successful, OpenBSC never tries to remap the TRAU to the new channel, therefore both phones got disconnected (properly). This is as far as I can get with this problem. Maybe now that I narrowed down the root cause, someone can help me with it. I still think this problem is not Nokia specific, maybe other BTSes are affected (BS11 or other E1 based units). Csaba From holger at freyther.de Tue Oct 29 19:42:28 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 29 Oct 2013 20:42:28 +0100 Subject: Abis RSL and channel allocation issue In-Reply-To: <411407237.20131029165932@freemail.hu> References: <411407237.20131029165932@freemail.hu> Message-ID: <20131029194228.GH6152@xiaoyu.lan> On Tue, Oct 29, 2013 at 04:59:32PM +0100, Sipos Csaba wrote: > Tue Oct 29 15:06:21 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=1) SAPI=3 Tue Oct 29 15:06:21 2013 <0000> abis_rsl.c:1599 (bts=0,trx=0,ts=0,ss=1) ERROR INDICATION cause=Timer T200 expired (N200+1) times was SAPI=3 ever established? Is T3109 0 for you? You might want to change that too. > I still think this problem is not Nokia specific, maybe other BTSes > are affected (BS11 or other E1 based units). What is the issue with the BS11? Maybe it is something as simple as the local end release being nrpken in the Nokia BTS? From dchardware at gmail.com Tue Oct 29 22:01:24 2013 From: dchardware at gmail.com (Sipos Csaba) Date: Tue, 29 Oct 2013 23:01:24 +0100 Subject: Abis RSL and channel allocation issue In-Reply-To: <20131029194228.GH6152@xiaoyu.lan> References: <411407237.20131029165932@freemail.hu> <20131029194228.GH6152@xiaoyu.lan> Message-ID: <912026565.20131029230124@freemail.hu> Hello Holger, > was SAPI=3 ever established? Of cause it was established. Here is a complete log of the situation with SMS: Tue Oct 29 21:21:40 2013 <001e> sms_queue.c:220 Attempting to send 20 SMS Tue Oct 29 21:21:42 2013 <0004> abis_rsl.c:1467 (bts=0,trx=0,ts=0,ss=0) Activating ARFCN(885) SS(0) lctype SDCCH r=LOCATION_UPDATE ra=0x16 ta=0 Tue Oct 29 21:21:42 2013 <0004> abis_rsl.c:1169 (bts=0,trx=0,ts=0,ss=0) CHANNEL ACTIVATE ACK Tue Oct 29 21:21:42 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=0) SAPI=0 ESTABLISH INDICATION Tue Oct 29 21:21:42 2013 <0003> gsm_04_08.c:1187 PAGING RESPONSE: mi_type=0x04 MI(2040770818) Tue Oct 29 21:21:42 2013 <0003> gsm_04_08.c:1205 <- Channel was requested by 244153333330127 Tue Oct 29 21:21:42 2013 <0001> transaction.c:69 subscr=0x9ad51f0, subscr->net=0x9a90248 Tue Oct 29 21:21:42 2013 <0000> abis_rsl.c:866 (bts=0,trx=0,ts=0,ss=0) RSL RLL ESTABLISH REQ (link_id=0x03) Tue Oct 29 21:21:42 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=0) SAPI=0 DATA INDICATION Tue Oct 29 21:21:42 2013 <0003> bsc_api.c:615 CLASSMARK CHANGE CM2(len=3) CM3(len=9) Tue Oct 29 21:21:42 2013 <001a> input/dahdi.c:320 send returns -1 instead of 160 Tue Oct 29 21:21:42 2013 <001a> input/dahdi.c:320 send returns -1 instead of 160 Tue Oct 29 21:21:43 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=0) SAPI=3 ESTABLISH CONFIRM Tue Oct 29 21:21:44 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=0) SAPI=3 DATA INDICATION Tue Oct 29 21:21:44 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=0) SAPI=3 DATA INDICATION Tue Oct 29 21:21:45 2013 <001e> sms_queue.c:220 Attempting to send 20 SMS Tue Oct 29 21:21:45 2013 <0000> chan_alloc.c:457 (bts=0,trx=0,ts=0,ss=0) starting release sequence Tue Oct 29 21:21:45 2013 <0000> abis_rsl.c:892 (bts=0,trx=0,ts=0,ss=0) RSL RLL RELEASE REQ (link_id=0x03, reason=1) Tue Oct 29 21:21:45 2013 <0003> gsm_04_08_utils.c:231 Sending Channel Release: Chan: Number: 0 Type: 1 Tue Oct 29 21:21:45 2013 <0004> abis_rsl.c:634 (bts=0,trx=0,ts=0,ss=0) DEACTivate SACCH CMD Tue Oct 29 21:21:45 2013 <0004> abis_rsl.c:1070 (bts=0,trx=0,ts=0,ss=0): MEAS RES for inactive channel Tue Oct 29 21:21:45 2013 <001a> input/dahdi.c:320 send returns -1 instead of 160 Tue Oct 29 21:21:45 2013 <001a> input/dahdi.c:320 send returns -1 instead of 160 Tue Oct 29 21:21:45 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=0) SAPI=0 RELEASE INDICATION Tue Oct 29 21:21:45 2013 <0004> abis_rsl.c:1628 (bts=0,trx=0,ts=0,ss=0) waiting for SAPI=3 to be released. Tue Oct 29 21:21:51 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=0) SAPI=3 Tue Oct 29 21:21:51 2013 <0000> abis_rsl.c:1599 (bts=0,trx=0,ts=0,ss=0) ERROR INDICATION cause=Timer T200 expired (N200+1) times Tue Oct 29 21:21:51 2013 <0004> abis_rsl.c:680 (bts=0,trx=0,ts=0,ss=0) RF Channel Release CMD due error 1 Tue Oct 29 21:21:51 2013 <0004> abis_rsl.c:634 (bts=0,trx=0,ts=0,ss=0) DEACTivate SACCH CMD Tue Oct 29 21:21:51 2013 <0000> abis_rsl.c:892 (bts=0,trx=0,ts=0,ss=0) RSL RLL RELEASE REQ (link_id=0x03, reason=1) Tue Oct 29 21:21:51 2013 <0004> abis_rsl.c:732 (bts=0,trx=0,ts=0,ss=0) RF CHANNEL RELEASE ACK Tue Oct 29 21:21:53 2013 <0004> abis_rsl.c:649 (bts=0,trx=0,ts=0,ss=0) is back in operation. > Is T3109 0 for you? You might want to change that too. Yes, it was 0, I raised it to 10, but it doesn't change anything, all the problems still exists. Should I try and change other timers too? > Maybe it is something as simple as the local end release being nrpken in the Nokia BTS? You mean the local end release being broken in the BTS? How can I find this out? I see your point, that the release command has been sent, but we never got any ACK or something like that back. But how is it possible that it works for SAPI=0 and it does not for SAPI=3 ? These units were used by big organizations to improve the indoor coverage, I really don't think that the BTS or its firmware is wrong by design. Maybe OpenBSC destroys SAPI=0 too fast, and there is not enough time for this: <0000> abis_rsl.c:892 (bts=0,trx=0,ts=0,ss=0) RSL RLL RELEASE REQ (link_id=0x03, reason=1) to be ACKed by the BTS? Here is another log from the failing handover initiated by the Openbsc VTY "handover" command. THe handover is failing even if I move the phone within the same TRX to another channel: Silent call for the MS started (SDCCH): Tue Oct 29 21:28:37 2013 <0004> abis_rsl.c:1467 (bts=0,trx=0,ts=0,ss=0) Activating ARFCN(885) SS(0) lctype SDCCH r=LOCATION_UPDATE ra=0x1f ta=0 Tue Oct 29 21:28:37 2013 <0004> abis_rsl.c:1169 (bts=0,trx=0,ts=0,ss=0) CHANNEL ACTIVATE ACK Tue Oct 29 21:28:38 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=0) SAPI=0 ESTABLISH INDICATION Tue Oct 29 21:28:38 2013 <0003> gsm_04_08.c:1187 PAGING RESPONSE: mi_type=0x04 MI(2040680933) Tue Oct 29 21:28:38 2013 <0003> gsm_04_08.c:1205 <- Channel was requested by 244153333330127 Tue Oct 29 21:28:38 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=0,ss=0) SAPI=0 DATA INDICATION Tue Oct 29 21:28:38 2013 <0003> bsc_api.c:615 CLASSMARK CHANGE CM2(len=3) CM3(len=9) The handover command given in Openbsc VTY (% Handover started from (bts=0,trx=0,ts=0,ss=0) to (bts=0,trx=0,ts=2,ss=0): Tue Oct 29 21:28:50 2013 <000c> handover_logic.c:66 (BTS 0 (subscr 244153333330127)) Start Handover Tue Oct 29 21:28:50 2013 <0004> abis_rsl.c:1169 (bts=0,trx=0,ts=2,ss=0) CHANNEL ACTIVATE ACK Tue Oct 29 21:28:50 2013 <000c> handover_logic.c:66 (BTS 0 (subscr 244153333330127)) Channel activate ack, send HO/AS Command Tue Oct 29 21:28:51 2013 <0004> abis_rsl.c:1142 (bts=0,trx=0,ts=2,ss=0) HANDOVER DETECT access delay = 0 Tue Oct 29 21:28:51 2013 <000c> handover_logic.c:66 (BTS 0 (subscr 244153333330127)) Handover RACH detected Tue Oct 29 21:28:51 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=2,ss=0) SAPI=0 ESTABLISH INDICATION Tue Oct 29 21:28:51 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=2,ss=0) SAPI=0 DATA INDICATION Tue Oct 29 21:28:51 2013 <0003> bsc_api.c:651 HANDOVER COMPLETE cause = Normal event Tue Oct 29 21:28:51 2013 <000c> handover_logic.c:66 (BTS 0 (subscr 244153333330127)) Handover/Assignment completed Handover success from BSC point of view, but we have to close the old chan first: Tue Oct 29 21:28:51 2013 <0000> chan_alloc.c:457 (bts=0,trx=0,ts=0,ss=0) starting release sequence Tue Oct 29 21:28:51 2013 <0000> abis_rsl.c:892 (bts=0,trx=0,ts=0,ss=0) RSL RLL RELEASE REQ (link_id=0x00, reason=1) Tue Oct 29 21:28:51 2013 <0004> abis_rsl.c:1070 (bts=0,trx=0,ts=0,ss=0): MEAS RES for inactive channel ............................... Tue Oct 29 21:29:20 2013 <0004> abis_rsl.c:1070 (bts=0,trx=0,ts=0,ss=0): MEAS RES for inactive channel Which is not happening despite we given the command, and times out after "radio-link-timeout 16": Tue Oct 29 21:29:20 2013 <0004> abis_rsl.c:989 (bts=0,trx=0,ts=0,ss=0) CONNECTION FAIL: RELEASING CAUSE=0x01(Radio Link Failure) Tue Oct 29 21:29:20 2013 <0004> abis_rsl.c:680 (bts=0,trx=0,ts=0,ss=0) RF Channel Release CMD due error 1 Tue Oct 29 21:29:20 2013 <0004> abis_rsl.c:634 (bts=0,trx=0,ts=0,ss=0) DEACTivate SACCH CMD Tue Oct 29 21:29:20 2013 <0000> abis_rsl.c:892 (bts=0,trx=0,ts=0,ss=0) RSL RLL RELEASE REQ (link_id=0x00, reason=1) Tue Oct 29 21:29:20 2013 <0004> abis_rsl.c:1070 (bts=0,trx=0,ts=0,ss=0): MEAS RES for inactive channel Tue Oct 29 21:29:20 2013 <0004> abis_rsl.c:732 (bts=0,trx=0,ts=0,ss=0) RF CHANNEL RELEASE ACK Tue Oct 29 21:29:22 2013 <0004> abis_rsl.c:649 (bts=0,trx=0,ts=0,ss=0) is back in operation. The slient call is still working on the new channel, so I gave command to close it (silent-call stop): Tue Oct 29 21:29:49 2013 <0000> chan_alloc.c:457 (bts=0,trx=0,ts=2,ss=0) starting release sequence Tue Oct 29 21:29:49 2013 <0003> gsm_04_08_utils.c:231 Sending Channel Release: Chan: Number: 0 Type: 2 Tue Oct 29 21:29:49 2013 <0004> abis_rsl.c:634 (bts=0,trx=0,ts=2,ss=0) DEACTivate SACCH CMD Tue Oct 29 21:29:49 2013 <0004> abis_rsl.c:1070 (bts=0,trx=0,ts=2,ss=0): MEAS RES for inactive channel Tue Oct 29 21:29:49 2013 <0000> abis_rsl.c:1657 (bts=0,trx=0,ts=2,ss=0) SAPI=0 RELEASE INDICATION Tue Oct 29 21:29:49 2013 <0004> abis_rsl.c:680 (bts=0,trx=0,ts=2,ss=0) RF Channel Release CMD due error 0 Tue Oct 29 21:29:49 2013 <0004> abis_rsl.c:732 (bts=0,trx=0,ts=2,ss=0) RF CHANNEL RELEASE ACK I hope someone can help me with this. I think we are close to solve this problem. BR, Csaba From holger at freyther.de Wed Oct 30 06:36:14 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Wed, 30 Oct 2013 07:36:14 +0100 Subject: Abis RSL and channel allocation issue In-Reply-To: <912026565.20131029230124@freemail.hu> References: <411407237.20131029165932@freemail.hu> <20131029194228.GH6152@xiaoyu.lan> <912026565.20131029230124@freemail.hu> Message-ID: <20131030063614.GI6152@xiaoyu.lan> On Tue, Oct 29, 2013 at 11:01:24PM +0100, Sipos Csaba wrote: > You mean the local end release being broken in the BTS? How can I find > this out? I see your point, that the release command has been sent, > but we never got any ACK or something like that back. But how is it > possible that it works for SAPI=0 and it does not for SAPI=3 ? These > units were used by big organizations to improve the indoor coverage, I > really don't think that the BTS or its firmware is wrong by design. > > Maybe OpenBSC destroys SAPI=0 too fast, and there is not enough time > for this: Check rsl_release_sapis_from and the caller in _lchan_handle_release. First everything from 1 t X is released and the SACCH deactivated. Play with that, or attempt to get a trace of a Nokia BTS with a Nokia BSC and look at there release procedure. E.g. if order or release requests kinds are different. From dchardware at gmail.com Tue Oct 29 16:14:26 2013 From: dchardware at gmail.com (Sipos Csaba) Date: Tue, 29 Oct 2013 17:14:26 +0100 Subject: Abis RSL and channel allocation issue In-Reply-To: References: Message-ID: <101684353.20131029171426@freemail.hu> For my previous post in the subject: show lchan clearly indicates that the logical connections were never got disconnected. When the above output as made, there were no activity on the BTS for more than 20 minutes, yet these channels are not released: OpenBSC# show lchan BTS 0, TRX 0, Timeslot 0, Lchan 0: Type SDCCH Connection: 0, State: RELEASE REQUESTED BS Power: 22 dBm, MS Power: 26 dBm No Subscriber Measurement Report: Flags: DLinval RXL-FULL-ul: -110 dBm, RXL-SUB-ul: -110 dBm RXQ-FULL-ul: 0, RXQ-SUB-ul: 0 BTS 0, TRX 0, Timeslot 0, Lchan 1: Type SDCCH Connection: 0, State: RELEASE REQUESTED BS Power: 22 dBm, MS Power: 26 dBm No Subscriber Measurement Report: Flags: DLinval RXL-FULL-ul: -110 dBm, RXL-SUB-ul: -110 dBm RXQ-FULL-ul: 0, RXQ-SUB-ul: 0 BTS 0, TRX 0, Timeslot 0, Lchan 2: Type SDCCH Connection: 0, State: RELEASE REQUESTED BS Power: 22 dBm, MS Power: 26 dBm No Subscriber Measurement Report: Flags: DLinval RXL-FULL-ul: -110 dBm, RXL-SUB-ul: -110 dBm RXQ-FULL-ul: 0, RXQ-SUB-ul: 0 BTS 0, TRX 0, Timeslot 0, Lchan 3: Type SDCCH Connection: 0, State: RELEASE REQUESTED BS Power: 22 dBm, MS Power: 26 dBm No Subscriber Measurement Report: Flags: L1 MS Power: 26 dBm, Timing Advance: 0 RXL-FULL-dl: -47 dBm, RXL-SUB-dl: -47 dBm RXQ-FULL-dl: 0, RXQ-SUB-dl: 0 RXL-FULL-ul: -47 dBm, RXL-SUB-ul: -47 dBm RXQ-FULL-ul: 0, RXQ-SUB-ul: 0 BTS 0, TRX 0, Timeslot 1, Lchan 0: Type SDCCH Connection: 0, State: RELEASE REQUESTED BS Power: 22 dBm, MS Power: 26 dBm No Subscriber Measurement Report: Flags: DLinval RXL-FULL-ul: -110 dBm, RXL-SUB-ul: -110 dBm RXQ-FULL-ul: 0, RXQ-SUB-ul: 0 OpenBSC# With this method I can fill the whole signalling capacity of the BTS without any actual call or SMS being sent. Csaba From Jason.DSouza at octasic.com Wed Oct 30 11:11:48 2013 From: Jason.DSouza at octasic.com (Jason DSouza) Date: Wed, 30 Oct 2013 11:11:48 +0000 Subject: Openbsc support for new BTS Message-ID: <813F249CA3F4814F9249E5253FFA7CC2496EA33A@MAIL2.octasic.com> Hello Harald and everyone out there! I have been going through your Osmocom projects especially Openbsc (osmo-nitb) and Osmobts projects and I must say it's a real great work! I'm a lead engineer at Octasic and after looking at your work on OpenBSC and OsmoBTS, we decided to use your OpenBSC stack for internal testing of our Octasic PHY. I know currently openbsc supports few BTS models like ip.access, sysmocom etc. I have gone through the wiki and some of the openbsc archives. I could find an archive regarding Octasic SDR, but I guess it has not gone any further. http://lists.osmocom.org/pipermail/openbsc/2010-November/002196.html I will be interested in osmo-nitb which I can use for network part of GSM and use osmo-bts for BTS L2/L3 stuff, which already has abis-over-ip interface to openBSC(osmo-nitb). I have Octasic SDR hardware that has the layer1 (DSP image), so all I need to implement is the interfaces between Octasic Layer1 and osmobts L2/L3 to communicate between them, which I'm working on. I have already installed openbsc (osmo-nitb) and also osmobts on my Debian 7.1.0. I'm currently in a process of writing interfaces between Octasic L1 and osmobts. I'm using the default config file openbsc.cfg for osmo-nitb & using ip.access config file for osmobts (with changes in the OML ip & band GSM900) At present I'm trying to get TRX config request from osmo-nitb. However though I'm receiving few OML messages like NM_MT_SET_BTS_ATTR (pcap attached), I guess they are specific to ip.access BTS, I'm not able to see any TRX config request coming from osmo-nitb (Or by any chance is that what I'm receiving is the TRX config one?) I'm simply sending ack for those OML messages and eventually expecting a TRX config request from osmo-nitb. I'm not sure if osmo-nitb expects something to se sent from BTS side, looks like it is simply waiting for something(see below). I have tried to run osmo-nitb program and it look like: ./osmo-nitb -c openbsc.cfg <0019> input/ipaccess.c:934 enabling ipaccess BSC mode DB: Database initialized. DB: Database prepared. <001d> sms_queue.c:220 Attempting to send 20 SMS <0019> input/ipa.c:323 accept()ed new link from 127.0.0.1 to port 3002 (I do not see RSL link becoming up here) I tried turn on debug: ./osmo-nitb -c openbsc.cfg -C --debug=DRLL:DCC:DMM:DRR:DRSL:DNM DB: Database initialized. DB: Database prepared. <0005> abis_nm.c:315 OC=SITE-MANAGER(00) INST=(ff,ff,ff) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=BTS(01) INST=(00,ff,ff) STATE CHG: OP_STATE=NULL AVAIL=Dependency(05) <0005> abis_nm.c:1442 Set BTS Attr (bts=0) <0005> abis_nm.c:1763 OC=BTS(01) INST=(00,ff,ff) Sending OPSTART <0005> abis_nm.c:315 OC=GPRS-NSE(f0) INST=(00,ff,ff) STATE CHG: OP_STATE=NULL AVAIL=Dependency(05) <0005> abis_nm.c:315 OC=GPRS-CELL(f1) INST=(00,ff,ff) STATE CHG: OP_STATE=NULL AVAIL=Dependency(05) <0005> abis_nm.c:315 OC=GPRS-NSVC(f2) INST=(00,00,ff) STATE CHG: OP_STATE=NULL AVAIL=Dependency(05) <0005> abis_nm.c:315 OC=GPRS-NSVC(f2) INST=(00,01,ff) STATE CHG: OP_STATE=NULL AVAIL=Dependency(05) <0005> abis_nm.c:315 OC=RADIO-CARRIER(02) INST=(00,00,ff) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=BASEBAND-TRANSCEIVER(04) INST=(00,00,ff) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,00) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,01) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,02) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,03) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,04) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,05) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,06) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,07) STATE CHG: OP_STATE=NULL AVAIL=Power off(02) <0005> abis_nm.c:315 OC=BTS(01) INST=(00,ff,ff) STATE CHG: OP_STATE=Enabled AVAIL=Dependency(05) <0005> abis_nm.c:1442 Set BTS Attr (bts=0) <0005> abis_nm.c:1763 OC=BTS(01) INST=(00,ff,ff) Sending OPSTART And then BSC keeps waiting here though at osmobts - osmo-nitb interface IPACCESS ping-pong goes on for keep-alive of the abis OML link and after some time, Osmobts reports link down(see attached osmo-bts debug). At present, I have just created socket interface from osmo-bts to octasic L1 and I'm in the process of writing interfaces for the messages. I'm expecting 1st message, TRX config request from osmo-nitb and do not see it. I was thinking, once the abis interface is up (OML link), osmo-nitb will trigger TRX configuration and then based on the response from BTS, other configurations. Does osmo-nitb require some kind of handshake from the BTS side to send the TRX configuration? I shall be really grateful to hear advices from the experts out there. I can give you more information if required. Thanks, Jason D'Souza -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: output.txt URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: osmo-nitb.pcap Type: application/octet-stream Size: 7244 bytes Desc: osmo-nitb.pcap URL: From jerlbeck at sysmocom.de Thu Oct 31 09:47:02 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 31 Oct 2013 10:47:02 +0100 Subject: [PATCH] bsc/ussd: Send faked CM Service Accept before sending USSD Message-ID: <1383212822-12424-1-git-send-email-jerlbeck@sysmocom.de> The MS do not show the USSD messages yet. This patch modifies the implementation to insert a CM Service Accept before the ussdNotify to finish the establishment of the MM connection according to 3GPP TS 04.10/3.2.1. This fix has been tested with a Blackberry phone that has shown an ussd_grace_txt after rf_locked has been set to '1'. Without this patch, that message wasn't shown. The phone has sent a CC Setup and other messages before processing the channel release message sent by the BSC, but these messages have not been forwarded to the MSC (as expected). Ticket: OW#957 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gsm_04_08.h | 3 +++ openbsc/src/libmsc/gsm_04_08.c | 4 ++-- openbsc/src/osmo-bsc/Makefile.am | 6 ++++-- openbsc/src/osmo-bsc/osmo_bsc_api.c | 17 +++++++++++------ 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 2f5aaa9..8df7b73 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -39,6 +39,9 @@ void gsm_net_update_ctype(struct gsm_network *net); int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn); int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand, int key_seq); int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn); +int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn); +int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, + enum gsm48_reject_value value); int gsm48_send_rr_release(struct gsm_lchan *lchan); int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv); int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, uint8_t apdu_id, diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index c41443e..df985ca 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -804,14 +804,14 @@ int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn) return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ); } -static int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn) +int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn) { DEBUGP(DMM, "-> CM SERVICE ACK\n"); return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC); } /* 9.2.6 CM service reject */ -static int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, +int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, enum gsm48_reject_value value) { struct msgb *msg; diff --git a/openbsc/src/osmo-bsc/Makefile.am b/openbsc/src/osmo-bsc/Makefile.am index 63972c8..9c091af 100644 --- a/openbsc/src/osmo-bsc/Makefile.am +++ b/openbsc/src/osmo-bsc/Makefile.am @@ -16,5 +16,7 @@ osmo_bsc_LDADD = $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libcommon/libcommon.a \ $(top_builddir)/src/libctrl/libctrl.a \ $(top_builddir)/src/libcommon/libcommon.a \ - $(LIBOSMOSCCP_LIBS) $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS) $(LIBOSMOABIS_LIBS) + -ldbi -ldl $(LIBOSMOSCCP_LIBS) \ + $(LIBSMPP34_LIBS) $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS) \ + $(LIBOSMOABIS_LIBS) diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c index 675bbb2..8288d3b 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_api.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c @@ -87,8 +87,8 @@ static void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, queue_msg_or_return(resp); } -static void bsc_send_ussd_notification(struct gsm_subscriber_connection *conn, - struct msgb *msg, const char *text) +static void bsc_send_ussd_no_srv(struct gsm_subscriber_connection *conn, + struct msgb *msg, const char *text) { struct gsm48_hdr *gh; int8_t pdisc; @@ -119,10 +119,14 @@ static void bsc_send_ussd_notification(struct gsm_subscriber_connection *conn, } if (drop_message) { - LOGP(DMSC, LOGL_DEBUG, "Skipping (not sending) USSD message: '%s'\n", text); + LOGP(DMSC, LOGL_DEBUG, "Skipping (not sending) USSD message: '%s'\n", + text); return; } + LOGP(DMSC, LOGL_INFO, "Sending CM Service Accept\n"); + gsm48_tx_mm_serv_ack(conn); + LOGP(DMSC, LOGL_INFO, "Sending USSD message: '%s'\n", text); gsm0480_send_ussdNotify(conn, 1, text); gsm0480_send_releaseComplete(conn); @@ -143,7 +147,8 @@ static int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg msc = bsc_find_msc(conn, msg); if (!msc) { LOGP(DMSC, LOGL_ERROR, "Failed to find a MSC for a connection.\n"); - bsc_send_ussd_notification(conn, msg, conn->bts->network->bsc_data->ussd_no_msc_txt); + bsc_send_ussd_no_srv(conn, msg, + conn->bts->network->bsc_data->ussd_no_msc_txt); return -1; } @@ -164,9 +169,9 @@ static int complete_layer3(struct gsm_subscriber_connection *conn, if (ret != BSC_CON_SUCCESS) { /* allocation has failed */ if (ret == BSC_CON_REJECT_NO_LINK) - bsc_send_ussd_notification(conn, msg, msc->ussd_msc_lost_txt); + bsc_send_ussd_no_srv(conn, msg, msc->ussd_msc_lost_txt); else if (ret == BSC_CON_REJECT_RF_GRACE) - bsc_send_ussd_notification(conn, msg, msc->ussd_grace_txt); + bsc_send_ussd_no_srv(conn, msg, msc->ussd_grace_txt); return BSC_API_CONN_POL_REJECT; } -- 1.7.9.5 From holger at freyther.de Thu Oct 31 12:38:55 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 31 Oct 2013 13:38:55 +0100 Subject: [PATCH] bsc/ussd: Send faked CM Service Accept before sending USSD In-Reply-To: <1383212822-12424-1-git-send-email-jerlbeck@sysmocom.de> References: <1383212822-12424-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <20131031123855.GA13600@xiaoyu.lan> On Thu, Oct 31, 2013 at 10:47:02AM +0100, Jacob Erlbeck wrote: haha, you got me. I have pushed and reverted your patch. > --- a/openbsc/src/libmsc/gsm_04_08.c > +++ b/openbsc/src/libmsc/gsm_04_08.c > @@ -804,14 +804,14 @@ int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn) > return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ); > } > > -static int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn) > +int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn) > { > DEBUGP(DMM, "-> CM SERVICE ACK\n"); > return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC); > } > > /* 9.2.6 CM service reject */ > -static int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, > +int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, > enum gsm48_reject_value value) no. You need to move this code to the gsm_04_08_utils.c of libbsc. > + -ldbi -ldl $(LIBOSMOSCCP_LIBS) \ > + $(LIBSMPP34_LIBS) $(LIBOSMOCORE_LIBS) \ > + $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS) \ > + $(LIBOSMOABIS_LIBS) eeeek. There is no reason that the BSC should link to libsmpp34 and dbi and dl.. When moving the above code to gsm_04_08_utils.c no Makefile.am change is necessary. > + LOGP(DMSC, LOGL_INFO, "Sending CM Service Accept\n"); > + gsm48_tx_mm_serv_ack(conn); I would prefer if this is the only change your patch is doing inside the BSC. This will ease chery-picking. Feel free to do the renaming of the method after. holger From jerlbeck at sysmocom.de Thu Oct 31 14:36:41 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 31 Oct 2013 15:36:41 +0100 Subject: [PATCH 1/3] bsc: Move gsm48_tx_mm_serv_ack/rej to gsm_04_08_utils.c In-Reply-To: <1383212822-12424-1-git-send-email-jerlbeck@sysmocom.de> References: <1383212822-12424-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1383230203-4786-1-git-send-email-jerlbeck@sysmocom.de> These functions are currently located in libmsc/gsm_04_08.c together with other symbols that (transitively) depend on many external symbols (and thus libraries) that aren't otherwise needed by e.g. osmo-bsc. Since gsm48_tx_mm_serv_ack() will be needed by osmo-bsc, these functions are moved to avoid the dependency on gsm_04_08.o. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gsm_04_08.h | 3 +++ openbsc/src/libbsc/gsm_04_08_utils.c | 34 ++++++++++++++++++++++++++++++++++ openbsc/src/libmsc/gsm_04_08.c | 23 ----------------------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 2f5aaa9..8df7b73 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -39,6 +39,9 @@ void gsm_net_update_ctype(struct gsm_network *net); int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn); int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand, int key_seq); int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn); +int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn); +int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, + enum gsm48_reject_value value); int gsm48_send_rr_release(struct gsm_lchan *lchan); int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv); int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, uint8_t apdu_id, diff --git a/openbsc/src/libbsc/gsm_04_08_utils.c b/openbsc/src/libbsc/gsm_04_08_utils.c index 8ccefd7..a0e7e5d 100644 --- a/openbsc/src/libbsc/gsm_04_08_utils.c +++ b/openbsc/src/libbsc/gsm_04_08_utils.c @@ -36,6 +36,7 @@ #include #include #include +#include /* should ip.access BTS use direct RTP streams between each other (1), * or should OpenBSC always act as RTP relay/proxy in between (0) ? */ @@ -649,3 +650,36 @@ struct msgb *gsm48_create_loc_upd_rej(uint8_t cause) gh->data[0] = cause; return msg; } + +/* 9.2.5 CM service accept */ +int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn) +{ + struct msgb *msg = gsm48_msgb_alloc(); + struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + + msg->lchan = conn->lchan; + + gh->proto_discr = GSM48_PDISC_MM; + gh->msg_type = GSM48_MT_MM_CM_SERV_ACC; + + DEBUGP(DMM, "-> CM SERVICE ACK\n"); + + return gsm0808_submit_dtap(conn, msg, 0, 0); +} + +/* 9.2.6 CM service reject */ +int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, + enum gsm48_reject_value value) +{ + struct msgb *msg; + + msg = gsm48_create_mm_serv_rej(value); + if (!msg) { + LOGP(DMM, LOGL_ERROR, "Failed to allocate CM Service Reject.\n"); + return -1; + } + + DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value); + + return gsm0808_submit_dtap(conn, msg, 0, 0); +} diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index c41443e..3cfc455 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -804,29 +804,6 @@ int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn) return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ); } -static int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn) -{ - DEBUGP(DMM, "-> CM SERVICE ACK\n"); - return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC); -} - -/* 9.2.6 CM service reject */ -static int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, - enum gsm48_reject_value value) -{ - struct msgb *msg; - - msg = gsm48_create_mm_serv_rej(value); - if (!msg) { - LOGP(DMM, LOGL_ERROR, "Failed to allocate CM Service Reject.\n"); - return -1; - } - - DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value); - msg->lchan = conn->lchan; - return gsm48_conn_sendmsg(msg, conn, NULL); -} - static int _gsm48_rx_mm_serv_req_sec_cb( unsigned int hooknum, unsigned int event, struct msgb *msg, void *data, void *param) -- 1.7.9.5 From jerlbeck at sysmocom.de Thu Oct 31 14:36:42 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 31 Oct 2013 15:36:42 +0100 Subject: [PATCH 2/3] bsc/ussd: Send faked CM Service Accept before sending USSD In-Reply-To: <1383230203-4786-1-git-send-email-jerlbeck@sysmocom.de> References: <1383212822-12424-1-git-send-email-jerlbeck@sysmocom.de> <1383230203-4786-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1383230203-4786-2-git-send-email-jerlbeck@sysmocom.de> The MS do not show the USSD messages yet. This patch modifies the implementation to insert a CM Service Accept to finish the establishment of the MM connection according to 3GPP TS 04.10/3.2.1 before the USSD notification is sent. This fix has been tested with a Blackberry phone that has shown an ussd_grace_txt after rf_locked has been set to '1'. Without this patch, that message wasn't shown. The phone has sent a CC Setup and other messages before processing the channel release message sent by the BSC, but these messages have not been forwarded to the MSC (as expected). Ticket: OW#957 Sponsored-by: On-Waves ehf --- openbsc/src/osmo-bsc/osmo_bsc_api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c index 675bbb2..eca2535 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_api.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c @@ -123,6 +123,9 @@ static void bsc_send_ussd_notification(struct gsm_subscriber_connection *conn, return; } + LOGP(DMSC, LOGL_INFO, "Sending CM Service Accept\n"); + gsm48_tx_mm_serv_ack(conn); + LOGP(DMSC, LOGL_INFO, "Sending USSD message: '%s'\n", text); gsm0480_send_ussdNotify(conn, 1, text); gsm0480_send_releaseComplete(conn); -- 1.7.9.5 From jerlbeck at sysmocom.de Thu Oct 31 14:36:43 2013 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 31 Oct 2013 15:36:43 +0100 Subject: [PATCH 3/3] bsc/ussd: Rename bsc_send_ussd_notification() In-Reply-To: <1383230203-4786-1-git-send-email-jerlbeck@sysmocom.de> References: <1383212822-12424-1-git-send-email-jerlbeck@sysmocom.de> <1383230203-4786-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <1383230203-4786-3-git-send-email-jerlbeck@sysmocom.de> Rename this function to bsc_send_ussd_no_srv() since it's a rather specialised function and not a generic USSD notification function. Sponsored-by: On-Waves ehf --- openbsc/src/osmo-bsc/osmo_bsc_api.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c index eca2535..1751df7 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_api.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c @@ -87,8 +87,8 @@ static void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, queue_msg_or_return(resp); } -static void bsc_send_ussd_notification(struct gsm_subscriber_connection *conn, - struct msgb *msg, const char *text) +static void bsc_send_ussd_no_srv(struct gsm_subscriber_connection *conn, + struct msgb *msg, const char *text) { struct gsm48_hdr *gh; int8_t pdisc; @@ -146,7 +146,8 @@ static int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg msc = bsc_find_msc(conn, msg); if (!msc) { LOGP(DMSC, LOGL_ERROR, "Failed to find a MSC for a connection.\n"); - bsc_send_ussd_notification(conn, msg, conn->bts->network->bsc_data->ussd_no_msc_txt); + bsc_send_ussd_no_srv(conn, msg, + conn->bts->network->bsc_data->ussd_no_msc_txt); return -1; } @@ -167,9 +168,9 @@ static int complete_layer3(struct gsm_subscriber_connection *conn, if (ret != BSC_CON_SUCCESS) { /* allocation has failed */ if (ret == BSC_CON_REJECT_NO_LINK) - bsc_send_ussd_notification(conn, msg, msc->ussd_msc_lost_txt); + bsc_send_ussd_no_srv(conn, msg, msc->ussd_msc_lost_txt); else if (ret == BSC_CON_REJECT_RF_GRACE) - bsc_send_ussd_notification(conn, msg, msc->ussd_grace_txt); + bsc_send_ussd_no_srv(conn, msg, msc->ussd_grace_txt); return BSC_API_CONN_POL_REJECT; } -- 1.7.9.5