From laforge at gnumonks.org Fri Apr 1 09:45:03 2016 From: laforge at gnumonks.org (Harald Welte) Date: Fri, 1 Apr 2016 11:45:03 +0200 Subject: sccp_helpers: osmo_prim_init() and msgb In-Reply-To: <20160331224913.GA17974@dub6> References: <20160331224913.GA17974@dub6> Message-ID: <20160401094503.GQ26767@nataraja> Hi Neels, On Fri, Apr 01, 2016 at 12:49:13AM +0200, Neels Hofmeyr wrote: > First off, we allocate 1024 bytes of msgb. Into it goes an osmo_scu_prim > struct (here 'prim'). We set some parameters in prim, fair enough. But > now what, prim->oph, the prim header, has a msg pointer, which points back > at the msgb that contains the prim. really?? The msgb containing a struct > pointing back at the same msgb has my head spinning. I actually think it's a pretty straight-forward solution when thinking of of the general problem and the constraints: * we already had 'msgb' handling everywhere in our message processing code and were using it quite happily to pass messages around. * at inter-layer boundaries in the ISO/OSI model, you have primitives that consist of the primitive itself, as well as the payload data. The primitive consists of some operation like N-DATA, plus the associatted request/indication/confirmation/response part. A primitive occors on a given SAP. This was put into struct osmo_prim_hdr * In order to not have the primitive separate and out-of-band, we store it inside the msgb itself. In early versions of some code, we had the osmo_prim_hdr allocated separately and passed both it and the msgb to every function. That was a bit cumbersome and error-prone. * To avoid all the primitive-handling code having to derive the pointer to osmo_prim_hdr as the first line of code, we pass around a pointer to the osmo_prim_hdr itself, rather than a pointer to msgb. This also makes the code more explicit in that you can clearly see that it doesn't expect a generic msgb, but that it deals with a primitive as argument. * As the osmo_prim_hdr is not stored at a fixed offset inside the msgb, we cannot use tricks like 'offset_of()' to get back from the osmo_prim_hdr to the msgb. Thus we store the pointer to the msgb header inside the osmo_prim_hdr. The knowledge of the msgb is needed particularly in case the primitive needs to be free()d. > Finally we add the data, l2h pointing at the start of it. I'm confused ... > how large is the msgb supposed to be? Is it len + sizeof(*prim)? yes, at the very minimum it has to be that size. If you need to determine that frequently, we could add an inline function or macro to the code. > Secondly, let's look at: > > int osmo_sccp_tx_unitdata_msg(struct osmo_sua_link *link, > const struct osmo_sccp_addr *calling_addr, > const struct osmo_sccp_addr *called_addr, > struct msgb *msg) > { > int rc; > > rc = osmo_sccp_tx_unitdata(link, calling_addr, called_addr, > msg->data, msgb_length(msg)); > msgb_free(msg); > > return rc; > } > So, something out there has a msgb containing data. For example, from > ranap_new_msg_paging_cmd(). That msgb has probably been allocated > specifically to compose a message to go over the sccp link. > > We go on, though, to allocate *another* msgb (size 1024, remember), and > memcpy the first msgb into the second msgb, behind the osmo_scu_prim > struct. > > Are there good reasons for this? This function was just a quick wrapper around the already-existing osmo_sccp_tx_unitdata() function, avoiding a copy+paste of that funtion's body. > I would have envisioned something like: tell ranap_new_msg_paging_cmd() to > allocate sizeof(*prim) of headroom; or first create a msgb of fixed > known-max size, and add first the prim header and then compose the data. the problem particularly when interfacing with asn1c generated code is that you end up doing so many copies and dynamic allocations all the time, that it probably hardly matters anymore. It's one hell of inefficiency, at least for from where we come from. > And, given the union prim->u has "unknown" size, why not point at the data > from prim->oph directly, instead of pointing back at the msgb? Or have > that union first? That would be easier to understand. Now you are mixing up the SCCP-User pimitives (osmo_scu_prim) with the generic underlying osmo_prim_hdr layer. osmo_prim_hdr is used in other contexts, including osmo-tetra, for which I first developed it, AFAIR. It is also used in libosmogb, osmocom-bb. It should IMHO be used much more generically at inter-layer boundaries, but a lot of the exiting code pre-dates osmo_prim_hdr. From my point of view, every layer boundary should be using the osmo_prim_hdr construct and associated service access points. To get back to your question: * SCCP Use SAP: prim->u doesn't have unknown size, but has the size of the largest member in the union. You should always allocate memory for sizeof(prim). * prim->oph (osmo_prim_hdr) pointing to the message data is way too restrictive. How would you go back to 'msg' in order to free it? How would yo get to all the other meta-data of a msg that it carries around, like msgb->dst, the header pointers to variuos layers, the msgb->cb information, ..? > If some code needs to know the msgb that contains the prim->oph, I find it > weird to pass it the prim->oph with a backpointer, instead of just passing > the msgb right away. I find that much more convenient instead of having an extra msgb argument to each and every function dealing with osmo_prim_hdr. The goal should be to make it easy for the programmer to write code that is readable, rather than passing around a second pointer that points virtually to the same chunk of data. It also poses the danger of a caller passing a pointer to an oph not inside the msgb (or vice versa), with desastrous results. The only case where you as a user of the primitives really have to worry about it is when you msgb_copy() the msgb holding a primitive. But then, if your get passed an osmo_prim_hdr as argument, you should use a (to be written) dedicated osmo_prim_copy() function, which understands the peculiarities of osmo_prim and performs a msgb_copy() with oph->msg pointer adjustment after the copy. calling msgb_copy() on a oph->msg is just not allowed. But I don't think we have ever needed that so far, that's why the osmo_prim_copy() doesn't exist yet. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From holger at freyther.de Fri Apr 1 17:04:00 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 1 Apr 2016 19:04:00 +0200 Subject: Introducing nightly debian builds In-Reply-To: <8EA504F4-8D3F-4A19-B8FD-E3F693997E71@freyther.de> References: <8EA504F4-8D3F-4A19-B8FD-E3F693997E71@freyther.de> Message-ID: <0C2683A7-DEFE-4385-BBCE-09244702E734@freyther.de> > On 18 Mar 2016, at 20:42, Holger Freyther wrote: > > Hi, Hi! > > What is missing is: > > osmo-trx (in progress) that is available for a bit now. I think the code ends up being optimized for i386 and it would be nice if the users and benefactors of it could have a look and offer an alternative. > osmo-bts I have packages osmo-bts-trx. Again it would be nice if users and benefactors could give it a try, specially the systemd service file. Starting from tonight there should be nightly packages available. As part of the nightly build we will copy the current gsm_data_shared.{c,h} into the osmo-bts directory. I didn't notice that we include the C file through ../../ all the time. :} > osmo-pcu pending, but I will finish it today. holger From holger at freyther.de Fri Apr 1 18:33:33 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 1 Apr 2016 20:33:33 +0200 Subject: [PATCH 1/3] subscr: Add testcase creating an already created subscriber Message-ID: <1459535615-16683-1-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther Add testcase to issue the subscriber create twice. db_create_subscriber in db.c will first try to find the subscriber and if it exists, it will update the "updated" column in the database. Related: OS Issue #1657 --- openbsc/tests/vty_test_runner.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 8db0825..620254e 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -307,6 +307,34 @@ class TestVTYNITB(TestVTYGenericBSC): if classNum != 10: self.assertEquals(res.find("rach access-control-class " + str(classNum) + " barred"), -1) + def testSubscriberCreateDeleteTwice(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) + res2 = self.vty.command('subscriber create imsi '+imsi) + self.assert_(res2.find(" IMSI: "+imsi) > 0) + self.assertEqual(res, res2) + + # Now we have it + res = self.vty.command('show subscriber imsi '+imsi) + self.assert_(res.find(" IMSI: "+imsi) > 0) + + # Delete it + res = self.vty.command('subscriber delete imsi '+imsi) + self.assert_(res != "") + + # Now it should not be there anymore + res = self.vty.command('show subscriber imsi '+imsi) + self.assert_(res != '% No subscriber found for imsi '+imsi) + + def testSubscriberCreateDelete(self): self.vty.enable() -- 2.6.3 From holger at freyther.de Fri Apr 1 18:33:34 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 1 Apr 2016 20:33:34 +0200 Subject: [PATCH 2/3] subscr: Make db_create_subscriber fail on duplicates In-Reply-To: <1459535615-16683-1-git-send-email-holger@freyther.de> References: <1459535615-16683-1-git-send-email-holger@freyther.de> Message-ID: <1459535615-16683-2-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther The issue of db_create_subscriber updating an already existing subcr is that the same subscriber will then have two entries in the active subscribers list. In general this will break assumptions that a subscr can be compared by comparing the pointer. In the case of the VTY this was not an issue as the created subscr was immediately destroyed again but it is better to avoid this problem. Change the VTY command to find the subscriber and then call sync to have the updated time set. The side-effect is we will now have two queries for the subscriber. Once through subscr_get_by_imsi and once through db_create_subscriber. Change the db_create_subscriber to fail if a subscriber already exists, and add a testcase for this behavior. Related: OS Issue #1657 --- openbsc/src/libmsc/db.c | 10 ++-------- openbsc/src/libmsc/vty_interface_layer3.c | 16 +++++++++++----- openbsc/tests/db/db_test.c | 6 +++++- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 0935fc5..17bea24 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -508,14 +508,8 @@ struct gsm_subscriber *db_create_subscriber(const char *imsi) /* Is this subscriber known in the db? */ subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, imsi); if (subscr) { - result = dbi_conn_queryf(conn, - "UPDATE Subscriber set updated = datetime('now') " - "WHERE imsi = %s " , imsi); - if (!result) - LOGP(DDB, LOGL_ERROR, "failed to update timestamp\n"); - else - dbi_result_free(result); - return subscr; + subscr_put(subscr); + return NULL; } subscr = subscr_alloc(); diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c index f49c53a..790fedf 100644 --- a/openbsc/src/libmsc/vty_interface_layer3.c +++ b/openbsc/src/libmsc/vty_interface_layer3.c @@ -236,11 +236,17 @@ DEFUN(subscriber_create, struct gsm_network *gsmnet = gsmnet_from_vty(vty); struct gsm_subscriber *subscr; - subscr = subscr_create_subscriber(gsmnet->subscr_group, argv[0]); - if (!subscr) { - vty_out(vty, "%% No subscriber created for IMSI %s%s", - argv[0], VTY_NEWLINE); - return CMD_WARNING; + subscr = subscr_get_by_imsi(gsmnet->subscr_group, argv[0]); + if (subscr) + db_sync_subscriber(subscr); + else { + subscr = subscr_create_subscriber(gsmnet->subscr_group, 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. */ diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index a02d1f8..fb159a5 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -1,5 +1,5 @@ /* (C) 2008 by Jan Luebbe - * (C) 2009 by Holger Hans Peter Freyther + * (C) 2009-2016 by Holger Hans Peter Freyther * (C) 2014 by Alexander Chemeris * All Rights Reserved * @@ -246,6 +246,10 @@ int main() SUBSCR_PUT(alice_db); SUBSCR_PUT(alice); + /* create it again and see it fails */ + alice = db_create_subscriber(alice_imsi); + OSMO_ASSERT(!alice); + test_sms(); test_sms_migrate(); -- 2.6.3 From holger at freyther.de Fri Apr 1 18:33:35 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 1 Apr 2016 20:33:35 +0200 Subject: [PATCH 3/3] db: If creating a subscriber in the db fails, return NULL In-Reply-To: <1459535615-16683-1-git-send-email-holger@freyther.de> References: <1459535615-16683-1-git-send-email-holger@freyther.de> Message-ID: <1459535615-16683-3-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther We should not return a subscriber in case it was not written to the database. Instead free the memory allocated and return NULL. Callers in gsm_04_08.c are prepared to have the creation fail. Related: OS Issue #1657 --- openbsc/src/libmsc/db.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 17bea24..267b5ef 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -523,8 +523,11 @@ struct gsm_subscriber *db_create_subscriber(const char *imsi) "(%s, datetime('now'), datetime('now')) ", imsi ); - if (!result) + if (!result) { LOGP(DDB, LOGL_ERROR, "Failed to create Subscriber by IMSI.\n"); + subscr_put(subscr); + return NULL; + } subscr->id = dbi_conn_sequence_last(conn, NULL); strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1); dbi_result_free(result); -- 2.6.3 From holger at freyther.de Fri Apr 1 18:36:25 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 1 Apr 2016 20:36:25 +0200 Subject: Introducing nightly debian builds In-Reply-To: <0C2683A7-DEFE-4385-BBCE-09244702E734@freyther.de> References: <8EA504F4-8D3F-4A19-B8FD-E3F693997E71@freyther.de> <0C2683A7-DEFE-4385-BBCE-09244702E734@freyther.de> Message-ID: <290EDC2A-973E-4432-B58E-94976C24AE13@freyther.de> > On 01 Apr 2016, at 19:04, Holger Freyther wrote: > > >> osmo-pcu > > pending, but I will finish it today. and it is available for Debian 8.0 as well. have a nice weekend holger From nhofmeyr at sysmocom.de Fri Apr 1 22:55:43 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Sat, 2 Apr 2016 00:55:43 +0200 Subject: sccp_helpers: osmo_prim_init() and msgb In-Reply-To: <20160401094503.GQ26767@nataraja> References: <20160331224913.GA17974@dub6> <20160401094503.GQ26767@nataraja> Message-ID: <20160401225543.GC15638@dub6> On Fri, Apr 01, 2016 at 11:45:03AM +0200, Harald Welte wrote: > Hi Neels, > > On Fri, Apr 01, 2016 at 12:49:13AM +0200, Neels Hofmeyr wrote: > > First off, we allocate 1024 bytes of msgb. Into it goes an osmo_scu_prim > > struct (here 'prim'). We set some parameters in prim, fair enough. But > > now what, prim->oph, the prim header, has a msg pointer, which points back > > at the msgb that contains the prim. really?? The msgb containing a struct > > pointing back at the same msgb has my head spinning. > > I actually think it's a pretty straight-forward solution when thinking > of of the general problem and the constraints: > > * we already had 'msgb' handling everywhere in our message processing > code and were using it quite happily to pass messages around. Disclaimer ahead: I won't get carried away too far. It's not like I'm going to change the most central building block of the osmoverse any time soon (ever). I just wish it were more explicit and instantly readable. So let's read this not as a proposal to change, but just me getting used to the way it is. I understand that it's handy to use a generic data structure to pass messages around, but with msgb you have to read just about *all* of the code to find out what is stored where in the msgb for a given code path. I think my main problem (again) is that I like things to be explicit and well named in data structures. So much of the msgb use is implicit, like the dst and lNh pointers, particularly the cb[], which makes it hard to wrap your head around, let alone change its use safely. Also, I find the names for data_len vs len, data+tail vs head, quite confusing. It's shaken and stirred ;) Adding a layer of self-reference on top of this makes it even harder to keep a straight head on what's going on. > * at inter-layer boundaries in the ISO/OSI model, you have primitives > that consist of the primitive itself, as well as the payload data. > The primitive consists of some operation like N-DATA, plus the > associatted request/indication/confirmation/response part. A > primitive occors on a given SAP. This was put into struct > osmo_prim_hdr > > * In order to not have the primitive separate and out-of-band, we store > it inside the msgb itself. In early versions of some code, we had the > osmo_prim_hdr allocated separately and passed both it and the msgb to > every function. That was a bit cumbersome and error-prone. If a primitive refers to a msgb, it would be easier to understand to have the msgb as member of the prim struct, allocate it in one go with enough "tail room" for the msgb, and go on passing the prim around. I admit that using the msgb API to allocate the memory in the first place is reducing code duplication. But it is kind of twisted :) > * To avoid all the primitive-handling code having to derive the pointer > to osmo_prim_hdr as the first line of code, we pass around a pointer > to the osmo_prim_hdr itself, rather than a pointer to msgb. This > also makes the code more explicit in that you can clearly see that it > doesn't expect a generic msgb, but that it deals with a primitive as > argument. > > * As the osmo_prim_hdr is not stored at a fixed offset inside the msgb, > we cannot use tricks like 'offset_of()' to get back from the > osmo_prim_hdr to the msgb. Thus we store the pointer to the msgb > header inside the osmo_prim_hdr. The knowledge of the msgb is needed > particularly in case the primitive needs to be free()d. free() is a good point. > > Finally we add the data, l2h pointing at the start of it. I'm confused ... > > how large is the msgb supposed to be? Is it len + sizeof(*prim)? > > yes, at the very minimum it has to be that size. If you need to > determine that frequently, we could add an inline function or macro to > the code. I meant: that function is allocating 1024 bytes, even though it has a len argument and knows sizeof(*prim). It has all the information to allocate precisely the right amount. Can len+sizeof(*prim) > 1024 happen? > the problem particularly when interfacing with asn1c generated code is > that you end up doing so many copies and dynamic allocations all the > time, that it probably hardly matters anymore. It's one hell of > inefficiency, at least for from where we come from. Yes, and arguably it doesn't make that much of a difference in real world terms. (Of course, this mindset taken too far gets you run times and memory usage we know from Java.) > > And, given the union prim->u has "unknown" size, why not point at the data > > from prim->oph directly, instead of pointing back at the msgb? Or have > > that union first? That would be easier to understand. > > Now you are mixing up the SCCP-User pimitives (osmo_scu_prim) with the > generic underlying osmo_prim_hdr layer. osmo_prim_hdr is used in > other contexts, including osmo-tetra, for which I first developed it, > AFAIR. It is also used in libosmogb, osmocom-bb. It should IMHO be > used much more generically at inter-layer boundaries, but a lot of the > exiting code pre-dates osmo_prim_hdr. From my point of view, every > layer boundary should be using the osmo_prim_hdr construct and > associated service access points. > > To get back to your question: > > * SCCP Use SAP: prim->u doesn't have unknown size, but has the size of > the largest member in the union. You should always allocate memory > for sizeof(prim). The image in my mind was that the data starts behind the header. If the header has a union, the data starts behind the union, even though the way the union is used may be smaller. "unknown" is the wrong word, yes... So it's like msgb { <--+ | +- *l2h | | | | | | data | | |prim | | | oph | | | *msgb -+ | | u +->|payload |... | } But this would be easier to read: prim { oph *payload ---+ u | msgb | data <--+ } I assume this is wishful thinking, because functions that currently only know the oph and can free the entire prim via msgb would suddenly have to know about prim too, right? > * prim->oph (osmo_prim_hdr) pointing to the message data is way too > restrictive. How would you go back to 'msg' in order to free it? How > would yo get to all the other meta-data of a msg that it carries > around, like msgb->dst, the header pointers to variuos layers, the > msgb->cb information, ..? Well, I'd kind of wish it didn't have to get back to all the generic bits of meta-data implicitly used in different ways depending on the code path, but that it would name its meta-data explicitly... > I find that much more convenient instead of having an extra msgb > argument to each and every function dealing with osmo_prim_hdr. The No, of course not a second pointer, but one plain structure without self-reference, with names a human coder can relate to... Which gets me back to the disclaimer. I'm not going to rewire the way messages get passed through the layers. I even assume that I'll get used to it and learn to like the current way, once I've seen all constraints. Nevertheless, I find the code is hard to get used to for a newcomer. Thanks for taking the time to write down the reasoning! ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Fri Apr 1 23:47:48 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 2 Apr 2016 01:47:48 +0200 Subject: sccp_helpers: osmo_prim_init() and msgb In-Reply-To: <20160401225543.GC15638@dub6> References: <20160331224913.GA17974@dub6> <20160401094503.GQ26767@nataraja> <20160401225543.GC15638@dub6> Message-ID: <20160401234748.GF11498@nataraja> Hi Neels, On Sat, Apr 02, 2016 at 12:55:43AM +0200, Neels Hofmeyr wrote: > I think my main problem (again) is that I like things to be explicit and > well named in data structures. So much of the msgb use is implicit, like > the dst and lNh pointers, particularly the cb[], which makes it hard to > wrap your head around, let alone change its use safely. Also, I find the > names for data_len vs len, data+tail vs head, quite confusing. It's shaken > and stirred ;) both the cb[] and the member names are inherited from 'struct sk_buff' in the linux kernel, which is what I was used to in my former life (and whihc some other early OpenBSC developers also had at least some exposure to, I believe). > Adding a layer of self-reference on top of this makes it even harder to > keep a straight head on what's going on. I think the main problem is that you have to worry so much about those implementation details. I'm actually surprised by this, as it points out we must have done something wrong, and we should improve the APIs and utilities in a way that you and other developers *using* msgb's and primitivesit have to worry less about it. You shouldn't have to care about the detailed usage of the cb[] as every program / library / protocol stack should have it's own wrappers and inline functions or macros to obtain the respective values, like msgb_bvci() in case if the Gb protocol stack. Similar analogy to the kernel. When you're inside the TCP code, you use the cb[] for a tcp specific structure and there's an easy way to get to that structure or its members. The l2h/l3h should proably be used less and more with a wrapper macro, too. Like 'msgb_rslh()' to get the rsl header, or the like. msgb->l3h should really only be used in cases where there is a clear definiton what the layer3 protocol is. In GSM, it is RR/MM/CC. The problem is that depending on the interface (Abis/A/Iuh/Iub/IuCS), below can be multiple sub-layes of 'layer 2'. > > * In order to not have the primitive separate and out-of-band, we store > > it inside the msgb itself. In early versions of some code, we had the > > osmo_prim_hdr allocated separately and passed both it and the msgb to > > every function. That was a bit cumbersome and error-prone. > > If a primitive refers to a msgb, it would be easier to understand to have > the msgb as member of the prim struct, allocate it in one go with enough > "tail room" for the msgb, and go on passing the prim around. I admit that > using the msgb API to allocate the memory in the first place is reducing > code duplication. But it is kind of twisted :) At some point you receive data from a socket. At this point you only have a msgb, and not yet a primitive. Only later, after some header parsing, you will know you need a primitive, and which type of primitive. So you push the osmo_prim_hdr + SAP specific struct to the msgb, as a shim-header between the different layers in a stack. Sounds pretty straight-forward to me. Think of the SAP and its detailed primitive (including the osmo_prim_hader) as an additional prtocol layer header between two elements of a protocol stack on the local host. And once again my point is: Why would you want to or need to care how the internals are twisted. The only point that detail about the back pointer matters is in case of msgb_copy(), see my previous mail. > > yes, at the very minimum it has to be that size. If you need to > > determine that frequently, we could add an inline function or macro to > > the code. > > I meant: that function is allocating 1024 bytes, even though it has a len > argument and knows sizeof(*prim). It has all the information to allocate > precisely the right amount. Can len+sizeof(*prim) > 1024 happen? Allocating blocks of memory in equal size is often/typically more efficient and leads to less memory fragmentation than allocating odd lengths. This is particularly the case when using talloc pools, like we recently started to do in osmo-bts. In almost all OSmo* code modules, you will find a wrapper around msgb_alloc() or msgb_alloc_headroom(), whcih will typically allocate with a fixed size. See RSL_ALLOC_SIZE, L3_MSG_SIZE, MSGB_MAX, RR_ALLOC_SIZE, GSM_MACBLOCK_LEN, or sometimes hard-coded magic numbers, like in the case of osmo-bts-* definitions of l1p_msgb_alloc() or the like. If the length should ever be larger, then msgb_push() beyond the size of the msgb will OSMO_ASSERT and you see the problem at runtime. I prefer this generally to 'hidden' increase of allocations to a runtime-computed length. The idea is that a developer writing a particular module should generally have an idea about what roughly is the maximum message size at the given protocol that he implements and decide for a reasonable allocation size, including sufficient space in the headroom for what he might push to that msgb, including the respective primtive headers. > > * SCCP Use SAP: prim->u doesn't have unknown size, but has the size of > > the largest member in the union. You should always allocate memory > > for sizeof(prim). > > The image in my mind was that the data starts behind the header. If the > header has a union, the data starts behind the union, even though the way > the union is used may be smaller. "unknown" is the wrong word, yes... > > So it's like > > msgb { <--+ > | > +- *l2h | > | | > | | > | data | > | |prim | > | | oph | > | | *msgb -+ > | | u > +->|payload > |... > | > } > > But this would be easier to read: > > prim { > oph > *payload ---+ > u | > msgb | > data <--+ > } Is it really that much more difficult to write "oph->msg->l2h" than to your proposed "oph->data" ? And if that's the case, why not have a osmo_sua_prim_data(oph) that hides the additional pointer deref from you (and which oould do consistency checking like if oph->sap really is the SAP you expect)? Why would you have to worry or care how things are ordered in memory? I really don't understand this part, sorry ;) Why would you care? Your typical primitive-consuming function gets a 'struct osmo_prim_hdr *' as input, and from there you a) know how to get to the msgb from that (oph->msgb) b) know how to get the SAP-specific larger primitive structure from it (they type-casting macro. You know to what to type-cast by knowing from which SAP you receive primitives. You could even do it dynamically baesd on oph->sap value, or ASSERT to make sure your code is not making the wrong choice here) c) know how to get to a particular layer header at any level of your protocol stack inside the msgb (msgb->l2h/l3h/...) (as indicated, a protocol stack / application / SAP specificmacro/inline function should probably be used anyway to have a more expressive way of what the l2 header at this SAP really is, so think of msgb_suah(oph->msg), msgb_ruah(oph->msg), msgb_iuh(oph->msg) which then resolve to the respective lXh or cb pointer.) And if you want to wrap a msgb in a primitive, the given SAP and related code should contain a convenience function that does that for you, i.e. pushing the SAP-specific structure, including the osmo_prim_hdr at its beginning, to the head of the msgb. Basically a "I want to turn this msgb into a primitive at SAP X, using the following details related to the primitive" > > * prim->oph (osmo_prim_hdr) pointing to the message data is way too > > restrictive. How would you go back to 'msg' in order to free it? How > > would yo get to all the other meta-data of a msg that it carries > > around, like msgb->dst, the header pointers to variuos layers, the > > msgb->cb information, ..? > > Well, I'd kind of wish it didn't have to get back to all the generic bits > of meta-data implicitly used in different ways depending on the code path, > but that it would name its meta-data explicitly... but where should that meta-data be stored and named explicitly? Whats' wrong with having that in msgb->cb, where it is always passed along with the mesasge? Things that I think would improve the situation: * include a 'magic value' in the msgb->cb[] that defines which structure is currently type-casted to it. This way we could have assert-style macros at various places in the code, making sure that nobody is trying to dereference it to the wrong structure * reduce the amount of direct lXh accesses, particularly for != l3h. In fact, they predate the cb, and if we had a cb from the beginning, they might not even have needed to exist. * document the usage of msgb (particularly lXh and cb usage) for each prtoocol/interface/stack/sap. > No, of course not a second pointer, but one plain structure without > self-reference, with names a human coder can relate to... but then you end up copying everything from a msgb (or it's cb) to that new structure and vice versa. I also think the question of naming is a completely separate topic. You can have (from your point of view) better naming also in the current structures / members / apis. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From nhofmeyr at sysmocom.de Sat Apr 2 22:00:03 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Sun, 3 Apr 2016 00:00:03 +0200 Subject: Iuh -> HNB-GW -> Iu: Reset vs. Initial-UE Message-ID: <20160402220003.GA18867@dub6> We've recently noticed that our HNB-GW doesn't ever send an id-Reset to the CN. Now I'm trying to pinpoint precisely when this should happen. For discussion, I'm focusing on CS, though this applies to PS as well. To facilitate paging, the CSCN needs to remember which RNC-Ids it has seen on a given IuCS link. The id-Reset message contains the Global RNC Id and allows the CSCN to know who's connected. So far my thoughts are that the HNB-GW should forward all and any id-Reset messages received from an hNodeB to the connected CSCN. It should look like the RNCs were directly connected to the CN. "Any" number of hNodeBs (each with an own RNC) may be connected to a single HNB-GW, and the CSCN wants to know all of the RNC Ids (and RNC resets) using that SUA link. On the other hand, the Location Update Requests arrive at the CSCN in an initialUE Message, and its RANAP part always contains the Global RNC Id (mandatory). So, technically, the CSCN doesn't need id-Reset messages to find out the RNC Ids. It may simply remember all RNC Ids seen coming in on a given SUA link, be they initial-UE or Reset messages. I wonder though if it should be an error condition to receive a LU Request with an RNC Id that wasn't seen in an id-Reset message yet. My current focus is on paging. So even though the HNB-GW should forward id-Resets, the CSCN can find out RNC Ids from LU requests alone, so I guess I'm postponing the fix of HNB-GW. Any thoughts are welcome. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Sat Apr 2 22:38:51 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Sun, 3 Apr 2016 00:38:51 +0200 Subject: sccp_helpers: osmo_prim_init() and msgb In-Reply-To: <20160401234748.GF11498@nataraja> References: <20160331224913.GA17974@dub6> <20160401094503.GQ26767@nataraja> <20160401225543.GC15638@dub6> <20160401234748.GF11498@nataraja> Message-ID: <20160402223851.GB18867@dub6> On Sat, Apr 02, 2016 at 01:47:48AM +0200, Harald Welte wrote: > You shouldn't have to care about the detailed usage of the cb[] as every > program / library / protocol stack should have it's own wrappers and > inline functions or macros to obtain the respective values ok ... I see. > The l2h/l3h should proably be used less and more with a wrapper macro, > too. Like 'msgb_rslh()' to get the rsl header, or the like. msgb->l3h > should really only be used in cases where there is a clear definiton > what the layer3 protocol is. In GSM, it is RR/MM/CC. The problem is > that depending on the interface (Abis/A/Iuh/Iub/IuCS), below can be > multiple sub-layes of 'layer 2'. GSM is by far the most complex thing I've worked on in terms of layerings and specifications. It often seems so simple to just tell the other side what should happen, but to get it across takes layers of hard work ;) > Allocating blocks of memory in equal size is often/typically more > efficient and leads to less memory fragmentation than allocating odd ok, makes sense. > Is it really that much more difficult to write "oph->msg->l2h" than to [...] > Why would you have to worry or care how things are ordered in memory? I > really don't understand this part, sorry ;) Why would you care? I think my problems start when I "briefly" want to understand everything about a given code path, but am tumbling down a rabbit hole of indirections and generic names used all over the place. Try to grep for 'cb' and you'd get huge amount of hits completely unrelated to a given 'cb' you might want to grok. If things are named explicitly, it's quite easy to grep for source and sinks of values put in it. It's not harder to write things down, It's just often hard to find out on my own what to write down ;) My progress is often slow these days because I try to understand things, and that takes more work than I expect... Well, but I'm getting there. > Your typical primitive-consuming function gets a > 'struct osmo_prim_hdr *' as input, and from there you > > a) know how to get to the msgb from that (oph->msgb) > > b) know how to get the SAP-specific larger primitive structure from it > > c) know how to get to a particular layer header at any level of your > protocol stack inside the msgb (msgb->l2h/l3h/...) With a firm map like this in your head, it sounds quite straightforward, yes. I've come from the other side: I saw a bare msgb struct and didn't know how to navigate it, first need to find the infrastructure around it. > Things that I think would improve the situation: > > * include a 'magic value' in the msgb->cb[] that defines which structure > is currently type-casted to it. This way we could have assert-style > macros at various places in the code, making sure that nobody is > trying to dereference it to the wrong structure > * reduce the amount of direct lXh accesses, particularly for != l3h. In > fact, they predate the cb, and if we had a cb from the beginning, they > might not even have needed to exist. > * document the usage of msgb (particularly lXh and cb usage) for each > prtoocol/interface/stack/sap. Sounds pretty good: a new reader should be guided to the higher level view and specific usage within a given protocol stack. Assertions for 'magic values' in the code could highlight that and guide to the documentation. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Sun Apr 3 20:05:07 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sun, 3 Apr 2016 22:05:07 +0200 Subject: Iuh -> HNB-GW -> Iu: Reset vs. Initial-UE In-Reply-To: <20160402220003.GA18867@dub6> References: <20160402220003.GA18867@dub6> Message-ID: <20160403200507.GB6125@nataraja> Hi Neels, On Sun, Apr 03, 2016 at 12:00:03AM +0200, Neels Hofmeyr wrote: > We've recently noticed that our HNB-GW doesn't ever send an id-Reset to > the CN. Now I'm trying to pinpoint precisely when this should happen. > For discussion, I'm focusing on CS, though this applies to PS as well. It should happen once every time the signalling link between the HNB-GW and the respective CN node is established, or whenever the HNB-GW looses some state and thus wants to request re-initialization of the state on the CN side. > To facilitate paging, the CSCN needs to remember which RNC-Ids it has seen > on a given IuCS link. The id-Reset message contains the Global RNC Id and > allows the CSCN to know who's connected. > > So far my thoughts are that the HNB-GW should forward all and any id-Reset > messages received from an hNodeB to the connected CSCN. It should look > like the RNCs were directly connected to the CN. I don't think so, sorry. One of the major reasons to have a HNB-GW in the HomeNodeB Architecture from my understanding is that you want to "Hide" the presence of potentially tens or hundreds of thousands of femtocells (hNodeB) from your core signalling elements like the MSC. Classic MSCs are not designed to talk to such a large quantity of signalling peers, and most likely run into scalability and/or licensing issues. Just because the situation is different in a new implementation like the Osocom one, we shouldn't throw those principles over board. I therefore think the HNB-GW should try to look only like a single RNC to the MSC, and very clearly only a single RANAP Reset should be sent. Even worse, as all the multiple RANAP Reset you propose to send will originate from the same peer on the SS7/SIGTAN point of view, a "regular" MSC might simply only store the content of the last Reset. Subsequent registrations of hNodeB's would then simply look like a single RNC that is re-configured all the time, and only its most recent global RNC ID is to be stored by the MSC. > On the other hand, the Location Update Requests arrive at the CSCN in an > initialUE Message, and its RANAP part always contains the Global RNC Id > (mandatory). So, technically, the CSCN doesn't need id-Reset messages to > find out the RNC Ids. It may simply remember all RNC Ids seen coming in on > a given SUA link, be they initial-UE or Reset messages. The RANAP Reset is primarily used to determine which resources (connections, state, ...) is to be reset at the time of a reboot/reinitialization/state-loss of the peer. So once a RANAP Reset is received by the MSC, it must release all signalling connections or other resources allocated to any MS/UE within that global RNC ID. > My current focus is on paging. So even though the HNB-GW should forward > id-Resets, the CSCN can find out RNC Ids from LU requests alone, so I > guess I'm postponing the fix of HNB-GW. I think: * A hNodeB sends a HNB-REGISTER-REQUEST to the HNB-GW * The HNB-REGSITER-RESPONSE contains the RNC-ID, i.e. the HNB-GW tells the hNodeB which RNC-ID to use. Each logical HNB-GW has one RNC-ID and thus all hNodeB connected to it should have the same * the hNodeB's will use that RNC-ID and MCC+MNC to construct the GlobalRNC-ID which is used for RANAP signalling, including RANAP Reset towards HNB-GW * irrespective of the Iuh signalling or any hNodeB actually existing in the network, the HNB-GW should always send one RANAP Reset using the same constructed GlobalRNC-ID towards the MSC and SGSN via Iu. This Reset is sent whenever the signalling link towards the CN element is re-established. * The GlobalRNC-ID is used by the MSC to determine the RNC to which to send paging requests. I believe this should be a single Global RNC ID for all femtocells at a HNB-GW. So basically in our primary use case, it will help us to determine to which of the N possible HNB-GWs that are connected we should send the paging request. * The HNB-GW internally uses the IMSI (from the HNBAP UE REGISTER) to determine the hnb-gw (or group of hnb-gws within same LA) to which a paging message should be forwarded. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sun Apr 3 20:27:51 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sun, 3 Apr 2016 22:27:51 +0200 Subject: Iuh -> HNB-GW -> Iu: Reset vs. Initial-UE In-Reply-To: <20160403200507.GB6125@nataraja> References: <20160402220003.GA18867@dub6> <20160403200507.GB6125@nataraja> Message-ID: <20160403202751.GC6125@nataraja> Hi Neels, one more comment: On Sun, Apr 03, 2016 at 10:05:07PM +0200, Harald Welte wrote: > I therefore think the HNB-GW should try to look only like a single RNC > to the MSC, and very clearly only a single RANAP Reset should be sent. One further reason: The RNC-ID only has a range from 0..4095, i.e. if every hNodeB was identified by a separate RNC-ID, you could never have more hNodeBs in your entire network. For public telco networks, 4096 hNodeB (and no macro network!) is certainly not sufficient. That's certainly not how the system was designed. So the HNB-GW serves a similar purpose as the osmo-bsc_nat: To hide many (hnb-internal RNCs) towards a CN element, so the CN element thinks it only deals with very few of them. In fact, a typical "many co-located OsmoBTS+OsmoBSC" talking to bsc_nat is the exact correspondence to the hNodeB (NodeB+RNC) talking to HNB-GW setup in UMTS. With the big difference, that in the UMTS case, there is a specification for such as system, and in the GSM space, it is something that only exists in the Osmocom implementation. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From nhofmeyr at sysmocom.de Mon Apr 4 08:06:59 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 4 Apr 2016 10:06:59 +0200 Subject: Iuh -> HNB-GW -> Iu: Reset vs. Initial-UE In-Reply-To: <20160403200507.GB6125@nataraja> References: <20160402220003.GA18867@dub6> <20160403200507.GB6125@nataraja> Message-ID: <20160404080659.GA7397@dub6> On Sun, Apr 03, 2016 at 10:05:07PM +0200, Harald Welte wrote: > On Sun, Apr 03, 2016 at 12:00:03AM +0200, Neels Hofmeyr wrote: > > We've recently noticed that our HNB-GW doesn't ever send an id-Reset to > > the CN. Now I'm trying to pinpoint precisely when this should happen. > > For discussion, I'm focusing on CS, though this applies to PS as well. > > It should happen once every time the signalling link between the HNB-GW > and the respective CN node is established, or whenever the HNB-GW looses > some state and thus wants to request re-initialization of the state on > the CN side. Ok, good thing I asked, then. So far I assumed that each hNodeB contains an RNC with its own RNC Id, and any number of RNC Ids are sent via the same HNB-GW to the CN. So when the CN pages on Iu, "RNC Id wise" we'd always page on all of the other hNodeBs on the same HNB-GW. It's up to the HNB-GW to remember which IMSIs were last seen on which hNodeB and page only there first. > * A hNodeB sends a HNB-REGISTER-REQUEST to the HNB-GW > * The HNB-REGSITER-RESPONSE contains the RNC-ID, i.e. the HNB-GW > tells the hNodeB which RNC-ID to use. Each logical HNB-GW has one > RNC-ID and thus all hNodeB connected to it should have the same Interesting, because so far I've actually configured the RNC-Id in the hNodeB's config interface (see our wiki page for "UMTS Configuration", which lists the parameter). I wasn't aware yet, but in the pcaps, there is indeed an RNC Id sent from the HNB-GW during the HNB_REGISTER_ACCEPT (e.g. 14). But subsequently the hNodeB sends a different RNC Id (the one configured in the hNodeB settings, e.g. 0). So our hNodeB apparently doesn't remember the RNC Id it receives during the HNB_REGISTER_ACCEPT. What would you say, is this just yet another thing that the operator has to configure correctly? Is it a spec violation by our particular hNodeB? Or should the HNB-GW actually overwrite the RNC-Id going to the CN? Maybe our HNB-GW sends the HNB_REGISTER_ACCEPT incorrectly and the hNodeB refuses to take on the RNC Id? But in that case, I'm pretty sure, it wouldn't accept UE subscribers, as seen when no CN is connected. For the time being I'll just configure the hNodeB and the HNB-GW to use the same RNC Id. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Mon Apr 4 08:16:00 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 4 Apr 2016 10:16:00 +0200 Subject: Iuh -> HNB-GW -> Iu: Reset vs. Initial-UE In-Reply-To: <20160403202751.GC6125@nataraja> References: <20160402220003.GA18867@dub6> <20160403200507.GB6125@nataraja> <20160403202751.GC6125@nataraja> Message-ID: <20160404081600.GB7397@dub6> On Sun, Apr 03, 2016 at 10:27:51PM +0200, Harald Welte wrote: > Hi Neels, > > one more comment: > > On Sun, Apr 03, 2016 at 10:05:07PM +0200, Harald Welte wrote: > > I therefore think the HNB-GW should try to look only like a single RNC > > to the MSC, and very clearly only a single RANAP Reset should be sent. > > One further reason: The RNC-ID only has a range from 0..4095, i.e. if Hold on, in the RANAP specs I see the Extended RNC-ID IE: "The Extended RNC-ID IE shall be used if the RNC identity has a value larger than 4095." It extends the range to ..65535 (9.2.1.39a in 3GPP TS 25.413 version 12.4.0 Release 12). 65536 RNC Ids sounds more reasonable for an entire country, but is still kind of limited. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Mon Apr 4 08:19:41 2016 From: laforge at gnumonks.org (Harald Welte) Date: Mon, 4 Apr 2016 10:19:41 +0200 Subject: Iuh -> HNB-GW -> Iu: Reset vs. Initial-UE In-Reply-To: <20160404080659.GA7397@dub6> References: <20160402220003.GA18867@dub6> <20160403200507.GB6125@nataraja> <20160404080659.GA7397@dub6> Message-ID: <20160404081941.GF6125@nataraja> Hi Neels, On Mon, Apr 04, 2016 at 10:06:59AM +0200, Neels Hofmeyr wrote: > I wasn't aware yet, but in the pcaps, there is indeed an RNC Id sent from > the HNB-GW during the HNB_REGISTER_ACCEPT (e.g. 14). But subsequently the > hNodeB sends a different RNC Id (the one configured in the hNodeB > settings, e.g. 0). So our hNodeB apparently doesn't remember the RNC Id it > receives during the HNB_REGISTER_ACCEPT. > > What would you say, is this just yet another thing that the operator has > to configure correctly? Is it a spec violation by our particular hNodeB? Yes, I think it is a bug / spec violation / different interpretation. > Or should the HNB-GW actually overwrite the RNC-Id going to the CN? No. > For the time being I'll just configure the hNodeB and the HNB-GW to use > the same RNC Id. Ack. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From msuraev at sysmocom.de Mon Apr 4 13:30:56 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 4 Apr 2016 15:30:56 +0200 Subject: [PATCH 4/4] NAT: reload BSCs config dynamically In-Reply-To: <1459776656-31929-1-git-send-email-msuraev@sysmocom.de> References: <1459776656-31929-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1459776656-31929-4-git-send-email-msuraev@sysmocom.de> From: Max Add vty tests for BSC configuration reloading. Load BSCs configuration on bscs-config-file command: * remove all runtime configured BSC not in the config file * close connections to all BSC with updated token value Fixes: OS#1670 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/bsc_nat.h | 7 +- openbsc/src/osmo-bsc_nat/bsc_nat.c | 4 +- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 38 ++++++++- openbsc/tests/vty_test_runner.py | 140 ++++++++++++++++++++++++++++++++- 4 files changed, 183 insertions(+), 6 deletions(-) diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index ab1c590..419f111 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -35,10 +35,11 @@ #include #include +#include #define DIR_BSC 1 #define DIR_MSC 2 - +#define DEFAULT_TOKEN_VALUE "__UNKNOWN__" #define PAGIN_GROUP_UNASSIGNED -1 struct sccp_source_reference; @@ -164,6 +165,10 @@ struct bsc_config { /* audio handling */ int max_endpoints; + /* used internally for reload handling */ + bool remove; + bool token_updated; + /* backpointer */ struct bsc_nat *nat; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index 7dcacfd..9bbb253 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -1321,8 +1321,8 @@ static int ipaccess_bsc_read_cb(struct osmo_fd *bfd) bsc->cfg ? bsc->cfg->nr : -1); else LOGP(DNAT, LOGL_ERROR, - "Stream error on BSC Nr: %d. Failed to parse ip access message: %d\n", - bsc->cfg ? bsc->cfg->nr : -1, ret); + "Stream error on BSC Nr: %d. Failed to parse ip access message: %d (%s)\n", + bsc->cfg ? bsc->cfg->nr : -1, ret, strerror(-ret)); bsc_close_connection(bsc); return -1; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 8def3ed..495e505 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -39,6 +39,7 @@ #include #include +#include static struct bsc_nat *_nat; @@ -512,15 +513,40 @@ DEFUN(cfg_nat_include, "Set the filename of the BSC configuration to include.\n" "The filename to be included.") { + int rc; + struct bsc_config *cf1, *cf2; + struct bsc_connection *con1, *con2; const char *path = bsc_nat_resolve_path(_nat, _nat->include_base, argv[0]); - int rc = vty_read_config_file(path, NULL); + + llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) { + cf1->remove = true; + cf1->token_updated = false; + } + + rc = vty_read_config_file(path, NULL); if (rc < 0) { vty_out(vty, "Failed to parse the config file %s: %s%s", path, strerror(-rc), VTY_NEWLINE); return CMD_WARNING; } + bsc_replace_string(_nat, &_nat->include_file, argv[0]); + + llist_for_each_entry_safe(con1, con2, &_nat->bsc_connections, + list_entry) { + if (con1->cfg) + if (con1->cfg->token_updated || con1->cfg->remove) + bsc_close_connection(con1); + } + + llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) { + if (cf1->remove) { + bsc_config_free(cf1); + _nat->num_bsc--; + } + } + return CMD_SUCCESS; } @@ -836,13 +862,14 @@ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", return CMD_WARNING; } else if (bsc_nr == _nat->num_bsc) { /* allocate a new one */ - bsc = bsc_config_alloc(_nat, "unknown"); + bsc = bsc_config_alloc(_nat, DEFAULT_TOKEN_VALUE); } else bsc = bsc_config_num(_nat, bsc_nr); if (!bsc) return CMD_WARNING; + bsc->remove = false; vty->index = bsc; vty->node = NAT_BSC_NODE; @@ -855,6 +882,13 @@ DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN", { struct bsc_config *conf = vty->index; + if (strncmp(conf->token, DEFAULT_TOKEN_VALUE, 16) != 0 && + strncmp(conf->token, argv[0], 128) != 0) { + vty_out(vty, "updated token: %s -> %s%s", conf->token, argv[0], + VTY_NEWLINE); + conf->token_updated = true; + } + bsc_replace_string(conf, &conf->token, argv[0]); return CMD_SUCCESS; } diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 8db0825..8e117b2 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -584,12 +584,56 @@ class TestVTYBSC(TestVTYGenericBSC): class TestVTYNAT(TestVTYGenericBSC): def vty_command(self): - return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-c", + return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-l", "127.0.0.1", "-c", "doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg"] def vty_app(self): return (4244, "src/osmo-bsc_nat/osmo-bsc_nat", "OsmoBSCNAT", "nat") + def testBSCreload(self): + # use separate ip to avoid interference with other tests + ip = "127.0.0.4" + self.vty.enable() + bscs1 = self.vty.command("show bsc-config") + nat_bsc_reload(self) + bscs2 = self.vty.command("show bsc-config") + # check that multiple calls to bscs-config-file give the same result + self.assertEquals(bscs1, bscs2) + + # add new bsc + self.vty.command("configure terminal") + self.vty.command("nat") + self.vty.command("bsc 2") + self.vty.command("token key") + self.vty.command("location_area_code 666") + self.vty.command("end") + + # update bsc token + self.vty.command("configure terminal") + self.vty.command("nat") + self.vty.command("bsc 1") + self.vty.command("token xyu") + self.vty.command("end") + + nat_msc_ip(self, ip) + msc = nat_msc_test(self, ip) + b0 = nat_bsc_sock_test(0, "lol") + b1 = nat_bsc_sock_test(1, "xyu") + b2 = nat_bsc_sock_test(2, "key") + + self.assertEquals("3 BSCs configured", self.vty.command("show nat bsc")) + self.assertTrue(3 == nat_bsc_num_con(self)) + self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection")) + + nat_bsc_reload(self) + bscs2 = self.vty.command("show bsc-config") + # check that the reset to initial config succeeded + self.assertEquals(bscs1, bscs2) + + self.assertEquals("2 BSCs configured", self.vty.command("show nat bsc")) + self.assertTrue(1 == nat_bsc_num_con(self)) + self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection")) + def testVtyTree(self): self.vty.enable() self.assertTrue(self.vty.verify('configure terminal', [''])) @@ -971,6 +1015,100 @@ def add_nat_test(suite, workdir): test = unittest.TestLoader().loadTestsFromTestCase(TestVTYNAT) suite.addTest(test) +def nat_bsc_reload(x): + x.vty.command("configure terminal") + x.vty.command("nat") + x.vty.command("bscs-config-file bscs.config") + x.vty.command("end") + +def nat_msc_ip(x, ip): + x.vty.command("configure terminal") + x.vty.command("nat") + x.vty.command("msc ip " + ip) + x.vty.command("end") + +def data2str(d): + return "".join("{:02x}".format(ord(c)) for c in d) + +def nat_msc_test(x, ip, verbose = False): + msc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + msc.settimeout(32) + msc.bind((ip, 5000)) + msc.listen(5) + if (verbose): + print "MSC is ready at " + ip + while "MSC is connected: 0" == x.vty.command("show msc connection"): + conn, addr = msc.accept() + if (verbose): + print "MSC got connection from ", addr + return conn + +def ipa_send_pong(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: PONG!" + x.send("\x00\x01\xfe\x01") + +def ipa_send_ping(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: PING?" + x.send("\x00\x01\xfe\x00") + +def ipa_send_ack(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: IPA ID ACK" + x.send("\x00\x01\xfe\x06") + +def ipa_handle_small(x, verbose = False): + s = data2str(x.recv(4)) + if "0001fe00" == s: + if (verbose): + print "\tBSC <- NAT: PING?" + ipa_send_pong(x, verbose) + elif "0001fe06" == s: + if (verbose): + print "\tBSC <- NAT: IPA ID ACK" + ipa_send_ack(x, verbose) + elif "0001fe00" == s: + if (verbose): + print "\tBSC <- NAT: PONG!" + else: + if (verbose): + print "\tBSC <- NAT: ", s + +def ipa_send_reset(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: RESET" + x.send("\x00\x12\xfd\x09\x00\x03\x05\x07\x02\x42\xfe\x02\x42\xfe\x06\x00\x04\x30\x04\x01\x20") + +def ipa_send_resp(x, tk, verbose = False): + if (verbose): + print "\tBSC -> NAT: IPA ID RESP" + x.send("\x00\x07\xfe\x05\x00\x04\x01" + tk) + +def ipa_handle_resp(x, tk, verbose = False): + s = data2str(x.recv(38)) + if "0023fe040108010701020103010401050101010011" in s: + ipa_send_resp(x, tk, verbose) + else: + if (verbose): + print "\tBSC <- NAT: ", s + +def nat_bsc_num_con(x): + return len(x.vty.command("show bsc connections").split('\n')) + +def nat_bsc_sock_test(nr, tk, verbose = False): + bsc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + bsc.bind(('127.0.0.1' + str(nr), 0)) + bsc.connect(('127.0.0.1', 5000)) + if (verbose): + print "BSC%d " %nr + print "\tconnected to %s:%d" % bsc.getpeername() + ipa_handle_small(bsc, verbose) + ipa_handle_resp(bsc, tk, verbose) + bsc.recv(27) # MGCP msg + ipa_handle_small(bsc, verbose) + return bsc + 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") -- 2.8.1 From msuraev at sysmocom.de Mon Apr 4 13:30:53 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 4 Apr 2016 15:30:53 +0200 Subject: [PATCH 1/4] Ignore vty test byproducts Message-ID: <1459776656-31929-1-git-send-email-msuraev@sysmocom.de> From: Max --- openbsc/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openbsc/.gitignore b/openbsc/.gitignore index 28fdcc8..bae3b65 100644 --- a/openbsc/.gitignore +++ b/openbsc/.gitignore @@ -90,3 +90,5 @@ tests/testsuite.log src/openbsc.cfg* +writtenconfig/ +gtphub_restart_count -- 2.8.1 From msuraev at sysmocom.de Mon Apr 4 13:30:54 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 4 Apr 2016 15:30:54 +0200 Subject: [PATCH 2/4] NAT: vty command to display number of BSCs In-Reply-To: <1459776656-31929-1-git-send-email-msuraev@sysmocom.de> References: <1459776656-31929-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1459776656-31929-2-git-send-email-msuraev@sysmocom.de> From: Max Add command 'show nat bsc' to display number of configured BSCs. Sponsored-by: On-Waves ehf --- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index cd8293c..96559b0 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -204,6 +204,14 @@ DEFUN(show_sccp, show_sccp_cmd, "show sccp connections", return CMD_SUCCESS; } +DEFUN(show_nat_bsc, show_nat_bsc_cmd, "show nat bsc", + SHOW_STR "Display NAT configuration details\n" + "BSCs-related\n") +{ + vty_out(vty, "%d BSCs configured%s", _nat->num_bsc, VTY_NEWLINE); + return CMD_SUCCESS; +} + DEFUN(show_bsc, show_bsc_cmd, "show bsc connections", SHOW_STR BSC_STR "All active connections\n") @@ -1169,6 +1177,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) /* show commands */ install_element_ve(&show_sccp_cmd); install_element_ve(&show_bsc_cmd); + install_element_ve(&show_nat_bsc_cmd); install_element_ve(&show_bsc_cfg_cmd); install_element_ve(&show_stats_cmd); install_element_ve(&show_stats_lac_cmd); -- 2.8.1 From msuraev at sysmocom.de Mon Apr 4 13:30:55 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 4 Apr 2016 15:30:55 +0200 Subject: [PATCH 3/4] NAT: move BSC config into separate file In-Reply-To: <1459776656-31929-1-git-send-email-msuraev@sysmocom.de> References: <1459776656-31929-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1459776656-31929-3-git-send-email-msuraev@sysmocom.de> From: Max Introduce new configuration option bscs-config-file which includes BSC configuration from the given file. Both absolute and relative (to the main config file) paths are supported. Add 'show bscs-config' command to display current BSC configuration. Note: it is still possible to have BSC configuration in the main file (provided proper index number is used) and in runtime but BSC configuration is no longer saved automatically. The management of included configuration file is left to external tools. Update configuration examples. Fixes: OS#1669 Sponsored-by: On-Waves ehf --- openbsc/doc/examples/osmo-bsc_nat/bscs.config | 13 +++++++ openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg | 8 +---- openbsc/include/openbsc/bsc_nat.h | 5 +++ openbsc/osmoappdesc.py | 3 ++ openbsc/src/osmo-bsc_nat/bsc_nat.c | 13 ++++++- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 40 ++++++++++++++++++++-- 6 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 openbsc/doc/examples/osmo-bsc_nat/bscs.config diff --git a/openbsc/doc/examples/osmo-bsc_nat/bscs.config b/openbsc/doc/examples/osmo-bsc_nat/bscs.config new file mode 100644 index 0000000..176debe --- /dev/null +++ b/openbsc/doc/examples/osmo-bsc_nat/bscs.config @@ -0,0 +1,13 @@ +nat + bsc 0 + token lol + location_area_code 1234 + description bsc + max-endpoints 32 + paging forbidden 0 + bsc 1 + token wat + location_area_code 5678 + description bsc + max-endpoints 32 + paging forbidden 0 diff --git a/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg b/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg index 737d104..2e00bc2 100644 --- a/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg +++ b/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg @@ -62,11 +62,5 @@ nat timeout ping 20 timeout pong 5 ip-dscp 0 + bscs-config-file bscs.config access-list bla imsi-allow ^11$ - - bsc 0 - token bla - location_area_code 1234 - description bsc - max-endpoints 32 - paging forbidden 0 diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 309adb1..ab1c590 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -264,6 +264,10 @@ struct bsc_nat { struct bsc_endpoint *bsc_endpoints; + /* path to file with BSC config */ + char *include_file; + char *include_base; + /* filter */ char *acc_lst_name; @@ -336,6 +340,7 @@ void sccp_connection_destroy(struct nat_sccp_connection *); void bsc_close_connection(struct bsc_connection *); const char *bsc_con_type_to_string(int type); +const char *bsc_nat_resolve_path(void *ctx, const char *base, const char *name); /** * parse the given message into the above structure diff --git a/openbsc/osmoappdesc.py b/openbsc/osmoappdesc.py index 76f03fc..d10ecae 100644 --- a/openbsc/osmoappdesc.py +++ b/openbsc/osmoappdesc.py @@ -26,6 +26,9 @@ nitb_e1_configs = [ "doc/examples/osmo-nitb/rbs2308/openbsc.cfg" ] +copy_files = [ + "doc/examples/osmo-bsc_nat/bscs.config" +] app_configs = { "osmo-bsc": ["doc/examples/osmo-bsc/osmo-bsc.cfg"], diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index cacb919..7dcacfd 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -34,6 +34,7 @@ #include #include #include +#include #define _GNU_SOURCE #include @@ -1451,6 +1452,12 @@ static int ipaccess_listen_bsc_cb(struct osmo_fd *bfd, unsigned int what) return 0; } +const char *bsc_nat_resolve_path(void *ctx, const char *base, const char *name) +{ + return ('/' == name[0]) ? name : talloc_asprintf(ctx, "%s/%s", base, + name); +} + static void print_usage() { printf("Usage: bsc_nat\n"); @@ -1626,6 +1633,8 @@ int main(int argc, char **argv) local_addr.s_addr = INADDR_ANY; handle_options(argc, argv); + nat->include_base = dirname(talloc_strdup(tall_bsc_ctx, config_file)); + rate_ctr_init(tall_bsc_ctx); osmo_stats_init(tall_bsc_ctx); @@ -1651,7 +1660,9 @@ int main(int argc, char **argv) /* seed the PRNG */ srand(time(NULL)); - + LOGP(DNAT, LOGL_NOTICE, "BSCs configured from %s\n", + bsc_nat_resolve_path(tall_bsc_ctx, nat->include_base, + nat->include_file)); /* * Setup the MGCP code.. diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 96559b0..8def3ed 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -96,6 +96,8 @@ static int config_write_nat(struct vty *vty) vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE); vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE); vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE); + if (_nat->include_file) + vty_out(vty, " bscs-config-file %s%s", _nat->include_file, VTY_NEWLINE); if (_nat->token) vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE); vty_out(vty, " ip-dscp %d%s", _nat->bsc_ip_dscp, VTY_NEWLINE); @@ -181,6 +183,15 @@ static int config_write_bsc(struct vty *vty) return CMD_SUCCESS; } +DEFUN(show_bscs, show_bscs_cmd, "show bscs-config", + SHOW_STR "Show configured BSCs\n" + "Both from included file and vty\n") +{ + vty_out(vty, "BSCs configuration loaded from %s:%s", + bsc_nat_resolve_path(_nat, _nat->include_base, + _nat->include_file), VTY_NEWLINE); + return config_write_bsc(vty); +} DEFUN(show_sccp, show_sccp_cmd, "show sccp connections", SHOW_STR "Display information about SCCP\n" @@ -495,6 +506,24 @@ DEFUN(cfg_nat_acc_lst_name, return CMD_SUCCESS; } +DEFUN(cfg_nat_include, + cfg_nat_include_cmd, + "bscs-config-file NAME", + "Set the filename of the BSC configuration to include.\n" + "The filename to be included.") +{ + const char *path = bsc_nat_resolve_path(_nat, _nat->include_base, + argv[0]); + int rc = vty_read_config_file(path, NULL); + if (rc < 0) { + vty_out(vty, "Failed to parse the config file %s: %s%s", path, + strerror(-rc), VTY_NEWLINE); + return CMD_WARNING; + } + bsc_replace_string(_nat, &_nat->include_file, argv[0]); + return CMD_SUCCESS; +} + DEFUN(cfg_nat_no_acc_lst_name, cfg_nat_no_acc_lst_name_cmd, "no access-list-name", @@ -871,8 +900,11 @@ DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>", /* verify that the LACs are unique */ llist_for_each_entry(tmp, &_nat->bsc_configs, entry) { if (bsc_config_handles_lac(tmp, lac)) { - vty_out(vty, "%% LAC %d is already used.%s", lac, VTY_NEWLINE); - return CMD_ERR_INCOMPLETE; + if (tmp->nr != conf->nr) { + vty_out(vty, "%% LAC %d is already used.%s", lac, + VTY_NEWLINE); + return CMD_ERR_INCOMPLETE; + } } } @@ -1185,6 +1217,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element_ve(&show_msc_cmd); install_element_ve(&test_regex_cmd); install_element_ve(&show_bsc_mgcp_cmd); + install_element_ve(&show_bscs_cmd); install_element_ve(&show_bar_lst_cmd); install_element_ve(&show_prefix_tree_cmd); install_element_ve(&show_ussd_connection_cmd); @@ -1206,6 +1239,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd); install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd); install_element(NAT_NODE, &cfg_nat_no_acc_lst_name_cmd); + install_element(NAT_NODE, &cfg_nat_include_cmd); install_element(NAT_NODE, &cfg_nat_imsi_black_list_fn_cmd); install_element(NAT_NODE, &cfg_nat_no_imsi_black_list_fn_cmd); install_element(NAT_NODE, &cfg_nat_ussd_lst_name_cmd); @@ -1242,7 +1276,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) /* BSC subgroups */ install_element(NAT_NODE, &cfg_bsc_cmd); - install_node(&bsc_node, config_write_bsc); + install_node(&bsc_node, NULL); vty_install_default(NAT_BSC_NODE); install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_auth_key_cmd); -- 2.8.1 From nhofmeyr at sysmocom.de Mon Apr 4 13:57:07 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 4 Apr 2016 15:57:07 +0200 Subject: SUA on-link cb? Message-ID: <20160404135707.GC7397@dub6> I'm taking a brief look at how osmo-hnbgw would send a Reset to the CN. So I'd like to be notified when osmo-hnbgw first establishes a link to a CN component, and then send a Reset message on it. I see there's an OSMO_SCU_PRIM_N_CONNECT, but am I right that this is related to actual messages being sent on the link, and can't be used to get notified about a connection per se? Link establishment traces out as: hnbgw_cnlink_init() osmo_sua_client_connect() osmo_stream_cli_open2() <-- includes a timer that retries connecting In the osmo_stream_cli_* API, there's a connect_cb, but it isn't used from osmo_sua_client_*. So I would * add a connect cb to struct osmo_sua_user (and osmo_sua_user_create()) * call it from a static cb fed to osmo_stream_cli_set_connect_cb() in osmo_sua_client_connect() Yes? Thanks, ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From msuraev at sysmocom.de Mon Apr 4 14:06:34 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 4 Apr 2016 16:06:34 +0200 Subject: [PATCH] NAT: reload BSCs config dynamically Message-ID: <1459778794-15778-1-git-send-email-msuraev@sysmocom.de> From: Max Add vty tests for BSC configuration reloading. Load BSCs configuration on bscs-config-file command: * remove all runtime configured BSC not in the config file * close connections to all BSC with updated token value Fixes: OS#1670 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/bsc_nat.h | 5 ++ openbsc/src/osmo-bsc_nat/bsc_nat.c | 4 +- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 35 +++++++- openbsc/tests/vty_test_runner.py | 145 ++++++++++++++++++++++++++++++++- 4 files changed, 185 insertions(+), 4 deletions(-) diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index ab1c590..c664d24 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -35,6 +35,7 @@ #include #include +#include #define DIR_BSC 1 #define DIR_MSC 2 @@ -164,6 +165,10 @@ struct bsc_config { /* audio handling */ int max_endpoints; + /* used internally for reload handling */ + bool remove; + bool token_updated; + /* backpointer */ struct bsc_nat *nat; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index 7dcacfd..9bbb253 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -1321,8 +1321,8 @@ static int ipaccess_bsc_read_cb(struct osmo_fd *bfd) bsc->cfg ? bsc->cfg->nr : -1); else LOGP(DNAT, LOGL_ERROR, - "Stream error on BSC Nr: %d. Failed to parse ip access message: %d\n", - bsc->cfg ? bsc->cfg->nr : -1, ret); + "Stream error on BSC Nr: %d. Failed to parse ip access message: %d (%s)\n", + bsc->cfg ? bsc->cfg->nr : -1, ret, strerror(-ret)); bsc_close_connection(bsc); return -1; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 8def3ed..45e408c 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -39,6 +39,7 @@ #include #include +#include static struct bsc_nat *_nat; @@ -512,15 +513,40 @@ DEFUN(cfg_nat_include, "Set the filename of the BSC configuration to include.\n" "The filename to be included.") { + int rc; + struct bsc_config *cf1, *cf2; + struct bsc_connection *con1, *con2; const char *path = bsc_nat_resolve_path(_nat, _nat->include_base, argv[0]); - int rc = vty_read_config_file(path, NULL); + + llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) { + cf1->remove = true; + cf1->token_updated = false; + } + + rc = vty_read_config_file(path, NULL); if (rc < 0) { vty_out(vty, "Failed to parse the config file %s: %s%s", path, strerror(-rc), VTY_NEWLINE); return CMD_WARNING; } + bsc_replace_string(_nat, &_nat->include_file, argv[0]); + + llist_for_each_entry_safe(con1, con2, &_nat->bsc_connections, + list_entry) { + if (con1->cfg) + if (con1->cfg->token_updated || con1->cfg->remove) + bsc_close_connection(con1); + } + + llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) { + if (cf1->remove) { + bsc_config_free(cf1); + _nat->num_bsc--; + } + } + return CMD_SUCCESS; } @@ -843,6 +869,7 @@ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", if (!bsc) return CMD_WARNING; + bsc->remove = false; vty->index = bsc; vty->node = NAT_BSC_NODE; @@ -855,6 +882,12 @@ DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN", { struct bsc_config *conf = vty->index; + if (strncmp(conf->token, argv[0], 128) != 0) { + vty_out(vty, "updated token: %s -> %s%s", conf->token, argv[0], + VTY_NEWLINE); + conf->token_updated = true; + } + bsc_replace_string(conf, &conf->token, argv[0]); return CMD_SUCCESS; } diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 8db0825..bd2cefd 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -584,12 +584,61 @@ class TestVTYBSC(TestVTYGenericBSC): class TestVTYNAT(TestVTYGenericBSC): def vty_command(self): - return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-c", + return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-l", "127.0.0.1", "-c", "doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg"] def vty_app(self): return (4244, "src/osmo-bsc_nat/osmo-bsc_nat", "OsmoBSCNAT", "nat") + def testBSCreload(self): + # use separate ip to avoid interference with other tests + ip = "127.0.0.4" + self.vty.enable() + bscs1 = self.vty.command("show bsc-config") + nat_bsc_reload(self) + bscs2 = self.vty.command("show bsc-config") + # check that multiple calls to bscs-config-file give the same result + self.assertEquals(bscs1, bscs2) + + # add new bsc + self.vty.command("configure terminal") + self.vty.command("nat") + self.vty.command("bsc 2") + self.vty.command("token key") + self.vty.command("location_area_code 666") + self.vty.command("end") + + # update bsc token + self.vty.command("configure terminal") + self.vty.command("nat") + self.vty.command("bsc 1") + self.vty.command("token xyu") + self.vty.command("end") + + nat_msc_ip(self, ip) + msc = nat_msc_test(self, ip) + b0 = nat_bsc_sock_test(0, "lol") + b1 = nat_bsc_sock_test(1, "xyu") + b2 = nat_bsc_sock_test(2, "key") + + self.assertEquals("3 BSCs configured", self.vty.command("show nat bsc")) + self.assertTrue(3 == nat_bsc_num_con(self)) + self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection")) + + nat_bsc_reload(self) + bscs2 = self.vty.command("show bsc-config") + # check that the reset to initial config succeeded + self.assertEquals(bscs1, bscs2) + + self.assertEquals("2 BSCs configured", self.vty.command("show nat bsc")) + self.assertTrue(1 == nat_bsc_num_con(self)) + rem = self.vty.command("show bsc connections").split(' ') + # remaining connection is for BSC0 + self.assertEquals('0', rem[2]) + # remaining connection is authorized + self.assertEquals('1', rem[4]) + self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection")) + def testVtyTree(self): self.vty.enable() self.assertTrue(self.vty.verify('configure terminal', [''])) @@ -971,6 +1020,100 @@ def add_nat_test(suite, workdir): test = unittest.TestLoader().loadTestsFromTestCase(TestVTYNAT) suite.addTest(test) +def nat_bsc_reload(x): + x.vty.command("configure terminal") + x.vty.command("nat") + x.vty.command("bscs-config-file bscs.config") + x.vty.command("end") + +def nat_msc_ip(x, ip): + x.vty.command("configure terminal") + x.vty.command("nat") + x.vty.command("msc ip " + ip) + x.vty.command("end") + +def data2str(d): + return "".join("{:02x}".format(ord(c)) for c in d) + +def nat_msc_test(x, ip, verbose = False): + msc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + msc.settimeout(32) + msc.bind((ip, 5000)) + msc.listen(5) + if (verbose): + print "MSC is ready at " + ip + while "MSC is connected: 0" == x.vty.command("show msc connection"): + conn, addr = msc.accept() + if (verbose): + print "MSC got connection from ", addr + return conn + +def ipa_send_pong(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: PONG!" + x.send("\x00\x01\xfe\x01") + +def ipa_send_ping(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: PING?" + x.send("\x00\x01\xfe\x00") + +def ipa_send_ack(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: IPA ID ACK" + x.send("\x00\x01\xfe\x06") + +def ipa_handle_small(x, verbose = False): + s = data2str(x.recv(4)) + if "0001fe00" == s: + if (verbose): + print "\tBSC <- NAT: PING?" + ipa_send_pong(x, verbose) + elif "0001fe06" == s: + if (verbose): + print "\tBSC <- NAT: IPA ID ACK" + ipa_send_ack(x, verbose) + elif "0001fe00" == s: + if (verbose): + print "\tBSC <- NAT: PONG!" + else: + if (verbose): + print "\tBSC <- NAT: ", s + +def ipa_send_reset(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: RESET" + x.send("\x00\x12\xfd\x09\x00\x03\x05\x07\x02\x42\xfe\x02\x42\xfe\x06\x00\x04\x30\x04\x01\x20") + +def ipa_send_resp(x, tk, verbose = False): + if (verbose): + print "\tBSC -> NAT: IPA ID RESP" + x.send("\x00\x07\xfe\x05\x00\x04\x01" + tk) + +def ipa_handle_resp(x, tk, verbose = False): + s = data2str(x.recv(38)) + if "0023fe040108010701020103010401050101010011" in s: + ipa_send_resp(x, tk, verbose) + else: + if (verbose): + print "\tBSC <- NAT: ", s + +def nat_bsc_num_con(x): + return len(x.vty.command("show bsc connections").split('\n')) + +def nat_bsc_sock_test(nr, tk, verbose = False): + bsc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + bsc.bind(('127.0.0.1' + str(nr), 0)) + bsc.connect(('127.0.0.1', 5000)) + if (verbose): + print "BSC%d " %nr + print "\tconnected to %s:%d" % bsc.getpeername() + ipa_handle_small(bsc, verbose) + ipa_handle_resp(bsc, tk, verbose) + bsc.recv(27) # MGCP msg + ipa_handle_small(bsc, verbose) + return bsc + 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") -- 2.8.1 From laforge at gnumonks.org Mon Apr 4 14:09:05 2016 From: laforge at gnumonks.org (Harald Welte) Date: Mon, 4 Apr 2016 16:09:05 +0200 Subject: SUA on-link cb? In-Reply-To: <20160404135707.GC7397@dub6> References: <20160404135707.GC7397@dub6> Message-ID: <20160404140905.GJ27299@nataraja> Hi Neels, On Mon, Apr 04, 2016 at 03:57:07PM +0200, Neels Hofmeyr wrote: > I'm taking a brief look at how osmo-hnbgw would send a Reset to the CN. > So I'd like to be notified when osmo-hnbgw first establishes a link to a > CN component, and then send a Reset message on it. > > I see there's an OSMO_SCU_PRIM_N_CONNECT, but am I right that this is > related to actual messages being sent on the link, and can't be used to > get notified about a connection per se? Please check the ITU specs for SCCP, specifically the N-CONNECT primitive at the SCCP user SAP. I think it is quite clear that there's a full set of N-CONNECT with full request/confirm (initiator) / indication/response (responder) primitives. For example, Table 1 and Figure 8 of Q.711 should give a good idea. This should be the guideline against which we implement the SCCP provider underneath our SCCP USER SAP. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Mon Apr 4 15:10:58 2016 From: laforge at gnumonks.org (Harald Welte) Date: Mon, 4 Apr 2016 17:10:58 +0200 Subject: Lack of maintenance for osmo-bts-trx Message-ID: <20160404151058.GN27299@nataraja> Dear all, I am growing incredibly frustrated at the fact that osmo-bts-trx is effectively unmaintained, despite the fact that there are plenty of users as well as even commercial users / companies (particularly Fairwaves). I'm not pointing Fairwaves out because I am associated with sysmocom. I'm pointing them out as for me as Osmocom project founder and co-maintainer, I sincerely think something is wrong here. And particuarly commercial vendors of BTSs using the Osmocom stack should at the very absolute minimum ensure proper maintenance of their own hardware support in the respective Osmocom projects. They should equally consider contributing to maintenance and developemnt of the 'core' code of those projects, too, in order to fairly share the burden of that effort. I explicitly asked for proper maintenance of osmo-bts-trx first in August 2014 in this post: http://lists.osmocom.org/pipermail/openbsc/2014-August/007657.html Back in 2014 and the first half of 2015 I spent a lot of time in forward-porting and cleaning up the the (fairwaves-commissioned?) l1sap changes, as well as the associated osmo-bts-trx port. Back then, there were several patches in related (several) branches that I could not merge. See my mail (and follow-up mails) from http://lists.osmocom.org/pipermail/openbsc/2015-September/000379.html Ever since the merge in August 2015, as far as I recall, I never saw a single message from any osmo-bts-trx user whether a) the L1SAP merge back then works for them b) it introduced any regressions The same happened after the phy_link/phy_interface merge. While some people think I sometimes write good code, I fail to believe that all those intrusive changes didn't break anything for OsmoTRX users. Still, no feedback and no fall-out was reported. Like any larger project, particularly one with different hardware support, we need somebody with essential interest in that hardware to maintain the respective back-end. Think of device driver maintainers in the Linux kernel as an example. For osmo-bts-sysmo, it is clear that sysmocom has such a vital interest, and that it is the primary hardware on whcih Holger and I are working on. For osmo-bts-octphy, Octasic funds related maintenance work to be done at sysmocom. We need a sub-maintainer for osmo-bts-trx, one who 1) consistently follows the developments in master and checks for regressiosn 2) fixes osmo-bts-trx specific bugs like the fact that GPRS measurment values are not passed to the PCU, breaking rate/link adaption for this platform 3) tests interoperability with OsmoTRX and other OpenBTS transceivers out three 4) ensures that important osmo-bts-trx related patches/branches end up in master, ensuring that master is what people use. Telling users to use a branch different than master is *wrong* for anything but the most bleeding edge / experiemental code which is to be merged ASAP. I thus strongly suggest that the users and proponents of osmo-bts-trx get together and see how they can ensure the proper maintenance of this port. Thanks for your consideration. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From msuraev at sysmocom.de Mon Apr 4 15:49:37 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 4 Apr 2016 17:49:37 +0200 Subject: [PATCH] Add ubit <-> sbit convertors Message-ID: <1459784977-2471-1-git-send-email-msuraev@sysmocom.de> From: Max Move functions for conversion between soft and unpacked bits to main library as they are generally useful. --- include/osmocom/core/bits.h | 3 +++ src/bits.c | 24 ++++++++++++++++++++++++ tests/conv/conv_test.c | 23 ++--------------------- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h index 46f0c8b..e082313 100644 --- a/include/osmocom/core/bits.h +++ b/include/osmocom/core/bits.h @@ -42,6 +42,9 @@ int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits); int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits); +void osmo_ubit2sbit(sbit_t *out, const ubit_t *in, unsigned int num_bits); +void osmo_sbit2ubit(ubit_t *out, const sbit_t *in, unsigned int num_bits); + int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs, const ubit_t *in, unsigned int in_ofs, unsigned int num_bits, int lsb_mode); diff --git a/src/bits.c b/src/bits.c index a0a9d9e..494c825 100644 --- a/src/bits.c +++ b/src/bits.c @@ -61,6 +61,30 @@ int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits) return outptr - out; } +/*! \brief convert unpacked bits to soft bits + * \param[out] out output buffer of soft bits + * \param[in] in input buffer of unpacked bits + * \param[in] num_bits number of bits + */ +void osmo_ubit2sbit(sbit_t *out, const ubit_t *in, unsigned int num_bits) +{ + int i; + for (i = 0; i < num_bits; i++) + out[i] = in[i] ? -127 : 127; +} + +/*! \brief convert soft bits to unpacked bits + * \param[out] out output buffer of unpacked bits + * \param[in] in input buffer of soft bits + * \param[in] num_bits number of bits + */ +void osmo_sbit2ubit(ubit_t *out, const sbit_t *in, unsigned int num_bits) +{ + int i; + for (i = 0; i < num_bits; i++) + out[i] = in[i] < 0; +} + /*! \brief convert packed bits to unpacked bits, return length in bytes * \param[out] out output buffer of unpacked bits * \param[in] in input buffer of packed bits diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index d9440f9..de62f23 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -339,25 +339,6 @@ fill_random(ubit_t *b, int n) b[i] = random() & 1; } -static void -ubit_to_sbit(sbit_t *dst, ubit_t *src, int n) -{ - int i; - for (i=0; icode, bs, bu1); if (l != 0) { @@ -459,7 +440,7 @@ int main(int argc, char *argv[]) return -1; } - ubit_to_sbit(bs, bu1, l); + osmo_ubit2sbit(bs, bu1, l); l = osmo_conv_decode(tst->code, bs, bu1); if (l != 0) { -- 2.8.1 From nhofmeyr at sysmocom.de Mon Apr 4 15:55:50 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 4 Apr 2016 17:55:50 +0200 Subject: SUA on-link cb? In-Reply-To: <20160404140905.GJ27299@nataraja> References: <20160404135707.GC7397@dub6> <20160404140905.GJ27299@nataraja> Message-ID: <20160404155550.GF7397@dub6> On Mon, Apr 04, 2016 at 04:09:05PM +0200, Harald Welte wrote: > Please check the ITU specs for SCCP, specifically the N-CONNECT > Figure 8 of Q.711 should give a good idea. I see those specs, yet it is hard to put them in practical perspective. My point is, I don't see N-CONNECT primitives in wireshark. So it seems to me there's no use hooking on those ... or is it because the osmo sccp code simply fails to do that negotiation? When I place debug output (using printf to make sure debug log levels aren't disabled) in the N-CONNECT prim rx code in osmo-hnbgw, I also don't get any hits when connecting omso-hnbgw to the CN. Assuming osmo-sccp is working correctly, I'm pretty sure the N-CONNECT doesn't help in sending a Reset from omso-hnbgw to the CN upon connecting. I already have the on-connect callback implemented as described before, which does register when connecting to the CN. So I'll commit it on libosmo-sccp branch sysmocom/iu and use that to send a Reset. I wouldn't really want to get side-tracked from the side-track, but it's not set in stone: comments welcome! ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Mon Apr 4 16:27:36 2016 From: laforge at gnumonks.org (Harald Welte) Date: Mon, 4 Apr 2016 18:27:36 +0200 Subject: SUA on-link cb? In-Reply-To: <20160404155550.GF7397@dub6> References: <20160404135707.GC7397@dub6> <20160404140905.GJ27299@nataraja> <20160404155550.GF7397@dub6> Message-ID: <20160404162736.GQ27299@nataraja> Hi Neels, On Mon, Apr 04, 2016 at 05:55:50PM +0200, Neels Hofmeyr wrote: > My point is, I don't see N-CONNECT primitives in wireshark. As a primitive is something between two layers on your local protocol stack, you will never see that in wireshark. The actual protocol message payload at the given layer boundary is one attribute (typically called DATA) of the primitive. To translate it in IP: The 'connect()', 'bind()', 'recvmsg()' primitive at the TCP/UDP User SAP (BSD socket intreface) between the UDP protocol implementation an your application is also not observed in wireshark. Instead of calling 'connect()' on a TCP socket, in an ITU primtive world, you send a N-CONNET.request primitive to the TCP Provider. Instead of getting an incoming connection via 'accept()', you get a N-CONNECT.indication from the TCP provider. Primitives are just a different way of an API to talk to a protocol stack (or rather a layer in a stack). > So it seems to me there's no use hooking on those ... or is it > because the osmo sccp code simply fails to do that negotiation? Which negotiation? > When I place debug output (using printf to make sure debug log levels > aren't disabled) in the N-CONNECT prim rx code in osmo-hnbgw, I also don't > get any hits when connecting omso-hnbgw to the CN. This is because the SCCP User SAP apparently is not yet generating those primitives. > Assuming osmo-sccp is working correctly, As usual, I only implement those bits that were immediately needed/used at the time it was written. Very likely the primitives you need are simply not generated yet. > I already have the on-connect callback implemented as described before, > which does register when connecting to the CN. So I'll commit it on > libosmo-sccp branch sysmocom/iu and use that to send a Reset. all communication between the SCCP user (application) and SCCP provider should go through the same SAP interface. A call-bcak from a lower-layer transport library like libosmo-netif should be trasnformed into a SCCP User SAP primitive an then sent to the SCCP User via the SAP. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Mon Apr 4 18:19:39 2016 From: laforge at gnumonks.org (Harald Welte) Date: Mon, 4 Apr 2016 20:19:39 +0200 Subject: SUA on-link cb? In-Reply-To: <20160404162736.GQ27299@nataraja> References: <20160404135707.GC7397@dub6> <20160404140905.GJ27299@nataraja> <20160404155550.GF7397@dub6> <20160404162736.GQ27299@nataraja> Message-ID: <20160404181939.GA16601@nataraja> Dear Neels and others, I was confused earlier today. N-CONNECT is a primitive for a connection oriented SCCP-layer connection. You receive it at each time a UE establishes a connection-oriented SCCP for signalling, and it is what carrie RANAP InitialUE and related messages. What you are talking about for the RANAP Reset is the establishment of a signalling link (underneath SCCP/SUA), so something like the SCTP connection being established and released underneath. In the SUA RFC 3868 there are: * M-SCTP_ESTABLISH confirm ASP confirms to LM that it has established an SCTP association with its peer * M-SCTP_ESTABLISH indication SUA informs LM that a remote ASP has established an SCTP association. "LM" is the "Layer Manager". This is not the SCCP user, so no luck here. However, Q.711 / Q.714 contain a N-STATE.indication, which can be sent to a local SCCP user to inform it about the subsystem status. FRrom 5.3.6.2: "The local broadcast procedure provides a mechanism to inform local allowed concerned subsystems of any related SCCP/subsystem/signalling point status information received. [...] SCCP management then informs local allowed concerned SCCP subsystems about the subsystem status by invoking N-STATE indication primitive with "User-out-of-service" information." So once we loose the signalling link, all SCCP users should receive N-STATE.ind with "User-out-of-service". When the signalling link is (re-)established, all SCCP users should receive N-STATE.ind with "User-in-service". This should then be the trigger to send a N-UNITDATA.req() with a RANAP Reset inside. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From alexander.chemeris at gmail.com Mon Apr 4 20:35:31 2016 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Mon, 4 Apr 2016 21:35:31 +0100 Subject: Lack of maintenance for osmo-bts-trx In-Reply-To: <20160404151058.GN27299@nataraja> References: <20160404151058.GN27299@nataraja> Message-ID: Hi Harald, I guess the frustration was mutual - about a year ago we had a chat that the branch couldn't be merged only because Sysmocom didn't have time to test it with their hardware. We even offered to pay for that testing, but it never happened. So I guess it took some other incentives to get it merged. Now it's our time to take time and test the latest master for compatibility with our hardware. Meanwhile we unfortunately have to maintain a version which works for us. There were reports that the latest master of osmo-bts-trx doesn't work and I can confirm that that's the case. There were also a report from me that the branch right after the merge with master "basically worked". So you can't blame community for not reporting. That said, once we get over the potential barrier of fixing the master and porting our changes to it, we'll be happy to maintain it further on, as we do with our branch right now. If there are anyone else who want to take the burden - we would welcome that as well. On Mon, Apr 4, 2016 at 4:10 PM, Harald Welte wrote: > Dear all, > > I am growing incredibly frustrated at the fact that osmo-bts-trx is > effectively unmaintained, despite the fact that there are plenty of > users as well as even commercial users / companies (particularly > Fairwaves). > > I'm not pointing Fairwaves out because I am associated with sysmocom. > I'm pointing them out as for me as Osmocom project founder and > co-maintainer, I sincerely think something is wrong here. And > particuarly commercial vendors of BTSs using the Osmocom stack should > at the very absolute minimum ensure proper maintenance of their own > hardware support in the respective Osmocom projects. They should > equally consider contributing to maintenance and developemnt of the > 'core' code of those projects, too, in order to fairly share the burden > of that effort. > > I explicitly asked for proper maintenance of osmo-bts-trx first in > August 2014 in this post: > http://lists.osmocom.org/pipermail/openbsc/2014-August/007657.html > > Back in 2014 and the first half of 2015 I spent a lot of time in > forward-porting and cleaning up the the (fairwaves-commissioned?) l1sap > changes, as well as the associated osmo-bts-trx port. Back then, there > were several patches in related (several) branches that I could not > merge. See my mail (and follow-up mails) from > http://lists.osmocom.org/pipermail/openbsc/2015-September/000379.html > > Ever since the merge in August 2015, as far as I recall, I never saw a > single message from any osmo-bts-trx user whether > a) the L1SAP merge back then works for them > b) it introduced any regressions > > The same happened after the phy_link/phy_interface merge. > > While some people think I sometimes write good code, I fail to believe > that all those intrusive changes didn't break anything for OsmoTRX > users. Still, no feedback and no fall-out was reported. > > Like any larger project, particularly one with different hardware > support, we need somebody with essential interest in that hardware to > maintain the respective back-end. Think of device driver maintainers in > the Linux kernel as an example. > > For osmo-bts-sysmo, it is clear that sysmocom has such a vital interest, > and that it is the primary hardware on whcih Holger and I are working > on. For osmo-bts-octphy, Octasic funds related maintenance work to be > done at sysmocom. > > We need a sub-maintainer for osmo-bts-trx, one who > 1) consistently follows the developments in master and checks for > regressiosn > 2) fixes osmo-bts-trx specific bugs like the fact that GPRS measurment > values are not passed to the PCU, breaking rate/link adaption for > this platform > 3) tests interoperability with OsmoTRX and other OpenBTS transceivers > out three > 4) ensures that important osmo-bts-trx related patches/branches end up > in master, ensuring that master is what people use. Telling users to > use a branch different than master is *wrong* for anything but the > most bleeding edge / experiemental code which is to be merged ASAP. > > I thus strongly suggest that the users and proponents of osmo-bts-trx > get together and see how they can ensure the proper maintenance of this > port. Thanks for your consideration. > > Regards, > Harald > -- > - Harald Welte > http://laforge.gnumonks.org/ > > ============================================================================ > "Privacy in residential applications is a desirable marketing option." > (ETSI EN 300 175-7 Ch. > A6) > -- Regards, Alexander Chemeris. CEO, Fairwaves, Inc. https://fairwaves.co -------------- next part -------------- An HTML attachment was scrubbed... URL: From choukoumoun at gmail.com Mon Apr 4 21:04:04 2016 From: choukoumoun at gmail.com (Choukou Moun) Date: Mon, 4 Apr 2016 23:04:04 +0200 Subject: Lack of maintenance for osmo-bts-trx In-Reply-To: References: <20160404151058.GN27299@nataraja> Message-ID: Troll : "clash of titans" Sorry im running .....:) Le 4 avr. 2016 22:35, "Alexander Chemeris" a ?crit : > Hi Harald, > > I guess the frustration was mutual - about a year ago we had a chat that > the branch couldn't be merged only because Sysmocom didn't have time to > test it with their hardware. We even offered to pay for that testing, but > it never happened. So I guess it took some other incentives to get it > merged. Now it's our time to take time and test the latest master for > compatibility with our hardware. Meanwhile we unfortunately have to > maintain a version which works for us. > > There were reports that the latest master of osmo-bts-trx doesn't work and > I can confirm that that's the case. There were also a report from me that > the branch right after the merge with master "basically worked". So you > can't blame community for not reporting. > That said, once we get over the potential barrier of fixing the master and > porting our changes to it, we'll be happy to maintain it further on, as we > do with our branch right now. If there are anyone else who want to take the > burden - we would welcome that as well. > > On Mon, Apr 4, 2016 at 4:10 PM, Harald Welte wrote: > >> Dear all, >> >> I am growing incredibly frustrated at the fact that osmo-bts-trx is >> effectively unmaintained, despite the fact that there are plenty of >> users as well as even commercial users / companies (particularly >> Fairwaves). >> >> I'm not pointing Fairwaves out because I am associated with sysmocom. >> I'm pointing them out as for me as Osmocom project founder and >> co-maintainer, I sincerely think something is wrong here. And >> particuarly commercial vendors of BTSs using the Osmocom stack should >> at the very absolute minimum ensure proper maintenance of their own >> hardware support in the respective Osmocom projects. They should >> equally consider contributing to maintenance and developemnt of the >> 'core' code of those projects, too, in order to fairly share the burden >> of that effort. >> >> I explicitly asked for proper maintenance of osmo-bts-trx first in >> August 2014 in this post: >> http://lists.osmocom.org/pipermail/openbsc/2014-August/007657.html >> >> Back in 2014 and the first half of 2015 I spent a lot of time in >> forward-porting and cleaning up the the (fairwaves-commissioned?) l1sap >> changes, as well as the associated osmo-bts-trx port. Back then, there >> were several patches in related (several) branches that I could not >> merge. See my mail (and follow-up mails) from >> http://lists.osmocom.org/pipermail/openbsc/2015-September/000379.html >> >> Ever since the merge in August 2015, as far as I recall, I never saw a >> single message from any osmo-bts-trx user whether >> a) the L1SAP merge back then works for them >> b) it introduced any regressions >> >> The same happened after the phy_link/phy_interface merge. >> >> While some people think I sometimes write good code, I fail to believe >> that all those intrusive changes didn't break anything for OsmoTRX >> users. Still, no feedback and no fall-out was reported. >> >> Like any larger project, particularly one with different hardware >> support, we need somebody with essential interest in that hardware to >> maintain the respective back-end. Think of device driver maintainers in >> the Linux kernel as an example. >> >> For osmo-bts-sysmo, it is clear that sysmocom has such a vital interest, >> and that it is the primary hardware on whcih Holger and I are working >> on. For osmo-bts-octphy, Octasic funds related maintenance work to be >> done at sysmocom. >> >> We need a sub-maintainer for osmo-bts-trx, one who >> 1) consistently follows the developments in master and checks for >> regressiosn >> 2) fixes osmo-bts-trx specific bugs like the fact that GPRS measurment >> values are not passed to the PCU, breaking rate/link adaption for >> this platform >> 3) tests interoperability with OsmoTRX and other OpenBTS transceivers >> out three >> 4) ensures that important osmo-bts-trx related patches/branches end up >> in master, ensuring that master is what people use. Telling users to >> use a branch different than master is *wrong* for anything but the >> most bleeding edge / experiemental code which is to be merged ASAP. >> >> I thus strongly suggest that the users and proponents of osmo-bts-trx >> get together and see how they can ensure the proper maintenance of this >> port. Thanks for your consideration. >> >> Regards, >> Harald >> -- >> - Harald Welte >> http://laforge.gnumonks.org/ >> >> ============================================================================ >> "Privacy in residential applications is a desirable marketing option." >> (ETSI EN 300 175-7 Ch. >> A6) >> > > > > -- > Regards, > Alexander Chemeris. > CEO, Fairwaves, Inc. > https://fairwaves.co > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From evilsocket at gmail.com Tue Apr 5 06:59:32 2016 From: evilsocket at gmail.com (evilsocket) Date: Tue, 5 Apr 2016 08:59:32 +0200 Subject: Hacking with libosmocore, osmo-bts and osmo-bts-trx code: a few questions. Message-ID: <57036254.3060805@gmail.com> Dear all I'm an independent mobile security researcher and coder from Italy (therefore, forgive me if my English will cause you a headache), I've been reading GSM specs for quite a few months now and studying openbts, yatebts and osmo* source code for a few days due to a GSM related project I'd really like to realize. I have few questions to ask, but first let me explain my main objective. I'm working on something like ScaPy ( an ip packet injection and manipulation framework ) but for GSM, on a higher level what I want to create is a C library which would allow developers to do something like (forgive the pseudo-crappy programming and the oversimplification, I just want to highlight what I'm looking for): Passive / Sniffing concept: open(sdr-device) while(running) { data = read_and_demodulate burst = osmo_something_decode(data) dump(data) } close(sdr-device) Injection concept: imsi = "1234456..." open(sdr-device) data = osmo_encode_packet( IMSI_DETACH, imsi ) osmo_write( sdr-device, data ) close(sdr-device) ( I know I'm not considering synchronization, not really interested in that, the user would implement his own logic ) My point is that GSM is not "that hard" with the right tools, but currently there're no such tools and I think it's such a shame because it should be open to the users exactly as TCP/IP is. Now to the questions: A. Is the low-level communication ( from raw to basic demodulated bursts ) with SDR devices still handled by omso-bts-trx? If not, what's handling the physical layer? B. Could you point me to the right direction I'd need to take in order to extend the code to support Nuand's BladeRF devices ( the only one I have and the only one I can afford right now )? C. Do you have simple (even incomplete) code examples for both the "concepts" I've exposed ? I find your documentation to be really great, but for higher level understanding people need usage examples. Any piece of code, reference link, guidance, answer or whatever info will be great. Thanks, Simone 'evilsocket' Margaritelli From msuraev at sysmocom.de Tue Apr 5 07:56:27 2016 From: msuraev at sysmocom.de (Max) Date: Tue, 5 Apr 2016 09:56:27 +0200 Subject: ANN: https://patchwork.osmocom.org In-Reply-To: References: Message-ID: <57036FAB.6070209@sysmocom.de> Hi. Seems to work fine. Should we decommission our projects from https://patchwork.ozlabs.org/ than? This would help to avoid confusion. -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From nhofmeyr at sysmocom.de Tue Apr 5 09:29:35 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 5 Apr 2016 11:29:35 +0200 Subject: SUA on-link cb? In-Reply-To: <20160404181939.GA16601@nataraja> References: <20160404135707.GC7397@dub6> <20160404140905.GJ27299@nataraja> <20160404155550.GF7397@dub6> <20160404162736.GQ27299@nataraja> <20160404181939.GA16601@nataraja> Message-ID: <20160405092935.GA3293@ass40.sysmocom.de> Excellent, thanks for finding this info! So I should implement N-STATE ind to be sent from our osmo_sua_* implementation to the SUA user: * Trigger the N-STATE User-in-service from a callback put in osmo_stream_cli_set_connect_cb(). * Trigger the out-of-service from ... ? It seems we're lacking an osmo_stream_* disconnect cb? In a side note, this is deviating from what is strictly necessary to get paging working. I could just use the RNC Ids from the InitialUE messages for now and postpone the Reset issue. Another shortcut could be to send the Reset message "directly" from the osmo_stream_cli_set_connect_cb() without composing N-STATE prims. Would you say that Reset and the SUA N-STATE primitives are important enough to implement those first? Thanks, ~Neels On Mon, Apr 04, 2016 at 08:19:39PM +0200, Harald Welte wrote: > Dear Neels and others, > > I was confused earlier today. > > N-CONNECT is a primitive for a connection oriented SCCP-layer > connection. You receive it at each time a UE establishes a > connection-oriented SCCP for signalling, and it is what carrie RANAP > InitialUE and related messages. > > What you are talking about for the RANAP Reset is the establishment of a > signalling link (underneath SCCP/SUA), so something like the SCTP > connection being established and released underneath. > > In the SUA RFC 3868 there are: > * M-SCTP_ESTABLISH confirm > ASP confirms to LM that it has established an SCTP association with its peer > * M-SCTP_ESTABLISH indication > SUA informs LM that a remote ASP has established an SCTP association. > "LM" is the "Layer Manager". This is not the SCCP user, so no luck > here. > > However, Q.711 / Q.714 contain a N-STATE.indication, which can be sent > to a local SCCP user to inform it about the subsystem status. > > FRrom 5.3.6.2: > > "The local broadcast procedure provides a mechanism to inform local > allowed concerned subsystems of any related SCCP/subsystem/signalling > point status information received. [...] SCCP management then informs > local allowed concerned SCCP subsystems about the subsystem status by > invoking N-STATE indication primitive with "User-out-of-service" > information." > > So once we loose the signalling link, all SCCP users should receive > N-STATE.ind with "User-out-of-service". > > When the signalling link is (re-)established, all SCCP users should > receive N-STATE.ind with "User-in-service". This should then be the > trigger to send a N-UNITDATA.req() with a RANAP Reset inside. > > Regards, > Harald > -- > - Harald Welte http://laforge.gnumonks.org/ > ============================================================================ > "Privacy in residential applications is a desirable marketing option." > (ETSI EN 300 175-7 Ch. A6) -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From holger at freyther.de Tue Apr 5 09:50:47 2016 From: holger at freyther.de (Holger Freyther) Date: Tue, 5 Apr 2016 11:50:47 +0200 Subject: ANN: https://patchwork.osmocom.org In-Reply-To: <57036FAB.6070209@sysmocom.de> References: <57036FAB.6070209@sysmocom.de> Message-ID: > On 05 Apr 2016, at 09:56, Max wrote: > > Hi. > > Seems to work fine. Should we decommission our projects from > https://patchwork.ozlabs.org/ than? This would help to avoid confusion. what about the few patches that are only in the old one? E.g. Alexander's SMS series from 2014 that require another round before merging it, your Supplementary Services patchset, Sergey's USSD/SS fixes that stalled after having asked for a testcase and the question to generalize the gsup connection code, and I think Jacob's 48.016 GPRS-NS wip patch. It looks a bit premature to just ask them to switch it off. We can remove the ML subscription from mailman so that no new patches are being archived? holger From laforge at gnumonks.org Tue Apr 5 09:54:47 2016 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 5 Apr 2016 11:54:47 +0200 Subject: SUA on-link cb? In-Reply-To: <20160405092935.GA3293@ass40.sysmocom.de> References: <20160404135707.GC7397@dub6> <20160404140905.GJ27299@nataraja> <20160404155550.GF7397@dub6> <20160404162736.GQ27299@nataraja> <20160404181939.GA16601@nataraja> <20160405092935.GA3293@ass40.sysmocom.de> Message-ID: <20160405095447.GJ16601@nataraja> Hi Neels, On Tue, Apr 05, 2016 at 11:29:35AM +0200, Neels Hofmeyr wrote: > Would you say that Reset and the SUA N-STATE primitives are important > enough to implement those first? no. But please make sure that this deficiency and the proper implementation are documented in a ticket so we don't have to have this discussion again in the future :) -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From nhofmeyr at sysmocom.de Tue Apr 5 11:07:03 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 5 Apr 2016 13:07:03 +0200 Subject: SUA on-link cb? In-Reply-To: <20160405095447.GJ16601@nataraja> References: <20160404135707.GC7397@dub6> <20160404140905.GJ27299@nataraja> <20160404155550.GF7397@dub6> <20160404162736.GQ27299@nataraja> <20160404181939.GA16601@nataraja> <20160405092935.GA3293@ass40.sysmocom.de> <20160405095447.GJ16601@nataraja> Message-ID: <20160405110703.GA3653@ass40.sysmocom.de> On Tue, Apr 05, 2016 at 11:54:47AM +0200, Harald Welte wrote: > no. But please make sure that this deficiency and the proper > implementation are documented in a ticket so we don't have to have this > discussion again in the future :) http://osmocom.org/issues/1688 ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Apr 5 12:03:54 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 5 Apr 2016 14:03:54 +0200 Subject: RNC-Id and LAC both present in InitialUE msgs Message-ID: <20160405120354.GC3653@ass40.sysmocom.de> More on the pairing of RNC-Id and LAC: We've discussed that the CN should be manually configured for which RNC-Id belongs to which LAC, in order to find the correct SUA link to page on upon having the to-be-paged subscriber's LAC. Turns out: even though only the RNC-Id is sent in the id-Reset message, both the RNC-Id *and* the LAC are transmitted in an InitialUE message. So we can actually record the LACs as well as the RNC<->LAC mappings from the InitialUE messages (like Location Update Request) and don't need to configure them manually. Does that sound reasonable? We can still keep the manual vty config of RNC<->LAC mappings to detect errors in the field configuration from InitialUE messages. ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Apr 5 12:10:46 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 5 Apr 2016 14:10:46 +0200 Subject: RNC-Id and LAC both present in InitialUE msgs In-Reply-To: <20160405120354.GC3653@ass40.sysmocom.de> References: <20160405120354.GC3653@ass40.sysmocom.de> Message-ID: <20160405121046.GD3653@ass40.sysmocom.de> On Tue, Apr 05, 2016 at 02:03:54PM +0200, Neels Hofmeyr wrote: > Turns out: even though only the RNC-Id is sent in the id-Reset message, > both the RNC-Id *and* the LAC are transmitted in an InitialUE message. For the record, see the RANAP spec (3GPP TS 25.413 version 12.4.0 Release 12) chapter 9.1.33, which lists all of Global RNC-ID, LAI and SAI IEs as mandatory, where both LAI and SAI include the LAC, also mandatorily. It's interesting how LAI and SAI are mostly redundant, yet both are mandatory. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Apr 5 13:06:05 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 5 Apr 2016 15:06:05 +0200 Subject: Iuh -> HNB-GW -> Iu: Reset vs. Initial-UE In-Reply-To: <20160404081600.GB7397@dub6> References: <20160402220003.GA18867@dub6> <20160403200507.GB6125@nataraja> <20160403202751.GC6125@nataraja> <20160404081600.GB7397@dub6> Message-ID: <20160405130605.GE3653@ass40.sysmocom.de> On Mon, Apr 04, 2016 at 10:16:00AM +0200, Neels Hofmeyr wrote: > On Sun, Apr 03, 2016 at 10:27:51PM +0200, Harald Welte wrote: > > Hi Neels, > > > > one more comment: > > > > On Sun, Apr 03, 2016 at 10:05:07PM +0200, Harald Welte wrote: > > > I therefore think the HNB-GW should try to look only like a single RNC > > > to the MSC, and very clearly only a single RANAP Reset should be sent. > > > > One further reason: The RNC-ID only has a range from 0..4095, i.e. if > > Hold on, in the RANAP specs I see the Extended RNC-ID IE: > > "The Extended RNC-ID IE shall be used if the RNC identity has a value > larger than 4095." > > It extends the range to ..65535 (9.2.1.39a in 3GPP TS 25.413 version > 12.4.0 Release 12). However, in our asn.1 the Extended RNC-ID seems to be available only for Enhanced Relocation Complete messages. 9.1.33 lists it as optional IE for an InitialUE message, but it seems I can't parse it with anything except ranap_decode_enhancedrelocationcompleterequesties(), which is not related to InitialUE messages. It thus seems that extended RNC IDs aren't widely used? I also found the words "Note: Application of the Extended RNC-ID IE to very large networks is FFS." in 9.2.1.39a. FFS meaning... For Future Something? I'm not supporting extended RNC-Ids at this point. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From holger at freyther.de Tue Apr 5 14:44:50 2016 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 5 Apr 2016 16:44:50 +0200 Subject: [PATCH] misc: Replace libosmocore with talloc Message-ID: <1459867490-66746-1-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther The libosmocore depedency is used for talloc and OSMO_ASSERT. Reduce the depedencies by using libtalloc directly and replace the ASSERT with a local one (without backtrace support). --- configure.ac | 2 +- include/asn1c/asn_internal.h | 2 +- libasn1c.pc.in | 4 ++-- src/Makefile.am | 4 ++-- src/asn1helpers.c | 20 ++++++++++++-------- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index aaa2b5a..dcec465 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ AC_PROG_LIBTOOL AC_CONFIG_MACRO_DIR([m4]) -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.13) +PKG_CHECK_MODULES(LIBTALLOC, talloc) # The following test is taken from WebKit's webkit.m4 saved_CFLAGS="$CFLAGS" diff --git a/include/asn1c/asn_internal.h b/include/asn1c/asn_internal.h index 58b4583..580c2e7 100644 --- a/include/asn1c/asn_internal.h +++ b/include/asn1c/asn_internal.h @@ -15,7 +15,7 @@ #include /* for assert() macro */ #endif -#include +#include #ifdef __cplusplus extern "C" { diff --git a/libasn1c.pc.in b/libasn1c.pc.in index 149fe2d..89ad53a 100644 --- a/libasn1c.pc.in +++ b/libasn1c.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: asn1c runtime library Description: C Utility Library Version: @VERSION@ -Libs: -L${libdir} -lasn1c -lm -Cflags: -I${includedir}/ -I${includedir}/asn1c +Libs: -L${libdir} @LIBTALLOC_LIBS@ -lasn1c -lm +Cflags: -I${includedir}/ -I${includedir}/asn1c @LIBTALLOC_CFLAGS@ diff --git a/src/Makefile.am b/src/Makefile.am index 120d29b..0f05cce 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,13 +4,13 @@ LIBVERSION=1:0:0 AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include/asn1c -AM_CFLAGS = -fPIC -Wall $(LIBOSMOCORE_CFLAGS) +AM_CFLAGS = -fPIC -Wall $(LIBTALLOC_CFLAGS) if BUILD_DEBUG AM_CFLAGS += -DEMIT_ASN_DEBUG=1 endif lib_LTLIBRARIES = libasn1c.la -libasn1c_la_LDFLAGS = $(LIBOSMOCORE_LIBS) +libasn1c_la_LDFLAGS = $(LIBTALLOC_LIBS) libasn1c_la_SOURCES = ANY.c constraints.c GeneralizedTime.c NumericString.c T61String.c asn_codecs_prim.c constr_CHOICE.c GeneralString.c ObjectDescriptor.c TeletexString.c asn_SEQUENCE_OF.c constr_SEQUENCE.c GraphicString.c OBJECT_IDENTIFIER.c UniversalString.c asn_SET_OF.c constr_SEQUENCE_OF.c IA5String.c OCTET_STRING.c UTCTime.c ber_decoder.c constr_SET.c INTEGER.c per_decoder.c UTF8String.c ber_tlv_length.c constr_SET_OF.c ISO646String.c per_encoder.c VideotexString.c ber_tlv_tag.c constr_TYPE.c NativeEnumerated.c per_support.c VisibleString.c BIT_STRING.c NativeInteger.c PrintableString.c xer_decoder.c BMPString.c der_encoder.c NativeReal.c REAL.c xer_encoder.c BOOLEAN.c ENUMERATED.c NULL.c RELATIVE-OID.c xer_support.c per_opentype.c asn1helpers .c diff --git a/src/asn1helpers.c b/src/asn1helpers.c index 8ce9bf4..aca5300 100644 --- a/src/asn1helpers.c +++ b/src/asn1helpers.c @@ -22,11 +22,15 @@ #include #include -#include - #include "asn1helpers.h" #include "asn_internal.h" +#define ASN1C_ASSERT(exp) \ + if (!(exp)) { \ + fprintf(stderr, "Assert failed %s %s:%d\n", #exp, __FILE__, __LINE__); \ + abort(); \ + } + void asn1_u32_to_bitstring(BIT_STRING_t *bitstr, uint32_t *buf, uint32_t in) { *buf = htonl(in); @@ -126,39 +130,39 @@ int asn1_strncpy(char *out, const OCTET_STRING_t *in, size_t n) uint32_t asn1str_to_u32(const OCTET_STRING_t *in) { - OSMO_ASSERT(in && in->size == sizeof(uint32_t)); + ASN1C_ASSERT(in && in->size == sizeof(uint32_t)); return ntohl(*(uint32_t *)in->buf); } uint16_t asn1str_to_u16(const OCTET_STRING_t *in) { - OSMO_ASSERT(in && in->size == sizeof(uint16_t)); + ASN1C_ASSERT(in && in->size == sizeof(uint16_t)); return ntohs(*(uint16_t *)in->buf); } uint8_t asn1str_to_u8(const OCTET_STRING_t *in) { - OSMO_ASSERT(in && in->size == sizeof(uint8_t)); + ASN1C_ASSERT(in && in->size == sizeof(uint8_t)); return *(uint8_t *)in->buf; } uint32_t asn1bitstr_to_u32(const BIT_STRING_t *in) { - OSMO_ASSERT(in && in->size == sizeof(uint32_t)); + ASN1C_ASSERT(in && in->size == sizeof(uint32_t)); return ntohl(*(uint32_t *)in->buf); } uint32_t asn1bitstr_to_u28(const BIT_STRING_t *in) { - OSMO_ASSERT(in && in->size == sizeof(uint32_t) && in->bits_unused == 4); + ASN1C_ASSERT(in && in->size == sizeof(uint32_t) && in->bits_unused == 4); return ntohl(*(uint32_t *)in->buf) >> 4; } uint32_t asn1bitstr_to_u24(const BIT_STRING_t *in) { - OSMO_ASSERT(in && in->size == 3); + ASN1C_ASSERT(in && in->size == 3); return ntohl(*(uint32_t *)in->buf) >> 8; } -- 2.6.3 From laforge at gnumonks.org Tue Apr 5 17:12:49 2016 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 5 Apr 2016 19:12:49 +0200 Subject: [PATCH] misc: Replace libosmocore with talloc In-Reply-To: <1459867490-66746-1-git-send-email-holger@freyther.de> References: <1459867490-66746-1-git-send-email-holger@freyther.de> Message-ID: <20160405171249.GQ16601@nataraja> Hi Holger, On Tue, Apr 05, 2016 at 04:44:50PM +0200, Holger Hans Peter Freyther wrote: > The libosmocore depedency is used for talloc and OSMO_ASSERT. > Reduce the depedencies by using libtalloc directly and replace > the ASSERT with a local one (without backtrace support). looks fine to me! -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From holger at freyther.de Tue Apr 5 20:38:12 2016 From: holger at freyther.de (Holger Freyther) Date: Tue, 5 Apr 2016 22:38:12 +0200 Subject: [PATCH 2/4] NAT: vty command to display number of BSCs In-Reply-To: <1459776656-31929-2-git-send-email-msuraev@sysmocom.de> References: <1459776656-31929-1-git-send-email-msuraev@sysmocom.de> <1459776656-31929-2-git-send-email-msuraev@sysmocom.de> Message-ID: > On 04 Apr 2016, at 15:30, msuraev at sysmocom.de wrote: > > From: Max > > Add command 'show nat bsc' to display number of configured BSCs. Thank you for moving this to a separate patch. > +DEFUN(show_nat_bsc, show_nat_bsc_cmd, "show nat bsc", > + SHOW_STR "Display NAT configuration details\n" > + "BSCs-related\n") > +{ > + vty_out(vty, "%d BSCs configured%s", _nat->num_bsc, VTY_NEWLINE); > + return CMD_SUCCESS; > +} If somebody asked me what "show nat bsc" would do, I would not have guessed it prints a number. Can you think of a better name? "show nat configured-bsc-count"? "show nat bscs-configured"? "show nat num-bscs-configured"? kind regards holger From holger at freyther.de Tue Apr 5 20:47:13 2016 From: holger at freyther.de (Holger Freyther) Date: Tue, 5 Apr 2016 22:47:13 +0200 Subject: [PATCH 1/2] Refactor mncc code In-Reply-To: <1458817545-2039-1-git-send-email-msuraev@sysmocom.de> References: <1458817545-2039-1-git-send-email-msuraev@sysmocom.de> Message-ID: > On 24 Mar 2016, at 12:05, msuraev at sysmocom.de wrote: > > From: Max > > Use bool for boolean types. > Consistently use enums instead of (u)int, char etc. > Note: because actual enum representation is up to compiler this might > change the size of gsm_mncc struct. => bump protocol version then > -int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate); > +int gsm0808_assign_req(struct gsm_subscriber_connection *conn, enum gsm48_chan_mode chan_mode, bool full_rate); we had this out of band. The topic is "boolean" trap, so if you want to change, then also consider using enums with just two values to express the meaning even stronger (and allow for extension). E.g. with "full rate" it might turn into a tri-state * You have to use a TCH/F * You have to use a TCH/H * It would be nice to use a TCH/F.. > > -int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode) > +int gsm48_lchan_modify(struct gsm_lchan *lchan, enum gsm48_chan_mode lchan_mode) > { > - int rc; > - > - rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode); > - if (rc < 0) > - return rc; > - > - return rc; > + return gsm48_tx_chan_mode_modify(lchan, lchan_mode); > } hehe, split this into a separate patch. Yes, it is obvious it returns rc either way and let's assume we don't have a unsigned -> int kind of conversion here. From holger at freyther.de Tue Apr 5 20:51:20 2016 From: holger at freyther.de (Holger Freyther) Date: Tue, 5 Apr 2016 22:51:20 +0200 Subject: [PATCH] Add ubit <-> sbit convertors In-Reply-To: <1459784977-2471-1-git-send-email-msuraev@sysmocom.de> References: <1459784977-2471-1-git-send-email-msuraev@sysmocom.de> Message-ID: <4549DE5D-D786-45E5-9040-003E7139CB28@freyther.de> > On 04 Apr 2016, at 17:49, msuraev at sysmocom.de wrote: > > From: Max > > Move functions for conversion between soft and unpacked bits to main > library as they are generally useful. Hi! > +void osmo_ubit2sbit(sbit_t *out, const ubit_t *in, unsigned int num_bits) > +{ > + int i; > + for (i = 0; i < num_bits; i++) > + out[i] = in[i] ? -127 : 127; > -static void > -ubit_to_sbit(sbit_t *dst, ubit_t *src, int n) either keep it with 'int' or at least be consistent. Doesn't the compiler warn here anyway? We don't expect to run on systems where sizeof(int) < sizeof(4) and num_bits > INT_MAX is very unlikely for our domain. Anyway. if you decide to to use unsigned (or size_t) then please be consistent and use it for num_bits and the index variable. thanks holger From holger at freyther.de Tue Apr 5 21:00:31 2016 From: holger at freyther.de (Holger Freyther) Date: Tue, 5 Apr 2016 23:00:31 +0200 Subject: [PATCH 3/4] NAT: move BSC config into separate file In-Reply-To: <1459776656-31929-3-git-send-email-msuraev@sysmocom.de> References: <1459776656-31929-1-git-send-email-msuraev@sysmocom.de> <1459776656-31929-3-git-send-email-msuraev@sysmocom.de> Message-ID: > On 04 Apr 2016, at 15:30, msuraev at sysmocom.de wrote: > Hi Max, > +const char *bsc_nat_resolve_path(void *ctx, const char *base, const char *name) > +{ > + return ('/' == name[0]) ? name : talloc_asprintf(ctx, "%s/%s", base, > + name); > +} I had hinted to you to repeat config reload (and relative paths) and observing memory consumption by using top -p `pidof osmo-bsc_nat`. This routine is problematic either way in C. Semantic: Sometimes new memory will be allocated sometimes not Responsibility: Sometimes the callers needs to call talloc_free, sometimes not. Result: a.) Caller will never call talloc_free => sometimes leaks b.) Caller will always call talloc_free => sometimes crashes Solution: Make the semantic consistent So please, take this leak and make yourself familiar with valgrind, talloc leak check, etc. It is important to learn from it. See my previous mail for an example how to script it. kind regards holger From holger at freyther.de Tue Apr 5 21:08:58 2016 From: holger at freyther.de (Holger Freyther) Date: Tue, 5 Apr 2016 23:08:58 +0200 Subject: [PATCH] NAT: reload BSCs config dynamically In-Reply-To: <1459778794-15778-1-git-send-email-msuraev@sysmocom.de> References: <1459778794-15778-1-git-send-email-msuraev@sysmocom.de> Message-ID: > On 04 Apr 2016, at 16:06, msuraev at sysmocom.de wrote: > > > @@ -1321,8 +1321,8 @@ static int ipaccess_bsc_read_cb(struct osmo_fd *bfd) > bsc->cfg ? bsc->cfg->nr : -1); > else > LOGP(DNAT, LOGL_ERROR, > - "Stream error on BSC Nr: %d. Failed to parse ip access message: %d\n", > - bsc->cfg ? bsc->cfg->nr : -1, ret); > + "Stream error on BSC Nr: %d. Failed to parse ip access message: %d (%s)\n", > + bsc->cfg ? bsc->cfg->nr : -1, ret, strerror(-ret)); good! but separate patch. And have a look at where ret is coming from that you need to invert it. > > bsc_replace_string(_nat, &_nat->include_file, argv[0]); > + > + llist_for_each_entry_safe(con1, con2, &_nat->bsc_connections, > + list_entry) { > + if (con1->cfg) > + if (con1->cfg->token_updated || con1->cfg->remove) > + bsc_close_connection(con1); > + } In terms of style the following is preferred as it is reducing the level of indentation and makes you see what the code is about (instead of shifting it to the right) if (!con1->cfg) continue; if (!con->cfg->token_updated && !con1->cfg->remove) continue; bsc_close_connection(con1); resulting assembly should not be any different and the ultimate action is seen. > + > + llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) { > + if (cf1->remove) { > + bsc_config_free(cf1); > + _nat->num_bsc--; that one is a "nasty" topic 1.) this should be within bsc_config_free 2.) bsc_config_alloc(..) { conf->nr = nat->num_bsc; and the code assumes that conf->nr is unique so if we do num_bsc-- and then num_bsc++ again we might re-use an existing id and break the assumption.. What I propose (and in a separate patch) * Remove the requirement to assign BSCs in order. I thought I had lifted it a long time ago (but I did not) * Change bsc_config_alloc to include the nr to be assigned * change cfg_bsc_mcd to first search the given BSC and then create one.. holger From mdaiter8121 at gmail.com Tue Apr 5 21:18:51 2016 From: mdaiter8121 at gmail.com (Matthew Daiter) Date: Tue, 5 Apr 2016 23:18:51 +0200 Subject: Patches Message-ID: Hey, Was scrolling across some of your code and saw some syntactical touching up and optimizations that could be made. They're attached, if you'd like to commit them. Best, Matthew Daiter -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- diff --git a/openbsc/src/osmo-bsc/osmo_bsc_filter.c b/openbsc/src/osmo-bsc/osmo_bsc_filter.c index 14e0b71..5ad9fd7 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_filter.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_filter.c @@ -160,11 +160,9 @@ struct osmo_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, round_robin: llist_for_each_entry(msc, &bsc->mscs, entry) { - if (!msc->msc_con->is_authenticated) - continue; - if (!is_emerg && msc->type != MSC_CON_TYPE_NORMAL) - continue; - if (is_emerg && !msc->allow_emerg) + if ((!msc->msc_con->is_authenticated) || + (!is_emerg && msc->type != MSC_CON_TYPE_NORMAL) || + (is_emerg && !msc->allow_emerg)) continue; /* force round robin by moving it to the end */ -------------- next part -------------- diff --git a/openbsc/src/osmo-bsc/osmo_bsc_filter.c b/openbsc/src/osmo-bsc/osmo_bsc_filter.c index 5ad9fd7..6b15886 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_filter.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_filter.c @@ -47,7 +47,7 @@ static void handle_lu_request(struct gsm_subscriber_connection *conn, gsm48_generate_lai(&lai, net->country_code, net->network_code, conn->bts->location_area_code); - if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) { + if (memcmp(&lai, &lu->lai, sizeof(lai))) { LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n"); conn->sccp_con->new_subscriber = 1; } @@ -314,13 +314,10 @@ static int bsc_patch_mm_info(struct gsm_subscriber_connection *conn, static int has_core_identity(struct osmo_msc_data *msc) { - if (msc->core_mnc != -1) - return 1; - if (msc->core_mcc != -1) - return 1; - if (msc->core_lac != -1) - return 1; - if (msc->core_ci != -1) + if ((msc->core_mnc != -1) || + (msc->core_mcc != -1) || + (msc->core_lac != -1) || + (msc->core_ci != -1)) return 1; return 0; } @@ -367,7 +364,6 @@ int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg) if (conn->sccp_con->new_subscriber) return send_welcome_ussd(conn); - return 0; } else if (mtype == GSM48_MT_MM_INFO) { bsc_patch_mm_info(conn, &gh->data[0], length); } From tom.tsou at ettus.com Wed Apr 6 07:01:05 2016 From: tom.tsou at ettus.com (Tom Tsou) Date: Wed, 6 Apr 2016 00:01:05 -0700 Subject: Lack of maintenance for osmo-bts-trx Message-ID: Hi Harald, On Mon, Apr 4, 2016 at 8:10 AM, Harald Welte wrote: > Ever since the merge in August 2015, as far as I recall, I never saw a > single message from any osmo-bts-trx user whether > a) the L1SAP merge back then works for them > b) it introduced any regressions I suspect that there were issues since the beginning of the merge. The issue that I saw with master was reported by Sipos Csaba back in Nov 2015. http://lists.osmocom.org/pipermail/openbsc/2015-November/000856.html Unlike Alexander, I was never able to setup a working version with older commits including the one specified in this post. http://lists.osmocom.org/pipermail/openbsc/2015-September/000398.html I guess there is something wrong with the OML setup since trx->mo.nm_state is reporting NM_OPSTATE_NULL during the post-RACH channel allocation, but I am not familiar enough with those procedures to debug more. > While some people think I sometimes write good code, I fail to believe > that all those intrusive changes didn't break anything for OsmoTRX > users. Still, no feedback and no fall-out was reported. I suspect the case was that very few users, if any, had working setups to break or to report regressions. > Like any larger project, particularly one with different hardware > support, we need somebody with essential interest in that hardware to > maintain the respective back-end. Think of device driver maintainers in > the Linux kernel as an example. Agreed. > We need a sub-maintainer for osmo-bts-trx, one who > 1) consistently follows the developments in master and checks for > regressiosn > 2) fixes osmo-bts-trx specific bugs like the fact that GPRS measurment > values are not passed to the PCU, breaking rate/link adaption for > this platform > 3) tests interoperability with OsmoTRX and other OpenBTS transceivers > out three > 4) ensures that important osmo-bts-trx related patches/branches end up > in master, ensuring that master is what people use. Telling users to > use a branch different than master is *wrong* for anything but the > most bleeding edge / experiemental code which is to be merged ASAP. i I can provide a supporting role in the above tasks on behalf of Ettus but we do need a working starting point - that makes number 4 the most critical item. Unfortunately, I am not able to resolve the patch differences (I painfully tried) to make master the main user branch. I agree that directing users to the Fairwaves branch is the wrong approach, but right now it is the only branch for osmo-bts-trx that works. -TT From laforge at gnumonks.org Wed Apr 6 07:46:38 2016 From: laforge at gnumonks.org (Harald Welte) Date: Wed, 6 Apr 2016 09:46:38 +0200 Subject: Lack of maintenance for osmo-bts-trx In-Reply-To: References: <20160404151058.GN27299@nataraja> Message-ID: <20160406074638.GH11135@nataraja> Hi Alexander, On Mon, Apr 04, 2016 at 09:35:31PM +0100, Alexander Chemeris wrote: > I guess the frustration was mutual - about a year ago we had a chat that > the branch couldn't be merged only because Sysmocom didn't have time to > test it with their hardware. We even offered to pay for that testing, but > it never happened. So I guess it took some other incentives to get it > merged. Indeed it took long to get L1SAP tested + merged. To be fair though, L1SAP was the single biggest infrastructure change in the history of the OsmoBTS project, and even careful review didn't prevent a lot of fall-out from the merge which we subsequently had to fix. > Now it's our time to take time and test the latest master for > compatibility with our hardware. Meanwhile we unfortunately have to > maintain a version which works for us. I very well understand the need for _also_ maintaining a stable branch for existing users, of course. That's a frequent pratise and makes a lot of sense. But companies with a lot of experience in FOSS (e.g. Redhat in case of the Linux kernel) have long adopted an "upstream first" policy, i.e. you first fix a bug or add a feature in master and submit it upstream, and then back-port it to your stable version(s). That's the only sustainable way in the long term, rather than spending more and more time catching up and forward-porting an every growing pile of out-of-master patches. But the question the even goes as far as 'why have osmo-bts-trx in master then in the first place?'. Now I certainly don't want to intentionally push anything out of master, but what's the point of keeping something in master for many months (August 2015 to April 2016) if it is known to be broken, and none of the users or proponents of the respective hardware have the interest or time in investigating and/or fixing it? It just creats a situation that's confusing to everyone involved, including the users. > There were reports that the latest master of osmo-bts-trx doesn't work and > I can confirm that that's the case. There were also a report from me that > the branch right after the merge with master "basically worked". So you > can't blame community for not reporting. But where is the detailed analysis? Where are the related fixes submitted to the mailing lists? > That said, once we get over the potential barrier of fixing the master and > porting our changes to it, we'll be happy to maintain it further on, as we > do with our branch right now. Thanks. Then we "just" have to find somebody who finally, after many months of apparently/allegedly broken master, thinks it is worth to investigate the actual issue or issues that may exist. > On Mon, Apr 4, 2016 at 4:10 PM, Harald Welte wrote: > [...] As an unrelated side note, I would appreciate if you could avoid top-posting/full-quoting on the mailing lists, if possible. Just a friendly reminder, I'd like to avoid anyone interpreting more into that. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Wed Apr 6 07:59:11 2016 From: laforge at gnumonks.org (Harald Welte) Date: Wed, 6 Apr 2016 09:59:11 +0200 Subject: Lack of maintenance for osmo-bts-trx In-Reply-To: References: Message-ID: <20160406075911.GI11135@nataraja> Hi Tom, On Wed, Apr 06, 2016 at 12:01:05AM -0700, Tom Tsou wrote: > I suspect that there were issues since the beginning of the merge. The > issue that I saw with master was reported by Sipos Csaba back in Nov > 2015. > > http://lists.osmocom.org/pipermail/openbsc/2015-November/000856.html > > I guess there is something wrong with the OML setup since > trx->mo.nm_state is reporting NM_OPSTATE_NULL during the post-RACH > channel allocation, but I am not familiar enough with those procedures > to debug more. The lack of proper OML MO state machines on both sides of the A-bis OML link doesn't make it easier either, I know :/ I'm not quite sure how that relates to the bug report above, which indicates a problem in the UDP-based osmo-trx/osmo-bts-trx control interface about setting the BSIC. I would assume that this is the root cause, which only elevates towards e.g. a MO state not changing as it normally should. > I can provide a supporting role in the above tasks on behalf of Ettus Thanks. > but we do need a working starting point - that makes number 4 the most > critical item. Unfortunately, I am not able to resolve the patch > differences (I painfully tried) to make master the main user branch. I > agree that directing users to the Fairwaves branch is the wrong > approach, but right now it is the only branch for osmo-bts-trx that > works. Can you or somebody else interested in getting this resolved provide a full bug report, including * debug log output on OsmoNITB side for for the rsl and nm * debug log output on OsmoBTS side for oml / transceiver interface or anything else related * pcap file of A-bis traffic between OsmoBTS and OsmoNITB, as well as the control commands between osmo-bts-trx and osmo-trx The above is what to me seems like the "obvious" way to report a bug in order for other developers on this list to try to figure out what is causing the problem. Maybe it's not as obvious to others and we should put together some guidelines in the wiki on this? In any case, I don't recall seeing a comprehensive report like this on the list yet. If I missed it, my apologies. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Wed Apr 6 08:05:46 2016 From: laforge at gnumonks.org (Harald Welte) Date: Wed, 6 Apr 2016 10:05:46 +0200 Subject: Patches In-Reply-To: References: Message-ID: <20160406080546.GJ11135@nataraja> Hi Matthew, thanks for your patches and your interest in contributing. On Tue, Apr 05, 2016 at 11:18:51PM +0200, Matthew Daiter wrote: > - if (!msc->msc_con->is_authenticated) > - continue; > - if (!is_emerg && msc->type != MSC_CON_TYPE_NORMAL) > - continue; > - if (is_emerg && !msc->allow_emerg) > + if ((!msc->msc_con->is_authenticated) || > + (!is_emerg && msc->type != MSC_CON_TYPE_NORMAL) || > + (is_emerg && !msc->allow_emerg)) > continue; I thinkt it's a matter of taste. To me, the existing code actually is more obvious and easier to read, as convolutd nested parenthesis in a single 'if' statement, where there are more possible relationship of the individual conditions. > - if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) { > + if (memcmp(&lai, &lu->lai, sizeof(lai))) { again here, it is a question of taste. The '!= 0' proabably serves as a reminder at the strange behavior of memcmp() returning 0 in case of success. So I'm sorry, but I wouldn't merge any of your patches, I don't think they make the core more readable or improve it in any other way :( I'd hope you could focus your interest in contributing into a different area that actually makes a difference to the OpenBSC user community. Thanks! -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Wed Apr 6 08:09:01 2016 From: laforge at gnumonks.org (Harald Welte) Date: Wed, 6 Apr 2016 10:09:01 +0200 Subject: [osmo-sim-auth] Only AUTS returning In-Reply-To: <56FC446E.8010209@posteo.de> References: <56FC446E.8010209@posteo.de> Message-ID: <20160406080901.GK11135@nataraja> Hi Marco, On Wed, Mar 30, 2016 at 11:26:06PM +0200, Marco Heumann wrote: > a student college and me are using the osmo-sim-auth tool for a student > project. We have valid data for our SIM card since it's a special > ordered test SIM card. are you aware that test sim cards sometimes use different algorithms (XOR instead of MILENAGE) and even might have the sequence number (SQN) handling turned off? > In 2G mode we get the correct RES value, but in 3G mode we always get > only an AUTS value. We calculated the SQN value from the AUTS to > verify that we have the correct SQN value, but still we only get AUTS > as return. What is your expectation? What do you expect in addition to the AUTS? Have you actually bothered to look at the code of osmo-sim-auth.py? In UMTS AKA case, there is only a single print line: ????????ret = u.authenticate(rand_bin, autn_bin, ctx='3G') ????????if len(ret) == 1: ????????????????print "AUTS:\t%s" % b2a_hex(byteToString(ret[0])) ????????else: ????????????????print "RES:\t%s" % b2a_hex(byteToString(ret[0])) ????????????????print "CK:\t%s" % b2a_hex(byteToString(ret[1])) ????????????????print "IK:\t%s" % b2a_hex(byteToString(ret[2])) ????????????????if len(ret) == 4: ????????????????????????print "Kc:\t%s" % b2a_hex(byteToString(ret[3])) maybe you simply want to add the print-out of what you wnat to see printed? -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From sipos.csaba at kvk.uni-obuda.hu Wed Apr 6 09:46:17 2016 From: sipos.csaba at kvk.uni-obuda.hu (Sipos Csaba) Date: Wed, 6 Apr 2016 11:46:17 +0200 (CEST) Subject: Lack of maintenance for osmo-bts-trx In-Reply-To: <20160406075911.GI11135@nataraja> References: <20160406075911.GI11135@nataraja> Message-ID: <1394564972.2070353.1459935977632.JavaMail.zimbra@kvk.uni-obuda.hu> Dear Harald, As one of the few users of OsmoBTS/OsmoNITB with an USRP SDR, let me comment on this one. First, I don't have any commercial interest in this, I am an academic researcher, and as most of us, the only way to be able to create a GSM network and test it is via an SDR. For this reason I created and maintaining the Wiki article of how to get the full Osmocom stack to work with and Ettus SDR: http://openbsc.osmocom.org/trac/wiki/Ettus_USRP_B2xx_family For the first few tries I was only able to get it work with a lot of non-master branches involved. At this time, almost all non-master branches are now avoided, OsmoBTS is the only one that remains. I wanted to update this Wiki article and debug the current failures with EDGE introduced on both the PCU/BTS and TRX end, but unfortunately I am now abroad and I don't have access to any USRP devices. When I'll be back home, I am willing to take a closer look and try findig the issues, but that is 2 months away. Regards, Csaba ----- Eredeti ?zenet ----- Felad?: "Harald Welte" C?mzett: "Tom Tsou" M?solatot kap: "OpenBSC Mailing List" Elk?ld?tt ?zenetek: Szerda, 2016. ?prilis 6. 9:59:11 T?rgy: Re: Lack of maintenance for osmo-bts-trx Hi Tom, On Wed, Apr 06, 2016 at 12:01:05AM -0700, Tom Tsou wrote: > I suspect that there were issues since the beginning of the merge. The > issue that I saw with master was reported by Sipos Csaba back in Nov > 2015. > > http://lists.osmocom.org/pipermail/openbsc/2015-November/000856.html > > I guess there is something wrong with the OML setup since > trx->mo.nm_state is reporting NM_OPSTATE_NULL during the post-RACH > channel allocation, but I am not familiar enough with those procedures > to debug more. The lack of proper OML MO state machines on both sides of the A-bis OML link doesn't make it easier either, I know :/ I'm not quite sure how that relates to the bug report above, which indicates a problem in the UDP-based osmo-trx/osmo-bts-trx control interface about setting the BSIC. I would assume that this is the root cause, which only elevates towards e.g. a MO state not changing as it normally should. > I can provide a supporting role in the above tasks on behalf of Ettus Thanks. > but we do need a working starting point - that makes number 4 the most > critical item. Unfortunately, I am not able to resolve the patch > differences (I painfully tried) to make master the main user branch. I > agree that directing users to the Fairwaves branch is the wrong > approach, but right now it is the only branch for osmo-bts-trx that > works. Can you or somebody else interested in getting this resolved provide a full bug report, including * debug log output on OsmoNITB side for for the rsl and nm * debug log output on OsmoBTS side for oml / transceiver interface or anything else related * pcap file of A-bis traffic between OsmoBTS and OsmoNITB, as well as the control commands between osmo-bts-trx and osmo-trx The above is what to me seems like the "obvious" way to report a bug in order for other developers on this list to try to figure out what is causing the problem. Maybe it's not as obvious to others and we should put together some guidelines in the wiki on this? In any case, I don't recall seeing a comprehensive report like this on the list yet. If I missed it, my apologies. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From nhofmeyr at sysmocom.de Wed Apr 6 10:19:45 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 6 Apr 2016 12:19:45 +0200 Subject: [PATCH 3/3] mgcp: Remove the old MGCP based transcoding interface In-Reply-To: <1457458520-34314-3-git-send-email-holger@freyther.de> References: <1457458520-34314-1-git-send-email-holger@freyther.de> <1457458520-34314-3-git-send-email-holger@freyther.de> Message-ID: <20160406101945.GA2470@dub6> On Tue, Mar 08, 2016 at 06:35:20PM +0100, Holger Hans Peter Freyther wrote: > --- a/openbsc/src/libmgcp/mgcp_network.c > +++ b/openbsc/src/libmgcp/mgcp_network.c [...] > @@ -688,7 +661,6 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what) > > switch(endp->type) { > case MGCP_RTP_DEFAULT: > - case MGCP_RTP_TRANSCODED: > if (endp->net_end.rtp_port != addr.sin_port && > endp->net_end.rtcp_port != addr.sin_port) { > LOGP(DMGCP, LOGL_ERROR, > @@ -719,9 +691,6 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what) > case MGCP_RTP_DEFAULT: > return mgcp_send(endp, MGCP_DEST_BTS, proto == MGCP_PROTO_RTP, > &addr, buf, rc); > - case MGCP_RTP_TRANSCODED: > - return mgcp_send_transcoder(&endp->trans_net, endp->cfg, > - proto == MGCP_PROTO_RTP, buf, rc); > case MGCP_OSMUX_BSC_NAT: > return osmux_xfrm_to_osmux(MGCP_DEST_BTS, buf, rc, endp); > case MGCP_OSMUX_BSC: /* Should not happen */ > @@ -811,9 +780,6 @@ static int rtp_data_bts(struct osmo_fd *fd, unsigned int what) > case MGCP_RTP_DEFAULT: > return mgcp_send(endp, MGCP_DEST_NET, proto == MGCP_PROTO_RTP, > &addr, buf, rc); > - case MGCP_RTP_TRANSCODED: > - return mgcp_send_transcoder(&endp->trans_bts, endp->cfg, > - proto == MGCP_PROTO_RTP, buf, rc); > case MGCP_OSMUX_BSC: > /* OSMUX translation: BTS -> BSC */ > return osmux_xfrm_to_osmux(MGCP_DEST_NET, buf, rc, endp); It could be a good idea to add 'default:' cases to above switch statements? Now that we're removing some cases, would be good to catch callers still passing one of the legacy cases (for whatever weird reasons)... ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Wed Apr 6 10:24:41 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 6 Apr 2016 12:24:41 +0200 Subject: [PATCH 1/3] subscr: Add testcase creating an already created subscriber In-Reply-To: <1459535615-16683-1-git-send-email-holger@freyther.de> References: <1459535615-16683-1-git-send-email-holger@freyther.de> Message-ID: <20160406102441.GB2470@dub6> On Fri, Apr 01, 2016 at 08:33:33PM +0200, Holger Freyther wrote: > From: Holger Hans Peter Freyther > > Add testcase to issue the subscriber create twice. Could be nice to add this clarification in the test code as comment: > db_create_subscriber in db.c will first try to find the subscriber and if it > exists, it will update the "updated" column in the database. [...] > + > + # Lets create one > + res = self.vty.command('subscriber create imsi '+imsi) > + self.assert_(res.find(" IMSI: "+imsi) > 0) ... right here. > + res2 = self.vty.command('subscriber create imsi '+imsi) > + self.assert_(res2.find(" IMSI: "+imsi) > 0) > + self.assertEqual(res, res2) The test isn't testing the update of the 'updated' column, right? Why though would the db want to update the 'updated' column for such a noop anyway? ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Wed Apr 6 10:34:50 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 6 Apr 2016 12:34:50 +0200 Subject: [PATCH 2/3] subscr: Make db_create_subscriber fail on duplicates In-Reply-To: <1459535615-16683-2-git-send-email-holger@freyther.de> References: <1459535615-16683-1-git-send-email-holger@freyther.de> <1459535615-16683-2-git-send-email-holger@freyther.de> Message-ID: <20160406103450.GC2470@dub6> On Fri, Apr 01, 2016 at 08:33:34PM +0200, Holger Freyther wrote: > From: Holger Hans Peter Freyther > > The issue of db_create_subscriber updating an already existing subcr s/subcr/subscr ;) > is that the same subscriber will then have two entries in the active > subscribers list. In general this will break assumptions that a subscr > can be compared by comparing the pointer. > > In the case of the VTY this was not an issue as the created subscr > was immediately destroyed again but it is better to avoid this problem. > > Change the VTY command to find the subscriber and then call sync to > have the updated time set. The side-effect is we will now have two > queries for the subscriber. Once through subscr_get_by_imsi and once > through db_create_subscriber. > > Change the db_create_subscriber to fail if a subscriber already exists, and do not update the 'updated' timestamp of an already existing subscriber. Add a testcase for this behavior. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Wed Apr 6 10:37:37 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 6 Apr 2016 12:37:37 +0200 Subject: [PATCH 3/3] db: If creating a subscriber in the db fails, return NULL In-Reply-To: <1459535615-16683-3-git-send-email-holger@freyther.de> References: <1459535615-16683-1-git-send-email-holger@freyther.de> <1459535615-16683-3-git-send-email-holger@freyther.de> Message-ID: <20160406103737.GD2470@dub6> On Fri, Apr 01, 2016 at 08:33:35PM +0200, Holger Freyther wrote: > From: Holger Hans Peter Freyther > > We should not return a subscriber in case it was not written to > the database. Instead free the memory allocated and return NULL. > Callers in gsm_04_08.c are prepared to have the creation fail. > > Related: OS Issue #1657 curious: 1657 says "VTY command seems to be able to crash OsmoNITB", how did that happen, and does this patch set change anything about it? ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From holger at freyther.de Wed Apr 6 10:41:40 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 6 Apr 2016 12:41:40 +0200 Subject: [PATCH 3/3] db: If creating a subscriber in the db fails, return NULL In-Reply-To: <20160406103737.GD2470@dub6> References: <1459535615-16683-1-git-send-email-holger@freyther.de> <1459535615-16683-3-git-send-email-holger@freyther.de> <20160406103737.GD2470@dub6> Message-ID: > On 06 Apr 2016, at 12:37, Neels Hofmeyr wrote: > >> >> Related: OS Issue #1657 > > curious: 1657 says "VTY command seems to be able to crash OsmoNITB", how did > that happen, and does this patch set change anything about it? I don't know. My test tries to explore it but right now I think OS#1657 is not an issue. From msuraev at sysmocom.de Wed Apr 6 11:05:30 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 6 Apr 2016 13:05:30 +0200 Subject: [PATCH 2/2] Add convolutional code generators for CS2/3 In-Reply-To: <1459940730-23452-1-git-send-email-msuraev@sysmocom.de> References: <1459940730-23452-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1459940730-23452-2-git-send-email-msuraev@sysmocom.de> From: Max --- include/osmocom/core/conv_gen.h | 26 ++++++++++++++++++++ src/Makefile.am | 2 +- src/conv_csx_gen.c | 53 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/conv_csx_gen.c diff --git a/include/osmocom/core/conv_gen.h b/include/osmocom/core/conv_gen.h index e4f1b65..eb8668e 100644 --- a/include/osmocom/core/conv_gen.h +++ b/include/osmocom/core/conv_gen.h @@ -44,3 +44,29 @@ static const struct osmo_conv_code osmo_conv_gsm0503_xcch = { .next_output = osmo_conv_gsm0503_xcch_output, .next_state = osmo_conv_gsm0503_xcch_state, }; + +extern const int osmo_conv_gsm0503_cs2_puncture[]; + +/*! \brief structure describing convolutional code CS2 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_cs2 = { + .N = 2, + .K = 5, + .len = 290, + .next_output = osmo_conv_gsm0503_xcch_output, + .next_state = osmo_conv_gsm0503_xcch_state, + .puncture = osmo_conv_gsm0503_cs2_puncture +}; + +extern const int osmo_conv_gsm0503_cs3_puncture[]; + +/*! \brief structure describing convolutional code CS2 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_cs3 = { + .N = 2, + .K = 5, + .len = 334, + .next_output = osmo_conv_gsm0503_xcch_output, + .next_state = osmo_conv_gsm0503_xcch_state, + .puncture = osmo_conv_gsm0503_cs3_puncture +}; diff --git a/src/Makefile.am b/src/Makefile.am index 2555ff8..fceb931 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,7 +13,7 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \ conv_xcch_gen.c write_queue.c utils.c socket.c \ logging.c logging_syslog.c rate_ctr.c \ gsmtap_util.c crc16.c panic.c backtrace.c \ - conv.c application.c rbtree.c strrb.c \ + conv.c application.c conv_csx_gen.c rbtree.c strrb.c \ loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c \ macaddr.c stat_item.c stats.c stats_statsd.c prim.c diff --git a/src/conv_csx_gen.c b/src/conv_csx_gen.c new file mode 100644 index 0000000..a1ef7a8 --- /dev/null +++ b/src/conv_csx_gen.c @@ -0,0 +1,53 @@ +/* + * conv_xcch_gen.c + * + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +const int osmo_conv_gsm0503_cs2_puncture[] = { + 15, 19, 23, 27, 31, 35, 43, 47, 51, 55, 59, 63, 67, 71, 75, 79, 83, 91, + 95, 99, 103, 107, 111, 115, 119, 123, 127, 131, 139, 143, 147, 151, 155, + 159, 163, 167, 171, 175, 179, 187, 191, 195, 199, 203, 207, 211, 215, + 219, 223, 227, 235, 239, 243, 247, 251, 255, 259, 263, 267, 271, 275, + 283, 287, 291, 295, 299, 303, 307, 311, 315, 319, 323, 331, 335, 339, + 343, 347, 351, 355, 359, 363, 367, 371, 379, 383, 387, 391, 395, 399, + 403, 407, 411, 415, 419, 427, 431, 435, 439, 443, 447, 451, 455, 459, + 463, 467, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 515, 523, + 527, 531, 535, 539, 543, 547, 551, 555, 559, 563, 571, 575, 579, 583, + 587, -1 +}; + +const int osmo_conv_gsm0503_cs3_puncture[] = { + 15, 17, 21, 23, 27, 29, 33, 35, 39, 41, 45, 47, 51, 53, 57, 59, 63, 65, + 69, 71, 75, 77, 81, 83, 87, 89, 93, 95, 99, 101, 105, 107, 111, 113, + 117, 119, 123, 125, 129, 131, 135, 137, 141, 143, 147, 149, 153, 155, + 159, 161, 165, 167, 171, 173, 177, 179, 183, 185, 189, 191, 195, 197, + 201, 203, 207, 209, 213, 215, 219, 221, 225, 227, 231, 233, 237, 239, + 243, 245, 249, 251, 255, 257, 261, 263, 267, 269, 273, 275, 279, 281, + 285, 287, 291, 293, 297, 299, 303, 305, 309, 311, 315, 317, 321, 323, + 327, 329, 333, 335, 339, 341, 345, 347, 351, 353, 357, 359, 363, 365, + 369, 371, 375, 377, 381, 383, 387, 389, 393, 395, 399, 401, 405, 407, + 411, 413, 417, 419, 423, 425, 429, 431, 435, 437, 441, 443, 447, 449, + 453, 455, 459, 461, 465, 467, 471, 473, 477, 479, 483, 485, 489, 491, + 495, 497, 501, 503, 507, 509, 513, 515, 519, 521, 525, 527, 531, 533, + 537, 539, 543, 545, 549, 551, 555, 557, 561, 563, 567, 569, 573, 575, + 579, 581, 585, 587, 591, 593, 597, 599, 603, 605, 609, 611, 615, 617, + 621, 623, 627, 629, 633, 635, 639, 641, 645, 647, 651, 653, 657, 659, + 663, 665, 669, 671, -1 +}; -- 2.8.1 From msuraev at sysmocom.de Wed Apr 6 11:05:29 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 6 Apr 2016 13:05:29 +0200 Subject: [PATCH 1/2] Add concolutional code generator for *CCH Message-ID: <1459940730-23452-1-git-send-email-msuraev@sysmocom.de> From: Max Move convolutional code for *CCH channels from test to public API because it's useful not only for testing. --- include/Makefile.am | 1 + include/osmocom/core/conv.h | 2 +- include/osmocom/core/conv_gen.h | 46 +++++++++++++++++++++++++++++++ src/Makefile.am | 4 +-- src/conv_xcch_gen.c | 61 +++++++++++++++++++++++++++++++++++++++++ tests/conv/conv_test.c | 31 ++------------------- 6 files changed, 114 insertions(+), 31 deletions(-) create mode 100644 include/osmocom/core/conv_gen.h create mode 100644 src/conv_xcch_gen.c diff --git a/include/Makefile.am b/include/Makefile.am index 0e5ed74..7c10a72 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -9,6 +9,7 @@ nobase_include_HEADERS = \ osmocom/core/bitvec.h \ osmocom/core/bitcomp.h \ osmocom/core/conv.h \ + osmocom/core/conv_gen.h \ osmocom/core/crc16.h \ osmocom/core/crc16gen.h \ osmocom/core/crc32gen.h \ diff --git a/include/osmocom/core/conv.h b/include/osmocom/core/conv.h index e7f6bd6..42807fa 100644 --- a/include/osmocom/core/conv.h +++ b/include/osmocom/core/conv.h @@ -139,5 +139,5 @@ int osmo_conv_decode_get_output(struct osmo_conv_decoder *decoder, int osmo_conv_decode(const struct osmo_conv_code *code, const sbit_t *input, ubit_t *output); - +#include /*! @} */ diff --git a/include/osmocom/core/conv_gen.h b/include/osmocom/core/conv_gen.h new file mode 100644 index 0000000..e4f1b65 --- /dev/null +++ b/include/osmocom/core/conv_gen.h @@ -0,0 +1,46 @@ +/* + * conv_gen.h + * + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +extern const uint8_t osmo_conv_gsm0503_xcch_output[][2]; +extern const uint8_t osmo_conv_gsm0503_xcch_state[][2]; + +/*! \file conv_gen.h + * Osmocom convolutional encoder/decoder for xCCH channels, see 3GPP TS 05.03 + */ + +/*! \brief structure describing convolutional code xCCH + * + * Non-recursive code, flushed, not punctured code. + * Generator polynomials: + * G0 = 1 + D3 + D4 + * G1 = 1 + D + D3 + D4 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_xcch = { + .N = 2, + .K = 5, + .len = 224, + .term = CONV_TERM_FLUSH, + .next_output = osmo_conv_gsm0503_xcch_output, + .next_state = osmo_conv_gsm0503_xcch_state, +}; diff --git a/src/Makefile.am b/src/Makefile.am index 45a77e3..2555ff8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,14 +10,14 @@ lib_LTLIBRARIES = libosmocore.la libosmocore_la_LIBADD = $(BACKTRACE_LIB) $(TALLOC_LIBS) libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \ bitvec.c bitcomp.c statistics.c \ - write_queue.c utils.c socket.c \ + conv_xcch_gen.c write_queue.c utils.c socket.c \ logging.c logging_syslog.c rate_ctr.c \ gsmtap_util.c crc16.c panic.c backtrace.c \ conv.c application.c rbtree.c strrb.c \ loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c \ macaddr.c stat_item.c stats.c stats_statsd.c prim.c -BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c +BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c conv_xcch_gen.c if ENABLE_PLUGIN libosmocore_la_SOURCES += plugin.c diff --git a/src/conv_xcch_gen.c b/src/conv_xcch_gen.c new file mode 100644 index 0000000..b948e7b --- /dev/null +++ b/src/conv_xcch_gen.c @@ -0,0 +1,61 @@ +/* + * conv_xcch_gen.c + * + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +const uint8_t osmo_conv_gsm0503_xcch_output[][2] = { + { 0, 3 }, + { 3, 0 }, + { 3, 0 }, + { 0, 3 }, + { 0, 3 }, + { 3, 0 }, + { 3, 0 }, + { 0, 3 }, + { 1, 2 }, + { 2, 1 }, + { 2, 1 }, + { 1, 2 }, + { 1, 2 }, + { 2, 1 }, + { 2, 1 }, + { 1, 2 }, +}; + +const uint8_t osmo_conv_gsm0503_xcch_state[][2] = { + { 0, 8 }, + { 0, 8 }, + { 1, 9 }, + { 1, 9 }, + { 2, 10 }, + { 2, 10 }, + { 3, 11 }, + { 3, 11 }, + { 4, 12 }, + { 4, 12 }, + { 5, 13 }, + { 5, 13 }, + { 6, 14 }, + { 6, 14 }, + { 7, 15 }, + { 7, 15 }, +}; diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index de62f23..baebdbe 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -15,31 +15,6 @@ /* Test codes */ /* ------------------------------------------------------------------------ */ -/* GSM xCCH -> Non-recursive code, flushed, not punctured */ -static const uint8_t conv_gsm_xcch_next_output[][2] = { - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, -}; - -static const uint8_t conv_gsm_xcch_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, -}; - -static const struct osmo_conv_code conv_gsm_xcch = { - .N = 2, - .K = 5, - .len = 224, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, -}; - - /* GSM TCH/AFS 7.95 -> Recursive code, flushed, with puncturing */ static const uint8_t conv_gsm_tch_afs_7_95_next_output[][2] = { { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, @@ -227,8 +202,8 @@ static const struct osmo_conv_code conv_trunc = { .K = 5, .len = 224, .term = CONV_TERM_TRUNCATION, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, + .next_output = osmo_conv_gsm0503_xcch_output, + .next_state = osmo_conv_gsm0503_xcch_state, }; @@ -249,7 +224,7 @@ struct conv_test_vector { static const struct conv_test_vector tests[] = { { .name = "GSM xCCH (non-recursive, flushed, not punctured)", - .code = &conv_gsm_xcch, + .code = &osmo_conv_gsm0503_xcch, .in_len = 224, .out_len = 456, .has_vec = 1, -- 2.8.1 From nhofmeyr at sysmocom.de Wed Apr 6 12:20:26 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 6 Apr 2016 14:20:26 +0200 Subject: PLMN identity: 04.08 vs. RANAP Message-ID: <20160406122026.GE2470@dub6> Hi list, I've noted a subtle difference in specifications for BCD-coding MCC and MNC. I'll illustrate by encoding the two sets MCC 123, MNC 45 and MCC 123, MNC 456 In Figure 10.5.3/3GPP TS 04.08, we have both the third digits in the second byte, i.e. above are encoded as: 21 f3 54 and 21 63 54 respectively In 3GPP TS 25.413 in 9.2.3.55 PLMN Identity, I see a very similar definition for BCD coding, but it omits the detail to put the last MNC digit into the second byte. So, by omittance, it defines a different coding from 04.08: 21 f3 54 (same) but 21 43 65 respectively. This strikes me as pretty odd, and I wonder whether the spec author overlooked this detail. The definition in the RANAP spec is also squeezed into the rightmost column of the IE description table, so it looks like a "quick hack". I would like to replace the ranap_parse_lai() implementation with gsm48_mcc_mnc_from_bcd() to have less code duplication, and hence I hit this weird difference. Does anyone have an idea how I should handle this? We could test it by setting our hNodeB to a three digit MNC and see whether it encodes it like 04.08 in the RANAP coding... Daniel, could you check this out in wireshark while you're busy testing? ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Wed Apr 6 12:52:16 2016 From: laforge at gnumonks.org (Harald Welte) Date: Wed, 6 Apr 2016 14:52:16 +0200 Subject: OsmoDevCon 2016 update Message-ID: <20160406125216.GB11349@nataraja> Dear attendees of OsmoDevCon 2016, below are some updates regarding OsmoDevCon 2016 = Lunch Catering = OsmoDevCon lunch catering has been finalized by now. I wanted to try some change by having (authentic) thai food, but unfortunately that didn't work out and we're back to our trusted old suppliers for all of the lunches. More details are available on http://projects.osmocom.org/projects/openbsc/wiki/OsmoDevCon2016 = Dinner Catering = In terms of dinner catering, we didn't plan/schedule anything yet. I know it was a request to have it and we introduced it (last year?) but I didn't have time to actively look for a sponsor for this in 2016, sorry. If you think it's important, I can try to get something organized for dinner too, but there's not much time left. It might be easier to simply go out in 2-3 groups, order pizza from the place down the road or even place a larger 'a la carte' order from another place. = Schedule / Talks = Thre's already a list of topics listed at the wiki, specifically: http://projects.osmocom.org/projects/openbsc/wiki/OsmoDevCon2016#TalksDiscussions I think we still have plenty of slots for talks, presentations, discussions, workshops, you name it. Each of you: Please take some time to think about a) topics that you would be able to contribute to the event by giving a talk or leading a discussion or workshop b) topics that you would like to hear about from somebody else Even if we do the actual scheduling ad-hoc at the event itself, it still is useful to have some advance notice about the topics, as the speaker(s) will need to prepare accordingly. = Attendance = If you have registered but will not attend, please let us know as we can still adjust the amount of food we get delivered, and we might offer your seat to somebody else. If you did not register but are an active contributor to the project(s) and would like to attend, let me know, too. I will let you know if somebody cancels their attendance. Looking forward to meeting all of you in Berlin soon. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From msuraev at sysmocom.de Wed Apr 6 13:54:59 2016 From: msuraev at sysmocom.de (Max) Date: Wed, 6 Apr 2016 15:54:59 +0200 Subject: [PATCH 1/2] Refactor mncc code In-Reply-To: References: <1458817545-2039-1-git-send-email-msuraev@sysmocom.de> Message-ID: <57051533.4050207@sysmocom.de> On 04/05/2016 10:47 PM, Holger Freyther wrote: > > -int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode) > +int gsm48_lchan_modify(struct gsm_lchan *lchan, enum gsm48_chan_mode lchan_mode) > { > - int rc; > - > - rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode); > - if (rc < 0) > - return rc; > - > - return rc; > + return gsm48_tx_chan_mode_modify(lchan, lchan_mode); > } > > hehe, split this into a separate patch. Yes, it is obvious it returns rc either way and let's assume we don't have a unsigned -> int kind of conversion here. > > Can we remove this wrapper altogether and just use the function directly? Also, no need to assume anything - both gsm48_tx_chan_mode_modify() and wrapper are returning int so there is no conversion. -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Wed Apr 6 14:04:55 2016 From: msuraev at sysmocom.de (Max) Date: Wed, 6 Apr 2016 16:04:55 +0200 Subject: [PATCH 2/2] Add extra debug output with channel mode and type In-Reply-To: <20160327084604.GR27418@nataraja> References: <1458817545-2039-1-git-send-email-msuraev@sysmocom.de> <1458817545-2039-2-git-send-email-msuraev@sysmocom.de> <20160327084604.GR27418@nataraja> Message-ID: <57051787.9030408@sysmocom.de> The necessary changes are now in libosmocore master. On 03/27/2016 10:46 AM, Harald Welte wrote: > Hi Max, > > On Thu, Mar 24, 2016 at 12:05:45PM +0100, msuraev at sysmocom.de wrote: >> This provides helpful information for debugging internal MNCC handler. > this patch depends on the export of gsm48_chan_mode_names, so it will > hav to wait for the resolution of the feedback on that part. -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Wed Apr 6 14:13:00 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 6 Apr 2016 16:13:00 +0200 Subject: [PATCH] Add ubit <-> sbit convertors Message-ID: <1459951980-6687-1-git-send-email-msuraev@sysmocom.de> From: Max Move functions for conversion between soft and unpacked bits to main library as they are generally useful. --- include/osmocom/core/bits.h | 3 +++ src/bits.c | 24 ++++++++++++++++++++++++ tests/conv/conv_test.c | 23 ++--------------------- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h index 46f0c8b..e082313 100644 --- a/include/osmocom/core/bits.h +++ b/include/osmocom/core/bits.h @@ -42,6 +42,9 @@ int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits); int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits); +void osmo_ubit2sbit(sbit_t *out, const ubit_t *in, unsigned int num_bits); +void osmo_sbit2ubit(ubit_t *out, const sbit_t *in, unsigned int num_bits); + int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs, const ubit_t *in, unsigned int in_ofs, unsigned int num_bits, int lsb_mode); diff --git a/src/bits.c b/src/bits.c index a0a9d9e..48314af 100644 --- a/src/bits.c +++ b/src/bits.c @@ -61,6 +61,30 @@ int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits) return outptr - out; } +/*! \brief convert unpacked bits to soft bits + * \param[out] out output buffer of soft bits + * \param[in] in input buffer of unpacked bits + * \param[in] num_bits number of bits + */ +void osmo_ubit2sbit(sbit_t *out, const ubit_t *in, unsigned int num_bits) +{ + unsigned int i; + for (i = 0; i < num_bits; i++) + out[i] = in[i] ? -127 : 127; +} + +/*! \brief convert soft bits to unpacked bits + * \param[out] out output buffer of unpacked bits + * \param[in] in input buffer of soft bits + * \param[in] num_bits number of bits + */ +void osmo_sbit2ubit(ubit_t *out, const sbit_t *in, unsigned int num_bits) +{ + unsigned int i; + for (i = 0; i < num_bits; i++) + out[i] = in[i] < 0; +} + /*! \brief convert packed bits to unpacked bits, return length in bytes * \param[out] out output buffer of unpacked bits * \param[in] in input buffer of packed bits diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index 182ae20..baebdbe 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -314,25 +314,6 @@ fill_random(ubit_t *b, int n) b[i] = random() & 1; } -static void -ubit_to_sbit(sbit_t *dst, ubit_t *src, int n) -{ - int i; - for (i=0; icode, bs, bu1); if (l != 0) { @@ -434,7 +415,7 @@ int main(int argc, char *argv[]) return -1; } - ubit_to_sbit(bs, bu1, l); + osmo_ubit2sbit(bs, bu1, l); l = osmo_conv_decode(tst->code, bs, bu1); if (l != 0) { -- 2.8.1 From dwillmann at sysmocom.de Wed Apr 6 15:18:54 2016 From: dwillmann at sysmocom.de (Daniel Willmann) Date: Wed, 06 Apr 2016 17:18:54 +0200 Subject: PLMN identity: 04.08 vs. RANAP In-Reply-To: <20160406122026.GE2470@dub6> (sfid-20160406_142151_888175_15275D01) References: <20160406122026.GE2470@dub6> (sfid-20160406_142151_888175_15275D01) Message-ID: <1459955934.2985.22.camel@sysmocom.de> Hi, On Wed, 2016-04-06 at 14:20 +0200, Neels Hofmeyr wrote: > Hi list, > > I've noted a subtle difference in specifications for BCD-coding MCC and MNC. > > I'll illustrate by encoding the two sets > MCC 123, MNC 45 > and > MCC 123, MNC 456 > > In Figure 10.5.3/3GPP TS 04.08, we have both the third digits in the second > byte, i.e. above are encoded as: > 21 f3 54 > and > 21 63 54 > respectively > In 3GPP TS 25.413 in 9.2.3.55 PLMN Identity, I see a very similar definition > for BCD coding, but it omits the detail to put the last MNC digit into the > second byte. So, by omittance, it defines a different coding from 04.08: > 21 f3 54 (same) > but > 21 43 65 > respectively. This is what the hnb does. A PLMNID of 901123 results in 09 11 32 being transmitted in HNBAP. PLMNID of 90123 corresponds to 09 f1 32 The RANAP fields for LAI and SAI are encoded the same. > This strikes me as pretty odd, and I wonder whether the spec author overlooked > this detail. The definition in the RANAP spec is also squeezed into the > rightmost column of the IE description table, so it looks like a "quick hack". Yet another fun quirk... > I would like to replace the ranap_parse_lai() implementation with > gsm48_mcc_mnc_from_bcd() to have less code duplication, and hence I hit this > weird difference. > > Does anyone have an idea how I should handle this? Since the coding differs I wouldn't try to merge the implementations. I'd think that it would obscure more than it helps. Regards Daniel -- - Daniel Willmann http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Wed Apr 6 15:20:05 2016 From: msuraev at sysmocom.de (Max) Date: Wed, 6 Apr 2016 17:20:05 +0200 Subject: [PATCH] Add optional copy_files attribute In-Reply-To: <9969441B-9173-4C4A-A168-9BA384556DC2@freyther.de> References: <1459430596-9066-1-git-send-email-msuraev@sysmocom.de> <9969441B-9173-4C4A-A168-9BA384556DC2@freyther.de> Message-ID: <57052925.5070108@sysmocom.de> On 03/31/2016 04:19 PM, Holger Freyther wrote: >> On 31 Mar 2016, at 15:23, msuraev at sysmocom.de wrote: >> >> From: Max >> >> This allows to specify additional files which shall be copied into >> temporary directory where tests are executed. > when we chatted I had something like this in make > > make_tmp_dir > copy_recursively(orig, tmp_dir) > run(tmp_dir/cfg_file) > > was your approach more simple? > Yes - instead of trying to re-create directory structure (which would make test runner unnecessary complex) I simply copy necessary additional configs explicitly. Using extension other than .cfg makes sure that they won't be copied (this one is recursive already btw) by config tester. -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Wed Apr 6 15:25:43 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 6 Apr 2016 17:25:43 +0200 Subject: [PATCH 1/2] NAT: move BSC config into separate file Message-ID: <1459956344-4870-1-git-send-email-msuraev@sysmocom.de> From: Max Introduce new configuration option bscs-config-file which includes BSC configuration from the given file. Both absolute and relative (to the main config file) paths are supported. Add 'show bscs-config' command to display current BSC configuration. Note: it is still possible to have BSC configuration in the main file (provided proper index number is used) and in runtime but BSC configuration is no longer saved automatically. The management of included configuration file is left to external tools. Update configuration examples. Fixes: OS#1669 Sponsored-by: On-Waves ehf --- openbsc/doc/examples/osmo-bsc_nat/bscs.config | 13 ++++++ openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg | 8 +--- openbsc/include/openbsc/bsc_nat.h | 5 +++ openbsc/osmoappdesc.py | 3 ++ openbsc/src/osmo-bsc_nat/bsc_nat.c | 5 ++- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 49 ++++++++++++++++++++-- 6 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 openbsc/doc/examples/osmo-bsc_nat/bscs.config diff --git a/openbsc/doc/examples/osmo-bsc_nat/bscs.config b/openbsc/doc/examples/osmo-bsc_nat/bscs.config new file mode 100644 index 0000000..176debe --- /dev/null +++ b/openbsc/doc/examples/osmo-bsc_nat/bscs.config @@ -0,0 +1,13 @@ +nat + bsc 0 + token lol + location_area_code 1234 + description bsc + max-endpoints 32 + paging forbidden 0 + bsc 1 + token wat + location_area_code 5678 + description bsc + max-endpoints 32 + paging forbidden 0 diff --git a/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg b/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg index 737d104..2e00bc2 100644 --- a/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg +++ b/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg @@ -62,11 +62,5 @@ nat timeout ping 20 timeout pong 5 ip-dscp 0 + bscs-config-file bscs.config access-list bla imsi-allow ^11$ - - bsc 0 - token bla - location_area_code 1234 - description bsc - max-endpoints 32 - paging forbidden 0 diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 309adb1..7ede1fb 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -264,6 +264,11 @@ struct bsc_nat { struct bsc_endpoint *bsc_endpoints; + /* path to file with BSC config */ + char *include_file; + char *include_base; + char *resolved_path; + /* filter */ char *acc_lst_name; diff --git a/openbsc/osmoappdesc.py b/openbsc/osmoappdesc.py index 76f03fc..d10ecae 100644 --- a/openbsc/osmoappdesc.py +++ b/openbsc/osmoappdesc.py @@ -26,6 +26,9 @@ nitb_e1_configs = [ "doc/examples/osmo-nitb/rbs2308/openbsc.cfg" ] +copy_files = [ + "doc/examples/osmo-bsc_nat/bscs.config" +] app_configs = { "osmo-bsc": ["doc/examples/osmo-bsc/osmo-bsc.cfg"], diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index cacb919..f588e4b 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -34,6 +34,7 @@ #include #include #include +#include #define _GNU_SOURCE #include @@ -1626,6 +1627,8 @@ int main(int argc, char **argv) local_addr.s_addr = INADDR_ANY; handle_options(argc, argv); + nat->include_base = dirname(talloc_strdup(tall_bsc_ctx, config_file)); + rate_ctr_init(tall_bsc_ctx); osmo_stats_init(tall_bsc_ctx); @@ -1651,7 +1654,7 @@ int main(int argc, char **argv) /* seed the PRNG */ srand(time(NULL)); - + LOGP(DNAT, LOGL_NOTICE, "BSCs configured from %s\n", nat->resolved_path); /* * Setup the MGCP code.. diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index cd8293c..b9a8d31 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -96,6 +96,8 @@ static int config_write_nat(struct vty *vty) vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE); vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE); vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE); + if (_nat->include_file) + vty_out(vty, " bscs-config-file %s%s", _nat->include_file, VTY_NEWLINE); if (_nat->token) vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE); vty_out(vty, " ip-dscp %d%s", _nat->bsc_ip_dscp, VTY_NEWLINE); @@ -181,6 +183,14 @@ static int config_write_bsc(struct vty *vty) return CMD_SUCCESS; } +DEFUN(show_bscs, show_bscs_cmd, "show bscs-config", + SHOW_STR "Show configured BSCs\n" + "Both from included file and vty\n") +{ + vty_out(vty, "BSCs configuration loaded from %s:%s", _nat->resolved_path, + VTY_NEWLINE); + return config_write_bsc(vty); +} DEFUN(show_sccp, show_sccp_cmd, "show sccp connections", SHOW_STR "Display information about SCCP\n" @@ -487,6 +497,34 @@ DEFUN(cfg_nat_acc_lst_name, return CMD_SUCCESS; } +DEFUN(cfg_nat_include, + cfg_nat_include_cmd, + "bscs-config-file NAME", + "Set the filename of the BSC configuration to include.\n" + "The filename to be included.") +{ + char *path; + int rc; + + if ('/' == argv[0][0]) + bsc_replace_string(_nat, &_nat->resolved_path, argv[0]); + else { + path = talloc_asprintf(_nat, "%s/%s", _nat->include_base, + argv[0]); + bsc_replace_string(_nat, &_nat->resolved_path, path); + talloc_free(path); + } + + rc = vty_read_config_file(_nat->resolved_path, NULL); + if (rc < 0) { + vty_out(vty, "Failed to parse the config file %s: %s%s", + _nat->resolved_path, strerror(-rc), VTY_NEWLINE); + return CMD_WARNING; + } + bsc_replace_string(_nat, &_nat->include_file, argv[0]); + return CMD_SUCCESS; +} + DEFUN(cfg_nat_no_acc_lst_name, cfg_nat_no_acc_lst_name_cmd, "no access-list-name", @@ -863,8 +901,11 @@ DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>", /* verify that the LACs are unique */ llist_for_each_entry(tmp, &_nat->bsc_configs, entry) { if (bsc_config_handles_lac(tmp, lac)) { - vty_out(vty, "%% LAC %d is already used.%s", lac, VTY_NEWLINE); - return CMD_ERR_INCOMPLETE; + if (tmp->nr != conf->nr) { + vty_out(vty, "%% LAC %d is already used.%s", lac, + VTY_NEWLINE); + return CMD_ERR_INCOMPLETE; + } } } @@ -1176,6 +1217,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element_ve(&show_msc_cmd); install_element_ve(&test_regex_cmd); install_element_ve(&show_bsc_mgcp_cmd); + install_element_ve(&show_bscs_cmd); install_element_ve(&show_bar_lst_cmd); install_element_ve(&show_prefix_tree_cmd); install_element_ve(&show_ussd_connection_cmd); @@ -1197,6 +1239,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd); install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd); install_element(NAT_NODE, &cfg_nat_no_acc_lst_name_cmd); + install_element(NAT_NODE, &cfg_nat_include_cmd); install_element(NAT_NODE, &cfg_nat_imsi_black_list_fn_cmd); install_element(NAT_NODE, &cfg_nat_no_imsi_black_list_fn_cmd); install_element(NAT_NODE, &cfg_nat_ussd_lst_name_cmd); @@ -1233,7 +1276,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) /* BSC subgroups */ install_element(NAT_NODE, &cfg_bsc_cmd); - install_node(&bsc_node, config_write_bsc); + install_node(&bsc_node, NULL); vty_install_default(NAT_BSC_NODE); install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_auth_key_cmd); -- 2.8.1 From msuraev at sysmocom.de Wed Apr 6 15:25:44 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 6 Apr 2016 17:25:44 +0200 Subject: [PATCH 2/2] NAT: vty command to display number of BSCs In-Reply-To: <1459956344-4870-1-git-send-email-msuraev@sysmocom.de> References: <1459956344-4870-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1459956344-4870-2-git-send-email-msuraev@sysmocom.de> From: Max Add command 'show nat num-bscs-configured' to display number of configured BSCs. Sponsored-by: On-Waves ehf --- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index b9a8d31..26b0fd6 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -214,6 +214,14 @@ DEFUN(show_sccp, show_sccp_cmd, "show sccp connections", return CMD_SUCCESS; } +DEFUN(show_nat_bsc, show_nat_bsc_cmd, "show nat num-bscs-configured", + SHOW_STR "Display NAT configuration details\n" + "BSCs-related\n") +{ + vty_out(vty, "%d BSCs configured%s", _nat->num_bsc, VTY_NEWLINE); + return CMD_SUCCESS; +} + DEFUN(show_bsc, show_bsc_cmd, "show bsc connections", SHOW_STR BSC_STR "All active connections\n") @@ -1210,6 +1218,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) /* show commands */ install_element_ve(&show_sccp_cmd); install_element_ve(&show_bsc_cmd); + install_element_ve(&show_nat_bsc_cmd); install_element_ve(&show_bsc_cfg_cmd); install_element_ve(&show_stats_cmd); install_element_ve(&show_stats_lac_cmd); -- 2.8.1 From nhofmeyr at sysmocom.de Wed Apr 6 15:40:17 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 6 Apr 2016 17:40:17 +0200 Subject: Patches In-Reply-To: <20160406080546.GJ11135@nataraja> References: <20160406080546.GJ11135@nataraja> Message-ID: <20160406154017.GF2470@dub6> On Wed, Apr 06, 2016 at 10:05:46AM +0200, Harald Welte wrote: > Hi Matthew, > > thanks for your patches and your interest in contributing. > > On Tue, Apr 05, 2016 at 11:18:51PM +0200, Matthew Daiter wrote: > > - if (!msc->msc_con->is_authenticated) > > - continue; > > - if (!is_emerg && msc->type != MSC_CON_TYPE_NORMAL) > > - continue; > > - if (is_emerg && !msc->allow_emerg) > > + if ((!msc->msc_con->is_authenticated) || > > + (!is_emerg && msc->type != MSC_CON_TYPE_NORMAL) || > > + (is_emerg && !msc->allow_emerg)) > > continue; > > I thinkt it's a matter of taste. To me, the existing code actually is > more obvious and easier to read I also prefer the separate if()s for instant clarity. > > - if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) { > > + if (memcmp(&lai, &lu->lai, sizeof(lai))) { > > again here, it is a question of taste. The '!= 0' proabably serves as > a reminder at the strange behavior of memcmp() returning 0 in case of > success. I always do the != 0 with strcmp :) Though I wouldn't bother to commit a patch to change it, I agree with != 0. Thanks for joining us, Matthew! Do stay around and help us out :) ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Wed Apr 6 15:46:49 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 6 Apr 2016 17:46:49 +0200 Subject: PLMN identity: 04.08 vs. RANAP In-Reply-To: <1459955934.2985.22.camel@sysmocom.de> References: <20160406122026.GE2470@dub6> <1459955934.2985.22.camel@sysmocom.de> Message-ID: <20160406154649.GG2470@dub6> On Wed, Apr 06, 2016 at 05:18:54PM +0200, Daniel Willmann wrote: > > In 3GPP TS 25.413 in 9.2.3.55 PLMN Identity, I see a very similar definition > > for BCD coding, but it omits the detail to put the last MNC digit into the > > second byte. So, by omittance, it defines a different coding from 04.08: > > 21 f3 54 (same) > > but > > 21 43 65 > > respectively. > > This is what the hnb does. A PLMNID of 901123 results in > 09 11 32 being transmitted in HNBAP. > PLMNID of 90123 corresponds to 09 f1 32 > > The RANAP fields for LAI and SAI are encoded the same. [...] > Since the coding differs I wouldn't try to merge the implementations. > I'd think that it would obscure more than it helps. Excellent, thanks for testing it!! Quite curious result though. I agree to not use gsm48_mcc_mnc_from_bcd() directly, but maybe ranap_parse_lai() can reuse some more general bcd code... ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From msuraev at sysmocom.de Wed Apr 6 15:52:39 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 6 Apr 2016 17:52:39 +0200 Subject: [PATCH 2/2] Factor out ipaccess send routines In-Reply-To: <1459957959-15333-1-git-send-email-msuraev@sysmocom.de> References: <1459957959-15333-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1459957959-15333-2-git-send-email-msuraev@sysmocom.de> From: Max Introduce several python functions for sending various ipaccess protocol messages. Convert existing test code to use them. --- openbsc/tests/vty_test_runner.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 8db0825..1c4ecb4 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -700,13 +700,13 @@ class TestVTYNAT(TestVTYGenericBSC): self.assertEqual(data, "\x00\x01\xfe\x04") print "Going to send ID_RESP response" - res = ussdSocket.send("\x00\x07\xfe\x05\x00\x04\x01\x6b\x65\x79") + res = ipa_send_resp(ussdSocket, "\x6b\x65\x79") self.assertEqual(res, 10) # initiating PING/PONG cycle to know, that the ID_RESP message has been processed print "Going to send PING request" - res = ussdSocket.send("\x00\x01\xfe\x00") + res = ipa_send_ping(ussdSocket) self.assertEqual(res, 4) print "Expecting PONG response" @@ -971,6 +971,31 @@ def add_nat_test(suite, workdir): test = unittest.TestLoader().loadTestsFromTestCase(TestVTYNAT) suite.addTest(test) +def ipa_send_pong(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: PONG!" + return x.send("\x00\x01\xfe\x01") + +def ipa_send_ping(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: PING?" + return x.send("\x00\x01\xfe\x00") + +def ipa_send_ack(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: IPA ID ACK" + return x.send("\x00\x01\xfe\x06") + +def ipa_send_reset(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: RESET" + return x.send("\x00\x12\xfd\x09\x00\x03\x05\x07\x02\x42\xfe\x02\x42\xfe\x06\x00\x04\x30\x04\x01\x20") + +def ipa_send_resp(x, tk, verbose = False): + if (verbose): + print "\tBSC -> NAT: IPA ID RESP" + return x.send("\x00\x07\xfe\x05\x00\x04\x01" + tk) + 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") -- 2.8.1 From msuraev at sysmocom.de Wed Apr 6 15:52:38 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 6 Apr 2016 17:52:38 +0200 Subject: [PATCH 1/2] NAT: extend debug output for ipaccess errors Message-ID: <1459957959-15333-1-git-send-email-msuraev@sysmocom.de> From: Max --- openbsc/src/osmo-bsc_nat/bsc_nat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index f588e4b..f433324 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -1321,8 +1321,8 @@ static int ipaccess_bsc_read_cb(struct osmo_fd *bfd) bsc->cfg ? bsc->cfg->nr : -1); else LOGP(DNAT, LOGL_ERROR, - "Stream error on BSC Nr: %d. Failed to parse ip access message: %d\n", - bsc->cfg ? bsc->cfg->nr : -1, ret); + "Stream error on BSC Nr: %d. Failed to parse ip access message: %d (%s)\n", + bsc->cfg ? bsc->cfg->nr : -1, ret, strerror(-ret)); bsc_close_connection(bsc); return -1; -- 2.8.1 From dwillmann at sysmocom.de Wed Apr 6 16:17:23 2016 From: dwillmann at sysmocom.de (Daniel Willmann) Date: Wed, 06 Apr 2016 18:17:23 +0200 Subject: PLMN identity: 04.08 vs. RANAP In-Reply-To: <20160406154649.GG2470@dub6> (sfid-20160406_174813_295040_214F8A8C) References: <20160406122026.GE2470@dub6> <1459955934.2985.22.camel@sysmocom.de> <20160406154649.GG2470@dub6> (sfid-20160406_174813_295040_214F8A8C) Message-ID: <1459959443.2985.25.camel@sysmocom.de> On Wed, 2016-04-06 at 17:46 +0200, Neels Hofmeyr wrote: > On Wed, Apr 06, 2016 at 05:18:54PM +0200, Daniel Willmann wrote: > > > In 3GPP TS 25.413 in 9.2.3.55 PLMN Identity, I see a very similar definition > > > for BCD coding, but it omits the detail to put the last MNC digit into the > > > second byte. So, by omittance, it defines a different coding from 04.08: > > > 21 f3 54 (same) > > > but > > > 21 43 65 > > > respectively. > > > > This is what the hnb does. A PLMNID of 901123 results in > > 09 11 32 being transmitted in HNBAP. > > PLMNID of 90123 corresponds to 09 f1 32 > > > > The RANAP fields for LAI and SAI are encoded the same. > [...] > > Since the coding differs I wouldn't try to merge the implementations. > > I'd think that it would obscure more than it helps. > > Excellent, thanks for testing it!! Quite curious result though. > I agree to not use gsm48_mcc_mnc_from_bcd() directly, but maybe > ranap_parse_lai() can reuse some more general bcd code... Yeah, that could help. The BCD descrambling is needed for more than those two (MSISDN, IMSI, ...). Fun fact: The Dell phone displays the network correctly as 901123 - the Sony Ericsson K800i incorrectly displays it as 901231. :-) Daniel -- - Daniel Willmann http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Wed Apr 6 16:20:46 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 6 Apr 2016 18:20:46 +0200 Subject: [PATCH] NAT: allow allocating BSC in arbitrary order Message-ID: <1459959646-27455-1-git-send-email-msuraev@sysmocom.de> From: Max Check for existing BSC before allocating new one. Track number of remaining BSCs on deallocation. Explicitly use BSC number in allocation function. --- openbsc/include/openbsc/bsc_nat.h | 3 ++- openbsc/src/osmo-bsc_nat/bsc_nat_utils.c | 9 +++++++-- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 14 ++++---------- openbsc/tests/bsc-nat/bsc_nat_test.c | 14 +++++++------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 7ede1fb..5ccc02e 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -325,7 +325,8 @@ struct bsc_nat_ussd_con { }; /* create and init the structures */ -struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token); +struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, + unsigned int number); struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num); struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len); void bsc_config_free(struct bsc_config *); diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c index cc7d442..1bf3266 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c @@ -155,14 +155,15 @@ struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat) return con; } -struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token) +struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, + unsigned int number) { struct bsc_config *conf = talloc_zero(nat, struct bsc_config); if (!conf) return NULL; conf->token = talloc_strdup(conf, token); - conf->nr = nat->num_bsc; + conf->nr = number; conf->nat = nat; conf->max_endpoints = 32; conf->paging_group = PAGIN_GROUP_UNASSIGNED; @@ -205,6 +206,10 @@ void bsc_config_free(struct bsc_config *cfg) llist_del(&cfg->entry); rate_ctr_group_free(cfg->stats.ctrg); talloc_free(cfg); + cfg->nat->num_bsc--; + if (cfg->nat->num_bsc < 0) + LOGP(DNAT, LOGL_ERROR, "Internal error while deallocating BSC " + "config: negative BSC index!\n"); } static void _add_lac(void *ctx, struct llist_head *list, int _lac) diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 26b0fd6..b7b49e6 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -837,17 +837,11 @@ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "BSC configuration\n" "Identifier of the BSC\n") { int bsc_nr = atoi(argv[0]); - struct bsc_config *bsc; + struct bsc_config *bsc = bsc_config_num(_nat, bsc_nr); - if (bsc_nr > _nat->num_bsc) { - vty_out(vty, "%% The next unused BSC number is %u%s", - _nat->num_bsc, VTY_NEWLINE); - return CMD_WARNING; - } else if (bsc_nr == _nat->num_bsc) { - /* allocate a new one */ - bsc = bsc_config_alloc(_nat, "unknown"); - } else - bsc = bsc_config_num(_nat, bsc_nr); + /* allocate a new one */ + if (!bsc) + bsc = bsc_config_alloc(_nat, "unknown", bsc_nr); if (!bsc) return CMD_WARNING; diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c index a4b313c..a405763 100644 --- a/openbsc/tests/bsc-nat/bsc_nat_test.c +++ b/openbsc/tests/bsc-nat/bsc_nat_test.c @@ -316,7 +316,7 @@ static void test_contrack() printf("Testing connection tracking.\n"); nat = bsc_nat_alloc(); con = bsc_connection_alloc(nat); - con->cfg = bsc_config_alloc(nat, "foo"); + con->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(con->cfg, 23); bsc_config_add_lac(con->cfg, 49); bsc_config_add_lac(con->cfg, 42); @@ -434,7 +434,7 @@ static void test_paging(void) nat = bsc_nat_alloc(); con = bsc_connection_alloc(nat); - cfg = bsc_config_alloc(nat, "unknown"); + cfg = bsc_config_alloc(nat, "unknown", 0); con->cfg = cfg; bsc_config_add_lac(cfg, 23); con->authenticated = 1; @@ -476,7 +476,7 @@ static void test_mgcp_allocations(void) nat->mgcp_cfg->trunk.number_endpoints = 64; bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc->cfg->max_endpoints = 60; bsc_config_add_lac(bsc->cfg, 2323); bsc->last_endpoint = 0x22; @@ -522,7 +522,7 @@ static void test_mgcp_ass_tracking(void) mgcp_endpoints_allocate(&nat->mgcp_cfg->trunk); bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 2323); bsc->last_endpoint = 0x1e; con.bsc = bsc; @@ -874,7 +874,7 @@ static void test_cr_filter() struct bsc_nat *nat = bsc_nat_alloc(); struct bsc_connection *bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 1234); bsc->cfg->acc_lst_name = "bsc"; nat->acc_lst_name = "nat"; @@ -953,7 +953,7 @@ static void test_dt_filter() struct bsc_connection *bsc = bsc_connection_alloc(nat); struct nat_sccp_connection *con = talloc_zero(0, struct nat_sccp_connection); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 23); con->bsc = bsc; @@ -1525,7 +1525,7 @@ static void test_nat_extract_lac() /* initialize the testcase */ nat = bsc_nat_alloc(); bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); memset(&con, 0, sizeof(con)); con.bsc = bsc; -- 2.8.1 From nhofmeyr at sysmocom.de Wed Apr 6 16:34:05 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 6 Apr 2016 18:34:05 +0200 Subject: OsmoDevCon 2016 update In-Reply-To: <20160406125216.GB11349@nataraja> References: <20160406125216.GB11349@nataraja> Message-ID: <20160406163405.GI2470@dub6> On Wed, Apr 06, 2016 at 02:52:16PM +0200, Harald Welte wrote: > = Dinner Catering = > > In terms of dinner catering, we didn't plan/schedule anything yet. I'd recommend Gasthaus Figl [1] in Urbanstr 47 for one evening, where there's outstanding (!!) pizza as well as quite an interesting ancient Kegelbahn [2] in the basement we might be able to book for an hour after diner. Even without a sponsor, I'd book a table for us "on own accord". I'd go for thursday since I expect a higher probability of having room for as many guests. Who would be interested in coming along on thursday? [1] https://en.wikipedia.org/wiki/Kegeln [2] http://gasthaus-figl.de/ ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Wed Apr 6 17:11:39 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 6 Apr 2016 19:11:39 +0200 Subject: osmo-iuh decoding of MNC fixed Message-ID: <20160406171139.GJ2470@dub6> I've just pushed a fix of the BCD decoding for the MNC part of the RANAP PLMN-Id to master: osmo-iuh.git d8013d1f8caf1c38c9b4191f0bbb411f6a4ff9d6 (along with a few other commits) BTW, my apologies for the unrelated and unnecessary cosmetic change in @@ -93,7 +98,8 @@ void test_asn1_helpers(void). I've recently been pushing to osmo-iuh without posting for reviews, since the code is in flux and not in production use yet. Let me know if I should post patches instead. ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From tom at tsou.cc Wed Apr 6 17:34:45 2016 From: tom at tsou.cc (Tom Tsou) Date: Wed, 6 Apr 2016 10:34:45 -0700 Subject: Lack of maintenance for osmo-bts-trx In-Reply-To: <20160406075911.GI11135@nataraja> References: <20160406075911.GI11135@nataraja> Message-ID: On Wed, Apr 6, 2016 at 12:59 AM, Harald Welte wrote: > Can you or somebody else interested in getting this resolved provide a > full bug report, including > * debug log output on OsmoNITB side for for the rsl and nm > * debug log output on OsmoBTS side for oml / transceiver interface or > anything else related > * pcap file of A-bis traffic between OsmoBTS and OsmoNITB, as well as > the control commands between osmo-bts-trx and osmo-trx Yes. I can generate the traces at some point this week. > The above is what to me seems like the "obvious" way to report a bug in > order for other developers on this list to try to figure out what is > causing the problem. Maybe it's not as obvious to others and we should > put together some guidelines in the wiki on this? I think wiki guidelines on bug reporting would be quite valuable. The range of users for Osmocom and OpenBTS is extremely wide - especially with the latter. For many users and potential users, reporting bugs in the manner suggested above is far from obvious. -TT From laforge at gnumonks.org Wed Apr 6 17:27:09 2016 From: laforge at gnumonks.org (Harald Welte) Date: Wed, 6 Apr 2016 19:27:09 +0200 Subject: OsmoDevCon 2016 update In-Reply-To: <20160406163405.GI2470@dub6> References: <20160406125216.GB11349@nataraja> <20160406163405.GI2470@dub6> Message-ID: <20160406172709.GC8524@nataraja> Hi Neels, On Wed, Apr 06, 2016 at 06:34:05PM +0200, Neels Hofmeyr wrote: > I'd recommend Gasthaus Figl [1] in Urbanstr 47 for one evening, where there's > outstanding (!!) pizza as well as quite an interesting ancient Kegelbahn [2] in > the basement we might be able to book for an hour after diner. generally peple seemed concerned with not spending too much time going to the other end of town (a bit of an exaggeration, but still...) and rather prefer somethign quick in the vicinity of the venue. But that's just my observation from past events, of course that might have been a wrong impression, and of course this year people could be in a different mood. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From holger at freyther.de Wed Apr 6 19:03:18 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 6 Apr 2016 21:03:18 +0200 Subject: [PATCH] Add optional copy_files attribute In-Reply-To: <57052925.5070108@sysmocom.de> References: <1459430596-9066-1-git-send-email-msuraev@sysmocom.de> <9969441B-9173-4C4A-A168-9BA384556DC2@freyther.de> <57052925.5070108@sysmocom.de> Message-ID: <32841AE3-5084-487B-B91F-9E2D7B972154@freyther.de> > On 06 Apr 2016, at 17:20, Max wrote: > > >> was your approach more simple? >> > Yes - instead of trying to re-create directory structure (which would > make test runner unnecessary complex) I simply copy necessary additional > configs explicitly. Using extension other than .cfg makes sure that they > won't be copied (this one is recursive already btw) by config tester. yes, but the code seems to be more involved than: shutil.copytree Can't we simplify the code by using this routine instead of having an extra list of files to copy? From holger at freyther.de Wed Apr 6 19:07:16 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 6 Apr 2016 21:07:16 +0200 Subject: [PATCH 1/2] Refactor mncc code In-Reply-To: <57051533.4050207@sysmocom.de> References: <1458817545-2039-1-git-send-email-msuraev@sysmocom.de> <57051533.4050207@sysmocom.de> Message-ID: > On 06 Apr 2016, at 15:54, Max wrote: > > > Can we remove this wrapper altogether and just use the function directly? > Also, no need to assume anything - both gsm48_tx_chan_mode_modify() and > wrapper are returning int so there is no conversion. we could, but which name to pick? Before 2009 there was a difference between as we called an ipaccess function in one but not the other. From holger at freyther.de Wed Apr 6 19:09:50 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 6 Apr 2016 21:09:50 +0200 Subject: [PATCH 3/3] mgcp: Remove the old MGCP based transcoding interface In-Reply-To: <20160406101945.GA2470@dub6> References: <1457458520-34314-1-git-send-email-holger@freyther.de> <1457458520-34314-3-git-send-email-holger@freyther.de> <20160406101945.GA2470@dub6> Message-ID: <8E7A15E5-6D62-413C-8723-7E986CE6D8BB@freyther.de> > On 06 Apr 2016, at 12:19, Neels Hofmeyr wrote: > > On Tue, Mar 08, 2016 at 06:35:20PM +0100, Holger Hans Peter Freyther wrote: >> --- a/openbsc/src/libmgcp/mgcp_network.c >> +++ b/openbsc/src/libmgcp/mgcp_network.c > [...] >> @@ -688,7 +661,6 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what) >> >> switch(endp->type) { > It could be a good idea to add 'default:' cases to above switch statements? > Now that we're removing some cases, would be good to catch callers still > passing one of the legacy cases (for whatever weird reasons)... I believe in tools. typeof(endp->type) == enum mgcp_type. So if any value of that enum is not handled, the compiler should (and did) warn. holger From holger at freyther.de Wed Apr 6 19:26:57 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 6 Apr 2016 21:26:57 +0200 Subject: iuh: Coverity build breakage because of old sctp Message-ID: <55242E3B-94E9-4864-A201-2F18CA199D01@freyther.de> Hi, sua.c: In function 'rx_inact_tmr_cb': sua.c:288: warning: unused variable 'conn' sua.c: In function 'sua_rx_coref': sua.c:908: warning: unused variable 'cause' sua.c: In function 'sua_rx_codt': sua.c:1059: warning: unused variable 'cur' sua.c: In function 'sua_srv_conn_cb': sua.c:1266: error: 'SCTP_SENDER_DRY_EVENT' undeclared (first use in this function) sua.c:1266: error: (Each undeclared identifier is reported only once sua.c:1266: error: for each function it appears in.) sua.c: In function 'sua_cli_read_cb': sua.c:1451: error: 'SCTP_SENDER_DRY_EVENT' undeclared (first use in this function) can we make the SCTP_SENDER_DRY_EVENT optional or is a strict requirement? If it is strict then maybe we can check for this in autoconf? holger From holger at freyther.de Wed Apr 6 19:38:44 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 6 Apr 2016 21:38:44 +0200 Subject: [PATCH] Add vty command to explicitly reset given BVCI In-Reply-To: <1459453226-8966-1-git-send-email-suraev@alumni.ntnu.no> References: <1459453226-8966-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: > On 31 Mar 2016, at 21:40, suraev at alumni.ntnu.no wrote: > argh.. this breaks the build Documentation error (missing docs): > +DEFUN(bvc_reset, bvc_reset_cmd, > + "bssgp bvc nsei <0-65535> bvci <0-65535> reset", > + "Initiate BVC RESET procedure for a given NSEI and BVCI\n") > +{ each parameter needs to be documented. Please send a fix for this tomorrow morning. holger From holger at freyther.de Wed Apr 6 20:44:52 2016 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Wed, 6 Apr 2016 22:44:52 +0200 Subject: [PATCH] ctrl: Extend ctrl command to optionally handle alg+ki Message-ID: <1459975492-74488-1-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther Extend the existing ctrl command to be able to specify the algorithm and Ki. In contrast to the VTY no size check is done. Together with the VTY this code only supports a small part of what is supported by libosmocore. The algorithm and ki are considered optional but if a valid and non none algorithm is passed, a KI must be passed as well. Extend the test coverage by passing the potential values. It is not verified that the KI/algorithm is stored. --- openbsc/src/libmsc/ctrl_commands.c | 59 ++++++++++++++++++++++++++++++++++++-- openbsc/tests/ctrl_test_runner.py | 27 +++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/openbsc/src/libmsc/ctrl_commands.c b/openbsc/src/libmsc/ctrl_commands.c index e48c6a3..566240c 100644 --- a/openbsc/src/libmsc/ctrl_commands.c +++ b/openbsc/src/libmsc/ctrl_commands.c @@ -24,9 +24,25 @@ #include #include +static bool alg_supported(const char *alg) +{ + /* + * TODO: share this with the vty_interface and extend to all + * algorithms supported by libosmocore now. Make it table based + * as well. + */ + if (strcasecmp(alg, "none") == 0) + return true; + if (strcasecmp(alg, "xor") == 0) + return true; + if (strcasecmp(alg, "comp128v1") == 0) + return true; + return false; +} + static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, void *d) { - char *tmp, *imsi, *msisdn, *saveptr = NULL; + char *tmp, *imsi, *msisdn, *alg, *ki, *saveptr = NULL; int rc = 0; tmp = talloc_strdup(cmd, value); @@ -35,6 +51,8 @@ static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, voi imsi = strtok_r(tmp, ",", &saveptr); msisdn = strtok_r(NULL, ",", &saveptr); + alg = strtok_r(NULL, ",", &saveptr); + ki = strtok_r(NULL, ",", &saveptr); if (!imsi || !msisdn) rc = 1; @@ -42,6 +60,12 @@ static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, voi rc = 1; else if (strlen(msisdn) >= GSM_EXTENSION_LENGTH) rc = 1; + else if (alg) { + if (!alg_supported(alg)) + rc = 1; + else if (strcasecmp(alg, "none") != 0 && !ki) + rc = 1; + } talloc_free(tmp); return rc; @@ -56,7 +80,7 @@ static int get_subscriber_modify(struct ctrl_cmd *cmd, void *data) static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data) { struct gsm_network *net = cmd->node; - char *tmp, *imsi, *msisdn, *saveptr = NULL; + char *tmp, *imsi, *msisdn, *alg, *ki, *saveptr = NULL; struct gsm_subscriber* subscr; int rc; @@ -66,6 +90,8 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data) imsi = strtok_r(tmp, ",", &saveptr); msisdn = strtok_r(NULL, ",", &saveptr); + alg = strtok_r(NULL, ",", &saveptr); + ki = strtok_r(NULL, ",", &saveptr); subscr = subscr_get_by_imsi(net->subscr_group, imsi); if (!subscr) @@ -80,6 +106,35 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data) /* put it back to the db */ rc = db_sync_subscriber(subscr); db_subscriber_update(subscr); + + /* handle optional ciphering */ + if (!alg || strcasecmp(alg, "none") == 0) + db_sync_authinfo_for_subscr(NULL, subscr); + else { + struct gsm_auth_info ainfo = { 0, }; + /* the verify should make sure that this is okay */ + OSMO_ASSERT(alg); + OSMO_ASSERT(ki); + + if (strcasecmp(alg, "xor") == 0) + ainfo.auth_algo = AUTH_ALGO_XOR; + else if (strcasecmp(alg, "comp128v1") == 0) + ainfo.auth_algo = AUTH_ALGO_COMP128v1; + + rc = osmo_hexparse(ki, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki)); + if (rc < 0) { + subscr_put(subscr); + talloc_free(tmp); + cmd->reply = "Failed to parse KI"; + return CTRL_CMD_ERROR; + } + + ainfo.a3a8_ki_len = rc; + db_sync_authinfo_for_subscr(&ainfo, subscr); + rc = 0; + } + + db_sync_lastauthtuple_for_subscr(NULL, subscr); subscr_put(subscr); talloc_free(tmp); diff --git a/openbsc/tests/ctrl_test_runner.py b/openbsc/tests/ctrl_test_runner.py index 21850e3..7a12643 100644 --- a/openbsc/tests/ctrl_test_runner.py +++ b/openbsc/tests/ctrl_test_runner.py @@ -469,6 +469,33 @@ class TestCtrlNITB(TestCtrlBase): self.assertEquals(r['var'], 'number-of-bts') self.assertEquals(r['value'], '1') + def testSubscriberAddWithKi(self): + """Test that we can set the algorithm to none, xor, comp128v1""" + + r = self.do_set('subscriber-modify-v1', '2620345,445566') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,none') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,xor') + self.assertEquals(r['mtype'], 'ERROR') + self.assertEquals(r['error'], 'Value failed verification.') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,comp128v1,00112233445566778899AABBCCDDEEFF') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,none') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + def testSubscriberAddRemove(self): r = self.do_set('subscriber-modify-v1', '2620345,445566') self.assertEquals(r['mtype'], 'SET_REPLY') -- 2.6.3 From nhofmeyr at sysmocom.de Wed Apr 6 22:47:35 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 7 Apr 2016 00:47:35 +0200 Subject: [PATCH 2/2] Factor out ipaccess send routines In-Reply-To: <1459957959-15333-2-git-send-email-msuraev@sysmocom.de> References: <1459957959-15333-1-git-send-email-msuraev@sysmocom.de> <1459957959-15333-2-git-send-email-msuraev@sysmocom.de> Message-ID: <20160406224735.GK2470@dub6> A few things in this patch draw my attention: - the verbose parameters have to be passed to each function call instead of having a global verbosity switch? Can make sense, but does it? It doesn't look like anyone is ever using the verbosity anyway? - the function defs are below their use; not a problem in python but unusual as far as I'm concerned. - 5 functions are added, only two are used. Why add unused functions? Will they ever be used? - Two functions are factored out and three others are added afresh. Admitted, the second part of the log message mentions adding functions, yet the summary above sounds like it's only factoring out. Sorry if I'm getting on your case with these details, but it seems you've thrown in too many curiosities at the same time for my taste :) ~Neels On Wed, Apr 06, 2016 at 05:52:39PM +0200, msuraev at sysmocom.de wrote: > From: Max > > Introduce several python functions for sending various ipaccess > protocol messages. Convert existing test code to use them. > --- > openbsc/tests/vty_test_runner.py | 29 +++++++++++++++++++++++++++-- > 1 file changed, 27 insertions(+), 2 deletions(-) > > diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py > index 8db0825..1c4ecb4 100644 > --- a/openbsc/tests/vty_test_runner.py > +++ b/openbsc/tests/vty_test_runner.py > @@ -700,13 +700,13 @@ class TestVTYNAT(TestVTYGenericBSC): > self.assertEqual(data, "\x00\x01\xfe\x04") > > print "Going to send ID_RESP response" > - res = ussdSocket.send("\x00\x07\xfe\x05\x00\x04\x01\x6b\x65\x79") > + res = ipa_send_resp(ussdSocket, "\x6b\x65\x79") > self.assertEqual(res, 10) > > # initiating PING/PONG cycle to know, that the ID_RESP message has been processed > > print "Going to send PING request" > - res = ussdSocket.send("\x00\x01\xfe\x00") > + res = ipa_send_ping(ussdSocket) > self.assertEqual(res, 4) > > print "Expecting PONG response" > @@ -971,6 +971,31 @@ def add_nat_test(suite, workdir): > test = unittest.TestLoader().loadTestsFromTestCase(TestVTYNAT) > suite.addTest(test) > > +def ipa_send_pong(x, verbose = False): > + if (verbose): > + print "\tBSC -> NAT: PONG!" > + return x.send("\x00\x01\xfe\x01") > + > +def ipa_send_ping(x, verbose = False): > + if (verbose): > + print "\tBSC -> NAT: PING?" > + return x.send("\x00\x01\xfe\x00") > + > +def ipa_send_ack(x, verbose = False): > + if (verbose): > + print "\tBSC -> NAT: IPA ID ACK" > + return x.send("\x00\x01\xfe\x06") > + > +def ipa_send_reset(x, verbose = False): > + if (verbose): > + print "\tBSC -> NAT: RESET" > + return x.send("\x00\x12\xfd\x09\x00\x03\x05\x07\x02\x42\xfe\x02\x42\xfe\x06\x00\x04\x30\x04\x01\x20") > + > +def ipa_send_resp(x, tk, verbose = False): > + if (verbose): > + print "\tBSC -> NAT: IPA ID RESP" > + return x.send("\x00\x07\xfe\x05\x00\x04\x01" + tk) > + > 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") > -- > 2.8.1 > -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Wed Apr 6 23:04:50 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 7 Apr 2016 01:04:50 +0200 Subject: [PATCH] NAT: allow allocating BSC in arbitrary order In-Reply-To: <1459959646-27455-1-git-send-email-msuraev@sysmocom.de> References: <1459959646-27455-1-git-send-email-msuraev@sysmocom.de> Message-ID: <20160406230450.GL2470@dub6> > > conf->token = talloc_strdup(conf, token); > - conf->nr = nat->num_bsc; > + conf->nr = number; I think you could completely remove the num_bsc variable? It looks like its sole use was to determine the next available BSC number without iterating the list. > conf->nat = nat; > conf->max_endpoints = 32; > conf->paging_group = PAGIN_GROUP_UNASSIGNED; > @@ -205,6 +206,10 @@ void bsc_config_free(struct bsc_config *cfg) > llist_del(&cfg->entry); > rate_ctr_group_free(cfg->stats.ctrg); > talloc_free(cfg); > + cfg->nat->num_bsc--; > + if (cfg->nat->num_bsc < 0) > + LOGP(DNAT, LOGL_ERROR, "Internal error while deallocating BSC " > + "config: negative BSC index!\n"); > } I don't understand why you would add this check for negative BSC index. The llist_del() should ensure that we don't double free a BSC, right? Also nice would be to add a test case that has a non-null BSC number, to show that having gaps in the numbering doesn't have side effects. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Wed Apr 6 23:12:41 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 7 Apr 2016 01:12:41 +0200 Subject: iuh: Coverity build breakage because of old sctp In-Reply-To: <55242E3B-94E9-4864-A201-2F18CA199D01@freyther.de> References: <55242E3B-94E9-4864-A201-2F18CA199D01@freyther.de> Message-ID: <20160406231241.GM2470@dub6> On Wed, Apr 06, 2016 at 09:26:57PM +0200, Holger Freyther wrote: > Hi, > > sua.c: In function 'rx_inact_tmr_cb': > sua.c:288: warning: unused variable 'conn' > sua.c: In function 'sua_rx_coref': > sua.c:908: warning: unused variable 'cause' > sua.c: In function 'sua_rx_codt': > sua.c:1059: warning: unused variable 'cur' > sua.c: In function 'sua_srv_conn_cb': > sua.c:1266: error: 'SCTP_SENDER_DRY_EVENT' undeclared (first use in this function) > sua.c:1266: error: (Each undeclared identifier is reported only once > sua.c:1266: error: for each function it appears in.) > sua.c: In function 'sua_cli_read_cb': > sua.c:1451: error: 'SCTP_SENDER_DRY_EVENT' undeclared (first use in this function) > > can we make the SCTP_SENDER_DRY_EVENT optional or is a strict requirement? If it is strict then maybe we can check for this in autoconf? It's completely unnecessary, I only added logging for it. Before, it printed a notification for "32777", and we surely want to know what that's supposed to mean. We could add a conditional define like #ifndef SCTP_SENDER_DRY_EVENT #define SCTP_SENDER_DRY_EVENT ((1<<15)+9) #endif because sctp.h defines the value both as enum *and* as a #define: enum sctp_sn_type { SCTP_SN_TYPE_BASE = (1<<15), SCTP_ASSOC_CHANGE, #define SCTP_ASSOC_CHANGE SCTP_ASSOC_CHANGE SCTP_PEER_ADDR_CHANGE, #define SCTP_PEER_ADDR_CHANGE SCTP_PEER_ADDR_CHANGE SCTP_SEND_FAILED, #define SCTP_SEND_FAILED SCTP_SEND_FAILED SCTP_REMOTE_ERROR, #define SCTP_REMOTE_ERROR SCTP_REMOTE_ERROR SCTP_SHUTDOWN_EVENT, #define SCTP_SHUTDOWN_EVENT SCTP_SHUTDOWN_EVENT SCTP_PARTIAL_DELIVERY_EVENT, #define SCTP_PARTIAL_DELIVERY_EVENT SCTP_PARTIAL_DELIVERY_EVENT SCTP_ADAPTATION_INDICATION, #define SCTP_ADAPTATION_INDICATION SCTP_ADAPTATION_INDICATION SCTP_AUTHENTICATION_INDICATION, #define SCTP_AUTHENTICATION_INDICATION SCTP_AUTHENTICATION_INDICATION SCTP_SENDER_DRY_EVENT, #define SCTP_SENDER_DRY_EVENT SCTP_SENDER_DRY_EVENT }; Not sure though whether we should rely on this. I could also hardcode 32777, but that's not such a good idea either. Last resort is to not log the event and hope that all of us know what 32777 is all about. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Thu Apr 7 00:52:50 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 7 Apr 2016 02:52:50 +0200 Subject: [PATCH] ctrl: Extend ctrl command to optionally handle alg+ki In-Reply-To: <1459975492-74488-1-git-send-email-holger@freyther.de> References: <1459975492-74488-1-git-send-email-holger@freyther.de> Message-ID: <20160407005250.GO2470@dub6> On Wed, Apr 06, 2016 at 10:44:52PM +0200, Holger Hans Peter Freyther wrote: > + > + /* handle optional ciphering */ > + if (!alg || strcasecmp(alg, "none") == 0) > + db_sync_authinfo_for_subscr(NULL, subscr); > + else { > + struct gsm_auth_info ainfo = { 0, }; > + /* the verify should make sure that this is okay */ > + OSMO_ASSERT(alg); > + OSMO_ASSERT(ki); > + > + if (strcasecmp(alg, "xor") == 0) > + ainfo.auth_algo = AUTH_ALGO_XOR; > + else if (strcasecmp(alg, "comp128v1") == 0) > + ainfo.auth_algo = AUTH_ALGO_COMP128v1; > + > + rc = osmo_hexparse(ki, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki)); > + if (rc < 0) { > + subscr_put(subscr); > + talloc_free(tmp); > + cmd->reply = "Failed to parse KI"; > + return CTRL_CMD_ERROR; > + } > + > + ainfo.a3a8_ki_len = rc; > + db_sync_authinfo_for_subscr(&ainfo, subscr); > + rc = 0; > + } > + > + db_sync_lastauthtuple_for_subscr(NULL, subscr); You didn't bump to v2 because it is supposedly backwards compatible to subscriber-modify-v1 without auth info, right? But consider that a subscriber-modify-v1 will now clear out the auth info when the newly added parameters are omitted. So it's not strictly backwards compatible, right? With the previous v1 I could only modify IMSI and MSISDN and leave algo and KI untouched. After this patch I will always either have to pass algo+KI again or they will be cleared out. Also, this will always clear out the lastauthtuple, regardless of the auth info being changed or not. Even if I again pass the same algo+KI as were stored previously. OTOH clearing might be good when the IMSI has changed?? :P Maybe it's better / less complex to have a separate command for auth or bump to v2... > + r = self.do_set('subscriber-modify-v1', '2620345,445566,xor') > + self.assertEquals(r['mtype'], 'ERROR') > + self.assertEquals(r['error'], 'Value failed verification.') I'm not familiar with the ctrl interface, but couldn't the error message be more descriptive, like "missing KI argument"? log msg: > The algorithm and ki are considered optional but if a valid > and non none algorithm is passed, a KI must be passed as well. rather say 'not-none' or 'a valid algorithm other than "none"'. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Thu Apr 7 01:13:29 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 7 Apr 2016 03:13:29 +0200 Subject: PLMN identity: 04.08 vs. RANAP In-Reply-To: <1459959443.2985.25.camel@sysmocom.de> References: <20160406122026.GE2470@dub6> <1459955934.2985.22.camel@sysmocom.de> <20160406154649.GG2470@dub6> <1459959443.2985.25.camel@sysmocom.de> Message-ID: <20160407011329.GQ2470@dub6> On Wed, Apr 06, 2016 at 06:17:23PM +0200, Daniel Willmann wrote: > Fun fact: The Dell phone displays the network correctly as 901123 - the > Sony Ericsson K800i incorrectly displays it as 901231. :-) LOL, this thing is causing widespread confusion :) So the Ericsson is decoding the RANAP PLMN-Id in a 04.08 way, and the Dell and our hnb agree that RANAP works differently... Counting a vote of 2 against 1 that the codings differ. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From holger at freyther.de Thu Apr 7 07:15:30 2016 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 7 Apr 2016 09:15:30 +0200 Subject: [PATCH v2] ctrl: Extend ctrl command to optionally handle alg+ki Message-ID: <1460013330-75690-1-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther Extend the existing ctrl command to be able to specify the algorithm and Ki. In contrast to the VTY no size check is done. Together with the VTY this code only supports a small part of what is supported by libosmocore. The algorithm and ki are considered optional but if a valid and non none algorithm is passed, a KI must be passed as well. Extend the test coverage by passing the potential values. It is not verified that the KI/algorithm is stored. --- openbsc/src/libmsc/ctrl_commands.c | 60 ++++++++++++++++++++++++++++++++++++-- openbsc/tests/ctrl_test_runner.py | 27 +++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/openbsc/src/libmsc/ctrl_commands.c b/openbsc/src/libmsc/ctrl_commands.c index e48c6a3..9ac39de 100644 --- a/openbsc/src/libmsc/ctrl_commands.c +++ b/openbsc/src/libmsc/ctrl_commands.c @@ -24,9 +24,25 @@ #include #include +static bool alg_supported(const char *alg) +{ + /* + * TODO: share this with the vty_interface and extend to all + * algorithms supported by libosmocore now. Make it table based + * as well. + */ + if (strcasecmp(alg, "none") == 0) + return true; + if (strcasecmp(alg, "xor") == 0) + return true; + if (strcasecmp(alg, "comp128v1") == 0) + return true; + return false; +} + static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, void *d) { - char *tmp, *imsi, *msisdn, *saveptr = NULL; + char *tmp, *imsi, *msisdn, *alg, *ki, *saveptr = NULL; int rc = 0; tmp = talloc_strdup(cmd, value); @@ -35,6 +51,8 @@ static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, voi imsi = strtok_r(tmp, ",", &saveptr); msisdn = strtok_r(NULL, ",", &saveptr); + alg = strtok_r(NULL, ",", &saveptr); + ki = strtok_r(NULL, ",", &saveptr); if (!imsi || !msisdn) rc = 1; @@ -42,6 +60,12 @@ static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, voi rc = 1; else if (strlen(msisdn) >= GSM_EXTENSION_LENGTH) rc = 1; + else if (alg) { + if (!alg_supported(alg)) + rc = 1; + else if (strcasecmp(alg, "none") != 0 && !ki) + rc = 1; + } talloc_free(tmp); return rc; @@ -56,7 +80,7 @@ static int get_subscriber_modify(struct ctrl_cmd *cmd, void *data) static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data) { struct gsm_network *net = cmd->node; - char *tmp, *imsi, *msisdn, *saveptr = NULL; + char *tmp, *imsi, *msisdn, *alg, *ki, *saveptr = NULL; struct gsm_subscriber* subscr; int rc; @@ -66,6 +90,8 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data) imsi = strtok_r(tmp, ",", &saveptr); msisdn = strtok_r(NULL, ",", &saveptr); + alg = strtok_r(NULL, ",", &saveptr); + ki = strtok_r(NULL, ",", &saveptr); subscr = subscr_get_by_imsi(net->subscr_group, imsi); if (!subscr) @@ -80,6 +106,36 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data) /* put it back to the db */ rc = db_sync_subscriber(subscr); db_subscriber_update(subscr); + + /* handle optional ciphering */ + if (alg) { + if (strcasecmp(alg, "none") == 0) + db_sync_authinfo_for_subscr(NULL, subscr); + else { + struct gsm_auth_info ainfo = { 0, }; + /* the verify should make sure that this is okay */ + OSMO_ASSERT(alg); + OSMO_ASSERT(ki); + + if (strcasecmp(alg, "xor") == 0) + ainfo.auth_algo = AUTH_ALGO_XOR; + else if (strcasecmp(alg, "comp128v1") == 0) + ainfo.auth_algo = AUTH_ALGO_COMP128v1; + + rc = osmo_hexparse(ki, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki)); + if (rc < 0) { + subscr_put(subscr); + talloc_free(tmp); + cmd->reply = "Failed to parse KI"; + return CTRL_CMD_ERROR; + } + + ainfo.a3a8_ki_len = rc; + db_sync_authinfo_for_subscr(&ainfo, subscr); + rc = 0; + } + db_sync_lastauthtuple_for_subscr(NULL, subscr); + } subscr_put(subscr); talloc_free(tmp); diff --git a/openbsc/tests/ctrl_test_runner.py b/openbsc/tests/ctrl_test_runner.py index 21850e3..7a12643 100644 --- a/openbsc/tests/ctrl_test_runner.py +++ b/openbsc/tests/ctrl_test_runner.py @@ -469,6 +469,33 @@ class TestCtrlNITB(TestCtrlBase): self.assertEquals(r['var'], 'number-of-bts') self.assertEquals(r['value'], '1') + def testSubscriberAddWithKi(self): + """Test that we can set the algorithm to none, xor, comp128v1""" + + r = self.do_set('subscriber-modify-v1', '2620345,445566') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,none') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,xor') + self.assertEquals(r['mtype'], 'ERROR') + self.assertEquals(r['error'], 'Value failed verification.') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,comp128v1,00112233445566778899AABBCCDDEEFF') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,none') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + def testSubscriberAddRemove(self): r = self.do_set('subscriber-modify-v1', '2620345,445566') self.assertEquals(r['mtype'], 'SET_REPLY') -- 2.6.3 From holger at freyther.de Thu Apr 7 07:18:09 2016 From: holger at freyther.de (Holger Freyther) Date: Thu, 7 Apr 2016 09:18:09 +0200 Subject: [PATCH] NAT: allow allocating BSC in arbitrary order In-Reply-To: <20160406230450.GL2470@dub6> References: <1459959646-27455-1-git-send-email-msuraev@sysmocom.de> <20160406230450.GL2470@dub6> Message-ID: <4395A62B-6A39-4894-AA3A-84063530F154@freyther.de> > On 07 Apr 2016, at 01:04, Neels Hofmeyr wrote: > >> >> conf->token = talloc_strdup(conf, token); >> - conf->nr = nat->num_bsc; >> + conf->nr = number; > > I think you could completely remove the num_bsc variable? It looks like its > sole use was to determine the next available BSC number without iterating the > list. I have emotional attachments to this variable and would prefer to keep it around. > >> + cfg->nat->num_bsc--; >> + if (cfg->nat->num_bsc < 0) >> + LOGP(DNAT, LOGL_ERROR, "Internal error while deallocating BSC " >> + "config: negative BSC index!\n"); >> } > > I don't understand why you would add this check for negative BSC index. > The llist_del() should ensure that we don't double free a BSC, right? more like maintaining an invariant. So maybe OSMO_ASSERT(num_bsc >= 0) is better? > Also nice would be to add a test case that has a non-null BSC number, to show > that having gaps in the numbering doesn't have side effects. Do you have an idea for the testcase? holger From holger at freyther.de Thu Apr 7 07:28:08 2016 From: holger at freyther.de (Holger Freyther) Date: Thu, 7 Apr 2016 09:28:08 +0200 Subject: [PATCH] ctrl: Extend ctrl command to optionally handle alg+ki In-Reply-To: <20160407005250.GO2470@dub6> References: <1459975492-74488-1-git-send-email-holger@freyther.de> <20160407005250.GO2470@dub6> Message-ID: > On 07 Apr 2016, at 02:52, Neels Hofmeyr wrote: > > > You didn't bump to v2 because it is supposedly backwards compatible to > subscriber-modify-v1 without auth info, right? right. The v1 testcase is still passing and the customer using this interface will not notice any change. > Also, this will always clear out the lastauthtuple, regardless of the auth info > being changed or not. Even if I again pass the same algo+KI as were stored > previously. OTOH clearing might be good when the IMSI has changed?? :P IMSI has changed == new subscriber. Also for a CTRL interface only case we could not have set the keys before, so clearing the auth tuples has no effect. But anyway, I have sent a v2 that moves this handling into an if so there is no semantic change for the current usage of the interface. > > Maybe it's better / less complex to have a separate command for auth or bump to > v2... I didn't want to open the can of deprecation and removing old commands yet. The v1 behavior is tested (the test should actually check the DB for the state or such but that is a different topic). I found it easier to add to the existing command and based on the ctrl test I am confident to not break the users of that interface. >> + r = self.do_set('subscriber-modify-v1', '2620345,445566,xor') >> + self.assertEquals(r['mtype'], 'ERROR') >> + self.assertEquals(r['error'], 'Value failed verification.') > > I'm not familiar with the ctrl interface, but couldn't the error message be > more descriptive, like "missing KI argument"?\ The CTRL command has a READ, VERIFY and WRITE method. VERIFY will be executed before WRITE. The VERIFY method can only return yes or no. We can add improving/extending the VERIFY to our backlog. > log msg: >> The algorithm and ki are considered optional but if a valid >> and non none algorithm is passed, a KI must be passed as well. > > rather say 'not-none' or 'a valid algorithm other than "none"'. fixed locally but that is not in the v2 patch holger From holger at freyther.de Thu Apr 7 08:40:19 2016 From: holger at freyther.de (Holger Freyther) Date: Thu, 7 Apr 2016 10:40:19 +0200 Subject: iuh: Coverity build breakage because of old sctp In-Reply-To: <20160406231241.GM2470@dub6> References: <55242E3B-94E9-4864-A201-2F18CA199D01@freyther.de> <20160406231241.GM2470@dub6> Message-ID: > On 07 Apr 2016, at 01:12, Neels Hofmeyr wrote: > > On Wed, Apr 06, 2016 at 09:26:57PM +0200, Holger Freyther wrote: >> Hi, >> >> sua.c: In function 'rx_inact_tmr_cb': >> sua.c:288: warning: unused variable 'conn' >> sua.c: In function 'sua_rx_coref': >> sua.c:908: warning: unused variable 'cause' >> sua.c: In function 'sua_rx_codt': >> sua.c:1059: warning: unused variable 'cur' >> sua.c: In function 'sua_srv_conn_cb': >> sua.c:1266: error: 'SCTP_SENDER_DRY_EVENT' undeclared (first use in this function) >> sua.c:1266: error: (Each undeclared identifier is reported only once >> sua.c:1266: error: for each function it appears in.) >> sua.c: In function 'sua_cli_read_cb': >> sua.c:1451: error: 'SCTP_SENDER_DRY_EVENT' undeclared (first use in this function) >> >> can we make the SCTP_SENDER_DRY_EVENT optional or is a strict requirement? If it is strict then maybe we can check for this in autoconf? > > It's completely unnecessary, I only added logging for it. Before, it printed a > notification for "32777", and we surely want to know what that's supposed to > mean. > > We could add a conditional define like > > #ifndef SCTP_SENDER_DRY_EVENT > #define SCTP_SENDER_DRY_EVENT ((1<<15)+9) > #endif besides on FreeBSD it is #define SCTP_SENDER_DRY_EVENT 0x000a but both define it so please cover the case in a #ifdef. thanks From msuraev at sysmocom.de Thu Apr 7 09:01:52 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 7 Apr 2016 11:01:52 +0200 Subject: [PATCH] Add missing docs for bssgp bvc reset vty command Message-ID: <1460019712-4368-1-git-send-email-msuraev@sysmocom.de> From: Max Fixes the build failure with extended tests enabled. --- src/gb/gprs_bssgp_vty.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gb/gprs_bssgp_vty.c b/src/gb/gprs_bssgp_vty.c index a3af69b..f23d75f 100644 --- a/src/gb/gprs_bssgp_vty.c +++ b/src/gb/gprs_bssgp_vty.c @@ -115,8 +115,14 @@ static void dump_bssgp(struct vty *vty, int stats) } DEFUN(bvc_reset, bvc_reset_cmd, - "bssgp bvc nsei <0-65535> bvci <0-65535> reset", - "Initiate BVC RESET procedure for a given NSEI and BVCI\n") + "bssgp bvc nsei <0-65535> bvci <0-65535> reset", + "Initiate BVC RESET procedure for a given NSEI and BVCI\n" + "Filter based on BSSGP Virtual Connection\n" + "NSEI of the BVC to be filtered\n" + "Network Service Entity Identifier (NSEI)\n" + "BVCI of the BVC to be filtered\n" + "BSSGP Virtual Connection Identifier (BVCI)\n" + "Perform reset procedure\n") { int r; uint16_t nsei = atoi(argv[0]), bvci = atoi(argv[1]); -- 2.8.1 From msuraev at sysmocom.de Thu Apr 7 09:15:31 2016 From: msuraev at sysmocom.de (Max) Date: Thu, 7 Apr 2016 11:15:31 +0200 Subject: [PATCH 2/2] Factor out ipaccess send routines In-Reply-To: <20160406224735.GK2470@dub6> References: <1459957959-15333-1-git-send-email-msuraev@sysmocom.de> <1459957959-15333-2-git-send-email-msuraev@sysmocom.de> <20160406224735.GK2470@dub6> Message-ID: <57062533.80107@sysmocom.de> Thanks for review. Comments are inline On 04/07/2016 12:47 AM, Neels Hofmeyr wrote: > A few things in this patch draw my attention: > > - the verbose parameters have to be passed to each function call instead of > having a global verbosity switch? Can make sense, but does it? It doesn't > look like anyone is ever using the verbosity anyway? They were useful for debugging the tests but once it's ready the'd just clutter the output unnecessary. Still, they'll be useful again when we want to expand tests further so instead of adding and removing them every time I'd prefer to keep them. > > - the function defs are below their use; not a problem in python but unusual as > far as I'm concerned. Matter of taste I guess: I prefer to have all the functions not belonging to particular class to be in one place instead being spread over the file according to where it's used. > > - 5 functions are added, only two are used. Why add unused functions? > Will they ever be used? Perhaps :) I've added them while trying to mock BSC and MSC. It turned out that not all of them are actually necessary for current test-cases. Nevertheless I'd rather keep them because those are simple wrappers around magic hex constants for IPA protocol which are tried and tested, so next time we need more tests we can just use them right away instead of duplicating the efforts of finding out proper hex number sequences. > > - Two functions are factored out and three others are added afresh. Admitted, > the second part of the log message mentions adding functions, yet the summary > above sounds like it's only factoring out. > How would you summarize it? -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Thu Apr 7 09:38:52 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 7 Apr 2016 11:38:52 +0200 Subject: [PATCH] Remove trivial wrapper function Message-ID: <1460021932-18597-1-git-send-email-msuraev@sysmocom.de> From: Max Rename gsm48_tx_chan_mode_modify() to gsm48_lchan_modify() and remove corresponding wrapper code. --- openbsc/src/libbsc/gsm_04_08_utils.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/openbsc/src/libbsc/gsm_04_08_utils.c b/openbsc/src/libbsc/gsm_04_08_utils.c index 8c6dbef..635665a 100644 --- a/openbsc/src/libbsc/gsm_04_08_utils.c +++ b/openbsc/src/libbsc/gsm_04_08_utils.c @@ -463,7 +463,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, /* * fill the channel information element, this code * should probably be shared with rsl_rx_chan_rqd(), - * gsm48_tx_chan_mode_modify. But beware that 10.5.2.5 + * gsm48_lchan_modify(). But beware that 10.5.2.5 * 10.5.2.5.a have slightly different semantic for * the chan_desc. But as long as multi-slot configurations * are not used we seem to be fine. @@ -488,7 +488,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, } /* 9.1.5 Channel mode modify: Modify the mode on the MS side */ -int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, uint8_t mode) +int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode) { struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CHN MOD"); struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); @@ -513,17 +513,6 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, uint8_t mode) return gsm48_sendmsg(msg); } -int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode) -{ - int rc; - - rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode); - if (rc < 0) - return rc; - - return rc; -} - int gsm48_rx_rr_modif_ack(struct msgb *msg) { int rc; -- 2.8.1 From msuraev at sysmocom.de Thu Apr 7 09:58:35 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 7 Apr 2016 11:58:35 +0200 Subject: [PATCH] NAT: allow allocating BSC in arbitrary order Message-ID: <1460023115-26378-1-git-send-email-msuraev@sysmocom.de> From: Max Check for existing BSC before allocating new one. Track number of remaining BSCs on deallocation. Explicitly use BSC number in allocation function. --- openbsc/include/openbsc/bsc_nat.h | 3 ++- openbsc/src/osmo-bsc_nat/bsc_nat_utils.c | 7 +++++-- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 14 ++++---------- openbsc/tests/bsc-nat/bsc_nat_test.c | 14 +++++++------- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 7ede1fb..5ccc02e 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -325,7 +325,8 @@ struct bsc_nat_ussd_con { }; /* create and init the structures */ -struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token); +struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, + unsigned int number); struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num); struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len); void bsc_config_free(struct bsc_config *); diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c index cc7d442..285f1aa 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c @@ -155,14 +155,15 @@ struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat) return con; } -struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token) +struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, + unsigned int number) { struct bsc_config *conf = talloc_zero(nat, struct bsc_config); if (!conf) return NULL; conf->token = talloc_strdup(conf, token); - conf->nr = nat->num_bsc; + conf->nr = number; conf->nat = nat; conf->max_endpoints = 32; conf->paging_group = PAGIN_GROUP_UNASSIGNED; @@ -205,6 +206,8 @@ void bsc_config_free(struct bsc_config *cfg) llist_del(&cfg->entry); rate_ctr_group_free(cfg->stats.ctrg); talloc_free(cfg); + cfg->nat->num_bsc--; + OSMO_ASSERT(num_bsc >= 0) } static void _add_lac(void *ctx, struct llist_head *list, int _lac) diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 26b0fd6..b7b49e6 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -837,17 +837,11 @@ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "BSC configuration\n" "Identifier of the BSC\n") { int bsc_nr = atoi(argv[0]); - struct bsc_config *bsc; + struct bsc_config *bsc = bsc_config_num(_nat, bsc_nr); - if (bsc_nr > _nat->num_bsc) { - vty_out(vty, "%% The next unused BSC number is %u%s", - _nat->num_bsc, VTY_NEWLINE); - return CMD_WARNING; - } else if (bsc_nr == _nat->num_bsc) { - /* allocate a new one */ - bsc = bsc_config_alloc(_nat, "unknown"); - } else - bsc = bsc_config_num(_nat, bsc_nr); + /* allocate a new one */ + if (!bsc) + bsc = bsc_config_alloc(_nat, "unknown", bsc_nr); if (!bsc) return CMD_WARNING; diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c index a4b313c..a405763 100644 --- a/openbsc/tests/bsc-nat/bsc_nat_test.c +++ b/openbsc/tests/bsc-nat/bsc_nat_test.c @@ -316,7 +316,7 @@ static void test_contrack() printf("Testing connection tracking.\n"); nat = bsc_nat_alloc(); con = bsc_connection_alloc(nat); - con->cfg = bsc_config_alloc(nat, "foo"); + con->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(con->cfg, 23); bsc_config_add_lac(con->cfg, 49); bsc_config_add_lac(con->cfg, 42); @@ -434,7 +434,7 @@ static void test_paging(void) nat = bsc_nat_alloc(); con = bsc_connection_alloc(nat); - cfg = bsc_config_alloc(nat, "unknown"); + cfg = bsc_config_alloc(nat, "unknown", 0); con->cfg = cfg; bsc_config_add_lac(cfg, 23); con->authenticated = 1; @@ -476,7 +476,7 @@ static void test_mgcp_allocations(void) nat->mgcp_cfg->trunk.number_endpoints = 64; bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc->cfg->max_endpoints = 60; bsc_config_add_lac(bsc->cfg, 2323); bsc->last_endpoint = 0x22; @@ -522,7 +522,7 @@ static void test_mgcp_ass_tracking(void) mgcp_endpoints_allocate(&nat->mgcp_cfg->trunk); bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 2323); bsc->last_endpoint = 0x1e; con.bsc = bsc; @@ -874,7 +874,7 @@ static void test_cr_filter() struct bsc_nat *nat = bsc_nat_alloc(); struct bsc_connection *bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 1234); bsc->cfg->acc_lst_name = "bsc"; nat->acc_lst_name = "nat"; @@ -953,7 +953,7 @@ static void test_dt_filter() struct bsc_connection *bsc = bsc_connection_alloc(nat); struct nat_sccp_connection *con = talloc_zero(0, struct nat_sccp_connection); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 23); con->bsc = bsc; @@ -1525,7 +1525,7 @@ static void test_nat_extract_lac() /* initialize the testcase */ nat = bsc_nat_alloc(); bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); memset(&con, 0, sizeof(con)); con.bsc = bsc; -- 2.8.1 From msuraev at sysmocom.de Thu Apr 7 10:03:35 2016 From: msuraev at sysmocom.de (Max) Date: Thu, 7 Apr 2016 12:03:35 +0200 Subject: [PATCH] NAT: allow allocating BSC in arbitrary order In-Reply-To: <4395A62B-6A39-4894-AA3A-84063530F154@freyther.de> References: <1459959646-27455-1-git-send-email-msuraev@sysmocom.de> <20160406230450.GL2470@dub6> <4395A62B-6A39-4894-AA3A-84063530F154@freyther.de> Message-ID: <57063077.8050404@sysmocom.de> Thanks for review. I can add the test-case for adding bscs with numbers 0, 1, 3 in vty tests for dynamic conf reloading - I'm adding/removing it there anyway. On 04/07/2016 09:18 AM, Holger Freyther wrote: >> On 07 Apr 2016, at 01:04, Neels Hofmeyr wrote: >> Also nice would be to add a test case that has a non-null BSC number, to show >> that having gaps in the numbering doesn't have side effects. > > Do you have an idea for the testcase? > > holger > -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From nhofmeyr at sysmocom.de Thu Apr 7 10:21:52 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 7 Apr 2016 12:21:52 +0200 Subject: [PATCH 2/2] Factor out ipaccess send routines In-Reply-To: <57062533.80107@sysmocom.de> References: <1459957959-15333-1-git-send-email-msuraev@sysmocom.de> <1459957959-15333-2-git-send-email-msuraev@sysmocom.de> <20160406224735.GK2470@dub6> <57062533.80107@sysmocom.de> Message-ID: <20160407102152.GA1211@ass40.sysmocom.de> On Thu, Apr 07, 2016 at 11:15:31AM +0200, Max wrote: > They were useful for debugging the tests but once it's ready the'd just > clutter the output unnecessary. Still, they'll be useful again when we > want to expand tests further so instead of adding and removing them > every time I'd prefer to keep them. would be nice to mention in the log message body... > > - 5 functions are added, only two are used. Why add unused functions? > > Will they ever be used? > > Perhaps :) also nice to mention in the log message body > > - Two functions are factored out and three others are added afresh. Admitted, > > the second part of the log message mentions adding functions, yet the summary > > above sounds like it's only factoring out. > > > How would you summarize it? "vty_test_runner: ipa_send: factor out 2, add 3 functions" :) BTW, just to set the tone, I would like to mention that my feedback is generally meant as friendly comment, in a happy office, from colleague to colleague ;) (I'd be glad if you'd return such reviews on my patches.) ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Thu Apr 7 10:26:30 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 7 Apr 2016 12:26:30 +0200 Subject: [PATCH] NAT: allow allocating BSC in arbitrary order In-Reply-To: <4395A62B-6A39-4894-AA3A-84063530F154@freyther.de> References: <1459959646-27455-1-git-send-email-msuraev@sysmocom.de> <20160406230450.GL2470@dub6> <4395A62B-6A39-4894-AA3A-84063530F154@freyther.de> Message-ID: <20160407102630.GB1211@ass40.sysmocom.de> On Thu, Apr 07, 2016 at 09:18:09AM +0200, Holger Freyther wrote: > Do you have an idea for the testcase? - make sure I can create BTS 23 first, then BTS 0 and then BTS 5, and find all of them again later; and that all three are cleaned up. - what happens when I try to create BTS -42. - what happens when I try to access BTS 7 though it wasn't created. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From msuraev at sysmocom.de Thu Apr 7 10:27:11 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 7 Apr 2016 12:27:11 +0200 Subject: [PATCH] NAT: allow allocating BSC in arbitrary order Message-ID: <1460024831-5177-1-git-send-email-msuraev@sysmocom.de> From: Max Check for existing BSC before allocating new one. Track number of remaining BSCs on deallocation. Explicitly use BSC number in allocation function. --- openbsc/include/openbsc/bsc_nat.h | 3 ++- openbsc/src/osmo-bsc_nat/bsc_nat_utils.c | 7 +++++-- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 14 ++++---------- openbsc/tests/bsc-nat/bsc_nat_test.c | 14 +++++++------- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 7ede1fb..5ccc02e 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -325,7 +325,8 @@ struct bsc_nat_ussd_con { }; /* create and init the structures */ -struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token); +struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, + unsigned int number); struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num); struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len); void bsc_config_free(struct bsc_config *); diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c index cc7d442..37b01e3 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c @@ -155,14 +155,15 @@ struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat) return con; } -struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token) +struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, + unsigned int number) { struct bsc_config *conf = talloc_zero(nat, struct bsc_config); if (!conf) return NULL; conf->token = talloc_strdup(conf, token); - conf->nr = nat->num_bsc; + conf->nr = number; conf->nat = nat; conf->max_endpoints = 32; conf->paging_group = PAGIN_GROUP_UNASSIGNED; @@ -205,6 +206,8 @@ void bsc_config_free(struct bsc_config *cfg) llist_del(&cfg->entry); rate_ctr_group_free(cfg->stats.ctrg); talloc_free(cfg); + cfg->nat->num_bsc--; + OSMO_ASSERT(cfg->nat->num_bsc >= 0) } static void _add_lac(void *ctx, struct llist_head *list, int _lac) diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 26b0fd6..b7b49e6 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -837,17 +837,11 @@ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "BSC configuration\n" "Identifier of the BSC\n") { int bsc_nr = atoi(argv[0]); - struct bsc_config *bsc; + struct bsc_config *bsc = bsc_config_num(_nat, bsc_nr); - if (bsc_nr > _nat->num_bsc) { - vty_out(vty, "%% The next unused BSC number is %u%s", - _nat->num_bsc, VTY_NEWLINE); - return CMD_WARNING; - } else if (bsc_nr == _nat->num_bsc) { - /* allocate a new one */ - bsc = bsc_config_alloc(_nat, "unknown"); - } else - bsc = bsc_config_num(_nat, bsc_nr); + /* allocate a new one */ + if (!bsc) + bsc = bsc_config_alloc(_nat, "unknown", bsc_nr); if (!bsc) return CMD_WARNING; diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c index a4b313c..a405763 100644 --- a/openbsc/tests/bsc-nat/bsc_nat_test.c +++ b/openbsc/tests/bsc-nat/bsc_nat_test.c @@ -316,7 +316,7 @@ static void test_contrack() printf("Testing connection tracking.\n"); nat = bsc_nat_alloc(); con = bsc_connection_alloc(nat); - con->cfg = bsc_config_alloc(nat, "foo"); + con->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(con->cfg, 23); bsc_config_add_lac(con->cfg, 49); bsc_config_add_lac(con->cfg, 42); @@ -434,7 +434,7 @@ static void test_paging(void) nat = bsc_nat_alloc(); con = bsc_connection_alloc(nat); - cfg = bsc_config_alloc(nat, "unknown"); + cfg = bsc_config_alloc(nat, "unknown", 0); con->cfg = cfg; bsc_config_add_lac(cfg, 23); con->authenticated = 1; @@ -476,7 +476,7 @@ static void test_mgcp_allocations(void) nat->mgcp_cfg->trunk.number_endpoints = 64; bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc->cfg->max_endpoints = 60; bsc_config_add_lac(bsc->cfg, 2323); bsc->last_endpoint = 0x22; @@ -522,7 +522,7 @@ static void test_mgcp_ass_tracking(void) mgcp_endpoints_allocate(&nat->mgcp_cfg->trunk); bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 2323); bsc->last_endpoint = 0x1e; con.bsc = bsc; @@ -874,7 +874,7 @@ static void test_cr_filter() struct bsc_nat *nat = bsc_nat_alloc(); struct bsc_connection *bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 1234); bsc->cfg->acc_lst_name = "bsc"; nat->acc_lst_name = "nat"; @@ -953,7 +953,7 @@ static void test_dt_filter() struct bsc_connection *bsc = bsc_connection_alloc(nat); struct nat_sccp_connection *con = talloc_zero(0, struct nat_sccp_connection); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 23); con->bsc = bsc; @@ -1525,7 +1525,7 @@ static void test_nat_extract_lac() /* initialize the testcase */ nat = bsc_nat_alloc(); bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); memset(&con, 0, sizeof(con)); con.bsc = bsc; -- 2.8.1 From msuraev at sysmocom.de Thu Apr 7 12:11:25 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 7 Apr 2016 14:11:25 +0200 Subject: [PATCH] Recursively copy files before config test Message-ID: <1460031085-30498-1-git-send-email-msuraev@sysmocom.de> From: Max Copy all potentially necessary files (like includable configs) before running config test. --- osmopy/osmotestconfig.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osmopy/osmotestconfig.py b/osmopy/osmotestconfig.py index b020d86..5c981d1 100644 --- a/osmopy/osmotestconfig.py +++ b/osmopy/osmotestconfig.py @@ -17,7 +17,7 @@ import os import os.path import time -import sys +import sys, shutil import tempfile import osmopy.obscvty as obscvty @@ -72,15 +72,15 @@ def test_config_atest(app_desc, config, run_test, verbose=True): return ret - def copy_config(dirname, config): + shutil.rmtree(dirname, True) + ign = shutil.ignore_patterns('*.cfg') + shutil.copytree(os.path.dirname(config), dirname, ignore=ign) + try: os.stat(dirname) except OSError: os.mkdir(dirname) - else: - remove_tmpdir(dirname) - os.mkdir(dirname) prefix = os.path.basename(config) tmpfile = tempfile.NamedTemporaryFile( -- 2.8.1 From nhofmeyr at sysmocom.de Thu Apr 7 22:46:05 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 8 Apr 2016 00:46:05 +0200 Subject: [PATCH] remove two compiler warnings for unused variables Message-ID: <1460069165-5638-1-git-send-email-nhofmeyr@sysmocom.de> --- src/sua.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sua.c b/src/sua.c index 6e187d8..df60c13 100644 --- a/src/sua.c +++ b/src/sua.c @@ -793,7 +793,6 @@ static int sua_rx_core(struct osmo_sua_link *link, struct xua_msg *xua) struct xua_msg_part *data_ie = xua_msg_find_tag(xua, SUA_IEI_DATA); struct msgb *upmsg; struct sua_connection *conn; - uint8_t *cur; /* fill conn */ conn = conn_create(link); @@ -926,7 +925,8 @@ static int sua_rx_coref(struct osmo_sua_link *link, struct xua_msg *xua) memcpy(¶m->calling_addr, &conn->calling_addr, sizeof(param->calling_addr)); //param->in_sequence_control; - cause = xua_msg_get_u32(xua, SUA_IEI_CAUSE); + /* TODO evaluate cause: + * cause = xua_msg_get_u32(xua, SUA_IEI_CAUSE); */ /* optional: src addr */ /* optional: dest addr */ param->importance = xua_msg_get_u32(xua, SUA_IEI_IMPORTANCE); -- 2.1.4 From msuraev at sysmocom.de Fri Apr 8 09:52:34 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 8 Apr 2016 11:52:34 +0200 Subject: [PATCH] Fix segfault with broken config Message-ID: <1460109154-30975-1-git-send-email-msuraev@sysmocom.de> From: Max Fixes OS#1691 --- openbsc/src/libbsc/bsc_init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 859d999..713109c 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -373,6 +373,9 @@ static int bootstrap_bts(struct gsm_bts *bts) { int i, n; + if (!bts->model) + return -EFAULT; + if (bts->model->start && !bts->model->started) { int ret = bts->model->start(bts->network); if (ret < 0) -- 2.8.1 From tom at tsou.cc Fri Apr 8 22:55:42 2016 From: tom at tsou.cc (Tom Tsou) Date: Fri, 8 Apr 2016 15:55:42 -0700 Subject: osmo-bts-trx: "CHAN RQD: no resources for SDCCH" on master Message-ID: Hi Harald, On Wed, Apr 6, 2016 at 12:59 AM, Harald Welte wrote: > Can you or somebody else interested in getting this resolved provide a > full bug report, including > * debug log output on OsmoNITB side for for the rsl and nm > * debug log output on OsmoBTS side for oml / transceiver interface or > anything else related > * pcap file of A-bis traffic between OsmoBTS and OsmoNITB, as well as > the control commands between osmo-bts-trx and osmo-trx Attached are the logs for master branches of OpenBSC, OsmoBTS, and OsmoTRX leading up to the following RACH access behavior. <0004> abis_rsl.c:1423 BTS 0 CHAN RQD: no resources for SDCCH 0x2 Hopefully, somebody more familiar than myself with A-bis and related L1/L2 dependencies can provide some insight on why the above is happening or where to start debugging. I'll be happy to test any subsequent changes or look into specific parts of the A-bis code. -TT -------------- next part -------------- A non-text attachment was scrubbed... Name: openbsc.log Type: text/x-log Size: 10555 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: osmo-trx.log Type: text/x-log Size: 1387 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: osmo-bts.log Type: text/x-log Size: 23136 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: networking.pcap Type: application/vnd.tcpdump.pcap Size: 34047 bytes Desc: not available URL: From laforge at gnumonks.org Sat Apr 9 08:49:41 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 9 Apr 2016 10:49:41 +0200 Subject: osmo-bts-trx: "CHAN RQD: no resources for SDCCH" on master In-Reply-To: References: Message-ID: <20160409084941.GD16522@nataraja> Hi Tom and list, On Fri, Apr 08, 2016 at 03:55:42PM -0700, Tom Tsou wrote: > Hopefully, somebody more familiar than myself with A-bis and related > L1/L2 dependencies can provide some insight on why the above is > happening or where to start debugging. Everything seems fine up and until frame 225, but in frame 226, the BSC is sending another "Set BTS Attributes". This message re-sets a lot of the other managed objects and results in the transceiver (and channels) being disabled again(Frame 230..233), which means the BSC cannot activate any logical channel. "Set BTS Attributes" is originally sent in frame 23, and at the moment Im not quite sure yet why that happens. So basically everythign looks fine and is brought up correctly, including all the channels (aka timeslots), but then one message destroys it all. > I'll be happy to test any subsequent changes or look into specific > parts of the A-bis code. Thanks in advance. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sat Apr 9 10:25:53 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 9 Apr 2016 12:25:53 +0200 Subject: osmo-bts-trx: "CHAN RQD: no resources for SDCCH" on master In-Reply-To: <20160409084941.GD16522@nataraja> References: <20160409084941.GD16522@nataraja> Message-ID: <20160409102553.GE16522@nataraja> On Sat, Apr 09, 2016 at 10:49:41AM +0200, Harald Welte wrote: > "Set BTS Attributes" is originally sent in frame 23, and at the moment > Im not quite sure yet why that happens. Actually, it's more complicated than that The entire block of * Baseband Transceiver: Change Admin State Unlocked + ACK * Baseband Transceiver: Opstart + ACK * Baseband Transceiver: State Chg Event Report Enabled OK * Baseband Transceiver: IPA RSL Connect + ACK happens once at frame 73...84, but then is repeated at frame 212..221. In that second occurrence, it is followed immediatey by the surplus "Set BTS Attributes" in frame 226. There is only a single location in the BSC code where we send a "Change Administrative State Unlocked" for the "Baseband Transceiver" MO, and that is triggered by a Software Activation Report for the Baseband Transceiver from the BTS to BSC, see sw_activ_rep() in bts_ipaccess_nanobts.c, around line 450. However, there is also only a single instance of a "Software Activation Report" for the "Baseband Transceiver" in the protocol trace, and that's in frame 26. So I currently fail to see why it would happen again from frame 212 on. Or rather, why would it happen already in frame 26? According to Chapter Figure 4 of our A-bis/IP protocol specification at http://ftp.osmocom.org/docs/latest/osmobts-abis.pdf the software activated erport should only happen after * the BTS/MO requesting to activate the software (SW Activate Req) * the BSC acknowledging that (SW Activate Req Ack) * the BSC instructing the BTS to activate the software (Activate SW) * the BTS/MO acknowledging that (Activate SW Ack) So the root question is: What is it, that osmo-bts-trx could possibly do to cause this. "oml_mo_tx_sw_act_rep(&trx->bb_transc.mo);" is what sends the software activation report on the baseband transceiver. Looking at the got log, the above function call of oml_mo_tx_sw_act_rep() for the baseband transceiver was always sent unconditionally from within check_tranceiver_availability() even in Jolly's original osmo-bts-trx code from February 2013, see commit acc71ffb4b61b3354bbb2fa14981e4e6a46946e6. THe code even states that iti s a HACK and it should only be done once we receive CLOCK indications from osmo-trx. However, even that is wrong, as CLOCK is already received in Frame 11, too soon to make that a criterion. In the osmo-bts-{sysmo,litecell15,octphy} backends, the related oml_mo_tx_sw_act_rep() is generated from activate_rf_compl_cb(), i.e. after the transceiver hardware has confirmed activation of the radio carrier, which is again the result of asking for activation via l1if_activate_rf(), which in turn is called from info_compl_cb() which is called from l1if_get_info(), which is called from reset_compl_cb(), which is ther result of l1if_reset(), which is called from l1if_open(), which is called from bts_model_phy_link_open(), which is called from main. So we also don't do it properly with regard to the 'software activate request / ... state machine, but it apparently happens in any case at a much later point in the initialization sequence. Summary: * all osmo-bts backends are cheating in terms of OML initialization and don't go through the full sequence * osmo-bts-trx seems to send the sowftware activation report for the baseband transceiver at a much too early point, before other MO's higher up in the hierarchy (BTS MO, Site Manager) MOs have even been started. * osmo-bts-sysmo is "lucky" in that due to the long code path and plenty of L1 interactions before sendding the SW activation report take sufficiently long that all the other initialization has already passed until then. Solution: * OML initialization (the most complex part of Abis) needs to be more properly handled. No part of the code should do something like dynamically sending software activation reports at runtime. In osm-bts-trx, every time 'transceiver_available' goes from 0->1 (which apparently can happen even after start), a software activation report is sent to the BSC. This is wrong. The software is only activated once during boot, and it is activated not before the parent MOs for BTS and Site Manager are enabled. Unrelated to that, osmo-bts-trx desparately needs to avoid the use of global variables. Each gsm_bts_trx / gsm_bts / phy_link / phy_instance has private data store for implementation-specific state. global variables have always been discouraged. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From 246tnt at gmail.com Mon Apr 11 05:05:05 2016 From: 246tnt at gmail.com (Sylvain Munaut) Date: Mon, 11 Apr 2016 07:05:05 +0200 Subject: [PATCH 1/2] Add concolutional code generator for *CCH In-Reply-To: <1459940730-23452-1-git-send-email-msuraev@sysmocom.de> References: <1459940730-23452-1-git-send-email-msuraev@sysmocom.de> Message-ID: On Wed, Apr 6, 2016 at 1:05 PM, wrote: > From: Max > > Move convolutional code for *CCH channels from test to public API > because it's useful not only for testing. Those code are for GSM, I'd say they need to go in libosmogsm. Cheers, Sylvain From aschultz at tpip.net Mon Apr 11 14:10:01 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:10:01 +0200 Subject: [PATCH 07/12] gtp-rtnl: sync GTPA_FLOW nl attribute name from kernel to userspace In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-8-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- libgtnl/include/linux/gtp_nl.h | 2 +- libgtnl/src/gtp-genl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libgtnl/include/linux/gtp_nl.h b/libgtnl/include/linux/gtp_nl.h index a8fdf3a..a1e8ce1 100644 --- a/libgtnl/include/linux/gtp_nl.h +++ b/libgtnl/include/linux/gtp_nl.h @@ -39,7 +39,7 @@ enum gtp_attrs { GTPA_TID, /* 64 bits for GTPv1 */ GTPA_SGSN_ADDRESS, GTPA_MS_ADDRESS, - GTPA_FLOWID, /* only for GTPv0 */ + GTPA_FLOW, /* only for GTPv0 */ GTPA_NET_NS_FD, __GTPA_MAX, }; diff --git a/libgtnl/src/gtp-genl.c b/libgtnl/src/gtp-genl.c index bffa7a5..ddb7cc7 100644 --- a/libgtnl/src/gtp-genl.c +++ b/libgtnl/src/gtp-genl.c @@ -50,7 +50,7 @@ static void gtp_build_payload(struct nlmsghdr *nlh, struct gtp_tunnel *t) mnl_attr_put_u32(nlh, GTPA_SGSN_ADDRESS, t->sgsn_addr.s_addr); mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, t->ms_addr.s_addr); mnl_attr_put_u64(nlh, GTPA_TID, t->tid); - mnl_attr_put_u16(nlh, GTPA_FLOWID, t->flowid); + mnl_attr_put_u16(nlh, GTPA_FLOW, t->flowid); } int gtp_add_tunnel(int genl_id, struct mnl_socket *nl, struct gtp_tunnel *t) -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:10:04 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:10:04 +0200 Subject: [PATCH 10/12] gtp: get started with IPv6 support In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-11-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- gtp.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 125 insertions(+), 27 deletions(-) diff --git a/gtp.c b/gtp.c index 457587e..48e98d8 100644 --- a/gtp.c +++ b/gtp.c @@ -452,6 +452,21 @@ ip4_route_output_gtp(struct net *net, struct flowi4 *fl4, return ip_route_output_key(net, fl4); } +static struct dst_entry * +ip6_route_output_gtp(struct net *net, struct flowi6 *fl6, + const struct sock *sk, + struct in6_addr *daddr) +{ + memset(fl6, 0, sizeof(*fl6)); + fl6->flowi6_oif = sk->sk_bound_dev_if; + fl6->daddr = *daddr; + fl6->saddr = inet6_sk(sk)->saddr; + fl6->flowi6_tos = RT_CONN_FLAGS(sk); + fl6->flowi6_proto = sk->sk_protocol; + + return ip6_route_output(net, NULL, fl6); +} + static inline void gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) { @@ -524,8 +539,12 @@ struct gtp_pktinfo { }; union { struct flowi4 fl4; + struct flowi6 fl6; + }; + union { + struct rtable *rt; + struct dst_entry *ndst; }; - struct rtable *rt; struct pdp_ctx *pctx; struct net_device *dev; }; @@ -634,11 +653,101 @@ err: return -EBADMSG; } +static inline void +gtp_set_pktinfo_ipv6(struct gtp_pktinfo *pktinfo, struct sock *sk, + struct ipv6hdr *ip6h, + struct pdp_ctx *pctx, struct dst_entry *ndst, + struct flowi6 *fl6, struct net_device *dev) +{ + pktinfo->sk = sk; + pktinfo->ip6h = ip6h; + pktinfo->pctx = pctx; + pktinfo->ndst = ndst; + pktinfo->fl6 = *fl6; + pktinfo->dev = dev; +} + static int gtp_ip6_prepare_xmit(struct sk_buff *skb, struct net_device *dev, struct gtp_pktinfo *pktinfo) { - /* TODO IPV6 support */ + struct gtp_instance *gti = netdev_priv(dev); + struct sock *sk; + struct ipv6hdr *ipv6h; + struct pdp_ctx *pctx; + struct dst_entry *ndst; + struct flowi6 fl6; + int mtu; + + /* Read the IP destination address and resolve the PDP context. + * Prepend PDP header with TEI/TID from PDP ctx. + */ + ipv6h = ipv6_hdr(skb); + pctx = ipv6_pdp_find(gti, &ipv6h->daddr); + if (!pctx) { + netdev_dbg(dev, "no PDP ctx found for this packet, skip\n"); + return -ENOENT; + } + netdev_dbg(dev, "found PDP context %p\n", pctx); + + /* Obtain route for the new encapsulated GTP packet */ + switch (pctx->gtp_version) { + case GTP_V0: + sk = gti->sock0->sk; + break; + case GTP_V1: + sk = gti->sock1u->sk; + break; + default: + return -ENOENT; + } + + ndst = ip6_route_output_gtp(sock_net(sk), &fl6, + gti->sock0->sk, + &pctx->sgsn_addr.ip6); + if (IS_ERR(ndst)) { + netdev_dbg(dev, "no route to SSGN %pI6\n", + &pctx->sgsn_addr.ip6.s6_addr); + dev->stats.tx_carrier_errors++; + goto err; + } + + /* There is a routing loop */ + if (ndst->dev == dev) { + netdev_dbg(dev, "circular route to SSGN %pI6\n", + &pctx->sgsn_addr.ip6); + dev->stats.collisions++; + goto err_dst; + } + + skb_dst_drop(skb); + + mtu = dst_mtu(ndst) - dev->hard_header_len - + sizeof(struct ipv6hdr) - sizeof(struct udphdr); + switch (pctx->gtp_version) { + case GTP_V0: + mtu -= sizeof(struct gtp0_header); + break; + case GTP_V1: + mtu -= sizeof(struct gtp1_header); + break; + } + ndst->ops->update_pmtu(ndst, NULL, skb, mtu); + + if (!skb_is_gso(skb) && skb->len > mtu) { + netdev_dbg(dev, "packet too big, fragmentation needed\n"); + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); + goto err_dst; + } + + gtp_set_pktinfo_ipv6(pktinfo, sk, ipv6h, pctx, ndst, &fl6, dev); + return 0; +err_dst: + dst_release(ndst); +err: + return -EBADMSG; } static inline int @@ -657,15 +766,23 @@ gtp_udp_tunnel_xmit(struct sk_buff *skb, __be16 port, } static inline int -gtp_ip6tunnel_xmit(struct sk_buff *skb, struct gtp_pktinfo *pktinfo) +gtp_ip6tunnel_xmit(struct sk_buff *skb, __be16 port, + struct gtp_pktinfo *pktinfo) { - /* TODO IPV6 support */ + netdev_dbg(pktinfo->dev, "gtp -> IP src: %pI6 dst: %pI6\n", + &pktinfo->ip6h->saddr, &pktinfo->ip6h->daddr); + + return udp_tunnel6_xmit_skb(pktinfo->ndst, pktinfo->sk, skb, + pktinfo->ndst->dev, + &pktinfo->fl6.saddr, + &pktinfo->fl6.daddr, + 0, + ip6_dst_hoplimit(pktinfo->ndst), + port, port, false); } static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) { - struct udphdr *uh; - unsigned int payload_len; struct gtp_pktinfo pktinfo; unsigned int proto = ntohs(skb->protocol); int gtph_len, err = -EINVAL; @@ -713,28 +830,9 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) case ETH_P_IP: err = gtp_udp_tunnel_xmit(skb, gtph_port, &pktinfo); break; - case ETH_P_IPV6: - /* Annotate length of the encapsulated packet */ - payload_len = skb->len; - - /* Push down and install the UDP header. */ - skb_push(skb, sizeof(struct udphdr)); - skb_reset_transport_header(skb); - - uh = udp_hdr(skb); - - uh->source = uh->dest = gtph_port; - uh->len = htons(sizeof(struct udphdr) + payload_len + gtph_len); - uh->check = 0; - netdev_dbg(dev, "gtp -> UDP src: %u dst: %u (len %u)\n", - ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); - - nf_reset(skb); - - netdev_dbg(dev, "Good, now packet leaving from GGSN to SGSN\n"); - - err = gtp_ip6tunnel_xmit(skb, &pktinfo); + case ETH_P_IPV6: + err = gtp_ip6tunnel_xmit(skb, gtph_port, &pktinfo); break; } -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:10:05 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:10:05 +0200 Subject: [PATCH 11/12] list Andreas Schultz as author In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-12-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- gtp.c | 1 + libgtnl/AUTHORS | 1 + 2 files changed, 2 insertions(+) diff --git a/gtp.c b/gtp.c index 48e98d8..f569d62 100644 --- a/gtp.c +++ b/gtp.c @@ -3,6 +3,7 @@ /* (C) 2012-2014 by sysmocom - s.f.m.c. GmbH * Author: Harald Welte * Pablo Neira Ayuso + * Andreas Schultz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/libgtnl/AUTHORS b/libgtnl/AUTHORS index 7deed5b..649d40b 100644 --- a/libgtnl/AUTHORS +++ b/libgtnl/AUTHORS @@ -1 +1,2 @@ Pablo Neira Ayuso +Andreas Schultz -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:10:00 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:10:00 +0200 Subject: [PATCH 06/12] gtp: Split TID handling for GTPv0 and GTPv1 In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-7-git-send-email-aschultz@tpip.net> GTPv1 tunnel use separate TEI for each direction. Add a union to hold TID for v0 and TEI for v1 separately. Signed-off-by: Andreas Schultz --- gtp.c | 211 +++++++++++++++++++++++++++++++++++---------------------------- gtp_nl.h | 2 + 2 files changed, 118 insertions(+), 95 deletions(-) diff --git a/gtp.c b/gtp.c index bead51f..457587e 100644 --- a/gtp.c +++ b/gtp.c @@ -39,7 +39,17 @@ struct pdp_ctx { struct hlist_node hlist_tid; struct hlist_node hlist_addr; - u64 tid; + union { + uint64_t tid; + struct { + uint64_t tid; + u16 flow; + } v0; + struct { + uint32_t i_tei; + uint32_t o_tei; + } v1; + } u; u8 gtp_version; u16 af; @@ -53,7 +63,6 @@ struct pdp_ctx { struct in_addr ip4; } sgsn_addr; - u16 flow; atomic_t tx_seq; struct rcu_head rcu_head; @@ -113,7 +122,7 @@ static struct pdp_ctx *gtp0_pdp_find(struct gtp_instance *gti, u64 tid) head = >i->tid_hash[gtp0_hashfn(tid) % gti->hash_size]; hlist_for_each_entry_rcu(pdp, head, hlist_tid) { - if (pdp->gtp_version == GTP_V0 && pdp->tid == tid) + if (pdp->gtp_version == GTP_V0 && pdp->u.v0.tid == tid) return pdp; } @@ -129,7 +138,7 @@ static struct pdp_ctx *gtp1_pdp_find(struct gtp_instance *gti, u32 tid) head = >i->tid_hash[gtp1u_hashfn(tid) % gti->hash_size]; hlist_for_each_entry_rcu(pdp, head, hlist_tid) { - if (pdp->gtp_version == GTP_V1 && pdp->tid == tid) + if (pdp->gtp_version == GTP_V1 && pdp->u.v1.i_tei == tid) return pdp; } @@ -456,10 +465,10 @@ gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) gtp0->type = GTP_TPDU; gtp0->length = htons(payload_len); gtp0->seq = htons((atomic_inc_return(&pctx->tx_seq)-1) % 0xffff); - gtp0->flow = htons(pctx->flow); + gtp0->flow = htons(pctx->u.v0.flow); gtp0->number = 0xFF; gtp0->spare[0] = gtp0->spare[1] = gtp0->spare[2] = 0xFF; - gtp0->tid = cpu_to_be64(pctx->tid); + gtp0->tid = cpu_to_be64(pctx->u.v0.tid); } static inline void @@ -480,7 +489,7 @@ gtp1_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) gtp1->flags = 0x38; /* V1, GTP-non-prime */ gtp1->type = GTP_TPDU; gtp1->length = htons(payload_len); - gtp1->tid = htonl((u32)pctx->tid); + gtp1->tid = htonl(pctx->u.v1.o_tei); /* TODO: Suppport for extension header, sequence number and N-PDU. * Update the length field if any of them is available. @@ -1021,43 +1030,45 @@ static struct net_device *gtp_find_dev(struct net *net, int ifindex) return NULL; } -static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) +static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) { - struct gtp_instance *gti = netdev_priv(dev); - struct pdp_ctx *pctx; - u16 flow = 0; - u32 gtp_version, sgsn_addr, ms_addr, hash_ms, hash_tid; - u64 tid; - bool found = false; + pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); + pctx->af = AF_INET; + pctx->sgsn_addr.ip4.s_addr = + nla_get_u32(info->attrs[GTPA_SGSN_ADDRESS]); + pctx->ms_addr.ip4.s_addr = + nla_get_u32(info->attrs[GTPA_MS_ADDRESS]); - gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); - switch (gtp_version) { + switch (pctx->gtp_version) { case GTP_V0: - case GTP_V1: + + /* According to TS 09.60, sections 7.5.1 and 7.5.2, the flow + * label needs to be the same for uplink and downlink packets, + * so let's annotate this. + */ + pctx->u.v0.tid = nla_get_u64(info->attrs[GTPA_TID]); + pctx->u.v0.flow = nla_get_u16(info->attrs[GTPA_FLOW]); break; - default: - return -EINVAL; - } - tid = nla_get_u64(info->attrs[GTPA_TID]); - /* GTPv1 allows 32-bits tunnel IDs */ - if (gtp_version == GTP_V1 && tid > UINT_MAX) - return -EINVAL; + case GTP_V1: + pctx->u.v1.i_tei = nla_get_u32(info->attrs[GTPA_I_TEI]); + pctx->u.v1.o_tei = nla_get_u32(info->attrs[GTPA_O_TEI]); - /* According to TS 09.60, sections 7.5.1 and 7.5.2, the flow label - * needs to be the same for uplink and downlink packets, so let's - * annotate this. - */ - if (gtp_version == GTP_V0) { - if (!info->attrs[GTPA_FLOW]) - return -EINVAL; + break; - flow = nla_get_u16(info->attrs[GTPA_FLOW]); + default: + break; } +} - sgsn_addr = nla_get_u32(info->attrs[GTPA_SGSN_ADDRESS]); - ms_addr = nla_get_u32(info->attrs[GTPA_MS_ADDRESS]); +static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) +{ + struct gtp_instance *gti = netdev_priv(dev); + struct pdp_ctx *pctx; + u32 ms_addr, hash_ms, hash_tid = 0; + bool found = false; + ms_addr = nla_get_u32(info->attrs[GTPA_MS_ADDRESS]); hash_ms = ipv4_hashfn(ms_addr) % gti->hash_size; hlist_for_each_entry_rcu(pctx, >i->addr_hash[hash_ms], hlist_addr) { @@ -1073,47 +1084,50 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE) return -EOPNOTSUPP; - pctx->af = AF_INET; - pctx->gtp_version = gtp_version; - pctx->tid = tid; - pctx->sgsn_addr.ip4.s_addr = sgsn_addr; - pctx->ms_addr.ip4.s_addr = ms_addr; + ipv4_pdp_fill(pctx, info); - netdev_dbg(dev, "update tunnel id = %llx (pdp %p)\n", - tid, pctx); + if (pctx->gtp_version == GTP_V0) + netdev_dbg(dev, "GTPv0-U: update tunnel id = %llx (pdp %p)\n", + pctx->u.v0.tid, pctx); + else if (pctx->gtp_version == GTP_V1) + netdev_dbg(dev, "GTPv1-U: update tunnel id = %x/%x (pdp %p)\n", + pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx); return 0; + } pctx = kmalloc(sizeof(struct pdp_ctx), GFP_KERNEL); if (pctx == NULL) return -ENOMEM; - pctx->af = AF_INET; - pctx->gtp_version = gtp_version; - pctx->tid = tid; - pctx->sgsn_addr.ip4.s_addr = sgsn_addr; - pctx->ms_addr.ip4.s_addr = ms_addr; - pctx->flow = flow; + ipv4_pdp_fill(pctx, info); atomic_set(&pctx->tx_seq, 0); - switch (gtp_version) { + switch (pctx->gtp_version) { case GTP_V0: /* TS 09.60: "The flow label identifies unambiguously a GTP * flow.". We use the tid for this instead, I cannot find a * situation in which this doesn't unambiguosly identify the * PDP context. */ - hash_tid = gtp0_hashfn(tid) % gti->hash_size; + hash_tid = gtp0_hashfn(pctx->u.v0.tid) % gti->hash_size; break; + case GTP_V1: - hash_tid = gtp1u_hashfn(tid) % gti->hash_size; + hash_tid = gtp1u_hashfn(pctx->u.v1.i_tei) % gti->hash_size; break; } + hlist_add_head_rcu(&pctx->hlist_addr, >i->addr_hash[hash_ms]); hlist_add_head_rcu(&pctx->hlist_tid, >i->tid_hash[hash_tid]); - netdev_dbg(dev, "adding tunnel id = %llx (pdp %p)\n", tid, pctx); + if (pctx->gtp_version == GTP_V0) + netdev_dbg(dev, "GTPv0-U: adding tunnel id = %llx (pdp %p)\n", + pctx->u.v0.tid, pctx); + else if (pctx->gtp_version == GTP_V1) + netdev_dbg(dev, "GTPv1-U: adding tunnel id = %x/%x (pdp %p)\n", + pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx); return 0; } @@ -1126,9 +1140,25 @@ static int gtp_genl_tunnel_new(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[GTPA_VERSION] || !info->attrs[GTPA_LINK] || !info->attrs[GTPA_SGSN_ADDRESS] || - !info->attrs[GTPA_MS_ADDRESS] || - !info->attrs[GTPA_TID]) + !info->attrs[GTPA_MS_ADDRESS]) + return -EINVAL; + + switch (nla_get_u32(info->attrs[GTPA_VERSION])) { + case GTP_V0: + if (!info->attrs[GTPA_TID] || + !info->attrs[GTPA_FLOW]) + return -EINVAL; + break; + + case GTP_V1: + if (!info->attrs[GTPA_I_TEI] || + !info->attrs[GTPA_O_TEI]) + return -EINVAL; + break; + + default: return -EINVAL; + } net = gtp_genl_get_net(sock_net(skb->sk), info->attrs); if (IS_ERR(net)) @@ -1148,28 +1178,9 @@ static int gtp_genl_tunnel_delete(struct sk_buff *skb, struct genl_info *info) struct gtp_instance *gti; struct net_device *dev; struct pdp_ctx *pctx; - u32 gtp_version; - u64 tid; if (!info->attrs[GTPA_VERSION] || - !info->attrs[GTPA_LINK] || - !info->attrs[GTPA_SGSN_ADDRESS] || - !info->attrs[GTPA_MS_ADDRESS] || - !info->attrs[GTPA_TID]) - return -EINVAL; - - gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]); - switch (gtp_version) { - case GTP_V0: - case GTP_V1: - break; - default: - return -EINVAL; - } - - tid = nla_get_u64(info->attrs[GTPA_TID]); - /* GTPv1 allows 32-bits tunnel IDs */ - if (gtp_version == GTP_V1 && tid > UINT_MAX) + !info->attrs[GTPA_LINK]) return -EINVAL; net = gtp_genl_get_net(sock_net(skb->sk), info->attrs); @@ -1183,20 +1194,32 @@ static int gtp_genl_tunnel_delete(struct sk_buff *skb, struct genl_info *info) gti = netdev_priv(dev); - switch (gtp_version) { + switch (nla_get_u32(info->attrs[GTPA_VERSION])) { case GTP_V0: + if (!info->attrs[GTPA_TID]) + return -EINVAL; pctx = gtp0_pdp_find(gti, nla_get_u64(info->attrs[GTPA_TID])); break; + case GTP_V1: - pctx = gtp1_pdp_find(gti, nla_get_u64(info->attrs[GTPA_TID])); + if (!info->attrs[GTPA_I_TEI]) + return -EINVAL; + pctx = gtp1_pdp_find(gti, nla_get_u64(info->attrs[GTPA_I_TEI])); break; + + default: + return -EINVAL; } if (pctx == NULL) return -ENOENT; - netdev_dbg(dev, "deleting tunnel with ID %lld\n", - (unsigned long long) nla_get_u64(info->attrs[GTPA_TID])); + if (pctx->gtp_version == GTP_V0) + netdev_dbg(dev, "GTPv0-U: deleting tunnel id = %llx (pdp %p)\n", + pctx->u.v0.tid, pctx); + else if (pctx->gtp_version == GTP_V1) + netdev_dbg(dev, "GTPv1-U: deleting tunnel id = %x/%x (pdp %p)\n", + pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx); hlist_del_rcu(&pctx->hlist_tid); hlist_del_rcu(&pctx->hlist_addr); @@ -1228,9 +1251,12 @@ gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) || nla_put_u32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr.ip4.s_addr) || nla_put_u32(skb, GTPA_MS_ADDRESS, pctx->ms_addr.ip4.s_addr) || - nla_put_u64(skb, GTPA_TID, pctx->tid) || (pctx->gtp_version == GTP_V0 && - nla_put_u16(skb, GTPA_FLOW, pctx->flow))) + nla_put_u64(skb, GTPA_TID, pctx->u.v0.tid) && + nla_put_u16(skb, GTPA_FLOW, pctx->u.v0.flow)) || + (pctx->gtp_version == GTP_V1 && + nla_put_u32(skb, GTPA_I_TEI, pctx->u.v1.i_tei) && + nla_put_u32(skb, GTPA_O_TEI, pctx->u.v1.o_tei))) goto nla_put_failure; genlmsg_end(skb, genlh); @@ -1277,23 +1303,16 @@ static int gtp_genl_tunnel_get(struct sk_buff *skb, struct genl_info *info) gti = netdev_priv(dev); rcu_read_lock(); - if (info->attrs[GTPA_TID]) { + if (gtp_version == GTP_V0 && + info->attrs[GTPA_TID]) { u64 tid = nla_get_u64(info->attrs[GTPA_TID]); - /* GTPv1 allows 32-bits tunnel IDs */ - if (gtp_version == GTP_V1 && tid > UINT_MAX) { - err = -EINVAL; - goto err_unlock; - } + pctx = gtp0_pdp_find(gti, tid); + } else if (gtp_version == GTP_V1 && + info->attrs[GTPA_I_TEI]) { + u32 tid = nla_get_u32(info->attrs[GTPA_I_TEI]); - switch (gtp_version) { - case GTP_V0: - pctx = gtp0_pdp_find(gti, tid); - break; - case GTP_V1: - pctx = gtp1_pdp_find(gti, tid); - break; - } + pctx = gtp1_pdp_find(gti, tid); } else if (info->attrs[GTPA_MS_ADDRESS]) { u32 ip = nla_get_u32(info->attrs[GTPA_MS_ADDRESS]); @@ -1347,7 +1366,7 @@ gtp_genl_tunnel_dump(struct sk_buff *skb, struct netlink_callback *cb) for (i = k; i < gti->hash_size; i++) { hlist_for_each_entry_rcu(pctx, >i->tid_hash[i], hlist_tid) { - if (tid && tid != pctx->tid) + if (tid && tid != pctx->u.tid) continue; else tid = 0; @@ -1358,7 +1377,7 @@ gtp_genl_tunnel_dump(struct sk_buff *skb, struct netlink_callback *cb) cb->nlh->nlmsg_type, pctx); if (ret < 0) { cb->args[0] = i; - cb->args[1] = pctx->tid; + cb->args[1] = pctx->u.tid; cb->args[2] = (unsigned long)gti; goto out; } @@ -1378,6 +1397,8 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = { [GTPA_MS_ADDRESS] = { .type = NLA_NESTED, }, [GTPA_FLOW] = { .type = NLA_U16, }, [GTPA_NET_NS_FD] = { .type = NLA_U32, }, + [GTPA_I_TEI] = { .type = NLA_U32, }, + [GTPA_O_TEI] = { .type = NLA_U32, }, }; static const struct genl_ops gtp_genl_ops[] = { diff --git a/gtp_nl.h b/gtp_nl.h index c20666d..6dc768f 100644 --- a/gtp_nl.h +++ b/gtp_nl.h @@ -41,6 +41,8 @@ enum gtp_attrs { GTPA_MS_ADDRESS, GTPA_FLOW, GTPA_NET_NS_FD, + GTPA_I_TEI, + GTPA_O_TEI, __GTPA_MAX, }; #define GTPA_MAX (__GTPA_MAX + 1) -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:09:54 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:09:54 +0200 Subject: [PATCH 00/12] GTP kernel support Message-ID: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Hi, Here are the not yet merged pieces of the kernel GTP support. I tried to address all the comment from the previous rounds. After this series has been applied, IPv4 GTP tunnels over IPv4 should be complete. Anything IPv6 still needs work. Regrads Andreas -- Andreas Schultz (12): gtp: select netns based on NL attribute gtp-rtnl: and netns support gtp: add socket destroy handler gtp: replace udp encap setup with setup_udp_tunnel_sock gtp: switch to iptunnel framework and no longer depend on real_dev gtp: Split TID handling for GTPv0 and GTPv1 gtp-rtnl: sync GTPA_FLOW nl attribute name from kernel to userspace gtp-rtnl: real_ifname is not long needed, remove it gtp-rtnl: Split TID handling for GTPv0 and GTPv1 gtp: get started with IPv6 support list Andreas Schultz as author gtp: add support for replacing PDP contexts gtp.c | 669 +++++++++++++++++++++++++-------------- gtp_nl.h | 3 + libgtnl/AUTHORS | 1 + libgtnl/include/libgtpnl/gtp.h | 6 + libgtnl/include/libgtpnl/gtpnl.h | 3 +- libgtnl/include/linux/gtp_nl.h | 5 +- libgtnl/src/gtp-genl.c | 36 ++- libgtnl/src/gtp-rtnl.c | 6 +- libgtnl/src/gtp.c | 44 ++- libgtnl/src/internal.h | 13 +- libgtnl/src/libgtpnl.map | 6 + libgtnl/tools/Makefile.am | 4 +- libgtnl/tools/gtp-link-add.c | 5 +- libgtnl/tools/gtp-tunnel.c | 134 +++++--- libgtnl/tools/gtpnl.c | 35 -- 15 files changed, 642 insertions(+), 328 deletions(-) delete mode 100644 libgtnl/tools/gtpnl.c -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:10:03 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:10:03 +0200 Subject: [PATCH 09/12] gtp-rtnl: Split TID handling for GTPv0 and GTPv1 In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-10-git-send-email-aschultz@tpip.net> GTPv1 tunnel use separate 32bit Tunnel Endpoint Identifier's for each direction while GTPv0 uses only one 64bit Tunnel IDentifier. Signed-off-by: Andreas Schultz --- libgtnl/include/libgtpnl/gtp.h | 4 ++ libgtnl/include/linux/gtp_nl.h | 2 + libgtnl/src/gtp-genl.c | 34 +++++++++-- libgtnl/src/gtp.c | 32 ++++++++-- libgtnl/src/internal.h | 12 +++- libgtnl/src/libgtpnl.map | 4 ++ libgtnl/tools/Makefile.am | 4 +- libgtnl/tools/gtp-tunnel.c | 134 ++++++++++++++++++++++++++++------------- libgtnl/tools/gtpnl.c | 35 ----------- 9 files changed, 172 insertions(+), 89 deletions(-) delete mode 100644 libgtnl/tools/gtpnl.c diff --git a/libgtnl/include/libgtpnl/gtp.h b/libgtnl/include/libgtpnl/gtp.h index fa09d2a..521339d 100644 --- a/libgtnl/include/libgtpnl/gtp.h +++ b/libgtnl/include/libgtpnl/gtp.h @@ -14,6 +14,8 @@ void gtp_tunnel_set_ms_ip4(struct gtp_tunnel *t, struct in_addr *ms_addr); void gtp_tunnel_set_sgsn_ip4(struct gtp_tunnel *t, struct in_addr *sgsn_addr); void gtp_tunnel_set_version(struct gtp_tunnel *t, uint32_t version); void gtp_tunnel_set_tid(struct gtp_tunnel *t, uint64_t tid); +void gtp_tunnel_set_i_tei(struct gtp_tunnel *t, uint32_t i_tei); +void gtp_tunnel_set_o_tei(struct gtp_tunnel *t, uint32_t o_tei); void gtp_tunnel_set_flowid(struct gtp_tunnel *t, uint16_t flowid); const int gtp_tunnel_get_ifns(struct gtp_tunnel *t); @@ -22,6 +24,8 @@ const struct in_addr *gtp_tunnel_get_ms_ip4(struct gtp_tunnel *t); const struct in_addr *gtp_tunnel_get_sgsn_ip4(struct gtp_tunnel *t); int gtp_tunnel_get_version(struct gtp_tunnel *t); uint64_t gtp_tunnel_get_tid(struct gtp_tunnel *t); +uint32_t gtp_tunnel_get_i_tei(struct gtp_tunnel *t); +uint32_t gtp_tunnel_get_o_tei(struct gtp_tunnel *t); uint16_t gtp_tunnel_get_flowid(struct gtp_tunnel *t); #endif diff --git a/libgtnl/include/linux/gtp_nl.h b/libgtnl/include/linux/gtp_nl.h index a1e8ce1..deb92cf 100644 --- a/libgtnl/include/linux/gtp_nl.h +++ b/libgtnl/include/linux/gtp_nl.h @@ -41,6 +41,8 @@ enum gtp_attrs { GTPA_MS_ADDRESS, GTPA_FLOW, /* only for GTPv0 */ GTPA_NET_NS_FD, + GTPA_I_TEI, + GTPA_O_TEI, __GTPA_MAX, }; #define GTPA_MAX (__GTPA_MAX + 1) diff --git a/libgtnl/src/gtp-genl.c b/libgtnl/src/gtp-genl.c index ddb7cc7..3c7deed 100644 --- a/libgtnl/src/gtp-genl.c +++ b/libgtnl/src/gtp-genl.c @@ -49,8 +49,13 @@ static void gtp_build_payload(struct nlmsghdr *nlh, struct gtp_tunnel *t) mnl_attr_put_u32(nlh, GTPA_LINK, t->ifidx); mnl_attr_put_u32(nlh, GTPA_SGSN_ADDRESS, t->sgsn_addr.s_addr); mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, t->ms_addr.s_addr); - mnl_attr_put_u64(nlh, GTPA_TID, t->tid); - mnl_attr_put_u16(nlh, GTPA_FLOW, t->flowid); + if (t->gtp_version == GTP_V0) { + mnl_attr_put_u64(nlh, GTPA_TID, t->u.v0.tid); + mnl_attr_put_u16(nlh, GTPA_FLOW, t->u.v0.flowid); + } else if (t->gtp_version == GTP_V1) { + mnl_attr_put_u32(nlh, GTPA_I_TEI, t->u.v1.i_tei); + mnl_attr_put_u32(nlh, GTPA_O_TEI, t->u.v1.o_tei); + } } int gtp_add_tunnel(int genl_id, struct mnl_socket *nl, struct gtp_tunnel *t) @@ -95,7 +100,15 @@ EXPORT_SYMBOL(gtp_del_tunnel); struct gtp_pdp { uint32_t version; - uint64_t tid; + union { + struct { + uint64_t tid; + } v0; + struct { + uint32_t i_tei; + uint32_t o_tei; + } v1; + } u; struct in_addr sgsn_addr; struct in_addr ms_addr; }; @@ -115,6 +128,8 @@ static int genl_gtp_validate_cb(const struct nlattr *attr, void *data) return MNL_CB_ERROR; } break; + case GTPA_O_TEI: + case GTPA_I_TEI: case GTPA_SGSN_ADDRESS: case GTPA_MS_ADDRESS: case GTPA_VERSION: @@ -138,7 +153,11 @@ static int genl_gtp_attr_cb(const struct nlmsghdr *nlh, void *data) mnl_attr_parse(nlh, sizeof(*genl), genl_gtp_validate_cb, tb); if (tb[GTPA_TID]) - pdp.tid = mnl_attr_get_u64(tb[GTPA_TID]); + pdp.u.v0.tid = mnl_attr_get_u64(tb[GTPA_TID]); + if (tb[GTPA_I_TEI]) + pdp.u.v1.i_tei = mnl_attr_get_u32(tb[GTPA_I_TEI]); + if (tb[GTPA_O_TEI]) + pdp.u.v1.o_tei = mnl_attr_get_u32(tb[GTPA_O_TEI]); if (tb[GTPA_SGSN_ADDRESS]) { pdp.sgsn_addr.s_addr = mnl_attr_get_u32(tb[GTPA_SGSN_ADDRESS]); @@ -151,7 +170,12 @@ static int genl_gtp_attr_cb(const struct nlmsghdr *nlh, void *data) } printf("version %u ", pdp.version); - printf("tid %"PRIu64" ms_addr %s ", pdp.tid, inet_ntoa(pdp.sgsn_addr)); + if (pdp.version == GTP_V0) + printf("tid %"PRIu64" ms_addr %s ", + pdp.u.v0.tid, inet_ntoa(pdp.sgsn_addr)); + else if (pdp.version == GTP_V1) + printf("tei %u/%u ms_addr %s ", pdp.u.v1.i_tei, + pdp.u.v1.o_tei, inet_ntoa(pdp.sgsn_addr)); printf("sgsn_addr %s\n", inet_ntoa(pdp.ms_addr)); return MNL_CB_OK; diff --git a/libgtnl/src/gtp.c b/libgtnl/src/gtp.c index 6e3d473..bb5eaaf 100644 --- a/libgtnl/src/gtp.c +++ b/libgtnl/src/gtp.c @@ -71,16 +71,28 @@ EXPORT_SYMBOL(gtp_tunnel_set_version); void gtp_tunnel_set_tid(struct gtp_tunnel *t, uint64_t tid) { - t->tid = tid; + t->u.v0.tid = tid; } EXPORT_SYMBOL(gtp_tunnel_set_tid); void gtp_tunnel_set_flowid(struct gtp_tunnel *t, uint16_t flowid) { - t->flowid = flowid; + t->u.v0.flowid = flowid; } EXPORT_SYMBOL(gtp_tunnel_set_flowid); +void gtp_tunnel_set_i_tei(struct gtp_tunnel *t, uint32_t i_tei) +{ + t->u.v1.i_tei = i_tei; +} +EXPORT_SYMBOL(gtp_tunnel_set_i_tei); + +void gtp_tunnel_set_o_tei(struct gtp_tunnel *t, uint32_t o_tei) +{ + t->u.v1.o_tei = o_tei; +} +EXPORT_SYMBOL(gtp_tunnel_set_o_tei); + const int gtp_tunnel_get_ifns(struct gtp_tunnel *t) { return t->ifns; @@ -113,12 +125,24 @@ EXPORT_SYMBOL(gtp_tunnel_get_version); uint64_t gtp_tunnel_get_tid(struct gtp_tunnel *t) { - return t->tid; + return t->u.v0.tid; } EXPORT_SYMBOL(gtp_tunnel_get_tid); uint16_t gtp_tunnel_get_flowid(struct gtp_tunnel *t) { - return t->flowid; + return t->u.v0.flowid; } EXPORT_SYMBOL(gtp_tunnel_get_flowid); + +uint32_t gtp_tunnel_get_i_tei(struct gtp_tunnel *t) +{ + return t->u.v1.i_tei; +} +EXPORT_SYMBOL(gtp_tunnel_get_i_tei); + +uint32_t gtp_tunnel_get_o_tei(struct gtp_tunnel *t) +{ + return t->u.v1.o_tei; +} +EXPORT_SYMBOL(gtp_tunnel_get_o_tei); diff --git a/libgtnl/src/internal.h b/libgtnl/src/internal.h index 68f0135..1754e3b 100644 --- a/libgtnl/src/internal.h +++ b/libgtnl/src/internal.h @@ -17,9 +17,17 @@ struct gtp_tunnel { uint32_t ifidx; struct in_addr ms_addr; struct in_addr sgsn_addr; - uint64_t tid; - uint16_t flowid; int gtp_version; + union { + struct { + uint64_t tid; + uint16_t flowid; + } v0; + struct { + uint32_t i_tei; + uint32_t o_tei; + } v1; + } u; }; #endif diff --git a/libgtnl/src/libgtpnl.map b/libgtnl/src/libgtpnl.map index 2368467..9ca83c7 100644 --- a/libgtnl/src/libgtpnl.map +++ b/libgtnl/src/libgtpnl.map @@ -22,6 +22,8 @@ global: gtp_tunnel_set_version; gtp_tunnel_set_tid; gtp_tunnel_set_flowid; + gtp_tunnel_set_i_tei; + gtp_tunnel_set_o_tei; gtp_tunnel_get_ifns; gtp_tunnel_get_ifidx; gtp_tunnel_get_ms_ip4; @@ -29,6 +31,8 @@ global: gtp_tunnel_get_version; gtp_tunnel_get_tid; gtp_tunnel_get_flowid; + gtp_tunnel_get_i_tei; + gtp_tunnel_get_o_tei; local: *; }; diff --git a/libgtnl/tools/Makefile.am b/libgtnl/tools/Makefile.am index 7880f3c..89dca32 100644 --- a/libgtnl/tools/Makefile.am +++ b/libgtnl/tools/Makefile.am @@ -3,8 +3,8 @@ include $(top_srcdir)/Make_global.am check_PROGRAMS = gtp-link-add \ gtp-tunnel -gtp_link_add_SOURCES = gtp-link-add.c gtpnl.c +gtp_link_add_SOURCES = gtp-link-add.c gtp_link_add_LDADD = ../src/libgtpnl.la ${LIBMNL_LIBS} -gtp_tunnel_SOURCES = gtp-tunnel.c gtpnl.c +gtp_tunnel_SOURCES = gtp-tunnel.c gtp_tunnel_LDADD = ../src/libgtpnl.la ${LIBMNL_LIBS} diff --git a/libgtnl/tools/gtp-tunnel.c b/libgtnl/tools/gtp-tunnel.c index 9c52a27..bb12c3f 100644 --- a/libgtnl/tools/gtp-tunnel.c +++ b/libgtnl/tools/gtp-tunnel.c @@ -28,71 +28,91 @@ #include #include #include +#include +#include #include #include #include +#include #include +static void add_usage(const char *name) +{ + printf("%s add \n", + name); + printf("%s add \n", + name); +} + static int add_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) { + struct gtp_tunnel *t; uint32_t gtp_ifidx; struct in_addr ms, sgsn; - struct nlmsghdr *nlh; - char buf[MNL_SOCKET_BUFFER_SIZE]; - uint32_t seq = time(NULL), gtp_version; + uint32_t gtp_version; + int optidx; - if (argc != 7) { - printf("%s add \n", - argv[0]); + if (argc < 7 || argc > 8) { + add_usage(argv[0]); return EXIT_FAILURE; } - gtp_ifidx = if_nametoindex(argv[2]); + + t = gtp_tunnel_alloc(); + optidx = 2; + + gtp_ifidx = if_nametoindex(argv[optidx]); if (gtp_ifidx == 0) { - fprintf(stderr, "wrong GTP interface %s\n", argv[2]); + fprintf(stderr, "wrong GTP interface %s\n", argv[optidx]); return EXIT_FAILURE; } + gtp_tunnel_set_ifidx(t, gtp_ifidx); - if (inet_aton(argv[5], &ms) < 0) { - perror("bad address for ms"); - exit(EXIT_FAILURE); - } - - if (inet_aton(argv[6], &sgsn) < 0) { - perror("bad address for sgsn"); - exit(EXIT_FAILURE); - } + optidx++; - if (strcmp(argv[3], "v0") == 0) + if (strcmp(argv[optidx], "v0") == 0) gtp_version = GTP_V0; - else if (strcmp(argv[3], "v1") == 0) + else if (strcmp(argv[optidx], "v1") == 0) gtp_version = GTP_V1; else { fprintf(stderr, "wrong GTP version %s, use v0 or v1\n", - argv[3]); + argv[optidx]); return EXIT_FAILURE; } + gtp_tunnel_set_version(t, gtp_version); - nlh = genl_nlmsg_build_hdr(buf, genl_id, NLM_F_EXCL | NLM_F_ACK, ++seq, - GTP_CMD_TUNNEL_NEW); - gtp_build_payload(nlh, atoi(argv[4]), gtp_ifidx, sgsn.s_addr, - ms.s_addr, gtp_version); + if (gtp_version == GTP_V0) + gtp_tunnel_set_tid(t, atoi(argv[optidx++])); + else if (gtp_version == GTP_V1) { + gtp_tunnel_set_i_tei(t, atoi(argv[optidx++])); + gtp_tunnel_set_o_tei(t, atoi(argv[optidx++])); + } - if (genl_socket_talk(nl, nlh, seq, NULL, NULL) < 0) - perror("genl_socket_talk"); + if (inet_aton(argv[optidx++], &ms) < 0) { + perror("bad address for ms"); + exit(EXIT_FAILURE); + } + gtp_tunnel_set_ms_ip4(t, &ms); + + if (inet_aton(argv[optidx++], &sgsn) < 0) { + perror("bad address for sgsn"); + exit(EXIT_FAILURE); + } + gtp_tunnel_set_sgsn_ip4(t, &sgsn); + + gtp_add_tunnel(genl_id, nl, t); + gtp_tunnel_free(t); return 0; } static int del_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) { + struct gtp_tunnel *t; uint32_t gtp_ifidx; - char buf[MNL_SOCKET_BUFFER_SIZE]; - struct nlmsghdr *nlh; - uint32_t seq = time(NULL); if (argc != 5) { printf("%s add \n", @@ -100,21 +120,44 @@ del_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) return EXIT_FAILURE; } - gtp_ifidx = if_nametoindex(argv[2]); + t = gtp_tunnel_alloc(); - nlh = genl_nlmsg_build_hdr(buf, genl_id, NLM_F_ACK, ++seq, - GTP_CMD_TUNNEL_DELETE); - gtp_build_payload(nlh, atoi(argv[4]), gtp_ifidx, 0, 0, atoi(argv[3])); + gtp_ifidx = if_nametoindex(argv[2]); + if (gtp_ifidx == 0) { + fprintf(stderr, "wrong GTP interface %s\n", argv[2]); + return EXIT_FAILURE; + } + gtp_tunnel_set_ifidx(t, gtp_ifidx); + + if (strcmp(argv[3], "v0") == 0) { + gtp_tunnel_set_version(t, GTP_V0); + gtp_tunnel_set_tid(t, atoi(argv[4])); + } else if (strcmp(argv[3], "v1") == 0) { + gtp_tunnel_set_version(t, GTP_V1); + gtp_tunnel_set_i_tei(t, atoi(argv[4])); + } else { + fprintf(stderr, "wrong GTP version %s, use v0 or v1\n", + argv[3]); + return EXIT_FAILURE; + } - if (genl_socket_talk(nl, nlh, seq, NULL, NULL) < 0) - perror("genl_socket_talk"); + gtp_del_tunnel(genl_id, nl, t); + gtp_tunnel_free(t); return 0; } struct gtp_pdp { uint32_t version; - uint64_t tid; + union { + struct { + uint64_t tid; + } v0; + struct { + uint32_t i_tei; + uint32_t o_tei; + } v1; + } u; struct in_addr sgsn_addr; struct in_addr ms_addr; }; @@ -134,6 +177,8 @@ static int genl_gtp_validate_cb(const struct nlattr *attr, void *data) return MNL_CB_ERROR; } break; + case GTPA_I_TEI: + case GTPA_O_TEI: case GTPA_SGSN_ADDRESS: case GTPA_MS_ADDRESS: case GTPA_VERSION: @@ -152,12 +197,16 @@ static int genl_gtp_validate_cb(const struct nlattr *attr, void *data) static int genl_gtp_attr_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[GTPA_MAX + 1] = {}; - struct gtp_pdp pdp; + struct gtp_pdp pdp = {}; struct genlmsghdr *genl; mnl_attr_parse(nlh, sizeof(*genl), genl_gtp_validate_cb, tb); if (tb[GTPA_TID]) - pdp.tid = mnl_attr_get_u64(tb[GTPA_TID]); + pdp.u.v0.tid = mnl_attr_get_u64(tb[GTPA_TID]); + if (tb[GTPA_I_TEI]) + pdp.u.v1.i_tei = mnl_attr_get_u32(tb[GTPA_I_TEI]); + if (tb[GTPA_O_TEI]) + pdp.u.v1.o_tei = mnl_attr_get_u32(tb[GTPA_O_TEI]); if (tb[GTPA_SGSN_ADDRESS]) { pdp.sgsn_addr.s_addr = mnl_attr_get_u32(tb[GTPA_SGSN_ADDRESS]); @@ -170,7 +219,12 @@ static int genl_gtp_attr_cb(const struct nlmsghdr *nlh, void *data) } printf("version %u ", pdp.version); - printf("tid %llx ms_addr %s ", pdp.tid, inet_ntoa(pdp.ms_addr)); + if (pdp.version == GTP_V0) + printf("tid %"PRIu64" ms_addr %s ", + pdp.u.v0.tid, inet_ntoa(pdp.sgsn_addr)); + else if (pdp.version == GTP_V1) + printf("tei %u/%u ms_addr %s ", pdp.u.v1.i_tei, + pdp.u.v1.o_tei, inet_ntoa(pdp.sgsn_addr)); printf("sgsn_addr %s\n", inet_ntoa(pdp.sgsn_addr)); return MNL_CB_OK; @@ -197,8 +251,6 @@ list_tunnel(int argc, char *argv[], int genl_id, struct mnl_socket *nl) int main(int argc, char *argv[]) { struct mnl_socket *nl; - char buf[MNL_SOCKET_BUFFER_SIZE]; - unsigned int portid; int32_t genl_id; int ret; diff --git a/libgtnl/tools/gtpnl.c b/libgtnl/tools/gtpnl.c deleted file mode 100644 index 252f0b1..0000000 --- a/libgtnl/tools/gtpnl.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Helper functions */ - -/* (C) 2014 by sysmocom - s.f.m.c. GmbH - * Author: Pablo Neira Ayuso - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include -#include -#include - -void gtp_build_payload(struct nlmsghdr *nlh, uint64_t tid, uint32_t ifidx, - uint32_t sgsn_addr, uint32_t ms_addr, uint32_t version) -{ - mnl_attr_put_u32(nlh, GTPA_VERSION, version); - mnl_attr_put_u32(nlh, GTPA_LINK, ifidx); - mnl_attr_put_u32(nlh, GTPA_SGSN_ADDRESS, sgsn_addr); - mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, ms_addr); - mnl_attr_put_u64(nlh, GTPA_TID, tid); -} -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:09:58 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:09:58 +0200 Subject: [PATCH 04/12] gtp: replace udp encap setup with setup_udp_tunnel_sock In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-5-git-send-email-aschultz@tpip.net> setup_udp_tunnel_sock() is doing exactly the same as we did before. So instead of replicating all that, simply use it instead. Signed-off-by: Andreas Schultz --- gtp.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/gtp.c b/gtp.c index 280e93b..4ab2b01 100644 --- a/gtp.c +++ b/gtp.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -917,7 +918,7 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_instance *gti, { int err; struct socket *sock0, *sock1u; - struct sock *sk; + struct udp_tunnel_sock_cfg tuncfg = {NULL}; netdev_dbg(dev, "enable gtp on %d, %d\n", fd_gtp0, fd_gtp1); @@ -951,18 +952,15 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_instance *gti, gti->sock0 = sock0; gti->sock1u = sock1u; - sk = gti->sock0->sk; - udp_sk(sk)->encap_type = UDP_ENCAP_GTP0; - udp_sk(sk)->encap_rcv = gtp_udp_encap_recv; - udp_sk(sk)->encap_destroy = gtp_udp_encap_destroy; - sk->sk_user_data = gti; - udp_encap_enable(); - - sk = gti->sock1u->sk; - udp_sk(sk)->encap_type = UDP_ENCAP_GTP1U; - udp_sk(sk)->encap_rcv = gtp_udp_encap_recv; - udp_sk(sk)->encap_destroy = gtp_udp_encap_destroy; - sk->sk_user_data = gti; + tuncfg.sk_user_data = gti; + tuncfg.encap_rcv = gtp_udp_encap_recv; + tuncfg.encap_destroy = gtp_udp_encap_destroy; + + tuncfg.encap_type = UDP_ENCAP_GTP0; + setup_udp_tunnel_sock(sock_net(gti->sock0->sk), gti->sock0, &tuncfg); + + tuncfg.encap_type = UDP_ENCAP_GTP1U; + setup_udp_tunnel_sock(sock_net(gti->sock1u->sk), gti->sock1u, &tuncfg); err = 0; -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:09:57 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:09:57 +0200 Subject: [PATCH 03/12] gtp: add socket destroy handler In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-4-git-send-email-aschultz@tpip.net> Add a socket destroy handler and use it to detach and release all resources from an UDP socket. Do not longer pin the socket with a reference. This together with the release handler allows user space to close the socket from underneath us. The destroy handler will handle the rest. Signed-off-by: Andreas Schultz --- gtp.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/gtp.c b/gtp.c index cd41aea..280e93b 100644 --- a/gtp.c +++ b/gtp.c @@ -80,6 +80,8 @@ struct gtp_net { struct list_head gtp_instance_list; }; +static void gtp_encap_disable(struct gtp_instance *gti); + static inline u32 gtp0_hashfn(u64 tid) { u32 *tid32 = (u32 *) &tid; @@ -317,6 +319,16 @@ out_rcu: return ret; } +static void gtp_udp_encap_destroy(struct sock *sk) +{ + struct gtp_instance *gti = sk_to_gti(sk); + + if (gti) { + gtp_encap_disable(gti); + sock_put(sk); + } +} + /* UDP encapsulation receive handler. See net/ipv4/udp.c. * Return codes: 0: success, <0: error, >0: passed up to userspace UDP. */ @@ -401,8 +413,6 @@ static int gtp_dev_init(struct net_device *dev) return 0; } -static void gtp_encap_disable(struct gtp_instance *gti); - static void gtp_dev_uninit(struct net_device *dev) { struct gtp_instance *gti = netdev_priv(dev); @@ -944,15 +954,18 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_instance *gti, sk = gti->sock0->sk; udp_sk(sk)->encap_type = UDP_ENCAP_GTP0; udp_sk(sk)->encap_rcv = gtp_udp_encap_recv; + udp_sk(sk)->encap_destroy = gtp_udp_encap_destroy; sk->sk_user_data = gti; udp_encap_enable(); sk = gti->sock1u->sk; udp_sk(sk)->encap_type = UDP_ENCAP_GTP1U; udp_sk(sk)->encap_rcv = gtp_udp_encap_recv; + udp_sk(sk)->encap_destroy = gtp_udp_encap_destroy; sk->sk_user_data = gti; - return 0; + err = 0; + err2: sockfd_put(sock1u); err1: @@ -962,10 +975,17 @@ err1: static void gtp_encap_disable(struct gtp_instance *gti) { - if (gti->sock1u) - sockfd_put(gti->sock1u); - if (gti->sock0) - sockfd_put(gti->sock0); + if (gti->sock0 && gti->sock0->sk) { + udp_sk(gti->sock0->sk)->encap_type = 0; + rcu_assign_sk_user_data(gti->sock0->sk, NULL); + } + if (gti->sock1u && gti->sock1u->sk) { + udp_sk(gti->sock1u->sk)->encap_type = 0; + rcu_assign_sk_user_data(gti->sock1u->sk, NULL); + } + + gti->sock0 = NULL; + gti->sock1u = NULL; } static struct net_device *gtp_find_dev(struct net *net, int ifindex) -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:09:55 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:09:55 +0200 Subject: [PATCH 01/12] gtp: select netns based on NL attribute In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-2-git-send-email-aschultz@tpip.net> This permits a split namespace setup where the GTP transport sockets are in one namespace the gtp tunnel interface is in another namespace. The target namespece is selected by the new GTPA_NET_NS_FD NL attributes. It fall back to the netns of the GTP-U sockets if the NL attr is not present. Signed-off-by: Andreas Schultz --- gtp.c | 35 +++++++++++++++++++++++++++++++---- gtp_nl.h | 1 + 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/gtp.c b/gtp.c index cbe2da1..cd41aea 100644 --- a/gtp.c +++ b/gtp.c @@ -740,7 +740,7 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_instance *gti, static int gtp_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { - struct gtp_net *gn = net_generic(src_net, gtp_net_id); + struct gtp_net *gn; struct net_device *real_dev; struct gtp_instance *gti; int hashsize, err, fd0, fd1; @@ -780,6 +780,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, if (err < 0) goto err1; + gn = net_generic(dev_net(dev), gtp_net_id); list_add_rcu(>i->list, &gn->gtp_instance_list); netdev_dbg(dev, "registered new interface\n"); @@ -847,6 +848,19 @@ static struct rtnl_link_ops gtp_link_ops __read_mostly = { .fill_info = gtp_fill_info, }; +static struct net *gtp_genl_get_net(struct net *src_net, struct nlattr *tb[]) +{ + struct net *net; + /* Examine the link attributes and figure out which + * network namespace we are talking about. + */ + if (tb[GTPA_NET_NS_FD]) + net = get_net_ns_by_fd(nla_get_u32(tb[GTPA_NET_NS_FD])); + else + net = get_net(src_net); + return net; +} + static int gtp_hashtable_new(struct gtp_instance *gti, int hsize) { int i; @@ -1065,7 +1079,7 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) static int gtp_genl_tunnel_new(struct sk_buff *skb, struct genl_info *info) { - struct net *net = sock_net(skb->sk); + struct net *net; struct net_device *dev; if (!info->attrs[GTPA_VERSION] || @@ -1075,6 +1089,10 @@ static int gtp_genl_tunnel_new(struct sk_buff *skb, struct genl_info *info) !info->attrs[GTPA_TID]) return -EINVAL; + net = gtp_genl_get_net(sock_net(skb->sk), info->attrs); + if (IS_ERR(net)) + return PTR_ERR(net); + /* Check if there's an existing gtpX device to configure */ dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK])); if (dev == NULL) @@ -1085,7 +1103,7 @@ static int gtp_genl_tunnel_new(struct sk_buff *skb, struct genl_info *info) static int gtp_genl_tunnel_delete(struct sk_buff *skb, struct genl_info *info) { - struct net *net = sock_net(skb->sk); + struct net *net; struct gtp_instance *gti; struct net_device *dev; struct pdp_ctx *pctx; @@ -1113,6 +1131,10 @@ static int gtp_genl_tunnel_delete(struct sk_buff *skb, struct genl_info *info) if (gtp_version == GTP_V1 && tid > UINT_MAX) return -EINVAL; + net = gtp_genl_get_net(sock_net(skb->sk), info->attrs); + if (IS_ERR(net)) + return PTR_ERR(net); + /* Check if there's an existing gtpX device to configure */ dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK])); if (dev == NULL) @@ -1181,7 +1203,7 @@ nla_put_failure: static int gtp_genl_tunnel_get(struct sk_buff *skb, struct genl_info *info) { - struct net *net = sock_net(skb->sk); + struct net *net; struct net_device *dev; struct gtp_instance *gti; struct pdp_ctx *pctx = NULL; @@ -1202,6 +1224,10 @@ static int gtp_genl_tunnel_get(struct sk_buff *skb, struct genl_info *info) return -EINVAL; } + net = gtp_genl_get_net(sock_net(skb->sk), info->attrs); + if (IS_ERR(net)) + return PTR_ERR(net); + /* Check if there's an existing gtpX device to configure */ dev = gtp_find_dev(net, nla_get_u32(info->attrs[GTPA_LINK])); if (dev == NULL) @@ -1310,6 +1336,7 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = { [GTPA_SGSN_ADDRESS] = { .type = NLA_NESTED, }, [GTPA_MS_ADDRESS] = { .type = NLA_NESTED, }, [GTPA_FLOW] = { .type = NLA_U16, }, + [GTPA_NET_NS_FD] = { .type = NLA_U32, }, }; static const struct genl_ops gtp_genl_ops[] = { diff --git a/gtp_nl.h b/gtp_nl.h index 7bdd2f5..c20666d 100644 --- a/gtp_nl.h +++ b/gtp_nl.h @@ -40,6 +40,7 @@ enum gtp_attrs { GTPA_SGSN_ADDRESS, GTPA_MS_ADDRESS, GTPA_FLOW, + GTPA_NET_NS_FD, __GTPA_MAX, }; #define GTPA_MAX (__GTPA_MAX + 1) -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:09:59 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:09:59 +0200 Subject: [PATCH 05/12] gtp: switch to iptunnel framework and no longer depend on real_dev In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-6-git-send-email-aschultz@tpip.net> Send tunnel data on GTP-U socket insead of raw interface and use existing iptunnel helpers for that. Signed-off-by: Andreas Schultz --- gtp.c | 241 ++++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 132 insertions(+), 109 deletions(-) diff --git a/gtp.c b/gtp.c index 4ab2b01..bead51f 100644 --- a/gtp.c +++ b/gtp.c @@ -68,7 +68,6 @@ struct gtp_instance { struct socket *sock1u; struct net_device *dev; - struct net_device *real_dev; unsigned int hash_size; struct hlist_head *tid_hash; @@ -404,7 +403,6 @@ static int gtp_dev_init(struct net_device *dev) { struct gtp_instance *gti = netdev_priv(dev); - dev->flags = IFF_NOARP; gti->dev = dev; dev->tstats = alloc_percpu(struct pcpu_sw_netstats); @@ -424,26 +422,34 @@ static void gtp_dev_uninit(struct net_device *dev) #define IP_UDP_LEN (sizeof(struct iphdr) + sizeof(struct udphdr)) -static struct rtable * -ip4_route_output_gtp(struct net *net, struct flowi4 *fl4, - __be32 daddr, __be32 saddr, __u8 tos, int oif) +static inline void init_gtp_flow(struct flowi4 *fl4, + const struct sock *sk, + __be32 daddr) { memset(fl4, 0, sizeof(*fl4)); - fl4->flowi4_oif = oif; + fl4->flowi4_oif = sk->sk_bound_dev_if; fl4->daddr = daddr; - fl4->saddr = saddr; - fl4->flowi4_tos = tos; - fl4->flowi4_proto = IPPROTO_UDP; + fl4->saddr = inet_sk(sk)->inet_saddr; + fl4->flowi4_tos = RT_CONN_FLAGS(sk); + fl4->flowi4_proto = sk->sk_protocol; +} + +static struct rtable * +ip4_route_output_gtp(struct net *net, struct flowi4 *fl4, + const struct sock *sk, + __be32 daddr) +{ + init_gtp_flow(fl4, sk, daddr); return ip_route_output_key(net, fl4); } static inline void -gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx, int payload_len) +gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) { struct gtp0_header *gtp0; + int payload_len = skb->len; /* ensure there is sufficient headroom */ - skb_cow(skb, sizeof(*gtp0) + IP_UDP_LEN); gtp0 = (struct gtp0_header *) skb_push(skb, sizeof(*gtp0)); gtp0->flags = 0x1e; /* V0, GTP-non-prime */ @@ -457,12 +463,12 @@ gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx, int payload_len) } static inline void -gtp1_push_header(struct sk_buff *skb, struct pdp_ctx *pctx, int payload_len) +gtp1_push_header(struct sk_buff *skb, struct pdp_ctx *pctx) { struct gtp1_header *gtp1; + int payload_len = skb->len; /* ensure there is sufficient headroom */ - skb_cow(skb, sizeof(*gtp1) + IP_UDP_LEN); gtp1 = (struct gtp1_header *) skb_push(skb, sizeof(*gtp1)); /* Bits 8 7 6 5 4 3 2 1 @@ -502,6 +508,7 @@ gtp_iptunnel_xmit_stats(int err, struct net_device_stats *err_stats, } struct gtp_pktinfo { + struct sock *sk; union { struct iphdr *iph; struct ipv6hdr *ip6h; @@ -515,10 +522,12 @@ struct gtp_pktinfo { }; static inline void -gtp_set_pktinfo_ipv4(struct gtp_pktinfo *pktinfo, struct iphdr *iph, +gtp_set_pktinfo_ipv4(struct gtp_pktinfo *pktinfo, struct sock *sk, + struct iphdr *iph, struct pdp_ctx *pctx, struct rtable *rt, struct flowi4 *fl4, struct net_device *dev) { + pktinfo->sk = sk; pktinfo->iph = iph; pktinfo->pctx = pctx; pktinfo->rt = rt; @@ -530,7 +539,7 @@ static int gtp_ip4_prepare_xmit(struct sk_buff *skb, struct net_device *dev, struct gtp_pktinfo *pktinfo) { struct gtp_instance *gti = netdev_priv(dev); - struct inet_sock *inet = inet_sk(gti->sock0->sk); + struct sock *sk; struct iphdr *iph; struct pdp_ctx *pctx; struct rtable *rt; @@ -549,14 +558,23 @@ static int gtp_ip4_prepare_xmit(struct sk_buff *skb, struct net_device *dev, netdev_dbg(dev, "found PDP context %p\n", pctx); /* Obtain route for the new encapsulated GTP packet */ - rt = ip4_route_output_gtp(dev_net(dev), &fl4, - pctx->sgsn_addr.ip4.s_addr, - inet->inet_saddr, 0, - gti->real_dev->ifindex); + switch (pctx->gtp_version) { + case GTP_V0: + sk = gti->sock0->sk; + break; + case GTP_V1: + sk = gti->sock1u->sk; + break; + default: + return -ENOENT; + } + + rt = ip4_route_output_gtp(sock_net(sk), &fl4, + gti->sock0->sk, + pctx->sgsn_addr.ip4.s_addr); if (IS_ERR(rt)) { - netdev_dbg(dev, "no route to SSGN %pI4 from ifidx=%d\n", - &pctx->sgsn_addr.ip4.s_addr, - gti->real_dev->ifindex); + netdev_dbg(dev, "no route to SSGN %pI4\n", + &pctx->sgsn_addr.ip4.s_addr); dev->stats.tx_carrier_errors++; goto err; } @@ -570,12 +588,11 @@ static int gtp_ip4_prepare_xmit(struct sk_buff *skb, struct net_device *dev, } skb_dst_drop(skb); - skb_dst_set(skb, &rt->dst); /* This is similar to tnl_update_pmtu() */ df = iph->frag_off; if (df) { - mtu = dst_mtu(&rt->dst) - gti->real_dev->hard_header_len - + mtu = dst_mtu(&rt->dst) - dev->hard_header_len - sizeof(struct iphdr) - sizeof(struct udphdr); switch (pctx->gtp_version) { case GTP_V0: @@ -586,10 +603,9 @@ static int gtp_ip4_prepare_xmit(struct sk_buff *skb, struct net_device *dev, break; } } else - mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; + mtu = dst_mtu(&rt->dst); - if (skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu); if (!skb_is_gso(skb) && (iph->frag_off & htons(IP_DF)) && mtu < ntohs(iph->tot_len)) { @@ -600,7 +616,7 @@ static int gtp_ip4_prepare_xmit(struct sk_buff *skb, struct net_device *dev, goto err_rt; } - gtp_set_pktinfo_ipv4(pktinfo, iph, pctx, rt, &fl4, dev); + gtp_set_pktinfo_ipv4(pktinfo, sk, iph, pctx, rt, &fl4, dev); return 0; err_rt: @@ -616,34 +632,23 @@ static int gtp_ip6_prepare_xmit(struct sk_buff *skb, struct net_device *dev, return 0; } -static inline void -gtp_push_ip4hdr(struct sk_buff *skb, struct gtp_pktinfo *pktinfo) +static inline int +gtp_udp_tunnel_xmit(struct sk_buff *skb, __be16 port, + struct gtp_pktinfo *pktinfo) { - struct iphdr *iph; - - /* Push down and install the IP header. Similar to iptunnel_xmit() */ - skb_push(skb, sizeof(struct iphdr)); - skb_reset_network_header(skb); - - iph = ip_hdr(skb); - - iph->version = 4; - iph->ihl = sizeof(struct iphdr) >> 2; - iph->frag_off = htons(IP_DF); - iph->protocol = IPPROTO_UDP; - iph->tos = pktinfo->iph->tos; - iph->daddr = pktinfo->fl4.daddr; - iph->saddr = pktinfo->fl4.saddr; - iph->ttl = ip4_dst_hoplimit(&pktinfo->rt->dst); - __ip_select_ident(dev_net(pktinfo->rt->dst.dev), iph, - (skb_shinfo(skb)->gso_segs ?: 1) - 1); - netdev_dbg(pktinfo->dev, "gtp -> IP src: %pI4 dst: %pI4\n", - &iph->saddr, &iph->daddr); + &pktinfo->iph->saddr, &pktinfo->iph->daddr); + + return udp_tunnel_xmit_skb(pktinfo->rt, pktinfo->sk, skb, + pktinfo->fl4.saddr, + pktinfo->fl4.daddr, + pktinfo->iph->tos, + ip4_dst_hoplimit(&pktinfo->rt->dst), + htons(IP_DF), port, port, true, false); } -static inline void -gtp_push_ip6hdr(struct sk_buff *skb, struct gtp_pktinfo *pktinfo) +static inline int +gtp_ip6tunnel_xmit(struct sk_buff *skb, struct gtp_pktinfo *pktinfo) { /* TODO IPV6 support */ } @@ -654,9 +659,17 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) unsigned int payload_len; struct gtp_pktinfo pktinfo; unsigned int proto = ntohs(skb->protocol); - int gtph_len, err; + int gtph_len, err = -EINVAL; + __be16 gtph_port; rcu_read_lock(); + + /* ensure there is sufficient headroom */ + if (skb_cow_head(skb, dev->needed_headroom)) + goto tx_error; + + skb_reset_inner_headers(skb); + switch (proto) { case ETH_P_IP: err = gtp_ip4_prepare_xmit(skb, dev, &pktinfo); @@ -669,56 +682,55 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) if (err < 0) goto tx_error; - /* Annotate length of the encapsulated packet */ - payload_len = skb->len; - /* Push down GTP header */ switch (pktinfo.pctx->gtp_version) { case GTP_V0: - gtp0_push_header(skb, pktinfo.pctx, payload_len); - break; - case GTP_V1: - gtp1_push_header(skb, pktinfo.pctx, payload_len); - break; - } - - /* Push down and install the UDP header. */ - skb_push(skb, sizeof(struct udphdr)); - skb_reset_transport_header(skb); - - uh = udp_hdr(skb); - switch (pktinfo.pctx->gtp_version) { - case GTP_V0: - uh->source = uh->dest = htons(GTP0_PORT); + gtph_port = htons(GTP0_PORT); gtph_len = sizeof(struct gtp0_header); + + gtp0_push_header(skb, pktinfo.pctx); break; case GTP_V1: - uh->source = uh->dest = htons(GTP1U_PORT); + gtph_port = htons(GTP1U_PORT); gtph_len = sizeof(struct gtp1_header); + + gtp1_push_header(skb, pktinfo.pctx); break; + default: + goto tx_error; } - uh->len = htons(sizeof(struct udphdr) + payload_len + gtph_len); - uh->check = 0; - - netdev_dbg(dev, "gtp -> UDP src: %u dst: %u (len %u)\n", - ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); - switch (proto) { case ETH_P_IP: - gtp_push_ip4hdr(skb, &pktinfo); + err = gtp_udp_tunnel_xmit(skb, gtph_port, &pktinfo); break; case ETH_P_IPV6: - gtp_push_ip6hdr(skb, &pktinfo); + /* Annotate length of the encapsulated packet */ + payload_len = skb->len; + + /* Push down and install the UDP header. */ + skb_push(skb, sizeof(struct udphdr)); + skb_reset_transport_header(skb); + + uh = udp_hdr(skb); + + uh->source = uh->dest = gtph_port; + uh->len = htons(sizeof(struct udphdr) + payload_len + gtph_len); + uh->check = 0; + + netdev_dbg(dev, "gtp -> UDP src: %u dst: %u (len %u)\n", + ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); + + nf_reset(skb); + + netdev_dbg(dev, "Good, now packet leaving from GGSN to SGSN\n"); + + err = gtp_ip6tunnel_xmit(skb, &pktinfo); break; } - rcu_read_unlock(); - nf_reset(skb); - - netdev_dbg(dev, "Good, now packet leaving from GGSN to SGSN\n"); + rcu_read_unlock(); - err = ip_local_out(skb); gtp_iptunnel_xmit_stats(err, &dev->stats, dev->tstats); return NETDEV_TX_OK; @@ -737,10 +749,26 @@ static const struct net_device_ops gtp_netdev_ops = { static void gtp_link_setup(struct net_device *dev) { - dev->priv_flags |= IFF_NO_QUEUE; - dev->netdev_ops = >p_netdev_ops; dev->destructor = free_netdev; + + dev->hard_header_len = 0; + dev->addr_len = 0; + + /* Zero header length */ + dev->type = ARPHRD_NONE; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->tx_queue_len = 1000; + + dev->priv_flags |= IFF_NO_QUEUE; + dev->features |= NETIF_F_LLTX; + netif_keep_dst(dev); + + dev->needed_headroom = LL_MAX_HEADER + + sizeof(struct iphdr) + + sizeof(struct udphdr) + + sizeof(struct gtp0_header); + } static int gtp_hashtable_new(struct gtp_instance *gti, int hsize); @@ -752,31 +780,20 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { struct gtp_net *gn; - struct net_device *real_dev; struct gtp_instance *gti; int hashsize, err, fd0, fd1; - if (!tb[IFLA_LINK]) - return -EINVAL; - - real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); - if (!real_dev) - return -ENODEV; - - dev_hold(real_dev); - if (!tb[IFLA_MTU]) - dev->mtu = real_dev->mtu; - else if (dev->mtu > real_dev->mtu) - return -EINVAL; + dev->mtu = 1500; gti = netdev_priv(dev); - gti->real_dev = real_dev; fd0 = nla_get_u32(data[IFLA_GTP_FD0]); fd1 = nla_get_u32(data[IFLA_GTP_FD1]); - gtp_encap_enable(dev, gti, fd0, fd1); + err = gtp_encap_enable(dev, gti, fd0, fd1); + if (err < 0) + goto out_err; if (!data[IFLA_GTP_HASHSIZE]) hashsize = 1024; @@ -785,21 +802,28 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, err = gtp_hashtable_new(gti, hashsize); if (err < 0) - return err; + goto out_encap; err = register_netdevice(dev); - if (err < 0) - goto err1; + if (err < 0) { + netdev_dbg(dev, "failed to register new netdev %d\n", err); + goto out_hashtable; + } gn = net_generic(dev_net(dev), gtp_net_id); list_add_rcu(>i->list, &gn->gtp_instance_list); - netdev_dbg(dev, "registered new interface\n"); + netdev_dbg(dev, "registered new GTP interface\n"); return 0; -err1: - netdev_dbg(dev, "failed to register new netdev %d\n", err); + +out_hashtable: gtp_hashtable_free(gti); + +out_encap: + gtp_encap_disable(gti); + +out_err: return err; } @@ -809,7 +833,6 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head) gtp_encap_disable(gti); gtp_hashtable_free(gti); - dev_put(gti->real_dev); list_del_rcu(>i->list); unregister_netdevice_queue(dev, head); } -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:10:06 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:10:06 +0200 Subject: [PATCH 12/12] gtp: add support for replacing PDP contexts In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-13-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- gtp.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/gtp.c b/gtp.c index f569d62..e46638a 100644 --- a/gtp.c +++ b/gtp.c @@ -1178,24 +1178,45 @@ static int ipv4_pdp_add(struct net_device *dev, struct genl_info *info) } if (found) { + struct pdp_ctx *repl_pctx; + if (info->nlhdr->nlmsg_flags & NLM_F_EXCL) return -EEXIST; - if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE) - return -EOPNOTSUPP; - ipv4_pdp_fill(pctx, info); + repl_pctx = kmemdup(pctx, sizeof(struct pdp_ctx), GFP_KERNEL); + if (repl_pctx == NULL) + return -ENOMEM; + + ipv4_pdp_fill(repl_pctx, info); + + /* only the SGSN can be changed */ + if (pctx->af != repl_pctx->af || + pctx->gtp_version != repl_pctx->gtp_version || + memcpy(&pctx->u, &repl_pctx->u, sizeof(pctx->u) != 0)) { + kfree(repl_pctx); + return -EINVAL; + } + + hlist_replace_rcu(&pctx->hlist_addr, &repl_pctx->hlist_addr); + hlist_replace_rcu(&pctx->hlist_tid, &repl_pctx->hlist_tid); - if (pctx->gtp_version == GTP_V0) + kfree_rcu(pctx, rcu_head); + + if (repl_pctx->gtp_version == GTP_V0) netdev_dbg(dev, "GTPv0-U: update tunnel id = %llx (pdp %p)\n", - pctx->u.v0.tid, pctx); - else if (pctx->gtp_version == GTP_V1) + repl_pctx->u.v0.tid, repl_pctx); + else if (repl_pctx->gtp_version == GTP_V1) netdev_dbg(dev, "GTPv1-U: update tunnel id = %x/%x (pdp %p)\n", - pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx); + repl_pctx->u.v1.i_tei, + repl_pctx->u.v1.o_tei, repl_pctx); return 0; } + if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE) + return -ENXIO; + pctx = kmalloc(sizeof(struct pdp_ctx), GFP_KERNEL); if (pctx == NULL) return -ENOMEM; -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:10:02 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:10:02 +0200 Subject: [PATCH 08/12] gtp-rtnl: real_ifname is not long needed, remove it In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-9-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- libgtnl/include/libgtpnl/gtpnl.h | 3 +-- libgtnl/src/gtp-rtnl.c | 4 +--- libgtnl/tools/gtp-link-add.c | 5 ++--- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/libgtnl/include/libgtpnl/gtpnl.h b/libgtnl/include/libgtpnl/gtpnl.h index 3d3fd73..49ba03d 100644 --- a/libgtnl/include/libgtpnl/gtpnl.h +++ b/libgtnl/include/libgtpnl/gtpnl.h @@ -16,8 +16,7 @@ int genl_lookup_family(struct mnl_socket *nl, const char *family); struct in_addr; -int gtp_dev_create(int dest_ns, const char *gtp_ifname, const char *real_ifname, - int fd0, int fd1); +int gtp_dev_create(int dest_ns, const char *gtp_ifname, int fd0, int fd1); int gtp_dev_config(const char *iface, struct in_addr *net, uint32_t prefix); int gtp_dev_destroy(const char *gtp_ifname); diff --git a/libgtnl/src/gtp-rtnl.c b/libgtnl/src/gtp-rtnl.c index 76e2021..527015b 100644 --- a/libgtnl/src/gtp-rtnl.c +++ b/libgtnl/src/gtp-rtnl.c @@ -104,8 +104,7 @@ static int gtp_dev_talk(struct nlmsghdr *nlh, uint32_t seq) return ret; } -int gtp_dev_create(int dest_ns, const char *gtp_ifname, const char *real_ifname, - int fd0, int fd1) +int gtp_dev_create(int dest_ns, const char *gtp_ifname, int fd0, int fd1) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; @@ -122,7 +121,6 @@ int gtp_dev_create(int dest_ns, const char *gtp_ifname, const char *real_ifname, if (dest_ns >= 0) mnl_attr_put_u32(nlh, IFLA_NET_NS_FD, dest_ns); - mnl_attr_put_u32(nlh, IFLA_LINK, if_nametoindex(real_ifname)); mnl_attr_put_str(nlh, IFLA_IFNAME, gtp_ifname); nest = mnl_attr_nest_start(nlh, IFLA_LINKINFO); mnl_attr_put_str(nlh, IFLA_INFO_KIND, "gtp"); diff --git a/libgtnl/tools/gtp-link-add.c b/libgtnl/tools/gtp-link-add.c index 3d893eb..4ef025e 100644 --- a/libgtnl/tools/gtp-link-add.c +++ b/libgtnl/tools/gtp-link-add.c @@ -43,8 +43,8 @@ int main(int argc, char *argv[]) unsigned int seq, portid, change = 0, flags = 0; struct nlattr *nest, *nest2; - if (argc != 2) { - printf("Usage: %s [ifname]\n", argv[0]); + if (argc != 1) { + printf("Usage: %s\n", argv[0]); exit(EXIT_FAILURE); } @@ -62,7 +62,6 @@ int main(int argc, char *argv[]) int fd1 = socket(AF_INET, SOCK_DGRAM, 0); int fd2 = socket(AF_INET, SOCK_DGRAM, 0); - mnl_attr_put_u32(nlh, IFLA_LINK, if_nametoindex(argv[1])); mnl_attr_put_str(nlh, IFLA_IFNAME, "gtp0"); nest = mnl_attr_nest_start(nlh, IFLA_LINKINFO); mnl_attr_put_str(nlh, IFLA_INFO_KIND, "gtp"); -- 2.7.4 From aschultz at tpip.net Mon Apr 11 14:09:56 2016 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 11 Apr 2016 16:09:56 +0200 Subject: [PATCH 02/12] gtp-rtnl: and netns support In-Reply-To: <1460383806-17772-1-git-send-email-aschultz@tpip.net> References: <1460383806-17772-1-git-send-email-aschultz@tpip.net> Message-ID: <1460383806-17772-3-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- libgtnl/include/libgtpnl/gtp.h | 2 ++ libgtnl/include/libgtpnl/gtpnl.h | 2 +- libgtnl/include/linux/gtp_nl.h | 1 + libgtnl/src/gtp-genl.c | 2 ++ libgtnl/src/gtp-rtnl.c | 4 +++- libgtnl/src/gtp.c | 12 ++++++++++++ libgtnl/src/internal.h | 1 + libgtnl/src/libgtpnl.map | 2 ++ 8 files changed, 24 insertions(+), 2 deletions(-) diff --git a/libgtnl/include/libgtpnl/gtp.h b/libgtnl/include/libgtpnl/gtp.h index 10b34d5..fa09d2a 100644 --- a/libgtnl/include/libgtpnl/gtp.h +++ b/libgtnl/include/libgtpnl/gtp.h @@ -8,6 +8,7 @@ struct gtp_tunnel; struct gtp_tunnel *gtp_tunnel_alloc(void); void gtp_tunnel_free(struct gtp_tunnel *t); +void gtp_tunnel_set_ifns(struct gtp_tunnel *t, int ifns); void gtp_tunnel_set_ifidx(struct gtp_tunnel *t, uint32_t ifidx); void gtp_tunnel_set_ms_ip4(struct gtp_tunnel *t, struct in_addr *ms_addr); void gtp_tunnel_set_sgsn_ip4(struct gtp_tunnel *t, struct in_addr *sgsn_addr); @@ -15,6 +16,7 @@ void gtp_tunnel_set_version(struct gtp_tunnel *t, uint32_t version); void gtp_tunnel_set_tid(struct gtp_tunnel *t, uint64_t tid); void gtp_tunnel_set_flowid(struct gtp_tunnel *t, uint16_t flowid); +const int gtp_tunnel_get_ifns(struct gtp_tunnel *t); const uint32_t gtp_tunnel_get_ifidx(struct gtp_tunnel *t); const struct in_addr *gtp_tunnel_get_ms_ip4(struct gtp_tunnel *t); const struct in_addr *gtp_tunnel_get_sgsn_ip4(struct gtp_tunnel *t); diff --git a/libgtnl/include/libgtpnl/gtpnl.h b/libgtnl/include/libgtpnl/gtpnl.h index c4faf6c..3d3fd73 100644 --- a/libgtnl/include/libgtpnl/gtpnl.h +++ b/libgtnl/include/libgtpnl/gtpnl.h @@ -16,7 +16,7 @@ int genl_lookup_family(struct mnl_socket *nl, const char *family); struct in_addr; -int gtp_dev_create(const char *gtp_ifname, const char *real_ifname, +int gtp_dev_create(int dest_ns, const char *gtp_ifname, const char *real_ifname, int fd0, int fd1); int gtp_dev_config(const char *iface, struct in_addr *net, uint32_t prefix); int gtp_dev_destroy(const char *gtp_ifname); diff --git a/libgtnl/include/linux/gtp_nl.h b/libgtnl/include/linux/gtp_nl.h index 0a28046..a8fdf3a 100644 --- a/libgtnl/include/linux/gtp_nl.h +++ b/libgtnl/include/linux/gtp_nl.h @@ -40,6 +40,7 @@ enum gtp_attrs { GTPA_SGSN_ADDRESS, GTPA_MS_ADDRESS, GTPA_FLOWID, /* only for GTPv0 */ + GTPA_NET_NS_FD, __GTPA_MAX, }; #define GTPA_MAX (__GTPA_MAX + 1) diff --git a/libgtnl/src/gtp-genl.c b/libgtnl/src/gtp-genl.c index c1f60ab..bffa7a5 100644 --- a/libgtnl/src/gtp-genl.c +++ b/libgtnl/src/gtp-genl.c @@ -44,6 +44,8 @@ static void gtp_build_payload(struct nlmsghdr *nlh, struct gtp_tunnel *t) { mnl_attr_put_u32(nlh, GTPA_VERSION, t->gtp_version); + if (t->ifns >= 0) + mnl_attr_put_u32(nlh, GTPA_NET_NS_FD, t->ifns); mnl_attr_put_u32(nlh, GTPA_LINK, t->ifidx); mnl_attr_put_u32(nlh, GTPA_SGSN_ADDRESS, t->sgsn_addr.s_addr); mnl_attr_put_u32(nlh, GTPA_MS_ADDRESS, t->ms_addr.s_addr); diff --git a/libgtnl/src/gtp-rtnl.c b/libgtnl/src/gtp-rtnl.c index 22b9430..76e2021 100644 --- a/libgtnl/src/gtp-rtnl.c +++ b/libgtnl/src/gtp-rtnl.c @@ -104,7 +104,7 @@ static int gtp_dev_talk(struct nlmsghdr *nlh, uint32_t seq) return ret; } -int gtp_dev_create(const char *gtp_ifname, const char *real_ifname, +int gtp_dev_create(int dest_ns, const char *gtp_ifname, const char *real_ifname, int fd0, int fd1) { char buf[MNL_SOCKET_BUFFER_SIZE]; @@ -120,6 +120,8 @@ int gtp_dev_create(const char *gtp_ifname, const char *real_ifname, ifm->ifi_change |= IFF_UP; ifm->ifi_flags |= IFF_UP; + if (dest_ns >= 0) + mnl_attr_put_u32(nlh, IFLA_NET_NS_FD, dest_ns); mnl_attr_put_u32(nlh, IFLA_LINK, if_nametoindex(real_ifname)); mnl_attr_put_str(nlh, IFLA_IFNAME, gtp_ifname); nest = mnl_attr_nest_start(nlh, IFLA_LINKINFO); diff --git a/libgtnl/src/gtp.c b/libgtnl/src/gtp.c index 4534091..6e3d473 100644 --- a/libgtnl/src/gtp.c +++ b/libgtnl/src/gtp.c @@ -39,6 +39,12 @@ void gtp_tunnel_free(struct gtp_tunnel *t) } EXPORT_SYMBOL(gtp_tunnel_free); +void gtp_tunnel_set_ifns(struct gtp_tunnel *t, int ifns) +{ + t->ifns = ifns; +} +EXPORT_SYMBOL(gtp_tunnel_set_ifns); + void gtp_tunnel_set_ifidx(struct gtp_tunnel *t, uint32_t ifidx) { t->ifidx = ifidx; @@ -75,6 +81,12 @@ void gtp_tunnel_set_flowid(struct gtp_tunnel *t, uint16_t flowid) } EXPORT_SYMBOL(gtp_tunnel_set_flowid); +const int gtp_tunnel_get_ifns(struct gtp_tunnel *t) +{ + return t->ifns; +} +EXPORT_SYMBOL(gtp_tunnel_get_ifns); + const uint32_t gtp_tunnel_get_ifidx(struct gtp_tunnel *t) { return t->ifidx; diff --git a/libgtnl/src/internal.h b/libgtnl/src/internal.h index 75b3954..68f0135 100644 --- a/libgtnl/src/internal.h +++ b/libgtnl/src/internal.h @@ -13,6 +13,7 @@ #include struct gtp_tunnel { + int ifns; uint32_t ifidx; struct in_addr ms_addr; struct in_addr sgsn_addr; diff --git a/libgtnl/src/libgtpnl.map b/libgtnl/src/libgtpnl.map index 6e69ef8..2368467 100644 --- a/libgtnl/src/libgtpnl.map +++ b/libgtnl/src/libgtpnl.map @@ -15,12 +15,14 @@ global: gtp_tunnel_alloc; gtp_tunnel_free; + gtp_tunnel_set_ifns; gtp_tunnel_set_ifidx; gtp_tunnel_set_ms_ip4; gtp_tunnel_set_sgsn_ip4; gtp_tunnel_set_version; gtp_tunnel_set_tid; gtp_tunnel_set_flowid; + gtp_tunnel_get_ifns; gtp_tunnel_get_ifidx; gtp_tunnel_get_ms_ip4; gtp_tunnel_get_sgsn_ip4; -- 2.7.4 From msuraev at sysmocom.de Mon Apr 11 14:22:47 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 11 Apr 2016 16:22:47 +0200 Subject: [PATCH 2/4] Add concolutional code generator for *CCH In-Reply-To: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> References: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1460384569-13790-2-git-send-email-msuraev@sysmocom.de> From: Max Move convolutional code for *CCH channels from test to public API because it's useful not only for testing. Note: the code was manually generating with utils/conv_gen.py --- include/Makefile.am | 1 + include/osmocom/gsm/gsm0503.h | 47 +++++++++++++++++++++++++++++ src/gsm/Makefile.am | 2 +- src/gsm/conv_xcch_gen.c | 69 +++++++++++++++++++++++++++++++++++++++++++ src/gsm/libosmogsm.map | 1 + tests/Makefile.am | 2 +- tests/conv/conv_test.c | 32 +++----------------- 7 files changed, 124 insertions(+), 30 deletions(-) create mode 100644 include/osmocom/gsm/gsm0503.h create mode 100644 src/gsm/conv_xcch_gen.c diff --git a/include/Makefile.am b/include/Makefile.am index 0e5ed74..e7888c5 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -64,6 +64,7 @@ nobase_include_HEADERS = \ osmocom/gsm/gsm0411_utils.h \ osmocom/gsm/gsm0480.h \ osmocom/gsm/gsm0502.h \ + osmocom/gsm/gsm0503.h \ osmocom/gsm/gsm0808.h \ osmocom/gsm/gsm48.h \ osmocom/gsm/gsm48_ie.h \ diff --git a/include/osmocom/gsm/gsm0503.h b/include/osmocom/gsm/gsm0503.h new file mode 100644 index 0000000..e68aa9a --- /dev/null +++ b/include/osmocom/gsm/gsm0503.h @@ -0,0 +1,47 @@ +/* + * gsm0503.h + * + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include + +#include + +extern const uint8_t osmo_conv_gsm0503_xcch_output[][2]; +extern const uint8_t osmo_conv_gsm0503_xcch_state[][2]; + +/*! \file conv_gen.h + * Osmocom convolutional encoder/decoder for xCCH channels, see 3GPP TS 05.03 + */ + +/*! \brief structure describing convolutional code xCCH + * + * Non-recursive code, flushed, not punctured code. + */ +static const struct osmo_conv_code osmo_conv_gsm0503_xcch = { + .N = 2, + .K = 5, + .len = 224, + .term = CONV_TERM_FLUSH, + .next_output = osmo_conv_gsm0503_xcch_output, + .next_state = osmo_conv_gsm0503_xcch_state, +}; diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index b0ea643..0ab2bd8 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -17,7 +17,7 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \ gsm_utils.c rsl.c gsm48.c gsm48_ie.c gsm0808.c sysinfo.c \ gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \ gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \ - lapd_core.c lapdm.c kasumi.c \ + lapd_core.c lapdm.c kasumi.c conv_xcch_gen.c \ auth_core.c auth_comp128v1.c auth_comp128v23.c \ auth_milenage.c milenage/aes-encblock.c \ milenage/aes-internal.c milenage/aes-internal-enc.c \ diff --git a/src/gsm/conv_xcch_gen.c b/src/gsm/conv_xcch_gen.c new file mode 100644 index 0000000..25fa226 --- /dev/null +++ b/src/gsm/conv_xcch_gen.c @@ -0,0 +1,69 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* *CCH convolutional code: + 228 bits blocks, rate 1/2, k = 5 + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 + */ + +/* .next_state */ +const uint8_t osmo_conv_gsm0503_xcch_state[][2] = { + { 0, 1 }, + { 2, 3 }, + { 4, 5 }, + { 6, 7 }, + { 8, 9 }, + { 10, 11 }, + { 12, 13 }, + { 14, 15 }, + { 0, 1 }, + { 2, 3 }, + { 4, 5 }, + { 6, 7 }, + { 8, 9 }, + { 10, 11 }, + { 12, 13 }, + { 14, 15 }, +}; + +/* .next_output */ +const uint8_t osmo_conv_gsm0503_xcch_output[][2] = { + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, +}; diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index a3e4e14..53d112e 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -25,6 +25,7 @@ abis_nm_osmo_magic; abis_nm_ipa_magic; osmo_sitype_strs; +osmo_conv_gsm0503_xcch; comp128; dbm2rxlev; diff --git a/tests/Makefile.am b/tests/Makefile.am index 03506af..3aaa99b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -47,7 +47,7 @@ bits_bitcomp_test_SOURCES = bits/bitcomp_test.c bits_bitcomp_test_LDADD = $(top_builddir)/src/libosmocore.la conv_conv_test_SOURCES = conv/conv_test.c -conv_conv_test_LDADD = $(top_builddir)/src/libosmocore.la +conv_conv_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libgsmint.la gsm0808_gsm0808_test_SOURCES = gsm0808/gsm0808_test.c gsm0808_gsm0808_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index de62f23..6e99b2e 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -6,6 +6,7 @@ #include #include #include +#include #define MAX_LEN_BITS 512 #define MAX_LEN_BYTES (512/8) @@ -15,31 +16,6 @@ /* Test codes */ /* ------------------------------------------------------------------------ */ -/* GSM xCCH -> Non-recursive code, flushed, not punctured */ -static const uint8_t conv_gsm_xcch_next_output[][2] = { - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, -}; - -static const uint8_t conv_gsm_xcch_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, -}; - -static const struct osmo_conv_code conv_gsm_xcch = { - .N = 2, - .K = 5, - .len = 224, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, -}; - - /* GSM TCH/AFS 7.95 -> Recursive code, flushed, with puncturing */ static const uint8_t conv_gsm_tch_afs_7_95_next_output[][2] = { { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, @@ -227,8 +203,8 @@ static const struct osmo_conv_code conv_trunc = { .K = 5, .len = 224, .term = CONV_TERM_TRUNCATION, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, + .next_output = osmo_conv_gsm0503_xcch_output, + .next_state = osmo_conv_gsm0503_xcch_state, }; @@ -249,7 +225,7 @@ struct conv_test_vector { static const struct conv_test_vector tests[] = { { .name = "GSM xCCH (non-recursive, flushed, not punctured)", - .code = &conv_gsm_xcch, + .code = &osmo_conv_gsm0503_xcch, .in_len = 224, .out_len = 456, .has_vec = 1, -- 2.8.1 From msuraev at sysmocom.de Mon Apr 11 14:22:48 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 11 Apr 2016 16:22:48 +0200 Subject: [PATCH 3/4] Add convolutional code generators for CS2/3 In-Reply-To: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> References: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1460384569-13790-3-git-send-email-msuraev@sysmocom.de> From: Max --- include/osmocom/gsm/gsm0503.h | 26 +++++++++++++++++++++ src/gsm/Makefile.am | 2 +- src/gsm/conv_csx.c | 53 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/gsm/conv_csx.c diff --git a/include/osmocom/gsm/gsm0503.h b/include/osmocom/gsm/gsm0503.h index e68aa9a..3896821 100644 --- a/include/osmocom/gsm/gsm0503.h +++ b/include/osmocom/gsm/gsm0503.h @@ -45,3 +45,29 @@ static const struct osmo_conv_code osmo_conv_gsm0503_xcch = { .next_output = osmo_conv_gsm0503_xcch_output, .next_state = osmo_conv_gsm0503_xcch_state, }; + +extern const int osmo_conv_gsm0503_cs2_puncture[]; + +/*! \brief structure describing convolutional code CS2 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_cs2 = { + .N = 2, + .K = 5, + .len = 290, + .next_output = osmo_conv_gsm0503_xcch_output, + .next_state = osmo_conv_gsm0503_xcch_state, + .puncture = osmo_conv_gsm0503_cs2_puncture +}; + +extern const int osmo_conv_gsm0503_cs3_puncture[]; + +/*! \brief structure describing convolutional code CS2 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_cs3 = { + .N = 2, + .K = 5, + .len = 334, + .next_output = osmo_conv_gsm0503_xcch_output, + .next_state = osmo_conv_gsm0503_xcch_state, + .puncture = osmo_conv_gsm0503_cs3_puncture +}; diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index 0ab2bd8..8c7f2be 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -17,7 +17,7 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \ gsm_utils.c rsl.c gsm48.c gsm48_ie.c gsm0808.c sysinfo.c \ gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \ gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \ - lapd_core.c lapdm.c kasumi.c conv_xcch_gen.c \ + lapd_core.c lapdm.c kasumi.c conv_xcch_gen.c conv_csx.c \ auth_core.c auth_comp128v1.c auth_comp128v23.c \ auth_milenage.c milenage/aes-encblock.c \ milenage/aes-internal.c milenage/aes-internal-enc.c \ diff --git a/src/gsm/conv_csx.c b/src/gsm/conv_csx.c new file mode 100644 index 0000000..1f94cd4 --- /dev/null +++ b/src/gsm/conv_csx.c @@ -0,0 +1,53 @@ +/* + * conv_csx.c + * + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +const int osmo_conv_gsm0503_cs2_puncture[] = { + 15, 19, 23, 27, 31, 35, 43, 47, 51, 55, 59, 63, 67, 71, 75, 79, 83, 91, + 95, 99, 103, 107, 111, 115, 119, 123, 127, 131, 139, 143, 147, 151, 155, + 159, 163, 167, 171, 175, 179, 187, 191, 195, 199, 203, 207, 211, 215, + 219, 223, 227, 235, 239, 243, 247, 251, 255, 259, 263, 267, 271, 275, + 283, 287, 291, 295, 299, 303, 307, 311, 315, 319, 323, 331, 335, 339, + 343, 347, 351, 355, 359, 363, 367, 371, 379, 383, 387, 391, 395, 399, + 403, 407, 411, 415, 419, 427, 431, 435, 439, 443, 447, 451, 455, 459, + 463, 467, 475, 479, 483, 487, 491, 495, 499, 503, 507, 511, 515, 523, + 527, 531, 535, 539, 543, 547, 551, 555, 559, 563, 571, 575, 579, 583, + 587, -1 +}; + +const int osmo_conv_gsm0503_cs3_puncture[] = { + 15, 17, 21, 23, 27, 29, 33, 35, 39, 41, 45, 47, 51, 53, 57, 59, 63, 65, + 69, 71, 75, 77, 81, 83, 87, 89, 93, 95, 99, 101, 105, 107, 111, 113, + 117, 119, 123, 125, 129, 131, 135, 137, 141, 143, 147, 149, 153, 155, + 159, 161, 165, 167, 171, 173, 177, 179, 183, 185, 189, 191, 195, 197, + 201, 203, 207, 209, 213, 215, 219, 221, 225, 227, 231, 233, 237, 239, + 243, 245, 249, 251, 255, 257, 261, 263, 267, 269, 273, 275, 279, 281, + 285, 287, 291, 293, 297, 299, 303, 305, 309, 311, 315, 317, 321, 323, + 327, 329, 333, 335, 339, 341, 345, 347, 351, 353, 357, 359, 363, 365, + 369, 371, 375, 377, 381, 383, 387, 389, 393, 395, 399, 401, 405, 407, + 411, 413, 417, 419, 423, 425, 429, 431, 435, 437, 441, 443, 447, 449, + 453, 455, 459, 461, 465, 467, 471, 473, 477, 479, 483, 485, 489, 491, + 495, 497, 501, 503, 507, 509, 513, 515, 519, 521, 525, 527, 531, 533, + 537, 539, 543, 545, 549, 551, 555, 557, 561, 563, 567, 569, 573, 575, + 579, 581, 585, 587, 591, 593, 597, 599, 603, 605, 609, 611, 615, 617, + 621, 623, 627, 629, 633, 635, 639, 641, 645, 647, 651, 653, 657, 659, + 663, 665, 669, 671, -1 +}; -- 2.8.1 From msuraev at sysmocom.de Mon Apr 11 14:22:49 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 11 Apr 2016 16:22:49 +0200 Subject: [PATCH 4/4] Add convolutional code for TCH/AFS In-Reply-To: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> References: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1460384569-13790-4-git-send-email-msuraev@sysmocom.de> From: Max Replace implementation in tests with added code. Note: the code was manually generated with utils/conv_gen.py --- include/osmocom/gsm/gsm0503.h | 160 ++++++++++++++++++++++++++++++++++++ src/gsm/Makefile.am | 5 ++ src/gsm/conv_tch_afs.c | 119 +++++++++++++++++++++++++++ src/gsm/conv_tch_afs_10_2_gen.c | 79 ++++++++++++++++++ src/gsm/conv_tch_afs_12_2_gen.c | 79 ++++++++++++++++++ src/gsm/conv_tch_afs_4_75_gen.c | 177 ++++++++++++++++++++++++++++++++++++++++ src/gsm/conv_tch_afs_5_15_gen.c | 81 ++++++++++++++++++ src/gsm/conv_tch_afs_5_9_gen.c | 177 ++++++++++++++++++++++++++++++++++++++++ src/gsm/conv_tch_afs_6_7_gen.c | 80 ++++++++++++++++++ src/gsm/conv_tch_afs_7_4_gen.c | 79 ++++++++++++++++++ src/gsm/conv_tch_afs_7_95_gen.c | 175 +++++++++++++++++++++++++++++++++++++++ tests/conv/conv_test.c | 78 +----------------- 12 files changed, 1212 insertions(+), 77 deletions(-) create mode 100644 src/gsm/conv_tch_afs.c create mode 100644 src/gsm/conv_tch_afs_10_2_gen.c create mode 100644 src/gsm/conv_tch_afs_12_2_gen.c create mode 100644 src/gsm/conv_tch_afs_4_75_gen.c create mode 100644 src/gsm/conv_tch_afs_5_15_gen.c create mode 100644 src/gsm/conv_tch_afs_5_9_gen.c create mode 100644 src/gsm/conv_tch_afs_6_7_gen.c create mode 100644 src/gsm/conv_tch_afs_7_4_gen.c create mode 100644 src/gsm/conv_tch_afs_7_95_gen.c diff --git a/include/osmocom/gsm/gsm0503.h b/include/osmocom/gsm/gsm0503.h index 3896821..b9e5cba 100644 --- a/include/osmocom/gsm/gsm0503.h +++ b/include/osmocom/gsm/gsm0503.h @@ -71,3 +71,163 @@ static const struct osmo_conv_code osmo_conv_gsm0503_cs3 = { .next_state = osmo_conv_gsm0503_xcch_state, .puncture = osmo_conv_gsm0503_cs3_puncture }; + +extern const int osmo_conv_gsm0503_tch_afs_12_2_puncture[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_12_2_output[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_12_2_state[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_12_2_term_output[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_12_2_term_state[]; + +/*! \brief structure describing convolutional code TCH/AFS 12.2 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_12_2 = { + .N = 2, + .K = 5, + .len = 250, + .term = CONV_TERM_FLUSH, + .next_output = osmo_conv_gsm0503_tch_afs_12_2_output, + .next_state = osmo_conv_gsm0503_tch_afs_12_2_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_12_2_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_12_2_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_12_2_puncture +}; + +extern const int osmo_conv_gsm0503_tch_afs_10_2_puncture[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_10_2_output[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_10_2_state[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_10_2_term_output[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_10_2_term_state[]; + +/*! \brief structure describing convolutional code TCH/AFS 10.2 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_10_2 = { + .N = 3, + .K = 5, + .len = 210, + .term = CONV_TERM_FLUSH, + .next_output = osmo_conv_gsm0503_tch_afs_10_2_output, + .next_state = osmo_conv_gsm0503_tch_afs_10_2_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_10_2_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_10_2_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_10_2_puncture +}; + +extern const int osmo_conv_gsm0503_tch_afs_7_95_puncture[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_7_95_output[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_7_95_state[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_7_95_term_output[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_7_95_term_state[]; + +/*! \brief structure describing convolutional code TCH/AFS 7.95 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_7_95 = { + .N = 3, + .K = 7, + .len = 165, + .term = CONV_TERM_FLUSH, + .next_output = osmo_conv_gsm0503_tch_afs_7_95_output, + .next_state = osmo_conv_gsm0503_tch_afs_7_95_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_7_95_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_7_95_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_7_95_puncture +}; + +extern const int osmo_conv_gsm0503_tch_afs_7_4_puncture[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_7_4_output[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_7_4_state[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_7_4_term_output[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_7_4_term_state[]; + +/*! \brief structure describing convolutional code TCH/AFS 7.4 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_7_4 = { + .N = 3, + .K = 5, + .len = 154, + .term = CONV_TERM_FLUSH, + .next_output = osmo_conv_gsm0503_tch_afs_7_4_output, + .next_state = osmo_conv_gsm0503_tch_afs_7_4_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_7_4_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_7_4_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_7_4_puncture +}; + +extern const int osmo_conv_gsm0503_tch_afs_6_7_puncture[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_6_7_output[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_6_7_state[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_6_7_term_output[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_6_7_term_state[]; + +/*! \brief structure describing convolutional code TCH/AFS 6.7 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_6_7 = { + .N = 4, + .K = 5, + .len = 140, + .term = CONV_TERM_FLUSH, + .next_output = osmo_conv_gsm0503_tch_afs_6_7_output, + .next_state = osmo_conv_gsm0503_tch_afs_6_7_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_6_7_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_6_7_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_6_7_puncture +}; + +extern const int osmo_conv_gsm0503_tch_afs_5_9_puncture[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_5_9_output[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_5_9_state[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_5_9_term_output[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_5_9_term_state[]; + +/*! \brief structure describing convolutional code TCH/AFS 5.9 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_5_9 = { + .N = 4, + .K = 7, + .len = 124, + .term = CONV_TERM_FLUSH, + .next_output = osmo_conv_gsm0503_tch_afs_5_9_output, + .next_state = osmo_conv_gsm0503_tch_afs_5_9_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_5_9_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_5_9_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_5_9_puncture +}; + +extern const int osmo_conv_gsm0503_tch_afs_5_15_puncture[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_5_15_output[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_5_15_state[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_5_15_term_output[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_5_15_term_state[]; + +/*! \brief structure describing convolutional code TCH/AFS 5.15 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_5_15 = { + .N = 5, + .K = 5, + .len = 109, + .term = CONV_TERM_FLUSH, + .next_output = osmo_conv_gsm0503_tch_afs_5_15_output, + .next_state = osmo_conv_gsm0503_tch_afs_5_15_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_5_15_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_5_15_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_5_15_puncture +}; + +extern const int osmo_conv_gsm0503_tch_afs_4_75_puncture[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_4_75_output[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_4_75_state[][2]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_4_75_term_output[]; +extern const uint8_t osmo_conv_gsm0503_tch_afs_4_75_term_state[]; + +/*! \brief structure describing convolutional code TCH/AFS 4.75 + */ +static const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_4_75 = { + .N = 5, + .K = 7, + .len = 101, + .term = CONV_TERM_FLUSH, + .next_output = osmo_conv_gsm0503_tch_afs_4_75_output, + .next_state = osmo_conv_gsm0503_tch_afs_4_75_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_4_75_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_4_75_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_4_75_puncture +}; diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index 8c7f2be..a362a3b 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -18,6 +18,11 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \ gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \ gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \ lapd_core.c lapdm.c kasumi.c conv_xcch_gen.c conv_csx.c \ + conv_tch_afs.c conv_tch_afs_12_2_gen.c \ + conv_tch_afs_4_75_gen.c \ + conv_tch_afs_10_2_gen.c conv_tch_afs_7_95_gen.c \ + conv_tch_afs_7_4_gen.c conv_tch_afs_6_7_gen.c \ + conv_tch_afs_5_9_gen.c conv_tch_afs_5_15_gen.c \ auth_core.c auth_comp128v1.c auth_comp128v23.c \ auth_milenage.c milenage/aes-encblock.c \ milenage/aes-internal.c milenage/aes-internal-enc.c \ diff --git a/src/gsm/conv_tch_afs.c b/src/gsm/conv_tch_afs.c new file mode 100644 index 0000000..dd65e0d --- /dev/null +++ b/src/gsm/conv_tch_afs.c @@ -0,0 +1,119 @@ +/* + * conv_tch_afs.c + * + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +const int osmo_conv_gsm0503_tch_afs_12_2_puncture[] = { + 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 363, + 365, 369, 373, 377, 379, 381, 385, 389, 393, 395, 397, 401, + 405, 409, 411, 413, 417, 421, 425, 427, 429, 433, 437, 441, + 443, 445, 449, 453, 457, 459, 461, 465, 469, 473, 475, 477, + 481, 485, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, + -1, /* end */ +}; + +const int osmo_conv_gsm0503_tch_afs_10_2_puncture[] = { + 1, 4, 7, 10, 16, 19, 22, 28, 31, 34, 40, 43, + 46, 52, 55, 58, 64, 67, 70, 76, 79, 82, 88, 91, + 94, 100, 103, 106, 112, 115, 118, 124, 127, 130, 136, 139, + 142, 148, 151, 154, 160, 163, 166, 172, 175, 178, 184, 187, + 190, 196, 199, 202, 208, 211, 214, 220, 223, 226, 232, 235, + 238, 244, 247, 250, 256, 259, 262, 268, 271, 274, 280, 283, + 286, 292, 295, 298, 304, 307, 310, 316, 319, 322, 325, 328, + 331, 334, 337, 340, 343, 346, 349, 352, 355, 358, 361, 364, + 367, 370, 373, 376, 379, 382, 385, 388, 391, 394, 397, 400, + 403, 406, 409, 412, 415, 418, 421, 424, 427, 430, 433, 436, + 439, 442, 445, 448, 451, 454, 457, 460, 463, 466, 469, 472, + 475, 478, 481, 484, 487, 490, 493, 496, 499, 502, 505, 508, + 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, + 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, + 583, 586, 589, 592, 595, 598, 601, 604, 607, 609, 610, 613, + 616, 619, 621, 622, 625, 627, 628, 631, 633, 634, 636, 637, + 639, 640, + -1, /* end */ +}; + +const int osmo_conv_gsm0503_tch_afs_7_95_puncture[] = { + 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310, + 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367, + 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415, + 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463, + 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505, + 506, 508, 509, 511, 512, + -1, /* end */ +}; + +const int osmo_conv_gsm0503_tch_afs_7_4_puncture[] = { + 0, 355, 361, 367, 373, 379, 385, 391, 397, 403, 409, 415, + 421, 427, 433, 439, 445, 451, 457, 460, 463, 466, 468, 469, + 471, 472, + -1, /* end */ +}; + +const int osmo_conv_gsm0503_tch_afs_6_7_puncture[] = { + 1, 3, 7, 11, 15, 27, 39, 55, 67, 79, 95, 107, + 119, 135, 147, 159, 175, 187, 199, 215, 227, 239, 255, 267, + 279, 287, 291, 295, 299, 303, 307, 311, 315, 319, 323, 327, + 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 369, 371, + 375, 377, 379, 383, 385, 387, 391, 393, 395, 399, 401, 403, + 407, 409, 411, 415, 417, 419, 423, 425, 427, 431, 433, 435, + 439, 441, 443, 447, 449, 451, 455, 457, 459, 463, 465, 467, + 471, 473, 475, 479, 481, 483, 487, 489, 491, 495, 497, 499, + 503, 505, 507, 511, 513, 515, 519, 521, 523, 527, 529, 531, + 535, 537, 539, 543, 545, 547, 549, 551, 553, 555, 557, 559, + 561, 563, 565, 567, 569, 571, 573, 575, + -1, /* end */ +}; + +const int osmo_conv_gsm0503_tch_afs_5_9_puncture[] = { + 0, 1, 3, 5, 7, 11, 15, 31, 47, 63, 79, 95, + 111, 127, 143, 159, 175, 191, 207, 223, 239, 255, 271, 287, + 303, 319, 327, 331, 335, 343, 347, 351, 359, 363, 367, 375, + 379, 383, 391, 395, 399, 407, 411, 415, 423, 427, 431, 439, + 443, 447, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, + 495, 499, 503, 507, 509, 511, 512, 513, 515, 516, 517, 519, + -1, /* end */ +}; + +const int osmo_conv_gsm0503_tch_afs_5_15_puncture[] = { + 0, 4, 5, 9, 10, 14, 15, 20, 25, 30, 35, 40, + 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, + 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, + 290, 300, 310, 315, 320, 325, 330, 334, 335, 340, 344, 345, + 350, 354, 355, 360, 364, 365, 370, 374, 375, 380, 384, 385, + 390, 394, 395, 400, 404, 405, 410, 414, 415, 420, 424, 425, + 430, 434, 435, 440, 444, 445, 450, 454, 455, 460, 464, 465, + 470, 474, 475, 480, 484, 485, 490, 494, 495, 500, 504, 505, + 510, 514, 515, 520, 524, 525, 529, 530, 534, 535, 539, 540, + 544, 545, 549, 550, 554, 555, 559, 560, 564, + -1, /* end */ +}; + +const int osmo_conv_gsm0503_tch_afs_4_75_puncture[] = { + 0, 1, 2, 4, 5, 7, 9, 15, 25, 35, 45, 55, + 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, + 185, 195, 205, 215, 225, 235, 245, 255, 265, 275, 285, 295, + 305, 315, 325, 335, 345, 355, 365, 375, 385, 395, 400, 405, + 410, 415, 420, 425, 430, 435, 440, 445, 450, 455, 459, 460, + 465, 470, 475, 479, 480, 485, 490, 495, 499, 500, 505, 509, + 510, 515, 517, 519, 520, 522, 524, 525, 526, 527, 529, 530, + 531, 532, 534, + -1, /* end */ +}; diff --git a/src/gsm/conv_tch_afs_10_2_gen.c b/src/gsm/conv_tch_afs_10_2_gen.c new file mode 100644 index 0000000..a4c3826 --- /dev/null +++ b/src/gsm/conv_tch_afs_10_2_gen.c @@ -0,0 +1,79 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* TCH/AFS 10.2 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + */ + +/* .next_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_10_2_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, +}; + +/* .next_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_10_2_output[][2] = { + { 0, 7 }, + { 2, 5 }, + { 4, 3 }, + { 6, 1 }, + { 2, 5 }, + { 0, 7 }, + { 6, 1 }, + { 4, 3 }, + { 0, 7 }, + { 2, 5 }, + { 4, 3 }, + { 6, 1 }, + { 2, 5 }, + { 0, 7 }, + { 6, 1 }, + { 4, 3 }, +}; + +/* .next_term_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_10_2_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +/* .next_term_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_10_2_term_output[] = { + 0, 5, 3, 6, 5, 0, 6, 3, 7, 2, 4, 1, 2, 7, 1, 4, +}; diff --git a/src/gsm/conv_tch_afs_12_2_gen.c b/src/gsm/conv_tch_afs_12_2_gen.c new file mode 100644 index 0000000..e5e8a92 --- /dev/null +++ b/src/gsm/conv_tch_afs_12_2_gen.c @@ -0,0 +1,79 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* TCH/AFS 12.2 convolutional code: + 250 bits block, rate 1/2, punctured + G0/G0 = 1 + G1/G0 = 1 + D + D3 + D4 / 1 + D3 + D4 + */ + +/* .next_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_12_2_state[][2] = { + { 0, 1 }, + { 2, 3 }, + { 4, 5 }, + { 6, 7 }, + { 9, 8 }, + { 11, 10 }, + { 13, 12 }, + { 15, 14 }, + { 1, 0 }, + { 3, 2 }, + { 5, 4 }, + { 7, 6 }, + { 8, 9 }, + { 10, 11 }, + { 12, 13 }, + { 14, 15 }, +}; + +/* .next_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_12_2_output[][2] = { + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, +}; + +/* .next_term_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_12_2_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +/* .next_term_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_12_2_term_output[] = { + 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2, 0, 1, 0, 1, +}; diff --git a/src/gsm/conv_tch_afs_4_75_gen.c b/src/gsm/conv_tch_afs_4_75_gen.c new file mode 100644 index 0000000..9180fbc --- /dev/null +++ b/src/gsm/conv_tch_afs_4_75_gen.c @@ -0,0 +1,177 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* TCH/AFS 4.75 kbits convolutional code: + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 + */ + +/* .next_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_4_75_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 17, 16 }, + { 18, 19 }, + { 20, 21 }, + { 23, 22 }, + { 24, 25 }, + { 27, 26 }, + { 29, 28 }, + { 30, 31 }, + { 32, 33 }, + { 35, 34 }, + { 37, 36 }, + { 38, 39 }, + { 41, 40 }, + { 42, 43 }, + { 44, 45 }, + { 47, 46 }, + { 49, 48 }, + { 50, 51 }, + { 52, 53 }, + { 55, 54 }, + { 56, 57 }, + { 59, 58 }, + { 61, 60 }, + { 62, 63 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, + { 16, 17 }, + { 19, 18 }, + { 21, 20 }, + { 22, 23 }, + { 25, 24 }, + { 26, 27 }, + { 28, 29 }, + { 31, 30 }, + { 33, 32 }, + { 34, 35 }, + { 36, 37 }, + { 39, 38 }, + { 40, 41 }, + { 43, 42 }, + { 45, 44 }, + { 46, 47 }, + { 48, 49 }, + { 51, 50 }, + { 53, 52 }, + { 54, 55 }, + { 57, 56 }, + { 58, 59 }, + { 60, 61 }, + { 63, 62 }, +}; + +/* .next_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_4_75_output[][2] = { + { 0, 31 }, + { 24, 7 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 0, 31 }, + { 24, 7 }, + { 24, 7 }, + { 0, 31 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 24, 7 }, + { 0, 31 }, + { 24, 7 }, + { 0, 31 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 24, 7 }, + { 0, 31 }, + { 0, 31 }, + { 24, 7 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 0, 31 }, + { 24, 7 }, + { 0, 31 }, + { 24, 7 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 0, 31 }, + { 24, 7 }, + { 24, 7 }, + { 0, 31 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 24, 7 }, + { 0, 31 }, + { 24, 7 }, + { 0, 31 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 24, 7 }, + { 0, 31 }, + { 0, 31 }, + { 24, 7 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 0, 31 }, + { 24, 7 }, +}; + +/* .next_term_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_4_75_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, +}; + +/* .next_term_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_4_75_term_output[] = { + 0, 7, 27, 28, 27, 28, 0, 7, 7, 0, 28, 27, 28, 27, 7, 0, 24, 31, 3, 4, 3, 4, 24, 31, 31, 24, 4, 3, 4, 3, 31, 24, 31, 24, 4, 3, 4, 3, 31, 24, 24, 31, 3, 4, 3, 4, 24, 31, 7, 0, 28, 27, 28, 27, 7, 0, 0, 7, 27, 28, 27, 28, 0, 7, +}; diff --git a/src/gsm/conv_tch_afs_5_15_gen.c b/src/gsm/conv_tch_afs_5_15_gen.c new file mode 100644 index 0000000..1f20978 --- /dev/null +++ b/src/gsm/conv_tch_afs_5_15_gen.c @@ -0,0 +1,81 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* TCH/AFS 5.15 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 + */ + +/* .next_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_5_15_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, +}; + +/* .next_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_5_15_output[][2] = { + { 0, 31 }, + { 4, 27 }, + { 24, 7 }, + { 28, 3 }, + { 4, 27 }, + { 0, 31 }, + { 28, 3 }, + { 24, 7 }, + { 0, 31 }, + { 4, 27 }, + { 24, 7 }, + { 28, 3 }, + { 4, 27 }, + { 0, 31 }, + { 28, 3 }, + { 24, 7 }, +}; + +/* .next_term_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_5_15_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +/* .next_term_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_5_15_term_output[] = { + 0, 27, 7, 28, 27, 0, 28, 7, 31, 4, 24, 3, 4, 31, 3, 24, +}; diff --git a/src/gsm/conv_tch_afs_5_9_gen.c b/src/gsm/conv_tch_afs_5_9_gen.c new file mode 100644 index 0000000..1aa9b31 --- /dev/null +++ b/src/gsm/conv_tch_afs_5_9_gen.c @@ -0,0 +1,177 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* TCH/AFS 5.9 kbits convolutional code: + 124 bits + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 + */ + +/* .next_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_5_9_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 17, 16 }, + { 18, 19 }, + { 20, 21 }, + { 23, 22 }, + { 24, 25 }, + { 27, 26 }, + { 29, 28 }, + { 30, 31 }, + { 32, 33 }, + { 35, 34 }, + { 37, 36 }, + { 38, 39 }, + { 41, 40 }, + { 42, 43 }, + { 44, 45 }, + { 47, 46 }, + { 49, 48 }, + { 50, 51 }, + { 52, 53 }, + { 55, 54 }, + { 56, 57 }, + { 59, 58 }, + { 61, 60 }, + { 62, 63 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, + { 16, 17 }, + { 19, 18 }, + { 21, 20 }, + { 22, 23 }, + { 25, 24 }, + { 26, 27 }, + { 28, 29 }, + { 31, 30 }, + { 33, 32 }, + { 34, 35 }, + { 36, 37 }, + { 39, 38 }, + { 40, 41 }, + { 43, 42 }, + { 45, 44 }, + { 46, 47 }, + { 48, 49 }, + { 51, 50 }, + { 53, 52 }, + { 54, 55 }, + { 57, 56 }, + { 58, 59 }, + { 60, 61 }, + { 63, 62 }, +}; + +/* .next_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_5_9_output[][2] = { + { 0, 15 }, + { 8, 7 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 0, 15 }, + { 8, 7 }, + { 8, 7 }, + { 0, 15 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 8, 7 }, + { 0, 15 }, + { 8, 7 }, + { 0, 15 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 8, 7 }, + { 0, 15 }, + { 0, 15 }, + { 8, 7 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 0, 15 }, + { 8, 7 }, + { 0, 15 }, + { 8, 7 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 0, 15 }, + { 8, 7 }, + { 8, 7 }, + { 0, 15 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 8, 7 }, + { 0, 15 }, + { 8, 7 }, + { 0, 15 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 8, 7 }, + { 0, 15 }, + { 0, 15 }, + { 8, 7 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 0, 15 }, + { 8, 7 }, +}; + +/* .next_term_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_5_9_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, +}; + +/* .next_term_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_5_9_term_output[] = { + 0, 7, 11, 12, 11, 12, 0, 7, 7, 0, 12, 11, 12, 11, 7, 0, 8, 15, 3, 4, 3, 4, 8, 15, 15, 8, 4, 3, 4, 3, 15, 8, 15, 8, 4, 3, 4, 3, 15, 8, 8, 15, 3, 4, 3, 4, 8, 15, 7, 0, 12, 11, 12, 11, 7, 0, 0, 7, 11, 12, 11, 12, 0, 7, +}; diff --git a/src/gsm/conv_tch_afs_6_7_gen.c b/src/gsm/conv_tch_afs_6_7_gen.c new file mode 100644 index 0000000..fe17e7b --- /dev/null +++ b/src/gsm/conv_tch_afs_6_7_gen.c @@ -0,0 +1,80 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* TCH/AFS 6.7 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 + */ + +/* .next_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_6_7_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, +}; + +/* .next_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_6_7_output[][2] = { + { 0, 15 }, + { 4, 11 }, + { 8, 7 }, + { 12, 3 }, + { 4, 11 }, + { 0, 15 }, + { 12, 3 }, + { 8, 7 }, + { 0, 15 }, + { 4, 11 }, + { 8, 7 }, + { 12, 3 }, + { 4, 11 }, + { 0, 15 }, + { 12, 3 }, + { 8, 7 }, +}; + +/* .next_term_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_6_7_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +/* .next_term_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_6_7_term_output[] = { + 0, 11, 7, 12, 11, 0, 12, 7, 15, 4, 8, 3, 4, 15, 3, 8, +}; diff --git a/src/gsm/conv_tch_afs_7_4_gen.c b/src/gsm/conv_tch_afs_7_4_gen.c new file mode 100644 index 0000000..d4441c6 --- /dev/null +++ b/src/gsm/conv_tch_afs_7_4_gen.c @@ -0,0 +1,79 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* TCH/AFS 7.4 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + */ + +/* .next_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_7_4_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, +}; + +/* .next_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_7_4_output[][2] = { + { 0, 7 }, + { 2, 5 }, + { 4, 3 }, + { 6, 1 }, + { 2, 5 }, + { 0, 7 }, + { 6, 1 }, + { 4, 3 }, + { 0, 7 }, + { 2, 5 }, + { 4, 3 }, + { 6, 1 }, + { 2, 5 }, + { 0, 7 }, + { 6, 1 }, + { 4, 3 }, +}; + +/* .next_term_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_7_4_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +/* .next_term_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_7_4_term_output[] = { + 0, 5, 3, 6, 5, 0, 6, 3, 7, 2, 4, 1, 2, 7, 1, 4, +}; diff --git a/src/gsm/conv_tch_afs_7_95_gen.c b/src/gsm/conv_tch_afs_7_95_gen.c new file mode 100644 index 0000000..f89be5b --- /dev/null +++ b/src/gsm/conv_tch_afs_7_95_gen.c @@ -0,0 +1,175 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +/* TCH/AFS 7.95 kbits convolutional code: + G4/G4 = 1 + G5/G4 = 1 + D + D4 + D6 / 1 + D2 + D3 + D5 + D6 + G6/G4 = 1 + D + D2 + D3 + D4 + D6 / 1 + D2 + D3 + D5 + D6 + */ + +/* .next_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_7_95_state[][2] = { + { 0, 1 }, + { 2, 3 }, + { 5, 4 }, + { 7, 6 }, + { 9, 8 }, + { 11, 10 }, + { 12, 13 }, + { 14, 15 }, + { 16, 17 }, + { 18, 19 }, + { 21, 20 }, + { 23, 22 }, + { 25, 24 }, + { 27, 26 }, + { 28, 29 }, + { 30, 31 }, + { 33, 32 }, + { 35, 34 }, + { 36, 37 }, + { 38, 39 }, + { 40, 41 }, + { 42, 43 }, + { 45, 44 }, + { 47, 46 }, + { 49, 48 }, + { 51, 50 }, + { 52, 53 }, + { 54, 55 }, + { 56, 57 }, + { 58, 59 }, + { 61, 60 }, + { 63, 62 }, + { 1, 0 }, + { 3, 2 }, + { 4, 5 }, + { 6, 7 }, + { 8, 9 }, + { 10, 11 }, + { 13, 12 }, + { 15, 14 }, + { 17, 16 }, + { 19, 18 }, + { 20, 21 }, + { 22, 23 }, + { 24, 25 }, + { 26, 27 }, + { 29, 28 }, + { 31, 30 }, + { 32, 33 }, + { 34, 35 }, + { 37, 36 }, + { 39, 38 }, + { 41, 40 }, + { 43, 42 }, + { 44, 45 }, + { 46, 47 }, + { 48, 49 }, + { 50, 51 }, + { 53, 52 }, + { 55, 54 }, + { 57, 56 }, + { 59, 58 }, + { 60, 61 }, + { 62, 63 }, +}; + +/* .next_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_7_95_output[][2] = { + { 0, 7 }, + { 3, 4 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 0, 7 }, + { 3, 4 }, + { 3, 4 }, + { 0, 7 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 3, 4 }, + { 0, 7 }, + { 3, 4 }, + { 0, 7 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 3, 4 }, + { 0, 7 }, + { 0, 7 }, + { 3, 4 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 0, 7 }, + { 3, 4 }, + { 0, 7 }, + { 3, 4 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 0, 7 }, + { 3, 4 }, + { 3, 4 }, + { 0, 7 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 3, 4 }, + { 0, 7 }, + { 3, 4 }, + { 0, 7 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 3, 4 }, + { 0, 7 }, + { 0, 7 }, + { 3, 4 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 0, 7 }, + { 3, 4 }, +}; + +/* .next_term_state */ +const uint8_t osmo_conv_gsm0503_tch_afs_7_95_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, +}; + +/* .next_term_output */ +const uint8_t osmo_conv_gsm0503_tch_afs_7_95_term_output[] = { + 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5, 6, 5, 3, 0, 4, 7, 1, 2, 1, 2, 4, 7, 7, 4, 2, 1, 2, 1, 7, 4, 7, 4, 2, 1, 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7, 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6, 5, 6, 0, 3, +}; diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index 6e99b2e..3032ee0 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -16,82 +16,6 @@ /* Test codes */ /* ------------------------------------------------------------------------ */ -/* GSM TCH/AFS 7.95 -> Recursive code, flushed, with puncturing */ -static const uint8_t conv_gsm_tch_afs_7_95_next_output[][2] = { - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 5, 4 }, { 7, 6 }, - { 9, 8 }, { 11, 10 }, { 12, 13 }, { 14, 15 }, - { 16, 17 }, { 18, 19 }, { 21, 20 }, { 23, 22 }, - { 25, 24 }, { 27, 26 }, { 28, 29 }, { 30, 31 }, - { 33, 32 }, { 35, 34 }, { 36, 37 }, { 38, 39 }, - { 40, 41 }, { 42, 43 }, { 45, 44 }, { 47, 46 }, - { 49, 48 }, { 51, 50 }, { 52, 53 }, { 54, 55 }, - { 56, 57 }, { 58, 59 }, { 61, 60 }, { 63, 62 }, - { 1, 0 }, { 3, 2 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 13, 12 }, { 15, 14 }, - { 17, 16 }, { 19, 18 }, { 20, 21 }, { 22, 23 }, - { 24, 25 }, { 26, 27 }, { 29, 28 }, { 31, 30 }, - { 32, 33 }, { 34, 35 }, { 37, 36 }, { 39, 38 }, - { 41, 40 }, { 43, 42 }, { 44, 45 }, { 46, 47 }, - { 48, 49 }, { 50, 51 }, { 53, 52 }, { 55, 54 }, - { 57, 56 }, { 59, 58 }, { 60, 61 }, { 62, 63 }, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_term_output[] = { - 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5, 6, 5, 3, 0, - 4, 7, 1, 2, 1, 2, 4, 7, 7, 4, 2, 1, 2, 1, 7, 4, - 7, 4, 2, 1, 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7, - 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6, 5, 6, 0, 3, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_term_state[] = { - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, -}; - -static int conv_gsm_tch_afs_7_95_puncture[] = { - 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310, - 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367, - 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415, - 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463, - 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505, - 506, 508, 509, 511, 512, - -1, /* end */ -}; - -static const struct osmo_conv_code conv_gsm_tch_afs_7_95 = { - .N = 3, - .K = 7, - .len = 165, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_tch_afs_7_95_next_output, - .next_state = conv_gsm_tch_afs_7_95_next_state, - .next_term_output = conv_gsm_tch_afs_7_95_next_term_output, - .next_term_state = conv_gsm_tch_afs_7_95_next_term_state, - .puncture = conv_gsm_tch_afs_7_95_puncture, -}; - - /* GMR-1 TCH3 Speech -> Non recursive code, tail-biting, punctured */ static const uint8_t conv_gmr1_tch3_speech_next_output[][2] = { { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, @@ -244,7 +168,7 @@ static const struct conv_test_vector tests[] = { }, { .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)", - .code = &conv_gsm_tch_afs_7_95, + .code = &osmo_conv_gsm0503_tch_afs_7_95, .in_len = 165, .out_len = 448, .has_vec = 1, -- 2.8.1 From msuraev at sysmocom.de Mon Apr 11 14:22:46 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 11 Apr 2016 16:22:46 +0200 Subject: [PATCH 1/4] Add code generator for convolutional codes Message-ID: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> From: Max Add python utility to generate .c code with state/output tables for convolutional encoder/decoder based on polynomial description of the code. If argument given it'll be interpreted as intended output directory, otherwise current working directory is used. Note: only necessary tables are generated. Corresponding header files with actual osmo_conv_code instance (including puncturing etc) have to be added manually. Fixes: OS#1629 --- utils/conv_gen.py | 359 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100755 utils/conv_gen.py diff --git a/utils/conv_gen.py b/utils/conv_gen.py new file mode 100755 index 0000000..52c1ab3 --- /dev/null +++ b/utils/conv_gen.py @@ -0,0 +1,359 @@ +#!/usr/bin/python + +license =""" +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +""" + +import sys, os + +class ConvolutionalCode(object): + + def __init__(self, block_len, k, polys, name = "call-me", description = "LOL"): + # Save simple params + self.block_len = block_len + self.k = k + self.rate_inv = len(polys) + + # Infos + self.name = name + self.description = description + + # Handle polynoms (and check for recursion) + self.polys = [(1, 1) if x[0] == x[1] else x for x in polys] + + rp = [x[1] for x in self.polys if x[1] != 1] + if rp: + if not all([x == rp[0] for x in rp]): + raise ValueError("Bad polynoms: Can't have multiple different divider polynoms !") + if not all([x[0] == 1 for x in polys if x[1] == 1]): + raise ValueError("Bad polynoms: Can't have a '1' divider with a non '1' dividend in a recursive code") + self.poly_divider = rp[0] + else: + self.poly_divider = 1 + + @property + def recursive(self): + return self.poly_divider != 1 + + def _combine(self, src, sel, nb): + x = src & sel + fn_xor = lambda x, y: x ^ y + return reduce(fn_xor, [(x >> n) & 1 for n in range(nb)]) + + @property + def _state_mask(self): + return ((1 << (self.k - 1)) - 1) + + def next_state(self, state, bit): + nb = self._combine( + (state << 1) | bit, + self.poly_divider, + self.k, + ) + return ((state << 1) | nb) & self._state_mask + + def next_term_state(self, state): + return (state << 1) & self._state_mask + + def next_output(self, state, bit, ns = None): + # Next state bit + if ns is None: + ns = self.next_state(state, bit) + + src = (ns & 1) | (state << 1) + + # Scan polynoms + rv = [] + for p_n, p_d in self.polys: + if self.recursive and p_d == 1: + o = bit # No choice ... (systematic output in recursive case) + else: + o = self._combine(src, p_n, self.k) + rv.append(o) + + return rv + + def next_term_output(self, state, ns = None): + # Next state bit + if ns is None: + ns = self.next_term_state(state) + + src = (ns & 1) | (state << 1) + + # Scan polynoms + rv = [] + for p_n, p_d in self.polys: + if self.recursive and p_d == 1: + # Systematic output are replaced when in 'termination' mode + o = self._combine(src, self.poly_divider, self.k) + else: + o = self._combine(src, p_n, self.k) + rv.append(o) + + return rv + + def next(self, state, bit): + ns = self.next_state(state, bit) + nb = self.next_output(state, bit, ns = ns) + return ns, nb + + def next_term(self, state): + ns = self.next_term_state(state) + nb = self.next_term_output(state, ns = ns) + return ns, nb + + def _print_term(self, pref, fi, num_states, pack, is_state = True): + s = "state" if is_state else "output" + print >>fi, "\n/* .next_term_%s */" % s + print >>fi, "const uint8_t %s_%s_term_%s[] = {" % (pref, self.name, s) + d = [] + for state in range(num_states): + if is_state: + x = self.next_term_state(state) + else: + x = pack(self.next_term_output(state)) + d.append("%d, " % x) + print >>fi, "\t%s\n};" % ''.join(d) + + def _print_x(self, pref, fi, num_states, pack, is_state = True): + s = "state" if is_state else "output" + print >>fi, "\n/* .next_%s */" % s + print >>fi, "const uint8_t %s_%s_%s[][2] = {" % (pref, self.name, s) + for state in range(num_states): + if is_state: + x0 = self.next_state(state, 0) + x1 = self.next_state(state, 1) + else: + x0 = pack(self.next_output(state, 0)) + x1 = pack(self.next_output(state, 1)) + print >>fi, "\t{ %2d, %2d }," % (x0, x1) + print >>fi, "};" + + def gen_tables(self, pref, fi): + pack = lambda n: sum([x << (self.rate_inv - i - 1) for i, x in enumerate(n)]) + num_states = 1 << (self.k - 1) + print >>fi, "\n/* %s */" % self.description + #print >>fi, "const int %s_%s_length = %d;" % (pref, self.name, self.block_len) + #print >>fi, "const int %s_%s_K = %d;" % (pref, self.name, self.k) + self._print_x(pref, fi, num_states, pack) + self._print_x(pref, fi, num_states, pack, False) + + if self.recursive: + self._print_term(pref, fi, num_states, pack) + self._print_term(pref, fi, num_states, pack, False) + +poly = lambda *args: sum([(1 << x) for x in args]) + +xcch = ConvolutionalCode( + 224, 5, + [ + ( poly(0, 3, 4), 1 ), + ( poly(0, 1, 3, 4), 1 ), + ], + name = "xcch", + description =""" *CCH convolutional code: + 228 bits blocks, rate 1/2, k = 5 + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 +""" +) + +tch_afs_12_2 = ConvolutionalCode( + 250, 5, + [ + ( 1, 1 ), + ( poly(0, 1, 3, 4), poly(0, 3, 4) ), + ], + name = 'tch_afs_12_2', + description = """TCH/AFS 12.2 convolutional code: + 250 bits block, rate 1/2, punctured + G0/G0 = 1 + G1/G0 = 1 + D + D3 + D4 / 1 + D3 + D4 +""" +) + +tch_afs_10_2 = ConvolutionalCode( + 210, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ], + name = 'tch_afs_10_2', + description = """TCH/AFS 10.2 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 +""" +) + +tch_afs_7_95 = ConvolutionalCode( + 165, 7, + [ + ( 1, 1 ), + ( poly(0, 1, 4, 6), poly(0, 2, 3, 5, 6) ), + ( poly(0, 1, 2, 3, 4, 6), poly(0, 2, 3, 5, 6) ), + ], + name = 'tch_afs_7_95', + description = """TCH/AFS 7.95 kbits convolutional code: + G4/G4 = 1 + G5/G4 = 1 + D + D4 + D6 / 1 + D2 + D3 + D5 + D6 + G6/G4 = 1 + D + D2 + D3 + D4 + D6 / 1 + D2 + D3 + D5 + D6 +""" +) + +tch_afs_7_4 = ConvolutionalCode( + 154, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ], + name = 'tch_afs_7_4', + description = """TCH/AFS 7.4 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 +""" +) + +tch_afs_6_7 = ConvolutionalCode( + 140, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ( 1, 1 ), + ], + name = 'tch_afs_6_7', + description = """TCH/AFS 6.7 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 +""" +) + +tch_afs_5_9 = ConvolutionalCode( + 124, 7, + [ + ( poly(0, 2, 3, 5, 6), poly(0, 1, 2, 3, 4, 6) ), + ( poly(0, 1, 4, 6), poly(0, 1, 2, 3, 4, 6) ), + ( 1, 1), + ( 1, 1), + ], + name = 'tch_afs_5_9', + description = """TCH/AFS 5.9 kbits convolutional code: + 124 bits + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 +""" +) + +tch_afs_5_15 = ConvolutionalCode( + 109, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ( 1, 1 ), + ], + name = 'tch_afs_5_15', + description = """TCH/AFS 5.15 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 +""" +) + +tch_afs_4_75 = ConvolutionalCode( + 101, 7, + [ + ( poly(0, 2, 3, 5, 6), poly(0, 1, 2, 3, 4, 6) ), + ( poly(0, 2, 3, 5, 6), poly(0, 1, 2, 3, 4, 6) ), + ( poly(0, 1, 4, 6), poly(0, 1, 2, 3, 4, 6) ), + ( 1, 1 ), + ( 1, 1 ), + ], + name = 'tch_afs_4_75', + description = """TCH/AFS 4.75 kbits convolutional code: + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 +""" +) + +tetra_rcpc = ConvolutionalCode( + 288, 5, + [ + ( poly(0,1,4), 1 ), + ( poly(0,2,3,4), 1 ), + ( poly(0,1,2,4), 1 ), + ( poly(0,1,3,4), 1 ), + ], + name = 'tetra_rcpc', + description = """TETRA RCPC code + G1 = 1 + D + D4 + G2 = 1 + D2 + D3 + D4 + G3 = 1 + D + D2 + D4 + G4 = 1 + D + D3 + D4 +""" +) + +tetra_rcpc_tch = ConvolutionalCode( + 288, 5, + [ + ( poly(0, 1, 2, 3, 4), 1 ), + ( poly(0, 1, 3, 4), 1 ), + ( poly(0, 2, 4), 1 ), + ], + description = """TETRA RCPC TCH code +""" +) + +def gen_c(path, prefix, code): + f = open(os.path.join(path, 'conv_' + code.name + '_gen.c'), 'w') + print >>f, license + print >>f, "#include " + code.gen_tables(prefix, f) + +if __name__ == '__main__': + print >>sys.stderr, "Generating convolutional codes..." + prefix = "osmo_conv_gsm0503" + path = sys.argv[1] if len(sys.argv) > 1 else os.getcwd() + gen_c(path, prefix, xcch) + gen_c(path, prefix, tch_afs_12_2) + gen_c(path, prefix, tch_afs_10_2) + gen_c(path, prefix, tch_afs_7_95) + gen_c(path, prefix, tch_afs_7_4) + gen_c(path, prefix, tch_afs_6_7) + gen_c(path, prefix, tch_afs_5_9) + gen_c(path, prefix, tch_afs_5_15) + gen_c(path, prefix, tch_afs_4_75) + print >>sys.stderr, "\tdone." -- 2.8.1 From msuraev at sysmocom.de Mon Apr 11 14:57:34 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 11 Apr 2016 16:57:34 +0200 Subject: [PATCH] Add bssgp_pdu_str to libosmogb namespace Message-ID: <1460386654-19512-1-git-send-email-msuraev@sysmocom.de> From: Max --- src/gb/libosmogb.map | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map index 75406c0..9aec280 100644 --- a/src/gb/libosmogb.map +++ b/src/gb/libosmogb.map @@ -2,6 +2,7 @@ LIBOSMOGB_1.0 { global: bssgp_cause_str; bssgp_create_cell_id; +bssgp_pdu_str; bssgp_fc_in; bssgp_fc_init; bssgp_fc_ms_init; -- 2.8.1 From nhofmeyr at sysmocom.de Mon Apr 11 15:23:02 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 11 Apr 2016 17:23:02 +0200 Subject: new subscriber connection Message-ID: <20160411152302.GB28465@ass40.sysmocom.de> Hi list, implementing paging on Iu-CS directed my attention to the following situation: What if a subscriber connects to the CN while another connection with the same subscriber is still recorded active? In the Iu case, one would expect an Iu-Release or a Reset message and invalidate old connections before a new connection would be established, but we can't/don't want to rely on that. A scenario would be that an hNodeB were suddenly powered down and the UE starts subscribing to another hNodeB nearby, or the UE moves to a new LAC and reconnects using an entirely different SUA link. So basically I'm saying, when a new gsm_subscriber_connection is established and, from the Location Updating procedure, the conn gets associated with an actual gsm_subscriber instance, I guess we should walk the conn list and discard all other connections that this gsm_subscriber still has open ... does that make sense? At least for Iu, there should never be more than one conn_id of a SUA link associated with the same gsm_subscriber, let alone more than one SUA link. I browsed the gsm_04_08.c related code paths but so far couldn't find anything that would discard old gsm_subscriber_connections upon establishing a new location update for a given gsm_subscriber. Is there a timeout for gsm_subscriber_connections? It's not the anchor_timeout() from gsm_04_08.c, right? That's only while establishing a link... Am I on the right track here? If yes, should we discard old conns as soon as the subscriber's IMSI is first seen on a new link, or only after a new Location Update is completed successfully? Thanks! ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From 246tnt at gmail.com Mon Apr 11 17:28:20 2016 From: 246tnt at gmail.com (Sylvain Munaut) Date: Mon, 11 Apr 2016 19:28:20 +0200 Subject: [PATCH 2/4] Add concolutional code generator for *CCH In-Reply-To: <1460384569-13790-2-git-send-email-msuraev@sysmocom.de> References: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> <1460384569-13790-2-git-send-email-msuraev@sysmocom.de> Message-ID: Why would you put the conv code struct in the .h ? And why expose the tables in the public symbols ? The fact you can 'reuse' the tables in the test is really no reason to pollute the API namespace. Cheers, Sylvain From laforge at gnumonks.org Mon Apr 11 22:23:52 2016 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 12 Apr 2016 00:23:52 +0200 Subject: [PATCH] remove two compiler warnings for unused variables In-Reply-To: <1460069165-5638-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460069165-5638-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20160411222352.GD15746@nataraja> Hi Max, I disagree with this patch. We don't want to make all warnings quiet at all cost. If that was the goal, we could simply disable compiler warnings and go ahead. The point is that the SUA code is incomplete, and I prefer to have a warning about it until it gets properly fixed. This: On Fri, Apr 08, 2016 at 12:46:05AM +0200, Neels Hofmeyr wrote: > - cause = xua_msg_get_u32(xua, SUA_IEI_CAUSE); > + /* TODO evaluate cause: > + * cause = xua_msg_get_u32(xua, SUA_IEI_CAUSE); */ will just mean that we all forget about having to fix it. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Mon Apr 11 22:21:31 2016 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 12 Apr 2016 00:21:31 +0200 Subject: [PATCH 2/4] Add concolutional code generator for *CCH In-Reply-To: References: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> <1460384569-13790-2-git-send-email-msuraev@sysmocom.de> Message-ID: <20160411222131.GC15746@nataraja> Hi Max, On Mon, Apr 11, 2016 at 07:28:20PM +0200, Sylvain Munaut wrote: > Why would you put the conv code struct in the .h ? I have to agree with Sylvain here, and fail to see the reason for the above design decisions. Particularly in a shared library like libosmocore/libosmogsm, the definition of the data should be in a C file that is actually shared read-only text to all its users, while the header files only contain forward declarations. > And why expose the tables in the public symbols ? Indeed let's try to avoid this if possible. > The fact you can 'reuse' the tables in the test is really no reason to > pollute the API namespace. If I understand the code corectly, users would interact with it by means of the 'struct osmo_conv_code'. So that one would have to be declared in a header file, like: extern const struct osmo_conv_code osmo_conv_gsm0503_xcch; This kind of symbol would have to be exported in the .map file for actual consumption by the users of the library. which is then subsequently defined in a C file: const struct osmo_conv_code osmo_conv_gsm0503_xcch = { ... } But why would those declaraions below be in a header file? Why are those relevant to the user? +extern const uint8_t osmo_conv_gsm0503_xcch_output[][2]; +extern const uint8_t osmo_conv_gsm0503_xcch_state[][2]; Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From holger at freyther.de Mon Apr 11 23:01:04 2016 From: holger at freyther.de (Holger Freyther) Date: Mon, 11 Apr 2016 19:01:04 -0400 Subject: [PATCH] Add bssgp_pdu_str to libosmogb namespace In-Reply-To: <1460386654-19512-1-git-send-email-msuraev@sysmocom.de> References: <1460386654-19512-1-git-send-email-msuraev@sysmocom.de> Message-ID: <3175DEBA-49A9-47DF-AB6C-6B368D1027F2@freyther.de> > On 11 Apr 2016, at 10:57, msuraev at sysmocom.de wrote: where do you want to use the symbol? From tom at tsou.cc Tue Apr 12 00:04:13 2016 From: tom at tsou.cc (Tom Tsou) Date: Mon, 11 Apr 2016 17:04:13 -0700 Subject: osmo-bts-trx: "CHAN RQD: no resources for SDCCH" on master In-Reply-To: <20160409102553.GE16522@nataraja> References: <20160409084941.GD16522@nataraja> <20160409102553.GE16522@nataraja> Message-ID: Harald, Thank you for the thorough log analysis which is greatly helpful. On Sat, Apr 9, 2016 at 3:25 AM, Harald Welte wrote: > Looking at the got log, the above function call of > oml_mo_tx_sw_act_rep() for the baseband transceiver was always sent > unconditionally from within check_tranceiver_availability() even in > Jolly's original osmo-bts-trx code from February 2013, see commit > acc71ffb4b61b3354bbb2fa14981e4e6a46946e6. THe code even states that iti > s a HACK and it should only be done once we receive CLOCK indications > from osmo-trx. However, even that is wrong, as CLOCK is already > received in Frame 11, too soon to make that a criterion. I noticed the behavior surrounding check_transceiver_availability() seemed suspect, but I wasn't sure about related effects. Indeed, if I restrict sections of check_transceiver_availability() containing oml_mo_tx_sw_act_rep() to running once, I am able to reach a functional OML setup (sometimes to the point of TCH channel establishment). Related is the question of when osmo-trx should send CLOCK indications. Right now a CLOCK indications is sent with arrival of commands on the control interface. After starting, CLOCK indications are sent at an one second interval (216 frames). The indications sent from the control interface are why osmo-bts is receiving CLOCK so early. > Solution: > * OML initialization (the most complex part of Abis) needs to be > more properly handled. No part of the code should do something like > dynamically sending software activation reports at runtime. In > osm-bts-trx, every time 'transceiver_available' goes from 0->1 (which > apparently can happen even after start), a software activation report > is sent to the BSC. This is wrong. The software is only activated > once during boot, and it is activated not before the parent MOs for > BTS and Site Manager are enabled. I can confirm that the sending of SW activation reports is currently broken and prevents usable operation with osmo-bts-trx. To start, I'll look into a better approach to the 'transceiver_available' state and limiting SW activation messages. Hopefully that can at least get us to a usable state with osmo-bts-trx. > Unrelated to that, osmo-bts-trx desparately needs to avoid the use of > global variables. Each gsm_bts_trx / gsm_bts / phy_link / phy_instance > has private data store for implementation-specific state. global > variables have always been discouraged. Agreed and noted. -TT From msuraev at sysmocom.de Tue Apr 12 08:09:53 2016 From: msuraev at sysmocom.de (Max) Date: Tue, 12 Apr 2016 10:09:53 +0200 Subject: [PATCH] Add bssgp_pdu_str to libosmogb namespace In-Reply-To: <3175DEBA-49A9-47DF-AB6C-6B368D1027F2@freyther.de> References: <1460386654-19512-1-git-send-email-msuraev@sysmocom.de> <3175DEBA-49A9-47DF-AB6C-6B368D1027F2@freyther.de> Message-ID: <570CAD51.7090203@sysmocom.de> In OsmoPCU. On 04/12/2016 01:01 AM, Holger Freyther wrote: >> On 11 Apr 2016, at 10:57, msuraev at sysmocom.de wrote: > > where do you want to use the symbol? > > -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From kluchnikovi at gmail.com Tue Apr 12 10:48:57 2016 From: kluchnikovi at gmail.com (Ivan Kluchnikov) Date: Tue, 12 Apr 2016 13:48:57 +0300 Subject: [PATCH 1/2] Add support of virtual networks for sending network name to ms depending on imsi Message-ID: <1460458138-12207-1-git-send-email-kluchnikovi@gmail.com> Before sending mm info message to ms: - extract mcc and mnc from imsi - try to find virtual network with the same mcc and mnc - if virtual network was found, use long and short network names of this virtual network for subscriber - if virtual network was not found, use long and short network names of main network for subscriber --- openbsc/include/openbsc/gsm_data.h | 16 ++++ openbsc/include/openbsc/vty.h | 1 + openbsc/src/libbsc/bsc_vty.c | 156 +++++++++++++++++++++++++++++++++++++ openbsc/src/libbsc/net_init.c | 1 + openbsc/src/libcommon/common_vty.c | 9 +++ openbsc/src/libcommon/gsm_data.c | 42 ++++++++++ openbsc/src/libmsc/gsm_04_08.c | 45 +++++++++-- 7 files changed, 262 insertions(+), 8 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 6d7aba3..9a52254 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -248,6 +248,9 @@ struct gsm_network { unsigned int num_bts; struct llist_head bts_list; + unsigned int num_virt_net; + struct llist_head virt_net_list; + /* timer values */ int T3101; int T3103; @@ -293,6 +296,16 @@ struct gsm_network { struct ctrl_handle *ctrl; }; +struct gsm_virt_network { + struct llist_head list; + uint8_t nr; + struct gsm_network *network; + uint16_t country_code; + uint16_t network_code; + char *name_long; + char *name_short; +}; + struct osmo_esme; enum gsm_sms_source_id { @@ -435,6 +448,9 @@ int gsm_bts_model_register(struct gsm_bts_model *model); struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan); void subscr_con_free(struct gsm_subscriber_connection *conn); +struct gsm_virt_network *gsm_virt_net_alloc_register(struct gsm_network *net); +struct gsm_virt_network *gsm_virt_net_num(struct gsm_network *net, int num); + struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_type type, uint8_t bsic); diff --git a/openbsc/include/openbsc/vty.h b/openbsc/include/openbsc/vty.h index bc30e23..2848702 100644 --- a/openbsc/include/openbsc/vty.h +++ b/openbsc/include/openbsc/vty.h @@ -17,6 +17,7 @@ extern struct cmd_element cfg_no_description_cmd; enum bsc_vty_node { GSMNET_NODE = _LAST_OSMOVTY_NODE + 1, + VIRT_NET_NODE, BTS_NODE, TRX_NODE, TS_NODE, diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 29f2501..b414395 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -112,6 +112,12 @@ struct cmd_node net_node = { 1, }; +struct cmd_node virt_net_node = { + VIRT_NET_NODE, + "%s(config-net-virt)# ", + 1, +}; + struct cmd_node bts_node = { BTS_NODE, "%s(config-net-bts)# ", @@ -343,6 +349,42 @@ DEFUN(show_bts, show_bts_cmd, "show bts [<0-255>]", return CMD_SUCCESS; } +static void virt_net_dump_vty(struct vty *vty, struct gsm_virt_network *virt_net) +{ + vty_out(vty, "Virtual network %u%s", virt_net->nr, VTY_NEWLINE); + vty_out(vty, " Country Code %u, Network Code %u%s", + virt_net->country_code, virt_net->network_code, VTY_NEWLINE); + vty_out(vty, " Long network name: '%s'%s", + virt_net->name_long, VTY_NEWLINE); + vty_out(vty, " Short network name: '%s'%s", + virt_net->name_short, VTY_NEWLINE); +} + +DEFUN(show_virt_net, show_virt_net_cmd, "show virtual-network [<0-255>]", + SHOW_STR "Display information about a virtual network\n" + "Virtual network number") +{ + struct gsm_network *net = gsmnet_from_vty(vty); + int virt_net_nr; + + if (argc != 0) { + /* use the virtual network number that the user has specified */ + virt_net_nr = atoi(argv[0]); + if (virt_net_nr >= net->num_virt_net) { + vty_out(vty, "%% can't find virtual network '%s'%s", argv[0], + VTY_NEWLINE); + return CMD_WARNING; + } + virt_net_dump_vty(vty, gsm_virt_net_num(net, virt_net_nr)); + return CMD_SUCCESS; + } + /* print all virtual networks */ + for (virt_net_nr = 0; virt_net_nr < net->num_virt_net; virt_net_nr++) + virt_net_dump_vty(vty, gsm_virt_net_num(net, virt_net_nr)); + + return CMD_SUCCESS; +} + /* utility functions */ static void parse_e1_link(struct gsm_e1_subslot *e1_link, const char *line, const char *ts, const char *ss) @@ -743,6 +785,26 @@ static int config_write_bts(struct vty *v) return CMD_SUCCESS; } +static void config_write_virt_net_single(struct vty *vty, struct gsm_virt_network *virt_net) +{ + vty_out(vty, " virtual-network %u%s", virt_net->nr, VTY_NEWLINE); + vty_out(vty, " network country code %u%s", virt_net->country_code, VTY_NEWLINE); + vty_out(vty, " mobile network code %u%s", virt_net->network_code, VTY_NEWLINE); + vty_out(vty, " short name %s%s", virt_net->name_short, VTY_NEWLINE); + vty_out(vty, " long name %s%s", virt_net->name_long, VTY_NEWLINE); +} + +static int config_write_virt_net(struct vty *v) +{ + struct gsm_network *gsmnet = gsmnet_from_vty(v); + struct gsm_virt_network *virt_net; + + llist_for_each_entry(virt_net, &gsmnet->virt_net_list, list) + config_write_virt_net_single(v, virt_net); + + return CMD_SUCCESS; +} + static int config_write_net(struct vty *vty) { struct gsm_network *gsmnet = gsmnet_from_vty(vty); @@ -1612,6 +1674,91 @@ DEFUN(cfg_net_subscr_keep, return CMD_SUCCESS; } +DEFUN(cfg_virt_net, + cfg_virt_net_cmd, + "virtual-network <0-255>", + "Select a virtual network to configure\n" + "Virtual-network Number\n") +{ + struct gsm_network *gsmnet = gsmnet_from_vty(vty); + int virt_net_nr = atoi(argv[0]); + struct gsm_virt_network *virt_net; + + if (virt_net_nr > gsmnet->num_virt_net) { + vty_out(vty, "%% The next unused Virtual-network number is %u%s", + gsmnet->num_virt_net, VTY_NEWLINE); + return CMD_WARNING; + } else if (virt_net_nr == gsmnet->num_virt_net) { + /* allocate a new one */ + virt_net = gsm_virt_net_alloc_register(gsmnet); + } else + virt_net = gsm_virt_net_num(gsmnet, virt_net_nr); + + if (!virt_net) { + vty_out(vty, "%% Unable to allocate Virtual-network %u%s", + gsmnet->num_virt_net, VTY_NEWLINE); + return CMD_WARNING; + } + + vty->index = virt_net; + vty->index_sub = NULL; + vty->node = VIRT_NET_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_virt_net_ncc, + cfg_virt_net_ncc_cmd, + "network country code <1-999>", + "Set the GSM network country code\n" + "Country commands\n" + CODE_CMD_STR + "Network Country Code to use\n") +{ + struct gsm_virt_network *virt_net = vty->index; + + virt_net->country_code = atoi(argv[0]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_virt_net_mnc, + cfg_virt_net_mnc_cmd, + "mobile network code <0-999>", + "Set the GSM mobile network code\n" + "Network Commands\n" + CODE_CMD_STR + "Mobile Network Code to use\n") +{ + struct gsm_virt_network *virt_net = vty->index; + + virt_net->network_code = atoi(argv[0]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_virt_net_name_short, + cfg_virt_net_name_short_cmd, + "short name NAME", + "Set the short GSM network name\n" NAME_CMD_STR NAME_STR) +{ + struct gsm_virt_network *virt_net = vty->index; + + bsc_replace_string(virt_net->network, &virt_net->name_short, argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_virt_net_name_long, + cfg_virt_net_name_long_cmd, + "long name NAME", + "Set the long GSM network name\n" NAME_CMD_STR NAME_STR) +{ + struct gsm_virt_network *virt_net = vty->index; + + bsc_replace_string(virt_net->network, &virt_net->name_long, argv[0]); + return CMD_SUCCESS; +} + /* per-BTS configuration */ DEFUN(cfg_bts, cfg_bts_cmd, @@ -3763,6 +3910,7 @@ int bsc_vty_init(const struct log_info *cat) install_element_ve(&show_net_cmd); + install_element_ve(&show_virt_net_cmd); install_element_ve(&show_bts_cmd); install_element_ve(&show_trx_cmd); install_element_ve(&show_ts_cmd); @@ -3811,6 +3959,14 @@ int bsc_vty_init(const struct log_info *cat) install_element(GSMNET_NODE, &cfg_net_subscr_keep_cmd); install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd); + install_element(GSMNET_NODE, &cfg_virt_net_cmd); + install_node(&virt_net_node, config_write_virt_net); + vty_install_default(VIRT_NET_NODE); + install_element(VIRT_NET_NODE, &cfg_virt_net_ncc_cmd); + install_element(VIRT_NET_NODE, &cfg_virt_net_mnc_cmd); + install_element(VIRT_NET_NODE, &cfg_virt_net_name_short_cmd); + install_element(VIRT_NET_NODE, &cfg_virt_net_name_long_cmd); + install_element(GSMNET_NODE, &cfg_bts_cmd); install_node(&bts_node, config_write_bts); vty_install_default(BTS_NODE); diff --git a/openbsc/src/libbsc/net_init.c b/openbsc/src/libbsc/net_init.c index 568a0b8..1fe9f3e 100644 --- a/openbsc/src/libbsc/net_init.c +++ b/openbsc/src/libbsc/net_init.c @@ -71,6 +71,7 @@ struct gsm_network *gsm_network_init(uint16_t country_code, uint16_t network_cod INIT_LLIST_HEAD(&net->trans_list); INIT_LLIST_HEAD(&net->upqueue); INIT_LLIST_HEAD(&net->bts_list); + INIT_LLIST_HEAD(&net->virt_net_list); net->stats.chreq.total = osmo_counter_alloc("net.chreq.total"); net->stats.chreq.no_channel = osmo_counter_alloc("net.chreq.no_channel"); diff --git a/openbsc/src/libcommon/common_vty.c b/openbsc/src/libcommon/common_vty.c index a0674f0..c3434f1 100644 --- a/openbsc/src/libcommon/common_vty.c +++ b/openbsc/src/libcommon/common_vty.c @@ -42,6 +42,15 @@ int bsc_vty_go_parent(struct vty *vty) vty->node = CONFIG_NODE; vty->index = NULL; break; + case VIRT_NET_NODE: + vty->node = GSMNET_NODE; + { + /* set vty->index correctly ! */ + struct gsm_virt_network *virt_net = vty->index; + vty->index = virt_net->network; + vty->index_sub = NULL; + } + break; case BTS_NODE: vty->node = GSMNET_NODE; { diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index 16035ed..5076a3e 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -192,6 +192,48 @@ const char *rrlp_mode_name(enum rrlp_mode mode) return get_value_string(rrlp_mode_names, mode); } +struct gsm_virt_network *gsm_virt_net_alloc(void *ctx) +{ + struct gsm_virt_network *virt_net = talloc_zero(ctx, struct gsm_virt_network); + if (!virt_net) + return NULL; + return virt_net; +} + +struct gsm_virt_network *gsm_virt_net_alloc_register(struct gsm_network *net) +{ + struct gsm_virt_network *virt_net; + + virt_net = gsm_virt_net_alloc(net); + if (!virt_net) + return NULL; + + virt_net->nr = net->num_virt_net++; + virt_net->network = net; + virt_net->country_code = 1; + virt_net->network_code = 1; + virt_net->name_short = talloc_strdup(net, "OpenBSC"); + virt_net->name_long = talloc_strdup(net, "OpenBSC"); + + llist_add_tail(&virt_net->list, &net->virt_net_list); + return virt_net; +} + +struct gsm_virt_network *gsm_virt_net_num(struct gsm_network *net, int num) +{ + struct gsm_virt_network *virt_net; + + if (num >= net->num_virt_net) + return NULL; + + llist_for_each_entry(virt_net, &net->virt_net_list, list) { + if (virt_net->nr == num) + return virt_net; + } + + return NULL; +} + static const struct value_string bts_gprs_mode_names[] = { { BTS_GPRS_NONE, "none" }, { BTS_GPRS_GPRS, "gprs" }, diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 1524ec4..db03d0e 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -702,6 +702,15 @@ static uint8_t bcdify(uint8_t value) return ret; } +static void mcc_mnc_from_imsi(char* imsi, uint16_t* mcc, uint16_t* mnc) +{ + char mcc_str[4]; + char mnc_str[3]; + strncpy(mcc_str, imsi, 3); + strncpy(mnc_str, imsi + 3, 2); + *mcc = atoi(mcc_str); + *mnc = atoi(mnc_str); +} /* Section 9.2.15a */ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) @@ -719,13 +728,33 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) int tzunits; int dst = 0; + uint16_t imsi_mcc; + uint16_t imsi_mnc; + char *name_long = net->name_long; + char *name_short = net->name_short; + int virt_net_nr; + msg->lchan = conn->lchan; gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); gh->proto_discr = GSM48_PDISC_MM; gh->msg_type = GSM48_MT_MM_INFO; - if (net->name_long) { + if (net->num_virt_net) { + mcc_mnc_from_imsi(conn->subscr->imsi, &imsi_mcc, &imsi_mnc); + for (virt_net_nr = 0; virt_net_nr < net->num_virt_net; virt_net_nr++) { + struct gsm_virt_network* virt_net = gsm_virt_net_num(net, virt_net_nr); + if (virt_net && + (virt_net->country_code == imsi_mcc) && + (virt_net->network_code == imsi_mnc)) { + name_long = virt_net->name_long; + name_short = virt_net->name_short; + break; + } + } + } + + if (name_long) { #if 0 name_len = strlen(net->name_long); /* 10.5.3.5a */ @@ -741,8 +770,8 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) /* FIXME: Use Cell Broadcast, not UCS-2, since * UCS-2 is only supported by later revisions of the spec */ #endif - name_len = (strlen(net->name_long)*7)/8; - name_pad = (8 - strlen(net->name_long)*7)%8; + name_len = (strlen(name_long)*7)/8; + name_pad = (8 - strlen(name_long)*7)%8; if (name_pad > 0) name_len++; /* 10.5.3.5a */ @@ -752,11 +781,11 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */ ptr8 = msgb_put(msg, name_len); - gsm_7bit_encode_n(ptr8, name_len, net->name_long, NULL); + gsm_7bit_encode_n(ptr8, name_len, name_long, NULL); } - if (net->name_short) { + if (name_short) { #if 0 name_len = strlen(net->name_short); /* 10.5.3.5a */ @@ -769,8 +798,8 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) for (i = 0; i < name_len; i++) ptr16[i] = htons(net->name_short[i]); #endif - name_len = (strlen(net->name_short)*7)/8; - name_pad = (8 - strlen(net->name_short)*7)%8; + name_len = (strlen(name_short)*7)/8; + name_pad = (8 - strlen(name_short)*7)%8; if (name_pad > 0) name_len++; /* 10.5.3.5a */ @@ -780,7 +809,7 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */ ptr8 = msgb_put(msg, name_len); - gsm_7bit_encode_n(ptr8, name_len, net->name_short, NULL); + gsm_7bit_encode_n(ptr8, name_len, name_short, NULL); } -- 1.9.1 From kluchnikovi at gmail.com Tue Apr 12 10:48:58 2016 From: kluchnikovi at gmail.com (Ivan Kluchnikov) Date: Tue, 12 Apr 2016 13:48:58 +0300 Subject: [PATCH 2/2] tests: Add VTY tests for setting virtual-networks In-Reply-To: <1460458138-12207-1-git-send-email-kluchnikovi@gmail.com> References: <1460458138-12207-1-git-send-email-kluchnikovi@gmail.com> Message-ID: <1460458138-12207-2-git-send-email-kluchnikovi@gmail.com> --- openbsc/tests/vty_test_runner.py | 52 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index ecf5204..ec90167 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -133,6 +133,9 @@ class TestVTYGenericBSC(TestVTYBase): self.assertTrue(self.vty.verify("network",[''])) self.assertEquals(self.vty.node(), 'config-net') self.checkForEndAndExit() + self.assertTrue(self.vty.verify("virtual-network 0",[''])) + self.assertEquals(self.vty.node(), 'config-net-virt') + self.checkForEndAndExit() self.assertTrue(self.vty.verify("bts 0",[''])) self.assertEquals(self.vty.node(), 'config-net-bts') self.checkForEndAndExit() @@ -154,6 +157,12 @@ class TestVTYGenericBSC(TestVTYBase): self.assertEquals(self.vty.node(), 'config-net-bts') self.assertTrue(self.vty.verify("exit",[''])) self.assertEquals(self.vty.node(), 'config-net') + self.assertTrue(self.vty.verify("virtual-network 1",[''])) + self.assertEquals(self.vty.node(), 'config-net-virt') + self.checkForEndAndExit() + self.vty.command("write terminal") + self.assertTrue(self.vty.verify("exit",[''])) + self.assertEquals(self.vty.node(), 'config-net') self.assertTrue(self.vty.verify("exit",[''])) self.assertEquals(self.vty.node(), 'config') self.assertTrue(self.vty.verify("exit",[''])) @@ -307,6 +316,48 @@ class TestVTYNITB(TestVTYGenericBSC): if classNum != 10: self.assertEquals(res.find("rach access-control-class " + str(classNum) + " barred"), -1) + def testVirtualNetworks(self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("network") + self.vty.command("virtual-network 0") + + # Test invalid input + self.vty.verify("network country code 0", ['% Unknown command.']) + self.vty.verify("network country code 1000", ['% Unknown command.']) + self.vty.verify("network country code 1234", ['% Unknown command.']) + self.vty.verify("mobile network code 0", ['% Unknown command.']) + self.vty.verify("mobile network code 1000", ['% Unknown command.']) + self.vty.verify("mobile network code 1234", ['% Unknown command.']) + self.vty.verify("mobile network code 1234", ['% Unknown command.']) + self.vty.verify("short name Test Net", ['% Unknown command.']) + self.vty.verify("long name Test Network", ['% Unknown command.']) + + # Set virtual-networks + self.vty.verify("network country code 2", ['']) + self.vty.verify("mobile network code 2", ['']) + self.vty.verify("short name TestNet2", ['']) + self.vty.verify("long name TestNetwork2", ['']) + self.vty.verify("exit",['']) + self.vty.command("virtual-network 1") + self.vty.verify("network country code 3", ['']) + self.vty.verify("mobile network code 3", ['']) + self.vty.verify("short name TestNet3", ['']) + self.vty.verify("long name TestNetwork3", ['']) + + # Verify settings + res = self.vty.command("write terminal") + self.assert_(res.find('virtual-network 0') > 0) + self.assert_(res.find('network country code 2') > 0) + self.assert_(res.find('mobile network code 2') > 0) + self.assert_(res.find('short name TestNet2') > 0) + self.assert_(res.find('long name TestNetwork2') > 0) + self.assert_(res.find('virtual-network 1') > 0) + self.assert_(res.find('network country code 3') > 0) + self.assert_(res.find('mobile network code 3') > 0) + self.assert_(res.find('short name TestNet3') > 0) + self.assert_(res.find('long name TestNetwork3') > 0) + def testSubscriberCreateDeleteTwice(self): """ OS#1657 indicates that there might be an issue creating the @@ -342,7 +393,6 @@ class TestVTYNITB(TestVTYGenericBSC): res = self.vty.command('show subscriber imsi '+imsi) self.assert_(res != '% No subscriber found for imsi '+imsi) - def testSubscriberCreateDelete(self): self.vty.enable() -- 1.9.1 From nhofmeyr at sysmocom.de Tue Apr 12 11:17:34 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 12 Apr 2016 13:17:34 +0200 Subject: [PATCH] remove two compiler warnings for unused variables In-Reply-To: <20160411222352.GD15746@nataraja> References: <1460069165-5638-1-git-send-email-nhofmeyr@sysmocom.de> <20160411222352.GD15746@nataraja> Message-ID: <20160412111734.GA1304@ass40.sysmocom.de> On Tue, Apr 12, 2016 at 12:23:52AM +0200, Harald Welte wrote: > Hi Max, It was me, not Max :) > will just mean that we all forget about having to fix it. Maybe instead of numerous unused variables, we should have a single #warning then. Every warning hinders my dev cycle. For pretty much every compilation, I have to parse/browse the list of warnings, *all* the time. Even a #warning would stare me in the face for every build. There are a couple of those already. So I'd even prefer a TODO file in / , admitted that these kind of files tend to go outdated. Also, having warnings around makes it harder to spot new warnings I've introduced. I see some warnings scroll by, then assume they're just the old ones, or have to scroll around to check every time. I'd prefer a way that I don't have to check for and read the same old warnings dozens of times every day, while not having the time to investigate/fix anyway... I unnecessarily lose time on those. A workaround for me would be to eradicate the warnings on our iu branches but not commit them to master. ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From robert.steve07 at gmail.com Tue Apr 12 14:06:10 2016 From: robert.steve07 at gmail.com (robert) Date: Tue, 12 Apr 2016 17:06:10 +0300 Subject: IMSI localization Message-ID: <69F373B5-BF0F-47B6-BB7A-8830576D9852@gmail.com> Hi, I am trying to find a solution that enables to find the position of the phone connected to my network. Are there any GSM protocols that provide such features or is it only done on the RF level using direction finders ? Best Regards, Robert, From holger at freyther.de Tue Apr 12 14:06:59 2016 From: holger at freyther.de (Holger Freyther) Date: Tue, 12 Apr 2016 10:06:59 -0400 Subject: [PATCH] Add optional copy_files attribute In-Reply-To: <32841AE3-5084-487B-B91F-9E2D7B972154@freyther.de> References: <1459430596-9066-1-git-send-email-msuraev@sysmocom.de> <9969441B-9173-4C4A-A168-9BA384556DC2@freyther.de> <57052925.5070108@sysmocom.de> <32841AE3-5084-487B-B91F-9E2D7B972154@freyther.de> Message-ID: > On 06 Apr 2016, at 15:03, Holger Freyther wrote: > > Max, > yes, but the code seems to be more involved than: > > shutil.copytree > > Can't we simplify the code by using this routine instead of having an extra list of files to copy? is this still relevant? Or old because of the other patch? holger From holger at freyther.de Tue Apr 12 14:22:17 2016 From: holger at freyther.de (Holger Freyther) Date: Tue, 12 Apr 2016 10:22:17 -0400 Subject: [PATCH 1/2] Add support of virtual networks for sending network name to ms depending on imsi In-Reply-To: <1460458138-12207-1-git-send-email-kluchnikovi@gmail.com> References: <1460458138-12207-1-git-send-email-kluchnikovi@gmail.com> Message-ID: <5D1B55C4-0B8C-414F-8B8C-BFF1094ECAF8@freyther.de> > On 12 Apr 2016, at 06:48, Ivan Kluchnikov wrote: Dear Ivan, can you please give a general introduction of that feature? Describe when one would want to use it. Why it is not a regexp for the IMSI but actually only the country code and network code? How you intend to deal with two or three digit network code? kind regards holger From msuraev at sysmocom.de Tue Apr 12 14:23:29 2016 From: msuraev at sysmocom.de (Max) Date: Tue, 12 Apr 2016 16:23:29 +0200 Subject: IMSI localization In-Reply-To: <69F373B5-BF0F-47B6-BB7A-8830576D9852@gmail.com> References: <69F373B5-BF0F-47B6-BB7A-8830576D9852@gmail.com> Message-ID: <570D04E1.4070803@sysmocom.de> Hi. You can use RRLP protocol. There is some code available in http://git.osmocom.org/osmocom-lcs/ On 04/12/2016 04:06 PM, robert wrote: > Hi, > > I am trying to find a solution that enables to find the position of the phone connected to my network. Are there any GSM protocols that provide such features or is it only done on the RF level using direction finders ? > > > > Best Regards, > Robert, -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Tue Apr 12 14:24:55 2016 From: msuraev at sysmocom.de (Max) Date: Tue, 12 Apr 2016 16:24:55 +0200 Subject: [PATCH] Add optional copy_files attribute In-Reply-To: References: <1459430596-9066-1-git-send-email-msuraev@sysmocom.de> <9969441B-9173-4C4A-A168-9BA384556DC2@freyther.de> <57052925.5070108@sysmocom.de> <32841AE3-5084-487B-B91F-9E2D7B972154@freyther.de> Message-ID: <570D0537.4040305@sysmocom.de> No, it's superseded by another patch. On 04/12/2016 04:06 PM, Holger Freyther wrote: >> On 06 Apr 2016, at 15:03, Holger Freyther wrote: >> >> > Max, > > >> yes, but the code seems to be more involved than: >> >> shutil.copytree >> >> Can't we simplify the code by using this routine instead of having an extra list of files to copy? > is this still relevant? Or old because of the other patch? > > holger -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Tue Apr 12 14:59:25 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Tue, 12 Apr 2016 16:59:25 +0200 Subject: [PATCH] NAT: move BSC config into separate file Message-ID: <1460473165-1700-1-git-send-email-msuraev@sysmocom.de> From: Max Introduce new configuration option bscs-config-file which includes BSC configuration from the given file. Both absolute and relative (to the main config file) paths are supported. Add 'show bscs-config' command to display current BSC configuration. Note: it is still possible to have BSC configuration in the main file (provided proper index number is used) and in runtime but BSC configuration is no longer saved automatically. The management of included configuration file is left to external tools. Update configuration examples. Fixes: OS#1669 Sponsored-by: On-Waves ehf --- openbsc/doc/examples/osmo-bsc_nat/bscs.config | 13 ++++++ openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg | 8 +--- openbsc/include/openbsc/bsc_nat.h | 5 +++ openbsc/osmoappdesc.py | 1 - openbsc/src/osmo-bsc_nat/bsc_nat.c | 5 ++- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 49 ++++++++++++++++++++-- 6 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 openbsc/doc/examples/osmo-bsc_nat/bscs.config diff --git a/openbsc/doc/examples/osmo-bsc_nat/bscs.config b/openbsc/doc/examples/osmo-bsc_nat/bscs.config new file mode 100644 index 0000000..176debe --- /dev/null +++ b/openbsc/doc/examples/osmo-bsc_nat/bscs.config @@ -0,0 +1,13 @@ +nat + bsc 0 + token lol + location_area_code 1234 + description bsc + max-endpoints 32 + paging forbidden 0 + bsc 1 + token wat + location_area_code 5678 + description bsc + max-endpoints 32 + paging forbidden 0 diff --git a/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg b/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg index 737d104..2e00bc2 100644 --- a/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg +++ b/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg @@ -62,11 +62,5 @@ nat timeout ping 20 timeout pong 5 ip-dscp 0 + bscs-config-file bscs.config access-list bla imsi-allow ^11$ - - bsc 0 - token bla - location_area_code 1234 - description bsc - max-endpoints 32 - paging forbidden 0 diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index c5fefe1..5ccc02e 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -264,6 +264,11 @@ struct bsc_nat { struct bsc_endpoint *bsc_endpoints; + /* path to file with BSC config */ + char *include_file; + char *include_base; + char *resolved_path; + /* filter */ char *acc_lst_name; diff --git a/openbsc/osmoappdesc.py b/openbsc/osmoappdesc.py index 76f03fc..50d7bf0 100644 --- a/openbsc/osmoappdesc.py +++ b/openbsc/osmoappdesc.py @@ -26,7 +26,6 @@ nitb_e1_configs = [ "doc/examples/osmo-nitb/rbs2308/openbsc.cfg" ] - app_configs = { "osmo-bsc": ["doc/examples/osmo-bsc/osmo-bsc.cfg"], "nat": ["doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg"], diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index ab82adf..f433324 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -34,6 +34,7 @@ #include #include #include +#include #define _GNU_SOURCE #include @@ -1626,6 +1627,8 @@ int main(int argc, char **argv) local_addr.s_addr = INADDR_ANY; handle_options(argc, argv); + nat->include_base = dirname(talloc_strdup(tall_bsc_ctx, config_file)); + rate_ctr_init(tall_bsc_ctx); osmo_stats_init(tall_bsc_ctx); @@ -1651,7 +1654,7 @@ int main(int argc, char **argv) /* seed the PRNG */ srand(time(NULL)); - + LOGP(DNAT, LOGL_NOTICE, "BSCs configured from %s\n", nat->resolved_path); /* * Setup the MGCP code.. diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 4348d6f..b7b49e6 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -96,6 +96,8 @@ static int config_write_nat(struct vty *vty) vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE); vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE); vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE); + if (_nat->include_file) + vty_out(vty, " bscs-config-file %s%s", _nat->include_file, VTY_NEWLINE); if (_nat->token) vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE); vty_out(vty, " ip-dscp %d%s", _nat->bsc_ip_dscp, VTY_NEWLINE); @@ -181,6 +183,14 @@ static int config_write_bsc(struct vty *vty) return CMD_SUCCESS; } +DEFUN(show_bscs, show_bscs_cmd, "show bscs-config", + SHOW_STR "Show configured BSCs\n" + "Both from included file and vty\n") +{ + vty_out(vty, "BSCs configuration loaded from %s:%s", _nat->resolved_path, + VTY_NEWLINE); + return config_write_bsc(vty); +} DEFUN(show_sccp, show_sccp_cmd, "show sccp connections", SHOW_STR "Display information about SCCP\n" @@ -495,6 +505,34 @@ DEFUN(cfg_nat_acc_lst_name, return CMD_SUCCESS; } +DEFUN(cfg_nat_include, + cfg_nat_include_cmd, + "bscs-config-file NAME", + "Set the filename of the BSC configuration to include.\n" + "The filename to be included.") +{ + char *path; + int rc; + + if ('/' == argv[0][0]) + bsc_replace_string(_nat, &_nat->resolved_path, argv[0]); + else { + path = talloc_asprintf(_nat, "%s/%s", _nat->include_base, + argv[0]); + bsc_replace_string(_nat, &_nat->resolved_path, path); + talloc_free(path); + } + + rc = vty_read_config_file(_nat->resolved_path, NULL); + if (rc < 0) { + vty_out(vty, "Failed to parse the config file %s: %s%s", + _nat->resolved_path, strerror(-rc), VTY_NEWLINE); + return CMD_WARNING; + } + bsc_replace_string(_nat, &_nat->include_file, argv[0]); + return CMD_SUCCESS; +} + DEFUN(cfg_nat_no_acc_lst_name, cfg_nat_no_acc_lst_name_cmd, "no access-list-name", @@ -865,8 +903,11 @@ DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>", /* verify that the LACs are unique */ llist_for_each_entry(tmp, &_nat->bsc_configs, entry) { if (bsc_config_handles_lac(tmp, lac)) { - vty_out(vty, "%% LAC %d is already used.%s", lac, VTY_NEWLINE); - return CMD_ERR_INCOMPLETE; + if (tmp->nr != conf->nr) { + vty_out(vty, "%% LAC %d is already used.%s", lac, + VTY_NEWLINE); + return CMD_ERR_INCOMPLETE; + } } } @@ -1179,6 +1220,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element_ve(&show_msc_cmd); install_element_ve(&test_regex_cmd); install_element_ve(&show_bsc_mgcp_cmd); + install_element_ve(&show_bscs_cmd); install_element_ve(&show_bar_lst_cmd); install_element_ve(&show_prefix_tree_cmd); install_element_ve(&show_ussd_connection_cmd); @@ -1200,6 +1242,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd); install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd); install_element(NAT_NODE, &cfg_nat_no_acc_lst_name_cmd); + install_element(NAT_NODE, &cfg_nat_include_cmd); install_element(NAT_NODE, &cfg_nat_imsi_black_list_fn_cmd); install_element(NAT_NODE, &cfg_nat_no_imsi_black_list_fn_cmd); install_element(NAT_NODE, &cfg_nat_ussd_lst_name_cmd); @@ -1236,7 +1279,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) /* BSC subgroups */ install_element(NAT_NODE, &cfg_bsc_cmd); - install_node(&bsc_node, config_write_bsc); + install_node(&bsc_node, NULL); vty_install_default(NAT_BSC_NODE); install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_auth_key_cmd); -- 2.8.1 From laforge at gnumonks.org Tue Apr 12 20:49:47 2016 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 12 Apr 2016 22:49:47 +0200 Subject: [PATCH] remove two compiler warnings for unused variables In-Reply-To: <20160412111734.GA1304@ass40.sysmocom.de> References: <1460069165-5638-1-git-send-email-nhofmeyr@sysmocom.de> <20160411222352.GD15746@nataraja> <20160412111734.GA1304@ass40.sysmocom.de> Message-ID: <20160412204947.GA6186@nataraja> Hi Neels, On Tue, Apr 12, 2016 at 01:17:34PM +0200, Neels Hofmeyr wrote: > On Tue, Apr 12, 2016 at 12:23:52AM +0200, Harald Welte wrote: > > Hi Max, > > It was me, not Max :) Sorry. > > will just mean that we all forget about having to fix it. > > Maybe instead of numerous unused variables, we should have a single > #warning then. Every warning hinders my dev cycle. For pretty much every > compilation, I have to parse/browse the list of warnings, *all* the time. Please let me know after how many compilatiosn the trade-off woudl trip towards actually addressing those warnings in fixing the related code. > Even a #warning would stare me in the face for every build. There are a > couple of those already. Well, if everyone every so often would address one of them, it wouldn't be so bad :) -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Tue Apr 12 21:21:04 2016 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 12 Apr 2016 23:21:04 +0200 Subject: IMSI localization In-Reply-To: <69F373B5-BF0F-47B6-BB7A-8830576D9852@gmail.com> References: <69F373B5-BF0F-47B6-BB7A-8830576D9852@gmail.com> Message-ID: <20160412212104.GE6186@nataraja> Dear Robert, On Tue, Apr 12, 2016 at 05:06:10PM +0300, robert wrote: > I am trying to find a solution that enables to find the position of > the phone connected to my network. Are there any GSM protocols that > provide such features or is it only done on the RF level using > direction finders ? Is your network running OpenBSC, or why do you raise this question on the OpenBSC mailing list? -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From holger at freyther.de Wed Apr 13 00:36:19 2016 From: holger at freyther.de (Holger Freyther) Date: Tue, 12 Apr 2016 20:36:19 -0400 Subject: iuh: Coverity build breakage because of old sctp In-Reply-To: <55242E3B-94E9-4864-A201-2F18CA199D01@freyther.de> References: <55242E3B-94E9-4864-A201-2F18CA199D01@freyther.de> Message-ID: <26D7E73B-CDD1-431A-9C19-4D3305FBDE28@freyther.de> > On 06 Apr 2016, at 15:26, Holger Freyther wrote: > > Hi, the coverity upload is now broken for a week... it is more than time to fix it! holger From holger at freyther.de Wed Apr 13 00:38:16 2016 From: holger at freyther.de (Holger Freyther) Date: Tue, 12 Apr 2016 20:38:16 -0400 Subject: [PATCH] Recursively copy files before config test In-Reply-To: <1460031085-30498-1-git-send-email-msuraev@sysmocom.de> References: <1460031085-30498-1-git-send-email-msuraev@sysmocom.de> Message-ID: > On 07 Apr 2016, at 08:11, msuraev at sysmocom.de wrote: > > From: Max > > Copy all potentially necessary files (like includable configs) before > running config test. http://jenkins.osmocom.org/jenkins/job/osmo-pcu/731/label=linux_i386_debian_squeeze,sysmobts=no,sysmodsp=no/console Traceback (most recent call last): File "/usr/local/bin/osmotestconfig.py", line 212, in confpath=confpath, verbose=args.verbose)) File "/usr/local/bin/osmotestconfig.py", line 169, in test_all_apps errors |= test_config(app, config, tmpdir, verbose) File "/usr/local/bin/osmotestconfig.py", line 34, in test_config newconfig = copy_config(tmpdir, config) File "/usr/local/bin/osmotestconfig.py", line 87, in copy_config dir=dirname, prefix=prefix, delete=False) File "/usr/lib/python2.6/tempfile.py", line 444, in NamedTemporaryFile (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) File "/usr/lib/python2.6/tempfile.py", line 228, in _mkstemp_inner fd = _os.open(file, flags, 0600) OSError: [Errno 13] Permission denied: 'writtenconfig/osmo-pcu.cfgayzRgv' is that related to your patch? From robert.steve07 at gmail.com Wed Apr 13 06:38:19 2016 From: robert.steve07 at gmail.com (robert) Date: Wed, 13 Apr 2016 09:38:19 +0300 Subject: IMSI localization In-Reply-To: <20160412212104.GE6186@nataraja> References: <69F373B5-BF0F-47B6-BB7A-8830576D9852@gmail.com> <20160412212104.GE6186@nataraja> Message-ID: <8FE2C799-D286-4CE8-9D68-9E8AE10B344F@gmail.com> Hi, yes it is running OpenBSC, I?m asking to know if there are some tools available over OpenBSC or at least if some code can be added to implement such function. Best regards, Robert, On Apr 13, 2016, at 12:21 AM, Harald Welte wrote: > Dear Robert, > > On Tue, Apr 12, 2016 at 05:06:10PM +0300, robert wrote: >> I am trying to find a solution that enables to find the position of >> the phone connected to my network. Are there any GSM protocols that >> provide such features or is it only done on the RF level using >> direction finders ? > > Is your network running OpenBSC, or why do you raise this question on > the OpenBSC mailing list? > > -- > - Harald Welte http://laforge.gnumonks.org/ > ============================================================================ > "Privacy in residential applications is a desirable marketing option." > (ETSI EN 300 175-7 Ch. A6) From msuraev at sysmocom.de Wed Apr 13 08:10:07 2016 From: msuraev at sysmocom.de (Max) Date: Wed, 13 Apr 2016 10:10:07 +0200 Subject: [PATCH] Recursively copy files before config test In-Reply-To: References: <1460031085-30498-1-git-send-email-msuraev@sysmocom.de> Message-ID: <570DFEDF.201@sysmocom.de> Not directly - the error is not triggered from the code I've added. But it could be that my code somehow changed/not changed metadata in some corner case. I'm unable to reproduce this locally - is there way to get file details from jenkins? Permission, owner, xattr etc from both target and destination of the copy and upper folders? On 04/13/2016 02:38 AM, Holger Freyther wrote: >> On 07 Apr 2016, at 08:11, msuraev at sysmocom.de wrote: >> >> From: Max >> >> Copy all potentially necessary files (like includable configs) before >> running config test. > http://jenkins.osmocom.org/jenkins/job/osmo-pcu/731/label=linux_i386_debian_squeeze,sysmobts=no,sysmodsp=no/console > > Traceback (most recent call last): > File "/usr/local/bin/osmotestconfig.py", line 212, in > confpath=confpath, verbose=args.verbose)) > File "/usr/local/bin/osmotestconfig.py", line 169, in test_all_apps > errors |= test_config(app, config, tmpdir, verbose) > File "/usr/local/bin/osmotestconfig.py", line 34, in test_config > newconfig = copy_config(tmpdir, config) > File "/usr/local/bin/osmotestconfig.py", line 87, in copy_config > dir=dirname, prefix=prefix, delete=False) > File "/usr/lib/python2.6/tempfile.py", line 444, in NamedTemporaryFile > (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) > File "/usr/lib/python2.6/tempfile.py", line 228, in _mkstemp_inner > fd = _os.open(file, flags, 0600) > OSError: [Errno 13] Permission denied: 'writtenconfig/osmo-pcu.cfgayzRgv' > > is that related to your patch? > > > -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From Ivan.Kluchnikov at fairwaves.ru Wed Apr 13 09:18:15 2016 From: Ivan.Kluchnikov at fairwaves.ru (Ivan Kluchnikov) Date: Wed, 13 Apr 2016 12:18:15 +0300 Subject: [PATCH 1/2] Add support of virtual networks for sending network name to ms depending on imsi In-Reply-To: <5D1B55C4-0B8C-414F-8B8C-BFF1094ECAF8@freyther.de> References: <1460458138-12207-1-git-send-email-kluchnikovi@gmail.com> <5D1B55C4-0B8C-414F-8B8C-BFF1094ECAF8@freyther.de> Message-ID: Hi Holger, Thank you for patch review. can you please give a general introduction of that feature? Describe when > one would want to use it. The basic idea is to support roaming-based network sharing. So subscribers of different operators can roam seamlessly in our network. For that purpose we should be able to check a subscriber's IMSI to identify the virtual network the IMSI belongs to. On the first stage to achieve seamless roaming we should be able to set network name for each supported virtual network. In future we plan to add more configuration parameters for virtual network: - auth policy (which could solve http://projects.osmocom.org/issues/1647) - location updating reject cause (useful for real deployments) May be you also have any ideas which parameters could be added to virtual network node? Why it is not a regexp for the IMSI but actually only the country code and > network code? How you intend to deal with two or three digit network code? Yes, I agree that the current implementation is not enough flexible and it is a good idea to use imsi-prefix instead of mcc and mnc, also it will fix the issue with 3 digit mnc. Do you think it makes sense? But I am not sure that I understand the idea of using regexp for the IMSI, could you please clarify for which cases it could be useful? -- Regards, Ivan Kluchnikov. http://fairwaves.ru -------------- next part -------------- An HTML attachment was scrubbed... URL: From msuraev at sysmocom.de Wed Apr 13 09:36:38 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 13 Apr 2016 11:36:38 +0200 Subject: [PATCH 1/2] vty_test_runner: update ipa sending code Message-ID: <1460540199-23321-1-git-send-email-msuraev@sysmocom.de> From: Max Factor out 2, add 3 functions. Those functions are simple wrappers around hex strings specific to IPA protocol. Not all of them are utilized at the moment but they were checked with wireshark while working on the tests. It might come in handy if we'd like to further expand related test harness in future. The same goes for optional verbosity argument which is not used right now but will be handy for future debugging. --- openbsc/tests/vty_test_runner.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index ecf5204..d574129 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -736,13 +736,13 @@ class TestVTYNAT(TestVTYGenericBSC): self.assertEqual(data, "\x00\x01\xfe\x04") print "Going to send ID_RESP response" - res = ussdSocket.send("\x00\x07\xfe\x05\x00\x04\x01\x6b\x65\x79") + res = ipa_send_resp(ussdSocket, "\x6b\x65\x79") self.assertEqual(res, 10) # initiating PING/PONG cycle to know, that the ID_RESP message has been processed print "Going to send PING request" - res = ussdSocket.send("\x00\x01\xfe\x00") + res = ipa_send_ping(ussdSocket) self.assertEqual(res, 4) print "Expecting PONG response" @@ -1007,6 +1007,31 @@ def add_nat_test(suite, workdir): test = unittest.TestLoader().loadTestsFromTestCase(TestVTYNAT) suite.addTest(test) +def ipa_send_pong(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: PONG!" + return x.send("\x00\x01\xfe\x01") + +def ipa_send_ping(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: PING?" + return x.send("\x00\x01\xfe\x00") + +def ipa_send_ack(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: IPA ID ACK" + return x.send("\x00\x01\xfe\x06") + +def ipa_send_reset(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: RESET" + return x.send("\x00\x12\xfd\x09\x00\x03\x05\x07\x02\x42\xfe\x02\x42\xfe\x06\x00\x04\x30\x04\x01\x20") + +def ipa_send_resp(x, tk, verbose = False): + if (verbose): + print "\tBSC -> NAT: IPA ID RESP" + return x.send("\x00\x07\xfe\x05\x00\x04\x01" + tk) + 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") -- 2.8.1 From msuraev at sysmocom.de Wed Apr 13 09:36:39 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 13 Apr 2016 11:36:39 +0200 Subject: [PATCH 2/2] NAT: reload BSCs config dynamically In-Reply-To: <1460540199-23321-1-git-send-email-msuraev@sysmocom.de> References: <1460540199-23321-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1460540199-23321-2-git-send-email-msuraev@sysmocom.de> From: Max Add vty tests for BSC configuration reloading. Load BSCs configuration on bscs-config-file command: * remove all runtime configured BSC not in the config file * close connections to all BSC with updated token value Fixes: OS#1670 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/bsc_nat.h | 5 ++ openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 29 ++++++++ openbsc/tests/vty_test_runner.py | 120 ++++++++++++++++++++++++++++++++- 3 files changed, 153 insertions(+), 1 deletion(-) diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 5ccc02e..94ab0e5 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -35,6 +35,7 @@ #include #include +#include #define DIR_BSC 1 #define DIR_MSC 2 @@ -164,6 +165,10 @@ struct bsc_config { /* audio handling */ int max_endpoints; + /* used internally for reload handling */ + bool remove; + bool token_updated; + /* backpointer */ struct bsc_nat *nat; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index b7b49e6..55f3dbf 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -39,6 +39,7 @@ #include #include +#include static struct bsc_nat *_nat; @@ -513,6 +514,8 @@ DEFUN(cfg_nat_include, { char *path; int rc; + struct bsc_config *cf1, *cf2; + struct bsc_connection *con1, *con2; if ('/' == argv[0][0]) bsc_replace_string(_nat, &_nat->resolved_path, argv[0]); @@ -523,13 +526,32 @@ DEFUN(cfg_nat_include, talloc_free(path); } + llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) { + cf1->remove = true; + cf1->token_updated = false; + } + rc = vty_read_config_file(_nat->resolved_path, NULL); if (rc < 0) { vty_out(vty, "Failed to parse the config file %s: %s%s", _nat->resolved_path, strerror(-rc), VTY_NEWLINE); return CMD_WARNING; } + bsc_replace_string(_nat, &_nat->include_file, argv[0]); + + llist_for_each_entry_safe(con1, con2, &_nat->bsc_connections, + list_entry) { + if (con1->cfg) + if (con1->cfg->token_updated || con1->cfg->remove) + bsc_close_connection(con1); + } + + llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) { + if (cf1->remove) + bsc_config_free(cf1); + } + return CMD_SUCCESS; } @@ -846,6 +868,7 @@ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", if (!bsc) return CMD_WARNING; + bsc->remove = false; vty->index = bsc; vty->node = NAT_BSC_NODE; @@ -858,6 +881,12 @@ DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN", { struct bsc_config *conf = vty->index; + if (strncmp(conf->token, argv[0], 128) != 0) { + vty_out(vty, "updated token: %s -> %s%s", conf->token, argv[0], + VTY_NEWLINE); + conf->token_updated = true; + } + bsc_replace_string(conf, &conf->token, argv[0]); return CMD_SUCCESS; } diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index d574129..59fdd2f 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -620,12 +620,61 @@ class TestVTYBSC(TestVTYGenericBSC): class TestVTYNAT(TestVTYGenericBSC): def vty_command(self): - return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-c", + return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-l", "127.0.0.1", "-c", "doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg"] def vty_app(self): return (4244, "src/osmo-bsc_nat/osmo-bsc_nat", "OsmoBSCNAT", "nat") + def testBSCreload(self): + # use separate ip to avoid interference with other tests + ip = "127.0.0.4" + self.vty.enable() + bscs1 = self.vty.command("show bscs-config") + nat_bsc_reload(self) + bscs2 = self.vty.command("show bscs-config") + # check that multiple calls to bscs-config-file give the same result + self.assertEquals(bscs1, bscs2) + + # add new bsc + self.vty.command("configure terminal") + self.vty.command("nat") + self.vty.command("bsc 5") + self.vty.command("token key") + self.vty.command("location_area_code 666") + self.vty.command("end") + + # update bsc token + self.vty.command("configure terminal") + self.vty.command("nat") + self.vty.command("bsc 1") + self.vty.command("token xyu") + self.vty.command("end") + + nat_msc_ip(self, ip) + msc = nat_msc_test(self, ip) + b0 = nat_bsc_sock_test(0, "lol") + b1 = nat_bsc_sock_test(1, "xyu") + b2 = nat_bsc_sock_test(5, "key") + + self.assertEquals("3 BSCs configured", self.vty.command("show nat num-bscs-configured")) + self.assertTrue(3 == nat_bsc_num_con(self)) + self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection")) + + nat_bsc_reload(self) + bscs2 = self.vty.command("show bscs-config") + # check that the reset to initial config succeeded + self.assertEquals(bscs1, bscs2) + + self.assertEquals("2 BSCs configured", self.vty.command("show nat num-bscs-configured")) + self.assertTrue(1 == nat_bsc_num_con(self)) + rem = self.vty.command("show bsc connections").split(' ') + # remaining connection is for BSC0 + self.assertEquals('0', rem[2]) + # remaining connection is authorized + self.assertEquals('1', rem[4]) + self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection")) + def testVtyTree(self): self.vty.enable() self.assertTrue(self.vty.verify('configure terminal', [''])) @@ -1032,6 +1081,75 @@ def ipa_send_resp(x, tk, verbose = False): print "\tBSC -> NAT: IPA ID RESP" return x.send("\x00\x07\xfe\x05\x00\x04\x01" + tk) +def nat_bsc_reload(x): + x.vty.command("configure terminal") + x.vty.command("nat") + x.vty.command("bscs-config-file bscs.config") + x.vty.command("end") + +def nat_msc_ip(x, ip): + x.vty.command("configure terminal") + x.vty.command("nat") + x.vty.command("msc ip " + ip) + x.vty.command("end") + +def data2str(d): + return "".join("{:02x}".format(ord(c)) for c in d) + +def nat_msc_test(x, ip, verbose = False): + msc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + msc.settimeout(32) + msc.bind((ip, 5000)) + msc.listen(5) + if (verbose): + print "MSC is ready at " + ip + while "MSC is connected: 0" == x.vty.command("show msc connection"): + conn, addr = msc.accept() + if (verbose): + print "MSC got connection from ", addr + return conn + +def ipa_handle_small(x, verbose = False): + s = data2str(x.recv(4)) + if "0001fe00" == s: + if (verbose): + print "\tBSC <- NAT: PING?" + ipa_send_pong(x, verbose) + elif "0001fe06" == s: + if (verbose): + print "\tBSC <- NAT: IPA ID ACK" + ipa_send_ack(x, verbose) + elif "0001fe00" == s: + if (verbose): + print "\tBSC <- NAT: PONG!" + else: + if (verbose): + print "\tBSC <- NAT: ", s + +def ipa_handle_resp(x, tk, verbose = False): + s = data2str(x.recv(38)) + if "0023fe040108010701020103010401050101010011" in s: + ipa_send_resp(x, tk, verbose) + else: + if (verbose): + print "\tBSC <- NAT: ", s + +def nat_bsc_num_con(x): + return len(x.vty.command("show bsc connections").split('\n')) + +def nat_bsc_sock_test(nr, tk, verbose = False): + bsc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + bsc.bind(('127.0.0.1' + str(nr), 0)) + bsc.connect(('127.0.0.1', 5000)) + if (verbose): + print "BSC%d " %nr + print "\tconnected to %s:%d" % bsc.getpeername() + ipa_handle_small(bsc, verbose) + ipa_handle_resp(bsc, tk, verbose) + bsc.recv(27) # MGCP msg + ipa_handle_small(bsc, verbose) + return bsc + 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") -- 2.8.1 From holger at freyther.de Wed Apr 13 10:39:11 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 13 Apr 2016 06:39:11 -0400 Subject: [PATCH 1/2] Add support of virtual networks for sending network name to ms depending on imsi In-Reply-To: References: <1460458138-12207-1-git-send-email-kluchnikovi@gmail.com> <5D1B55C4-0B8C-414F-8B8C-BFF1094ECAF8@freyther.de> Message-ID: > On 13 Apr 2016, at 05:18, Ivan Kluchnikov wrote: > > Hi Holger, > Hi Ivan, > > Yes, I agree that the current implementation is not enough flexible and it is a good idea to use imsi-prefix instead of mcc and mnc, also it will fix the issue with 3 digit mnc. yes? But how do you intend to fix it? The current structure will not be enough > Do you think it makes sense? > But I am not sure that I understand the idea of using regexp for the IMSI, could you please clarify for which cases it could be useful? I understand you want to fill a short-term gap but I don't think it is the right approach to "roaming" at all. At the end of classic roaming one will: * Get a yes/no if it is allowed to roam * Get subscriber data (MSISDN, ...) * The subscribed services (allowed to do telephony) Right now the code is just about sending different network names. that seems very different from roaming? holger From holger at freyther.de Wed Apr 13 10:39:47 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 13 Apr 2016 06:39:47 -0400 Subject: iuh: Coverity build breakage because of old sctp In-Reply-To: <26D7E73B-CDD1-431A-9C19-4D3305FBDE28@freyther.de> References: <55242E3B-94E9-4864-A201-2F18CA199D01@freyther.de> <26D7E73B-CDD1-431A-9C19-4D3305FBDE28@freyther.de> Message-ID: <5A2BC71A-3AAC-45F6-A44A-2FC7553218FD@freyther.de> > On 12 Apr 2016, at 20:36, Holger Freyther wrote: > > >> > > the coverity upload is now broken for a week... it is more than time to fix it! *sigh* From holger at freyther.de Wed Apr 13 10:49:18 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 13 Apr 2016 06:49:18 -0400 Subject: [PATCH] Recursively copy files before config test In-Reply-To: <570DFEDF.201@sysmocom.de> References: <1460031085-30498-1-git-send-email-msuraev@sysmocom.de> <570DFEDF.201@sysmocom.de> Message-ID: <65CF6518-3F3B-4286-B0F8-41F45288E5F7@freyther.de> > On 13 Apr 2016, at 04:10, Max wrote: > Hi, > Not directly - the error is not triggered from the code I've added. But > it could be that my code somehow changed/not changed metadata in some > corner case. I'm unable to reproduce this locally - is there way to get > file details from jenkins? Permission, owner, xattr etc from both target > and destination of the copy and upper folders? well, the responsibility is with you. Have you looked at the console output and when it happens? It happens with "make: *** [distcheck] Error 1". Which means the source directory will be checked out read-only, which means the files you copy are read-only. I would be surprised if DISTCHECK_CONFIGURE_FLAGS=--enable-sysmocom-bts=no --enable-sysmocom-dsp=no --enable-vty-tests AM_DISTCHECK_CONFIGURE_FLAGS=--enable-sysmocom-bts=no --enable-sysmocom-dsp=no --enable-vty-tests PKG_CONFIG_PATH=/home/builder/source/workspace/osmo-pcu/label/linux_i386_debian_squeeze/sysmobts/no/sysmodsp/no/deps/install/lib/pkgconfig LD_LIBRARY_PATH=/home/builder/source/workspace/osmo-pcu/label/linux_i386_debian_squeeze/sysmobts/no/sysmodsp/no/deps/install/lib make distcheck doesn't reproduce the issue for you. holger From msuraev at sysmocom.de Wed Apr 13 12:37:38 2016 From: msuraev at sysmocom.de (Max) Date: Wed, 13 Apr 2016 14:37:38 +0200 Subject: [PATCH] Recursively copy files before config test In-Reply-To: <65CF6518-3F3B-4286-B0F8-41F45288E5F7@freyther.de> References: <1460031085-30498-1-git-send-email-msuraev@sysmocom.de> <570DFEDF.201@sysmocom.de> <65CF6518-3F3B-4286-B0F8-41F45288E5F7@freyther.de> Message-ID: <570E3D92.2050505@sysmocom.de> The quickest solution would be to remove "--enable-vty-tests" from distcheck variables but I do not see how they are populated? I've reproduced it with osmo-pcu but not with openbsc - I wonder what's the difference between how distcheck is run for both. On 04/13/2016 12:49 PM, Holger Freyther wrote: >> On 13 Apr 2016, at 04:10, Max wrote: >> > Hi, > >> Not directly - the error is not triggered from the code I've added. But >> it could be that my code somehow changed/not changed metadata in some >> corner case. I'm unable to reproduce this locally - is there way to get >> file details from jenkins? Permission, owner, xattr etc from both target >> and destination of the copy and upper folders? > well, the responsibility is with you. Have you looked at the console output and when it happens? > > It happens with "make: *** [distcheck] Error 1". Which means the source directory will be checked out read-only, which means the files you copy are read-only. I would be surprised if > > DISTCHECK_CONFIGURE_FLAGS=--enable-sysmocom-bts=no --enable-sysmocom-dsp=no --enable-vty-tests AM_DISTCHECK_CONFIGURE_FLAGS=--enable-sysmocom-bts=no --enable-sysmocom-dsp=no --enable-vty-tests PKG_CONFIG_PATH=/home/builder/source/workspace/osmo-pcu/label/linux_i386_debian_squeeze/sysmobts/no/sysmodsp/no/deps/install/lib/pkgconfig LD_LIBRARY_PATH=/home/builder/source/workspace/osmo-pcu/label/linux_i386_debian_squeeze/sysmobts/no/sysmodsp/no/deps/install/lib make distcheck > > doesn't reproduce the issue for you. > > holger -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Wed Apr 13 15:29:51 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 13 Apr 2016 17:29:51 +0200 Subject: [PATCH] Fix build failure Message-ID: <1460561391-31296-1-git-send-email-msuraev@sysmocom.de> From: Max After copytree the destination directory might end up not being writable - this causes failure for subsequent writeconfig tests. Force rwx permissions to fix it. --- osmopy/osmotestconfig.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osmopy/osmotestconfig.py b/osmopy/osmotestconfig.py index 5c981d1..c601e82 100644 --- a/osmopy/osmotestconfig.py +++ b/osmopy/osmotestconfig.py @@ -17,7 +17,7 @@ import os import os.path import time -import sys, shutil +import sys, shutil, stat import tempfile import osmopy.obscvty as obscvty @@ -76,6 +76,7 @@ def copy_config(dirname, config): shutil.rmtree(dirname, True) ign = shutil.ignore_patterns('*.cfg') shutil.copytree(os.path.dirname(config), dirname, ignore=ign) + os.chmod(dirname, stat.S_IRWXU) try: os.stat(dirname) -- 2.8.1 From nhofmeyr at sysmocom.de Wed Apr 13 15:45:25 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 13 Apr 2016 17:45:25 +0200 Subject: [PATCH] Fix RANAP SSN: it's 142, not 143 Message-ID: <1460562325-21728-1-git-send-email-nhofmeyr@sysmocom.de> 143 is actually the SSN for RNSAP. Wireshark displayed a RNSAP message type and malformed packet warning until I fixed this to 142. Now I get the proper RANAP and id-Paging reported. There has been a reallocation for RANAP and RNSAP SSNs, though the old SSN for RANAP is apparently 32 (seen in a pcap from a real 3G network). When I send 32 instead of 142, wireshark also decodes the message as valid RANAP. --- include/osmocom/sigtran/sccp_sap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osmocom/sigtran/sccp_sap.h b/include/osmocom/sigtran/sccp_sap.h index 5696b47..15aa840 100644 --- a/include/osmocom/sigtran/sccp_sap.h +++ b/include/osmocom/sigtran/sccp_sap.h @@ -106,7 +106,7 @@ enum osmo_sccp_ssn { OSMO_SCCP_SSN_RES_INTL = 0x0c, OSMO_SCCP_SSN_BISDN = 0x0d, OSMO_SCCP_SSN_TC_TEST = 0x0e, - OSMO_SCCP_SSN_RANAP = 143, + OSMO_SCCP_SSN_RANAP = 142, }; struct osmo_sccp_gt { -- 2.1.4 From nhofmeyr at sysmocom.de Wed Apr 13 16:01:22 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 13 Apr 2016 18:01:22 +0200 Subject: [PATCH] sua_test_common.c: use global RANAP SSN definition Message-ID: <1460563282-23900-1-git-send-email-nhofmeyr@sysmocom.de> The test 'hardcoded' a local define for RANAP SSN as 142, instead use the proper OSMO_SCCP_SSN_RANAP define from sccp_sap.h --- tests/sigtran/sua_test_common.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/sigtran/sua_test_common.c b/tests/sigtran/sua_test_common.c index aed4899..66fade0 100644 --- a/tests/sigtran/sua_test_common.c +++ b/tests/sigtran/sua_test_common.c @@ -44,8 +44,6 @@ static void sccp_make_addr_pc_ssn(struct osmo_sccp_addr *addr, uint32_t pc, uint addr->pc = pc; } -#define SSN_RANAP 142 - struct osmo_prim_hdr *make_conn_req(uint32_t conn_id) { struct msgb *msg = msgb_alloc(1024, "conn_req"); @@ -56,8 +54,8 @@ struct osmo_prim_hdr *make_conn_req(uint32_t conn_id) OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_REQUEST, msg); /* Set SSN for calling and called addr */ - sccp_make_addr_pc_ssn(&prim->u.connect.called_addr, 2, SSN_RANAP); - sccp_make_addr_pc_ssn(&prim->u.connect.calling_addr, 1, SSN_RANAP); + sccp_make_addr_pc_ssn(&prim->u.connect.called_addr, 2, OSMO_SCCP_SSN_RANAP); + sccp_make_addr_pc_ssn(&prim->u.connect.calling_addr, 1, OSMO_SCCP_SSN_RANAP); prim->u.connect.sccp_class = 2; prim->u.connect.conn_id = conn_id; -- 2.1.4 From Ivan.Kluchnikov at fairwaves.ru Wed Apr 13 17:15:39 2016 From: Ivan.Kluchnikov at fairwaves.ru (Ivan Kluchnikov) Date: Wed, 13 Apr 2016 20:15:39 +0300 Subject: [PATCH 1/2] Add support of virtual networks for sending network name to ms depending on imsi In-Reply-To: References: <1460458138-12207-1-git-send-email-kluchnikovi@gmail.com> <5D1B55C4-0B8C-414F-8B8C-BFF1094ECAF8@freyther.de> Message-ID: Holger, > Yes, I agree that the current implementation is not enough flexible and > it is a good idea to use imsi-prefix instead of mcc and mnc, also it will > fix the issue with 3 digit mnc. > > yes? But how do you intend to fix it? The current structure will not be > enough > It requires changes in the code, but what I meant, we can have it as an option later - whether you want to specify mcc/mnc separately or as a prefix/regex. Btw, I think we can treat mcc/mnc as strings for virtual networks instead of integers to solve the 2/3 digit mnc issue. > > > Do you think it makes sense? > > But I am not sure that I understand the idea of using regexp for the > IMSI, could you please clarify for which cases it could be useful? > > I understand you want to fill a short-term gap but I don't think it is the > right approach to "roaming" at all. At the end of classic roaming one will: > > * Get a yes/no if it is allowed to roam > * Get subscriber data (MSISDN, ...) > * The subscribed services (allowed to do telephony) > > Right now the code is just about sending different network names. that > seems very different from roaming? Just for clarification, it is not about classic roaming, but about roaming-based network sharing concept which is described in TS 123 251 Network sharing; Architecture and functional description. It is also includes 4.2.3.2 Behaviour of non-supporting UEs (GERAN, UTRAN) "It is recommended for the network and the UE to support the Network Identity part of the Network Identity and Time Zone feature for providing the UE with the name of the serving PLMN operator." Regarding classic roaming, we have implemented remote protocol for LU (and also for SMS and USSD) based on gsup protocol and this protocol allows to update and manage the subscriber list, which includes: * Get a yes/no if it is allowed to roam * Get subscriber data (MSISDN, ...) Calls are handled through MNCC/SIP in case of roaming scenario and does not require any changes. This code in our fairwaves/sup-* branches, but it is not ready for merging now, I hope we will be able to cleanup this code soon. 2016-04-13 13:39 GMT+03:00 Holger Freyther : > > > On 13 Apr 2016, at 05:18, Ivan Kluchnikov > wrote: > > > > Hi Holger, > > > > Hi Ivan, > > > > > > Yes, I agree that the current implementation is not enough flexible and > it is a good idea to use imsi-prefix instead of mcc and mnc, also it will > fix the issue with 3 digit mnc. > > yes? But how do you intend to fix it? The current structure will not be > enough > > > Do you think it makes sense? > > But I am not sure that I understand the idea of using regexp for the > IMSI, could you please clarify for which cases it could be useful? > > I understand you want to fill a short-term gap but I don't think it is the > right approach to "roaming" at all. At the end of classic roaming one will: > > * Get a yes/no if it is allowed to roam > * Get subscriber data (MSISDN, ...) > * The subscribed services (allowed to do telephony) > > Right now the code is just about sending different network names. that > seems very different from roaming? > > holger -- Regards, Ivan Kluchnikov. http://fairwaves.ru -------------- next part -------------- An HTML attachment was scrubbed... URL: From suraev at alumni.ntnu.no Wed Apr 13 17:52:47 2016 From: suraev at alumni.ntnu.no (=?UTF-8?B?TWF4ICjimK0p?=) Date: Wed, 13 Apr 2016 19:52:47 +0200 Subject: IMSI localization In-Reply-To: <570D04E1.4070803@sysmocom.de> References: <69F373B5-BF0F-47B6-BB7A-8830576D9852@gmail.com> <570D04E1.4070803@sysmocom.de> Message-ID: <570E876F.4020804@alumni.ntnu.no> It goes without saying, but just in case a friendly reminder - make sure not to break any laws on privacy: government hates competition. 12.04.2016 16:23, Max ?????: > Hi. > > You can use RRLP protocol. There is some code available in > http://git.osmocom.org/osmocom-lcs/ > > On 04/12/2016 04:06 PM, robert wrote: >> Hi, >> >> I am trying to find a solution that enables to find the position of the phone connected to my network. Are there any GSM protocols that provide such features or is it only done on the RF level using direction finders ? >> >> >> >> Best Regards, >> Robert, > From holger at freyther.de Thu Apr 14 00:07:03 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 13 Apr 2016 20:07:03 -0400 Subject: [PATCH 2/2] Add extra debug output with channel mode and type In-Reply-To: <57051787.9030408@sysmocom.de> References: <1458817545-2039-1-git-send-email-msuraev@sysmocom.de> <1458817545-2039-2-git-send-email-msuraev@sysmocom.de> <20160327084604.GR27418@nataraja> <57051787.9030408@sysmocom.de> Message-ID: <2702D6A9-BDB3-4EF8-94FA-C1B981C56697@freyther.de> > On 06 Apr 2016, at 10:04, Max wrote: > > The necessary changes are now in libosmocore master. please rebase this series (1/2 and 2/2) and re-send. holger From holger at freyther.de Thu Apr 14 00:22:34 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 13 Apr 2016 20:22:34 -0400 Subject: [PATCH 1/4] Add code generator for convolutional codes In-Reply-To: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> References: <1460384569-13790-1-git-send-email-msuraev@sysmocom.de> Message-ID: > On 11 Apr 2016, at 10:22, msuraev at sysmocom.de wrote: > > From: Max > > Add python utility to generate .c code with state/output tables for > convolutional encoder/decoder based on polynomial description of the > code. If argument given it'll be interpreted as intended output > directory, otherwise current working directory is used. Note: only > necessary tables are generated. Corresponding header files with actual > osmo_conv_code instance (including puncturing etc) have to be added > manually. > > Fixes: OS#1629 > --- > utils/conv_gen.py | 359 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 359 insertions(+) > create mode 100755 utils/conv_gen.py > > diff --git a/utils/conv_gen.py b/utils/conv_gen.py > new file mode 100755 > index 0000000..52c1ab3 > --- /dev/null > +++ b/utils/conv_gen.py > @@ -0,0 +1,359 @@ > +#!/usr/bin/python > + > +license =""" > +/* > + * Copyright (C) 2011-2016 Sylvain Munaut > + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH what is yours (sysmocom's) contribution to that file? I assume that Sylvain did most of the work, it would be nice to have this be reflected in the commit message. thank you holger From nhofmeyr at sysmocom.de Thu Apr 14 12:45:56 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 14:45:56 +0200 Subject: [PATCH] compiler warning: pointer type in OCTET_STRING_noalloc() Message-ID: <1460637956-19900-1-git-send-email-nhofmeyr@sysmocom.de> It's useless to declare the str arg as const when all the function does is assign it to a non-const pointer. I found one caller that wants to pass a const pointer, ranap_msg_factory.c:184. Fixing that in a commit to osmo-iuh. All other callers pass non-const str arguments anyway. --- include/asn1c/asn1helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asn1c/asn1helpers.h b/include/asn1c/asn1helpers.h index d6b5e18..90e78ae 100644 --- a/include/asn1c/asn1helpers.h +++ b/include/asn1c/asn1helpers.h @@ -21,7 +21,7 @@ uint32_t asn1bitstr_to_u32(const BIT_STRING_t *in); uint32_t asn1bitstr_to_u28(const BIT_STRING_t *in); uint32_t asn1bitstr_to_u24(const BIT_STRING_t *in); -static inline void OCTET_STRING_noalloc(OCTET_STRING_t *s, const uint8_t *str, int size) +static inline void OCTET_STRING_noalloc(OCTET_STRING_t *s, uint8_t *str, int size) { s->buf = str; s->size = size; -- 2.1.4 From holger at freyther.de Thu Apr 14 12:49:49 2016 From: holger at freyther.de (Holger Freyther) Date: Thu, 14 Apr 2016 08:49:49 -0400 Subject: [PATCH 2/2] NAT: reload BSCs config dynamically In-Reply-To: <1460540199-23321-2-git-send-email-msuraev@sysmocom.de> References: <1460540199-23321-1-git-send-email-msuraev@sysmocom.de> <1460540199-23321-2-git-send-email-msuraev@sysmocom.de> Message-ID: > On 13 Apr 2016, at 05:36, msuraev at sysmocom.de wrote: > > > + # use separate ip to avoid interference with other tests > + ip = "127.0.0.4" First question with this comment: What other tests? Do you have an example? If yes, it should be in the comment. :) ====================================================================== ERROR: testBSCreload (__main__.TestVTYNAT) ---------------------------------------------------------------------- Traceback (most recent call last): File "./vty_test_runner.py", line 655, in testBSCreload msc = nat_msc_test(self, ip) File "./vty_test_runner.py", line 1102, in nat_msc_test msc.bind((ip, 5000)) File "", line 1, in bind error: [Errno 99] Cannot assign requested address ---------------------------------------------------------------------- Ran 41 tests in 41.953s http://jenkins.osmocom.org/jenkins/job/OpenBSC/2146/MGCP=--disable-mgcp-transcoding,SMPP=--disable-smpp,label=linux_i386_debian_squeeze/console From nhofmeyr at sysmocom.de Thu Apr 14 12:49:00 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 14:49:00 +0200 Subject: [PATCH] compiler warning: unconstify arg passed to OCTET_STRING_noalloc() Message-ID: <1460638140-20008-1-git-send-email-nhofmeyr@sysmocom.de> This is after the patch to libasn1c, removing str arg constness. --- src/ranap_msg_factory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ranap_msg_factory.c b/src/ranap_msg_factory.c index bdae92e..461df1a 100644 --- a/src/ranap_msg_factory.c +++ b/src/ranap_msg_factory.c @@ -181,7 +181,7 @@ struct msgb *ranap_new_msg_dt(uint8_t sapi, const uint8_t *nas, unsigned int nas ies.sapi = RANAP_SAPI_sapi_0; /* Avoid copying + later freeing of OCTET STRING */ - OCTET_STRING_noalloc(&ies.nas_pdu, nas, nas_len); + OCTET_STRING_noalloc(&ies.nas_pdu, (uint8_t*)nas, nas_len); /* ies -> dt */ rc = ranap_encode_directtransferies(&dt, &ies); -- 2.1.4 From nhofmeyr at sysmocom.de Thu Apr 14 13:12:16 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 15:12:16 +0200 Subject: [PATCH] logging.c: assert category_token allocation (CID #57871) Message-ID: <1460639536-21611-1-git-send-email-nhofmeyr@sysmocom.de> --- src/logging.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/logging.c b/src/logging.c index 35746e9..b96e64a 100644 --- a/src/logging.c +++ b/src/logging.c @@ -190,6 +190,7 @@ void log_parse_category_mask(struct log_target* target, const char *_mask) target->categories[i].enabled = 0; category_token = strtok(mask, ":"); + OSMO_ASSERT(category_token); do { for (i = 0; i < osmo_log_info->num_cat; ++i) { size_t length, cat_length; -- 2.1.4 From nhofmeyr at sysmocom.de Thu Apr 14 13:21:30 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 15:21:30 +0200 Subject: [PATCH 1/4] gprs_gmm: ensure llme present upon Attach Req (CID #57686) In-Reply-To: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1460640093-22167-2-git-send-email-nhofmeyr@sysmocom.de> --- openbsc/src/gprs/gprs_gmm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c index 5f0a5fd..438e047 100644 --- a/openbsc/src/gprs/gprs_gmm.c +++ b/openbsc/src/gprs/gprs_gmm.c @@ -838,6 +838,10 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg, int rc; LOGMMCTXP(LOGL_INFO, ctx, "-> GMM ATTACH REQUEST "); + if (!llme) { + LOGMMCTXP(LOGL_ERROR, ctx, "No LLME for GMM ATTACH REQUEST"); + return -EINVAL; + } /* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either * with a foreign TLLI (P-TMSI that was allocated to the MS before), -- 2.1.4 From nhofmeyr at sysmocom.de Thu Apr 14 13:21:29 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 15:21:29 +0200 Subject: [PATCH 0/4] take care of some coverity warnings Message-ID: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> Fixing a few NULL dereference warnings found by the Iu coverity check. They are not related apart from that. Neels Hofmeyr (4): gprs_gmm: ensure llme present upon Attach Req (CID #57686) gtphub_unmap_header_tei(): don't dereference unmapped_tei arg if not present (CID #57687) bsc_nat: forward_sccp_to_msc(): assert con presence (CID #57872) gbproxy_test: assert msg allocation (CID #57873) openbsc/src/gprs/gprs_gmm.c | 4 ++++ openbsc/src/gprs/gtphub.c | 10 ++++++---- openbsc/src/osmo-bsc_nat/bsc_nat.c | 1 + openbsc/tests/gbproxy/gbproxy_test.c | 1 + 4 files changed, 12 insertions(+), 4 deletions(-) -- 2.1.4 From nhofmeyr at sysmocom.de Thu Apr 14 13:21:31 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 15:21:31 +0200 Subject: [PATCH 2/4] gtphub_unmap_header_tei(): don't dereference unmapped_tei arg if not present (CID #57687) In-Reply-To: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1460640093-22167-3-git-send-email-nhofmeyr@sysmocom.de> --- openbsc/src/gprs/gtphub.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index e8bd3ae..58300ea 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -1434,14 +1434,16 @@ static int gtphub_unmap_header_tei(struct gtphub_peer_port **to_port_p, p->header_tei_rx, gtphub_port_str(from_port)); return -1; } - OSMO_ASSERT(*unmapped_from_tun); + + if (unmapped_from_tun) { + OSMO_ASSERT(*unmapped_from_tun); + LOG(LOGL_DEBUG, "Unmapped TEI coming from: %s\n", + gtphub_tunnel_str(*unmapped_from_tun)); + } uint32_t unmapped_tei = to->tei_orig; set_tei(p, unmapped_tei); - LOG(LOGL_DEBUG, "Unmapped TEI coming from: %s\n", - gtphub_tunnel_str(*unmapped_from_tun)); - /* May be NULL for an invalidated tunnel. */ *to_port_p = to->peer; -- 2.1.4 From nhofmeyr at sysmocom.de Thu Apr 14 13:21:32 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 15:21:32 +0200 Subject: [PATCH 3/4] bsc_nat: forward_sccp_to_msc(): assert con presence (CID #57872) In-Reply-To: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1460640093-22167-4-git-send-email-nhofmeyr@sysmocom.de> --- openbsc/src/osmo-bsc_nat/bsc_nat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index cacb919..b065769 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -1152,6 +1152,7 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg) if (!create_sccp_src_ref(bsc, parsed)) goto exit2; con = patch_sccp_src_ref_to_msc(msg, parsed, bsc); + OSMO_ASSERT(con); con->msc_con = bsc->nat->msc_con; con_msc = con->msc_con; con->filter_state.con_type = con_type; -- 2.1.4 From nhofmeyr at sysmocom.de Thu Apr 14 13:21:33 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 15:21:33 +0200 Subject: [PATCH 4/4] gbproxy_test: assert msg allocation (CID #57873) In-Reply-To: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1460640093-22167-5-git-send-email-nhofmeyr@sysmocom.de> --- openbsc/tests/gbproxy/gbproxy_test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 0ba827f..96a68b0 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -1293,6 +1293,7 @@ static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, stru } msg = gprs_ns_msgb_alloc(); + OSMO_ASSERT(msg); memmove(msg->data, data, data_len); msg->l2h = msg->data; msgb_put(msg, data_len); -- 2.1.4 From holger at freyther.de Thu Apr 14 13:33:37 2016 From: holger at freyther.de (Holger Freyther) Date: Thu, 14 Apr 2016 09:33:37 -0400 Subject: [PATCH] compiler warning: unconstify arg passed to OCTET_STRING_noalloc() In-Reply-To: <1460638140-20008-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460638140-20008-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <130058CD-4474-4EC5-AD77-68BEF9521C85@freyther.de> > On 14 Apr 2016, at 08:49, Neels Hofmeyr wrote: > > This is after the patch to libasn1c, removing str arg constness. > --- > src/ranap_msg_factory.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/src/ranap_msg_factory.c b/src/ranap_msg_factory.c > index bdae92e..461df1a 100644 > --- a/src/ranap_msg_factory.c > +++ b/src/ranap_msg_factory.c > @@ -181,7 +181,7 @@ struct msgb *ranap_new_msg_dt(uint8_t sapi, const uint8_t *nas, unsigned int nas > ies.sapi = RANAP_SAPI_sapi_0; > > /* Avoid copying + later freeing of OCTET STRING */ > - OCTET_STRING_noalloc(&ies.nas_pdu, nas, nas_len); > + OCTET_STRING_noalloc(&ies.nas_pdu, (uint8_t*)nas, nas_len); doesn't seem the right way forward. Does OCTET_STRING_noalloc or its users need/want to modify the buffer? holger From holger at freyther.de Thu Apr 14 13:37:52 2016 From: holger at freyther.de (Holger Freyther) Date: Thu, 14 Apr 2016 09:37:52 -0400 Subject: [PATCH 0/4] take care of some coverity warnings In-Reply-To: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: > On 14 Apr 2016, at 09:21, Neels Hofmeyr wrote: > > Fixing a few NULL dereference warnings found by the Iu coverity check. > They are not related apart from that. I just looked at the gprs_gmm patch and stopped reading. Your commit message should at least have some of the context of coverity. So when is llme NULL? Is it allowed to be NULL? Does it make sense? We don't want to blindly do these things but understand the code around and see if the tool is right or wrong. And if we disagree maybe change the flow of code or add an assert. holger From nhofmeyr at sysmocom.de Thu Apr 14 14:23:49 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 16:23:49 +0200 Subject: iuh: Coverity build breakage because of old sctp In-Reply-To: <5A2BC71A-3AAC-45F6-A44A-2FC7553218FD@freyther.de> References: <55242E3B-94E9-4864-A201-2F18CA199D01@freyther.de> <26D7E73B-CDD1-431A-9C19-4D3305FBDE28@freyther.de> <5A2BC71A-3AAC-45F6-A44A-2FC7553218FD@freyther.de> Message-ID: <20160414142349.GA2515@dub6> On Wed, Apr 13, 2016 at 06:39:47AM -0400, Holger Freyther wrote: > > On 12 Apr 2016, at 20:36, Holger Freyther wrote: > > the coverity upload is now broken for a week... it is more than time to fix it! > > *sigh* Apologies, for unknown reasons I saw these mails as new only today. Probably human error from my side. I had fixed one but missed the other, as you pointed out in chat. That definitely was human error from my side. To make up for it, I (hopefully) resolved a few coverity warnings today, as you may have noticed from the patches. ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From holger at freyther.de Thu Apr 14 14:40:56 2016 From: holger at freyther.de (Holger Freyther) Date: Thu, 14 Apr 2016 10:40:56 -0400 Subject: iuh: Coverity build breakage because of old sctp In-Reply-To: <20160414142349.GA2515@dub6> References: <55242E3B-94E9-4864-A201-2F18CA199D01@freyther.de> <26D7E73B-CDD1-431A-9C19-4D3305FBDE28@freyther.de> <5A2BC71A-3AAC-45F6-A44A-2FC7553218FD@freyther.de> <20160414142349.GA2515@dub6> Message-ID: > On 14 Apr 2016, at 10:23, Neels Hofmeyr wrote: > > To make up for it, I (hopefully) resolved a few coverity warnings today, as you > may have noticed from the patches. thanks! From nhofmeyr at sysmocom.de Thu Apr 14 14:38:42 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 16:38:42 +0200 Subject: [PATCH] queue_new(): if calloc fails, abort (CID #57918) Message-ID: <1460644722-22972-1-git-send-email-nhofmeyr@sysmocom.de> Coverity complains about a 'Dereference before null check' on *queue. So, push the NULL check further up, but also, instead of handling a calloc failure as error, rather abort the program. --- gtp/queue.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gtp/queue.c b/gtp/queue.c index 7c971b0..707b522 100644 --- a/gtp/queue.c +++ b/gtp/queue.c @@ -127,16 +127,15 @@ int queue_new(struct queue_t **queue) if (QUEUE_DEBUG) printf("queue_new\n"); *queue = calloc(1, sizeof(struct queue_t)); + if (!(*queue)) + abort(); (*queue)->next = 0; (*queue)->first = -1; (*queue)->last = -1; if (QUEUE_DEBUG) queue_print(*queue); - if (*queue) - return 0; - else - return EOF; + return 0; } /*! \brief Deallocates queue structure */ -- 2.1.4 From nhofmeyr at sysmocom.de Thu Apr 14 14:57:11 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 16:57:11 +0200 Subject: [PATCH] compiler warning: unconstify arg passed to OCTET_STRING_noalloc() In-Reply-To: <130058CD-4474-4EC5-AD77-68BEF9521C85@freyther.de> References: <1460638140-20008-1-git-send-email-nhofmeyr@sysmocom.de> <130058CD-4474-4EC5-AD77-68BEF9521C85@freyther.de> Message-ID: <20160414145711.GB2515@dub6> On Thu, Apr 14, 2016 at 09:33:37AM -0400, Holger Freyther wrote: > > > On 14 Apr 2016, at 08:49, Neels Hofmeyr wrote: > > > > This is after the patch to libasn1c, removing str arg constness. > > --- > > src/ranap_msg_factory.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/src/ranap_msg_factory.c b/src/ranap_msg_factory.c > > index bdae92e..461df1a 100644 > > --- a/src/ranap_msg_factory.c > > +++ b/src/ranap_msg_factory.c > > @@ -181,7 +181,7 @@ struct msgb *ranap_new_msg_dt(uint8_t sapi, const uint8_t *nas, unsigned int nas > > ies.sapi = RANAP_SAPI_sapi_0; > > > > /* Avoid copying + later freeing of OCTET STRING */ > > - OCTET_STRING_noalloc(&ies.nas_pdu, nas, nas_len); > > + OCTET_STRING_noalloc(&ies.nas_pdu, (uint8_t*)nas, nas_len); > > doesn't seem the right way forward. Does OCTET_STRING_noalloc or its users need/want to modify the buffer? So, I want to change this: static inline void OCTET_STRING_noalloc(OCTET_STRING_t *s, const uint8_t *str, int size) { s->buf = str; s->size = size; } because OCTET_STRING_t.s is not const, and must not be const, will never be const. OCTET_STRING_noalloc() has no way to tell whether callers will subsequently modify the buffer or not. So that function must not secretly unconst: static inline void OCTET_STRING_noalloc(OCTET_STRING_t *s, const uint8_t *str, int size) { s->buf = (uint8_t*)str; s->size = size; } ^ this is bad. To get rid of compiler warnings, I want to change to more sensible: static inline void OCTET_STRING_noalloc(OCTET_STRING_t *s, uint8_t *str, int size) { s->buf = str; s->size = size; } All callers of OCTET_STRING_noalloc() pass a non-const pointer, except that one above. I just want to unconst that single caller. OCTET_STRING_t.buf is simply not const. So if we're not going to do an ugly unconst like this somewhere, we have to change ranap_new_msg_dt() to take a non-const uint8_t* nas. I didn't want to change that though, because the function does rightfully signal outwards that *nas is never changed, because its use of the unconsted value is contained entirely in that function (to encode a message) and nas is in fact not modified (given that the encoders work correctly). Admitted, I should also add a comment. ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Thu Apr 14 15:05:27 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 14 Apr 2016 17:05:27 +0200 Subject: [PATCH] compiler warning: unconstify arg passed to OCTET_STRING_noalloc() Message-ID: <1460646327-23854-1-git-send-email-nhofmeyr@sysmocom.de> This is after the patch to libasn1c, removing str arg constness. Note the comment added in the code. --- src/ranap_msg_factory.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ranap_msg_factory.c b/src/ranap_msg_factory.c index bdae92e..e87eeaf 100644 --- a/src/ranap_msg_factory.c +++ b/src/ranap_msg_factory.c @@ -180,8 +180,13 @@ struct msgb *ranap_new_msg_dt(uint8_t sapi, const uint8_t *nas, unsigned int nas else ies.sapi = RANAP_SAPI_sapi_0; - /* Avoid copying + later freeing of OCTET STRING */ - OCTET_STRING_noalloc(&ies.nas_pdu, nas, nas_len); + /* + * Avoid copying + later freeing of OCTET STRING. + * To store the pointer in an OCTET_STRING_t without copying, we need + * to un-const *nas. Note: un-consting *nas is safe because ies.nas_pdu + * is only used to store the IEs in dt. + */ + OCTET_STRING_noalloc(&ies.nas_pdu, (uint8_t*)nas, nas_len); /* ies -> dt */ rc = ranap_encode_directtransferies(&dt, &ies); -- 2.1.4 From msuraev at sysmocom.de Fri Apr 15 14:04:04 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 15 Apr 2016 16:04:04 +0200 Subject: [PATCH] Add function to get osmo_earfcn bit size Message-ID: <1460729044-8855-1-git-send-email-msuraev@sysmocom.de> From: Max This function returns the number of bits necessary to pack osmo_earfcn into Repeated E-UTRAN Neighbour Cells IE (3GPP TS 44.018 Table 10.5.2.33b.1). --- include/osmocom/gsm/sysinfo.h | 1 + src/gsm/libosmogsm.map | 1 + src/gsm/sysinfo.c | 24 ++++++++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/include/osmocom/gsm/sysinfo.h b/include/osmocom/gsm/sysinfo.h index cb7e10d..c7972f4 100644 --- a/include/osmocom/gsm/sysinfo.h +++ b/include/osmocom/gsm/sysinfo.h @@ -66,6 +66,7 @@ typedef uint8_t sysinfo_buf_t[GSM_MACBLOCK_LEN]; extern const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE]; int osmo_earfcn_add(struct osmo_earfcn_si2q *e, uint16_t arfcn, uint8_t meas_bw); int osmo_earfcn_del(struct osmo_earfcn_si2q *e, uint16_t arfcn); +size_t osmo_earfcn_bit_size(const struct osmo_earfcn_si2q *e); void osmo_earfcn_init(struct osmo_earfcn_si2q *e); uint8_t osmo_sitype2rsl(enum osmo_sysinfo_type si_type); enum osmo_sysinfo_type osmo_rsl2sitype(uint8_t rsl_si); diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index a3e4e14..6886a6c 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -31,6 +31,7 @@ dbm2rxlev; osmo_earfcn_add; osmo_earfcn_del; +osmo_earfcn_bit_size; osmo_earfcn_init; gprs_cipher_gen_input_i; diff --git a/src/gsm/sysinfo.c b/src/gsm/sysinfo.c index 42e717f..3ec5444 100644 --- a/src/gsm/sysinfo.c +++ b/src/gsm/sysinfo.c @@ -144,6 +144,30 @@ int osmo_earfcn_add(struct osmo_earfcn_si2q *e, uint16_t arfcn, uint8_t meas_bw) return -ENOMEM; } +/*! \brief Return number of bits necessary to represent earfcn struct as + * Repeated E-UTRAN Neighbour Cells IE from 3GPP TS 44.018 Table 10.5.2.33b.1 + * \param[in,out] e earfcn struct + * \returns number of bits + */ +size_t osmo_earfcn_bit_size(const struct osmo_earfcn_si2q *e) +{ + /* 1 stop bit + 5 bits for THRESH_E-UTRAN_high */ + size_t i, bits = 6; + for (i = 0; i < e->length; i++) { + if (e->arfcn[i] != OSMO_EARFCN_INVALID) { + bits += 17; + if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i]) + bits++; + else + bits += 4; + } + } + bits += (e->prio_valid) ? 4 : 1; + bits += (e->thresh_lo_valid) ? 6 : 1; + bits += (e->qrxlm_valid) ? 6 : 1; + return bits; +} + /*! \brief Delete arfcn (and corresponding measurement bandwith) from earfcn * struct * \param[in,out] e earfcn struct -- 2.8.1 From msuraev at sysmocom.de Fri Apr 15 14:04:44 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 15 Apr 2016 16:04:44 +0200 Subject: [PATCH 1/3] Add SI2quater support to SI3 Message-ID: <1460729086-8961-1-git-send-email-msuraev@sysmocom.de> From: Max Advertise SI2 quater presence and location (if available) using SI3 according to 3GPP TS 44.018 ? 10.5.2.34 --- openbsc/include/openbsc/rest_octets.h | 3 ++- openbsc/src/libbsc/bsc_init.c | 1 + openbsc/src/libbsc/rest_octets.c | 7 +++++++ openbsc/src/libbsc/system_information.c | 8 +++++++- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/openbsc/include/openbsc/rest_octets.h b/openbsc/include/openbsc/rest_octets.h index 963b010..9560b14 100644 --- a/openbsc/include/openbsc/rest_octets.h +++ b/openbsc/include/openbsc/rest_octets.h @@ -43,7 +43,8 @@ struct gsm48_si_ro_info { present:1; } scheduling; struct gsm48_si3_gprs_ind gprs_ind; - + /* SI 3 specific */ + uint8_t si2quater_indicator; /* SI 4 specific */ struct gsm48_lsa_params lsa_params; uint16_t cell_id; diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 713109c..fd8dd66 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -140,6 +140,7 @@ int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx) gen_si[n_si++] = SYSINFO_TYPE_2; gen_si[n_si++] = SYSINFO_TYPE_2bis; gen_si[n_si++] = SYSINFO_TYPE_2ter; + gen_si[n_si++] = SYSINFO_TYPE_2quater; gen_si[n_si++] = SYSINFO_TYPE_3; gen_si[n_si++] = SYSINFO_TYPE_4; diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index 4545794..fa35f21 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -129,6 +129,13 @@ int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3) /* GPRS Indicator */ append_gprs_ind(&bv, &si3->gprs_ind); + bitvec_set_bit(&bv, H); /* 3G Early Classmark Sending Restriction controlled by early_cm_ctrl above */ + + if (si3->si2quater_indicator) { + bitvec_set_bit(&bv, H); /* indicator struct present */ + bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */ + } + bitvec_spare_padding(&bv, (bv.data_len*8)-1); return bv.data_len; } diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 1ee9d41..62ee306 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -510,6 +510,7 @@ static struct gsm48_si_ro_info si_info = { .ra_colour = 0, .present = 1, }, + .si2quater_indicator = 0, .lsa_params = { .present = 0, }, @@ -545,7 +546,12 @@ static int generate_si3(uint8_t *output, struct gsm_bts *bts) } else { si_info.si2ter_indicator = 0; } - + if ((bts->si_valid & (1 << SYSINFO_TYPE_2quater))) { + LOGP(DRR, LOGL_INFO, "SI 2quater is included.\n"); + si_info.si2quater_indicator = 1; + } else { + si_info.si2quater_indicator = 0; + } /* SI3 Rest Octets (10.5.2.34), containing CBQ, CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME Power Offset, 2ter Indicator, Early Classmark Sending, -- 2.8.1 From msuraev at sysmocom.de Fri Apr 15 14:04:45 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 15 Apr 2016 16:04:45 +0200 Subject: [PATCH 2/3] Refactor SI-related code In-Reply-To: <1460729086-8961-1-git-send-email-msuraev@sysmocom.de> References: <1460729086-8961-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1460729086-8961-2-git-send-email-msuraev@sysmocom.de> From: Max Move define to header file. Use inline functions where appropriate. Change int variables which are used as boolean into actual bool to make code easier to follow. --- openbsc/include/openbsc/abis_rsl.h | 1 + openbsc/src/libbsc/abis_rsl.c | 2 -- openbsc/src/libbsc/system_information.c | 37 +++++++++++++++++---------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h index b27595e..100a6d1 100644 --- a/openbsc/include/openbsc/abis_rsl.h +++ b/openbsc/include/openbsc/abis_rsl.h @@ -31,6 +31,7 @@ struct gsm_lchan; struct gsm_subscriber; struct gsm_bts_trx_ts; +#define GSM48_LEN2PLEN(a) (((a) << 2) | 1) int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data, int len); diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 8e9258c..df76788 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -1332,8 +1332,6 @@ static void t3109_expired(void *data) rsl_rf_chan_release(lchan, 1, SACCH_NONE); } -#define GSM48_LEN2PLEN(a) (((a) << 2) | 1) - /* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */ static int rsl_send_imm_ass_rej(struct gsm_bts *bts, unsigned int num_req_refs, diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 62ee306..5490c83 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -67,8 +68,8 @@ static int is_dcs_net(const struct gsm_bts *bts) return 1; } -static int use_arfcn(const struct gsm_bts *bts, const int bis, const int ter, - const int pgsm, const int arfcn) +static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter, + const bool pgsm, const int arfcn) { if (bts->force_combined_si) return !bis && !ter; @@ -135,9 +136,9 @@ static int freq_list_bmrel_set_arfcn(uint8_t *chan_list, unsigned int arfcn) } /* generate a variable bitmap */ -static int enc_freq_lst_var_bitmap(uint8_t *chan_list, +static inline int enc_freq_lst_var_bitmap(uint8_t *chan_list, struct bitvec *bv, const struct gsm_bts *bts, - int bis, int ter, int min, int pgsm) + bool bis, bool ter, int min, bool pgsm) { int i; @@ -164,9 +165,9 @@ static int enc_freq_lst_var_bitmap(uint8_t *chan_list, } /* generate a frequency list with the range 512 format */ -static int enc_freq_lst_range(uint8_t *chan_list, +static inline int enc_freq_lst_range(uint8_t *chan_list, struct bitvec *bv, const struct gsm_bts *bts, - int bis, int ter, int pgsm) + bool bis, bool ter, bool pgsm) { int arfcns[RANGE_ENC_MAX_ARFCNS]; int w[RANGE_ENC_MAX_ARFCNS]; @@ -226,15 +227,15 @@ static int enc_freq_lst_range(uint8_t *chan_list, /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */ static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv, - const struct gsm_bts *bts, int bis, int ter) + const struct gsm_bts *bts, bool bis, bool ter) { - int i, rc, min = -1, max = -1, pgsm = 0, arfcns = 0; - + int i, rc, min = -1, max = -1, arfcns = 0; + bool pgsm = false; memset(chan_list, 0, 16); if (bts->band == GSM_BAND_900 && bts->c0->arfcn >= 1 && bts->c0->arfcn <= 124) - pgsm = 1; + pgsm = true; /* P-GSM-only handsets only support 'bit map 0 format' */ if (!bis && !ter && pgsm) { chan_list[0] = 0; @@ -327,12 +328,12 @@ static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv, } /* then we generate a GSM 04.08 frequency list from the bitvec */ - return bitvec2freq_list(chan_list, bv, bts, 0, 0); + return bitvec2freq_list(chan_list, bv, bts, false, false); } /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */ static int generate_bcch_chan_list(uint8_t *chan_list, struct gsm_bts *bts, - int si5, int bis, int ter) + bool si5, bool bis, bool ter) { struct gsm_bts *cur_bts; struct bitvec *bv; @@ -422,7 +423,7 @@ static int generate_si2(uint8_t *output, struct gsm_bts *bts) si2->header.skip_indicator = 0; si2->header.system_information = GSM48_MT_RR_SYSINFO_2; - rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, 0, 0, 0); + rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, false, false, false); if (rc < 0) return rc; list_arfcn(si2->bcch_frequency_list, 0xce, @@ -448,7 +449,7 @@ static int generate_si2bis(uint8_t *output, struct gsm_bts *bts) si2b->header.skip_indicator = 0; si2b->header.system_information = GSM48_MT_RR_SYSINFO_2bis; - rc = generate_bcch_chan_list(si2b->bcch_frequency_list, bts, 0, 1, 0); + rc = generate_bcch_chan_list(si2b->bcch_frequency_list, bts, false, true, false); if (rc < 0) return rc; n = list_arfcn(si2b->bcch_frequency_list, 0xce, @@ -482,7 +483,7 @@ static int generate_si2ter(uint8_t *output, struct gsm_bts *bts) si2t->header.skip_indicator = 0; si2t->header.system_information = GSM48_MT_RR_SYSINFO_2ter; - rc = generate_bcch_chan_list(si2t->ext_bcch_frequency_list, bts, 0, 0, 1); + rc = generate_bcch_chan_list(si2t->ext_bcch_frequency_list, bts, false, false, true); if (rc < 0) return rc; n = list_arfcn(si2t->ext_bcch_frequency_list, 0x8e, @@ -630,7 +631,7 @@ static int generate_si5(uint8_t *output, struct gsm_bts *bts) si5->rr_protocol_discriminator = GSM48_PDISC_RR; si5->skip_indicator = 0; si5->system_information = GSM48_MT_RR_SYSINFO_5; - rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, 1, 0, 0); + rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, true, false, false); if (rc < 0) return rc; list_arfcn(si5->bcch_frequency_list, 0xce, @@ -665,7 +666,7 @@ static int generate_si5bis(uint8_t *output, struct gsm_bts *bts) si5b->rr_protocol_discriminator = GSM48_PDISC_RR; si5b->skip_indicator = 0; si5b->system_information = GSM48_MT_RR_SYSINFO_5bis; - rc = generate_bcch_chan_list(si5b->bcch_frequency_list, bts, 1, 1, 0); + rc = generate_bcch_chan_list(si5b->bcch_frequency_list, bts, true, true, false); if (rc < 0) return rc; n = list_arfcn(si5b->bcch_frequency_list, 0xce, @@ -709,7 +710,7 @@ static int generate_si5ter(uint8_t *output, struct gsm_bts *bts) si5t->rr_protocol_discriminator = GSM48_PDISC_RR; si5t->skip_indicator = 0; si5t->system_information = GSM48_MT_RR_SYSINFO_5ter; - rc = generate_bcch_chan_list(si5t->bcch_frequency_list, bts, 1, 0, 1); + rc = generate_bcch_chan_list(si5t->bcch_frequency_list, bts, true, false, true); if (rc < 0) return rc; n = list_arfcn(si5t->bcch_frequency_list, 0x8e, -- 2.8.1 From msuraev at sysmocom.de Fri Apr 15 14:04:46 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 15 Apr 2016 16:04:46 +0200 Subject: [PATCH 3/3] Add basic SI2quater support In-Reply-To: <1460729086-8961-1-git-send-email-msuraev@sysmocom.de> References: <1460729086-8961-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1460729086-8961-3-git-send-email-msuraev@sysmocom.de> From: Max * support for sending arbitrary static SI2quater. * vty interface for neightbor EARFCNs specific to SI2quater. * dynamic generation of SI2quater messages. * unit test for SI2quater messages. Fixes: OS#1630 --- openbsc/include/openbsc/gsm_data_shared.h | 5 + openbsc/include/openbsc/rest_octets.h | 5 + openbsc/src/libbsc/bsc_init.c | 6 +- openbsc/src/libbsc/bsc_vty.c | 71 +++++++++++ openbsc/src/libbsc/rest_octets.c | 200 ++++++++++++++++++++++++++++++ openbsc/src/libbsc/system_information.c | 23 ++++ openbsc/src/libcommon/gsm_data.c | 5 + openbsc/tests/gsm0408/Makefile.am | 3 +- openbsc/tests/gsm0408/gsm0408_test.c | 69 +++++++++++ openbsc/tests/gsm0408/gsm0408_test.ok | 8 ++ 10 files changed, 391 insertions(+), 4 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 000207d..cbc0c77 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -105,6 +105,7 @@ struct gsm_abis_mo { #define A38_XOR_MAX_KEY_LEN 16 #define A38_COMP128_KEY_LEN 16 #define RSL_ENC_ALG_A5(x) (x+1) +#define MAX_EARFCN_LIST 512 /* is the data link established? who established it? */ #define LCHAN_SAPI_UNUSED 0 @@ -715,12 +716,16 @@ struct gsm_bts { struct bitvec neigh_list; struct bitvec cell_alloc; struct bitvec si5_neigh_list; + struct bitvec si2quater_na_list; + struct osmo_earfcn_si2q si2quater_neigh_list; struct { /* bitmask large enough for all possible ARFCN's */ uint8_t neigh_list[1024/8]; uint8_t cell_alloc[1024/8]; /* If the user wants a different neighbor list in SI5 than in SI2 */ uint8_t si5_neigh_list[1024/8]; + uint8_t meas_bw_list[MAX_EARFCN_LIST]; + uint16_t earfcn_list[MAX_EARFCN_LIST]; } data; } si_common; diff --git a/openbsc/include/openbsc/rest_octets.h b/openbsc/include/openbsc/rest_octets.h index 9560b14..fd5ec6a 100644 --- a/openbsc/include/openbsc/rest_octets.h +++ b/openbsc/include/openbsc/rest_octets.h @@ -1,10 +1,15 @@ #ifndef _REST_OCTETS_H #define _REST_OCTETS_H +#include #include +#include /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net); +int rest_octets_si2quater(uint8_t *data, + const struct osmo_earfcn_si2q *e, bool uarfcn, + bool earfcn); struct gsm48_si_selection_params { uint16_t penalty_time:5, diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index fd8dd66..fea6562 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -192,9 +192,9 @@ int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx) return 0; err_out: - LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u, most likely " - "a problem with neighbor cell list generation\n", - get_value_string(osmo_sitype_strs, i), bts->nr); + LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u: error <%s>," + "most likely a problem with neighbor cell list generation\n", + get_value_string(osmo_sitype_strs, i), bts->nr, strerror(-rc)); return rc; } diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 29f2501..9634508 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -692,6 +692,21 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) } } + for (i = 0; i < MAX_EARFCN_LIST; i++) { + if (bts->si_common.si2quater_neigh_list.arfcn[i] != + OSMO_EARFCN_INVALID) { + vty_out(vty, " si2quater neighbor-list add earfcn %u threshold %u", + bts->si_common.si2quater_neigh_list.arfcn[i], + bts->si_common.si2quater_neigh_list.thresh_hi); + if (bts->si_common.si2quater_neigh_list.meas_bw[i] != + OSMO_EARFCN_MEAS_INVALID) + vty_out(vty, " %u", + bts->si_common.si2quater_neigh_list.meas_bw[i]); + + vty_out(vty, "%s", VTY_NEWLINE); + } + } + vty_out(vty, " codec-support fr"); if (bts->codec.hr) vty_out(vty, " hr"); @@ -2743,6 +2758,60 @@ DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, + "si2quater neighbor-list add earfcn <1900-2200> threshold <0-1000> " + "[<0-255>]", "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" + "EARFCN of neighbor\n" "EARFCN of neighbor\n" "threshold high bits\n" + "threshold high bits\n" "measurement bandwidth\n") +{ + struct gsm_bts *bts = vty->index; + struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; + uint16_t arfcn = atoi(argv[0]); + uint8_t meas = OSMO_EARFCN_MEAS_INVALID, thresh = atoi(argv[1]); + int r; + + if (3 == argc) + meas = atoi(argv[2]); + + r = osmo_earfcn_add(e, arfcn, meas); + + if (r < 0) { + vty_out(vty, "Unable to add arfcn %u: %s%s", arfcn, strerror(r), + VTY_NEWLINE); + return CMD_WARNING; + } + + if (e->thresh_hi && thresh != e->thresh_hi) + vty_out(vty, "Warning: multiple thresholds are not supported, " + "overriding previous threshold %u%s", + e->thresh_hi, VTY_NEWLINE); + + e->thresh_hi = thresh; + + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, + "si2quater neighbor-list del earfcn <1900-2200>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" + "Delete from SI2quater manual neighbor list\n" + "EARFCN of neighbor\n") +{ + struct gsm_bts *bts = vty->index; + struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; + uint16_t arfcn = atoi(argv[1]); + int r = osmo_earfcn_del(e, arfcn); + if (r < 0) { + vty_out(vty, "Unable to delete arfcn %u: %s%s", arfcn, + strerror(r), VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd, "si5 neighbor-list (add|del) arfcn <0-1023>", "SI5 Neighbor List\n" @@ -3873,6 +3942,8 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_neigh_mode_cmd); install_element(BTS_NODE, &cfg_bts_neigh_cmd); install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_neigh_add_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_neigh_del_cmd); install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_force_comb_si_cmd); diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index fa35f21..b0f8728 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -24,10 +24,15 @@ #include #include #include +#include +#include #include #include #include +#include + +#define SI2Q_MAX_LEN 160 /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net) @@ -53,6 +58,201 @@ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net) return bv.data_len; } +/* Append Repeated E-UTRAN Neighbour Cell to bitvec: + * see 3GPP TS 44.018 Table 10.5.2.33b.1 + */ +static inline void append_eutran_neib_cell(struct bitvec *bv, + const struct osmo_earfcn_si2q *e) +{ + unsigned i; + for (i = 0; i < e->length; i++) { + if (e->arfcn[i] != OSMO_EARFCN_INVALID) { + bitvec_set_bit(bv, 1); /* EARFCN: */ + bitvec_set_uint(bv, e->arfcn[i], 16); + + if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i]) + bitvec_set_bit(bv, 0); + else { + /* Measurement Bandwidth: 9.1.54 */ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->meas_bw[i], 3); + } + } + } + + /* stop bit - end of EARFCN + Measurement Bandwidth sequence */ + bitvec_set_bit(bv, 0); + + if (e->prio_valid) { + /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->prio, 3); + } else + bitvec_set_bit(bv, 0); + + /* THRESH_E-UTRAN_high */ + bitvec_set_uint(bv, e->thresh_hi, 5); + + if (e->thresh_lo_valid) { + /* THRESH_E-UTRAN_low: */ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->thresh_lo, 5); + } else + bitvec_set_bit(bv, 0); + + if (e->qrxlm_valid) { + /* E-UTRAN_QRXLEVMIN: */ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->qrxlm, 5); + } else + bitvec_set_bit(bv, 0); +} + +static inline int append_earfcn_size(const struct osmo_earfcn_si2q *e) +{ + if (!e) + return -EFAULT; + /* account for all the constant bits */ + return 25 + osmo_earfcn_bit_size(e); +} + +static inline void append_earfcn(struct bitvec *bv, + const struct osmo_earfcn_si2q *e) +{ + /* Additions in Rel-5: */ + bitvec_set_bit(bv, H); + /* No 3G Additional Measurement Param. Descr. */ + bitvec_set_bit(bv, 0); + /* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */ + bitvec_set_bit(bv, 0); + /* Additions in Rel-6: */ + bitvec_set_bit(bv, H); + /* 3G_CCN_ACTIVE */ + bitvec_set_bit(bv, 0); + /* Additions in Rel-7: */ + bitvec_set_bit(bv, H); + /* No 700_REPORTING_OFFSET */ + bitvec_set_bit(bv, 0); + /* No 810_REPORTING_OFFSET */ + bitvec_set_bit(bv, 0); + /* Additions in Rel-8: */ + bitvec_set_bit(bv, H); + + /* Priority and E-UTRAN Parameters Description */ + bitvec_set_bit(bv, 1); + + /* No Serving Cell Priority Parameters Descr. */ + bitvec_set_bit(bv, 0); + /* No 3G Priority Parameters Description */ + bitvec_set_bit(bv, 0); + /* E-UTRAN Parameters Description */ + bitvec_set_bit(bv, 1); + + /* E-UTRAN_CCN_ACTIVE */ + bitvec_set_bit(bv, 0); + /* E-UTRAN_Start: 9.1.54 */ + bitvec_set_bit(bv, 1); + /* E-UTRAN_Stop: 9.1.54 */ + bitvec_set_bit(bv, 1); + + /* No E-UTRAN Measurement Parameters Descr. */ + bitvec_set_bit(bv, 0); + /* No GPRS E-UTRAN Measurement Param. Descr. */ + bitvec_set_bit(bv, 0); + + /* Note: each of next 3 "repeated" structures might be repeated any + (0, 1, 2...) times - we only support 1 and 0 */ + + /* Repeated E-UTRAN Neighbour Cells */ + bitvec_set_bit(bv, 1); + + /* Note: we don't support different EARFCN arrays each with different + priority, threshold etc. */ + append_eutran_neib_cell(bv, e); + + /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */ + bitvec_set_bit(bv, 0); + + /* Note: following 2 repeated structs are not supported ATM */ + /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */ + bitvec_set_bit(bv, 0); + /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */ + bitvec_set_bit(bv, 0); + + /* Priority and E-UTRAN Parameters Description ends here */ + /* No 3G CSG Description */ + bitvec_set_bit(bv, 0); + /* No E-UTRAN CSG Description */ + bitvec_set_bit(bv, 0); + /* No Additions in Rel-9: */ + bitvec_set_bit(bv, L); +} + +/* generate SI2quater rest octets: 3GPP TS 44.018 ? 10.5.2.33b */ +int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, + bool uarfcn, bool earfcn) +{ + int rc; + struct bitvec bv; + bv.data = data; + bv.data_len = 20; + bitvec_zero(&bv); + + /* BA_IND */ + bitvec_set_bit(&bv, 1); + /* 3G_BA_IND */ + bitvec_set_bit(&bv, 1); + /* MP_CHANGE_MARK */ + bitvec_set_bit(&bv, 0); + + /* we do not support multiple si2quater messages at the moment: */ + /* SI2quater_INDEX */ + bitvec_set_uint(&bv, 0, 4); + /* SI2quater_COUNT */ + bitvec_set_uint(&bv, 0, 4); + + /* No Measurement_Parameters Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_Real Time Difference Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_BSIC Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_REPORT PRIORITY Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_MEASUREMENT_Parameters Description */ + bitvec_set_bit(&bv, 0); + /* No NC Measurement Parameters */ + bitvec_set_bit(&bv, 0); + /* No extension (length) */ + bitvec_set_bit(&bv, 0); + + if (uarfcn) { + + } else { /* No 3G Neighbour Cell Description */ + bitvec_set_bit(&bv, 0); + } + + /* No 3G Measurement Parameters Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_3G_MEASUREMENT Parameters Descr. */ + bitvec_set_bit(&bv, 0); + + if (earfcn) { + rc = append_earfcn_size(e); + if (rc < 0) + return rc; + if (rc + bv.cur_bit > SI2Q_MAX_LEN) + return -ENOMEM; + append_earfcn(&bv, e); + } else { + /* No Additions in Rel-5: */ + bitvec_set_bit(&bv, L); + } + + bitvec_spare_padding(&bv, (bv.data_len * 8) - 1); + return bv.data_len; +} + /* Append selection parameters to bitvec */ static void append_selection_params(struct bitvec *bv, const struct gsm48_si_selection_params *sp) diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 5490c83..43a492a 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -494,6 +494,28 @@ static int generate_si2ter(uint8_t *output, struct gsm_bts *bts) return sizeof(*si2t); } +static int generate_si2quater(uint8_t *output, struct gsm_bts *bts) +{ + int rc; + struct gsm48_system_information_type_2quater *si2q = + (struct gsm48_system_information_type_2quater *) output; + + memset(si2q, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN); + + si2q->header.l2_plen = GSM48_LEN2PLEN(22); + si2q->header.rr_protocol_discriminator = GSM48_PDISC_RR; + si2q->header.skip_indicator = 0; + si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater; + + rc = rest_octets_si2quater(si2q->rest_octets, + &bts->si_common.si2quater_neigh_list, false, + true); + if (rc < 0) + return rc; + + return sizeof(*si2q) + rc; +} + static struct gsm48_si_ro_info si_info = { .selection_params = { .present = 0, @@ -831,6 +853,7 @@ static const gen_si_fn_t gen_si_fn[_MAX_SYSINFO_TYPE] = { [SYSINFO_TYPE_2] = &generate_si2, [SYSINFO_TYPE_2bis] = &generate_si2bis, [SYSINFO_TYPE_2ter] = &generate_si2ter, + [SYSINFO_TYPE_2quater] = &generate_si2quater, [SYSINFO_TYPE_3] = &generate_si3, [SYSINFO_TYPE_4] = &generate_si4, [SYSINFO_TYPE_5] = &generate_si5, diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index 16035ed..242c014 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -315,6 +315,11 @@ struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_typ bts->neigh_list_manual_mode = 0; bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */ bts->si_common.cell_sel_par.rxlev_acc_min = 0; + bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list; + bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list; + bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST; + bts->si_common.si2quater_neigh_list.thresh_hi = 0; + osmo_earfcn_init(&bts->si_common.si2quater_neigh_list); bts->si_common.neigh_list.data = bts->si_common.data.neigh_list; bts->si_common.neigh_list.data_len = sizeof(bts->si_common.data.neigh_list); diff --git a/openbsc/tests/gsm0408/Makefile.am b/openbsc/tests/gsm0408/Makefile.am index 1c29ece..ee04102 100644 --- a/openbsc/tests/gsm0408/Makefile.am +++ b/openbsc/tests/gsm0408/Makefile.am @@ -7,6 +7,7 @@ EXTRA_DIST = gsm0408_test.ok gsm0408_test_SOURCES = gsm0408_test.c gsm0408_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libmsc/libmsc.a \ + $(top_builddir)/src/libtrau/libtrau.a \ $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libcommon/libcommon.a \ - $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -ldbi + $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOABIS_LIBS) -ldbi diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 781ef61..d6abce6 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -29,7 +29,11 @@ #include #include #include +#include +#include + #include +#include #define COMPARE(result, op, value) \ if (!((result) op (value))) {\ @@ -79,6 +83,70 @@ static void test_location_area_identifier(void) COMPARE(lai48.lac, ==, htons(0x000f)); } +static inline void add_arfcn_b(struct osmo_earfcn_si2q *e, uint16_t earfcn, + uint8_t bw) +{ + int r = osmo_earfcn_add(e, earfcn, bw); + if (r) + printf("failed to add EARFCN %u: %s\n", earfcn, strerror(r)); + else + printf("added EARFCN %u - ", earfcn); +} + +static inline void gen(struct gsm_bts *bts) +{ + int r = gsm_generate_si(bts, SYSINFO_TYPE_2quater); + if (r > 0) + printf("generated SI2quater: [%d] %s\n", r, + osmo_hexdump(bts->si_buf[SYSINFO_TYPE_2quater], r)); + else + printf("failed to generate SI2quater: %s\n", strerror(-r)); +} + +static inline void test_si2q(void) +{ + struct gsm_bts *bts; + struct gsm_network *network = gsm_network_init(1, 1, NULL); + printf("Testing SYSINFO_TYPE_2quater generation:\n"); + + if (!network) + exit(1); + bts = gsm_bts_alloc(network); + + bts->si_common.si2quater_neigh_list.arfcn = + bts->si_common.data.earfcn_list; + bts->si_common.si2quater_neigh_list.meas_bw = + bts->si_common.data.meas_bw_list; + bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST; + bts->si_common.si2quater_neigh_list.thresh_hi = 5; + + osmo_earfcn_init(&bts->si_common.si2quater_neigh_list); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1917, 1); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1932, + OSMO_EARFCN_MEAS_INVALID); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1937, 2); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1945, + OSMO_EARFCN_MEAS_INVALID); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1965, + OSMO_EARFCN_MEAS_INVALID); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1967, 4); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1982, 3); + gen(bts); +} + static void test_mi_functionality(void) { const char *imsi_odd = "987654321098763"; @@ -486,6 +554,7 @@ int main(int argc, char **argv) test_range_encoding(); test_gsm411_rp_ref_wrap(); + test_si2q(); printf("Done.\n"); return EXIT_SUCCESS; } diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 058563a..59319bf 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -62,4 +62,12 @@ testing RP-Reference wrap Allocated reference: 255 Allocated reference: 0 Allocated reference: 1 +Testing SYSINFO_TYPE_2quater generation: +added EARFCN 1917 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be c8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +added EARFCN 1932 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 30 14 03 2b 2b 2b 2b 2b 2b 2b 2b +added EARFCN 1937 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a0 a0 2b 2b 2b 2b 2b 2b +added EARFCN 1945 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c c8 28 0b 2b 2b 2b +added EARFCN 1965 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b +added EARFCN 1967 - failed to generate SI2quater: Cannot allocate memory +added EARFCN 1982 - failed to generate SI2quater: Cannot allocate memory Done. -- 2.8.1 From msuraev at sysmocom.de Fri Apr 15 16:16:14 2016 From: msuraev at sysmocom.de (Max) Date: Fri, 15 Apr 2016 18:16:14 +0200 Subject: range arfcn encoding Message-ID: <571113CE.8020004@sysmocom.de> Hi. How to properly use range_enc_arfcns() and range_enc_range*() from arfcn_range_decode.h? There're not many comments around the code. From function signature it seems like range_enc_arfcns() will put results into w parameter but in system_information.c after that there's also call to one of range_enc_range*(). I've tried to feed output to wireshark but it decode some unexpected stuff. So, if I have a sequence of ints which I'd like to run through range512 for example - ho do I get the output? -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From holger at freyther.de Fri Apr 15 17:36:25 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 15 Apr 2016 13:36:25 -0400 Subject: range arfcn encoding In-Reply-To: <571113CE.8020004@sysmocom.de> References: <571113CE.8020004@sysmocom.de> Message-ID: <29832FAA-DC3E-4B89-A9F4-274EC8799D31@freyther.de> > On 15 Apr 2016, at 12:16, Max wrote: > > Hi. > > How to properly use range_enc_arfcns() and range_enc_range*() from > arfcn_range_decode.h? There're not many comments around the code. From > function signature it seems like range_enc_arfcns() will put results > into w parameter but in system_information.c after that there's also > call to one of range_enc_range*(). > > I've tried to feed output to wireshark but it decode some unexpected > stuff. So, if I have a sequence of ints which I'd like to run through > range512 for example - ho do I get the output? 1st Determine which range to use 2nd filter out ARFCNs, e.g. if ARFCN 0 is included in the set or not 3rd encode according to the range does this already help? range = range_enc_determine_range(arfcns, arfcns_used, &f0); if (range == ARFCN_RANGE_INVALID) return -2; /* * Manipulate the ARFCN list according to the rules in J4 depending * on the selected range. */ arfcns_used = range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included); memset(w, 0, sizeof(w)); rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0); if (rc != 0) ... switch (range) { case ARFCN_RANGE_128: return range_enc_range128(chan_list, f0, w); break; case ARFCN_RANGE_256: From nhofmeyr at sysmocom.de Fri Apr 15 19:52:42 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 15 Apr 2016 21:52:42 +0200 Subject: [PATCH] compiler warning: unconstify arg passed to OCTET_STRING_noalloc() In-Reply-To: <20160414145711.GB2515@dub6> References: <1460638140-20008-1-git-send-email-nhofmeyr@sysmocom.de> <130058CD-4474-4EC5-AD77-68BEF9521C85@freyther.de> <20160414145711.GB2515@dub6> Message-ID: <20160415195242.GA13168@dub6> On Thu, Apr 14, 2016 at 04:57:11PM +0200, Neels Hofmeyr wrote: > So, I want to change this: > > static inline void OCTET_STRING_noalloc(OCTET_STRING_t *s, const uint8_t *str, int size) > { > s->buf = str; > s->size = size; > } > > because OCTET_STRING_t.s is not const, and must not be const, will never be const. I meant OCTET_STRING_t.buf, of course. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Fri Apr 15 21:01:04 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 15 Apr 2016 23:01:04 +0200 Subject: [PATCH 0/4] take care of some coverity warnings In-Reply-To: References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20160415210104.GD13168@dub6> On Thu, Apr 14, 2016 at 09:37:52AM -0400, Holger Freyther wrote: > > > On 14 Apr 2016, at 09:21, Neels Hofmeyr wrote: > > > > Fixing a few NULL dereference warnings found by the Iu coverity check. > > They are not related apart from that. > > I just looked at the gprs_gmm patch and stopped reading. Your commit message should at least have some of the context of coverity. > > So when is llme NULL? Is it allowed to be NULL? Does it make sense? We don't want to blindly do these things but understand the code around and see if the tool is right or wrong. And if we disagree maybe change the flow of code or add an assert. Spot on, I don't actually understand the llme one. All I know is that the calling function gsm0408_rcv_gmm() has a condition "if (llme..." up at the top. Let's drop that one unless someone else has the time to look at it. The others I do understand though. Do read on ;) ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Fri Apr 15 21:59:11 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 15 Apr 2016 23:59:11 +0200 Subject: [PATCH 0/4] take care of some coverity warnings In-Reply-To: <20160415210104.GD13168@dub6> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> <20160415210104.GD13168@dub6> Message-ID: <20160415215911.GA24964@dub6> On Fri, Apr 15, 2016 at 11:01:04PM +0200, Neels Hofmeyr wrote: > On Thu, Apr 14, 2016 at 09:37:52AM -0400, Holger Freyther wrote: > > > > > On 14 Apr 2016, at 09:21, Neels Hofmeyr wrote: > > > > > > Fixing a few NULL dereference warnings found by the Iu coverity check. > > > They are not related apart from that. > > > > I just looked at the gprs_gmm patch and stopped reading. Your commit message should at least have some of the context of coverity. > > > > So when is llme NULL? Is it allowed to be NULL? Does it make sense? We don't want to blindly do these things but understand the code around and see if the tool is right or wrong. And if we disagree maybe change the flow of code or add an assert. > > Spot on, I don't actually understand the llme one. All I know is that the > calling function gsm0408_rcv_gmm() has a condition "if (llme..." up at the top. > Let's drop that one unless someone else has the time to look at it. I just noticed that on the Iu branch and for Iu connections, llme is explicitly passed as NULL, so my patch would break things for Iu. Good thing you spotted that it's fishy. The patch should probably be [[[ diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c index f510e64..f8d75d5 100644 --- a/openbsc/src/gprs/gprs_gmm.c +++ b/openbsc/src/gprs/gprs_gmm.c @@ -1185,7 +1185,7 @@ rejected: rc = gsm48_tx_gmm_att_rej_oldmsg(msg, reject_cause); if (ctx) mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJ"); - else + else if (llme) /* TLLI unassignment */ gprs_llgmm_assign(llme, llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL); ]]] and I would appreciate if someone else could verify that. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Fri Apr 15 19:49:55 2016 From: laforge at gnumonks.org (Harald Welte) Date: Fri, 15 Apr 2016 21:49:55 +0200 Subject: [PATCH] compiler warning: pointer type in OCTET_STRING_noalloc() In-Reply-To: <1460637956-19900-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460637956-19900-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20160415194955.GC1832@nataraja> Hi Neels, On Thu, Apr 14, 2016 at 02:45:56PM +0200, Neels Hofmeyr wrote: > It's useless to declare the str arg as const when all the function does is > assign it to a non-const pointer. The point of doing it this way is that we don't have to write our code in a sub-standard way, just because asn1c is written in a way that you cannot have 'const' buffers as input into encoding. So 'const' here is used as a hint to the programmer, that a read-only string is passed into this function, and hence it is input data. So this was very intentional. Now you can argue that my line of thinking above is basically ignoring the reality of asn1c. But then, don't we have actual real issues to address, than to debate about thing slike this? Sorry... -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Fri Apr 15 19:52:01 2016 From: laforge at gnumonks.org (Harald Welte) Date: Fri, 15 Apr 2016 21:52:01 +0200 Subject: [PATCH] compiler warning: unconstify arg passed to OCTET_STRING_noalloc() In-Reply-To: <20160414145711.GB2515@dub6> References: <1460638140-20008-1-git-send-email-nhofmeyr@sysmocom.de> <130058CD-4474-4EC5-AD77-68BEF9521C85@freyther.de> <20160414145711.GB2515@dub6> Message-ID: <20160415195201.GD1832@nataraja> On Thu, Apr 14, 2016 at 04:57:11PM +0200, Neels Hofmeyr wrote: > All callers of OCTET_STRING_noalloc() pass a non-const pointer, except > that one above. I just want to unconst that single caller. I think the other callers should be fixed, rather than aligning the one correct part of the code. As indicated, I believe we shouldn't let bad impleentation or API design by asn1c contaminate our code. A pointer to input data into an encoding function should be const. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sat Apr 16 11:34:10 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 16 Apr 2016 13:34:10 +0200 Subject: [PATCH 0/4] take care of some coverity warnings In-Reply-To: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20160416113410.GJ31766@nataraja> On Thu, Apr 14, 2016 at 03:21:29PM +0200, Neels Hofmeyr wrote: > Fixing a few NULL dereference warnings found by the Iu coverity check. > They are not related apart from that. > > Neels Hofmeyr (4): > gprs_gmm: ensure llme present upon Attach Req (CID #57686) I think there was some discussion about whether llme could ever be NULL in this case anyway? > gtphub_unmap_header_tei(): don't dereference unmapped_tei arg if not > present (CID #57687) > bsc_nat: forward_sccp_to_msc(): assert con presence (CID #57872) > gbproxy_test: assert msg allocation (CID #57873) all three above have been merged now. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sat Apr 16 11:29:57 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 16 Apr 2016 13:29:57 +0200 Subject: [PATCH] sua_test_common.c: use global RANAP SSN definition In-Reply-To: <1460563282-23900-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460563282-23900-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20160416112957.GH31766@nataraja> On Wed, Apr 13, 2016 at 06:01:22PM +0200, Neels Hofmeyr wrote: > The test 'hardcoded' a local define for RANAP SSN as 142, instead use the > proper OSMO_SCCP_SSN_RANAP define from sccp_sap.h thanks, applied. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sat Apr 16 11:29:06 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 16 Apr 2016 13:29:06 +0200 Subject: [PATCH] Fix RANAP SSN: it's 142, not 143 In-Reply-To: <1460562325-21728-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460562325-21728-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20160416112906.GG31766@nataraja> On Wed, Apr 13, 2016 at 05:45:25PM +0200, Neels Hofmeyr wrote: > 143 is actually the SSN for RNSAP. thanks, fixed. Also added some more SSN definitions as my own patch on top. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sat Apr 16 11:31:35 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 16 Apr 2016 13:31:35 +0200 Subject: [PATCH] logging.c: assert category_token allocation (CID #57871) In-Reply-To: <1460639536-21611-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460639536-21611-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20160416113135.GI31766@nataraja> Thanks, merged. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sat Apr 16 11:37:41 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 16 Apr 2016 13:37:41 +0200 Subject: [PATCH] queue_new(): if calloc fails, abort (CID #57918) In-Reply-To: <1460644722-22972-1-git-send-email-nhofmeyr@sysmocom.de> References: <1460644722-22972-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20160416113741.GK31766@nataraja> Hi Neels On Thu, Apr 14, 2016 at 04:38:42PM +0200, Neels Hofmeyr wrote: > Coverity complains about a 'Dereference before null check' on *queue. > So, push the NULL check further up, No question here. > but also, instead of handling a calloc failure as error, rather abort > the program. I think that's a much more fundamental question. Should we really abort the program in this case? If so, why only in case of queue allocation failures, but not in general at all memory allocation failures? And if that's the case, wrapping calloc() / malloc() and other dynamic memory allocation calls with a function that contains the abort() (or an OSMO_ASSERT() on the result) might be more applicable? -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sat Apr 16 11:42:19 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 16 Apr 2016 13:42:19 +0200 Subject: [PATCH] Add function to get osmo_earfcn bit size In-Reply-To: <1460729044-8855-1-git-send-email-msuraev@sysmocom.de> References: <1460729044-8855-1-git-send-email-msuraev@sysmocom.de> Message-ID: <20160416114219.GL31766@nataraja> On Fri, Apr 15, 2016 at 04:04:04PM +0200, msuraev at sysmocom.de wrote: > This function returns the number of bits necessary to pack osmo_earfcn > into Repeated E-UTRAN Neighbour Cells IE (3GPP TS 44.018 Table > 10.5.2.33b.1). Thanks, applied. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From k at rhizomatica.org Fri Apr 15 13:05:29 2016 From: k at rhizomatica.org (=?UTF-8?Q?'kino_m=c3=a1s?=) Date: Fri, 15 Apr 2016 14:05:29 +0100 Subject: Lack of maintenance for osmo-bts-trx In-Reply-To: <20160404151058.GN27299@nataraja> References: <20160404151058.GN27299@nataraja> Message-ID: <5710E719.3010602@rhizomatica.org> On 04/04/2016 16:10, Harald Welte wrote: > Dear all, > > I am growing incredibly frustrated at the fact that osmo-bts-trx is > effectively unmaintained, despite the fact that there are plenty of > users as well as even commercial users / companies (particularly > Fairwaves). Hi all, I also am interested in this topic, as a user of Osmo* with a USRP SDR, which is what I have right now at home for doing tests involving an MS. Also because I assume that diversity in hardware cannot be a bad thing for the community GSM projects that are happening, ours included. I'm not a programmer and would not expect to be submitting patches at this level, but I can help with testing and going forward, hopefully contributing in other ways. More than anything I just wanted to add another voice to the support for getting Harald's concerns sorted out, and having a working master branch to support SDR hardware including such as BladeRF, or more economically accessable options that may become available in the future. Keith. From laforge at gnumonks.org Sat Apr 16 16:18:48 2016 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 16 Apr 2016 18:18:48 +0200 Subject: Guidelines for bug reports (was Re: Lack of maintenance for osmo-bts-trx) In-Reply-To: References: <20160406075911.GI11135@nataraja> Message-ID: <20160416161848.GU31766@nataraja> Hi Tom, On Wed, Apr 06, 2016 at 10:34:45AM -0700, Tom Tsou wrote: > I think wiki guidelines on bug reporting would be quite valuable. The > range of users for Osmocom and OpenBTS is extremely wide - especially > with the latter. For many users and potential users, reporting bugs in > the manner suggested above is far from obvious. I have started to put together something at http://projects.osmocom.org/projects/cellular-infrastructure/wiki/ReportingBugs which should cover the main points. It could be slightly expanded on an example tcpdump statement with default capture filter, but especially in terms of logging configuration it is not possible to give a "one size fits all" recommendation. What do you think? The page is not yet linked from other wiki pages, I plan to do that once we make some more progress. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From holger at freyther.de Sat Apr 16 20:09:05 2016 From: holger at freyther.de (Holger Freyther) Date: Sat, 16 Apr 2016 16:09:05 -0400 Subject: [PATCH 3/3] Add basic SI2quater support In-Reply-To: <1460729086-8961-3-git-send-email-msuraev@sysmocom.de> References: <1460729086-8961-1-git-send-email-msuraev@sysmocom.de> <1460729086-8961-3-git-send-email-msuraev@sysmocom.de> Message-ID: > On 15 Apr 2016, at 10:04, msuraev at sysmocom.de wrote: > > + install_element(BTS_NODE, &cfg_bts_si2quater_neigh_add_cmd); > + install_element(BTS_NODE, &cfg_bts_si2quater_neigh_del_cmd); Documentation error (missing docs): please fix. From msuraev at sysmocom.de Mon Apr 18 08:32:16 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 18 Apr 2016 10:32:16 +0200 Subject: [PATCH] Fix earfcn deletion Message-ID: <1460968336-23741-1-git-send-email-msuraev@sysmocom.de> From: Max * fix documentation for command parameters * fix typo in arg index * fix sign in error reporting --- openbsc/src/libbsc/bsc_vty.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 9634508..85b8394 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2797,15 +2797,16 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" - "EARFCN of neighbor\n") + "EARFCN of neighbor\n" + "EARFCN\n") { struct gsm_bts *bts = vty->index; struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; - uint16_t arfcn = atoi(argv[1]); + uint16_t arfcn = atoi(argv[0]); int r = osmo_earfcn_del(e, arfcn); if (r < 0) { vty_out(vty, "Unable to delete arfcn %u: %s%s", arfcn, - strerror(r), VTY_NEWLINE); + strerror(-r), VTY_NEWLINE); return CMD_WARNING; } -- 2.8.1 From kluchnikovi at gmail.com Mon Apr 18 08:31:41 2016 From: kluchnikovi at gmail.com (Ivan Kluchnikov) Date: Mon, 18 Apr 2016 11:31:41 +0300 Subject: [PATCH] Add support of virtual networks for sending network name to ms depending on imsi Message-ID: <1460968301-8162-1-git-send-email-kluchnikovi@gmail.com> Before sending mm info message to ms: - try to find virtual network with the imsi prefix which matches subscriber's imsi - if virtual network was found, use long and short network names of this virtual network for subscriber - if virtual network was not found, use long and short network names of main network for subscriber --- openbsc/include/openbsc/gsm_data.h | 16 +++++ openbsc/include/openbsc/vty.h | 2 + openbsc/src/libbsc/bsc_vty.c | 138 +++++++++++++++++++++++++++++++++++++ openbsc/src/libbsc/net_init.c | 1 + openbsc/src/libcommon/common_vty.c | 19 +++++ openbsc/src/libcommon/gsm_data.c | 41 +++++++++++ openbsc/src/libmsc/gsm_04_08.c | 42 ++++++++--- openbsc/src/libmsc/smpp_vty.c | 10 --- openbsc/tests/vty_test_runner.py | 40 +++++++++++ 9 files changed, 291 insertions(+), 18 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 6d7aba3..b3e9603 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -248,6 +248,9 @@ struct gsm_network { unsigned int num_bts; struct llist_head bts_list; + unsigned int num_virt_net; + struct llist_head virt_net_list; + /* timer values */ int T3101; int T3103; @@ -293,6 +296,16 @@ struct gsm_network { struct ctrl_handle *ctrl; }; +#define IMSI_PREFIX_LENGTH 16 +struct gsm_virt_network { + struct llist_head list; + uint8_t nr; + struct gsm_network *network; + char imsi_prefix[IMSI_PREFIX_LENGTH]; + char *name_long; + char *name_short; +}; + struct osmo_esme; enum gsm_sms_source_id { @@ -435,6 +448,9 @@ int gsm_bts_model_register(struct gsm_bts_model *model); struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan); void subscr_con_free(struct gsm_subscriber_connection *conn); +struct gsm_virt_network *gsm_virt_net_alloc_register(struct gsm_network *net); +struct gsm_virt_network *gsm_virt_net_num(struct gsm_network *net, int num); + struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_type type, uint8_t bsic); diff --git a/openbsc/include/openbsc/vty.h b/openbsc/include/openbsc/vty.h index bc30e23..711f82a 100644 --- a/openbsc/include/openbsc/vty.h +++ b/openbsc/include/openbsc/vty.h @@ -17,6 +17,7 @@ extern struct cmd_element cfg_no_description_cmd; enum bsc_vty_node { GSMNET_NODE = _LAST_OSMOVTY_NODE + 1, + VIRT_NET_NODE, BTS_NODE, TRX_NODE, TS_NODE, @@ -41,6 +42,7 @@ 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); +extern int osmo_is_digits(const char *str); struct log_info; int bsc_vty_init(const struct log_info *cat); diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 29f2501..6ca5048 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -112,6 +112,12 @@ struct cmd_node net_node = { 1, }; +struct cmd_node virt_net_node = { + VIRT_NET_NODE, + "%s(config-net-virt)# ", + 1, +}; + struct cmd_node bts_node = { BTS_NODE, "%s(config-net-bts)# ", @@ -343,6 +349,41 @@ DEFUN(show_bts, show_bts_cmd, "show bts [<0-255>]", return CMD_SUCCESS; } +static void virt_net_dump_vty(struct vty *vty, struct gsm_virt_network *virt_net) +{ + vty_out(vty, "Virtual network %u%s", virt_net->nr, VTY_NEWLINE); + vty_out(vty, " imsi-prefix %s%s", virt_net->imsi_prefix, VTY_NEWLINE); + vty_out(vty, " Long network name: '%s'%s", + virt_net->name_long, VTY_NEWLINE); + vty_out(vty, " Short network name: '%s'%s", + virt_net->name_short, VTY_NEWLINE); +} + +DEFUN(show_virt_net, show_virt_net_cmd, "show virtual-network [<0-255>]", + SHOW_STR "Display information about a virtual network\n" + "Virtual network number") +{ + struct gsm_network *net = gsmnet_from_vty(vty); + int virt_net_nr; + + if (argc != 0) { + /* use the virtual network number that the user has specified */ + virt_net_nr = atoi(argv[0]); + if (virt_net_nr >= net->num_virt_net) { + vty_out(vty, "%% can't find virtual network '%s'%s", argv[0], + VTY_NEWLINE); + return CMD_WARNING; + } + virt_net_dump_vty(vty, gsm_virt_net_num(net, virt_net_nr)); + return CMD_SUCCESS; + } + /* print all virtual networks */ + for (virt_net_nr = 0; virt_net_nr < net->num_virt_net; virt_net_nr++) + virt_net_dump_vty(vty, gsm_virt_net_num(net, virt_net_nr)); + + return CMD_SUCCESS; +} + /* utility functions */ static void parse_e1_link(struct gsm_e1_subslot *e1_link, const char *line, const char *ts, const char *ss) @@ -743,6 +784,25 @@ static int config_write_bts(struct vty *v) return CMD_SUCCESS; } +static void config_write_virt_net_single(struct vty *vty, struct gsm_virt_network *virt_net) +{ + vty_out(vty, " virtual-network %u%s", virt_net->nr, VTY_NEWLINE); + vty_out(vty, " imsi-prefix %s%s", virt_net->imsi_prefix, VTY_NEWLINE); + vty_out(vty, " short name %s%s", virt_net->name_short, VTY_NEWLINE); + vty_out(vty, " long name %s%s", virt_net->name_long, VTY_NEWLINE); +} + +static int config_write_virt_net(struct vty *v) +{ + struct gsm_network *gsmnet = gsmnet_from_vty(v); + struct gsm_virt_network *virt_net; + + llist_for_each_entry(virt_net, &gsmnet->virt_net_list, list) + config_write_virt_net_single(v, virt_net); + + return CMD_SUCCESS; +} + static int config_write_net(struct vty *vty) { struct gsm_network *gsmnet = gsmnet_from_vty(vty); @@ -1612,6 +1672,76 @@ DEFUN(cfg_net_subscr_keep, return CMD_SUCCESS; } +DEFUN(cfg_virt_net, + cfg_virt_net_cmd, + "virtual-network <0-255>", + "Select a virtual network to configure\n" + "Virtual-network Number\n") +{ + struct gsm_network *gsmnet = gsmnet_from_vty(vty); + int virt_net_nr = atoi(argv[0]); + struct gsm_virt_network *virt_net; + + if (virt_net_nr > gsmnet->num_virt_net) { + vty_out(vty, "%% The next unused Virtual-network number is %u%s", + gsmnet->num_virt_net, VTY_NEWLINE); + return CMD_WARNING; + } else if (virt_net_nr == gsmnet->num_virt_net) { + /* allocate a new one */ + virt_net = gsm_virt_net_alloc_register(gsmnet); + } else + virt_net = gsm_virt_net_num(gsmnet, virt_net_nr); + + if (!virt_net) { + vty_out(vty, "%% Unable to allocate Virtual-network %u%s", + gsmnet->num_virt_net, VTY_NEWLINE); + return CMD_WARNING; + } + + vty->index = virt_net; + vty->index_sub = NULL; + vty->node = VIRT_NET_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_virt_net_imsi_prefix, + cfg_virt_net_imsi_prefix_cmd, + "imsi-prefix PREFIX", + "Set the IMSI prefix\n" + "prefix\n") +{ + struct gsm_virt_network *virt_net = vty->index; + if (!osmo_is_digits(argv[0])) { + vty_out(vty, "%% PREFIX has to be numeric%s", VTY_NEWLINE); + return CMD_WARNING; + } + snprintf(virt_net->imsi_prefix, sizeof(virt_net->imsi_prefix), "%s", argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_virt_net_name_short, + cfg_virt_net_name_short_cmd, + "short name NAME", + "Set the short GSM network name\n" NAME_CMD_STR NAME_STR) +{ + struct gsm_virt_network *virt_net = vty->index; + + bsc_replace_string(virt_net->network, &virt_net->name_short, argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_virt_net_name_long, + cfg_virt_net_name_long_cmd, + "long name NAME", + "Set the long GSM network name\n" NAME_CMD_STR NAME_STR) +{ + struct gsm_virt_network *virt_net = vty->index; + + bsc_replace_string(virt_net->network, &virt_net->name_long, argv[0]); + return CMD_SUCCESS; +} + /* per-BTS configuration */ DEFUN(cfg_bts, cfg_bts_cmd, @@ -3763,6 +3893,7 @@ int bsc_vty_init(const struct log_info *cat) install_element_ve(&show_net_cmd); + install_element_ve(&show_virt_net_cmd); install_element_ve(&show_bts_cmd); install_element_ve(&show_trx_cmd); install_element_ve(&show_ts_cmd); @@ -3811,6 +3942,13 @@ int bsc_vty_init(const struct log_info *cat) install_element(GSMNET_NODE, &cfg_net_subscr_keep_cmd); install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd); + install_element(GSMNET_NODE, &cfg_virt_net_cmd); + install_node(&virt_net_node, config_write_virt_net); + vty_install_default(VIRT_NET_NODE); + install_element(VIRT_NET_NODE, &cfg_virt_net_imsi_prefix_cmd); + install_element(VIRT_NET_NODE, &cfg_virt_net_name_short_cmd); + install_element(VIRT_NET_NODE, &cfg_virt_net_name_long_cmd); + install_element(GSMNET_NODE, &cfg_bts_cmd); install_node(&bts_node, config_write_bts); vty_install_default(BTS_NODE); diff --git a/openbsc/src/libbsc/net_init.c b/openbsc/src/libbsc/net_init.c index 568a0b8..1fe9f3e 100644 --- a/openbsc/src/libbsc/net_init.c +++ b/openbsc/src/libbsc/net_init.c @@ -71,6 +71,7 @@ struct gsm_network *gsm_network_init(uint16_t country_code, uint16_t network_cod INIT_LLIST_HEAD(&net->trans_list); INIT_LLIST_HEAD(&net->upqueue); INIT_LLIST_HEAD(&net->bts_list); + INIT_LLIST_HEAD(&net->virt_net_list); net->stats.chreq.total = osmo_counter_alloc("net.chreq.total"); net->stats.chreq.no_channel = osmo_counter_alloc("net.chreq.no_channel"); diff --git a/openbsc/src/libcommon/common_vty.c b/openbsc/src/libcommon/common_vty.c index a0674f0..66a82d8 100644 --- a/openbsc/src/libcommon/common_vty.c +++ b/openbsc/src/libcommon/common_vty.c @@ -42,6 +42,15 @@ int bsc_vty_go_parent(struct vty *vty) vty->node = CONFIG_NODE; vty->index = NULL; break; + case VIRT_NET_NODE: + vty->node = GSMNET_NODE; + { + /* set vty->index correctly ! */ + struct gsm_virt_network *virt_net = vty->index; + vty->index = virt_net->network; + vty->index_sub = NULL; + } + break; case BTS_NODE: vty->node = GSMNET_NODE; { @@ -141,3 +150,13 @@ void bsc_replace_string(void *ctx, char **dst, const char *newstr) talloc_free(*dst); *dst = talloc_strdup(ctx, newstr); } + +int osmo_is_digits(const char *str) +{ + int i; + for (i = 0; i < strlen(str); i++) { + if (!isdigit(str[i])) + return 0; + } + return 1; +} diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index 16035ed..6b33b18 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -192,6 +192,47 @@ const char *rrlp_mode_name(enum rrlp_mode mode) return get_value_string(rrlp_mode_names, mode); } +struct gsm_virt_network *gsm_virt_net_alloc(void *ctx) +{ + struct gsm_virt_network *virt_net = talloc_zero(ctx, struct gsm_virt_network); + if (!virt_net) + return NULL; + return virt_net; +} + +struct gsm_virt_network *gsm_virt_net_alloc_register(struct gsm_network *net) +{ + struct gsm_virt_network *virt_net; + + virt_net = gsm_virt_net_alloc(net); + if (!virt_net) + return NULL; + + virt_net->nr = net->num_virt_net++; + virt_net->network = net; + strcpy(virt_net->imsi_prefix, "00101"); + virt_net->name_short = talloc_strdup(net, "OpenBSC"); + virt_net->name_long = talloc_strdup(net, "OpenBSC"); + + llist_add_tail(&virt_net->list, &net->virt_net_list); + return virt_net; +} + +struct gsm_virt_network *gsm_virt_net_num(struct gsm_network *net, int num) +{ + struct gsm_virt_network *virt_net; + + if (num >= net->num_virt_net) + return NULL; + + llist_for_each_entry(virt_net, &net->virt_net_list, list) { + if (virt_net->nr == num) + return virt_net; + } + + return NULL; +} + static const struct value_string bts_gprs_mode_names[] = { { BTS_GPRS_NONE, "none" }, { BTS_GPRS_GPRS, "gprs" }, diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 1524ec4..cdfcb2d 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -702,6 +702,16 @@ static uint8_t bcdify(uint8_t value) return ret; } +int is_prefix_match_imsi(char *imsi_prefix, char *imsi) +{ + size_t prefix_len = strlen(imsi_prefix); + size_t imsi_len = strlen(imsi); + if ((prefix_len <= imsi_len) && + (strncmp(imsi, imsi_prefix, prefix_len) == 0)) { + return 1; + } + return 0; +} /* Section 9.2.15a */ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) @@ -719,13 +729,29 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) int tzunits; int dst = 0; + char *name_long = net->name_long; + char *name_short = net->name_short; + int virt_net_nr; + msg->lchan = conn->lchan; gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); gh->proto_discr = GSM48_PDISC_MM; gh->msg_type = GSM48_MT_MM_INFO; - if (net->name_long) { + if (net->num_virt_net) { + for (virt_net_nr = 0; virt_net_nr < net->num_virt_net; virt_net_nr++) { + struct gsm_virt_network* virt_net = gsm_virt_net_num(net, virt_net_nr); + if (virt_net && + is_prefix_match_imsi(virt_net->imsi_prefix, conn->subscr->imsi)) { + name_long = virt_net->name_long; + name_short = virt_net->name_short; + break; + } + } + } + + if (name_long) { #if 0 name_len = strlen(net->name_long); /* 10.5.3.5a */ @@ -741,8 +767,8 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) /* FIXME: Use Cell Broadcast, not UCS-2, since * UCS-2 is only supported by later revisions of the spec */ #endif - name_len = (strlen(net->name_long)*7)/8; - name_pad = (8 - strlen(net->name_long)*7)%8; + name_len = (strlen(name_long)*7)/8; + name_pad = (8 - strlen(name_long)*7)%8; if (name_pad > 0) name_len++; /* 10.5.3.5a */ @@ -752,11 +778,11 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */ ptr8 = msgb_put(msg, name_len); - gsm_7bit_encode_n(ptr8, name_len, net->name_long, NULL); + gsm_7bit_encode_n(ptr8, name_len, name_long, NULL); } - if (net->name_short) { + if (name_short) { #if 0 name_len = strlen(net->name_short); /* 10.5.3.5a */ @@ -769,8 +795,8 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) for (i = 0; i < name_len; i++) ptr16[i] = htons(net->name_short[i]); #endif - name_len = (strlen(net->name_short)*7)/8; - name_pad = (8 - strlen(net->name_short)*7)%8; + name_len = (strlen(name_short)*7)/8; + name_pad = (8 - strlen(name_short)*7)%8; if (name_pad > 0) name_len++; /* 10.5.3.5a */ @@ -780,7 +806,7 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */ ptr8 = msgb_put(msg, name_len); - gsm_7bit_encode_n(ptr8, name_len, net->name_short, NULL); + gsm_7bit_encode_n(ptr8, name_len, name_short, NULL); } diff --git a/openbsc/src/libmsc/smpp_vty.c b/openbsc/src/libmsc/smpp_vty.c index 351e8be..72b816f 100644 --- a/openbsc/src/libmsc/smpp_vty.c +++ b/openbsc/src/libmsc/smpp_vty.c @@ -277,16 +277,6 @@ DEFUN(cfg_esme_no_passwd, cfg_esme_no_passwd_cmd, return CMD_SUCCESS; } -static int osmo_is_digits(const char *str) -{ - int i; - for (i = 0; i < strlen(str); i++) { - if (!isdigit(str[i])) - return 0; - } - return 1; -} - static const struct value_string route_errstr[] = { { -EEXIST, "Route already exists" }, { -ENODEV, "Route does not exist" }, diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index ecf5204..9a51260 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -133,6 +133,9 @@ class TestVTYGenericBSC(TestVTYBase): self.assertTrue(self.vty.verify("network",[''])) self.assertEquals(self.vty.node(), 'config-net') self.checkForEndAndExit() + self.assertTrue(self.vty.verify("virtual-network 0",[''])) + self.assertEquals(self.vty.node(), 'config-net-virt') + self.checkForEndAndExit() self.assertTrue(self.vty.verify("bts 0",[''])) self.assertEquals(self.vty.node(), 'config-net-bts') self.checkForEndAndExit() @@ -154,6 +157,12 @@ class TestVTYGenericBSC(TestVTYBase): self.assertEquals(self.vty.node(), 'config-net-bts') self.assertTrue(self.vty.verify("exit",[''])) self.assertEquals(self.vty.node(), 'config-net') + self.assertTrue(self.vty.verify("virtual-network 1",[''])) + self.assertEquals(self.vty.node(), 'config-net-virt') + self.checkForEndAndExit() + self.vty.command("write terminal") + self.assertTrue(self.vty.verify("exit",[''])) + self.assertEquals(self.vty.node(), 'config-net') self.assertTrue(self.vty.verify("exit",[''])) self.assertEquals(self.vty.node(), 'config') self.assertTrue(self.vty.verify("exit",[''])) @@ -342,6 +351,37 @@ class TestVTYNITB(TestVTYGenericBSC): res = self.vty.command('show subscriber imsi '+imsi) self.assert_(res != '% No subscriber found for imsi '+imsi) + def testVirtualNetworks(self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("network") + self.vty.command("virtual-network 0") + + # Test invalid input + self.vty.verify("imsi-prefix 1234567abcd89", ['% PREFIX has to be numeric']) + self.vty.verify("short name Test Net", ['% Unknown command.']) + self.vty.verify("long name Test Network", ['% Unknown command.']) + + # Set virtual-networks + self.vty.verify("imsi-prefix 00202", ['']) + self.vty.verify("short name TestNet2", ['']) + self.vty.verify("long name TestNetwork2", ['']) + self.vty.verify("exit",['']) + self.vty.command("virtual-network 1") + self.vty.verify("imsi-prefix 00303300", ['']) + self.vty.verify("short name TestNet3", ['']) + self.vty.verify("long name TestNetwork3", ['']) + + # Verify settings + res = self.vty.command("write terminal") + self.assert_(res.find('virtual-network 0') > 0) + self.assert_(res.find('imsi-prefix 00202') > 0) + self.assert_(res.find('short name TestNet2') > 0) + self.assert_(res.find('long name TestNetwork2') > 0) + self.assert_(res.find('virtual-network 1') > 0) + self.assert_(res.find('imsi-prefix 00303300') > 0) + self.assert_(res.find('short name TestNet3') > 0) + self.assert_(res.find('long name TestNetwork3') > 0) def testSubscriberCreateDelete(self): self.vty.enable() -- 1.9.1 From msuraev at sysmocom.de Mon Apr 18 09:07:01 2016 From: msuraev at sysmocom.de (Max) Date: Mon, 18 Apr 2016 11:07:01 +0200 Subject: range arfcn encoding In-Reply-To: <29832FAA-DC3E-4B89-A9F4-274EC8799D31@freyther.de> References: <571113CE.8020004@sysmocom.de> <29832FAA-DC3E-4B89-A9F4-274EC8799D31@freyther.de> Message-ID: <5714A3B5.200@sysmocom.de> Thanks for reply. Comments are inline. On 04/15/2016 07:36 PM, Holger Freyther wrote: >> On 15 Apr 2016, at 12:16, Max wrote: >> >> Hi. >> >> How to properly use range_enc_arfcns() and range_enc_range*() from >> arfcn_range_decode.h? There're not many comments around the code. From >> function signature it seems like range_enc_arfcns() will put results >> into w parameter but in system_information.c after that there's also >> call to one of range_enc_range*(). >> >> I've tried to feed output to wireshark but it decode some unexpected >> stuff. So, if I have a sequence of ints which I'd like to run through >> range512 for example - ho do I get the output? > 1st Determine which range to use If I know range in advance than this step can be skipped - are there some side effects to range_enc_determine_range() function? What's the meaning of f0? > 2nd filter out ARFCNs, e.g. if ARFCN 0 is included in the set or not So, range_enc_filter_arfcns() changes both arfcns and f0_included ? > 3rd encode according to the range So how do I supply input and where do I get output? The input is previously processed arfcns parameter to range_enc_arfcn() and the output is taken from which parameter of range_enc_range()? > > does this already help? Not entirely but we're getting there. > > > range = range_enc_determine_range(arfcns, arfcns_used, &f0); > if (range == ARFCN_RANGE_INVALID) > return -2; > > /* > * Manipulate the ARFCN list according to the rules in J4 depending > * on the selected range. > */ > arfcns_used = range_enc_filter_arfcns(arfcns, arfcns_used, > f0, &f0_included); > > memset(w, 0, sizeof(w)); > rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0); > if (rc != 0) > > > ... > > switch (range) { > case ARFCN_RANGE_128: > return range_enc_range128(chan_list, f0, w); > break; > case ARFCN_RANGE_256: -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Mon Apr 18 09:21:40 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 18 Apr 2016 11:21:40 +0200 Subject: [PATCH] Refactor range encoding Message-ID: <1460971300-14579-1-git-send-email-msuraev@sysmocom.de> From: Max Convert functions always returning the same constant into void type. Remove useless check of return value. --- openbsc/include/openbsc/arfcn_range_encode.h | 10 +++++----- openbsc/src/libbsc/arfcn_range_encode.c | 19 +++++++------------ openbsc/src/libbsc/system_information.c | 22 ++++++++++------------ openbsc/tests/gsm0408/gsm0408_test.c | 24 +++++++----------------- 4 files changed, 29 insertions(+), 46 deletions(-) diff --git a/openbsc/include/openbsc/arfcn_range_encode.h b/openbsc/include/openbsc/arfcn_range_encode.h index bd85d6a..7992c70 100644 --- a/openbsc/include/openbsc/arfcn_range_encode.h +++ b/openbsc/include/openbsc/arfcn_range_encode.h @@ -14,13 +14,13 @@ enum { #define RANGE_ENC_MAX_ARFCNS 29 int range_enc_determine_range(const int *arfcns, int size, int *f0_out); -int range_enc_arfcns(const int rng, const int *arfcns, int sze, int *out, int idx); +void range_enc_arfcns(const int rng, const int *arfcns, int sze, int *out, int idx); int range_enc_find_index(const int rng, const int *arfcns, int size); int range_enc_filter_arfcns(int *arfcns, const int sze, const int f0, int *f0_included); -int range_enc_range128(uint8_t *chan_list, int f0, int *w); -int range_enc_range256(uint8_t *chan_list, int f0, int *w); -int range_enc_range512(uint8_t *chan_list, int f0, int *w); -int range_enc_range1024(uint8_t *chan_list, int f0, int f0_incl, int *w); +void range_enc_range128(uint8_t *chan_list, int f0, int *w); +void range_enc_range256(uint8_t *chan_list, int f0, int *w); +void range_enc_range512(uint8_t *chan_list, int f0, int *w); +void range_enc_range1024(uint8_t *chan_list, int f0, int f0_incl, int *w); #endif diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c index e67bf0a..31fb8b8 100644 --- a/openbsc/src/libbsc/arfcn_range_encode.c +++ b/openbsc/src/libbsc/arfcn_range_encode.c @@ -79,7 +79,7 @@ int range_enc_find_index(const int range, const int *freqs, const int size) * \param size The size of the list of ARFCNs * \param out Place to store the W(i) output. */ -int range_enc_arfcns(const int range, +void range_enc_arfcns(const int range, const int *arfcns, int size, int *out, const int index) { @@ -100,11 +100,11 @@ int range_enc_arfcns(const int range, /* Test the two recursion anchors and stop processing */ if (size == 0) - return 0; + return; if (size == 1) { out[index] = 1 + arfcns[0]; - return 0; + return; } /* Now do the processing */ @@ -131,7 +131,6 @@ int range_enc_arfcns(const int range, out, index + greatest_power_of_2_lesser_or_equal_to(index + 1)); range_enc_arfcns((range -1 ) / 2, arfcns_right, r_size, out, index + (2 * greatest_power_of_2_lesser_or_equal_to(index + 1))); - return 0; } /* @@ -265,39 +264,35 @@ static void write_all_wn(uint8_t *chan_list, int bit_offs, } } -int range_enc_range128(uint8_t *chan_list, int f0, int *w) +void range_enc_range128(uint8_t *chan_list, int f0, int *w) { chan_list[0] = 0x8C; write_orig_arfcn(chan_list, f0); write_all_wn(&chan_list[2], 1, w, 28, 7); - return 0; } -int range_enc_range256(uint8_t *chan_list, int f0, int *w) +void range_enc_range256(uint8_t *chan_list, int f0, int *w) { chan_list[0] = 0x8A; write_orig_arfcn(chan_list, f0); write_all_wn(&chan_list[2], 1, w, 21, 8); - return 0; } -int range_enc_range512(uint8_t *chan_list, int f0, int *w) +void range_enc_range512(uint8_t *chan_list, int f0, int *w) { chan_list[0] = 0x88; write_orig_arfcn(chan_list, f0); write_all_wn(&chan_list[2], 1, w, 17, 9); - return 0; } -int range_enc_range1024(uint8_t *chan_list, int f0, int f0_included, int *w) +void range_enc_range1024(uint8_t *chan_list, int f0, int f0_included, int *w) { chan_list[0] = 0x80 | (f0_included << 2); write_all_wn(&chan_list[0], 6, w, 16, 10); - return 0; } int range_enc_filter_arfcns(int *arfcns, diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 43a492a..da36652 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -173,7 +173,7 @@ static inline int enc_freq_lst_range(uint8_t *chan_list, int w[RANGE_ENC_MAX_ARFCNS]; int f0_included = 0; int arfcns_used = 0; - int i, rc, range, f0; + int i, range, f0; /* * Select ARFCNs according to the rules in bitvec2freq_list @@ -202,24 +202,22 @@ static inline int enc_freq_lst_range(uint8_t *chan_list, f0, &f0_included); memset(w, 0, sizeof(w)); - rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0); - if (rc != 0) - return -3; + range_enc_arfcns(range, arfcns, arfcns_used, w, 0); /* Select the range and the amount of bits needed */ switch (range) { case ARFCN_RANGE_128: - return range_enc_range128(chan_list, f0, w); - break; + range_enc_range128(chan_list, f0, w); + return 0; case ARFCN_RANGE_256: - return range_enc_range256(chan_list, f0, w); - break; + range_enc_range256(chan_list, f0, w); + return 0; case ARFCN_RANGE_512: - return range_enc_range512(chan_list, f0, w); - break; + range_enc_range512(chan_list, f0, w); + return 0; case ARFCN_RANGE_1024: - return range_enc_range1024(chan_list, f0, f0_included, w); - break; + range_enc_range1024(chan_list, f0, f0_included, w); + return 0; default: return -4; }; diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index d6abce6..f0992f0 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -230,11 +230,7 @@ static int test_single_range_encoding(int range, const int *orig_arfcns, f0, &f0_included); memset(w, 0, sizeof(w)); - rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0); - if (rc != 0) { - printf("Cannot compute range W(k), rc = %d\n", rc); - return 1; - } + range_enc_arfcns(range, arfcns, arfcns_used, w, 0); if (!silent) fprintf(stderr, "range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n", @@ -243,24 +239,20 @@ static int test_single_range_encoding(int range, const int *orig_arfcns, /* Select the range and the amount of bits needed */ switch (range) { case ARFCN_RANGE_128: - rc = range_enc_range128(chan_list, f0, w); + range_enc_range128(chan_list, f0, w); break; case ARFCN_RANGE_256: - rc = range_enc_range256(chan_list, f0, w); + range_enc_range256(chan_list, f0, w); break; case ARFCN_RANGE_512: - rc = range_enc_range512(chan_list, f0, w); + range_enc_range512(chan_list, f0, w); break; case ARFCN_RANGE_1024: - rc = range_enc_range1024(chan_list, f0, f0_included, w); + range_enc_range1024(chan_list, f0, f0_included, w); break; default: return 1; }; - if (rc != 0) { - printf("Cannot encode range, rc = %d\n", rc); - return 1; - } if (!silent) printf("chan_list = %s\n", @@ -471,8 +463,7 @@ static void test_print_encoding() break; } - rc = range_enc_range512(chan_list, (1 << 9) | 0x96, w); - VERIFY(rc, ==, 0); + range_enc_range512(chan_list, (1 << 9) | 0x96, w); printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list))); } @@ -496,8 +487,7 @@ static void test_si_range_helpers() printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs3[i] : -1); VERIFY(i, ==, 0); - i = range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); - VERIFY(i, ==, 0); + range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) { printf("w[%d]=%d\n", i, ws[i]); -- 2.8.1 From holger at freyther.de Mon Apr 18 09:31:46 2016 From: holger at freyther.de (Holger Freyther) Date: Mon, 18 Apr 2016 11:31:46 +0200 Subject: range arfcn encoding In-Reply-To: <5714A3B5.200@sysmocom.de> References: <571113CE.8020004@sysmocom.de> <29832FAA-DC3E-4B89-A9F4-274EC8799D31@freyther.de> <5714A3B5.200@sysmocom.de> Message-ID: > On 18 Apr 2016, at 11:07, Max wrote: > > If I know range in advance than this step can be skipped - are there > some side effects to range_enc_determine_range() function? > What's the meaning of f0? > >> 2nd filter out ARFCNs, e.g. if ARFCN 0 is included in the set or not GSM 04.08: F0, frequency 0 indicator 0 ARFCN 0 is not a member of the set 1 ARFCN 0 is a member of the set At first I thought F0 is like f[0] (the first/lowest frequency in the set) but it is not. For range 1024 it is the question if ARFCN == 0 is part of it or not. > So, range_enc_filter_arfcns() changes both arfcns and f0_included ? >> 3rd encode according to the range > > So how do I supply input and where do I get output? The input is > previously processed arfcns parameter to range_enc_arfcn() and the > output is taken from which parameter of range_enc_range()? Have you considered looking at the testcases Jacob were adding? The nice thing of a testcase is, it is very few code, one can single step through it, etc. The nice thing about Jacob's code here is that it tests decode(encode(list)) == list. So you should be able to easily find where something is encoded to and from where the decoder is loading the data. E.g. code like the one below: if (!silent) printf("chan_list = %s\n", osmo_hexdump(chan_list, sizeof(chan_list))); rc = gsm48_decode_freq_list(dec_freq, chan_list, sizeof(chan_list), 0xfe, 1); On top of that using git log on the src/libbsc/arfcn_range_encode.c gives a good explanation of the history: * I added range512 because the customer needed it * Jacob fixed it * Jacob generalized it * Jacob added the other ranges too cheers holger From laforge at gnumonks.org Mon Apr 18 09:38:04 2016 From: laforge at gnumonks.org (Harald Welte) Date: Mon, 18 Apr 2016 11:38:04 +0200 Subject: [PATCH] Add support of virtual networks for sending network name to ms depending on imsi In-Reply-To: <1460968301-8162-1-git-send-email-kluchnikovi@gmail.com> References: <1460968301-8162-1-git-send-email-kluchnikovi@gmail.com> Message-ID: <20160418093804.GI4674@nataraja> Hi Ivan, I would prefer if we could use long-name and short-name instead of 'long name' and 'short name' in the VTY syntax. The VTY commands with spaces in them are a sign of my lack of understanding of the VTY system at that time. Multiple words should only be used if there actually is a 'fork' in the tree, i.e. if several commands are possible. So two commands 'name short' and 'name long' would make sense, as they are about name, and there are two options, one for short, and one for long name. Basically the same as 'name (short|long)' But 'short name' and 'long name' will install command nodes for 'short' and long', which doesn't make sense. We keep the old syntax for compatibility on the 'network' node, but for new code added, we should try to avoid this. So let's either use 'name (short|long)' (maybe the best solutioin) or 'short-name' and 'long-name'. > +#define IMSI_PREFIX_LENGTH 16 we should probably not pull the magic number 16 out of our sleeve here, but try to use an existing #define for the length of an IMSI. I'm quite sure we have one somewhere in libosmocore or the openbsc code base. > +struct gsm_virt_network *gsm_virt_net_alloc_register(struct gsm_network *net) > +{ > + struct gsm_virt_network *virt_net; > + > + virt_net = gsm_virt_net_alloc(net); > + if (!virt_net) > + return NULL; > + > + virt_net->nr = net->num_virt_net++; > + virt_net->network = net; > + strcpy(virt_net->imsi_prefix, "00101"); > + virt_net->name_short = talloc_strdup(net, "OpenBSC"); > + virt_net->name_long = talloc_strdup(net, "OpenBSC"); why do we have hard-coded defaults for a prefix 00101 inside the code? I think we should advoid such automatism, as creating a new virtual network will then instantaneously match 00101 prefixed IMSIs without the user ever specifying this. Or am I misunderstanding this? Thanks! -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From nhofmeyr at sysmocom.de Mon Apr 18 10:40:01 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 18 Apr 2016 12:40:01 +0200 Subject: [PATCH] compiler warning: pointer type in OCTET_STRING_noalloc() In-Reply-To: <20160415194955.GC1832@nataraja> References: <1460637956-19900-1-git-send-email-nhofmeyr@sysmocom.de> <20160415194955.GC1832@nataraja> Message-ID: <20160418104001.GC1703@dub6> On Fri, Apr 15, 2016 at 09:49:55PM +0200, Harald Welte wrote: > Hi Neels, > > On Thu, Apr 14, 2016 at 02:45:56PM +0200, Neels Hofmeyr wrote: > > It's useless to declare the str arg as const when all the function does is > > assign it to a non-const pointer. > > The point of doing it this way is that we don't have to write our code > in a sub-standard way, just because asn1c is written in a way that you > cannot have 'const' buffers as input into encoding. > > So 'const' here is used as a hint to the programmer, that a read-only > string is passed into this function, and hence it is input data. > > So this was very intentional. Now you can argue that my line of > thinking above is basically ignoring the reality of asn1c. But then, > don't we have actual real issues to address, than to debate about thing > slike this? Sorry... I would prefer not to debate about this as extensively, but you guys won't stop bickering ;) To resolve, I would appreciate if you either apply my patch or add the cast within the function. I still disagree and think it is the caller's duty to be aware that the asn1c struct entry is not const, and that passing such a buffer around possibly results in overwriting the data. That ugly cast should be in plain sight wherever it is necessary, not hidden away in a function call, invisible until your code breaks. I still see only the single caller that employs const data, and this caller can easily justify casting to non-const, as the use is well contained. Feel free to overrule, just please get rid of the warning... ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Mon Apr 18 10:56:19 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 18 Apr 2016 12:56:19 +0200 Subject: [PATCH] queue_new(): if calloc fails, abort (CID #57918) In-Reply-To: <20160416113741.GK31766@nataraja> References: <1460644722-22972-1-git-send-email-nhofmeyr@sysmocom.de> <20160416113741.GK31766@nataraja> Message-ID: <20160418105619.GD1703@dub6> On Sat, Apr 16, 2016 at 01:37:41PM +0200, Harald Welte wrote: > Hi Neels > > On Thu, Apr 14, 2016 at 04:38:42PM +0200, Neels Hofmeyr wrote: > > Coverity complains about a 'Dereference before null check' on *queue. > > So, push the NULL check further up, > > No question here. > > > but also, instead of handling a calloc failure as error, rather abort > > the program. > > I think that's a much more fundamental question. Should we really abort > the program in this case? In an in-person discussion with Holger on some other code way back some day, he recommended to abort() on allocation failure. Might not be applicable here, of course. > If so, why only in case of queue allocation > failures, but not in general at all memory allocation failures? And if > that's the case, wrapping calloc() / malloc() and other dynamic memory > allocation calls with a function that contains the abort() (or an > OSMO_ASSERT() on the result) might be more applicable? Yes, I would agree with that. (BTW, the only reason I didn't OSMO_ASSERT() was that there is no other use of OSMO_ASSERT() anywhere else in OpenGGSN.) How should we handle this, I'd prefer not to spend time on that now. Commit the patch with `return EOF' instead of abort()ing, as the old code suggests? I don't know about that, EOF doesn't seem applicable at all. ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From holger at freyther.de Mon Apr 18 11:25:42 2016 From: holger at freyther.de (Holger Freyther) Date: Mon, 18 Apr 2016 13:25:42 +0200 Subject: [PATCH] Fix earfcn deletion In-Reply-To: <1460968336-23741-1-git-send-email-msuraev@sysmocom.de> References: <1460968336-23741-1-git-send-email-msuraev@sysmocom.de> Message-ID: <63341C01-5CFE-41CE-8871-707F2149D7EE@freyther.de> > On 18 Apr 2016, at 10:32, msuraev at sysmocom.de wrote: > > From: Max > > * fix documentation for command parameters > * fix typo in arg index > * fix sign in error reporting add VTY test for this regression? I will pick the doc fix to get the build blue/green again. holger From kluchnikovi at gmail.com Mon Apr 18 17:22:22 2016 From: kluchnikovi at gmail.com (Ivan Kluchnikov) Date: Mon, 18 Apr 2016 20:22:22 +0300 Subject: [PATCH] Add support of virtual networks for sending network name to ms depending on imsi In-Reply-To: <20160418093804.GI4674@nataraja> References: <1460968301-8162-1-git-send-email-kluchnikovi@gmail.com> <20160418093804.GI4674@nataraja> Message-ID: Hi Harald, I would prefer if we could use long-name and short-name instead of 'long > name' and 'short name' in the VTY syntax. > > The VTY commands with spaces in them are a sign of my lack of > understanding of the VTY system at that time. Multiple words should > only be used if there actually is a 'fork' in the tree, i.e. if several > commands are possible. > > So two commands 'name short' and 'name long' would make sense, as they > are about name, and there are two options, one for short, and one for > long name. Basically the same as 'name (short|long)' > > But 'short name' and 'long name' will install command nodes for 'short' > and long', which doesn't make sense. We keep the old syntax for > compatibility on the 'network' node, but for new code added, we should > try to avoid this. > > So let's either use 'name (short|long)' (maybe the best solutioin) or > 'short-name' and 'long-name'. > Thank you for explanation. We will have different commands for configuring the same parameters for main network and virtual networks ("short name OpenBSC" and "name short OpenBSC"), but I think it's ok, I will change it to 'name (short|long)'. > > +#define IMSI_PREFIX_LENGTH 16 > > we should probably not pull the magic number 16 out of our sleeve here, > but try to use an existing #define for the length of an IMSI. I'm quite > sure we have one somewhere in libosmocore or the openbsc code base. > Ok, I see that GSM_IMSI_LENGTH is defined in gsm_subscriber.h, so I can just move it to gsm_data.h and use it. Btw, as I know maximum imsi length is 15, why 17 is used for GSM_IMSI_LENGTH instead of 16? > > +struct gsm_virt_network *gsm_virt_net_alloc_register(struct gsm_network > *net) > > +{ > > + struct gsm_virt_network *virt_net; > > + > > + virt_net = gsm_virt_net_alloc(net); > > + if (!virt_net) > > + return NULL; > > + > > + virt_net->nr = net->num_virt_net++; > > + virt_net->network = net; > > + strcpy(virt_net->imsi_prefix, "00101"); > > + virt_net->name_short = talloc_strdup(net, "OpenBSC"); > > + virt_net->name_long = talloc_strdup(net, "OpenBSC"); > > why do we have hard-coded defaults for a prefix 00101 inside the code? > I think we should advoid such automatism, as creating a new virtual > network will then instantaneously match 00101 prefixed IMSIs without the > user ever specifying this. Or am I misunderstanding this? > Yes, you are right, by default imsi-prefix should be undefined, I will fix it. -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.chemeris at gmail.com Mon Apr 18 18:52:26 2016 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Mon, 18 Apr 2016 21:52:26 +0300 Subject: [PATCH 1/2] utils: 'meas_json' utility to convert measurement feed into a JSON feed. In-Reply-To: <1449931457-6446-1-git-send-email-Alexander.Chemeris@gmail.com> References: <1449931457-6446-1-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: Dear all, Just wondering if this could be merged. I haven't seen any comments on the patch - probably fallen through the cracks of the patchwork again. Please excuse typos. Written with a touchscreen keyboard. -- Regards, Alexander Chemeris CEO Fairwaves, Inc. https://fairwaves.co On Dec 12, 2015 5:44 PM, "Alexander Chemeris" wrote: > --- > openbsc/src/utils/Makefile.am | 6 +- > openbsc/src/utils/meas_json.c | 169 > ++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 174 insertions(+), 1 deletion(-) > create mode 100644 openbsc/src/utils/meas_json.c > > diff --git a/openbsc/src/utils/Makefile.am b/openbsc/src/utils/Makefile.am > index f6255a0..89f2dfb 100644 > --- a/openbsc/src/utils/Makefile.am > +++ b/openbsc/src/utils/Makefile.am > @@ -4,7 +4,7 @@ AM_LDFLAGS = $(COVERAGE_LDFLAGS) > > noinst_HEADERS = meas_db.h > > -bin_PROGRAMS = bs11_config isdnsync > +bin_PROGRAMS = bs11_config isdnsync meas_json > if HAVE_SQLITE3 > bin_PROGRAMS += osmo-meas-pcap2db osmo-meas-udp2db > endif > @@ -32,6 +32,10 @@ meas_vis_SOURCES = meas_vis.c > meas_vis_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -lcdk -lncurses > meas_vis_CFLAGS = $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) > > +meas_json_SOURCES = meas_json.c > +meas_json_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) > +meas_json_CFLAGS = $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) > + > osmo_meas_pcap2db_SOURCES = meas_pcap2db.c meas_db.c > osmo_meas_pcap2db_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -lpcap > $(SQLITE3_LIBS) > osmo_meas_pcap2db_CFLAGS = $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) > diff --git a/openbsc/src/utils/meas_json.c b/openbsc/src/utils/meas_json.c > new file mode 100644 > index 0000000..940e5e7 > --- /dev/null > +++ b/openbsc/src/utils/meas_json.c > @@ -0,0 +1,169 @@ > +/* Convert measurement report feed into JSON feed printed to stdout. > + * Each measurement report is printed as a separae JSON root entry. > + * All measurement reports are separated by a new line. > + */ > + > +/* (C) 2015 by Alexander Chemeris > + * With parts of code adopted from different places in OpenBSC. > + * > + * 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 Affero General Public License for more details. > + * > + * You should have received a copy of the GNU Affero General Public > License > + * along with this program. If not, see . > + * > + */ > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#include > +#include > +#include > + > +#include > + > +#include > + > +static void print_meas_rep_uni_json(struct gsm_meas_rep_unidir *mru) > +{ > + printf("\"RXL-FULL\":%d, \"RXL-SUB\":%d, ", > + rxlev2dbm(mru->full.rx_lev), > + rxlev2dbm(mru->sub.rx_lev)); > + printf("\"RXQ-FULL\":%d, \"RXQ-SUB\":%d", > + mru->full.rx_qual, mru->sub.rx_qual); > +} > + > +static void print_meas_rep_json(struct gsm_meas_rep *mr) > +{ > + int i; > + > + printf("\"NR\":%d", mr->nr); > + > + if (mr->flags & MEAS_REP_F_DL_DTX) > + printf(", \"DTXd\":true"); > + > + printf(", \"UL_MEAS\":{"); > + print_meas_rep_uni_json(&mr->ul); > + printf("}"); > + printf(", \"BS_POWER\":%d", mr->bs_power); > + if (mr->flags & MEAS_REP_F_MS_TO) > + printf(", \"MS_TO\":%d", mr->ms_timing_offset); > + > + if (mr->flags & MEAS_REP_F_MS_L1) { > + printf(", \"L1_MS_PWR\":%d", mr->ms_l1.pwr); > + printf(", \"L1_FPC\":%s", > + mr->flags & MEAS_REP_F_FPC ? "true" : "false"); > + printf(", \"L1_TA\":%u", mr->ms_l1.ta); > + } > + > + if (mr->flags & MEAS_REP_F_UL_DTX) > + printf(", \"DTXu\":true"); > + if (mr->flags & MEAS_REP_F_BA1) > + printf(", \"BA1\":true"); > + if (mr->flags & MEAS_REP_F_DL_VALID) { > + printf(", \"DL_MEAS\":{"); > + print_meas_rep_uni_json(&mr->dl); > + printf("}"); > + } > + > + if (mr->num_cell == 7) > + return; > + printf(", \"NUM_NEIGH\":%u, \"NEIGH\":[", mr->num_cell); > + for (i = 0; i < mr->num_cell; i++) { > + struct gsm_meas_rep_cell *mrc = &mr->cell[i]; > + if (i!=0) printf(", "); > + printf("\"IDX\":%u, \"ARFCN\":%u, \"BSIC\":%u, > \"POWER\":%d", > + mrc->neigh_idx, mrc->arfcn, mrc->bsic, > rxlev2dbm(mrc->rxlev)); > + } > + printf("]"); > +} > + > +static void print_meas_feed_json(struct meas_feed_meas *mfm) > +{ > + time_t now = time(NULL); > + > + printf("{"); > + printf("\"time\":%ld, \"imsi\":\"%s\", \"name\":\"%s\", > \"scenario\":\"%s\", ", > + now, mfm->imsi, mfm->name, mfm->scenario); > + > + printf("\"meas_rep\":{"); > + print_meas_rep_json(&mfm->mr); > + printf("}"); > + > + printf("}\n"); > + > +} > + > +static int handle_meas(struct msgb *msg) > +{ > + struct meas_feed_meas *mfm = (struct meas_feed_meas *) > msgb_data(msg); > + > + print_meas_feed_json(mfm); > + > + return 0; > +} > + > +static int handle_msg(struct msgb *msg) > +{ > + struct meas_feed_hdr *mfh = (struct meas_feed_hdr *) > msgb_data(msg); > + > + if (mfh->version != MEAS_FEED_VERSION) > + return -EINVAL; > + > + switch (mfh->msg_type) { > + case MEAS_FEED_MEAS: > + handle_meas(msg); > + break; > + default: > + break; > + } > +} > + > +static int udp_fd_cb(struct osmo_fd *ofd, unsigned int what) > +{ > + int rc; > + > + if (what & BSC_FD_READ) { > + struct msgb *msg = msgb_alloc(1024, "UDP Rx"); > + > + rc = read(ofd->fd, msgb_data(msg), msgb_tailroom(msg)); > + if (rc < 0) > + return rc; > + msgb_put(msg, rc); > + handle_msg(msg); > + msgb_free(msg); > + } > + > + return 0; > +} > + > +int main(int argc, char **argv) > +{ > + int rc; > + struct osmo_fd udp_ofd; > + > + udp_ofd.cb = udp_fd_cb; > + rc = osmo_sock_init_ofd(&udp_ofd, AF_INET, SOCK_DGRAM, > IPPROTO_UDP, NULL, 8888, OSMO_SOCK_F_BIND); > + if (rc < 0) > + exit(1); > + > + while (1) { > + osmo_select_main(0); > + }; > + > + exit(0); > +} > -- > 1.9.1 > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.chemeris at gmail.com Mon Apr 18 18:53:12 2016 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Mon, 18 Apr 2016 21:53:12 +0300 Subject: [PATCH 2/2] utils: Support new fields in the v1 of meas_feed in meas_json. In-Reply-To: <1449931457-6446-2-git-send-email-Alexander.Chemeris@gmail.com> References: <1449931457-6446-1-git-send-email-Alexander.Chemeris@gmail.com> <1449931457-6446-2-git-send-email-Alexander.Chemeris@gmail.com> Message-ID: Ditto here Please excuse typos. Written with a touchscreen keyboard. -- Regards, Alexander Chemeris CEO Fairwaves, Inc. https://fairwaves.co On Dec 12, 2015 5:44 PM, "Alexander Chemeris" wrote: > --- > openbsc/src/utils/Makefile.am | 3 ++- > openbsc/src/utils/meas_json.c | 25 ++++++++++++++++++++++--- > 2 files changed, 24 insertions(+), 4 deletions(-) > > diff --git a/openbsc/src/utils/Makefile.am b/openbsc/src/utils/Makefile.am > index 89f2dfb..681d074 100644 > --- a/openbsc/src/utils/Makefile.am > +++ b/openbsc/src/utils/Makefile.am > @@ -33,7 +33,8 @@ meas_vis_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) > -lcdk -lncurses > meas_vis_CFLAGS = $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) > > meas_json_SOURCES = meas_json.c > -meas_json_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) > +meas_json_LDADD = $(top_builddir)/src/libcommon/libcommon.a \ > + $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) > meas_json_CFLAGS = $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) > > osmo_meas_pcap2db_SOURCES = meas_pcap2db.c meas_db.c > diff --git a/openbsc/src/utils/meas_json.c b/openbsc/src/utils/meas_json.c > index 940e5e7..88d713b 100644 > --- a/openbsc/src/utils/meas_json.c > +++ b/openbsc/src/utils/meas_json.c > @@ -36,6 +36,8 @@ > > #include > > +#include > +#include > #include > > static void print_meas_rep_uni_json(struct gsm_meas_rep_unidir *mru) > @@ -92,6 +94,14 @@ static void print_meas_rep_json(struct gsm_meas_rep *mr) > printf("]"); > } > > +static void print_chan_info_json(struct meas_feed_meas *mfm) > +{ > + printf("\"lchan_type\":\"%s\", \"pchan_type\":\"%s\", " > + "\"bts_nr\":%d, \"trx_nr\":%d, \"ts_nr\":%d, > \"ss_nr\":%d", > + gsm_lchant_name(mfm->lchan_type), gsm_pchan_name(mfm->pchan_type), > + mfm->bts_nr, mfm->trx_nr, mfm->ts_nr, mfm->ss_nr); > +} > + > static void print_meas_feed_json(struct meas_feed_meas *mfm) > { > time_t now = time(NULL); > @@ -100,9 +110,18 @@ static void print_meas_feed_json(struct > meas_feed_meas *mfm) > printf("\"time\":%ld, \"imsi\":\"%s\", \"name\":\"%s\", > \"scenario\":\"%s\", ", > now, mfm->imsi, mfm->name, mfm->scenario); > > - printf("\"meas_rep\":{"); > - print_meas_rep_json(&mfm->mr); > - printf("}"); > + switch (mfm->hdr.version) { > + case 1: > + printf("\"chan_info\":{"); > + print_chan_info_json(mfm); > + printf("}, "); > + /* no break, fall to version 0 */ > + case 0: > + printf("\"meas_rep\":{"); > + print_meas_rep_json(&mfm->mr); > + printf("}"); > + break; > + } > > printf("}\n"); > > -- > 1.9.1 > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From suraev at alumni.ntnu.no Mon Apr 18 20:24:08 2016 From: suraev at alumni.ntnu.no (suraev at alumni.ntnu.no) Date: Mon, 18 Apr 2016 22:24:08 +0200 Subject: [PATCH 1/4] Add code generator for convolutional codes Message-ID: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> From: Max Add python utility to generate .c code with state/output tables for convolutional encoder/decoder based on polynomial description of the code. If argument given it'll be interpreted as intended output directory, otherwise current working directory is used. Note: only necessary tables are generated. Corresponding header files with actual osmo_conv_code instance (including puncturing etc) have to be added manually. The main work for this patch was generously contributed by Sylvain Munaut. Fixes: OS#1629 --- utils/conv_gen.py | 510 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100755 utils/conv_gen.py diff --git a/utils/conv_gen.py b/utils/conv_gen.py new file mode 100755 index 0000000..da99c7d --- /dev/null +++ b/utils/conv_gen.py @@ -0,0 +1,510 @@ +#!/usr/bin/python + +license =""" +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +""" + +import sys, os + +class ConvolutionalCode(object): + + def __init__(self, block_len, n, k, polys, name = "call-me", description = "LOL", puncture = []): + # Save simple params + self.block_len = block_len + self.k = k + self.n = n + self.puncture = puncture + self.rate_inv = len(polys) + + # Infos + self.name = name + self.description = description + + # Handle polynoms (and check for recursion) + self.polys = [(1, 1) if x[0] == x[1] else x for x in polys] + + rp = [x[1] for x in self.polys if x[1] != 1] + if rp: + if not all([x == rp[0] for x in rp]): + raise ValueError("Bad polynoms: Can't have multiple different divider polynoms !") + if not all([x[0] == 1 for x in polys if x[1] == 1]): + raise ValueError("Bad polynoms: Can't have a '1' divider with a non '1' dividend in a recursive code") + self.poly_divider = rp[0] + else: + self.poly_divider = 1 + + @property + def recursive(self): + return self.poly_divider != 1 + + def _combine(self, src, sel, nb): + x = src & sel + fn_xor = lambda x, y: x ^ y + return reduce(fn_xor, [(x >> n) & 1 for n in range(nb)]) + + @property + def _state_mask(self): + return ((1 << (self.k - 1)) - 1) + + def next_state(self, state, bit): + nb = self._combine( + (state << 1) | bit, + self.poly_divider, + self.k, + ) + return ((state << 1) | nb) & self._state_mask + + def next_term_state(self, state): + return (state << 1) & self._state_mask + + def next_output(self, state, bit, ns = None): + # Next state bit + if ns is None: + ns = self.next_state(state, bit) + + src = (ns & 1) | (state << 1) + + # Scan polynoms + rv = [] + for p_n, p_d in self.polys: + if self.recursive and p_d == 1: + o = bit # No choice ... (systematic output in recursive case) + else: + o = self._combine(src, p_n, self.k) + rv.append(o) + + return rv + + def next_term_output(self, state, ns = None): + # Next state bit + if ns is None: + ns = self.next_term_state(state) + + src = (ns & 1) | (state << 1) + + # Scan polynoms + rv = [] + for p_n, p_d in self.polys: + if self.recursive and p_d == 1: + # Systematic output are replaced when in 'termination' mode + o = self._combine(src, self.poly_divider, self.k) + else: + o = self._combine(src, p_n, self.k) + rv.append(o) + + return rv + + def next(self, state, bit): + ns = self.next_state(state, bit) + nb = self.next_output(state, bit, ns = ns) + return ns, nb + + def next_term(self, state): + ns = self.next_term_state(state) + nb = self.next_term_output(state, ns = ns) + return ns, nb + + def _print_term(self, fi, num_states, pack = False): + d = [] + for state in range(num_states): + x = pack(self.next_term_output(state)) if pack else self.next_term_state(state) + d.append("%d, " % x) + print >>fi, "\t%s" % ''.join(d) + + def _print_x(self, fi, num_states, pack = False): + for state in range(num_states): + x0 = pack(self.next_output(state, 0)) if pack else self.next_state(state, 0) + x1 = pack(self.next_output(state, 1)) if pack else self.next_state(state, 1) + print >>fi, "\t{ %2d, %2d }," % (x0, x1) + + def gen_tables(self, pref, fi): + pack = lambda n: sum([x << (self.rate_inv - i - 1) for i, x in enumerate(n)]) + s = "%s_%s" % (pref, self.name) + num_states = 1 << (self.k - 1) + print >>fi, "\nstatic const uint8_t %s_state[][2] = {" % s + self._print_x(fi, num_states) + print >>fi, "};\n\nstatic const uint8_t %s_output[][2] = {" % s + self._print_x(fi, num_states, pack) + print >>fi, "};" + + if self.recursive: + print >>fi, "\nstatic const uint8_t %s_term_state[] = {" % s + self._print_term(fi, num_states) + print >>fi, "};\n\nstatic const uint8_t %s_term_output[] = {" % s + self._print_term(fi, num_states, pack) + print >>fi, "};" + + if len(self.puncture): + print >>fi, "\nstatic const int %s_puncture[] = {" % s + for p in self.puncture: + print >>fi, "\t%d," % p + print >>fi, "};" + + print >>fi, "\n/* %s */" % self.description + print >>fi, "const struct osmo_conv_code %s = {" % s + print >>fi, "\t.N = %d," % self.n + print >>fi, "\t.K = %d," % self.k + print >>fi, "\t.len = %d," % self.block_len + print >>fi, "\t.next_output = %s_output," % s + print >>fi, "\t.next_state = %s_state," % s + if self.recursive: + print >>fi, "\t.next_term_output = %s_term_output," % s + print >>fi, "\t.next_term_state = %s_term_state," % s + if len(self.puncture): + print >>fi, "\t.puncture = %s_puncture," % s + print >>fi, "};" + +poly = lambda *args: sum([(1 << x) for x in args]) + +cch_poly = [ ( poly(0, 3, 4), 1 ), + ( poly(0, 1, 3, 4), 1 ), +] + +xcch = ConvolutionalCode( + 224, 2, 5, + cch_poly, + name = "xcch", + description =""" *CCH convolutional code: + 228 bits blocks, rate 1/2, k = 5 + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 +""" +) + +cs2 = ConvolutionalCode( + 290, 2, 5, + cch_poly, + puncture = [ + 15, 19, 23, 27, 31, 35, 43, 47, 51, 55, 59, 63, 67, 71, + 75, 79, 83, 91, 95, 99, 103, 107, 111, 115, 119, 123, 127, 131, + 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, 187, 191, 195, + 199, 203, 207, 211, 215, 219, 223, 227, 235, 239, 243, 247, 251, 255, + 259, 263, 267, 271, 275, 283, 287, 291, 295, 299, 303, 307, 311, 315, + 319, 323, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 379, + 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 427, 431, 435, 439, + 443, 447, 451, 455, 459, 463, 467, 475, 479, 483, 487, 491, 495, 499, + 503, 507, 511, 515, 523, 527, 531, 535, 539, 543, 547, 551, 555, 559, + 563, 571, 575, 579, 583, 587, -1 + ], + name = "cs2", + description =""" CS2 convolutional code: + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 +""" +) + +cs3 = ConvolutionalCode( + 334, 2, 5, + cch_poly, + puncture = [ + 15, 17, 21, 23, 27, 29, 33, 35, 39, 41, 45, 47, 51, 53, + 57, 59, 63, 65, 69, 71, 75, 77, 81, 83, 87, 89, 93, 95, + 99, 101, 105, 107, 111, 113, 117, 119, 123, 125, 129, 131, 135, 137, + 141, 143, 147, 149, 153, 155, 159, 161, 165, 167, 171, 173, 177, 179, + 183, 185, 189, 191, 195, 197, 201, 203, 207, 209, 213, 215, 219, 221, + 225, 227, 231, 233, 237, 239, 243, 245, 249, 251, 255, 257, 261, 263, + 267, 269, 273, 275, 279, 281, 285, 287, 291, 293, 297, 299, 303, 305, + 309, 311, 315, 317, 321, 323, 327, 329, 333, 335, 339, 341, 345, 347, + 351, 353, 357, 359, 363, 365, 369, 371, 375, 377, 381, 383, 387, 389, + 393, 395, 399, 401, 405, 407, 411, 413, 417, 419, 423, 425, 429, 431, + 435, 437, 441, 443, 447, 449, 453, 455, 459, 461, 465, 467, 471, 473, + 477, 479, 483, 485, 489, 491, 495, 497, 501, 503, 507, 509, 513, 515, + 519, 521, 525, 527, 531, 533, 537, 539, 543, 545, 549, 551, 555, 557, + 561, 563, 567, 569, 573, 575, 579, 581, 585, 587, 591, 593, 597, 599, + 603, 605, 609, 611, 615, 617, 621, 623, 627, 629, 633, 635, 639, 641, + 645, 647, 651, 653, 657, 659, 663, 665, 669, 671, -1 + ], + name = "cs3", + description =""" CS3 convolutional code: + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 +""" +) + +tch_afs_12_2 = ConvolutionalCode( + 250, 2, 5, + [ + ( 1, 1 ), + ( poly(0, 1, 3, 4), poly(0, 3, 4) ), + ], + puncture = [ + 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 363, + 365, 369, 373, 377, 379, 381, 385, 389, 393, 395, 397, 401, + 405, 409, 411, 413, 417, 421, 425, 427, 429, 433, 437, 441, + 443, 445, 449, 453, 457, 459, 461, 465, 469, 473, 475, 477, + 481, 485, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, + -1 + ], + name = 'tch_afs_12_2', + description = """TCH/AFS 12.2 convolutional code: + 250 bits block, rate 1/2, punctured + G0/G0 = 1 + G1/G0 = 1 + D + D3 + D4 / 1 + D3 + D4 +""" +) + +tch_afs_10_2 = ConvolutionalCode( + 210, 3, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ], + puncture = [ + 1, 4, 7, 10, 16, 19, 22, 28, 31, 34, 40, 43, + 46, 52, 55, 58, 64, 67, 70, 76, 79, 82, 88, 91, + 94, 100, 103, 106, 112, 115, 118, 124, 127, 130, 136, 139, + 142, 148, 151, 154, 160, 163, 166, 172, 175, 178, 184, 187, + 190, 196, 199, 202, 208, 211, 214, 220, 223, 226, 232, 235, + 238, 244, 247, 250, 256, 259, 262, 268, 271, 274, 280, 283, + 286, 292, 295, 298, 304, 307, 310, 316, 319, 322, 325, 328, + 331, 334, 337, 340, 343, 346, 349, 352, 355, 358, 361, 364, + 367, 370, 373, 376, 379, 382, 385, 388, 391, 394, 397, 400, + 403, 406, 409, 412, 415, 418, 421, 424, 427, 430, 433, 436, + 439, 442, 445, 448, 451, 454, 457, 460, 463, 466, 469, 472, + 475, 478, 481, 484, 487, 490, 493, 496, 499, 502, 505, 508, + 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, + 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, + 583, 586, 589, 592, 595, 598, 601, 604, 607, 609, 610, 613, + 616, 619, 621, 622, 625, 627, 628, 631, 633, 634, 636, 637, + 639, 640, -1 + ], + name = 'tch_afs_10_2', + description = """TCH/AFS 10.2 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 +""" +) + +tch_afs_7_95 = ConvolutionalCode( + 165, 3, 7, + [ + ( 1, 1 ), + ( poly(0, 1, 4, 6), poly(0, 2, 3, 5, 6) ), + ( poly(0, 1, 2, 3, 4, 6), poly(0, 2, 3, 5, 6) ), + ], + puncture = [ + 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310, + 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367, + 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415, + 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463, + 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505, + 506, 508, 509, 511, 512, -1 + ], + name = 'tch_afs_7_95', + description = """TCH/AFS 7.95 kbits convolutional code: + G4/G4 = 1 + G5/G4 = 1 + D + D4 + D6 / 1 + D2 + D3 + D5 + D6 + G6/G4 = 1 + D + D2 + D3 + D4 + D6 / 1 + D2 + D3 + D5 + D6 +""" +) + +tch_afs_7_4 = ConvolutionalCode( + 154, 3, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ], + puncture = [ + 0, 355, 361, 367, 373, 379, 385, 391, 397, 403, 409, 415, + 421, 427, 433, 439, 445, 451, 457, 460, 463, 466, 468, 469, + 471, 472, -1 + ], + name = 'tch_afs_7_4', + description = """TCH/AFS 7.4 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 +""" +) + +tch_afs_6_7 = ConvolutionalCode( + 140, 4, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ( 1, 1 ), + ], + puncture = [ + 1, 3, 7, 11, 15, 27, 39, 55, 67, 79, 95, 107, + 119, 135, 147, 159, 175, 187, 199, 215, 227, 239, 255, 267, + 279, 287, 291, 295, 299, 303, 307, 311, 315, 319, 323, 327, + 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 369, 371, + 375, 377, 379, 383, 385, 387, 391, 393, 395, 399, 401, 403, + 407, 409, 411, 415, 417, 419, 423, 425, 427, 431, 433, 435, + 439, 441, 443, 447, 449, 451, 455, 457, 459, 463, 465, 467, + 471, 473, 475, 479, 481, 483, 487, 489, 491, 495, 497, 499, + 503, 505, 507, 511, 513, 515, 519, 521, 523, 527, 529, 531, + 535, 537, 539, 543, 545, 547, 549, 551, 553, 555, 557, 559, + 561, 563, 565, 567, 569, 571, 573, 575, -1 + ], + name = 'tch_afs_6_7', + description = """TCH/AFS 6.7 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 +""" +) + +tch_afs_5_9 = ConvolutionalCode( + 124, 4, 7, + [ + ( poly(0, 2, 3, 5, 6), poly(0, 1, 2, 3, 4, 6) ), + ( poly(0, 1, 4, 6), poly(0, 1, 2, 3, 4, 6) ), + ( 1, 1), + ( 1, 1), + ], + puncture = [ + 0, 1, 3, 5, 7, 11, 15, 31, 47, 63, 79, 95, + 111, 127, 143, 159, 175, 191, 207, 223, 239, 255, 271, 287, + 303, 319, 327, 331, 335, 343, 347, 351, 359, 363, 367, 375, + 379, 383, 391, 395, 399, 407, 411, 415, 423, 427, 431, 439, + 443, 447, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, + 495, 499, 503, 507, 509, 511, 512, 513, 515, 516, 517, 519, + -1 + ], + name = 'tch_afs_5_9', + description = """TCH/AFS 5.9 kbits convolutional code: + 124 bits + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 +""" +) + +tch_afs_5_15 = ConvolutionalCode( + 109, 5, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ( 1, 1 ), + ], + puncture = [ + 0, 4, 5, 9, 10, 14, 15, 20, 25, 30, 35, 40, + 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, + 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, + 290, 300, 310, 315, 320, 325, 330, 334, 335, 340, 344, 345, + 350, 354, 355, 360, 364, 365, 370, 374, 375, 380, 384, 385, + 390, 394, 395, 400, 404, 405, 410, 414, 415, 420, 424, 425, + 430, 434, 435, 440, 444, 445, 450, 454, 455, 460, 464, 465, + 470, 474, 475, 480, 484, 485, 490, 494, 495, 500, 504, 505, + 510, 514, 515, 520, 524, 525, 529, 530, 534, 535, 539, 540, + 544, 545, 549, 550, 554, 555, 559, 560, 564, -1 + ], + name = 'tch_afs_5_15', + description = """TCH/AFS 5.15 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 +""" +) + +tch_afs_4_75 = ConvolutionalCode( + 101, 5, 7, + [ + ( poly(0, 2, 3, 5, 6), poly(0, 1, 2, 3, 4, 6) ), + ( poly(0, 2, 3, 5, 6), poly(0, 1, 2, 3, 4, 6) ), + ( poly(0, 1, 4, 6), poly(0, 1, 2, 3, 4, 6) ), + ( 1, 1 ), + ( 1, 1 ), + ], + puncture = [ + 0, 1, 2, 4, 5, 7, 9, 15, 25, 35, 45, 55, + 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, + 185, 195, 205, 215, 225, 235, 245, 255, 265, 275, 285, 295, + 305, 315, 325, 335, 345, 355, 365, 375, 385, 395, 400, 405, + 410, 415, 420, 425, 430, 435, 440, 445, 450, 455, 459, 460, + 465, 470, 475, 479, 480, 485, 490, 495, 499, 500, 505, 509, + 510, 515, 517, 519, 520, 522, 524, 525, 526, 527, 529, 530, + 531, 532, 534, -1 + ], + name = 'tch_afs_4_75', + description = """TCH/AFS 4.75 kbits convolutional code: + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 +""" +) + +tetra_rcpc = ConvolutionalCode( + 288, 2, 5, + [ + ( poly(0,1,4), 1 ), + ( poly(0,2,3,4), 1 ), + ( poly(0,1,2,4), 1 ), + ( poly(0,1,3,4), 1 ), + ], + name = 'tetra_rcpc', + description = """TETRA RCPC code + G1 = 1 + D + D4 + G2 = 1 + D2 + D3 + D4 + G3 = 1 + D + D2 + D4 + G4 = 1 + D + D3 + D4 +""" +) + +tetra_rcpc_tch = ConvolutionalCode( + 288, 2, 5, + [ + ( poly(0, 1, 2, 3, 4), 1 ), + ( poly(0, 1, 3, 4), 1 ), + ( poly(0, 2, 4), 1 ), + ], + name = 'tetra_rcpc_tch', + description = """TETRA RCPC TCH code +""" +) + +def gen_c(path, prefix, code): + f = open(os.path.join(path, 'conv_' + code.name + '_gen.c'), 'w') + print >>f, license + print >>f, "#include " + print >>f, "#include " + code.gen_tables(prefix, f) + +if __name__ == '__main__': + print >>sys.stderr, "Generating convolutional codes..." + prefix = "osmo_conv_gsm0503" + path = sys.argv[1] if len(sys.argv) > 1 else os.getcwd() + gen_c(path, prefix, xcch) + gen_c(path, prefix, cs2) + gen_c(path, prefix, cs3) + gen_c(path, prefix, tch_afs_12_2) + gen_c(path, prefix, tch_afs_10_2) + gen_c(path, prefix, tch_afs_7_95) + gen_c(path, prefix, tch_afs_7_4) + gen_c(path, prefix, tch_afs_6_7) + gen_c(path, prefix, tch_afs_5_9) + gen_c(path, prefix, tch_afs_5_15) + gen_c(path, prefix, tch_afs_4_75) + print >>sys.stderr, "\tdone." -- 2.5.0 From suraev at alumni.ntnu.no Mon Apr 18 20:24:09 2016 From: suraev at alumni.ntnu.no (suraev at alumni.ntnu.no) Date: Mon, 18 Apr 2016 22:24:09 +0200 Subject: [PATCH 2/4] Add concolutional code generator for *CCH In-Reply-To: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> References: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: <1461011051-11657-2-git-send-email-suraev@alumni.ntnu.no> From: Max Move convolutional code for *CCH channels from test to public API because it's useful not only for testing. Note: the code was manually generating by calling "./utils/conv_gen.py src/gsm". In future we might switch to automated compile-time generation instead. --- include/Makefile.am | 1 + include/osmocom/gsm/gsm0503.h | 37 ++++++++ src/gsm/Makefile.am | 2 +- src/gsm/conv_xcch_gen.c | 75 +++++++++++++++ src/gsm/libosmogsm.map | 1 + tests/Makefile.am | 2 +- tests/conv/conv_test.c | 207 ++++++++++++++++++------------------------ 7 files changed, 205 insertions(+), 120 deletions(-) create mode 100644 include/osmocom/gsm/gsm0503.h create mode 100644 src/gsm/conv_xcch_gen.c diff --git a/include/Makefile.am b/include/Makefile.am index 0e5ed74..e7888c5 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -64,6 +64,7 @@ nobase_include_HEADERS = \ osmocom/gsm/gsm0411_utils.h \ osmocom/gsm/gsm0480.h \ osmocom/gsm/gsm0502.h \ + osmocom/gsm/gsm0503.h \ osmocom/gsm/gsm0808.h \ osmocom/gsm/gsm48.h \ osmocom/gsm/gsm48_ie.h \ diff --git a/include/osmocom/gsm/gsm0503.h b/include/osmocom/gsm/gsm0503.h new file mode 100644 index 0000000..46d86ad --- /dev/null +++ b/include/osmocom/gsm/gsm0503.h @@ -0,0 +1,37 @@ +/* + * gsm0503.h + * + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include + +#include + +/*! \file conv_gen.h + * Osmocom convolutional encoder/decoder for xCCH channels, see 3GPP TS 05.03 + */ + +/*! \brief structure describing convolutional code xCCH + * + * Non-recursive code, flushed, not punctured code. + */ +extern const struct osmo_conv_code osmo_conv_gsm0503_xcch; diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index b0ea643..0ab2bd8 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -17,7 +17,7 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \ gsm_utils.c rsl.c gsm48.c gsm48_ie.c gsm0808.c sysinfo.c \ gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \ gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \ - lapd_core.c lapdm.c kasumi.c \ + lapd_core.c lapdm.c kasumi.c conv_xcch_gen.c \ auth_core.c auth_comp128v1.c auth_comp128v23.c \ auth_milenage.c milenage/aes-encblock.c \ milenage/aes-internal.c milenage/aes-internal-enc.c \ diff --git a/src/gsm/conv_xcch_gen.c b/src/gsm/conv_xcch_gen.c new file mode 100644 index 0000000..5b8cc5e --- /dev/null +++ b/src/gsm/conv_xcch_gen.c @@ -0,0 +1,75 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_xcch_state[][2] = { + { 0, 1 }, + { 2, 3 }, + { 4, 5 }, + { 6, 7 }, + { 8, 9 }, + { 10, 11 }, + { 12, 13 }, + { 14, 15 }, + { 0, 1 }, + { 2, 3 }, + { 4, 5 }, + { 6, 7 }, + { 8, 9 }, + { 10, 11 }, + { 12, 13 }, + { 14, 15 }, +}; + +static const uint8_t osmo_conv_gsm0503_xcch_output[][2] = { + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, +}; + +/* *CCH convolutional code: + 228 bits blocks, rate 1/2, k = 5 + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 + */ +const struct osmo_conv_code osmo_conv_gsm0503_xcch = { + .N = 2, + .K = 5, + .len = 224, + .next_output = osmo_conv_gsm0503_xcch_output, + .next_state = osmo_conv_gsm0503_xcch_state, +}; diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 6886a6c..16fb7ee 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -25,6 +25,7 @@ abis_nm_osmo_magic; abis_nm_ipa_magic; osmo_sitype_strs; +osmo_conv_gsm0503_xcch; comp128; dbm2rxlev; diff --git a/tests/Makefile.am b/tests/Makefile.am index 03506af..3aaa99b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -47,7 +47,7 @@ bits_bitcomp_test_SOURCES = bits/bitcomp_test.c bits_bitcomp_test_LDADD = $(top_builddir)/src/libosmocore.la conv_conv_test_SOURCES = conv/conv_test.c -conv_conv_test_LDADD = $(top_builddir)/src/libosmocore.la +conv_conv_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libgsmint.la gsm0808_gsm0808_test_SOURCES = gsm0808/gsm0808_test.c gsm0808_gsm0808_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index de62f23..d8779db 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -6,6 +6,7 @@ #include #include #include +#include #define MAX_LEN_BITS 512 #define MAX_LEN_BYTES (512/8) @@ -15,31 +16,6 @@ /* Test codes */ /* ------------------------------------------------------------------------ */ -/* GSM xCCH -> Non-recursive code, flushed, not punctured */ -static const uint8_t conv_gsm_xcch_next_output[][2] = { - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, -}; - -static const uint8_t conv_gsm_xcch_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, -}; - -static const struct osmo_conv_code conv_gsm_xcch = { - .N = 2, - .K = 5, - .len = 224, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, -}; - - /* GSM TCH/AFS 7.95 -> Recursive code, flushed, with puncturing */ static const uint8_t conv_gsm_tch_afs_7_95_next_output[][2] = { { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, @@ -220,18 +196,6 @@ static const struct osmo_conv_code conv_wimax_fch = { .next_state = conv_wimax_fch_next_state, }; - -/* Random code -> Non recursive code, direct truncation, non-punctured */ -static const struct osmo_conv_code conv_trunc = { - .N = 2, - .K = 5, - .len = 224, - .term = CONV_TERM_TRUNCATION, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, -}; - - /* ------------------------------------------------------------------------ */ /* Test vectors */ /* ------------------------------------------------------------------------ */ @@ -246,87 +210,6 @@ struct conv_test_vector { pbit_t vec_out[MAX_LEN_BYTES]; }; -static const struct conv_test_vector tests[] = { - { - .name = "GSM xCCH (non-recursive, flushed, not punctured)", - .code = &conv_gsm_xcch, - .in_len = 224, - .out_len = 456, - .has_vec = 1, - .vec_in = { 0xf3, 0x1d, 0xb4, 0x0c, 0x4d, 0x1d, 0x9d, 0xae, - 0xc0, 0x0a, 0x42, 0x57, 0x13, 0x60, 0x80, 0x96, - 0xef, 0x23, 0x7e, 0x4c, 0x1d, 0x96, 0x24, 0x19, - 0x17, 0xf2, 0x44, 0x99 }, - .vec_out = { 0xe9, 0x4d, 0x70, 0xab, 0xa2, 0x87, 0xf0, 0xe7, - 0x04, 0x14, 0x7c, 0xab, 0xaf, 0x6b, 0xa1, 0x16, - 0xeb, 0x30, 0x00, 0xde, 0xc8, 0xfd, 0x0b, 0x85, - 0x80, 0x41, 0x4a, 0xcc, 0xd3, 0xc0, 0xd0, 0xb6, - 0x26, 0xe5, 0x4e, 0x32, 0x49, 0x69, 0x38, 0x17, - 0x33, 0xab, 0xaf, 0xb6, 0xc1, 0x08, 0xf3, 0x9f, - 0x8c, 0x75, 0x6a, 0x4e, 0x08, 0xc4, 0x20, 0x5f, - 0x8f }, - }, - { - .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)", - .code = &conv_gsm_tch_afs_7_95, - .in_len = 165, - .out_len = 448, - .has_vec = 1, - .vec_in = { 0x87, 0x66, 0xc3, 0x58, 0x09, 0xd4, 0x06, 0x59, - 0x10, 0xbf, 0x6b, 0x7f, 0xc8, 0xed, 0x72, 0xaa, - 0xc1, 0x3d, 0xf3, 0x1e, 0xb0 }, - .vec_out = { 0x92, 0xbc, 0xde, 0xa0, 0xde, 0xbe, 0x01, 0x2f, - 0xbe, 0xe4, 0x61, 0x32, 0x4d, 0x4f, 0xdc, 0x41, - 0x43, 0x0d, 0x15, 0xe0, 0x23, 0xdd, 0x18, 0x91, - 0xe5, 0x36, 0x2d, 0xb7, 0xd9, 0x78, 0xb8, 0xb1, - 0xb7, 0xcb, 0x2f, 0xc0, 0x52, 0x8f, 0xe2, 0x8c, - 0x6f, 0xa6, 0x79, 0x88, 0xed, 0x0c, 0x2e, 0x9e, - 0xa1, 0x5f, 0x45, 0x4a, 0xfb, 0xe6, 0x5a, 0x9c }, - }, - { - .name = "GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)", - .code = &conv_gmr1_tch3_speech, - .in_len = 48, - .out_len = 72, - .has_vec = 1, - .vec_in = { 0x4d, 0xcb, 0xfc, 0x72, 0xf4, 0x8c }, - .vec_out = { 0xc0, 0x86, 0x63, 0x4b, 0x8b, 0xd4, 0x6a, 0x76, 0xb2 }, - }, - { - .name = "WiMax FCH (non-recursive, tail-biting, not punctured)", - .code = &conv_wimax_fch, - .in_len = 48, - .out_len = 96, - .has_vec = 1, - .vec_in = { 0xfc, 0xa0, 0xa0, 0xfc, 0xa0, 0xa0 }, - .vec_out = { 0x19, 0x42, 0x8a, 0xed, 0x21, 0xed, 0x19, 0x42, - 0x8a, 0xed, 0x21, 0xed }, - }, - { - .name = "??? (non-recursive, direct truncation, not punctured)", - .code = &conv_trunc, - .in_len = 224, - .out_len = 448, - .has_vec = 1, - .vec_in = { 0xe5, 0xe0, 0x85, 0x7e, 0xf7, 0x08, 0x19, 0x5a, - 0xb9, 0xad, 0x82, 0x37, 0x98, 0x8b, 0x26, 0xb9, - 0x81, 0x26, 0x9c, 0x75, 0xaf, 0xf3, 0xcb, 0x07, - 0xac, 0x63, 0xe2, 0x9c, - }, - .vec_out = { 0xea, 0x3b, 0x55, 0x0c, 0xd3, 0xf7, 0x85, 0x69, - 0xe5, 0x79, 0x83, 0xd3, 0xc3, 0x9f, 0xb8, 0x61, - 0x21, 0x63, 0x51, 0x18, 0xac, 0xcd, 0x32, 0x49, - 0x53, 0x5c, 0x13, 0x1d, 0xbe, 0x05, 0x11, 0x63, - 0x5c, 0xc3, 0x42, 0x05, 0x1c, 0x68, 0x0a, 0xb4, - 0x61, 0x15, 0xaa, 0x4d, 0x94, 0xed, 0xb3, 0x3a, - 0x5d, 0x1b, 0x09, 0xc2, 0x99, 0x01, 0xec, 0x68 }, - }, - { /* end */ }, -}; - - - - /* ------------------------------------------------------------------------ */ /* Main */ /* ------------------------------------------------------------------------ */ @@ -345,6 +228,94 @@ int main(int argc, char *argv[]) ubit_t *bu0, *bu1; sbit_t *bs; +/* Random code -> Non recursive code, direct truncation, non-punctured */ + const struct osmo_conv_code conv_trunc = { + .N = 2, + .K = 5, + .len = 224, + .term = CONV_TERM_TRUNCATION, + .next_output = osmo_conv_gsm0503_xcch.next_output, + .next_state = osmo_conv_gsm0503_xcch.next_state, + }; + + const struct conv_test_vector tests[] = { + { + .name = "GSM xCCH (non-recursive, flushed, not punctured)", + .code = &osmo_conv_gsm0503_xcch, + .in_len = 224, + .out_len = 456, + .has_vec = 1, + .vec_in = { 0xf3, 0x1d, 0xb4, 0x0c, 0x4d, 0x1d, 0x9d, 0xae, + 0xc0, 0x0a, 0x42, 0x57, 0x13, 0x60, 0x80, 0x96, + 0xef, 0x23, 0x7e, 0x4c, 0x1d, 0x96, 0x24, 0x19, + 0x17, 0xf2, 0x44, 0x99 }, + .vec_out = { 0xe9, 0x4d, 0x70, 0xab, 0xa2, 0x87, 0xf0, 0xe7, + 0x04, 0x14, 0x7c, 0xab, 0xaf, 0x6b, 0xa1, 0x16, + 0xeb, 0x30, 0x00, 0xde, 0xc8, 0xfd, 0x0b, 0x85, + 0x80, 0x41, 0x4a, 0xcc, 0xd3, 0xc0, 0xd0, 0xb6, + 0x26, 0xe5, 0x4e, 0x32, 0x49, 0x69, 0x38, 0x17, + 0x33, 0xab, 0xaf, 0xb6, 0xc1, 0x08, 0xf3, 0x9f, + 0x8c, 0x75, 0x6a, 0x4e, 0x08, 0xc4, 0x20, 0x5f, + 0x8f }, + }, + { + .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)", + .code = &conv_gsm_tch_afs_7_95, + .in_len = 165, + .out_len = 448, + .has_vec = 1, + .vec_in = { 0x87, 0x66, 0xc3, 0x58, 0x09, 0xd4, 0x06, 0x59, + 0x10, 0xbf, 0x6b, 0x7f, 0xc8, 0xed, 0x72, 0xaa, + 0xc1, 0x3d, 0xf3, 0x1e, 0xb0 }, + .vec_out = { 0x92, 0xbc, 0xde, 0xa0, 0xde, 0xbe, 0x01, 0x2f, + 0xbe, 0xe4, 0x61, 0x32, 0x4d, 0x4f, 0xdc, 0x41, + 0x43, 0x0d, 0x15, 0xe0, 0x23, 0xdd, 0x18, 0x91, + 0xe5, 0x36, 0x2d, 0xb7, 0xd9, 0x78, 0xb8, 0xb1, + 0xb7, 0xcb, 0x2f, 0xc0, 0x52, 0x8f, 0xe2, 0x8c, + 0x6f, 0xa6, 0x79, 0x88, 0xed, 0x0c, 0x2e, 0x9e, + 0xa1, 0x5f, 0x45, 0x4a, 0xfb, 0xe6, 0x5a, 0x9c }, + }, + { + .name = "GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)", + .code = &conv_gmr1_tch3_speech, + .in_len = 48, + .out_len = 72, + .has_vec = 1, + .vec_in = { 0x4d, 0xcb, 0xfc, 0x72, 0xf4, 0x8c }, + .vec_out = { 0xc0, 0x86, 0x63, 0x4b, 0x8b, 0xd4, 0x6a, 0x76, 0xb2 }, + }, + { + .name = "WiMax FCH (non-recursive, tail-biting, not punctured)", + .code = &conv_wimax_fch, + .in_len = 48, + .out_len = 96, + .has_vec = 1, + .vec_in = { 0xfc, 0xa0, 0xa0, 0xfc, 0xa0, 0xa0 }, + .vec_out = { 0x19, 0x42, 0x8a, 0xed, 0x21, 0xed, 0x19, 0x42, + 0x8a, 0xed, 0x21, 0xed }, + }, + { + .name = "??? (non-recursive, direct truncation, not punctured)", + .code = &conv_trunc, + .in_len = 224, + .out_len = 448, + .has_vec = 1, + .vec_in = { 0xe5, 0xe0, 0x85, 0x7e, 0xf7, 0x08, 0x19, 0x5a, + 0xb9, 0xad, 0x82, 0x37, 0x98, 0x8b, 0x26, 0xb9, + 0x81, 0x26, 0x9c, 0x75, 0xaf, 0xf3, 0xcb, 0x07, + 0xac, 0x63, 0xe2, 0x9c, + }, + .vec_out = { 0xea, 0x3b, 0x55, 0x0c, 0xd3, 0xf7, 0x85, 0x69, + 0xe5, 0x79, 0x83, 0xd3, 0xc3, 0x9f, 0xb8, 0x61, + 0x21, 0x63, 0x51, 0x18, 0xac, 0xcd, 0x32, 0x49, + 0x53, 0x5c, 0x13, 0x1d, 0xbe, 0x05, 0x11, 0x63, + 0x5c, 0xc3, 0x42, 0x05, 0x1c, 0x68, 0x0a, 0xb4, + 0x61, 0x15, 0xaa, 0x4d, 0x94, 0xed, 0xb3, 0x3a, + 0x5d, 0x1b, 0x09, 0xc2, 0x99, 0x01, 0xec, 0x68 }, + }, + { /* end */ }, + }; + srandom(time(NULL)); bu0 = malloc(sizeof(ubit_t) * MAX_LEN_BITS); -- 2.5.0 From suraev at alumni.ntnu.no Mon Apr 18 20:26:13 2016 From: suraev at alumni.ntnu.no (suraev at alumni.ntnu.no) Date: Mon, 18 Apr 2016 22:26:13 +0200 Subject: [PATCH 1/2] Add convolutional code generators for CS2/3 Message-ID: <1461011174-11851-1-git-send-email-suraev@alumni.ntnu.no> From: Max --- include/osmocom/gsm/gsm0503.h | 5 + src/gsm/Makefile.am | 1 + src/gsm/conv_cs2_gen.c | 211 +++++++++++++++++++++++++++++ src/gsm/conv_cs3_gen.c | 299 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 516 insertions(+) create mode 100644 src/gsm/conv_cs2_gen.c create mode 100644 src/gsm/conv_cs3_gen.c diff --git a/include/osmocom/gsm/gsm0503.h b/include/osmocom/gsm/gsm0503.h index 46d86ad..764e2d1 100644 --- a/include/osmocom/gsm/gsm0503.h +++ b/include/osmocom/gsm/gsm0503.h @@ -35,3 +35,8 @@ * Non-recursive code, flushed, not punctured code. */ extern const struct osmo_conv_code osmo_conv_gsm0503_xcch; + +/*! \brief structures describing convolutional codes CS2/3 + */ +extern const struct osmo_conv_code osmo_conv_gsm0503_cs2; +extern const struct osmo_conv_code osmo_conv_gsm0503_cs3; diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index 0ab2bd8..53d16b3 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -18,6 +18,7 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \ gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \ gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \ lapd_core.c lapdm.c kasumi.c conv_xcch_gen.c \ + conv_cs2_gen.c conv_cs3_gen.c \ auth_core.c auth_comp128v1.c auth_comp128v23.c \ auth_milenage.c milenage/aes-encblock.c \ milenage/aes-internal.c milenage/aes-internal-enc.c \ diff --git a/src/gsm/conv_cs2_gen.c b/src/gsm/conv_cs2_gen.c new file mode 100644 index 0000000..1ecca96 --- /dev/null +++ b/src/gsm/conv_cs2_gen.c @@ -0,0 +1,211 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_cs2_state[][2] = { + { 0, 1 }, + { 2, 3 }, + { 4, 5 }, + { 6, 7 }, + { 8, 9 }, + { 10, 11 }, + { 12, 13 }, + { 14, 15 }, + { 0, 1 }, + { 2, 3 }, + { 4, 5 }, + { 6, 7 }, + { 8, 9 }, + { 10, 11 }, + { 12, 13 }, + { 14, 15 }, +}; + +static const uint8_t osmo_conv_gsm0503_cs2_output[][2] = { + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, +}; + +static const int osmo_conv_gsm0503_cs2_puncture[] = { + 15, + 19, + 23, + 27, + 31, + 35, + 43, + 47, + 51, + 55, + 59, + 63, + 67, + 71, + 75, + 79, + 83, + 91, + 95, + 99, + 103, + 107, + 111, + 115, + 119, + 123, + 127, + 131, + 139, + 143, + 147, + 151, + 155, + 159, + 163, + 167, + 171, + 175, + 179, + 187, + 191, + 195, + 199, + 203, + 207, + 211, + 215, + 219, + 223, + 227, + 235, + 239, + 243, + 247, + 251, + 255, + 259, + 263, + 267, + 271, + 275, + 283, + 287, + 291, + 295, + 299, + 303, + 307, + 311, + 315, + 319, + 323, + 331, + 335, + 339, + 343, + 347, + 351, + 355, + 359, + 363, + 367, + 371, + 379, + 383, + 387, + 391, + 395, + 399, + 403, + 407, + 411, + 415, + 419, + 427, + 431, + 435, + 439, + 443, + 447, + 451, + 455, + 459, + 463, + 467, + 475, + 479, + 483, + 487, + 491, + 495, + 499, + 503, + 507, + 511, + 515, + 523, + 527, + 531, + 535, + 539, + 543, + 547, + 551, + 555, + 559, + 563, + 571, + 575, + 579, + 583, + 587, + -1, +}; + +/* CS2 convolutional code: + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 + */ +const struct osmo_conv_code osmo_conv_gsm0503_cs2 = { + .N = 2, + .K = 5, + .len = 290, + .next_output = osmo_conv_gsm0503_cs2_output, + .next_state = osmo_conv_gsm0503_cs2_state, + .puncture = osmo_conv_gsm0503_cs2_puncture, +}; diff --git a/src/gsm/conv_cs3_gen.c b/src/gsm/conv_cs3_gen.c new file mode 100644 index 0000000..550452a --- /dev/null +++ b/src/gsm/conv_cs3_gen.c @@ -0,0 +1,299 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_cs3_state[][2] = { + { 0, 1 }, + { 2, 3 }, + { 4, 5 }, + { 6, 7 }, + { 8, 9 }, + { 10, 11 }, + { 12, 13 }, + { 14, 15 }, + { 0, 1 }, + { 2, 3 }, + { 4, 5 }, + { 6, 7 }, + { 8, 9 }, + { 10, 11 }, + { 12, 13 }, + { 14, 15 }, +}; + +static const uint8_t osmo_conv_gsm0503_cs3_output[][2] = { + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 3, 0 }, + { 2, 1 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, +}; + +static const int osmo_conv_gsm0503_cs3_puncture[] = { + 15, + 17, + 21, + 23, + 27, + 29, + 33, + 35, + 39, + 41, + 45, + 47, + 51, + 53, + 57, + 59, + 63, + 65, + 69, + 71, + 75, + 77, + 81, + 83, + 87, + 89, + 93, + 95, + 99, + 101, + 105, + 107, + 111, + 113, + 117, + 119, + 123, + 125, + 129, + 131, + 135, + 137, + 141, + 143, + 147, + 149, + 153, + 155, + 159, + 161, + 165, + 167, + 171, + 173, + 177, + 179, + 183, + 185, + 189, + 191, + 195, + 197, + 201, + 203, + 207, + 209, + 213, + 215, + 219, + 221, + 225, + 227, + 231, + 233, + 237, + 239, + 243, + 245, + 249, + 251, + 255, + 257, + 261, + 263, + 267, + 269, + 273, + 275, + 279, + 281, + 285, + 287, + 291, + 293, + 297, + 299, + 303, + 305, + 309, + 311, + 315, + 317, + 321, + 323, + 327, + 329, + 333, + 335, + 339, + 341, + 345, + 347, + 351, + 353, + 357, + 359, + 363, + 365, + 369, + 371, + 375, + 377, + 381, + 383, + 387, + 389, + 393, + 395, + 399, + 401, + 405, + 407, + 411, + 413, + 417, + 419, + 423, + 425, + 429, + 431, + 435, + 437, + 441, + 443, + 447, + 449, + 453, + 455, + 459, + 461, + 465, + 467, + 471, + 473, + 477, + 479, + 483, + 485, + 489, + 491, + 495, + 497, + 501, + 503, + 507, + 509, + 513, + 515, + 519, + 521, + 525, + 527, + 531, + 533, + 537, + 539, + 543, + 545, + 549, + 551, + 555, + 557, + 561, + 563, + 567, + 569, + 573, + 575, + 579, + 581, + 585, + 587, + 591, + 593, + 597, + 599, + 603, + 605, + 609, + 611, + 615, + 617, + 621, + 623, + 627, + 629, + 633, + 635, + 639, + 641, + 645, + 647, + 651, + 653, + 657, + 659, + 663, + 665, + 669, + 671, + -1, +}; + +/* CS3 convolutional code: + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 + */ +const struct osmo_conv_code osmo_conv_gsm0503_cs3 = { + .N = 2, + .K = 5, + .len = 334, + .next_output = osmo_conv_gsm0503_cs3_output, + .next_state = osmo_conv_gsm0503_cs3_state, + .puncture = osmo_conv_gsm0503_cs3_puncture, +}; -- 2.5.0 From suraev at alumni.ntnu.no Mon Apr 18 20:26:14 2016 From: suraev at alumni.ntnu.no (suraev at alumni.ntnu.no) Date: Mon, 18 Apr 2016 22:26:14 +0200 Subject: [PATCH 2/2] Add convolutional code for TCH/AFS In-Reply-To: <1461011174-11851-1-git-send-email-suraev@alumni.ntnu.no> References: <1461011174-11851-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: <1461011174-11851-2-git-send-email-suraev@alumni.ntnu.no> From: Max Replace implementation in tests with added code. --- include/osmocom/gsm/gsm0503.h | 32 +++++ src/gsm/Makefile.am | 4 + src/gsm/conv_tch_afs_10_2_gen.c | 284 ++++++++++++++++++++++++++++++++++++++++ src/gsm/conv_tch_afs_12_2_gen.c | 150 +++++++++++++++++++++ src/gsm/conv_tch_afs_4_75_gen.c | 275 ++++++++++++++++++++++++++++++++++++++ src/gsm/conv_tch_afs_5_15_gen.c | 209 +++++++++++++++++++++++++++++ src/gsm/conv_tch_afs_5_9_gen.c | 260 ++++++++++++++++++++++++++++++++++++ src/gsm/conv_tch_afs_6_7_gen.c | 219 +++++++++++++++++++++++++++++++ src/gsm/conv_tch_afs_7_4_gen.c | 116 ++++++++++++++++ src/gsm/conv_tch_afs_7_95_gen.c | 251 +++++++++++++++++++++++++++++++++++ tests/conv/conv_test.c | 78 +---------- 11 files changed, 1801 insertions(+), 77 deletions(-) create mode 100644 src/gsm/conv_tch_afs_10_2_gen.c create mode 100644 src/gsm/conv_tch_afs_12_2_gen.c create mode 100644 src/gsm/conv_tch_afs_4_75_gen.c create mode 100644 src/gsm/conv_tch_afs_5_15_gen.c create mode 100644 src/gsm/conv_tch_afs_5_9_gen.c create mode 100644 src/gsm/conv_tch_afs_6_7_gen.c create mode 100644 src/gsm/conv_tch_afs_7_4_gen.c create mode 100644 src/gsm/conv_tch_afs_7_95_gen.c diff --git a/include/osmocom/gsm/gsm0503.h b/include/osmocom/gsm/gsm0503.h index 764e2d1..4722e7e 100644 --- a/include/osmocom/gsm/gsm0503.h +++ b/include/osmocom/gsm/gsm0503.h @@ -40,3 +40,35 @@ extern const struct osmo_conv_code osmo_conv_gsm0503_xcch; */ extern const struct osmo_conv_code osmo_conv_gsm0503_cs2; extern const struct osmo_conv_code osmo_conv_gsm0503_cs3; + +/*! \brief structure describing convolutional code TCH/AFS 12.2 + */ +extern const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_12_2; + +/*! \brief structure describing convolutional code TCH/AFS 10.2 + */ +extern const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_10_2; + +/*! \brief structure describing convolutional code TCH/AFS 7.95 + */ +extern const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_7_95; + +/*! \brief structure describing convolutional code TCH/AFS 7.4 + */ +extern const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_7_4; + +/*! \brief structure describing convolutional code TCH/AFS 6.7 + */ +extern const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_6_7; + +/*! \brief structure describing convolutional code TCH/AFS 5.9 + */ +extern const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_5_9; + +/*! \brief structure describing convolutional code TCH/AFS 5.15 + */ +extern const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_5_15; + +/*! \brief structure describing convolutional code TCH/AFS 4.75 + */ +extern const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_4_75; diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index 53d16b3..101b532 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -19,6 +19,10 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \ gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \ lapd_core.c lapdm.c kasumi.c conv_xcch_gen.c \ conv_cs2_gen.c conv_cs3_gen.c \ + conv_tch_afs_12_2_gen.c conv_tch_afs_10_2_gen.c \ + conv_tch_afs_7_95_gen.c conv_tch_afs_7_4_gen.c \ + conv_tch_afs_6_7_gen.c conv_tch_afs_5_9_gen.c \ + conv_tch_afs_5_15_gen.c conv_tch_afs_4_75_gen.c \ auth_core.c auth_comp128v1.c auth_comp128v23.c \ auth_milenage.c milenage/aes-encblock.c \ milenage/aes-internal.c milenage/aes-internal-enc.c \ diff --git a/src/gsm/conv_tch_afs_10_2_gen.c b/src/gsm/conv_tch_afs_10_2_gen.c new file mode 100644 index 0000000..d67b455 --- /dev/null +++ b/src/gsm/conv_tch_afs_10_2_gen.c @@ -0,0 +1,284 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_tch_afs_10_2_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_10_2_output[][2] = { + { 0, 7 }, + { 2, 5 }, + { 4, 3 }, + { 6, 1 }, + { 2, 5 }, + { 0, 7 }, + { 6, 1 }, + { 4, 3 }, + { 0, 7 }, + { 2, 5 }, + { 4, 3 }, + { 6, 1 }, + { 2, 5 }, + { 0, 7 }, + { 6, 1 }, + { 4, 3 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_10_2_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_10_2_term_output[] = { + 0, 5, 3, 6, 5, 0, 6, 3, 7, 2, 4, 1, 2, 7, 1, 4, +}; + +static const int osmo_conv_gsm0503_tch_afs_10_2_puncture[] = { + 1, + 4, + 7, + 10, + 16, + 19, + 22, + 28, + 31, + 34, + 40, + 43, + 46, + 52, + 55, + 58, + 64, + 67, + 70, + 76, + 79, + 82, + 88, + 91, + 94, + 100, + 103, + 106, + 112, + 115, + 118, + 124, + 127, + 130, + 136, + 139, + 142, + 148, + 151, + 154, + 160, + 163, + 166, + 172, + 175, + 178, + 184, + 187, + 190, + 196, + 199, + 202, + 208, + 211, + 214, + 220, + 223, + 226, + 232, + 235, + 238, + 244, + 247, + 250, + 256, + 259, + 262, + 268, + 271, + 274, + 280, + 283, + 286, + 292, + 295, + 298, + 304, + 307, + 310, + 316, + 319, + 322, + 325, + 328, + 331, + 334, + 337, + 340, + 343, + 346, + 349, + 352, + 355, + 358, + 361, + 364, + 367, + 370, + 373, + 376, + 379, + 382, + 385, + 388, + 391, + 394, + 397, + 400, + 403, + 406, + 409, + 412, + 415, + 418, + 421, + 424, + 427, + 430, + 433, + 436, + 439, + 442, + 445, + 448, + 451, + 454, + 457, + 460, + 463, + 466, + 469, + 472, + 475, + 478, + 481, + 484, + 487, + 490, + 493, + 496, + 499, + 502, + 505, + 508, + 511, + 514, + 517, + 520, + 523, + 526, + 529, + 532, + 535, + 538, + 541, + 544, + 547, + 550, + 553, + 556, + 559, + 562, + 565, + 568, + 571, + 574, + 577, + 580, + 583, + 586, + 589, + 592, + 595, + 598, + 601, + 604, + 607, + 609, + 610, + 613, + 616, + 619, + 621, + 622, + 625, + 627, + 628, + 631, + 633, + 634, + 636, + 637, + 639, + 640, + -1, +}; + +/* TCH/AFS 10.2 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + */ +const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_10_2 = { + .N = 3, + .K = 5, + .len = 210, + .next_output = osmo_conv_gsm0503_tch_afs_10_2_output, + .next_state = osmo_conv_gsm0503_tch_afs_10_2_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_10_2_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_10_2_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_10_2_puncture, +}; diff --git a/src/gsm/conv_tch_afs_12_2_gen.c b/src/gsm/conv_tch_afs_12_2_gen.c new file mode 100644 index 0000000..b09ea93 --- /dev/null +++ b/src/gsm/conv_tch_afs_12_2_gen.c @@ -0,0 +1,150 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_tch_afs_12_2_state[][2] = { + { 0, 1 }, + { 2, 3 }, + { 4, 5 }, + { 6, 7 }, + { 9, 8 }, + { 11, 10 }, + { 13, 12 }, + { 15, 14 }, + { 1, 0 }, + { 3, 2 }, + { 5, 4 }, + { 7, 6 }, + { 8, 9 }, + { 10, 11 }, + { 12, 13 }, + { 14, 15 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_12_2_output[][2] = { + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_12_2_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_12_2_term_output[] = { + 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2, 0, 1, 0, 1, +}; + +static const int osmo_conv_gsm0503_tch_afs_12_2_puncture[] = { + 321, + 325, + 329, + 333, + 337, + 341, + 345, + 349, + 353, + 357, + 361, + 363, + 365, + 369, + 373, + 377, + 379, + 381, + 385, + 389, + 393, + 395, + 397, + 401, + 405, + 409, + 411, + 413, + 417, + 421, + 425, + 427, + 429, + 433, + 437, + 441, + 443, + 445, + 449, + 453, + 457, + 459, + 461, + 465, + 469, + 473, + 475, + 477, + 481, + 485, + 489, + 491, + 493, + 495, + 497, + 499, + 501, + 503, + 505, + 507, + -1, +}; + +/* TCH/AFS 12.2 convolutional code: + 250 bits block, rate 1/2, punctured + G0/G0 = 1 + G1/G0 = 1 + D + D3 + D4 / 1 + D3 + D4 + */ +const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_12_2 = { + .N = 2, + .K = 5, + .len = 250, + .next_output = osmo_conv_gsm0503_tch_afs_12_2_output, + .next_state = osmo_conv_gsm0503_tch_afs_12_2_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_12_2_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_12_2_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_12_2_puncture, +}; diff --git a/src/gsm/conv_tch_afs_4_75_gen.c b/src/gsm/conv_tch_afs_4_75_gen.c new file mode 100644 index 0000000..bbd35dd --- /dev/null +++ b/src/gsm/conv_tch_afs_4_75_gen.c @@ -0,0 +1,275 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_tch_afs_4_75_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 17, 16 }, + { 18, 19 }, + { 20, 21 }, + { 23, 22 }, + { 24, 25 }, + { 27, 26 }, + { 29, 28 }, + { 30, 31 }, + { 32, 33 }, + { 35, 34 }, + { 37, 36 }, + { 38, 39 }, + { 41, 40 }, + { 42, 43 }, + { 44, 45 }, + { 47, 46 }, + { 49, 48 }, + { 50, 51 }, + { 52, 53 }, + { 55, 54 }, + { 56, 57 }, + { 59, 58 }, + { 61, 60 }, + { 62, 63 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, + { 16, 17 }, + { 19, 18 }, + { 21, 20 }, + { 22, 23 }, + { 25, 24 }, + { 26, 27 }, + { 28, 29 }, + { 31, 30 }, + { 33, 32 }, + { 34, 35 }, + { 36, 37 }, + { 39, 38 }, + { 40, 41 }, + { 43, 42 }, + { 45, 44 }, + { 46, 47 }, + { 48, 49 }, + { 51, 50 }, + { 53, 52 }, + { 54, 55 }, + { 57, 56 }, + { 58, 59 }, + { 60, 61 }, + { 63, 62 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_4_75_output[][2] = { + { 0, 31 }, + { 24, 7 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 0, 31 }, + { 24, 7 }, + { 24, 7 }, + { 0, 31 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 24, 7 }, + { 0, 31 }, + { 24, 7 }, + { 0, 31 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 24, 7 }, + { 0, 31 }, + { 0, 31 }, + { 24, 7 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 0, 31 }, + { 24, 7 }, + { 0, 31 }, + { 24, 7 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 0, 31 }, + { 24, 7 }, + { 24, 7 }, + { 0, 31 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 24, 7 }, + { 0, 31 }, + { 24, 7 }, + { 0, 31 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 24, 7 }, + { 0, 31 }, + { 0, 31 }, + { 24, 7 }, + { 4, 27 }, + { 28, 3 }, + { 4, 27 }, + { 28, 3 }, + { 0, 31 }, + { 24, 7 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_4_75_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_4_75_term_output[] = { + 0, 7, 27, 28, 27, 28, 0, 7, 7, 0, 28, 27, 28, 27, 7, 0, 24, 31, 3, 4, 3, 4, 24, 31, 31, 24, 4, 3, 4, 3, 31, 24, 31, 24, 4, 3, 4, 3, 31, 24, 24, 31, 3, 4, 3, 4, 24, 31, 7, 0, 28, 27, 28, 27, 7, 0, 0, 7, 27, 28, 27, 28, 0, 7, +}; + +static const int osmo_conv_gsm0503_tch_afs_4_75_puncture[] = { + 0, + 1, + 2, + 4, + 5, + 7, + 9, + 15, + 25, + 35, + 45, + 55, + 65, + 75, + 85, + 95, + 105, + 115, + 125, + 135, + 145, + 155, + 165, + 175, + 185, + 195, + 205, + 215, + 225, + 235, + 245, + 255, + 265, + 275, + 285, + 295, + 305, + 315, + 325, + 335, + 345, + 355, + 365, + 375, + 385, + 395, + 400, + 405, + 410, + 415, + 420, + 425, + 430, + 435, + 440, + 445, + 450, + 455, + 459, + 460, + 465, + 470, + 475, + 479, + 480, + 485, + 490, + 495, + 499, + 500, + 505, + 509, + 510, + 515, + 517, + 519, + 520, + 522, + 524, + 525, + 526, + 527, + 529, + 530, + 531, + 532, + 534, + -1, +}; + +/* TCH/AFS 4.75 kbits convolutional code: + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 + */ +const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_4_75 = { + .N = 5, + .K = 7, + .len = 101, + .next_output = osmo_conv_gsm0503_tch_afs_4_75_output, + .next_state = osmo_conv_gsm0503_tch_afs_4_75_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_4_75_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_4_75_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_4_75_puncture, +}; diff --git a/src/gsm/conv_tch_afs_5_15_gen.c b/src/gsm/conv_tch_afs_5_15_gen.c new file mode 100644 index 0000000..d00dd5c --- /dev/null +++ b/src/gsm/conv_tch_afs_5_15_gen.c @@ -0,0 +1,209 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_tch_afs_5_15_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_5_15_output[][2] = { + { 0, 31 }, + { 4, 27 }, + { 24, 7 }, + { 28, 3 }, + { 4, 27 }, + { 0, 31 }, + { 28, 3 }, + { 24, 7 }, + { 0, 31 }, + { 4, 27 }, + { 24, 7 }, + { 28, 3 }, + { 4, 27 }, + { 0, 31 }, + { 28, 3 }, + { 24, 7 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_5_15_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_5_15_term_output[] = { + 0, 27, 7, 28, 27, 0, 28, 7, 31, 4, 24, 3, 4, 31, 3, 24, +}; + +static const int osmo_conv_gsm0503_tch_afs_5_15_puncture[] = { + 0, + 4, + 5, + 9, + 10, + 14, + 15, + 20, + 25, + 30, + 35, + 40, + 50, + 60, + 70, + 80, + 90, + 100, + 110, + 120, + 130, + 140, + 150, + 160, + 170, + 180, + 190, + 200, + 210, + 220, + 230, + 240, + 250, + 260, + 270, + 280, + 290, + 300, + 310, + 315, + 320, + 325, + 330, + 334, + 335, + 340, + 344, + 345, + 350, + 354, + 355, + 360, + 364, + 365, + 370, + 374, + 375, + 380, + 384, + 385, + 390, + 394, + 395, + 400, + 404, + 405, + 410, + 414, + 415, + 420, + 424, + 425, + 430, + 434, + 435, + 440, + 444, + 445, + 450, + 454, + 455, + 460, + 464, + 465, + 470, + 474, + 475, + 480, + 484, + 485, + 490, + 494, + 495, + 500, + 504, + 505, + 510, + 514, + 515, + 520, + 524, + 525, + 529, + 530, + 534, + 535, + 539, + 540, + 544, + 545, + 549, + 550, + 554, + 555, + 559, + 560, + 564, + -1, +}; + +/* TCH/AFS 5.15 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 + */ +const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_5_15 = { + .N = 5, + .K = 5, + .len = 109, + .next_output = osmo_conv_gsm0503_tch_afs_5_15_output, + .next_state = osmo_conv_gsm0503_tch_afs_5_15_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_5_15_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_5_15_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_5_15_puncture, +}; diff --git a/src/gsm/conv_tch_afs_5_9_gen.c b/src/gsm/conv_tch_afs_5_9_gen.c new file mode 100644 index 0000000..d182adb --- /dev/null +++ b/src/gsm/conv_tch_afs_5_9_gen.c @@ -0,0 +1,260 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_tch_afs_5_9_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 17, 16 }, + { 18, 19 }, + { 20, 21 }, + { 23, 22 }, + { 24, 25 }, + { 27, 26 }, + { 29, 28 }, + { 30, 31 }, + { 32, 33 }, + { 35, 34 }, + { 37, 36 }, + { 38, 39 }, + { 41, 40 }, + { 42, 43 }, + { 44, 45 }, + { 47, 46 }, + { 49, 48 }, + { 50, 51 }, + { 52, 53 }, + { 55, 54 }, + { 56, 57 }, + { 59, 58 }, + { 61, 60 }, + { 62, 63 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, + { 16, 17 }, + { 19, 18 }, + { 21, 20 }, + { 22, 23 }, + { 25, 24 }, + { 26, 27 }, + { 28, 29 }, + { 31, 30 }, + { 33, 32 }, + { 34, 35 }, + { 36, 37 }, + { 39, 38 }, + { 40, 41 }, + { 43, 42 }, + { 45, 44 }, + { 46, 47 }, + { 48, 49 }, + { 51, 50 }, + { 53, 52 }, + { 54, 55 }, + { 57, 56 }, + { 58, 59 }, + { 60, 61 }, + { 63, 62 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_5_9_output[][2] = { + { 0, 15 }, + { 8, 7 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 0, 15 }, + { 8, 7 }, + { 8, 7 }, + { 0, 15 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 8, 7 }, + { 0, 15 }, + { 8, 7 }, + { 0, 15 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 8, 7 }, + { 0, 15 }, + { 0, 15 }, + { 8, 7 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 0, 15 }, + { 8, 7 }, + { 0, 15 }, + { 8, 7 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 0, 15 }, + { 8, 7 }, + { 8, 7 }, + { 0, 15 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 8, 7 }, + { 0, 15 }, + { 8, 7 }, + { 0, 15 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 8, 7 }, + { 0, 15 }, + { 0, 15 }, + { 8, 7 }, + { 4, 11 }, + { 12, 3 }, + { 4, 11 }, + { 12, 3 }, + { 0, 15 }, + { 8, 7 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_5_9_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_5_9_term_output[] = { + 0, 7, 11, 12, 11, 12, 0, 7, 7, 0, 12, 11, 12, 11, 7, 0, 8, 15, 3, 4, 3, 4, 8, 15, 15, 8, 4, 3, 4, 3, 15, 8, 15, 8, 4, 3, 4, 3, 15, 8, 8, 15, 3, 4, 3, 4, 8, 15, 7, 0, 12, 11, 12, 11, 7, 0, 0, 7, 11, 12, 11, 12, 0, 7, +}; + +static const int osmo_conv_gsm0503_tch_afs_5_9_puncture[] = { + 0, + 1, + 3, + 5, + 7, + 11, + 15, + 31, + 47, + 63, + 79, + 95, + 111, + 127, + 143, + 159, + 175, + 191, + 207, + 223, + 239, + 255, + 271, + 287, + 303, + 319, + 327, + 331, + 335, + 343, + 347, + 351, + 359, + 363, + 367, + 375, + 379, + 383, + 391, + 395, + 399, + 407, + 411, + 415, + 423, + 427, + 431, + 439, + 443, + 447, + 455, + 459, + 463, + 467, + 471, + 475, + 479, + 483, + 487, + 491, + 495, + 499, + 503, + 507, + 509, + 511, + 512, + 513, + 515, + 516, + 517, + 519, + -1, +}; + +/* TCH/AFS 5.9 kbits convolutional code: + 124 bits + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 + */ +const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_5_9 = { + .N = 4, + .K = 7, + .len = 124, + .next_output = osmo_conv_gsm0503_tch_afs_5_9_output, + .next_state = osmo_conv_gsm0503_tch_afs_5_9_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_5_9_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_5_9_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_5_9_puncture, +}; diff --git a/src/gsm/conv_tch_afs_6_7_gen.c b/src/gsm/conv_tch_afs_6_7_gen.c new file mode 100644 index 0000000..8baedaa --- /dev/null +++ b/src/gsm/conv_tch_afs_6_7_gen.c @@ -0,0 +1,219 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_tch_afs_6_7_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_6_7_output[][2] = { + { 0, 15 }, + { 4, 11 }, + { 8, 7 }, + { 12, 3 }, + { 4, 11 }, + { 0, 15 }, + { 12, 3 }, + { 8, 7 }, + { 0, 15 }, + { 4, 11 }, + { 8, 7 }, + { 12, 3 }, + { 4, 11 }, + { 0, 15 }, + { 12, 3 }, + { 8, 7 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_6_7_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_6_7_term_output[] = { + 0, 11, 7, 12, 11, 0, 12, 7, 15, 4, 8, 3, 4, 15, 3, 8, +}; + +static const int osmo_conv_gsm0503_tch_afs_6_7_puncture[] = { + 1, + 3, + 7, + 11, + 15, + 27, + 39, + 55, + 67, + 79, + 95, + 107, + 119, + 135, + 147, + 159, + 175, + 187, + 199, + 215, + 227, + 239, + 255, + 267, + 279, + 287, + 291, + 295, + 299, + 303, + 307, + 311, + 315, + 319, + 323, + 327, + 331, + 335, + 339, + 343, + 347, + 351, + 355, + 359, + 363, + 367, + 369, + 371, + 375, + 377, + 379, + 383, + 385, + 387, + 391, + 393, + 395, + 399, + 401, + 403, + 407, + 409, + 411, + 415, + 417, + 419, + 423, + 425, + 427, + 431, + 433, + 435, + 439, + 441, + 443, + 447, + 449, + 451, + 455, + 457, + 459, + 463, + 465, + 467, + 471, + 473, + 475, + 479, + 481, + 483, + 487, + 489, + 491, + 495, + 497, + 499, + 503, + 505, + 507, + 511, + 513, + 515, + 519, + 521, + 523, + 527, + 529, + 531, + 535, + 537, + 539, + 543, + 545, + 547, + 549, + 551, + 553, + 555, + 557, + 559, + 561, + 563, + 565, + 567, + 569, + 571, + 573, + 575, + -1, +}; + +/* TCH/AFS 6.7 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 + */ +const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_6_7 = { + .N = 4, + .K = 5, + .len = 140, + .next_output = osmo_conv_gsm0503_tch_afs_6_7_output, + .next_state = osmo_conv_gsm0503_tch_afs_6_7_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_6_7_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_6_7_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_6_7_puncture, +}; diff --git a/src/gsm/conv_tch_afs_7_4_gen.c b/src/gsm/conv_tch_afs_7_4_gen.c new file mode 100644 index 0000000..924776b --- /dev/null +++ b/src/gsm/conv_tch_afs_7_4_gen.c @@ -0,0 +1,116 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_tch_afs_7_4_state[][2] = { + { 0, 1 }, + { 3, 2 }, + { 5, 4 }, + { 6, 7 }, + { 9, 8 }, + { 10, 11 }, + { 12, 13 }, + { 15, 14 }, + { 1, 0 }, + { 2, 3 }, + { 4, 5 }, + { 7, 6 }, + { 8, 9 }, + { 11, 10 }, + { 13, 12 }, + { 14, 15 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_7_4_output[][2] = { + { 0, 7 }, + { 2, 5 }, + { 4, 3 }, + { 6, 1 }, + { 2, 5 }, + { 0, 7 }, + { 6, 1 }, + { 4, 3 }, + { 0, 7 }, + { 2, 5 }, + { 4, 3 }, + { 6, 1 }, + { 2, 5 }, + { 0, 7 }, + { 6, 1 }, + { 4, 3 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_7_4_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_7_4_term_output[] = { + 0, 5, 3, 6, 5, 0, 6, 3, 7, 2, 4, 1, 2, 7, 1, 4, +}; + +static const int osmo_conv_gsm0503_tch_afs_7_4_puncture[] = { + 0, + 355, + 361, + 367, + 373, + 379, + 385, + 391, + 397, + 403, + 409, + 415, + 421, + 427, + 433, + 439, + 445, + 451, + 457, + 460, + 463, + 466, + 468, + 469, + 471, + 472, + -1, +}; + +/* TCH/AFS 7.4 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + */ +const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_7_4 = { + .N = 3, + .K = 5, + .len = 154, + .next_output = osmo_conv_gsm0503_tch_afs_7_4_output, + .next_state = osmo_conv_gsm0503_tch_afs_7_4_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_7_4_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_7_4_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_7_4_puncture, +}; diff --git a/src/gsm/conv_tch_afs_7_95_gen.c b/src/gsm/conv_tch_afs_7_95_gen.c new file mode 100644 index 0000000..737a7aa --- /dev/null +++ b/src/gsm/conv_tch_afs_7_95_gen.c @@ -0,0 +1,251 @@ + +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +static const uint8_t osmo_conv_gsm0503_tch_afs_7_95_state[][2] = { + { 0, 1 }, + { 2, 3 }, + { 5, 4 }, + { 7, 6 }, + { 9, 8 }, + { 11, 10 }, + { 12, 13 }, + { 14, 15 }, + { 16, 17 }, + { 18, 19 }, + { 21, 20 }, + { 23, 22 }, + { 25, 24 }, + { 27, 26 }, + { 28, 29 }, + { 30, 31 }, + { 33, 32 }, + { 35, 34 }, + { 36, 37 }, + { 38, 39 }, + { 40, 41 }, + { 42, 43 }, + { 45, 44 }, + { 47, 46 }, + { 49, 48 }, + { 51, 50 }, + { 52, 53 }, + { 54, 55 }, + { 56, 57 }, + { 58, 59 }, + { 61, 60 }, + { 63, 62 }, + { 1, 0 }, + { 3, 2 }, + { 4, 5 }, + { 6, 7 }, + { 8, 9 }, + { 10, 11 }, + { 13, 12 }, + { 15, 14 }, + { 17, 16 }, + { 19, 18 }, + { 20, 21 }, + { 22, 23 }, + { 24, 25 }, + { 26, 27 }, + { 29, 28 }, + { 31, 30 }, + { 32, 33 }, + { 34, 35 }, + { 37, 36 }, + { 39, 38 }, + { 41, 40 }, + { 43, 42 }, + { 44, 45 }, + { 46, 47 }, + { 48, 49 }, + { 50, 51 }, + { 53, 52 }, + { 55, 54 }, + { 57, 56 }, + { 59, 58 }, + { 60, 61 }, + { 62, 63 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_7_95_output[][2] = { + { 0, 7 }, + { 3, 4 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 0, 7 }, + { 3, 4 }, + { 3, 4 }, + { 0, 7 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 3, 4 }, + { 0, 7 }, + { 3, 4 }, + { 0, 7 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 3, 4 }, + { 0, 7 }, + { 0, 7 }, + { 3, 4 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 0, 7 }, + { 3, 4 }, + { 0, 7 }, + { 3, 4 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 0, 7 }, + { 3, 4 }, + { 3, 4 }, + { 0, 7 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 3, 4 }, + { 0, 7 }, + { 3, 4 }, + { 0, 7 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 3, 4 }, + { 0, 7 }, + { 0, 7 }, + { 3, 4 }, + { 2, 5 }, + { 1, 6 }, + { 2, 5 }, + { 1, 6 }, + { 0, 7 }, + { 3, 4 }, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_7_95_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, +}; + +static const uint8_t osmo_conv_gsm0503_tch_afs_7_95_term_output[] = { + 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5, 6, 5, 3, 0, 4, 7, 1, 2, 1, 2, 4, 7, 7, 4, 2, 1, 2, 1, 7, 4, 7, 4, 2, 1, 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7, 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6, 5, 6, 0, 3, +}; + +static const int osmo_conv_gsm0503_tch_afs_7_95_puncture[] = { + 1, + 2, + 4, + 5, + 8, + 22, + 70, + 118, + 166, + 214, + 262, + 310, + 317, + 319, + 325, + 332, + 334, + 341, + 343, + 349, + 356, + 358, + 365, + 367, + 373, + 380, + 382, + 385, + 389, + 391, + 397, + 404, + 406, + 409, + 413, + 415, + 421, + 428, + 430, + 433, + 437, + 439, + 445, + 452, + 454, + 457, + 461, + 463, + 469, + 476, + 478, + 481, + 485, + 487, + 490, + 493, + 500, + 502, + 503, + 505, + 506, + 508, + 509, + 511, + 512, + -1, +}; + +/* TCH/AFS 7.95 kbits convolutional code: + G4/G4 = 1 + G5/G4 = 1 + D + D4 + D6 / 1 + D2 + D3 + D5 + D6 + G6/G4 = 1 + D + D2 + D3 + D4 + D6 / 1 + D2 + D3 + D5 + D6 + */ +const struct osmo_conv_code osmo_conv_gsm0503_tch_afs_7_95 = { + .N = 3, + .K = 7, + .len = 165, + .next_output = osmo_conv_gsm0503_tch_afs_7_95_output, + .next_state = osmo_conv_gsm0503_tch_afs_7_95_state, + .next_term_output = osmo_conv_gsm0503_tch_afs_7_95_term_output, + .next_term_state = osmo_conv_gsm0503_tch_afs_7_95_term_state, + .puncture = osmo_conv_gsm0503_tch_afs_7_95_puncture, +}; diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index d8779db..980bbc3 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -16,82 +16,6 @@ /* Test codes */ /* ------------------------------------------------------------------------ */ -/* GSM TCH/AFS 7.95 -> Recursive code, flushed, with puncturing */ -static const uint8_t conv_gsm_tch_afs_7_95_next_output[][2] = { - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 5, 4 }, { 7, 6 }, - { 9, 8 }, { 11, 10 }, { 12, 13 }, { 14, 15 }, - { 16, 17 }, { 18, 19 }, { 21, 20 }, { 23, 22 }, - { 25, 24 }, { 27, 26 }, { 28, 29 }, { 30, 31 }, - { 33, 32 }, { 35, 34 }, { 36, 37 }, { 38, 39 }, - { 40, 41 }, { 42, 43 }, { 45, 44 }, { 47, 46 }, - { 49, 48 }, { 51, 50 }, { 52, 53 }, { 54, 55 }, - { 56, 57 }, { 58, 59 }, { 61, 60 }, { 63, 62 }, - { 1, 0 }, { 3, 2 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 13, 12 }, { 15, 14 }, - { 17, 16 }, { 19, 18 }, { 20, 21 }, { 22, 23 }, - { 24, 25 }, { 26, 27 }, { 29, 28 }, { 31, 30 }, - { 32, 33 }, { 34, 35 }, { 37, 36 }, { 39, 38 }, - { 41, 40 }, { 43, 42 }, { 44, 45 }, { 46, 47 }, - { 48, 49 }, { 50, 51 }, { 53, 52 }, { 55, 54 }, - { 57, 56 }, { 59, 58 }, { 60, 61 }, { 62, 63 }, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_term_output[] = { - 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5, 6, 5, 3, 0, - 4, 7, 1, 2, 1, 2, 4, 7, 7, 4, 2, 1, 2, 1, 7, 4, - 7, 4, 2, 1, 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7, - 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6, 5, 6, 0, 3, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_term_state[] = { - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, -}; - -static int conv_gsm_tch_afs_7_95_puncture[] = { - 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310, - 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367, - 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415, - 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463, - 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505, - 506, 508, 509, 511, 512, - -1, /* end */ -}; - -static const struct osmo_conv_code conv_gsm_tch_afs_7_95 = { - .N = 3, - .K = 7, - .len = 165, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_tch_afs_7_95_next_output, - .next_state = conv_gsm_tch_afs_7_95_next_state, - .next_term_output = conv_gsm_tch_afs_7_95_next_term_output, - .next_term_state = conv_gsm_tch_afs_7_95_next_term_state, - .puncture = conv_gsm_tch_afs_7_95_puncture, -}; - - /* GMR-1 TCH3 Speech -> Non recursive code, tail-biting, punctured */ static const uint8_t conv_gmr1_tch3_speech_next_output[][2] = { { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, @@ -260,7 +184,7 @@ int main(int argc, char *argv[]) }, { .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)", - .code = &conv_gsm_tch_afs_7_95, + .code = &osmo_conv_gsm0503_tch_afs_7_95, .in_len = 165, .out_len = 448, .has_vec = 1, -- 2.5.0 From msuraev at sysmocom.de Mon Apr 18 20:49:31 2016 From: msuraev at sysmocom.de (Max) Date: Mon, 18 Apr 2016 22:49:31 +0200 Subject: [PATCH 1/4] Add code generator for convolutional codes In-Reply-To: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> References: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: <5715485B.5000404@sysmocom.de> Oops, due to glitch with email client last 2 patches of this series were sent as a separate series. -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From suraev at alumni.ntnu.no Mon Apr 18 21:11:18 2016 From: suraev at alumni.ntnu.no (suraev at alumni.ntnu.no) Date: Mon, 18 Apr 2016 23:11:18 +0200 Subject: [PATCH] Add extra debug output with channel mode and type Message-ID: <1461013878-1582-1-git-send-email-suraev@alumni.ntnu.no> From: Max This provides helpful information for debugging internal MNCC handler. --- openbsc/src/libbsc/bsc_api.c | 6 ++++-- openbsc/src/libmsc/gsm_04_08.c | 23 ++++++++++++++++++----- openbsc/src/libmsc/mncc_builtin.c | 3 ++- openbsc/src/osmo-nitb/bsc_hack.c | 4 +++- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c index e6d820d..b8b5967 100644 --- a/openbsc/src/libbsc/bsc_api.c +++ b/openbsc/src/libbsc/bsc_api.c @@ -393,11 +393,13 @@ int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, in if (handle_new_assignment(conn, chan_mode, full_rate) != 0) goto error; } else { - LOGP(DMSC, LOGL_NOTICE, - "Sending ChanModify for speech %d %d\n", chan_mode, full_rate); if (chan_mode == GSM48_CMODE_SPEECH_AMR) handle_mr_config(conn, conn->lchan, full_rate); + LOGP(DMSC, LOGL_NOTICE, + "Sending ChanModify for speech: %s on channel %s\n", + get_value_string(gsm48_chan_mode_names, chan_mode), + get_value_string(gsm_chan_t_names, conn->lchan->type)); gsm48_lchan_modify(conn->lchan, chan_mode); } diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 1524ec4..7b78d48 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -1598,11 +1599,15 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) { struct gsm_bts *bts = lchan->ts->trx->bts; struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts; + enum gsm_chan_t lt = lchan->type, rt = remote_lchan->type; int rc; - DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n", - bts->nr, lchan->ts->trx->nr, lchan->ts->nr, - remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr); + DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u,%s) and " + "(bts=%u,trx=%u,ts=%u,%s)\n", + bts->nr, lchan->ts->trx->nr, lchan->ts->nr, + get_value_string(gsm_chan_t_names, lt), + remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr, + get_value_string(gsm_chan_t_names, rt)); if (bts->type != remote_bts->type) { LOGP(DCC, LOGL_ERROR, "Cannot switch calls between different BTS types yet\n"); @@ -2999,6 +3004,7 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref) struct gsm_bts *bts; struct gsm_lchan *lchan; struct gsm_trans *trans; + enum gsm48_chan_mode m; /* Find callref */ trans = trans_find_by_callref(net, callref); @@ -3038,8 +3044,11 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref) */ if (lchan->tch_mode == GSM48_CMODE_SIGN) { trans->conn->mncc_rtp_create_pending = 1; - return gsm0808_assign_req(trans->conn, - mncc_codec_for_mode(lchan->type), + m = mncc_codec_for_mode(lchan->type); + LOGP(DMNCC, LOGL_DEBUG, "RTP create: codec=%s, chan_type=%s\n", + get_value_string(gsm48_chan_mode_names, m), + get_value_string(gsm_chan_t_names, lchan->type)); + return gsm0808_assign_req(trans->conn, m, lchan->type != GSM_LCHAN_TCH_H); } @@ -3068,6 +3077,10 @@ static int tch_rtp_connect(struct gsm_network *net, void *arg) } lchan = trans->conn->lchan; + LOGP(DMNCC, LOGL_DEBUG, "RTP connect: codec=%s, chan_type=%s\n", + get_value_string(gsm48_chan_mode_names, + mncc_codec_for_mode(lchan->type)), + get_value_string(gsm_chan_t_names, lchan->type)); /* TODO: Check if payload_msg_type is compatible with what we have */ if (rtp->payload_type != lchan->abis_ip.rtp_payload) { diff --git a/openbsc/src/libmsc/mncc_builtin.c b/openbsc/src/libmsc/mncc_builtin.c index 77df6fb..ee98d2d 100644 --- a/openbsc/src/libmsc/mncc_builtin.c +++ b/openbsc/src/libmsc/mncc_builtin.c @@ -138,7 +138,8 @@ static int mncc_setup_ind(struct gsm_call *call, int msg_type, memset(&mncc, 0, sizeof(struct gsm_mncc)); mncc.callref = call->callref; mncc.lchan_mode = determine_lchan_mode(setup); - DEBUGP(DMNCC, "(call %x) Modify channel mode.\n", call->callref); + DEBUGP(DMNCC, "(call %x) Modify channel mode: %s\n", call->callref, + get_value_string(gsm48_chan_mode_names, mncc.lchan_mode)); mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, &mncc); /* send setup to remote */ diff --git a/openbsc/src/osmo-nitb/bsc_hack.c b/openbsc/src/osmo-nitb/bsc_hack.c index dffe642..0b360dc 100644 --- a/openbsc/src/osmo-nitb/bsc_hack.c +++ b/openbsc/src/osmo-nitb/bsc_hack.c @@ -288,8 +288,10 @@ int main(int argc, char **argv) rc = bsc_bootstrap_network(mncc_sock_from_cc, config_file); if (rc >= 0) mncc_sock_init(bsc_gsmnet, mncc_sock_path); - } else + } else { + DEBUGP(DMNCC, "Using internal MNCC handler.\n"); rc = bsc_bootstrap_network(int_mncc_recv, config_file); + } if (rc < 0) exit(1); #ifdef BUILD_SMPP -- 2.5.0 From nhofmeyr at sysmocom.de Tue Apr 19 00:20:41 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 19 Apr 2016 02:20:41 +0200 Subject: osmo-iuh: ranap_cn_common Message-ID: <20160419002041.GC3564@dub6> Hi osmo-iuh guys, for hnb-test, I've added misplaced cases to cn_ranap_*_initiating_msg_co(). The point is, hnb-test simulates an RNC, which is by definition not the CN, but so far it apparently uses the cn_* functions to parse Iu messages. Just wanted to let you know that I'm aware of it; I've eagerly pushed the commits to master but now noticed that hnb-test's use of cn_* is not accurate and that it's the wrong place to add those cases. 68b7a478688 That shall be fixed, so that cn_ranap_*_initiating_msg_co() still report all messages not expected at the CN as suspicious. I could keep the RNC side specifics to hnb-test.c, but I guess I will add the generic RNC side functions that hnb-test needs to the main headers and sources, just in case some other code may find that useful some day. ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Apr 19 00:48:07 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 19 Apr 2016 02:48:07 +0200 Subject: [PATCH 2/4] Add concolutional code generator for *CCH In-Reply-To: <1461011051-11657-2-git-send-email-suraev@alumni.ntnu.no> References: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> <1461011051-11657-2-git-send-email-suraev@alumni.ntnu.no> Message-ID: <20160419004807.GB8436@dub6> It's like the 4th time you post the "concolutional" commit log message ;) Can you fix the typo for me plz? ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From kluchnikovi at gmail.com Tue Apr 19 11:51:25 2016 From: kluchnikovi at gmail.com (Ivan Kluchnikov) Date: Tue, 19 Apr 2016 14:51:25 +0300 Subject: [PATCH] Add support of virtual networks for sending network name to ms depending on imsi Message-ID: <1461066685-9248-1-git-send-email-kluchnikovi@gmail.com> Before sending mm info message to ms: - try to find virtual network with the imsi prefix which matches subscriber's imsi - if virtual network was found, use long and short network names of this virtual network for subscriber - if virtual network was not found, use long and short network names of main network for subscriber --- openbsc/include/openbsc/gsm_data.h | 16 ++++ openbsc/include/openbsc/gsm_subscriber.h | 1 - openbsc/include/openbsc/vty.h | 2 + openbsc/src/libbsc/bsc_vty.c | 137 +++++++++++++++++++++++++++++++ openbsc/src/libbsc/net_init.c | 1 + openbsc/src/libcommon/common_vty.c | 19 +++++ openbsc/src/libcommon/gsm_data.c | 40 +++++++++ openbsc/src/libmsc/gsm_04_08.c | 42 ++++++++-- openbsc/src/libmsc/smpp_vty.c | 10 --- openbsc/tests/vty_test_runner.py | 42 +++++++++- 10 files changed, 290 insertions(+), 20 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 6d7aba3..04efbdc 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -248,6 +248,9 @@ struct gsm_network { unsigned int num_bts; struct llist_head bts_list; + unsigned int num_virt_net; + struct llist_head virt_net_list; + /* timer values */ int T3101; int T3103; @@ -293,6 +296,16 @@ struct gsm_network { struct ctrl_handle *ctrl; }; +#define GSM_IMSI_LENGTH 17 +struct gsm_virt_network { + struct llist_head list; + uint8_t nr; + struct gsm_network *network; + char imsi_prefix[GSM_IMSI_LENGTH]; + char *name_long; + char *name_short; +}; + struct osmo_esme; enum gsm_sms_source_id { @@ -435,6 +448,9 @@ int gsm_bts_model_register(struct gsm_bts_model *model); struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan); void subscr_con_free(struct gsm_subscriber_connection *conn); +struct gsm_virt_network *gsm_virt_net_alloc_register(struct gsm_network *net); +struct gsm_virt_network *gsm_virt_net_num(struct gsm_network *net, int num); + struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_type type, uint8_t bsic); diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index 7d6c776..7108bff 100644 --- a/openbsc/include/openbsc/gsm_subscriber.h +++ b/openbsc/include/openbsc/gsm_subscriber.h @@ -5,7 +5,6 @@ #include #define GSM_IMEI_LENGTH 17 -#define GSM_IMSI_LENGTH 17 #define GSM_NAME_LENGTH 160 #define GSM_EXTENSION_LENGTH 15 /* MSISDN can only be 15 digits length */ diff --git a/openbsc/include/openbsc/vty.h b/openbsc/include/openbsc/vty.h index bc30e23..711f82a 100644 --- a/openbsc/include/openbsc/vty.h +++ b/openbsc/include/openbsc/vty.h @@ -17,6 +17,7 @@ extern struct cmd_element cfg_no_description_cmd; enum bsc_vty_node { GSMNET_NODE = _LAST_OSMOVTY_NODE + 1, + VIRT_NET_NODE, BTS_NODE, TRX_NODE, TS_NODE, @@ -41,6 +42,7 @@ 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); +extern int osmo_is_digits(const char *str); struct log_info; int bsc_vty_init(const struct log_info *cat); diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 29f2501..f8e981e 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -112,6 +112,12 @@ struct cmd_node net_node = { 1, }; +struct cmd_node virt_net_node = { + VIRT_NET_NODE, + "%s(config-net-virt)# ", + 1, +}; + struct cmd_node bts_node = { BTS_NODE, "%s(config-net-bts)# ", @@ -343,6 +349,43 @@ DEFUN(show_bts, show_bts_cmd, "show bts [<0-255>]", return CMD_SUCCESS; } +static void virt_net_dump_vty(struct vty *vty, struct gsm_virt_network *virt_net) +{ + vty_out(vty, "Virtual network %u%s", virt_net->nr, VTY_NEWLINE); + if (strlen(virt_net->imsi_prefix)) { + vty_out(vty, " imsi-prefix %s%s", virt_net->imsi_prefix, VTY_NEWLINE); + } + vty_out(vty, " Long network name: '%s'%s", + virt_net->name_long, VTY_NEWLINE); + vty_out(vty, " Short network name: '%s'%s", + virt_net->name_short, VTY_NEWLINE); +} + +DEFUN(show_virt_net, show_virt_net_cmd, "show virtual-network [<0-255>]", + SHOW_STR "Display information about a virtual network\n" + "Virtual network number") +{ + struct gsm_network *net = gsmnet_from_vty(vty); + int virt_net_nr; + + if (argc != 0) { + /* use the virtual network number that the user has specified */ + virt_net_nr = atoi(argv[0]); + if (virt_net_nr >= net->num_virt_net) { + vty_out(vty, "%% can't find virtual network '%s'%s", argv[0], + VTY_NEWLINE); + return CMD_WARNING; + } + virt_net_dump_vty(vty, gsm_virt_net_num(net, virt_net_nr)); + return CMD_SUCCESS; + } + /* print all virtual networks */ + for (virt_net_nr = 0; virt_net_nr < net->num_virt_net; virt_net_nr++) + virt_net_dump_vty(vty, gsm_virt_net_num(net, virt_net_nr)); + + return CMD_SUCCESS; +} + /* utility functions */ static void parse_e1_link(struct gsm_e1_subslot *e1_link, const char *line, const char *ts, const char *ss) @@ -743,6 +786,27 @@ static int config_write_bts(struct vty *v) return CMD_SUCCESS; } +static void config_write_virt_net_single(struct vty *vty, struct gsm_virt_network *virt_net) +{ + vty_out(vty, " virtual-network %u%s", virt_net->nr, VTY_NEWLINE); + if (strlen(virt_net->imsi_prefix)) { + vty_out(vty, " imsi-prefix %s%s", virt_net->imsi_prefix, VTY_NEWLINE); + } + vty_out(vty, " name short %s%s", virt_net->name_short, VTY_NEWLINE); + vty_out(vty, " name long %s%s", virt_net->name_long, VTY_NEWLINE); +} + +static int config_write_virt_net(struct vty *v) +{ + struct gsm_network *gsmnet = gsmnet_from_vty(v); + struct gsm_virt_network *virt_net; + + llist_for_each_entry(virt_net, &gsmnet->virt_net_list, list) + config_write_virt_net_single(v, virt_net); + + return CMD_SUCCESS; +} + static int config_write_net(struct vty *vty) { struct gsm_network *gsmnet = gsmnet_from_vty(vty); @@ -1612,6 +1676,72 @@ DEFUN(cfg_net_subscr_keep, return CMD_SUCCESS; } +DEFUN(cfg_virt_net, + cfg_virt_net_cmd, + "virtual-network <0-255>", + "Select a virtual network to configure\n" + "Virtual-network Number\n") +{ + struct gsm_network *gsmnet = gsmnet_from_vty(vty); + int virt_net_nr = atoi(argv[0]); + struct gsm_virt_network *virt_net; + + if (virt_net_nr > gsmnet->num_virt_net) { + vty_out(vty, "%% The next unused Virtual-network number is %u%s", + gsmnet->num_virt_net, VTY_NEWLINE); + return CMD_WARNING; + } else if (virt_net_nr == gsmnet->num_virt_net) { + /* allocate a new one */ + virt_net = gsm_virt_net_alloc_register(gsmnet); + } else + virt_net = gsm_virt_net_num(gsmnet, virt_net_nr); + + if (!virt_net) { + vty_out(vty, "%% Unable to allocate Virtual-network %u%s", + gsmnet->num_virt_net, VTY_NEWLINE); + return CMD_WARNING; + } + + vty->index = virt_net; + vty->index_sub = NULL; + vty->node = VIRT_NET_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_virt_net_imsi_prefix, + cfg_virt_net_imsi_prefix_cmd, + "imsi-prefix PREFIX", + "Set the IMSI prefix\n" + "Prefix\n") +{ + struct gsm_virt_network *virt_net = vty->index; + if (!osmo_is_digits(argv[0])) { + vty_out(vty, "%% PREFIX has to be numeric%s", VTY_NEWLINE); + return CMD_WARNING; + } + snprintf(virt_net->imsi_prefix, sizeof(virt_net->imsi_prefix), "%s", argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_virt_net_name, + cfg_virt_net_name_cmd, + "name (short|long) NAME", + "Set the GSM network name\n" + "Short network name\n" + "Long network name\n" + NAME_CMD_STR NAME_STR) +{ + struct gsm_virt_network *virt_net = vty->index; + + if (!strcmp(argv[0], "short")) + bsc_replace_string(virt_net->network, &virt_net->name_short, argv[1]); + else + bsc_replace_string(virt_net->network, &virt_net->name_long, argv[1]); + + return CMD_SUCCESS; +} + /* per-BTS configuration */ DEFUN(cfg_bts, cfg_bts_cmd, @@ -3763,6 +3893,7 @@ int bsc_vty_init(const struct log_info *cat) install_element_ve(&show_net_cmd); + install_element_ve(&show_virt_net_cmd); install_element_ve(&show_bts_cmd); install_element_ve(&show_trx_cmd); install_element_ve(&show_ts_cmd); @@ -3811,6 +3942,12 @@ int bsc_vty_init(const struct log_info *cat) install_element(GSMNET_NODE, &cfg_net_subscr_keep_cmd); install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd); + install_element(GSMNET_NODE, &cfg_virt_net_cmd); + install_node(&virt_net_node, config_write_virt_net); + vty_install_default(VIRT_NET_NODE); + install_element(VIRT_NET_NODE, &cfg_virt_net_imsi_prefix_cmd); + install_element(VIRT_NET_NODE, &cfg_virt_net_name_cmd); + install_element(GSMNET_NODE, &cfg_bts_cmd); install_node(&bts_node, config_write_bts); vty_install_default(BTS_NODE); diff --git a/openbsc/src/libbsc/net_init.c b/openbsc/src/libbsc/net_init.c index 568a0b8..1fe9f3e 100644 --- a/openbsc/src/libbsc/net_init.c +++ b/openbsc/src/libbsc/net_init.c @@ -71,6 +71,7 @@ struct gsm_network *gsm_network_init(uint16_t country_code, uint16_t network_cod INIT_LLIST_HEAD(&net->trans_list); INIT_LLIST_HEAD(&net->upqueue); INIT_LLIST_HEAD(&net->bts_list); + INIT_LLIST_HEAD(&net->virt_net_list); net->stats.chreq.total = osmo_counter_alloc("net.chreq.total"); net->stats.chreq.no_channel = osmo_counter_alloc("net.chreq.no_channel"); diff --git a/openbsc/src/libcommon/common_vty.c b/openbsc/src/libcommon/common_vty.c index a0674f0..66a82d8 100644 --- a/openbsc/src/libcommon/common_vty.c +++ b/openbsc/src/libcommon/common_vty.c @@ -42,6 +42,15 @@ int bsc_vty_go_parent(struct vty *vty) vty->node = CONFIG_NODE; vty->index = NULL; break; + case VIRT_NET_NODE: + vty->node = GSMNET_NODE; + { + /* set vty->index correctly ! */ + struct gsm_virt_network *virt_net = vty->index; + vty->index = virt_net->network; + vty->index_sub = NULL; + } + break; case BTS_NODE: vty->node = GSMNET_NODE; { @@ -141,3 +150,13 @@ void bsc_replace_string(void *ctx, char **dst, const char *newstr) talloc_free(*dst); *dst = talloc_strdup(ctx, newstr); } + +int osmo_is_digits(const char *str) +{ + int i; + for (i = 0; i < strlen(str); i++) { + if (!isdigit(str[i])) + return 0; + } + return 1; +} diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index 16035ed..d75e7af 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -192,6 +192,46 @@ const char *rrlp_mode_name(enum rrlp_mode mode) return get_value_string(rrlp_mode_names, mode); } +struct gsm_virt_network *gsm_virt_net_alloc(void *ctx) +{ + struct gsm_virt_network *virt_net = talloc_zero(ctx, struct gsm_virt_network); + if (!virt_net) + return NULL; + return virt_net; +} + +struct gsm_virt_network *gsm_virt_net_alloc_register(struct gsm_network *net) +{ + struct gsm_virt_network *virt_net; + + virt_net = gsm_virt_net_alloc(net); + if (!virt_net) + return NULL; + + virt_net->nr = net->num_virt_net++; + virt_net->network = net; + virt_net->name_short = talloc_strdup(net, "OpenBSC"); + virt_net->name_long = talloc_strdup(net, "OpenBSC"); + + llist_add_tail(&virt_net->list, &net->virt_net_list); + return virt_net; +} + +struct gsm_virt_network *gsm_virt_net_num(struct gsm_network *net, int num) +{ + struct gsm_virt_network *virt_net; + + if (num >= net->num_virt_net) + return NULL; + + llist_for_each_entry(virt_net, &net->virt_net_list, list) { + if (virt_net->nr == num) + return virt_net; + } + + return NULL; +} + static const struct value_string bts_gprs_mode_names[] = { { BTS_GPRS_NONE, "none" }, { BTS_GPRS_GPRS, "gprs" }, diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 1524ec4..57a6726 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -702,6 +702,16 @@ static uint8_t bcdify(uint8_t value) return ret; } +int is_prefix_match_imsi(char *imsi_prefix, char *imsi) +{ + size_t prefix_len = strlen(imsi_prefix); + size_t imsi_len = strlen(imsi); + if ((prefix_len <= imsi_len) && + (strncmp(imsi, imsi_prefix, prefix_len) == 0)) { + return 1; + } + return 0; +} /* Section 9.2.15a */ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) @@ -719,13 +729,29 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) int tzunits; int dst = 0; + char *name_long = net->name_long; + char *name_short = net->name_short; + int virt_net_nr; + msg->lchan = conn->lchan; gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); gh->proto_discr = GSM48_PDISC_MM; gh->msg_type = GSM48_MT_MM_INFO; - if (net->name_long) { + if (net->num_virt_net) { + for (virt_net_nr = 0; virt_net_nr < net->num_virt_net; virt_net_nr++) { + struct gsm_virt_network* virt_net = gsm_virt_net_num(net, virt_net_nr); + if (virt_net && strlen(virt_net->imsi_prefix) && + is_prefix_match_imsi(virt_net->imsi_prefix, conn->subscr->imsi)) { + name_long = virt_net->name_long; + name_short = virt_net->name_short; + break; + } + } + } + + if (name_long) { #if 0 name_len = strlen(net->name_long); /* 10.5.3.5a */ @@ -741,8 +767,8 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) /* FIXME: Use Cell Broadcast, not UCS-2, since * UCS-2 is only supported by later revisions of the spec */ #endif - name_len = (strlen(net->name_long)*7)/8; - name_pad = (8 - strlen(net->name_long)*7)%8; + name_len = (strlen(name_long)*7)/8; + name_pad = (8 - strlen(name_long)*7)%8; if (name_pad > 0) name_len++; /* 10.5.3.5a */ @@ -752,11 +778,11 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */ ptr8 = msgb_put(msg, name_len); - gsm_7bit_encode_n(ptr8, name_len, net->name_long, NULL); + gsm_7bit_encode_n(ptr8, name_len, name_long, NULL); } - if (net->name_short) { + if (name_short) { #if 0 name_len = strlen(net->name_short); /* 10.5.3.5a */ @@ -769,8 +795,8 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) for (i = 0; i < name_len; i++) ptr16[i] = htons(net->name_short[i]); #endif - name_len = (strlen(net->name_short)*7)/8; - name_pad = (8 - strlen(net->name_short)*7)%8; + name_len = (strlen(name_short)*7)/8; + name_pad = (8 - strlen(name_short)*7)%8; if (name_pad > 0) name_len++; /* 10.5.3.5a */ @@ -780,7 +806,7 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */ ptr8 = msgb_put(msg, name_len); - gsm_7bit_encode_n(ptr8, name_len, net->name_short, NULL); + gsm_7bit_encode_n(ptr8, name_len, name_short, NULL); } diff --git a/openbsc/src/libmsc/smpp_vty.c b/openbsc/src/libmsc/smpp_vty.c index 351e8be..72b816f 100644 --- a/openbsc/src/libmsc/smpp_vty.c +++ b/openbsc/src/libmsc/smpp_vty.c @@ -277,16 +277,6 @@ DEFUN(cfg_esme_no_passwd, cfg_esme_no_passwd_cmd, return CMD_SUCCESS; } -static int osmo_is_digits(const char *str) -{ - int i; - for (i = 0; i < strlen(str); i++) { - if (!isdigit(str[i])) - return 0; - } - return 1; -} - static const struct value_string route_errstr[] = { { -EEXIST, "Route already exists" }, { -ENODEV, "Route does not exist" }, diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index ecf5204..03fdf45 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -133,6 +133,9 @@ class TestVTYGenericBSC(TestVTYBase): self.assertTrue(self.vty.verify("network",[''])) self.assertEquals(self.vty.node(), 'config-net') self.checkForEndAndExit() + self.assertTrue(self.vty.verify("virtual-network 0",[''])) + self.assertEquals(self.vty.node(), 'config-net-virt') + self.checkForEndAndExit() self.assertTrue(self.vty.verify("bts 0",[''])) self.assertEquals(self.vty.node(), 'config-net-bts') self.checkForEndAndExit() @@ -154,6 +157,12 @@ class TestVTYGenericBSC(TestVTYBase): self.assertEquals(self.vty.node(), 'config-net-bts') self.assertTrue(self.vty.verify("exit",[''])) self.assertEquals(self.vty.node(), 'config-net') + self.assertTrue(self.vty.verify("virtual-network 1",[''])) + self.assertEquals(self.vty.node(), 'config-net-virt') + self.checkForEndAndExit() + self.vty.command("write terminal") + self.assertTrue(self.vty.verify("exit",[''])) + self.assertEquals(self.vty.node(), 'config-net') self.assertTrue(self.vty.verify("exit",[''])) self.assertEquals(self.vty.node(), 'config') self.assertTrue(self.vty.verify("exit",[''])) @@ -307,6 +316,38 @@ class TestVTYNITB(TestVTYGenericBSC): if classNum != 10: self.assertEquals(res.find("rach access-control-class " + str(classNum) + " barred"), -1) + def testVirtualNetworks(self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("network") + self.vty.command("virtual-network 0") + + # Test invalid input + self.vty.verify("imsi-prefix 1234567abcd89", ['% PREFIX has to be numeric']) + self.vty.verify("name short Test Net", ['% Unknown command.']) + self.vty.verify("name long Test Network", ['% Unknown command.']) + + # Set virtual-networks + self.vty.verify("imsi-prefix 00202", ['']) + self.vty.verify("name short TestNet2", ['']) + self.vty.verify("name long TestNetwork2", ['']) + self.vty.verify("exit",['']) + self.vty.command("virtual-network 1") + self.vty.verify("imsi-prefix 00303300", ['']) + self.vty.verify("name short TestNet3", ['']) + self.vty.verify("name long TestNetwork3", ['']) + + # Verify settings + res = self.vty.command("write terminal") + self.assert_(res.find('virtual-network 0') > 0) + self.assert_(res.find('imsi-prefix 00202') > 0) + self.assert_(res.find('name short TestNet2') > 0) + self.assert_(res.find('name long TestNetwork2') > 0) + self.assert_(res.find('virtual-network 1') > 0) + self.assert_(res.find('imsi-prefix 00303300') > 0) + self.assert_(res.find('name short TestNet3') > 0) + self.assert_(res.find('name long TestNetwork3') > 0) + def testSubscriberCreateDeleteTwice(self): """ OS#1657 indicates that there might be an issue creating the @@ -342,7 +383,6 @@ class TestVTYNITB(TestVTYGenericBSC): res = self.vty.command('show subscriber imsi '+imsi) self.assert_(res != '% No subscriber found for imsi '+imsi) - def testSubscriberCreateDelete(self): self.vty.enable() -- 1.9.1 From msuraev at sysmocom.de Tue Apr 19 14:06:15 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Tue, 19 Apr 2016 16:06:15 +0200 Subject: [PATCH] Add function for appending range1024 to bitvec Message-ID: <1461074775-23946-1-git-send-email-msuraev@sysmocom.de> From: Max Add convenience function to append range1024 encoded data (see 3GPP TS 44.018 Annex J) to a given bitvec. --- include/osmocom/core/bitvec.h | 3 +++ src/bitvec.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/include/osmocom/core/bitvec.h b/include/osmocom/core/bitvec.h index c3c1153..704573c 100644 --- a/include/osmocom/core/bitvec.h +++ b/include/osmocom/core/bitvec.h @@ -44,6 +44,8 @@ #include #include +#include + /*! \brief A single GSM bit * * In GSM mac blocks, every bit can be 0 or 1, or L or H. L/H are @@ -75,6 +77,7 @@ int bitvec_set_uint(struct bitvec *bv, uint32_t in, unsigned int count); int bitvec_get_uint(struct bitvec *bv, unsigned int num_bits); int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val); int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit); +void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r); int bitvec_get_bytes(struct bitvec *bv, uint8_t *bytes, unsigned int count); int bitvec_set_bytes(struct bitvec *bv, const uint8_t *bytes, unsigned int count); struct bitvec *bitvec_alloc(unsigned int size, TALLOC_CTX *bvctx); diff --git a/src/bitvec.c b/src/bitvec.c index a92fd71..7334341 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -38,6 +38,7 @@ #include #include +#include #define BITNUM_FROM_COMP(byte, bit) ((byte*8)+bit) @@ -523,6 +524,41 @@ static inline unsigned leading_bits(uint8_t x, bool b) } return 7; } + +/*! \brief append range1024 encoded data to bit vector */ +void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r) +{ + bitvec_set_uint(bv, r->w1_hi, 2); + bitvec_set_uint(bv, r->w1_lo, 8); + bitvec_set_uint(bv, r->w2_hi, 8); + bitvec_set_uint(bv, r->w2_lo, 1); + bitvec_set_uint(bv, r->w3_hi, 7); + bitvec_set_uint(bv, r->w3_lo, 2); + bitvec_set_uint(bv, r->w4_hi, 6); + bitvec_set_uint(bv, r->w4_lo, 2); + bitvec_set_uint(bv, r->w5_hi, 6); + bitvec_set_uint(bv, r->w5_lo, 2); + bitvec_set_uint(bv, r->w6_hi, 6); + bitvec_set_uint(bv, r->w6_lo, 2); + bitvec_set_uint(bv, r->w7_hi, 6); + bitvec_set_uint(bv, r->w7_lo, 2); + bitvec_set_uint(bv, r->w8_hi, 6); + bitvec_set_uint(bv, r->w8_lo, 1); + bitvec_set_uint(bv, r->w9, 7); + bitvec_set_uint(bv, r->w10, 7); + bitvec_set_uint(bv, r->w11_hi, 1); + bitvec_set_uint(bv, r->w11_lo, 6); + bitvec_set_uint(bv, r->w12_hi, 2); + bitvec_set_uint(bv, r->w12_lo, 5); + bitvec_set_uint(bv, r->w13_hi, 3); + bitvec_set_uint(bv, r->w13_lo, 4); + bitvec_set_uint(bv, r->w14_hi, 4); + bitvec_set_uint(bv, r->w14_lo, 3); + bitvec_set_uint(bv, r->w15_hi, 5); + bitvec_set_uint(bv, r->w15_lo, 2); + bitvec_set_uint(bv, r->w16, 6); +} + /*! \brief force bit vector to all 0 and current bit to the beginnig of the vector */ void bitvec_zero(struct bitvec *bv) { -- 2.8.1 From 246tnt at gmail.com Wed Apr 20 05:13:16 2016 From: 246tnt at gmail.com (Sylvain Munaut) Date: Wed, 20 Apr 2016 07:13:16 +0200 Subject: [PATCH 1/2] Add convolutional code generators for CS2/3 In-Reply-To: <1461011174-11851-1-git-send-email-suraev@alumni.ntnu.no> References: <1461011174-11851-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: Hi, A few more comments, although those are mainly style so unless someone else also has those concerns, I'm not opposed to merging. > src/gsm/conv_cs2_gen.c | 211 +++++++++++++++++++++++++++++ > src/gsm/conv_cs3_gen.c | 299 ++++++++++++++++++++++++++++++++++++++++++ Why the _gen suffix ? If they're fully automatically generated, then the build process should generate them, they should not be in the repo at all. > +extern const struct osmo_conv_code osmo_conv_gsm0503_cs2; > +extern const struct osmo_conv_code osmo_conv_gsm0503_cs3; Looking at all the other symbol in osmogsm, it seems we deemed 'osmo_' to be redudant and so maybe "gsm0503_conv_cs2" would fit better in the naming scheme ? > +static const uint8_t osmo_conv_gsm0503_cs2_output[][2] = { All those being purely internal symbols, then don't need osmo_conv either Cheers, Sylvain From msuraev at sysmocom.de Wed Apr 20 07:58:24 2016 From: msuraev at sysmocom.de (Max) Date: Wed, 20 Apr 2016 09:58:24 +0200 Subject: [PATCH 1/2] Add convolutional code generators for CS2/3 In-Reply-To: References: <1461011174-11851-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: <571736A0.9060700@sysmocom.de> Thanks for review. Comments are inline. On 04/20/2016 07:13 AM, Sylvain Munaut wrote: > Hi, > > > A few more comments, although those are mainly style so unless someone > else also has those concerns, I'm not opposed to merging. > > >> src/gsm/conv_cs2_gen.c | 211 +++++++++++++++++++++++++++++ >> src/gsm/conv_cs3_gen.c | 299 ++++++++++++++++++++++++++++++++++++++++++ > Why the _gen suffix ? > > If they're fully automatically generated, then the build process > should generate them, they should not be in the repo at all. That's actually the thing we should discuss: the latest version is more or less complete - it can generate everything necessary, to use results we only need one-liner "extern osmo_conv...." in the header. But if we integrate it into build without adding generated files into repo than we'll have hard build dependency on python. That's fine by me - I don't think we support any platform which does not have python. But I'd like to hear what others think. > >> +extern const struct osmo_conv_code osmo_conv_gsm0503_cs2; >> +extern const struct osmo_conv_code osmo_conv_gsm0503_cs3; > Looking at all the other symbol in osmogsm, it seems we deemed 'osmo_' > to be redudant and so maybe "gsm0503_conv_cs2" would fit better in the > naming scheme ? > > >> +static const uint8_t osmo_conv_gsm0503_cs2_output[][2] = { > All those being purely internal symbols, then don't need osmo_conv either Both are fine by me and are trivial to fix. Thanks. > > Cheers, > > Sylvain -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Wed Apr 20 08:00:04 2016 From: msuraev at sysmocom.de (Max) Date: Wed, 20 Apr 2016 10:00:04 +0200 Subject: [PATCH 2/4] Add concolutional code generator for *CCH In-Reply-To: <20160419004807.GB8436@dub6> References: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> <1461011051-11657-2-git-send-email-suraev@alumni.ntnu.no> <20160419004807.GB8436@dub6> Message-ID: <57173704.6070605@sysmocom.de> Thanks for spotting it. I would have already fixed it if you'd voiced one of the previous 3 instances :) On 04/19/2016 02:48 AM, Neels Hofmeyr wrote: > It's like the 4th time you post the "concolutional" commit log message ;) > Can you fix the typo for me plz? > > ~Neels > -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Wed Apr 20 10:06:05 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 20 Apr 2016 12:06:05 +0200 Subject: [PATCH 1/2] Fix documentation for command parameters Message-ID: <1461146766-29042-1-git-send-email-msuraev@sysmocom.de> From: Max --- openbsc/src/libbsc/bsc_vty.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 9634508..3a699c4 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2797,7 +2797,8 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" - "EARFCN of neighbor\n") + "EARFCN of neighbor\n" + "EARFCN\n") { struct gsm_bts *bts = vty->index; struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; -- 2.8.1 From msuraev at sysmocom.de Wed Apr 20 10:06:06 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 20 Apr 2016 12:06:06 +0200 Subject: [PATCH 2/2] Fix earfcn deletion In-Reply-To: <1461146766-29042-1-git-send-email-msuraev@sysmocom.de> References: <1461146766-29042-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1461146766-29042-2-git-send-email-msuraev@sysmocom.de> From: Max * fix typo in arg index * fix sign in error reporting * add vty test --- openbsc/src/libbsc/bsc_vty.c | 4 ++-- openbsc/tests/vty_test_runner.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 3a699c4..85b8394 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2802,11 +2802,11 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, { struct gsm_bts *bts = vty->index; struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; - uint16_t arfcn = atoi(argv[1]); + uint16_t arfcn = atoi(argv[0]); int r = osmo_earfcn_del(e, arfcn); if (r < 0) { vty_out(vty, "Unable to delete arfcn %u: %s%s", arfcn, - strerror(r), VTY_NEWLINE); + strerror(-r), VTY_NEWLINE); return CMD_WARNING; } diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 143ba5d..7f64a80 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -231,6 +231,20 @@ class TestVTYNITB(TestVTYGenericBSC): self.assertEquals(self.vty.node(), 'config-mncc-int') + def testSi2Q(self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("network") + self.vty.command("bts 0") + before = self.vty.command("show running-config") + self.vty.command("si2quater neighbor-list add earfcn 1911 threshold 11 2") + self.vty.command("si2quater neighbor-list add earfcn 1924 threshold 11 3") + self.vty.command("si2quater neighbor-list add earfcn 2111 threshold 11") + self.vty.command("si2quater neighbor-list del earfcn 1911") + self.vty.command("si2quater neighbor-list del earfcn 1924") + self.vty.command("si2quater neighbor-list del earfcn 2111") + self.assertEquals(before, self.vty.command("show running-config")) + def testEnableDisablePeriodicLU(self): self.vty.enable() self.vty.command("configure terminal") -- 2.8.1 From alexander.chemeris at gmail.com Wed Apr 20 10:55:29 2016 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Wed, 20 Apr 2016 13:55:29 +0300 Subject: [PATCH 0/4] core/conv: Fast Viterbi decoding In-Reply-To: References: <20140429041352.GA5213@phenom.hsd1.va.comcast.net> <67121C8F-38EA-4835-AA8E-025DD0C024F4@freyther.de> Message-ID: Hi Thomas, Sylvain, Recent activity around convolutional coding has reminded me about this lost diamond. Just wondering if there is a chance to resolve the critical issues and get this merged? On Sat, Aug 1, 2015 at 12:16 AM, Sylvain Munaut <246tnt at gmail.com> wrote: > Ok, so I finally took some time to re-read this. > > First a quick comment on each patch. > > Patch 1/4: See below > Patch 2/4: Didn't really look deeply yet, but at first glance looks > OK, I'd say let's focus on getting the infra of patch 1 merged first. > Patch 3/4: I'm pretty sure -march=native will wreck cross-compiling > Patch 4/4: Looks good > > > For patch 1: > * About the state persistence, let's just ignore it for now. It does > cost some performance but there is no easy fix, the perf improvement > even with this over head is still massive and we can deal with it > internally later. > > * The symbol visibility and naming comments raised in the thread need > to be dealt with. To sum up there is 3 kinds of symbols/names : > > - Global functions / structures: Those that either appear in the > header or that are visible when doing an objdump on the resulting .so > . Those all need the osmo_ prefix > > - Internal to the lib: Those that are accessed between several > files in the lib. Those don't need an osmo_ prefix for brevity, but > they need something less conflicted than 'gen_' ... include 'viterbi' > or 'conv' or something to that effect in the name. They need to be > hidden from the outside (so they shouldn't show up in the resulting > .so), not sure about the current fvisibility situation in libosmocore > (don't know if we explicitely mark exported function or if we > explicitely mark non-exported one). > > - Internal to the file: Make sure they're static, naming is fairly > irrelevant > > > So I'd say re-submit patch 1 and 4 first, forward ported to apply > cleanly and pass a make distcheck on current master. We'll get that > merged first, then look at integrating the SSE stuff. > > > Cheers, > > Sylvain -- Regards, Alexander Chemeris. CEO, Fairwaves, Inc. https://fairwaves.co From msuraev at sysmocom.de Wed Apr 20 11:07:21 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 20 Apr 2016 13:07:21 +0200 Subject: [PATCH 1/2] Cleanup shared data structure Message-ID: <1461150442-9253-1-git-send-email-msuraev@sysmocom.de> From: Max * remove unused variable. * lower max number of (e|u)arfcns to more realistic value. --- openbsc/include/openbsc/gsm_data_shared.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index cbc0c77..52e4805 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -105,7 +105,7 @@ struct gsm_abis_mo { #define A38_XOR_MAX_KEY_LEN 16 #define A38_COMP128_KEY_LEN 16 #define RSL_ENC_ALG_A5(x) (x+1) -#define MAX_EARFCN_LIST 512 +#define MAX_EARFCN_LIST 32 /* is the data link established? who established it? */ #define LCHAN_SAPI_UNUSED 0 @@ -716,7 +716,6 @@ struct gsm_bts { struct bitvec neigh_list; struct bitvec cell_alloc; struct bitvec si5_neigh_list; - struct bitvec si2quater_na_list; struct osmo_earfcn_si2q si2quater_neigh_list; struct { /* bitmask large enough for all possible ARFCN's */ -- 2.8.1 From msuraev at sysmocom.de Wed Apr 20 11:07:22 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 20 Apr 2016 13:07:22 +0200 Subject: [PATCH 2/2] Add basic UARFCN support In-Reply-To: <1461150442-9253-1-git-send-email-msuraev@sysmocom.de> References: <1461150442-9253-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1461150442-9253-2-git-send-email-msuraev@sysmocom.de> From: Max * add data structures, generation functions * vty interface for neightbor UARFCNs specific to SI2quater * vty test * unit test Fixes: OS#1666 --- openbsc/include/openbsc/gsm_data_shared.h | 3 + openbsc/include/openbsc/rest_octets.h | 5 +- openbsc/include/openbsc/system_information.h | 9 +- openbsc/src/libbsc/bsc_vty.c | 53 ++++++++++ openbsc/src/libbsc/rest_octets.c | 81 ++++++++++++++-- openbsc/src/libbsc/system_information.c | 139 ++++++++++++++++++++++++++- openbsc/tests/gsm0408/gsm0408_test.c | 75 +++++++++++---- openbsc/tests/gsm0408/gsm0408_test.ok | 14 ++- openbsc/tests/vty_test_runner.py | 23 +++++ 9 files changed, 366 insertions(+), 36 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 52e4805..8658fe7 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -717,6 +717,7 @@ struct gsm_bts { struct bitvec cell_alloc; struct bitvec si5_neigh_list; struct osmo_earfcn_si2q si2quater_neigh_list; + size_t uarfcn_length; /* index for uarfcn and scramble lists */ struct { /* bitmask large enough for all possible ARFCN's */ uint8_t neigh_list[1024/8]; @@ -725,6 +726,8 @@ struct gsm_bts { uint8_t si5_neigh_list[1024/8]; uint8_t meas_bw_list[MAX_EARFCN_LIST]; uint16_t earfcn_list[MAX_EARFCN_LIST]; + uint16_t uarfcn_list[MAX_EARFCN_LIST]; + uint16_t scramble_list[MAX_EARFCN_LIST]; } data; } si_common; diff --git a/openbsc/include/openbsc/rest_octets.h b/openbsc/include/openbsc/rest_octets.h index fd5ec6a..4dfbfb0 100644 --- a/openbsc/include/openbsc/rest_octets.h +++ b/openbsc/include/openbsc/rest_octets.h @@ -7,9 +7,8 @@ /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net); -int rest_octets_si2quater(uint8_t *data, - const struct osmo_earfcn_si2q *e, bool uarfcn, - bool earfcn); +int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, + const uint16_t *u, const uint16_t *sc, size_t u_len); struct gsm48_si_selection_params { uint16_t penalty_time:5, diff --git a/openbsc/include/openbsc/system_information.h b/openbsc/include/openbsc/system_information.h index 6a56848..ecc6964 100644 --- a/openbsc/include/openbsc/system_information.h +++ b/openbsc/include/openbsc/system_information.h @@ -6,5 +6,12 @@ struct gsm_bts; int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type); - +uint16_t encode_fdd(uint16_t scramble, bool diversity); +unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len); +unsigned earfcn_size(const struct osmo_earfcn_si2q *e); +unsigned range1024_p(unsigned n); +unsigned range512_q(unsigned m); +int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble); +int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, + bool diversity); #endif diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 85b8394..cc46865 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -707,6 +707,14 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) } } + for (i = 0; i < bts->si_common.uarfcn_length; i++) { + vty_out(vty, " si2quater neighbor-list add uarfcn %u %u %u%s", + bts->si_common.data.uarfcn_list[i], + bts->si_common.data.scramble_list[i] & ~(1 << 9), + (bts->si_common.data.scramble_list[i] >> 9) & 1, + VTY_NEWLINE); + } + vty_out(vty, " codec-support fr"); if (bts->codec.hr) vty_out(vty, " hr"); @@ -2813,6 +2821,49 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, + "si2quater neighbor-list add uarfcn <1900-2200> <0-511> <0-1>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" + "UARFCN of neighbor\n" "UARFCN of neighbor\n" "scrambling code\n" + "diversity bit\n") +{ + struct gsm_bts *bts = vty->index; + uint16_t arfcn = atoi(argv[0]), scramble = atoi(argv[1]); + + switch(bts_uarfcn_add(bts, arfcn, scramble, atoi(argv[2]))) { + case -ENOMEM: + vty_out(vty, "Unable to add arfcn: max number of UARFCNs (%u) " + "reached%s", MAX_EARFCN_LIST, VTY_NEWLINE); + case -EADDRINUSE: + vty_out(vty, "Unable to add arfcn: (%u, %u) is already added%s", + arfcn, scramble, VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd, + "si2quater neighbor-list del uarfcn <1900-2200> <0-511>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" + "Delete from SI2quater manual neighbor list\n" + "UARFCN of neighbor\n" + "UARFCN\n" + "scrambling code\n") +{ + struct gsm_bts *bts = vty->index; + + if (bts_uarfcn_del(bts, atoi(argv[0]), atoi(argv[1])) < 0) { + vty_out(vty, "Unable to delete uarfcn: pair not found%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd, "si5 neighbor-list (add|del) arfcn <0-1023>", "SI5 Neighbor List\n" @@ -3945,6 +3996,8 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd); install_element(BTS_NODE, &cfg_bts_si2quater_neigh_add_cmd); install_element(BTS_NODE, &cfg_bts_si2quater_neigh_del_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_add_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_del_cmd); install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_force_comb_si_cmd); diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index 113af5c..ba534a1 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -31,6 +31,7 @@ #include #include #include +#include #define SI2Q_MAX_LEN 160 @@ -188,11 +189,62 @@ static inline void append_earfcn(struct bitvec *bv, bitvec_set_bit(bv, L); } +static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u, + const uint16_t *sc, size_t length) +{ + int f0_inc, i, arfcns_used, w[RANGE_ENC_MAX_ARFCNS], a[length]; + uint8_t chan_list[16] = {0}; + + /* 3G Neighbour Cell Description */ + bitvec_set_bit(bv, 1); + /* No Index_Start_3G */ + bitvec_set_bit(bv, 0); + /* No Absolute_Index_Start_EMR */ + bitvec_set_bit(bv, 0); + + /* UTRAN FDD Description */ + bitvec_set_bit(bv, 1); + /* No Bandwidth_FDD */ + bitvec_set_bit(bv, 0); + + memset(w, 0, sizeof(w)); + for (i = 0; i < length; i++) + a[i] = sc[i]; + + /* Note: we do not support repeating Neighbour Cells ATM */ + /* Repeated UTRAN FDD Neighbour Cells */ + bitvec_set_bit(bv, 1); + + /* FDD-ARFCN */ + bitvec_set_bit(bv, 0); + /* Note: we do not support multiple UARFCN values ATM: */ + bitvec_set_uint(bv, u[0], 14); + + arfcns_used = range_enc_filter_arfcns(a, length, 0, &f0_inc); + range_enc_arfcns(ARFCN_RANGE_1024, a, arfcns_used, w, 0); + range_enc_range1024(chan_list, 0, f0_inc, w); + + /* FDD_Indic0: parameter value '0000000000' is not a member of the set */ + bitvec_set_bit(bv, f0_inc); + /* NR_OF_FDD_CELLS */ + bitvec_set_uint(bv, length, 5); + + i = bv->cur_bit; + bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list); + bv->cur_bit = i + range1024_p(length); + + /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */ + bitvec_set_bit(bv, 0); + + /* UTRAN TDD Description */ + bitvec_set_bit(bv, 0); +} + /* generate SI2quater rest octets: 3GPP TS 44.018 ? 10.5.2.33b */ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, - bool uarfcn, bool earfcn) + const uint16_t *u, const uint16_t *sc, size_t u_len) { - int rc; + unsigned sz; struct bitvec bv; bv.data = data; bv.data_len = 20; @@ -226,8 +278,17 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, /* No extension (length) */ bitvec_set_bit(&bv, 0); - if (uarfcn) { - + if (u_len) { + sz = uarfcn_size(u, sc, u_len); + /* Even if we do not append EARFCN we still need to set 3 bits */ + if (sz + bv.cur_bit + 3 > SI2Q_MAX_LEN) { + LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to " + "add UARFCNs bits, current %u + required %u + " + "reminder %u > max %u\n", bv.cur_bit, sz, 3, + SI2Q_MAX_LEN); + return -ENOMEM; + } + append_uarfcn(&bv, u, sc, u_len); } else { /* No 3G Neighbour Cell Description */ bitvec_set_bit(&bv, 0); } @@ -237,12 +298,14 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, /* No GPRS_3G_MEASUREMENT Parameters Descr. */ bitvec_set_bit(&bv, 0); - if (earfcn) { - rc = append_earfcn_size(e); - if (rc < 0) - return rc; - if (rc + bv.cur_bit > SI2Q_MAX_LEN) + if (e) { + sz = earfcn_size(e); + if (sz + bv.cur_bit > SI2Q_MAX_LEN) { + LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to " + "add EARFCNs bits, current %u + required %u > max " + "%u\n", bv.cur_bit, sz, SI2Q_MAX_LEN); return -ENOMEM; + } append_earfcn(&bv, e); } else { /* No Additions in Rel-5: */ diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 43a492a..c573c2a 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -68,6 +68,139 @@ static int is_dcs_net(const struct gsm_bts *bts) return 1; } +/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */ +unsigned range1024_p(unsigned n) +{ + switch (n) { + case 0: return 0; + case 1: return 10; + case 2: return 19; + case 3: return 28; + case 4: return 36; + case 5: return 44; + case 6: return 52; + case 7: return 60; + case 8: return 67; + case 9: return 74; + case 10: return 81; + case 11: return 88; + case 12: return 95; + case 13: return 102; + case 14: return 109; + case 15: return 116; + case 16: return 122; + default: return 0; + } +} + +/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1b, 3GPP TS 44.018 */ +unsigned range512_q(unsigned m) +{ + switch (m) { + case 0: return 0; + case 1: return 9; + case 2: return 17; + case 3: return 25; + case 4: return 32; + case 5: return 39; + case 6: return 46; + case 7: return 53; + case 8: return 59; + case 9: return 65; + case 10: return 71; + case 11: return 77; + case 12: return 83; + case 13: return 89; + case 14: return 95; + case 15: return 101; + case 16: return 106; + case 17: return 111; + case 18: return 116; + case 19: return 121; + case 20: return 126; + default: return 0; + } +} + +unsigned earfcn_size(const struct osmo_earfcn_si2q *e) +{ + /* account for all the constant bits in append_earfcn() */ + return 25 + osmo_earfcn_bit_size(e); +} + +unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len) +{ + /*account for all the constant bits in append_uarfcn() */ + return 29 + range1024_p(u_len); +} + +/* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */ +uint16_t encode_fdd(uint16_t scramble, bool diversity) +{ + if (diversity) + return scramble | (1 << 9); + return scramble; +} + +int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, + bool diversity) +{ + size_t len = bts->si_common.uarfcn_length, i, k; + uint16_t scr, chk, + *ual = bts->si_common.data.uarfcn_list, + *scl = bts->si_common.data.scramble_list, + scramble1 = encode_fdd(scramble, true), + scramble0 = encode_fdd(scramble, false); + + scr = diversity ? scramble1 : scramble0; + chk = diversity ? scramble0 : scramble1; + + if (len == MAX_EARFCN_LIST) + return -ENOMEM; + + for (i = 0, k = 0; i < len; i++) { + if (arfcn == ual[i] && (scr == scl[i] || chk == scl[i])) + return -EADDRINUSE; + if (scr > scl[i]) + k = i + 1; + } + /* we keep lists sorted by scramble code: + insert into appropriate position and move the tail */ + if (len - k) { + memmove(ual + k + 1, ual + k, (len - k) * 2); + memmove(scl + k + 1, scl + k, (len - k) * 2); + } + ual[k] = arfcn; + scl[k] = scr; + bts->si_common.uarfcn_length++; + return 0; +} + +int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble) +{ + uint16_t sc0 = encode_fdd(scramble, false), sc1 = encode_fdd(scramble, true), + *ual = bts->si_common.data.uarfcn_list, + *scl = bts->si_common.data.scramble_list; + size_t len = bts->si_common.uarfcn_length, i; + for (i = 0; i < len; i++) { + if (arfcn == ual[i] && (sc0 == scl[i] || sc1 == scl[i])) { + /* we rely on the assumption that (uarfcn, scramble) + tuple is unique in the lists */ + if (i != len - 1) { /* move the tail if necessary */ + memmove(ual + i, ual + i + 1, 2 * (len - i + 1)); + memmove(scl + i, scl + i + 1, 2 * (len - i + 1)); + } + break; + } + } + + if (i == len) + return -EINVAL; + + bts->si_common.uarfcn_length--; + return 0; +} + static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter, const bool pgsm, const int arfcn) { @@ -508,8 +641,10 @@ static int generate_si2quater(uint8_t *output, struct gsm_bts *bts) si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater; rc = rest_octets_si2quater(si2q->rest_octets, - &bts->si_common.si2quater_neigh_list, false, - true); + &bts->si_common.si2quater_neigh_list, + bts->si_common.data.uarfcn_list, + bts->si_common.data.scramble_list, + bts->si_common.uarfcn_length); if (rc < 0) return rc; diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index d6abce6..2d91b68 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -103,11 +103,55 @@ static inline void gen(struct gsm_bts *bts) printf("failed to generate SI2quater: %s\n", strerror(-r)); } -static inline void test_si2q(void) +static inline void test_si2q_u(void) { struct gsm_bts *bts; struct gsm_network *network = gsm_network_init(1, 1, NULL); - printf("Testing SYSINFO_TYPE_2quater generation:\n"); + printf("Testing SYSINFO_TYPE_2quater UARFCN generation:\n"); + + if (!network) + exit(1); + bts = gsm_bts_alloc(network); + + bts_uarfcn_add(bts, 1982, 13, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 44, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 61, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 89, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 113, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 123, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 56, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 72, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 223, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 14, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 88, 0); + gen(bts); +} + +static inline void test_si2q_e(void) +{ + struct gsm_bts *bts; + struct gsm_network *network = gsm_network_init(1, 1, NULL); + printf("Testing SYSINFO_TYPE_2quater EARFCN generation:\n"); if (!network) exit(1); @@ -230,11 +274,7 @@ static int test_single_range_encoding(int range, const int *orig_arfcns, f0, &f0_included); memset(w, 0, sizeof(w)); - rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0); - if (rc != 0) { - printf("Cannot compute range W(k), rc = %d\n", rc); - return 1; - } + range_enc_arfcns(range, arfcns, arfcns_used, w, 0); if (!silent) fprintf(stderr, "range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n", @@ -243,24 +283,20 @@ static int test_single_range_encoding(int range, const int *orig_arfcns, /* Select the range and the amount of bits needed */ switch (range) { case ARFCN_RANGE_128: - rc = range_enc_range128(chan_list, f0, w); + range_enc_range128(chan_list, f0, w); break; case ARFCN_RANGE_256: - rc = range_enc_range256(chan_list, f0, w); + range_enc_range256(chan_list, f0, w); break; case ARFCN_RANGE_512: - rc = range_enc_range512(chan_list, f0, w); + range_enc_range512(chan_list, f0, w); break; case ARFCN_RANGE_1024: - rc = range_enc_range1024(chan_list, f0, f0_included, w); + range_enc_range1024(chan_list, f0, f0_included, w); break; default: return 1; }; - if (rc != 0) { - printf("Cannot encode range, rc = %d\n", rc); - return 1; - } if (!silent) printf("chan_list = %s\n", @@ -471,8 +507,7 @@ static void test_print_encoding() break; } - rc = range_enc_range512(chan_list, (1 << 9) | 0x96, w); - VERIFY(rc, ==, 0); + range_enc_range512(chan_list, (1 << 9) | 0x96, w); printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list))); } @@ -496,8 +531,7 @@ static void test_si_range_helpers() printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs3[i] : -1); VERIFY(i, ==, 0); - i = range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); - VERIFY(i, ==, 0); + range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) { printf("w[%d]=%d\n", i, ws[i]); @@ -554,7 +588,8 @@ int main(int argc, char **argv) test_range_encoding(); test_gsm411_rp_ref_wrap(); - test_si2q(); + test_si2q_e(); + test_si2q_u(); printf("Done.\n"); return EXIT_SUCCESS; } diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 59319bf..565eac6 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -62,7 +62,7 @@ testing RP-Reference wrap Allocated reference: 255 Allocated reference: 0 Allocated reference: 1 -Testing SYSINFO_TYPE_2quater generation: +Testing SYSINFO_TYPE_2quater EARFCN generation: added EARFCN 1917 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be c8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b added EARFCN 1932 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 30 14 03 2b 2b 2b 2b 2b 2b 2b 2b added EARFCN 1937 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a0 a0 2b 2b 2b 2b 2b 2b @@ -70,4 +70,16 @@ added EARFCN 1945 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1 added EARFCN 1965 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b added EARFCN 1967 - failed to generate SI2quater: Cannot allocate memory added EARFCN 1982 - failed to generate SI2quater: Cannot allocate memory +Testing SYSINFO_TYPE_2quater UARFCN generation: +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 0c 1a 10 99 64 00 0b 2b 2b 2b 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 14 1a 1f 00 44 b2 00 03 2b 2b 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 18 58 12 f0 84 86 59 00 03 2b 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 20 58 2e f0 f2 04 86 59 00 03 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 28 58 2e 22 f2 4e 84 86 59 00 03 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 34 1a 64 26 5d f2 05 04 86 59 00 03 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 38 58 12 22 fd ce 8e 05 04 86 59 00 03 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 40 58 1d 22 fa ce 88 85 7b 00 44 b2 00 03 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 10 99 64 00 0b +failed to generate SI2quater: Cannot allocate memory +failed to generate SI2quater: Cannot allocate memory Done. diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 7f64a80..c088855 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -244,6 +244,29 @@ class TestVTYNITB(TestVTYGenericBSC): self.vty.command("si2quater neighbor-list del earfcn 1924") self.vty.command("si2quater neighbor-list del earfcn 2111") self.assertEquals(before, self.vty.command("show running-config")) + self.vty.command("si2quater neighbor-list add uarfcn 1976 13 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 38 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 44 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 120 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 140 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 163 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 166 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 217 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 224 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 225 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 226 1") + self.vty.command("si2quater neighbor-list del uarfcn 1976 13") + self.vty.command("si2quater neighbor-list del uarfcn 1976 38") + self.vty.command("si2quater neighbor-list del uarfcn 1976 44") + self.vty.command("si2quater neighbor-list del uarfcn 1976 120") + self.vty.command("si2quater neighbor-list del uarfcn 1976 140") + self.vty.command("si2quater neighbor-list del uarfcn 1976 163") + self.vty.command("si2quater neighbor-list del uarfcn 1976 166") + self.vty.command("si2quater neighbor-list del uarfcn 1976 217") + self.vty.command("si2quater neighbor-list del uarfcn 1976 224") + self.vty.command("si2quater neighbor-list del uarfcn 1976 225") + self.vty.command("si2quater neighbor-list del uarfcn 1976 226") + self.assertEquals(before, self.vty.command("show running-config")) def testEnableDisablePeriodicLU(self): self.vty.enable() -- 2.8.1 From laforge at gnumonks.org Wed Apr 20 12:42:34 2016 From: laforge at gnumonks.org (Harald Welte) Date: Wed, 20 Apr 2016 14:42:34 +0200 Subject: [PATCH 1/2] Add convolutional code generators for CS2/3 In-Reply-To: References: <1461011174-11851-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: <20160420124234.GG13194@nataraja> Hi Sylvain and Max, On Wed, Apr 20, 2016 at 07:13:16AM +0200, Sylvain Munaut wrote: > > src/gsm/conv_cs2_gen.c | 211 +++++++++++++++++++++++++++++ > > src/gsm/conv_cs3_gen.c | 299 ++++++++++++++++++++++++++++++++++++++++++ > > Why the _gen suffix ? > > If they're fully automatically generated, then the build process > should generate them, they should not be in the repo at all. As Max confirmed they're auto-generated, indeed it should be best to use python to generate them during build. I don't mind a build dependency on python. We cannot affor a runtime dependency on it, but that's not the question here. > > +extern const struct osmo_conv_code osmo_conv_gsm0503_cs2; > > +extern const struct osmo_conv_code osmo_conv_gsm0503_cs3; > > Looking at all the other symbol in osmogsm, it seems we deemed 'osmo_' > to be redudant and so maybe "gsm0503_conv_cs2" would fit better in the > naming scheme ? The problems with legacy namespace pollution ;) The general rule is 'anything we add should have an osmo_ prefix'. In some cases we might deviate from this, e.g. if we simply add a function to an existing part of the code. We don't have any gsm0503_ prefixed symbols so far, so I'm more in favor of the 'general rule'. But I don't have strong feelings about it, so let's probably keep it that way. > > +static const uint8_t osmo_conv_gsm0503_cs2_output[][2] = { > > All those being purely internal symbols, then don't need osmo_conv > either that's correct, so let's remove the prefix to avoid overly long lines. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From msuraev at sysmocom.de Wed Apr 20 13:57:12 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 20 Apr 2016 15:57:12 +0200 Subject: [PATCH 3/5] Cleanup shared data structure In-Reply-To: <1461160634-14128-1-git-send-email-msuraev@sysmocom.de> References: <1461160634-14128-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1461160634-14128-3-git-send-email-msuraev@sysmocom.de> From: Max * remove unused variable. * lower max number of (e|u)arfcns to more realistic value. --- openbsc/include/openbsc/gsm_data_shared.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index cbc0c77..52e4805 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -105,7 +105,7 @@ struct gsm_abis_mo { #define A38_XOR_MAX_KEY_LEN 16 #define A38_COMP128_KEY_LEN 16 #define RSL_ENC_ALG_A5(x) (x+1) -#define MAX_EARFCN_LIST 512 +#define MAX_EARFCN_LIST 32 /* is the data link established? who established it? */ #define LCHAN_SAPI_UNUSED 0 @@ -716,7 +716,6 @@ struct gsm_bts { struct bitvec neigh_list; struct bitvec cell_alloc; struct bitvec si5_neigh_list; - struct bitvec si2quater_na_list; struct osmo_earfcn_si2q si2quater_neigh_list; struct { /* bitmask large enough for all possible ARFCN's */ -- 2.8.1 From msuraev at sysmocom.de Wed Apr 20 13:57:13 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 20 Apr 2016 15:57:13 +0200 Subject: [PATCH 4/5] Add basic UARFCN support In-Reply-To: <1461160634-14128-1-git-send-email-msuraev@sysmocom.de> References: <1461160634-14128-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1461160634-14128-4-git-send-email-msuraev@sysmocom.de> From: Max * add data structures, generation functions * vty interface for neightbor UARFCNs specific to SI2quater * vty test * unit test Fixes: OS#1666 --- openbsc/include/openbsc/gsm_data_shared.h | 3 + openbsc/include/openbsc/rest_octets.h | 8 +- openbsc/include/openbsc/system_information.h | 9 +- openbsc/src/libbsc/bsc_vty.c | 53 ++++++++++ openbsc/src/libbsc/rest_octets.c | 91 ++++++++++++++---- openbsc/src/libbsc/system_information.c | 139 ++++++++++++++++++++++++++- openbsc/tests/gsm0408/gsm0408_test.c | 75 +++++++++++---- openbsc/tests/gsm0408/gsm0408_test.ok | 14 ++- openbsc/tests/vty_test_runner.py | 23 +++++ 9 files changed, 369 insertions(+), 46 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 52e4805..8658fe7 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -717,6 +717,7 @@ struct gsm_bts { struct bitvec cell_alloc; struct bitvec si5_neigh_list; struct osmo_earfcn_si2q si2quater_neigh_list; + size_t uarfcn_length; /* index for uarfcn and scramble lists */ struct { /* bitmask large enough for all possible ARFCN's */ uint8_t neigh_list[1024/8]; @@ -725,6 +726,8 @@ struct gsm_bts { uint8_t si5_neigh_list[1024/8]; uint8_t meas_bw_list[MAX_EARFCN_LIST]; uint16_t earfcn_list[MAX_EARFCN_LIST]; + uint16_t uarfcn_list[MAX_EARFCN_LIST]; + uint16_t scramble_list[MAX_EARFCN_LIST]; } data; } si_common; diff --git a/openbsc/include/openbsc/rest_octets.h b/openbsc/include/openbsc/rest_octets.h index fd5ec6a..32b9963 100644 --- a/openbsc/include/openbsc/rest_octets.h +++ b/openbsc/include/openbsc/rest_octets.h @@ -5,11 +5,13 @@ #include #include +#define SI2Q_MAX_LEN 160 +#define SI2Q_MIN_LEN 18 + /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net); -int rest_octets_si2quater(uint8_t *data, - const struct osmo_earfcn_si2q *e, bool uarfcn, - bool earfcn); +int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, + const uint16_t *u, const uint16_t *sc, size_t u_len); struct gsm48_si_selection_params { uint16_t penalty_time:5, diff --git a/openbsc/include/openbsc/system_information.h b/openbsc/include/openbsc/system_information.h index 6a56848..ecc6964 100644 --- a/openbsc/include/openbsc/system_information.h +++ b/openbsc/include/openbsc/system_information.h @@ -6,5 +6,12 @@ struct gsm_bts; int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type); - +uint16_t encode_fdd(uint16_t scramble, bool diversity); +unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len); +unsigned earfcn_size(const struct osmo_earfcn_si2q *e); +unsigned range1024_p(unsigned n); +unsigned range512_q(unsigned m); +int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble); +int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, + bool diversity); #endif diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 85b8394..cc46865 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -707,6 +707,14 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) } } + for (i = 0; i < bts->si_common.uarfcn_length; i++) { + vty_out(vty, " si2quater neighbor-list add uarfcn %u %u %u%s", + bts->si_common.data.uarfcn_list[i], + bts->si_common.data.scramble_list[i] & ~(1 << 9), + (bts->si_common.data.scramble_list[i] >> 9) & 1, + VTY_NEWLINE); + } + vty_out(vty, " codec-support fr"); if (bts->codec.hr) vty_out(vty, " hr"); @@ -2813,6 +2821,49 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, + "si2quater neighbor-list add uarfcn <1900-2200> <0-511> <0-1>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" + "UARFCN of neighbor\n" "UARFCN of neighbor\n" "scrambling code\n" + "diversity bit\n") +{ + struct gsm_bts *bts = vty->index; + uint16_t arfcn = atoi(argv[0]), scramble = atoi(argv[1]); + + switch(bts_uarfcn_add(bts, arfcn, scramble, atoi(argv[2]))) { + case -ENOMEM: + vty_out(vty, "Unable to add arfcn: max number of UARFCNs (%u) " + "reached%s", MAX_EARFCN_LIST, VTY_NEWLINE); + case -EADDRINUSE: + vty_out(vty, "Unable to add arfcn: (%u, %u) is already added%s", + arfcn, scramble, VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd, + "si2quater neighbor-list del uarfcn <1900-2200> <0-511>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" + "Delete from SI2quater manual neighbor list\n" + "UARFCN of neighbor\n" + "UARFCN\n" + "scrambling code\n") +{ + struct gsm_bts *bts = vty->index; + + if (bts_uarfcn_del(bts, atoi(argv[0]), atoi(argv[1])) < 0) { + vty_out(vty, "Unable to delete uarfcn: pair not found%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd, "si5 neighbor-list (add|del) arfcn <0-1023>", "SI5 Neighbor List\n" @@ -3945,6 +3996,8 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd); install_element(BTS_NODE, &cfg_bts_si2quater_neigh_add_cmd); install_element(BTS_NODE, &cfg_bts_si2quater_neigh_del_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_add_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_del_cmd); install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_force_comb_si_cmd); diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index 113af5c..b59430b 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -31,8 +31,7 @@ #include #include #include - -#define SI2Q_MAX_LEN 160 +#include /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net) @@ -108,14 +107,6 @@ static inline void append_eutran_neib_cell(struct bitvec *bv, bitvec_set_bit(bv, 0); } -static inline int append_earfcn_size(const struct osmo_earfcn_si2q *e) -{ - if (!e) - return -EFAULT; - /* account for all the constant bits */ - return 25 + osmo_earfcn_bit_size(e); -} - static inline void append_earfcn(struct bitvec *bv, const struct osmo_earfcn_si2q *e) { @@ -188,11 +179,62 @@ static inline void append_earfcn(struct bitvec *bv, bitvec_set_bit(bv, L); } +static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u, + const uint16_t *sc, size_t length) +{ + int f0_inc, i, arfcns_used, w[RANGE_ENC_MAX_ARFCNS], a[length]; + uint8_t chan_list[16] = {0}; + + /* 3G Neighbour Cell Description */ + bitvec_set_bit(bv, 1); + /* No Index_Start_3G */ + bitvec_set_bit(bv, 0); + /* No Absolute_Index_Start_EMR */ + bitvec_set_bit(bv, 0); + + /* UTRAN FDD Description */ + bitvec_set_bit(bv, 1); + /* No Bandwidth_FDD */ + bitvec_set_bit(bv, 0); + + memset(w, 0, sizeof(w)); + for (i = 0; i < length; i++) + a[i] = sc[i]; + + /* Note: we do not support repeating Neighbour Cells ATM */ + /* Repeated UTRAN FDD Neighbour Cells */ + bitvec_set_bit(bv, 1); + + /* FDD-ARFCN */ + bitvec_set_bit(bv, 0); + /* Note: we do not support multiple UARFCN values ATM: */ + bitvec_set_uint(bv, u[0], 14); + + arfcns_used = range_enc_filter_arfcns(a, length, 0, &f0_inc); + range_enc_arfcns(ARFCN_RANGE_1024, a, arfcns_used, w, 0); + range_enc_range1024(chan_list, 0, f0_inc, w); + + /* FDD_Indic0: parameter value '0000000000' is not a member of the set */ + bitvec_set_bit(bv, f0_inc); + /* NR_OF_FDD_CELLS */ + bitvec_set_uint(bv, length, 5); + + i = bv->cur_bit; + bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list); + bv->cur_bit = i + range1024_p(length); + + /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */ + bitvec_set_bit(bv, 0); + + /* UTRAN TDD Description */ + bitvec_set_bit(bv, 0); +} + /* generate SI2quater rest octets: 3GPP TS 44.018 ? 10.5.2.33b */ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, - bool uarfcn, bool earfcn) + const uint16_t *u, const uint16_t *sc, size_t u_len) { - int rc; + unsigned sz; struct bitvec bv; bv.data = data; bv.data_len = 20; @@ -226,8 +268,17 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, /* No extension (length) */ bitvec_set_bit(&bv, 0); - if (uarfcn) { - + if (u_len) { + sz = uarfcn_size(u, sc, u_len); + /* Even if we do not append EARFCN we still need to set 3 bits */ + if (sz + bv.cur_bit + 3 > SI2Q_MAX_LEN) { + LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to " + "add UARFCNs bits, current %u + required %u + " + "reminder %u > max %u\n", bv.cur_bit, sz, 3, + SI2Q_MAX_LEN); + return -ENOMEM; + } + append_uarfcn(&bv, u, sc, u_len); } else { /* No 3G Neighbour Cell Description */ bitvec_set_bit(&bv, 0); } @@ -237,12 +288,14 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, /* No GPRS_3G_MEASUREMENT Parameters Descr. */ bitvec_set_bit(&bv, 0); - if (earfcn) { - rc = append_earfcn_size(e); - if (rc < 0) - return rc; - if (rc + bv.cur_bit > SI2Q_MAX_LEN) + if (e) { + sz = earfcn_size(e); + if (sz + bv.cur_bit > SI2Q_MAX_LEN) { + LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to " + "add EARFCNs bits, current %u + required %u > max " + "%u\n", bv.cur_bit, sz, SI2Q_MAX_LEN); return -ENOMEM; + } append_earfcn(&bv, e); } else { /* No Additions in Rel-5: */ diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 43a492a..8952534 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -68,6 +68,139 @@ static int is_dcs_net(const struct gsm_bts *bts) return 1; } +/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */ +unsigned range1024_p(unsigned n) +{ + switch (n) { + case 0: return 0; + case 1: return 10; + case 2: return 19; + case 3: return 28; + case 4: return 36; + case 5: return 44; + case 6: return 52; + case 7: return 60; + case 8: return 67; + case 9: return 74; + case 10: return 81; + case 11: return 88; + case 12: return 95; + case 13: return 102; + case 14: return 109; + case 15: return 116; + case 16: return 122; + default: return 0; + } +} + +/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1b, 3GPP TS 44.018 */ +unsigned range512_q(unsigned m) +{ + switch (m) { + case 0: return 0; + case 1: return 9; + case 2: return 17; + case 3: return 25; + case 4: return 32; + case 5: return 39; + case 6: return 46; + case 7: return 53; + case 8: return 59; + case 9: return 65; + case 10: return 71; + case 11: return 77; + case 12: return 83; + case 13: return 89; + case 14: return 95; + case 15: return 101; + case 16: return 106; + case 17: return 111; + case 18: return 116; + case 19: return 121; + case 20: return 126; + default: return 0; + } +} + +unsigned earfcn_size(const struct osmo_earfcn_si2q *e) +{ + /* account for all the constant bits in append_earfcn() */ + return 25 + osmo_earfcn_bit_size(e); +} + +unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len) +{ + /*account for all the constant bits in append_uarfcn() */ + return 29 + range1024_p(u_len); +} + +/* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */ +uint16_t encode_fdd(uint16_t scramble, bool diversity) +{ + if (diversity) + return scramble | (1 << 9); + return scramble; +} + +int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble) +{ + uint16_t sc0 = encode_fdd(scramble, false), sc1 = encode_fdd(scramble, true), + *ual = bts->si_common.data.uarfcn_list, + *scl = bts->si_common.data.scramble_list; + size_t len = bts->si_common.uarfcn_length, i; + for (i = 0; i < len; i++) { + if (arfcn == ual[i] && (sc0 == scl[i] || sc1 == scl[i])) { + /* we rely on the assumption that (uarfcn, scramble) + tuple is unique in the lists */ + if (i != len - 1) { /* move the tail if necessary */ + memmove(ual + i, ual + i + 1, 2 * (len - i + 1)); + memmove(scl + i, scl + i + 1, 2 * (len - i + 1)); + } + break; + } + } + + if (i == len) + return -EINVAL; + + bts->si_common.uarfcn_length--; + return 0; +} + +int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, + bool diversity) +{ + size_t len = bts->si_common.uarfcn_length, i, k; + uint16_t scr, chk, + *ual = bts->si_common.data.uarfcn_list, + *scl = bts->si_common.data.scramble_list, + scramble1 = encode_fdd(scramble, true), + scramble0 = encode_fdd(scramble, false); + + scr = diversity ? scramble1 : scramble0; + chk = diversity ? scramble0 : scramble1; + + if (len == MAX_EARFCN_LIST) + return -ENOMEM; + + for (i = 0, k = 0; i < len; i++) { + if (arfcn == ual[i] && (scr == scl[i] || chk == scl[i])) + return -EADDRINUSE; + if (scr > scl[i]) + k = i + 1; + } + /* we keep lists sorted by scramble code: + insert into appropriate position and move the tail */ + if (len - k) { + memmove(ual + k + 1, ual + k, (len - k) * 2); + memmove(scl + k + 1, scl + k, (len - k) * 2); + } + ual[k] = arfcn; + scl[k] = scr; + bts->si_common.uarfcn_length++; + return 0; +} + static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter, const bool pgsm, const int arfcn) { @@ -508,8 +641,10 @@ static int generate_si2quater(uint8_t *output, struct gsm_bts *bts) si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater; rc = rest_octets_si2quater(si2q->rest_octets, - &bts->si_common.si2quater_neigh_list, false, - true); + &bts->si_common.si2quater_neigh_list, + bts->si_common.data.uarfcn_list, + bts->si_common.data.scramble_list, + bts->si_common.uarfcn_length); if (rc < 0) return rc; diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index d6abce6..2d91b68 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -103,11 +103,55 @@ static inline void gen(struct gsm_bts *bts) printf("failed to generate SI2quater: %s\n", strerror(-r)); } -static inline void test_si2q(void) +static inline void test_si2q_u(void) { struct gsm_bts *bts; struct gsm_network *network = gsm_network_init(1, 1, NULL); - printf("Testing SYSINFO_TYPE_2quater generation:\n"); + printf("Testing SYSINFO_TYPE_2quater UARFCN generation:\n"); + + if (!network) + exit(1); + bts = gsm_bts_alloc(network); + + bts_uarfcn_add(bts, 1982, 13, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 44, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 61, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 89, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 113, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 123, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 56, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 72, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 223, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 14, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 88, 0); + gen(bts); +} + +static inline void test_si2q_e(void) +{ + struct gsm_bts *bts; + struct gsm_network *network = gsm_network_init(1, 1, NULL); + printf("Testing SYSINFO_TYPE_2quater EARFCN generation:\n"); if (!network) exit(1); @@ -230,11 +274,7 @@ static int test_single_range_encoding(int range, const int *orig_arfcns, f0, &f0_included); memset(w, 0, sizeof(w)); - rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0); - if (rc != 0) { - printf("Cannot compute range W(k), rc = %d\n", rc); - return 1; - } + range_enc_arfcns(range, arfcns, arfcns_used, w, 0); if (!silent) fprintf(stderr, "range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n", @@ -243,24 +283,20 @@ static int test_single_range_encoding(int range, const int *orig_arfcns, /* Select the range and the amount of bits needed */ switch (range) { case ARFCN_RANGE_128: - rc = range_enc_range128(chan_list, f0, w); + range_enc_range128(chan_list, f0, w); break; case ARFCN_RANGE_256: - rc = range_enc_range256(chan_list, f0, w); + range_enc_range256(chan_list, f0, w); break; case ARFCN_RANGE_512: - rc = range_enc_range512(chan_list, f0, w); + range_enc_range512(chan_list, f0, w); break; case ARFCN_RANGE_1024: - rc = range_enc_range1024(chan_list, f0, f0_included, w); + range_enc_range1024(chan_list, f0, f0_included, w); break; default: return 1; }; - if (rc != 0) { - printf("Cannot encode range, rc = %d\n", rc); - return 1; - } if (!silent) printf("chan_list = %s\n", @@ -471,8 +507,7 @@ static void test_print_encoding() break; } - rc = range_enc_range512(chan_list, (1 << 9) | 0x96, w); - VERIFY(rc, ==, 0); + range_enc_range512(chan_list, (1 << 9) | 0x96, w); printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list))); } @@ -496,8 +531,7 @@ static void test_si_range_helpers() printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs3[i] : -1); VERIFY(i, ==, 0); - i = range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); - VERIFY(i, ==, 0); + range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) { printf("w[%d]=%d\n", i, ws[i]); @@ -554,7 +588,8 @@ int main(int argc, char **argv) test_range_encoding(); test_gsm411_rp_ref_wrap(); - test_si2q(); + test_si2q_e(); + test_si2q_u(); printf("Done.\n"); return EXIT_SUCCESS; } diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 59319bf..565eac6 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -62,7 +62,7 @@ testing RP-Reference wrap Allocated reference: 255 Allocated reference: 0 Allocated reference: 1 -Testing SYSINFO_TYPE_2quater generation: +Testing SYSINFO_TYPE_2quater EARFCN generation: added EARFCN 1917 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be c8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b added EARFCN 1932 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 30 14 03 2b 2b 2b 2b 2b 2b 2b 2b added EARFCN 1937 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a0 a0 2b 2b 2b 2b 2b 2b @@ -70,4 +70,16 @@ added EARFCN 1945 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1 added EARFCN 1965 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b added EARFCN 1967 - failed to generate SI2quater: Cannot allocate memory added EARFCN 1982 - failed to generate SI2quater: Cannot allocate memory +Testing SYSINFO_TYPE_2quater UARFCN generation: +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 0c 1a 10 99 64 00 0b 2b 2b 2b 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 14 1a 1f 00 44 b2 00 03 2b 2b 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 18 58 12 f0 84 86 59 00 03 2b 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 20 58 2e f0 f2 04 86 59 00 03 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 28 58 2e 22 f2 4e 84 86 59 00 03 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 34 1a 64 26 5d f2 05 04 86 59 00 03 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 38 58 12 22 fd ce 8e 05 04 86 59 00 03 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 40 58 1d 22 fa ce 88 85 7b 00 44 b2 00 03 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 10 99 64 00 0b +failed to generate SI2quater: Cannot allocate memory +failed to generate SI2quater: Cannot allocate memory Done. diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 7f64a80..c088855 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -244,6 +244,29 @@ class TestVTYNITB(TestVTYGenericBSC): self.vty.command("si2quater neighbor-list del earfcn 1924") self.vty.command("si2quater neighbor-list del earfcn 2111") self.assertEquals(before, self.vty.command("show running-config")) + self.vty.command("si2quater neighbor-list add uarfcn 1976 13 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 38 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 44 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 120 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 140 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 163 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 166 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 217 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 224 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 225 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 226 1") + self.vty.command("si2quater neighbor-list del uarfcn 1976 13") + self.vty.command("si2quater neighbor-list del uarfcn 1976 38") + self.vty.command("si2quater neighbor-list del uarfcn 1976 44") + self.vty.command("si2quater neighbor-list del uarfcn 1976 120") + self.vty.command("si2quater neighbor-list del uarfcn 1976 140") + self.vty.command("si2quater neighbor-list del uarfcn 1976 163") + self.vty.command("si2quater neighbor-list del uarfcn 1976 166") + self.vty.command("si2quater neighbor-list del uarfcn 1976 217") + self.vty.command("si2quater neighbor-list del uarfcn 1976 224") + self.vty.command("si2quater neighbor-list del uarfcn 1976 225") + self.vty.command("si2quater neighbor-list del uarfcn 1976 226") + self.assertEquals(before, self.vty.command("show running-config")) def testEnableDisablePeriodicLU(self): self.vty.enable() -- 2.8.1 From msuraev at sysmocom.de Wed Apr 20 13:57:14 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 20 Apr 2016 15:57:14 +0200 Subject: [PATCH 5/5] Add vty check for max si2quater size In-Reply-To: <1461160634-14128-1-git-send-email-msuraev@sysmocom.de> References: <1461160634-14128-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1461160634-14128-5-git-send-email-msuraev@sysmocom.de> From: Max Explicitly check if added (U|E)ARFCN will fit into available si2quater message. --- openbsc/include/openbsc/system_information.h | 1 + openbsc/src/libbsc/bsc_vty.c | 23 +++++++----- openbsc/src/libbsc/system_information.c | 21 ++++++++++- openbsc/tests/gsm0408/gsm0408_test.c | 52 +++++++++++----------------- openbsc/tests/gsm0408/gsm0408_test.ok | 5 +-- 5 files changed, 60 insertions(+), 42 deletions(-) diff --git a/openbsc/include/openbsc/system_information.h b/openbsc/include/openbsc/system_information.h index ecc6964..7e3ceaa 100644 --- a/openbsc/include/openbsc/system_information.h +++ b/openbsc/include/openbsc/system_information.h @@ -11,6 +11,7 @@ unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len); unsigned earfcn_size(const struct osmo_earfcn_si2q *e); unsigned range1024_p(unsigned n); unsigned range512_q(unsigned m); +bool si2q_size_check(const struct gsm_bts *bts); int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble); int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, bool diversity); diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index cc46865..e81308b 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2789,15 +2789,19 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, VTY_NEWLINE); return CMD_WARNING; } + if (si2q_size_check(bts)) { + if (e->thresh_hi && thresh != e->thresh_hi) + vty_out(vty, "Warning: multiple thresholds are not " + "supported, overriding previous threshold %u%s", + e->thresh_hi, VTY_NEWLINE); - if (e->thresh_hi && thresh != e->thresh_hi) - vty_out(vty, "Warning: multiple thresholds are not supported, " - "overriding previous threshold %u%s", - e->thresh_hi, VTY_NEWLINE); - - e->thresh_hi = thresh; - - return CMD_SUCCESS; + e->thresh_hi = thresh; + return CMD_SUCCESS; + } + vty_out(vty, "Warning: not enough space in si2quater for a given arfcn%s" + , VTY_NEWLINE); + osmo_earfcn_del(e, arfcn); + return CMD_WARNING; } DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, @@ -2835,6 +2839,9 @@ DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, case -ENOMEM: vty_out(vty, "Unable to add arfcn: max number of UARFCNs (%u) " "reached%s", MAX_EARFCN_LIST, VTY_NEWLINE); + case -ENOSPC: + vty_out(vty, "Warning: not enough space in si2quater for a " + "given arfcn%s", VTY_NEWLINE); case -EADDRINUSE: vty_out(vty, "Unable to add arfcn: (%u, %u) is already added%s", arfcn, scramble, VTY_NEWLINE); diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 8952534..3b0f889 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -134,6 +134,20 @@ unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len) return 29 + range1024_p(u_len); } +bool si2q_size_check(const struct gsm_bts *bts) +{ + const struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; + const uint16_t *u = bts->si_common.data.uarfcn_list, + *sc = bts->si_common.data.scramble_list; + size_t len = bts->si_common.uarfcn_length; + unsigned e_sz = e ? earfcn_size(e) : 1, + u_sz = len ? uarfcn_size(u, sc, len) : 1; + /* 2 bits are used in between UARFCN and EARFCN structs */ + if (SI2Q_MIN_LEN + u_sz + 2 + e_sz > SI2Q_MAX_LEN) + return false; + return true; +} + /* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */ uint16_t encode_fdd(uint16_t scramble, bool diversity) { @@ -198,7 +212,12 @@ int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, ual[k] = arfcn; scl[k] = scr; bts->si_common.uarfcn_length++; - return 0; + + if (si2q_size_check(bts)) + return 0; + + bts_uarfcn_del(bts, arfcn, scramble); + return -ENOSPC; } static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter, diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 2d91b68..9262667 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -103,6 +103,16 @@ static inline void gen(struct gsm_bts *bts) printf("failed to generate SI2quater: %s\n", strerror(-r)); } +static inline void _bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, + uint16_t scramble, bool diversity) +{ + int r = bts_uarfcn_add(bts, arfcn, scramble, diversity); + if (r < 0) + printf("failed to add UARFCN to SI2quater: %s\n", strerror(-r)); + else + gen(bts); +} + static inline void test_si2q_u(void) { struct gsm_bts *bts; @@ -113,37 +123,17 @@ static inline void test_si2q_u(void) exit(1); bts = gsm_bts_alloc(network); - bts_uarfcn_add(bts, 1982, 13, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 44, 0); - gen(bts); - - bts_uarfcn_add(bts, 1982, 61, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 89, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 113, 0); - gen(bts); - - bts_uarfcn_add(bts, 1982, 123, 0); - gen(bts); - - bts_uarfcn_add(bts, 1982, 56, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 72, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 223, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 14, 0); - gen(bts); - - bts_uarfcn_add(bts, 1982, 88, 0); + _bts_uarfcn_add(bts, 1982, 13, 1); + _bts_uarfcn_add(bts, 1982, 44, 0); + _bts_uarfcn_add(bts, 1982, 61, 1); + _bts_uarfcn_add(bts, 1982, 89, 1); + _bts_uarfcn_add(bts, 1982, 113, 0); + _bts_uarfcn_add(bts, 1982, 123, 0); + _bts_uarfcn_add(bts, 1982, 56, 1); + _bts_uarfcn_add(bts, 1982, 72, 1); + _bts_uarfcn_add(bts, 1982, 223, 1); + _bts_uarfcn_add(bts, 1982, 14, 0); + _bts_uarfcn_add(bts, 1982, 88, 0); gen(bts); } diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 565eac6..7b7a2cc 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -80,6 +80,7 @@ generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 34 1a 64 26 5d f2 05 04 86 59 generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 38 58 12 22 fd ce 8e 05 04 86 59 00 03 2b 2b generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 40 58 1d 22 fa ce 88 85 7b 00 44 b2 00 03 2b generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 10 99 64 00 0b -failed to generate SI2quater: Cannot allocate memory -failed to generate SI2quater: Cannot allocate memory +failed to add UARFCN to SI2quater: No space left on device +failed to add UARFCN to SI2quater: No space left on device +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 10 99 64 00 0b Done. -- 2.8.1 From msuraev at sysmocom.de Wed Apr 20 13:57:10 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 20 Apr 2016 15:57:10 +0200 Subject: [PATCH 1/5] Fix documentation for command parameters Message-ID: <1461160634-14128-1-git-send-email-msuraev@sysmocom.de> From: Max --- openbsc/src/libbsc/bsc_vty.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 9634508..3a699c4 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2797,7 +2797,8 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" - "EARFCN of neighbor\n") + "EARFCN of neighbor\n" + "EARFCN\n") { struct gsm_bts *bts = vty->index; struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; -- 2.8.1 From msuraev at sysmocom.de Wed Apr 20 13:57:11 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 20 Apr 2016 15:57:11 +0200 Subject: [PATCH 2/5] Fix earfcn deletion In-Reply-To: <1461160634-14128-1-git-send-email-msuraev@sysmocom.de> References: <1461160634-14128-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1461160634-14128-2-git-send-email-msuraev@sysmocom.de> From: Max * fix typo in arg index * fix sign in error reporting * add vty test --- openbsc/src/libbsc/bsc_vty.c | 4 ++-- openbsc/tests/vty_test_runner.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 3a699c4..85b8394 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2802,11 +2802,11 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, { struct gsm_bts *bts = vty->index; struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; - uint16_t arfcn = atoi(argv[1]); + uint16_t arfcn = atoi(argv[0]); int r = osmo_earfcn_del(e, arfcn); if (r < 0) { vty_out(vty, "Unable to delete arfcn %u: %s%s", arfcn, - strerror(r), VTY_NEWLINE); + strerror(-r), VTY_NEWLINE); return CMD_WARNING; } diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 143ba5d..7f64a80 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -231,6 +231,20 @@ class TestVTYNITB(TestVTYGenericBSC): self.assertEquals(self.vty.node(), 'config-mncc-int') + def testSi2Q(self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("network") + self.vty.command("bts 0") + before = self.vty.command("show running-config") + self.vty.command("si2quater neighbor-list add earfcn 1911 threshold 11 2") + self.vty.command("si2quater neighbor-list add earfcn 1924 threshold 11 3") + self.vty.command("si2quater neighbor-list add earfcn 2111 threshold 11") + self.vty.command("si2quater neighbor-list del earfcn 1911") + self.vty.command("si2quater neighbor-list del earfcn 1924") + self.vty.command("si2quater neighbor-list del earfcn 2111") + self.assertEquals(before, self.vty.command("show running-config")) + def testEnableDisablePeriodicLU(self): self.vty.enable() self.vty.command("configure terminal") -- 2.8.1 From msuraev at sysmocom.de Wed Apr 20 15:36:38 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Wed, 20 Apr 2016 17:36:38 +0200 Subject: [PATCH] Add code generator for convolutional codes Message-ID: <1461166598-11997-1-git-send-email-msuraev@sysmocom.de> From: Max Add python utility to generate .c code with convolutional encoder/decoder based on polynomial description of the code. If argument given it'll be interpreted as intended output directory, otherwise current working directory is used. Codes for *CCH, CS2/3 and TCH/AFS are generated. Corresponding manual implementations are removed from tests. The main work for this patch was generously contributed by Sylvain Munaut. Fixes: OS#1629 --- .gitignore | 1 + include/Makefile.am | 1 + include/osmocom/gsm/gsm0503.h | 74 ++++++ src/gsm/Makefile.am | 8 + src/gsm/libosmogsm.map | 12 + tests/Makefile.am | 2 +- tests/conv/conv_test.c | 283 ++++++++--------------- utils/conv_gen.py | 509 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 695 insertions(+), 195 deletions(-) create mode 100644 include/osmocom/gsm/gsm0503.h create mode 100755 utils/conv_gen.py diff --git a/.gitignore b/.gitignore index f73a533..e3dbcac 100644 --- a/.gitignore +++ b/.gitignore @@ -100,6 +100,7 @@ doc/gsm doc/html.tar src/crc*gen.c +src/gsm/conv*gen.c include/osmocom/core/crc*gen.h include/osmocom/core/bit*gen.h diff --git a/include/Makefile.am b/include/Makefile.am index 0e5ed74..e7888c5 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -64,6 +64,7 @@ nobase_include_HEADERS = \ osmocom/gsm/gsm0411_utils.h \ osmocom/gsm/gsm0480.h \ osmocom/gsm/gsm0502.h \ + osmocom/gsm/gsm0503.h \ osmocom/gsm/gsm0808.h \ osmocom/gsm/gsm48.h \ osmocom/gsm/gsm48_ie.h \ diff --git a/include/osmocom/gsm/gsm0503.h b/include/osmocom/gsm/gsm0503.h new file mode 100644 index 0000000..cf1c976 --- /dev/null +++ b/include/osmocom/gsm/gsm0503.h @@ -0,0 +1,74 @@ +/* + * gsm0503.h + * + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include + +#include + +/*! \file conv_gen.h + * Osmocom convolutional encoder/decoder for xCCH channels, see 3GPP TS 05.03 + */ + +/*! \brief structure describing convolutional code xCCH + * + * Non-recursive code, flushed, not punctured code. + */ +extern const struct osmo_conv_code gsm0503_xcch; + +/*! \brief structures describing convolutional codes CS2/3 + */ +extern const struct osmo_conv_code gsm0503_cs2; +extern const struct osmo_conv_code gsm0503_cs3; + +/*! \brief structure describing convolutional code TCH/AFS 12.2 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_12_2; + +/*! \brief structure describing convolutional code TCH/AFS 10.2 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_10_2; + +/*! \brief structure describing convolutional code TCH/AFS 7.95 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_7_95; + +/*! \brief structure describing convolutional code TCH/AFS 7.4 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_7_4; + +/*! \brief structure describing convolutional code TCH/AFS 6.7 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_6_7; + +/*! \brief structure describing convolutional code TCH/AFS 5.9 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_5_9; + +/*! \brief structure describing convolutional code TCH/AFS 5.15 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_5_15; + +/*! \brief structure describing convolutional code TCH/AFS 4.75 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_4_75; diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index b0ea643..1b186b1 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -18,6 +18,11 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \ gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \ gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \ lapd_core.c lapdm.c kasumi.c \ + conv_cs2_gen.c conv_cs3_gen.c conv_xcch_gen.c \ + conv_tch_afs_12_2_gen.c conv_tch_afs_10_2_gen.c \ + conv_tch_afs_7_95_gen.c conv_tch_afs_7_4_gen.c \ + conv_tch_afs_6_7_gen.c conv_tch_afs_5_9_gen.c \ + conv_tch_afs_5_15_gen.c conv_tch_afs_4_75_gen.c \ auth_core.c auth_comp128v1.c auth_comp128v23.c \ auth_milenage.c milenage/aes-encblock.c \ milenage/aes-internal.c milenage/aes-internal-enc.c \ @@ -30,3 +35,6 @@ libosmogsm_la_LDFLAGS = $(LTLDFLAGS_OSMOGSM) -version-info $(LIBVERSION) -no-und libosmogsm_la_LIBADD = libgsmint.la EXTRA_DIST = libosmogsm.map + +conv%gen.c: ../../utils/conv_gen.py + $(AM_V_GEN)python ../../utils/conv_gen.py diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 6886a6c..a75acc0 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -26,6 +26,18 @@ abis_nm_ipa_magic; osmo_sitype_strs; +gsm0503_xcch; +gsm0503_cs2; +gsm0503_cs3; +gsm0503_tch_afs_12_2; +gsm0503_tch_afs_10_2; +gsm0503_tch_afs_7_95; +gsm0503_tch_afs_7_4; +gsm0503_tch_afs_6_7; +gsm0503_tch_afs_5_9; +gsm0503_tch_afs_5_15; +gsm0503_tch_afs_4_75; + comp128; dbm2rxlev; diff --git a/tests/Makefile.am b/tests/Makefile.am index 03506af..3aaa99b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -47,7 +47,7 @@ bits_bitcomp_test_SOURCES = bits/bitcomp_test.c bits_bitcomp_test_LDADD = $(top_builddir)/src/libosmocore.la conv_conv_test_SOURCES = conv/conv_test.c -conv_conv_test_LDADD = $(top_builddir)/src/libosmocore.la +conv_conv_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libgsmint.la gsm0808_gsm0808_test_SOURCES = gsm0808/gsm0808_test.c gsm0808_gsm0808_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index de62f23..608f829 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -6,6 +6,7 @@ #include #include #include +#include #define MAX_LEN_BITS 512 #define MAX_LEN_BYTES (512/8) @@ -15,107 +16,6 @@ /* Test codes */ /* ------------------------------------------------------------------------ */ -/* GSM xCCH -> Non-recursive code, flushed, not punctured */ -static const uint8_t conv_gsm_xcch_next_output[][2] = { - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, -}; - -static const uint8_t conv_gsm_xcch_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, -}; - -static const struct osmo_conv_code conv_gsm_xcch = { - .N = 2, - .K = 5, - .len = 224, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, -}; - - -/* GSM TCH/AFS 7.95 -> Recursive code, flushed, with puncturing */ -static const uint8_t conv_gsm_tch_afs_7_95_next_output[][2] = { - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 5, 4 }, { 7, 6 }, - { 9, 8 }, { 11, 10 }, { 12, 13 }, { 14, 15 }, - { 16, 17 }, { 18, 19 }, { 21, 20 }, { 23, 22 }, - { 25, 24 }, { 27, 26 }, { 28, 29 }, { 30, 31 }, - { 33, 32 }, { 35, 34 }, { 36, 37 }, { 38, 39 }, - { 40, 41 }, { 42, 43 }, { 45, 44 }, { 47, 46 }, - { 49, 48 }, { 51, 50 }, { 52, 53 }, { 54, 55 }, - { 56, 57 }, { 58, 59 }, { 61, 60 }, { 63, 62 }, - { 1, 0 }, { 3, 2 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 13, 12 }, { 15, 14 }, - { 17, 16 }, { 19, 18 }, { 20, 21 }, { 22, 23 }, - { 24, 25 }, { 26, 27 }, { 29, 28 }, { 31, 30 }, - { 32, 33 }, { 34, 35 }, { 37, 36 }, { 39, 38 }, - { 41, 40 }, { 43, 42 }, { 44, 45 }, { 46, 47 }, - { 48, 49 }, { 50, 51 }, { 53, 52 }, { 55, 54 }, - { 57, 56 }, { 59, 58 }, { 60, 61 }, { 62, 63 }, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_term_output[] = { - 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5, 6, 5, 3, 0, - 4, 7, 1, 2, 1, 2, 4, 7, 7, 4, 2, 1, 2, 1, 7, 4, - 7, 4, 2, 1, 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7, - 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6, 5, 6, 0, 3, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_term_state[] = { - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, -}; - -static int conv_gsm_tch_afs_7_95_puncture[] = { - 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310, - 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367, - 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415, - 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463, - 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505, - 506, 508, 509, 511, 512, - -1, /* end */ -}; - -static const struct osmo_conv_code conv_gsm_tch_afs_7_95 = { - .N = 3, - .K = 7, - .len = 165, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_tch_afs_7_95_next_output, - .next_state = conv_gsm_tch_afs_7_95_next_state, - .next_term_output = conv_gsm_tch_afs_7_95_next_term_output, - .next_term_state = conv_gsm_tch_afs_7_95_next_term_state, - .puncture = conv_gsm_tch_afs_7_95_puncture, -}; - - /* GMR-1 TCH3 Speech -> Non recursive code, tail-biting, punctured */ static const uint8_t conv_gmr1_tch3_speech_next_output[][2] = { { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, @@ -220,18 +120,6 @@ static const struct osmo_conv_code conv_wimax_fch = { .next_state = conv_wimax_fch_next_state, }; - -/* Random code -> Non recursive code, direct truncation, non-punctured */ -static const struct osmo_conv_code conv_trunc = { - .N = 2, - .K = 5, - .len = 224, - .term = CONV_TERM_TRUNCATION, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, -}; - - /* ------------------------------------------------------------------------ */ /* Test vectors */ /* ------------------------------------------------------------------------ */ @@ -246,87 +134,6 @@ struct conv_test_vector { pbit_t vec_out[MAX_LEN_BYTES]; }; -static const struct conv_test_vector tests[] = { - { - .name = "GSM xCCH (non-recursive, flushed, not punctured)", - .code = &conv_gsm_xcch, - .in_len = 224, - .out_len = 456, - .has_vec = 1, - .vec_in = { 0xf3, 0x1d, 0xb4, 0x0c, 0x4d, 0x1d, 0x9d, 0xae, - 0xc0, 0x0a, 0x42, 0x57, 0x13, 0x60, 0x80, 0x96, - 0xef, 0x23, 0x7e, 0x4c, 0x1d, 0x96, 0x24, 0x19, - 0x17, 0xf2, 0x44, 0x99 }, - .vec_out = { 0xe9, 0x4d, 0x70, 0xab, 0xa2, 0x87, 0xf0, 0xe7, - 0x04, 0x14, 0x7c, 0xab, 0xaf, 0x6b, 0xa1, 0x16, - 0xeb, 0x30, 0x00, 0xde, 0xc8, 0xfd, 0x0b, 0x85, - 0x80, 0x41, 0x4a, 0xcc, 0xd3, 0xc0, 0xd0, 0xb6, - 0x26, 0xe5, 0x4e, 0x32, 0x49, 0x69, 0x38, 0x17, - 0x33, 0xab, 0xaf, 0xb6, 0xc1, 0x08, 0xf3, 0x9f, - 0x8c, 0x75, 0x6a, 0x4e, 0x08, 0xc4, 0x20, 0x5f, - 0x8f }, - }, - { - .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)", - .code = &conv_gsm_tch_afs_7_95, - .in_len = 165, - .out_len = 448, - .has_vec = 1, - .vec_in = { 0x87, 0x66, 0xc3, 0x58, 0x09, 0xd4, 0x06, 0x59, - 0x10, 0xbf, 0x6b, 0x7f, 0xc8, 0xed, 0x72, 0xaa, - 0xc1, 0x3d, 0xf3, 0x1e, 0xb0 }, - .vec_out = { 0x92, 0xbc, 0xde, 0xa0, 0xde, 0xbe, 0x01, 0x2f, - 0xbe, 0xe4, 0x61, 0x32, 0x4d, 0x4f, 0xdc, 0x41, - 0x43, 0x0d, 0x15, 0xe0, 0x23, 0xdd, 0x18, 0x91, - 0xe5, 0x36, 0x2d, 0xb7, 0xd9, 0x78, 0xb8, 0xb1, - 0xb7, 0xcb, 0x2f, 0xc0, 0x52, 0x8f, 0xe2, 0x8c, - 0x6f, 0xa6, 0x79, 0x88, 0xed, 0x0c, 0x2e, 0x9e, - 0xa1, 0x5f, 0x45, 0x4a, 0xfb, 0xe6, 0x5a, 0x9c }, - }, - { - .name = "GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)", - .code = &conv_gmr1_tch3_speech, - .in_len = 48, - .out_len = 72, - .has_vec = 1, - .vec_in = { 0x4d, 0xcb, 0xfc, 0x72, 0xf4, 0x8c }, - .vec_out = { 0xc0, 0x86, 0x63, 0x4b, 0x8b, 0xd4, 0x6a, 0x76, 0xb2 }, - }, - { - .name = "WiMax FCH (non-recursive, tail-biting, not punctured)", - .code = &conv_wimax_fch, - .in_len = 48, - .out_len = 96, - .has_vec = 1, - .vec_in = { 0xfc, 0xa0, 0xa0, 0xfc, 0xa0, 0xa0 }, - .vec_out = { 0x19, 0x42, 0x8a, 0xed, 0x21, 0xed, 0x19, 0x42, - 0x8a, 0xed, 0x21, 0xed }, - }, - { - .name = "??? (non-recursive, direct truncation, not punctured)", - .code = &conv_trunc, - .in_len = 224, - .out_len = 448, - .has_vec = 1, - .vec_in = { 0xe5, 0xe0, 0x85, 0x7e, 0xf7, 0x08, 0x19, 0x5a, - 0xb9, 0xad, 0x82, 0x37, 0x98, 0x8b, 0x26, 0xb9, - 0x81, 0x26, 0x9c, 0x75, 0xaf, 0xf3, 0xcb, 0x07, - 0xac, 0x63, 0xe2, 0x9c, - }, - .vec_out = { 0xea, 0x3b, 0x55, 0x0c, 0xd3, 0xf7, 0x85, 0x69, - 0xe5, 0x79, 0x83, 0xd3, 0xc3, 0x9f, 0xb8, 0x61, - 0x21, 0x63, 0x51, 0x18, 0xac, 0xcd, 0x32, 0x49, - 0x53, 0x5c, 0x13, 0x1d, 0xbe, 0x05, 0x11, 0x63, - 0x5c, 0xc3, 0x42, 0x05, 0x1c, 0x68, 0x0a, 0xb4, - 0x61, 0x15, 0xaa, 0x4d, 0x94, 0xed, 0xb3, 0x3a, - 0x5d, 0x1b, 0x09, 0xc2, 0x99, 0x01, 0xec, 0x68 }, - }, - { /* end */ }, -}; - - - - /* ------------------------------------------------------------------------ */ /* Main */ /* ------------------------------------------------------------------------ */ @@ -345,6 +152,94 @@ int main(int argc, char *argv[]) ubit_t *bu0, *bu1; sbit_t *bs; +/* Random code -> Non recursive code, direct truncation, non-punctured */ + const struct osmo_conv_code conv_trunc = { + .N = 2, + .K = 5, + .len = 224, + .term = CONV_TERM_TRUNCATION, + .next_output = gsm0503_xcch.next_output, + .next_state = gsm0503_xcch.next_state, + }; + + const struct conv_test_vector tests[] = { + { + .name = "GSM xCCH (non-recursive, flushed, not punctured)", + .code = &gsm0503_xcch, + .in_len = 224, + .out_len = 456, + .has_vec = 1, + .vec_in = { 0xf3, 0x1d, 0xb4, 0x0c, 0x4d, 0x1d, 0x9d, 0xae, + 0xc0, 0x0a, 0x42, 0x57, 0x13, 0x60, 0x80, 0x96, + 0xef, 0x23, 0x7e, 0x4c, 0x1d, 0x96, 0x24, 0x19, + 0x17, 0xf2, 0x44, 0x99 }, + .vec_out = { 0xe9, 0x4d, 0x70, 0xab, 0xa2, 0x87, 0xf0, 0xe7, + 0x04, 0x14, 0x7c, 0xab, 0xaf, 0x6b, 0xa1, 0x16, + 0xeb, 0x30, 0x00, 0xde, 0xc8, 0xfd, 0x0b, 0x85, + 0x80, 0x41, 0x4a, 0xcc, 0xd3, 0xc0, 0xd0, 0xb6, + 0x26, 0xe5, 0x4e, 0x32, 0x49, 0x69, 0x38, 0x17, + 0x33, 0xab, 0xaf, 0xb6, 0xc1, 0x08, 0xf3, 0x9f, + 0x8c, 0x75, 0x6a, 0x4e, 0x08, 0xc4, 0x20, 0x5f, + 0x8f }, + }, + { + .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)", + .code = &gsm0503_tch_afs_7_95, + .in_len = 165, + .out_len = 448, + .has_vec = 1, + .vec_in = { 0x87, 0x66, 0xc3, 0x58, 0x09, 0xd4, 0x06, 0x59, + 0x10, 0xbf, 0x6b, 0x7f, 0xc8, 0xed, 0x72, 0xaa, + 0xc1, 0x3d, 0xf3, 0x1e, 0xb0 }, + .vec_out = { 0x92, 0xbc, 0xde, 0xa0, 0xde, 0xbe, 0x01, 0x2f, + 0xbe, 0xe4, 0x61, 0x32, 0x4d, 0x4f, 0xdc, 0x41, + 0x43, 0x0d, 0x15, 0xe0, 0x23, 0xdd, 0x18, 0x91, + 0xe5, 0x36, 0x2d, 0xb7, 0xd9, 0x78, 0xb8, 0xb1, + 0xb7, 0xcb, 0x2f, 0xc0, 0x52, 0x8f, 0xe2, 0x8c, + 0x6f, 0xa6, 0x79, 0x88, 0xed, 0x0c, 0x2e, 0x9e, + 0xa1, 0x5f, 0x45, 0x4a, 0xfb, 0xe6, 0x5a, 0x9c }, + }, + { + .name = "GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)", + .code = &conv_gmr1_tch3_speech, + .in_len = 48, + .out_len = 72, + .has_vec = 1, + .vec_in = { 0x4d, 0xcb, 0xfc, 0x72, 0xf4, 0x8c }, + .vec_out = { 0xc0, 0x86, 0x63, 0x4b, 0x8b, 0xd4, 0x6a, 0x76, 0xb2 }, + }, + { + .name = "WiMax FCH (non-recursive, tail-biting, not punctured)", + .code = &conv_wimax_fch, + .in_len = 48, + .out_len = 96, + .has_vec = 1, + .vec_in = { 0xfc, 0xa0, 0xa0, 0xfc, 0xa0, 0xa0 }, + .vec_out = { 0x19, 0x42, 0x8a, 0xed, 0x21, 0xed, 0x19, 0x42, + 0x8a, 0xed, 0x21, 0xed }, + }, + { + .name = "??? (non-recursive, direct truncation, not punctured)", + .code = &conv_trunc, + .in_len = 224, + .out_len = 448, + .has_vec = 1, + .vec_in = { 0xe5, 0xe0, 0x85, 0x7e, 0xf7, 0x08, 0x19, 0x5a, + 0xb9, 0xad, 0x82, 0x37, 0x98, 0x8b, 0x26, 0xb9, + 0x81, 0x26, 0x9c, 0x75, 0xaf, 0xf3, 0xcb, 0x07, + 0xac, 0x63, 0xe2, 0x9c, + }, + .vec_out = { 0xea, 0x3b, 0x55, 0x0c, 0xd3, 0xf7, 0x85, 0x69, + 0xe5, 0x79, 0x83, 0xd3, 0xc3, 0x9f, 0xb8, 0x61, + 0x21, 0x63, 0x51, 0x18, 0xac, 0xcd, 0x32, 0x49, + 0x53, 0x5c, 0x13, 0x1d, 0xbe, 0x05, 0x11, 0x63, + 0x5c, 0xc3, 0x42, 0x05, 0x1c, 0x68, 0x0a, 0xb4, + 0x61, 0x15, 0xaa, 0x4d, 0x94, 0xed, 0xb3, 0x3a, + 0x5d, 0x1b, 0x09, 0xc2, 0x99, 0x01, 0xec, 0x68 }, + }, + { /* end */ }, + }; + srandom(time(NULL)); bu0 = malloc(sizeof(ubit_t) * MAX_LEN_BITS); diff --git a/utils/conv_gen.py b/utils/conv_gen.py new file mode 100755 index 0000000..cd0d1e0 --- /dev/null +++ b/utils/conv_gen.py @@ -0,0 +1,509 @@ +#!/usr/bin/python + +mod_license = """ +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +""" + +import sys, os + +class ConvolutionalCode(object): + + def __init__(self, block_len, n, k, polys, name = "call-me", description = "LOL", puncture = []): + # Save simple params + self.block_len = block_len + self.k = k + self.n = n + self.puncture = puncture + self.rate_inv = len(polys) + + # Infos + self.name = name + self.description = description + + # Handle polynoms (and check for recursion) + self.polys = [(1, 1) if x[0] == x[1] else x for x in polys] + + rp = [x[1] for x in self.polys if x[1] != 1] + if rp: + if not all([x == rp[0] for x in rp]): + raise ValueError("Bad polynoms: Can't have multiple different divider polynoms !") + if not all([x[0] == 1 for x in polys if x[1] == 1]): + raise ValueError("Bad polynoms: Can't have a '1' divider with a non '1' dividend in a recursive code") + self.poly_divider = rp[0] + else: + self.poly_divider = 1 + + @property + def recursive(self): + return self.poly_divider != 1 + + @property + def _state_mask(self): + return (1 << (self.k - 1)) - 1 + + def next_state(self, state, bit): + nb = combine( + (state << 1) | bit, + self.poly_divider, + self.k, + ) + return ((state << 1) | nb) & self._state_mask + + def next_term_state(self, state): + return (state << 1) & self._state_mask + + def next_output(self, state, bit, ns = None): + # Next state bit + if ns is None: + ns = self.next_state(state, bit) + + src = (ns & 1) | (state << 1) + + # Scan polynoms + rv = [] + for p_n, p_d in self.polys: + if self.recursive and p_d == 1: + o = bit # No choice ... (systematic output in recursive case) + else: + o = combine(src, p_n, self.k) + rv.append(o) + + return rv + + def next_term_output(self, state, ns = None): + # Next state bit + if ns is None: + ns = self.next_term_state(state) + + src = (ns & 1) | (state << 1) + + # Scan polynoms + rv = [] + for p_n, p_d in self.polys: + if self.recursive and p_d == 1: + # Systematic output are replaced when in 'termination' mode + o = combine(src, self.poly_divider, self.k) + else: + o = combine(src, p_n, self.k) + rv.append(o) + + return rv + + def next(self, state, bit): + ns = self.next_state(state, bit) + nb = self.next_output(state, bit, ns = ns) + return ns, nb + + def next_term(self, state): + ns = self.next_term_state(state) + nb = self.next_term_output(state, ns = ns) + return ns, nb + + def _print_term(self, fi, num_states, pack = False): + d = [] + for state in range(num_states): + x = pack(self.next_term_output(state)) if pack else self.next_term_state(state) + d.append("%d, " % x) + print >>fi, "\t%s" % ''.join(d) + + def _print_x(self, fi, num_states, pack = False): + for state in range(num_states): + x0 = pack(self.next_output(state, 0)) if pack else self.next_state(state, 0) + x1 = pack(self.next_output(state, 1)) if pack else self.next_state(state, 1) + print >>fi, "\t{ %2d, %2d }," % (x0, x1) + + def gen_tables(self, pref, fi): + pack = lambda n: sum([x << (self.rate_inv - i - 1) for i, x in enumerate(n)]) + num_states = 1 << (self.k - 1) + print >>fi, "\nstatic const uint8_t %s_state[][2] = {" % self.name + self._print_x(fi, num_states) + print >>fi, "};\n\nstatic const uint8_t %s_output[][2] = {" % self.name + self._print_x(fi, num_states, pack) + print >>fi, "};" + + if self.recursive: + print >>fi, "\nstatic const uint8_t %s_term_state[] = {" % self.name + self._print_term(fi, num_states) + print >>fi, "};\n\nstatic const uint8_t %s_term_output[] = {" % self.name + self._print_term(fi, num_states, pack) + print >>fi, "};" + + if len(self.puncture): + print >>fi, "\nstatic const int %s_puncture[] = {" % self.name + for p in self.puncture: + print >>fi, "\t%d," % p + print >>fi, "};" + + print >>fi, "\n/* %s */" % self.description + print >>fi, "const struct osmo_conv_code %s_%s = {" % (pref, self.name) + print >>fi, "\t.N = %d," % self.n + print >>fi, "\t.K = %d," % self.k + print >>fi, "\t.len = %d," % self.block_len + print >>fi, "\t.next_output = %s_output," % self.name + print >>fi, "\t.next_state = %s_state," % self.name + if self.recursive: + print >>fi, "\t.next_term_output = %s_term_output," % self.name + print >>fi, "\t.next_term_state = %s_term_state," % self.name + if len(self.puncture): + print >>fi, "\t.puncture = %s_puncture," % self.name + print >>fi, "};" + +poly = lambda *args: sum([(1 << x) for x in args]) + +def combine(src, sel, nb): + x = src & sel + fn_xor = lambda x, y: x ^ y + return reduce(fn_xor, [(x >> n) & 1 for n in range(nb)]) + +CCH_poly = [ ( poly(0, 3, 4), 1 ), + ( poly(0, 1, 3, 4), 1 ), +] + +xCCH = ConvolutionalCode( + 224, 2, 5, + CCH_poly, + name = "xcch", + description =""" *CCH convolutional code: + 228 bits blocks, rate 1/2, k = 5 + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 +""" +) + +CS2 = ConvolutionalCode( + 290, 2, 5, + CCH_poly, + puncture = [ + 15, 19, 23, 27, 31, 35, 43, 47, 51, 55, 59, 63, 67, 71, + 75, 79, 83, 91, 95, 99, 103, 107, 111, 115, 119, 123, 127, 131, + 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, 187, 191, 195, + 199, 203, 207, 211, 215, 219, 223, 227, 235, 239, 243, 247, 251, 255, + 259, 263, 267, 271, 275, 283, 287, 291, 295, 299, 303, 307, 311, 315, + 319, 323, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 379, + 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 427, 431, 435, 439, + 443, 447, 451, 455, 459, 463, 467, 475, 479, 483, 487, 491, 495, 499, + 503, 507, 511, 515, 523, 527, 531, 535, 539, 543, 547, 551, 555, 559, + 563, 571, 575, 579, 583, 587, -1 + ], + name = "cs2", + description =""" CS2 convolutional code: + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 +""" +) + +CS3 = ConvolutionalCode( + 334, 2, 5, + CCH_poly, + puncture = [ + 15, 17, 21, 23, 27, 29, 33, 35, 39, 41, 45, 47, 51, 53, + 57, 59, 63, 65, 69, 71, 75, 77, 81, 83, 87, 89, 93, 95, + 99, 101, 105, 107, 111, 113, 117, 119, 123, 125, 129, 131, 135, 137, + 141, 143, 147, 149, 153, 155, 159, 161, 165, 167, 171, 173, 177, 179, + 183, 185, 189, 191, 195, 197, 201, 203, 207, 209, 213, 215, 219, 221, + 225, 227, 231, 233, 237, 239, 243, 245, 249, 251, 255, 257, 261, 263, + 267, 269, 273, 275, 279, 281, 285, 287, 291, 293, 297, 299, 303, 305, + 309, 311, 315, 317, 321, 323, 327, 329, 333, 335, 339, 341, 345, 347, + 351, 353, 357, 359, 363, 365, 369, 371, 375, 377, 381, 383, 387, 389, + 393, 395, 399, 401, 405, 407, 411, 413, 417, 419, 423, 425, 429, 431, + 435, 437, 441, 443, 447, 449, 453, 455, 459, 461, 465, 467, 471, 473, + 477, 479, 483, 485, 489, 491, 495, 497, 501, 503, 507, 509, 513, 515, + 519, 521, 525, 527, 531, 533, 537, 539, 543, 545, 549, 551, 555, 557, + 561, 563, 567, 569, 573, 575, 579, 581, 585, 587, 591, 593, 597, 599, + 603, 605, 609, 611, 615, 617, 621, 623, 627, 629, 633, 635, 639, 641, + 645, 647, 651, 653, 657, 659, 663, 665, 669, 671, -1 + ], + name = "cs3", + description =""" CS3 convolutional code: + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 +""" +) + +TCH_AFS_12_2 = ConvolutionalCode( + 250, 2, 5, + [ + ( 1, 1 ), + ( poly(0, 1, 3, 4), poly(0, 3, 4) ), + ], + puncture = [ + 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 363, + 365, 369, 373, 377, 379, 381, 385, 389, 393, 395, 397, 401, + 405, 409, 411, 413, 417, 421, 425, 427, 429, 433, 437, 441, + 443, 445, 449, 453, 457, 459, 461, 465, 469, 473, 475, 477, + 481, 485, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, + -1 + ], + name = 'tch_afs_12_2', + description = """TCH/AFS 12.2 convolutional code: + 250 bits block, rate 1/2, punctured + G0/G0 = 1 + G1/G0 = 1 + D + D3 + D4 / 1 + D3 + D4 +""" +) + +TCH_AFS_10_2 = ConvolutionalCode( + 210, 3, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ], + puncture = [ + 1, 4, 7, 10, 16, 19, 22, 28, 31, 34, 40, 43, + 46, 52, 55, 58, 64, 67, 70, 76, 79, 82, 88, 91, + 94, 100, 103, 106, 112, 115, 118, 124, 127, 130, 136, 139, + 142, 148, 151, 154, 160, 163, 166, 172, 175, 178, 184, 187, + 190, 196, 199, 202, 208, 211, 214, 220, 223, 226, 232, 235, + 238, 244, 247, 250, 256, 259, 262, 268, 271, 274, 280, 283, + 286, 292, 295, 298, 304, 307, 310, 316, 319, 322, 325, 328, + 331, 334, 337, 340, 343, 346, 349, 352, 355, 358, 361, 364, + 367, 370, 373, 376, 379, 382, 385, 388, 391, 394, 397, 400, + 403, 406, 409, 412, 415, 418, 421, 424, 427, 430, 433, 436, + 439, 442, 445, 448, 451, 454, 457, 460, 463, 466, 469, 472, + 475, 478, 481, 484, 487, 490, 493, 496, 499, 502, 505, 508, + 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, + 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, + 583, 586, 589, 592, 595, 598, 601, 604, 607, 609, 610, 613, + 616, 619, 621, 622, 625, 627, 628, 631, 633, 634, 636, 637, + 639, 640, -1 + ], + name = 'tch_afs_10_2', + description = """TCH/AFS 10.2 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 +""" +) + +TCH_AFS_7_95 = ConvolutionalCode( + 165, 3, 7, + [ + ( 1, 1 ), + ( poly(0, 1, 4, 6), poly(0, 2, 3, 5, 6) ), + ( poly(0, 1, 2, 3, 4, 6), poly(0, 2, 3, 5, 6) ), + ], + puncture = [ + 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310, + 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367, + 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415, + 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463, + 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505, + 506, 508, 509, 511, 512, -1 + ], + name = 'tch_afs_7_95', + description = """TCH/AFS 7.95 kbits convolutional code: + G4/G4 = 1 + G5/G4 = 1 + D + D4 + D6 / 1 + D2 + D3 + D5 + D6 + G6/G4 = 1 + D + D2 + D3 + D4 + D6 / 1 + D2 + D3 + D5 + D6 +""" +) + +TCH_AFS_7_4 = ConvolutionalCode( + 154, 3, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ], + puncture = [ + 0, 355, 361, 367, 373, 379, 385, 391, 397, 403, 409, 415, + 421, 427, 433, 439, 445, 451, 457, 460, 463, 466, 468, 469, + 471, 472, -1 + ], + name = 'tch_afs_7_4', + description = """TCH/AFS 7.4 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 +""" +) + +TCH_AFS_6_7 = ConvolutionalCode( + 140, 4, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ( 1, 1 ), + ], + puncture = [ + 1, 3, 7, 11, 15, 27, 39, 55, 67, 79, 95, 107, + 119, 135, 147, 159, 175, 187, 199, 215, 227, 239, 255, 267, + 279, 287, 291, 295, 299, 303, 307, 311, 315, 319, 323, 327, + 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 369, 371, + 375, 377, 379, 383, 385, 387, 391, 393, 395, 399, 401, 403, + 407, 409, 411, 415, 417, 419, 423, 425, 427, 431, 433, 435, + 439, 441, 443, 447, 449, 451, 455, 457, 459, 463, 465, 467, + 471, 473, 475, 479, 481, 483, 487, 489, 491, 495, 497, 499, + 503, 505, 507, 511, 513, 515, 519, 521, 523, 527, 529, 531, + 535, 537, 539, 543, 545, 547, 549, 551, 553, 555, 557, 559, + 561, 563, 565, 567, 569, 571, 573, 575, -1 + ], + name = 'tch_afs_6_7', + description = """TCH/AFS 6.7 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 +""" +) + +TCH_AFS_5_9 = ConvolutionalCode( + 124, 4, 7, + [ + ( poly(0, 2, 3, 5, 6), poly(0, 1, 2, 3, 4, 6) ), + ( poly(0, 1, 4, 6), poly(0, 1, 2, 3, 4, 6) ), + ( 1, 1), + ( 1, 1), + ], + puncture = [ + 0, 1, 3, 5, 7, 11, 15, 31, 47, 63, 79, 95, + 111, 127, 143, 159, 175, 191, 207, 223, 239, 255, 271, 287, + 303, 319, 327, 331, 335, 343, 347, 351, 359, 363, 367, 375, + 379, 383, 391, 395, 399, 407, 411, 415, 423, 427, 431, 439, + 443, 447, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, + 495, 499, 503, 507, 509, 511, 512, 513, 515, 516, 517, 519, + -1 + ], + name = 'tch_afs_5_9', + description = """TCH/AFS 5.9 kbits convolutional code: + 124 bits + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 +""" +) + +TCH_AFS_5_15 = ConvolutionalCode( + 109, 5, 5, + [ + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 1, 3, 4), poly(0, 1, 2, 3, 4) ), + ( poly(0, 2, 4), poly(0, 1, 2, 3, 4) ), + ( 1, 1 ), + ( 1, 1 ), + ], + puncture = [ + 0, 4, 5, 9, 10, 14, 15, 20, 25, 30, 35, 40, + 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, + 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, + 290, 300, 310, 315, 320, 325, 330, 334, 335, 340, 344, 345, + 350, 354, 355, 360, 364, 365, 370, 374, 375, 380, 384, 385, + 390, 394, 395, 400, 404, 405, 410, 414, 415, 420, 424, 425, + 430, 434, 435, 440, 444, 445, 450, 454, 455, 460, 464, 465, + 470, 474, 475, 480, 484, 485, 490, 494, 495, 500, 504, 505, + 510, 514, 515, 520, 524, 525, 529, 530, 534, 535, 539, 540, + 544, 545, 549, 550, 554, 555, 559, 560, 564, -1 + ], + name = 'tch_afs_5_15', + description = """TCH/AFS 5.15 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 +""" +) + +TCH_AFS_4_75 = ConvolutionalCode( + 101, 5, 7, + [ + ( poly(0, 2, 3, 5, 6), poly(0, 1, 2, 3, 4, 6) ), + ( poly(0, 2, 3, 5, 6), poly(0, 1, 2, 3, 4, 6) ), + ( poly(0, 1, 4, 6), poly(0, 1, 2, 3, 4, 6) ), + ( 1, 1 ), + ( 1, 1 ), + ], + puncture = [ + 0, 1, 2, 4, 5, 7, 9, 15, 25, 35, 45, 55, + 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, + 185, 195, 205, 215, 225, 235, 245, 255, 265, 275, 285, 295, + 305, 315, 325, 335, 345, 355, 365, 375, 385, 395, 400, 405, + 410, 415, 420, 425, 430, 435, 440, 445, 450, 455, 459, 460, + 465, 470, 475, 479, 480, 485, 490, 495, 499, 500, 505, 509, + 510, 515, 517, 519, 520, 522, 524, 525, 526, 527, 529, 530, + 531, 532, 534, -1 + ], + name = 'tch_afs_4_75', + description = """TCH/AFS 4.75 kbits convolutional code: + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 +""" +) + +TETRA_RCPC = ConvolutionalCode( + 288, 2, 5, + [ + ( poly(0,1,4), 1 ), + ( poly(0,2,3,4), 1 ), + ( poly(0,1,2,4), 1 ), + ( poly(0,1,3,4), 1 ), + ], + name = 'tetra_rcpc', + description = """TETRA RCPC code + G1 = 1 + D + D4 + G2 = 1 + D2 + D3 + D4 + G3 = 1 + D + D2 + D4 + G4 = 1 + D + D3 + D4 +""" +) + +TETRA_RCPC_TCH = ConvolutionalCode( + 288, 2, 5, + [ + ( poly(0, 1, 2, 3, 4), 1 ), + ( poly(0, 1, 3, 4), 1 ), + ( poly(0, 2, 4), 1 ), + ], + name = 'tetra_rcpc_tch', + description = """TETRA RCPC TCH code +""" +) + +def gen_c(dest, pref, code): + f = open(os.path.join(dest, 'conv_' + code.name + '_gen.c'), 'w') + print >>f, mod_license + print >>f, "#include " + print >>f, "#include " + code.gen_tables(pref, f) + +if __name__ == '__main__': + print >>sys.stderr, "Generating convolutional codes..." + prefix = "gsm0503" + path = sys.argv[1] if len(sys.argv) > 1 else os.getcwd() + gen_c(path, prefix, xCCH) + gen_c(path, prefix, CS2) + gen_c(path, prefix, CS3) + gen_c(path, prefix, TCH_AFS_12_2) + gen_c(path, prefix, TCH_AFS_10_2) + gen_c(path, prefix, TCH_AFS_7_95) + gen_c(path, prefix, TCH_AFS_7_4) + gen_c(path, prefix, TCH_AFS_6_7) + gen_c(path, prefix, TCH_AFS_5_9) + gen_c(path, prefix, TCH_AFS_5_15) + gen_c(path, prefix, TCH_AFS_4_75) + print >>sys.stderr, "\tdone." -- 2.8.1 From holger at freyther.de Wed Apr 20 15:38:55 2016 From: holger at freyther.de (Holger Freyther) Date: Wed, 20 Apr 2016 17:38:55 +0200 Subject: [PATCH 2/5] Fix earfcn deletion In-Reply-To: <1461160634-14128-2-git-send-email-msuraev@sysmocom.de> References: <1461160634-14128-1-git-send-email-msuraev@sysmocom.de> <1461160634-14128-2-git-send-email-msuraev@sysmocom.de> Message-ID: > On 20 Apr 2016, at 15:57, msuraev at sysmocom.de wrote: > > From: Max > > * fix typo in arg index > * fix sign in error reporting > * add vty test > > + def testSi2Q(self): > + self.vty.enable() > + self.vty.command("configure terminal") > + self.vty.command("network") > + self.vty.command("bts 0") > + before = self.vty.command("show running-config") > + self.vty.command("si2quater neighbor-list add earfcn 1911 threshold 11 2") > + self.vty.command("si2quater neighbor-list add earfcn 1924 threshold 11 3") > + self.vty.command("si2quater neighbor-list add earfcn 2111 threshold 11") > + self.vty.command("si2quater neighbor-list del earfcn 1911") > + self.vty.command("si2quater neighbor-list del earfcn 1924") > + self.vty.command("si2quater neighbor-list del earfcn 2111") > + self.assertEquals(before, self.vty.command("show running-config")) So if both add and del are broken, your test will still pass. * Put si2quater neighbor-list add earfcn 1911 threshold 11 2 in the default config and use show-running-config to check it is present? * Be explicit, e.g. add 1911.. use show running-config.. and check with indexOf that it is present? holger From msuraev at sysmocom.de Thu Apr 21 12:46:30 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 21 Apr 2016 14:46:30 +0200 Subject: [PATCH] Update internal GPRS cipher API Message-ID: <1461242790-18639-1-git-send-email-msuraev@sysmocom.de> From: Max Update internal API (for GPRS cipher implementors): make it compliant with ETSI TS 155.22. External API left untouched. --- TODO-RELEASE | 3 ++- include/osmocom/crypt/gprs_cipher.h | 8 ++++++-- src/gsm/gprs_cipher_core.c | 23 +++++++++++++++++++++-- src/gsm/libosmogsm.map | 1 + 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/TODO-RELEASE b/TODO-RELEASE index 0939336..ffdea4b 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -1,3 +1,4 @@ -#library what description / commit summary line +#library what description / commit summary line +libosmogsm internal API update Internal API for GPRS cipher implementors updated to accommodate for arbitrary key lengths libosmocore change major external talloc dependency / internal talloc removal libosmocore change major size of ph_data_param struct changed / Extend L1SAP PH-DATA with presence information \ No newline at end of file diff --git a/include/osmocom/crypt/gprs_cipher.h b/include/osmocom/crypt/gprs_cipher.h index 940b07b..d6edefa 100644 --- a/include/osmocom/crypt/gprs_cipher.h +++ b/include/osmocom/crypt/gprs_cipher.h @@ -9,6 +9,7 @@ enum gprs_ciph_algo { GPRS_ALGO_GEA1, GPRS_ALGO_GEA2, GPRS_ALGO_GEA3, + GPRS_ALGO_GEA4, _GPRS_ALGO_NUM }; @@ -27,7 +28,7 @@ struct gprs_cipher_impl { /* As specified in 04.64 Annex A. Uses Kc, IV and direction * to generate the 1523 bytes cipher stream that need to be * XORed wit the plaintext for encrypt / ciphertext for decrypt */ - int (*run)(uint8_t *out, uint16_t len, uint64_t kc, uint32_t iv, + int (*run)(uint8_t *out, uint16_t len, uint8_t *kc, uint32_t iv, enum gprs_cipher_direction direction); }; @@ -39,11 +40,14 @@ int gprs_cipher_load(const char *path); /* function to be called by core code */ int gprs_cipher_run(uint8_t *out, uint16_t len, enum gprs_ciph_algo algo, - uint64_t kc, uint32_t iv, enum gprs_cipher_direction dir); + uint8_t *kc, uint32_t iv, enum gprs_cipher_direction dir); /* Do we have an implementation for this cipher? */ int gprs_cipher_supported(enum gprs_ciph_algo algo); +/* Return key length for supported cipher, in bytes */ +unsigned gprs_cipher_key_length(enum gprs_ciph_algo algo); + /* GSM TS 04.64 / Section A.2.1 : Generation of 'input' */ uint32_t gprs_cipher_gen_input_ui(uint32_t iov_ui, uint8_t sapi, uint32_t lfn, uint32_t oc); diff --git a/src/gsm/gprs_cipher_core.c b/src/gsm/gprs_cipher_core.c index b9a22a1..e4fac04 100644 --- a/src/gsm/gprs_cipher_core.c +++ b/src/gsm/gprs_cipher_core.c @@ -53,12 +53,14 @@ int gprs_cipher_register(struct gprs_cipher_impl *ciph) int gprs_cipher_load(const char *path) { /* load all plugins available from path */ - return osmo_plugin_load_all(path); + if (path) + return osmo_plugin_load_all(path); + return 0; } /* function to be called by core code */ int gprs_cipher_run(uint8_t *out, uint16_t len, enum gprs_ciph_algo algo, - uint64_t kc, uint32_t iv, enum gprs_cipher_direction dir) + uint8_t *kc, uint32_t iv, enum gprs_cipher_direction dir) { if (algo >= ARRAY_SIZE(selected_ciphers)) return -ERANGE; @@ -73,6 +75,23 @@ int gprs_cipher_run(uint8_t *out, uint16_t len, enum gprs_ciph_algo algo, return selected_ciphers[algo]->run(out, len, kc, iv, dir); } +/*! \brief Obtain key lenght for given GPRS cipher + * \param[in] algo Enum representive GPRS cipher + * \returns unsigned integer key length for supported algorithms, + * for GEA0 and unknown ciphers will return 0 + */ +unsigned gprs_cipher_key_length(enum gprs_ciph_algo algo) +{ + switch (algo) { + case GPRS_ALGO_GEA0: return 0; + case GPRS_ALGO_GEA1: + case GPRS_ALGO_GEA2: + case GPRS_ALGO_GEA3: return 8; + case GPRS_ALGO_GEA4: return 16; + default: return 0; + } +} + int gprs_cipher_supported(enum gprs_ciph_algo algo) { if (algo >= ARRAY_SIZE(selected_ciphers)) diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 6886a6c..a526756 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -40,6 +40,7 @@ gprs_cipher_load; gprs_cipher_register; gprs_cipher_run; gprs_cipher_supported; +gprs_cipher_key_length; gprs_tlli_type; gprs_tmsi2tlli; -- 2.8.1 From msuraev at sysmocom.de Thu Apr 21 12:58:30 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 21 Apr 2016 14:58:30 +0200 Subject: [PATCH] Addditional classmark check against A5/4 support Message-ID: <1461243511-23101-1-git-send-email-msuraev@sysmocom.de> From: Max Add classmark check function according to GSM 04.08 Chapter 10.5.1.7 Fix interface to use unsigned for unsigned value. --- include/osmocom/gsm/gsm_utils.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h index 99aae65..0fbfcba 100644 --- a/include/osmocom/gsm/gsm_utils.h +++ b/include/osmocom/gsm/gsm_utils.h @@ -119,7 +119,7 @@ int rxlev2dbm(uint8_t rxlev); uint8_t dbm2rxlev(int dbm); /* According to GSM 04.08 Chapter 10.5.1.6 */ -static inline int ms_cm2_a5n_support(uint8_t *cm2, int n) { +static inline int ms_cm2_a5n_support(uint8_t *cm2, unsigned n) { switch (n) { case 0: return 1; case 1: return (cm2[0] & (1<<3)) ? 0 : 1; @@ -130,6 +130,18 @@ static inline int ms_cm2_a5n_support(uint8_t *cm2, int n) { } } +/* According to GSM 04.08 Chapter 10.5.1.7 */ +static inline int ms_cm3_a5n_support(uint8_t *cm3, unsigned n) { + switch (n) { + case 4: return (cm3[0] & (1<<0)) ? 1 : 0; + case 5: return (cm3[0] & (1<<1)) ? 1 : 0; + case 6: return (cm3[0] & (1<<2)) ? 1 : 0; + case 7: return (cm3[0] & (1<<3)) ? 1 : 0; + default: + return 0; + } +} + /* According to GSM 04.08 Chapter 10.5.2.29 */ static inline int rach_max_trans_val2raw(int val) { return (val >> 1) & 3; } static inline int rach_max_trans_raw2val(int raw) { -- 2.8.1 From msuraev at sysmocom.de Thu Apr 21 13:57:52 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 21 Apr 2016 15:57:52 +0200 Subject: [PATCH] Improve code reuse Message-ID: <1461247072-10049-1-git-send-email-msuraev@sysmocom.de> From: Max Use generic functions covered by testsuit for SQN calculations. --- src/gsm/auth_milenage.c | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/src/gsm/auth_milenage.c b/src/gsm/auth_milenage.c index 5b2787d..1635ac6 100644 --- a/src/gsm/auth_milenage.c +++ b/src/gsm/auth_milenage.c @@ -21,39 +21,10 @@ */ #include +#include #include "milenage/common.h" #include "milenage/milenage.h" -static void sqn_u64_to_48bit(uint8_t *sqn, const uint64_t sqn64) -{ - sqn[5] = (sqn64 >> 0) & 0xff; - sqn[4] = (sqn64 >> 8) & 0xff; - sqn[3] = (sqn64 >> 16) & 0xff; - sqn[2] = (sqn64 >> 24) & 0xff; - sqn[1] = (sqn64 >> 32) & 0xff; - sqn[0] = (sqn64 >> 40) & 0xff; -} - -static uint64_t sqn_48bit_to_u64(const uint8_t *sqn) -{ - uint64_t sqn64; - - sqn64 = sqn[0]; - sqn64 <<= 8; - sqn64 |= sqn[1]; - sqn64 <<= 8; - sqn64 |= sqn[2]; - sqn64 <<= 8; - sqn64 |= sqn[3]; - sqn64 <<= 8; - sqn64 |= sqn[4]; - sqn64 <<= 8; - sqn64 |= sqn[5]; - - return sqn64; -} - - static int milenage_gen_vec(struct osmo_auth_vector *vec, struct osmo_sub_auth_data *aud, const uint8_t *_rand) @@ -62,7 +33,7 @@ static int milenage_gen_vec(struct osmo_auth_vector *vec, uint8_t sqn[6]; int rc; - sqn_u64_to_48bit(sqn, aud->u.umts.sqn); + osmo_store64be_ext(aud->u.umts.sqn, sqn, 6); milenage_generate(aud->u.umts.opc, aud->u.umts.amf, aud->u.umts.k, sqn, _rand, vec->autn, vec->ik, vec->ck, vec->res, &res_len); @@ -101,7 +72,7 @@ static int milenage_gen_vec_auts(struct osmo_auth_vector *vec, if (rc < 0) return rc; - aud->u.umts.sqn = sqn_48bit_to_u64(sqn_out) + 1; + aud->u.umts.sqn = 1 + (osmo_load64be_ext(sqn_out, 6) >> 16); return milenage_gen_vec(vec, aud, _rand); } -- 2.8.1 From msuraev at sysmocom.de Thu Apr 21 14:51:04 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 21 Apr 2016 16:51:04 +0200 Subject: [PATCH] Deprecate osmo_a5_1 and osmo_a5_2 Message-ID: <1461250264-10133-1-git-send-email-msuraev@sysmocom.de> From: Max Mark the functions as deprecated to discourage their use: people should use unified osmo_a5 which supports all the A5/1-4 ciphers. --- include/osmocom/gsm/a5.h | 5 ++- src/gsm/a5.c | 108 +++++++++++++++++++++++++---------------------- 2 files changed, 61 insertions(+), 52 deletions(-) diff --git a/include/osmocom/gsm/a5.h b/include/osmocom/gsm/a5.h index d22cdbb..a2278f2 100644 --- a/include/osmocom/gsm/a5.h +++ b/include/osmocom/gsm/a5.h @@ -24,6 +24,7 @@ #include +#include #include /*! \defgroup a5 GSM A5 ciphering algorithm @@ -54,7 +55,7 @@ osmo_a5_fn_count(uint32_t fn) * (converted internally to fn_count) */ int osmo_a5(int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul); -void osmo_a5_1(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul); -void osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul); +void osmo_a5_1(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) OSMO_DEPRECATED("Use generic osmo_a5() instead"); +void osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) OSMO_DEPRECATED("Use generic osmo_a5() instead"); /*! @} */ diff --git a/src/gsm/a5.c b/src/gsm/a5.c index d0c7c5f..f1fd697 100644 --- a/src/gsm/a5.c +++ b/src/gsm/a5.c @@ -101,54 +101,6 @@ _a5_3(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul, bool fn_correct) _a5_4(ck, fn, dl, ul, fn_correct); } -/*! \brief Main method to generate a A5/x cipher stream - * \param[in] n Which A5/x method to use - * \param[in] key 8 or 16 (for a5/4) byte array for the key (as received from the SIM) - * \param[in] fn Frame number - * \param[out] dl Pointer to array of ubits to return Downlink cipher stream - * \param[out] ul Pointer to array of ubits to return Uplink cipher stream - * \returns 0 for success, -ENOTSUP for invalid cipher selection. - * - * Currently A5/[0-4] are supported. - * Either (or both) of dl/ul can be NULL if not needed. - */ -int -osmo_a5(int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) -{ - switch (n) - { - case 0: - if (dl) - memset(dl, 0x00, 114); - if (ul) - memset(ul, 0x00, 114); - break; - - case 1: - osmo_a5_1(key, fn, dl, ul); - break; - - case 2: - osmo_a5_2(key, fn, dl, ul); - break; - - case 3: - _a5_3(key, fn, dl, ul, true); - break; - - case 4: - _a5_4(key, fn, dl, ul, true); - break; - - default: - /* a5/[5..7] not supported here/yet */ - return -ENOTSUP; - } - - return 0; -} - - /* ------------------------------------------------------------------------ */ /* A5/1&2 common stuff */ /* ------------------------------------------------------------------------ */ @@ -261,7 +213,7 @@ _a5_1_get_output(uint32_t r[]) * Either (or both) of dl/ul can be NULL if not needed. */ void -osmo_a5_1(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) +_a5_1(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) { uint32_t r[3] = {0, 0, 0}; uint32_t fn_count; @@ -314,6 +266,10 @@ osmo_a5_1(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) } } +void osmo_a5_1(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) +{ + osmo_a5(1, key, fn, dl, ul); +} /* ------------------------------------------------------------------------ */ /* A5/2 */ @@ -378,7 +334,7 @@ _a5_2_get_output(uint32_t r[]) * Either (or both) of dl/ul can be NULL if not needed. */ void -osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) +_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) { uint32_t r[4] = {0, 0, 0, 0}; uint32_t fn_count; @@ -438,4 +394,56 @@ osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) } } +void osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) +{ + osmo_a5(2, key, fn, dl, ul); +} + +/*! \brief Main method to generate a A5/x cipher stream + * \param[in] n Which A5/x method to use + * \param[in] key 8 or 16 (for a5/4) byte array for the key (as received from the SIM) + * \param[in] fn Frame number + * \param[out] dl Pointer to array of ubits to return Downlink cipher stream + * \param[out] ul Pointer to array of ubits to return Uplink cipher stream + * \returns 0 for success, -ENOTSUP for invalid cipher selection. + * + * Currently A5/[0-4] are supported. + * Either (or both) of dl/ul can be NULL if not needed. + */ +int +osmo_a5(int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) +{ + switch (n) + { + case 0: + if (dl) + memset(dl, 0x00, 114); + if (ul) + memset(ul, 0x00, 114); + break; + + case 1: + _a5_1(key, fn, dl, ul); + break; + + case 2: + _a5_2(key, fn, dl, ul); + break; + + case 3: + _a5_3(key, fn, dl, ul, true); + break; + + case 4: + _a5_4(key, fn, dl, ul, true); + break; + + default: + /* a5/[5..7] not supported here/yet */ + return -ENOTSUP; + } + + return 0; +} + /*! @} */ -- 2.8.1 From msuraev at sysmocom.de Thu Apr 21 15:12:40 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 21 Apr 2016 17:12:40 +0200 Subject: [PATCH] Deprecate comp128 Message-ID: <1461251560-23628-1-git-send-email-msuraev@sysmocom.de> From: Max Mark function as deprecated to discourage its usage: people should use generic API in osmocom/crypt/auth.h --- include/osmocom/gsm/comp128.h | 8 ++++++-- src/gsm/auth_comp128v1.c | 2 +- src/gsm/comp128.c | 7 ++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/osmocom/gsm/comp128.h b/include/osmocom/gsm/comp128.h index 33b997a..8ff76b1 100644 --- a/include/osmocom/gsm/comp128.h +++ b/include/osmocom/gsm/comp128.h @@ -8,11 +8,15 @@ #include +#include + /* - * Performs the COMP128 algorithm (used as A3/A8) + * Performs the COMP128v1 algorithm (used as A3/A8) * ki : uint8_t [16] * srand : uint8_t [16] * sres : uint8_t [4] * kc : uint8_t [8] */ -void comp128(const uint8_t *ki, const uint8_t *srand, uint8_t *sres, uint8_t *kc); +void comp128v1(const uint8_t *ki, const uint8_t *srand, uint8_t *sres, uint8_t *kc); + +void comp128(const uint8_t *ki, const uint8_t *srand, uint8_t *sres, uint8_t *kc) OSMO_DEPRECATED("Use generic API from osmocom/crypt/auth.h instead"); diff --git a/src/gsm/auth_comp128v1.c b/src/gsm/auth_comp128v1.c index 41aef71..c40027e 100644 --- a/src/gsm/auth_comp128v1.c +++ b/src/gsm/auth_comp128v1.c @@ -28,7 +28,7 @@ static int c128v1_gen_vec(struct osmo_auth_vector *vec, struct osmo_sub_auth_data *aud, const uint8_t *_rand) { - comp128(aud->u.gsm.ki, _rand, vec->sres, vec->kc); + comp128v1(aud->u.gsm.ki, _rand, vec->sres, vec->kc); vec->auth_types = OSMO_AUTH_TYPE_GSM; return 0; diff --git a/src/gsm/comp128.c b/src/gsm/comp128.c index b7a2382..abb4917 100644 --- a/src/gsm/comp128.c +++ b/src/gsm/comp128.c @@ -185,7 +185,7 @@ _comp128_permutation(uint8_t *x, uint8_t *bits) } void -comp128(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc) +comp128v1(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc) { int i; uint8_t x[32], bits[128]; @@ -228,3 +228,8 @@ comp128(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc) kc[7] = 0; } +void +comp128(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc) +{ + comp128v1(ki, rand, sres, kc); +} -- 2.8.1 From msuraev at sysmocom.de Thu Apr 21 16:43:26 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 21 Apr 2016 18:43:26 +0200 Subject: [PATCH 1/2] LC15: refactor code to simplify understanding Message-ID: <1461257007-22060-1-git-send-email-msuraev@sysmocom.de> From: Max Use bool type for boolean values. Move common code out of if.. else. --- src/osmo-bts-litecell15/l1_if.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/osmo-bts-litecell15/l1_if.c b/src/osmo-bts-litecell15/l1_if.c index 6a60b3f..3e60726 100644 --- a/src/osmo-bts-litecell15/l1_if.c +++ b/src/osmo-bts-litecell15/l1_if.c @@ -28,7 +28,7 @@ #include #include #include - +#include #include #include @@ -96,7 +96,7 @@ static void l1if_req_timeout(void *data) } static int _l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, - int is_system_prim, l1if_compl_cb *cb, void *data) + bool is_system_prim, l1if_compl_cb *cb, void *data) { struct wait_l1_conf *wlc; struct osmo_wqueue *wqueue; @@ -108,7 +108,7 @@ static int _l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, wlc->cb_data = data; /* Make sure we actually have received a REQUEST type primitive */ - if (is_system_prim == 0) { + if (!is_system_prim) { GsmL1_Prim_t *l1p = msgb_l1prim(msg); LOGP(DL1P, LOGL_INFO, "Tx L1 prim %s\n", @@ -123,7 +123,6 @@ static int _l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, wlc->is_sys_prim = 0; wlc->conf_prim_id = lc15bts_get_l1prim_conf(l1p->id); wqueue = &fl1h->write_q[MQ_L1_WRITE]; - timeout_secs = 30; } else { Litecell15_Prim_t *sysp = msgb_sysprim(msg); @@ -139,9 +138,10 @@ static int _l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, wlc->is_sys_prim = 1; wlc->conf_prim_id = lc15bts_get_sysprim_conf(sysp->id); wqueue = &fl1h->write_q[MQ_SYS_WRITE]; - timeout_secs = 30; } + timeout_secs = 30; + /* enqueue the message in the queue and add wsc to list */ if (osmo_wqueue_enqueue(wqueue, msg) != 0) { /* So we will get a timeout but the log message might help */ @@ -163,13 +163,13 @@ static int _l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, int l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, l1if_compl_cb *cb, void *data) { - return _l1if_req_compl(fl1h, msg, 1, cb, data); + return _l1if_req_compl(fl1h, msg, true, cb, data); } int l1if_gsm_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg, l1if_compl_cb *cb, void *data) { - return _l1if_req_compl(fl1h, msg, 0, cb, data); + return _l1if_req_compl(fl1h, msg, false, cb, data); } /* allocate a msgb containing a GsmL1_Prim_t */ -- 2.8.1 From msuraev at sysmocom.de Thu Apr 21 16:43:27 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 21 Apr 2016 18:43:27 +0200 Subject: [PATCH 2/2] SysmoBTS: refactor code to simplify understanding In-Reply-To: <1461257007-22060-1-git-send-email-msuraev@sysmocom.de> References: <1461257007-22060-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1461257007-22060-2-git-send-email-msuraev@sysmocom.de> From: Max Use bool type for boolean values. Move common code out of if.. else. --- src/osmo-bts-sysmo/l1_if.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c index debc80a..e031461 100644 --- a/src/osmo-bts-sysmo/l1_if.c +++ b/src/osmo-bts-sysmo/l1_if.c @@ -24,7 +24,7 @@ #include #include #include - +#include #include #include @@ -92,7 +92,7 @@ static void l1if_req_timeout(void *data) } static int _l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, - int is_system_prim, l1if_compl_cb *cb, void *data) + bool is_system_prim, l1if_compl_cb *cb, void *data) { struct wait_l1_conf *wlc; struct osmo_wqueue *wqueue; @@ -104,7 +104,7 @@ static int _l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, wlc->cb_data = data; /* Make sure we actually have received a REQUEST type primitive */ - if (is_system_prim == 0) { + if (!is_system_prim) { GsmL1_Prim_t *l1p = msgb_l1prim(msg); LOGP(DL1P, LOGL_INFO, "Tx L1 prim %s\n", @@ -119,7 +119,6 @@ static int _l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, wlc->is_sys_prim = 0; wlc->conf_prim_id = femtobts_l1prim_req2conf[l1p->id]; wqueue = &fl1h->write_q[MQ_L1_WRITE]; - timeout_secs = 30; } else { SuperFemto_Prim_t *sysp = msgb_sysprim(msg); @@ -135,9 +134,10 @@ static int _l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, wlc->is_sys_prim = 1; wlc->conf_prim_id = femtobts_sysprim_req2conf[sysp->id]; wqueue = &fl1h->write_q[MQ_SYS_WRITE]; - timeout_secs = 30; } + timeout_secs = 30; + /* enqueue the message in the queue and add wsc to list */ if (osmo_wqueue_enqueue(wqueue, msg) != 0) { /* So we will get a timeout but the log message might help */ @@ -159,13 +159,13 @@ static int _l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, int l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, l1if_compl_cb *cb, void *data) { - return _l1if_req_compl(fl1h, msg, 1, cb, data); + return _l1if_req_compl(fl1h, msg, true, cb, data); } int l1if_gsm_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, l1if_compl_cb *cb, void *data) { - return _l1if_req_compl(fl1h, msg, 0, cb, data); + return _l1if_req_compl(fl1h, msg, false, cb, data); } /* allocate a msgb containing a GsmL1_Prim_t */ -- 2.8.1 From msuraev at sysmocom.de Thu Apr 21 16:55:09 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Thu, 21 Apr 2016 18:55:09 +0200 Subject: [PATCH] Ensure TRX invariant Message-ID: <1461257709-25977-1-git-send-email-msuraev@sysmocom.de> From: Max There is implicit invariant in trx_phy_instance() which is actively used by various hw-specific implementations to get TRX's phy instance. Let's make sure there's explicit assertion for this because there's been segfaults in the past related to it. --- include/osmo-bts/phy_link.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/osmo-bts/phy_link.h b/include/osmo-bts/phy_link.h index a559aa3..edc6cc0 100644 --- a/include/osmo-bts/phy_link.h +++ b/include/osmo-bts/phy_link.h @@ -125,6 +125,7 @@ void phy_user_statechg_notif(struct phy_instance *pinst, enum phy_link_state lin static inline struct phy_instance *trx_phy_instance(struct gsm_bts_trx *trx) { + OSMO_ASSERT(trx); return trx->role_bts.l1h; } -- 2.8.1 From robert.steve07 at gmail.com Fri Apr 22 07:57:25 2016 From: robert.steve07 at gmail.com (robert) Date: Fri, 22 Apr 2016 10:57:25 +0300 Subject: OpenBSC relating IMSI/IMEI Message-ID: <4B1C20EA-7056-43EB-836C-FE43D9F91BDA@gmail.com> Hi, I?m currently facing a strange issue where the number of entries in the subscriber table is different from the number of entries in the equipment table, therefore I cannot consistently relate each IMSI to its correct IMEI. I also had another issue where I have the same number of entries but the ID?s of the rows are different as shown below: Subscriber table Equipment table ID IMSI ID IMEI 1 XXXX 1 XXXX 2 XXXX 2 XXXX 4 XXXX 14 XXXX Does anyone know why this is happening, and how can I correctly relate each IMSI to its corresponding IMEI ? Best regards, Robert, From psb1979 at hotmail.com Fri Apr 22 11:40:18 2016 From: psb1979 at hotmail.com (Pavel Balashov) Date: Fri, 22 Apr 2016 11:40:18 +0000 Subject: Half sided calls In-Reply-To: <864880037.819106.1442745090880.JavaMail.zimbra@kvk.uni-obuda.hu> Message-ID: Hello! I can confirm a compatiblity issue with LibORTP >= 0.24.0. Here are some of my findings: In /osmo-bts/src/common/rsl.c in rsl_rx_ipac_XXcx there is a call to libosmo-abis function: osmo_rtp_socket_bind(lchan->abis_ip.rtp_socket, ipstr, -1). I assume, that last argument "-1" means that the random udp port should be selected for socket. in /libosmo-abis/src/trau/osmo-rtp.c in a function int osmo_rtp_socket_bind(struct osmo_rtp_socket *rs, const char *ip, int port) there is a call to LibORTP rtp_session_set_local_addr(rs->sess, ip, port, port+1). So as result this function calls rtp_session_set_local_addr with last arguments being equal to "-1" and "0". The LibORTP function int rtp_session_set_local_addr (RtpSession * session, const char * addr, int rtp_port, int rtcp_port) has a folollowing description: /** *rtp_session_set_local_addr: *@session: a rtp session freshly created. *@addr: a local IP address in the xxx.xxx.xxx.xxx form. *@rtp_port: a local port or -1 to let oRTP choose the port randomly *@rtcp_port: a local port or -1 to let oRTP choose the port randomly * ... **/ So this results in calling osmo_rtp_socket_bind(...,-1) -> rtp_session_set_local_addr(...,-1,0) what tries to bind rtp to random udp port and rtcp to 0th udp port, but not to random port. I guess that rtcp socket is never created regardless of LibORTP version. (there are periodic osmo-ortp(): network_error osmo-bts log messages due to ICMP port unreachable messages received, besides those mentioned in https://osmocom.org/issues/1662). So I suppose the correct code should check port value and either calling rtp_session_set_local_addr(rs->sess, ip, port, port+1) if port >0 or else calling rtp_session_set_local_addr(rs->sess, ip, port, port) ? Also, after inspecting sources of LibORTP it seems that the implementation of rtp_session_set_local_addr has changed for LibORTP >= 0.24.0. As I understand the functionality of selecting a random UDP port is broken. What results is one way audio. Regards, Pavel. -------------- next part -------------- An HTML attachment was scrubbed... URL: From holger at freyther.de Fri Apr 22 12:23:02 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 22 Apr 2016 14:23:02 +0200 Subject: gerrit comment example (from Qt) References: <20160422121421.A7BAB50FB6@mx.qt-project.org> Message-ID: Hi, I subscribed myself to more change notifications on another gerrit to see how the coments would look like. there is not a lot o context but at least some. > Begin forwarded message: > > Jesus Fernandez has posted comments on this change. > > Change subject: Possible crash in QMakeSourceFileInfo > ...................................................................... > > > Patch Set 7: > > (6 comments) > > Thank you > > .................................................... > File qmake/generators/makefiledeps.cpp > Line 606 > It's really weird, but you're right. > > Dropped... I mean Done. > > > Line 648 > Done > > > Line 655 > Done > > > Line 667 > Done > > > Line 592: for (x += 1 ; x + inc_len < buffer_len && buffer[x + inc_len] != '<'; > And an extra whitespace :) > > Done! > > > Line 639: for (x += 1; x + inc_len < buffer_len && buffer[x + inc_len] != '<'; > Done From psb1979 at hotmail.com Fri Apr 22 12:28:57 2016 From: psb1979 at hotmail.com (Pavel Balashov) Date: Fri, 22 Apr 2016 12:28:57 +0000 Subject: Half sided calls In-Reply-To: References: Message-ID: Some clarification - my post was intended as a reply to this message : http://lists.osmocom.org/pipermail/openbsc/2015-September/000413.html I'd inserted email header 'In-Reply-To: <864880037.819106.1442745090880.JavaMail.zimbra at kvk.uni-obuda.hu>' which points to message-id of the aforementioned post, hoping that my post will be glued to an existing thread of September 2015. But looks like this naive approach doesn't work. Regards, Pavel. On 04/22/2016 02:40 PM, Pavel Balashov wrote: Hello! I can confirm a compatiblity issue with LibORTP >= 0.24.0. Here are some of my findings: In /osmo-bts/src/common/rsl.c in rsl_rx_ipac_XXcx there is a call to libosmo-abis function: osmo_rtp_socket_bind(lchan->abis_ip.rtp_socket, ipstr, -1). I assume, that last argument "-1" means that the random udp port should be selected for socket. in /libosmo-abis/src/trau/osmo-rtp.c in a function int osmo_rtp_socket_bind(struct osmo_rtp_socket *rs, const char *ip, int port) there is a call to LibORTP rtp_session_set_local_addr(rs->sess, ip, port, port+1). So as result this function calls rtp_session_set_local_addr with last arguments being equal to "-1" and "0". The LibORTP function int rtp_session_set_local_addr (RtpSession * session, const char * addr, int rtp_port, int rtcp_port) has a folollowing description: /** *rtp_session_set_local_addr: *@session: a rtp session freshly created. *@addr: a local IP address in the xxx.xxx.xxx.xxx form. *@rtp_port: a local port or -1 to let oRTP choose the port randomly *@rtcp_port: a local port or -1 to let oRTP choose the port randomly * ... **/ So this results in calling osmo_rtp_socket_bind(...,-1) -> rtp_session_set_local_addr(...,-1,0) what tries to bind rtp to random udp port and rtcp to 0th udp port, but not to random port. I guess that rtcp socket is never created regardless of LibORTP version. (there are periodic osmo-ortp(): network_error osmo-bts log messages due to ICMP port unreachable messages received, besides those mentioned in https://osmocom.org/issues/1662). So I suppose the correct code should check port value and either calling rtp_session_set_local_addr(rs->sess, ip, port, port+1) if port >0 or else calling rtp_session_set_local_addr(rs->sess, ip, port, port) ? Also, after inspecting sources of LibORTP it seems that the implementation of rtp_session_set_local_addr has changed for LibORTP >= 0.24.0. As I understand the functionality of selecting a random UDP port is broken. What results is one way audio. Regards, Pavel. -------------- next part -------------- An HTML attachment was scrubbed... URL: From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:12 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:12 +0200 Subject: [PATCH 1/4] gsm0480: RELEASE COMPLETE can be without any payload Message-ID: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> From: Sergey Kostanbaev --- src/gsm/gsm0480.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index 8963b78..55bddd5 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -248,12 +248,6 @@ int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len, struct ss_request *req) { int rc = 0; - - if (len < sizeof(*hdr) + 2) { - LOGP(0, LOGL_DEBUG, "SS Request is too short.\n"); - return 0; - } - if (gsm48_hdr_pdisc(hdr) == GSM48_PDISC_NC_SS) { req->transaction_id = hdr->proto_discr & 0x70; rc = parse_ss(hdr, len, req); -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:13 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:13 +0200 Subject: [PATCH 2/4] gsm0480: Fix handling GSM0480_MTYPE_FACILITY, it has only LV and facility_ie In-Reply-To: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328875-8253-2-git-send-email-sergey.kostanbaev@gmail.com> From: Sergey Kostanbaev --- src/gsm/gsm0480.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index 55bddd5..9fc77a0 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -196,6 +196,8 @@ static int parse_ss(const struct gsm48_hdr *hdr, uint16_t len, struct ss_request *req); static int parse_ss_info_elements(const uint8_t *ussd_ie, uint16_t len, struct ss_request *req); +static int parse_ss_facility(const uint8_t *ss_facility, uint16_t len, + struct ss_request *req); static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length, struct ss_request *req); static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length, @@ -271,9 +273,11 @@ static int parse_ss(const struct gsm48_hdr *hdr, uint16_t len, struct ss_request req->ussd_text[0] = 0xFF; break; case GSM0480_MTYPE_REGISTER: - case GSM0480_MTYPE_FACILITY: rc &= parse_ss_info_elements(&hdr->data[0], len - sizeof(*hdr), req); break; + case GSM0480_MTYPE_FACILITY: + rc &= parse_ss_facility(&hdr->data[0], len - sizeof(*hdr), req); + break; default: LOGP(0, LOGL_DEBUG, "Unknown GSM 04.80 message-type field 0x%02x\n", hdr->msg_type); @@ -284,6 +288,18 @@ static int parse_ss(const struct gsm48_hdr *hdr, uint16_t len, struct ss_request return rc; } +static int parse_ss_facility(const uint8_t *ss_facility, uint16_t len, + struct ss_request *req) +{ + uint8_t facility_length; + + facility_length = ss_facility[0]; + if (len - 1 < facility_length) + return 0; + + return parse_facility_ie(ss_facility + 1, facility_length, req); +} + static int parse_ss_info_elements(const uint8_t *ss_ie, uint16_t len, struct ss_request *req) { -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:14 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:14 +0200 Subject: [PATCH 3/4] gsm0480: Separate ss_request struct to header and payload In-Reply-To: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328875-8253-3-git-send-email-sergey.kostanbaev@gmail.com> From: Sergey Kostanbaev Add ss_header structure to store L3 specific data and modify ss_request to store GSM0480 MAP payload. Do not decode strings inside ss_request, leave it for upper level to support other languages. Parse Return Result accordingly. --- include/osmocom/gsm/gsm0480.h | 34 ++++++-- src/gsm/gsm0480.c | 186 ++++++++++++++++++++++++++++++++++-------- src/gsm/libosmogsm.map | 1 + tests/ussd/ussd_test.c | 23 +++++- 4 files changed, 198 insertions(+), 46 deletions(-) diff --git a/include/osmocom/gsm/gsm0480.h b/include/osmocom/gsm/gsm0480.h index deac322..7cacc84 100644 --- a/include/osmocom/gsm/gsm0480.h +++ b/include/osmocom/gsm/gsm0480.h @@ -5,7 +5,8 @@ #include #include -#define MAX_LEN_USSD_STRING 31 +#define MAX_LEN_USSD_STRING 182 +#define MAX_ASN1_LEN_USSD_STRING 160 /* deprecated */ struct ussd_request { @@ -18,16 +19,35 @@ struct ussd_request { int gsm0480_decode_ussd_request(const struct gsm48_hdr *hdr, uint16_t len, struct ussd_request *request) OSMO_DEPRECATED("Use gsm0480_decode_ss_request() instead"); +struct ss_header { + uint8_t transaction_id; /**< L3 transaction ID */ + uint8_t message_type; /**< Message type 2.2 */ + + uint8_t component_offset; /**< Component offset in L3 */ + uint8_t component_length; /**< Component length in L3 */ +}; + struct ss_request { - uint8_t opcode; - uint8_t ss_code; - uint8_t ussd_text[MAX_LEN_USSD_STRING + 1]; - uint8_t transaction_id; - uint8_t invoke_id; + uint8_t component_type; /**< Component type 3.6.2 */ + uint8_t invoke_id; /**< Invoke id 3.6.3 */ + + union { + uint8_t opcode; /**< Operational code 3.6.4 */ + uint8_t error_code; /**< Error code 3.6.6 */ + uint8_t problem_code; /**< Problem code 3.6.7 */ + }; + + uint8_t ussd_text_len; + uint8_t ussd_text_language; + uint8_t ussd_text[MAX_ASN1_LEN_USSD_STRING + 1]; + + uint8_t ss_code; /**< parameters of a Interrogate/Activate/DeactivateSS Request */ }; +int gsm0480_parse_ss_facility(const uint8_t* data, uint8_t len, struct ss_request *out); + int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len, - struct ss_request *request); + struct ss_header *request); struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text); struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text); diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index 9fc77a0..e073602 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -193,25 +193,44 @@ struct msgb *gsm0480_create_notifySS(const char *text) /* Forward declarations */ static int parse_ss(const struct gsm48_hdr *hdr, - uint16_t len, struct ss_request *req); + uint16_t len, struct ss_header *req); static int parse_ss_info_elements(const uint8_t *ussd_ie, uint16_t len, - struct ss_request *req); + struct ss_header *req); static int parse_ss_facility(const uint8_t *ss_facility, uint16_t len, - struct ss_request *req); + struct ss_header *req); + static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length, struct ss_request *req); static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length, struct ss_request *req); +static int parse_ss_return_result(const uint8_t *rr_data, uint16_t length, + struct ss_request *req); static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length, struct ss_request *req); static int parse_ss_for_bs_req(const uint8_t *ss_req_data, uint16_t length, struct ss_request *req); +static const uint8_t *parse_asn1_small_len(const uint8_t *codedlen, uint16_t available, + uint8_t *out_len) +{ + uint8_t lenb = codedlen[0]; + if (lenb < 0x80 && available > 0) { + *out_len = lenb; + return &codedlen[1]; + } else if (lenb == 0x81 && available > 1) { + *out_len = codedlen[1]; + return &codedlen[2]; + } + + return NULL; +} + /* Decode a mobile-originated USSD-request message */ int gsm0480_decode_ussd_request(const struct gsm48_hdr *hdr, uint16_t len, struct ussd_request *req) { + struct ss_header sshdr; struct ss_request ss; int rc = 0; @@ -225,16 +244,31 @@ int gsm0480_decode_ussd_request(const struct gsm48_hdr *hdr, uint16_t len, if (gsm48_hdr_pdisc(hdr) == GSM48_PDISC_NC_SS) { req->transaction_id = hdr->proto_discr & 0x70; - ss.transaction_id = req->transaction_id; - rc = parse_ss(hdr, len, &ss); + sshdr.transaction_id = req->transaction_id; + rc = parse_ss(hdr, len, &sshdr); + if (rc) { + /* this if block was inside parse_ss() */ + if (sshdr.message_type == GSM0480_MTYPE_RELEASE_COMPLETE) { + /* could also parse out the optional Cause/Facility data */ + ss.ussd_text[0] = 0xFF; + } + rc = gsm0480_parse_ss_facility(hdr->data + sshdr.component_offset, + sshdr.component_length, + &ss); + } /* convert from ss_request to legacy ussd_request */ - req->transaction_id = ss.transaction_id; + req->transaction_id = sshdr.transaction_id; req->invoke_id = ss.invoke_id; - if (ss.ussd_text[0] == 0xFF) + if (ss.ussd_text_language != 0x0f || + ss.opcode != GSM0480_OP_CODE_PROCESS_USS_REQ) { + req->text[0] = '\0'; - else { - memcpy(req->text, ss.ussd_text, sizeof(req->text)); + } else { + gsm_7bit_decode_n_ussd(req->text, + sizeof(req->text), + ss.ussd_text, ss.ussd_text_len); + req->text[sizeof(req->text)-1] = '\0'; } } @@ -247,7 +281,7 @@ int gsm0480_decode_ussd_request(const struct gsm48_hdr *hdr, uint16_t len, /* Decode a mobile-originated SS request message */ int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len, - struct ss_request *req) + struct ss_header *req) { int rc = 0; if (gsm48_hdr_pdisc(hdr) == GSM48_PDISC_NC_SS) { @@ -261,16 +295,17 @@ int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len, return rc; } -static int parse_ss(const struct gsm48_hdr *hdr, uint16_t len, struct ss_request *req) +static int parse_ss(const struct gsm48_hdr *hdr, uint16_t len, struct ss_header *req) { int rc = 1; uint8_t msg_type = hdr->msg_type & 0xBF; /* message-type - section 3.4 */ + req->message_type = msg_type; + req->component_offset = 0; + switch (msg_type) { case GSM0480_MTYPE_RELEASE_COMPLETE: LOGP(0, LOGL_DEBUG, "SS Release Complete\n"); - /* could also parse out the optional Cause/Facility data */ - req->ussd_text[0] = 0xFF; break; case GSM0480_MTYPE_REGISTER: rc &= parse_ss_info_elements(&hdr->data[0], len - sizeof(*hdr), req); @@ -289,7 +324,7 @@ static int parse_ss(const struct gsm48_hdr *hdr, uint16_t len, struct ss_request } static int parse_ss_facility(const uint8_t *ss_facility, uint16_t len, - struct ss_request *req) + struct ss_header *req) { uint8_t facility_length; @@ -297,13 +332,15 @@ static int parse_ss_facility(const uint8_t *ss_facility, uint16_t len, if (len - 1 < facility_length) return 0; - return parse_facility_ie(ss_facility + 1, facility_length, req); + req->component_offset += 1; + req->component_length = facility_length; + return 1; } static int parse_ss_info_elements(const uint8_t *ss_ie, uint16_t len, - struct ss_request *req) + struct ss_header *req) { - int rc = -1; + int rc = 1; /* Information Element Identifier - table 3.2 & GSM 04.08 section 10.5 */ uint8_t iei; uint8_t iei_length; @@ -319,7 +356,8 @@ static int parse_ss_info_elements(const uint8_t *ss_ie, uint16_t len, case GSM48_IE_CAUSE: break; case GSM0480_IE_FACILITY: - rc = parse_facility_ie(ss_ie + 2, iei_length, req); + req->component_offset += 2; + req->component_length = iei_length; break; case GSM0480_IE_SS_VERSION: break; @@ -333,6 +371,11 @@ static int parse_ss_info_elements(const uint8_t *ss_ie, uint16_t len, return rc; } +int gsm0480_parse_ss_facility(const uint8_t* data, uint8_t len, struct ss_request *out) +{ + return parse_facility_ie(data, len, out); +} + static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length, struct ss_request *req) { @@ -342,25 +385,38 @@ static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length, while (offset + 2 <= length) { /* Component Type tag - table 3.7 */ uint8_t component_type = facility_ie[offset]; - uint8_t component_length = facility_ie[offset+1]; + uint8_t component_length = 0; + const uint8_t *nxt = parse_asn1_small_len(facility_ie + offset + 1, + length - offset - 1, + &component_length); /* size check */ - if (offset + 2 + component_length > length) { + offset = nxt - facility_ie; + if (nxt == NULL || offset + component_length > length) { LOGP(0, LOGL_ERROR, "Component does not fit.\n"); return 0; } + req->component_type = component_type; + switch (component_type) { case GSM0480_CTYPE_INVOKE: - rc &= parse_ss_invoke(facility_ie+2, + rc &= parse_ss_invoke(nxt, component_length, req); break; case GSM0480_CTYPE_RETURN_RESULT: + rc &= parse_ss_return_result(nxt, + component_length, + req); break; case GSM0480_CTYPE_RETURN_ERROR: + /* TODO Error codes */ + LOGP(0, LOGL_DEBUG, "Ignored GSM0480_CTYPE_RETURN_ERROR"); break; case GSM0480_CTYPE_REJECT: + /* TODO rejects */ + LOGP(0, LOGL_DEBUG, "Ignored GSM0480_CTYPE_REJECT"); break; default: LOGP(0, LOGL_DEBUG, "Unknown GSM 04.80 Facility " @@ -368,12 +424,58 @@ static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length, rc = 0; break; } - offset += (component_length+2); + offset += component_length; }; return rc; } +/* Parse an Return Result component - see table 3.4 */ +static int parse_ss_return_result(const uint8_t *rr_data, uint16_t length, + struct ss_request *req) +{ + int rc = 1; + uint8_t offset; + + if (length < 3) + return 0; + + /* mandatory part */ + if (rr_data[0] != GSM0480_COMPIDTAG_INVOKE_ID) { + LOGP(0, LOGL_DEBUG, "Unexpected GSM 04.80 Component-ID tag " + "0x%02x (expecting Invoke ID tag)\n", rr_data[0]); + } + + offset = rr_data[1] + 2; + req->invoke_id = rr_data[2]; + + if (offset < length) { + if (rr_data[offset] != GSM_0480_SEQUENCE_TAG) + return 0; + if (offset + 2 > length) + return 0; + offset += 2; + + uint8_t operation_code = rr_data[offset+2]; + req->opcode = operation_code; + switch (operation_code) { + case GSM0480_OP_CODE_USS_NOTIFY: + case GSM0480_OP_CODE_USS_REQUEST: + case GSM0480_OP_CODE_PROCESS_USS_REQ: + rc = parse_process_uss_req(rr_data + offset + 3, + length - offset - 3, + req); + break; + default: + LOGP(0, LOGL_DEBUG, "GSM 04.80 operation code 0x%02x " + "is not yet handled\n", operation_code); + rc = 0; + break; + } + } + return rc; +} + /* Parse an Invoke component - see table 3.3 */ static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length, struct ss_request *req) @@ -408,6 +510,8 @@ static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length, uint8_t operation_code = invoke_data[offset+2]; req->opcode = operation_code; switch (operation_code) { + case GSM0480_OP_CODE_USS_NOTIFY: + case GSM0480_OP_CODE_USS_REQUEST: case GSM0480_OP_CODE_PROCESS_USS_REQ: rc = parse_process_uss_req(invoke_data + offset + 3, length - offset - 3, @@ -441,27 +545,37 @@ static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length, struct ss_request *req) { int rc = 0; - int num_chars; - uint8_t dcs; - - + uint8_t dcs, seq_block_len, num_chars; + const uint8_t *next_ptr; /* we need at least that much */ if (length < 8) return 0; if (uss_req_data[0] == GSM_0480_SEQUENCE_TAG) { - if (uss_req_data[2] == ASN1_OCTET_STRING_TAG) { - dcs = uss_req_data[4]; - if ((dcs == 0x0F) && - (uss_req_data[5] == ASN1_OCTET_STRING_TAG)) { - num_chars = (uss_req_data[6] * 8) / 7; + next_ptr = parse_asn1_small_len(&uss_req_data[1], length - 1, &seq_block_len); + if (next_ptr == NULL || seq_block_len < 6) + return 0; + + if (next_ptr[0] == ASN1_OCTET_STRING_TAG) { + if (next_ptr[1] != 1) + return 0; + + dcs = next_ptr[2]; + + if (next_ptr[3] == ASN1_OCTET_STRING_TAG) { + next_ptr = parse_asn1_small_len(&next_ptr[4], + seq_block_len - 4, &num_chars); + if (next_ptr == NULL) + return 0; + /* Prevent a mobile-originated buffer-overrun! */ - if (num_chars > MAX_LEN_USSD_STRING) - num_chars = MAX_LEN_USSD_STRING; - gsm_7bit_decode_n_ussd((char *)req->ussd_text, - sizeof(req->ussd_text), - &(uss_req_data[7]), num_chars); + if (num_chars > MAX_ASN1_LEN_USSD_STRING) + num_chars = MAX_ASN1_LEN_USSD_STRING; + + req->ussd_text_language = dcs; + req->ussd_text_len = num_chars; + memcpy(req->ussd_text, next_ptr, num_chars); rc = 1; } } diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 6886a6c..04cc6c4 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -50,6 +50,7 @@ gsm0480_create_unstructuredSS_Notify; gsm0480_create_ussd_resp; gsm0480_decode_ussd_request; gsm0480_decode_ss_request; +gsm0480_parse_ss_facility; gsm0480_wrap_facility; gsm0480_wrap_invoke; diff --git a/tests/ussd/ussd_test.c b/tests/ussd/ussd_test.c index f798e37..ac35baa 100644 --- a/tests/ussd/ussd_test.c +++ b/tests/ussd/ussd_test.c @@ -39,12 +39,18 @@ static int parse_ussd(const uint8_t *_data, int len) uint8_t *data; int rc; struct ss_request req; + struct ss_header reqhdr; struct gsm48_hdr *hdr; data = malloc(len); memcpy(data, _data, len); hdr = (struct gsm48_hdr *) &data[0]; - rc = gsm0480_decode_ss_request(hdr, len, &req); + rc = gsm0480_decode_ss_request(hdr, len, &reqhdr); + if (rc) { + rc = gsm0480_parse_ss_facility(hdr->data + reqhdr.component_offset, + reqhdr.component_length, + &req); + } free(data); return rc; @@ -55,13 +61,20 @@ static int parse_mangle_ussd(const uint8_t *_data, int len) uint8_t *data; int rc; struct ss_request req; + struct ss_header reqhdr; struct gsm48_hdr *hdr; data = malloc(len); memcpy(data, _data, len); hdr = (struct gsm48_hdr *) &data[0]; hdr->data[1] = len - sizeof(*hdr) - 2; - rc = gsm0480_decode_ss_request(hdr, len, &req); + rc = gsm0480_decode_ss_request(hdr, len, &reqhdr); + if (rc) { + rc = gsm0480_parse_ss_facility(hdr->data + reqhdr.component_offset, + reqhdr.component_length, + &req); + } + free(data); return rc; @@ -114,13 +127,17 @@ static void test_7bit_ussd(const char *text, const char *encoded_hex, const char int main(int argc, char **argv) { struct ss_request req; + struct ss_header reqhdr; const int size = sizeof(ussd_request); int i; struct msgb *msg; osmo_init_logging(&info); - gsm0480_decode_ss_request((struct gsm48_hdr *) ussd_request, size, &req); + gsm0480_decode_ss_request((struct gsm48_hdr *) ussd_request, size, &reqhdr); + gsm0480_parse_ss_facility(ussd_request + reqhdr.component_offset, + reqhdr.component_length, + &req); printf("Tested if it still works. Text was: %s\n", req.ussd_text); -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:15 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:15 +0200 Subject: [PATCH 4/4] gsm0480: registerSS and eraseSS In-Reply-To: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328875-8253-4-git-send-email-sergey.kostanbaev@gmail.com> From: "Sergey.Kostanbaev" --- src/gsm/gsm0480.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index e073602..f11bdfe 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -517,6 +517,8 @@ static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length, length - offset - 3, req); break; + case GSM0480_OP_CODE_REGISTER_SS: + case GSM0480_OP_CODE_ERASE_SS: case GSM0480_OP_CODE_ACTIVATE_SS: case GSM0480_OP_CODE_DEACTIVATE_SS: case GSM0480_OP_CODE_INTERROGATE_SS: -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:30 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:30 +0200 Subject: [PATCH 1/9] debug: Add DSS category for supplementary service Message-ID: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> --- openbsc/include/openbsc/debug.h | 1 + openbsc/src/libcommon/debug.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h index 189ca47..6048a5c 100644 --- a/openbsc/include/openbsc/debug.h +++ b/openbsc/include/openbsc/debug.h @@ -34,6 +34,7 @@ enum { DSMPP, DFILTER, DGTPHUB, + DSS, Debug_LastEntry, }; diff --git a/openbsc/src/libcommon/debug.c b/openbsc/src/libcommon/debug.c index 7fb3ecb..6536944 100644 --- a/openbsc/src/libcommon/debug.c +++ b/openbsc/src/libcommon/debug.c @@ -165,6 +165,12 @@ static const struct log_info_cat default_categories[] = { .description = "BSC/NAT IMSI based filtering", .enabled = 1, .loglevel = LOGL_DEBUG, }, + [DSS] = { + .name = "DSS", + .description = "Layer3 Supplementary Service (SS)", + .color = "\033[0;33m", + .enabled = 1, .loglevel = LOGL_DEBUG, + }, }; enum log_filter { -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:31 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:31 +0200 Subject: [PATCH 2/9] libmsc: Add USSD MAP constant in gsup_message_type In-Reply-To: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328898-8298-2-git-send-email-sergey.kostanbaev@gmail.com> From: Sergey Kostanbaev --- openbsc/include/openbsc/gprs_gsup_messages.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openbsc/include/openbsc/gprs_gsup_messages.h b/openbsc/include/openbsc/gprs_gsup_messages.h index 8cbc809..fb9c66e 100644 --- a/openbsc/include/openbsc/gprs_gsup_messages.h +++ b/openbsc/include/openbsc/gprs_gsup_messages.h @@ -53,6 +53,8 @@ enum gprs_gsup_iei { }; enum gprs_gsup_message_type { + GPRS_GSUP_MSGT_USSD_MAP = 0b01111111, + GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST = 0b00000100, GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR = 0b00000101, GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT = 0b00000110, -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:32 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:32 +0200 Subject: [PATCH 3/9] libmsc: Update USSD to use new ss_request structure In-Reply-To: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328898-8298-3-git-send-email-sergey.kostanbaev@gmail.com> --- openbsc/include/openbsc/gsm_04_80.h | 15 +++-- openbsc/src/libmsc/gsm_04_80.c | 128 ++++++++++++++++++++++++------------ openbsc/src/libmsc/ussd.c | 79 ++++++++++++++++++---- 3 files changed, 162 insertions(+), 60 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_80.h b/openbsc/include/openbsc/gsm_04_80.h index 0a60652..371bc17 100644 --- a/openbsc/include/openbsc/gsm_04_80.h +++ b/openbsc/include/openbsc/gsm_04_80.h @@ -7,12 +7,17 @@ struct gsm_subscriber_connection; -int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn, - const struct msgb *in_msg, const char* response_text, - const struct ussd_request *req); +int gsm0480_send_component(struct gsm_subscriber_connection *conn, + struct msgb *msg, + struct ss_header* reqhdr); + int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn, - const struct msgb *msg, - const struct ussd_request *request); + uint8_t invoke_id, + uint8_t transaction_id); + +struct msgb *gsm0480_compose_ussd_component(struct ss_request* req); + + int gsm0480_send_ussdNotify(struct gsm_subscriber_connection *conn, int level, const char *text); int gsm0480_send_releaseComplete(struct gsm_subscriber_connection *conn); diff --git a/openbsc/src/libmsc/gsm_04_80.c b/openbsc/src/libmsc/gsm_04_80.c index f1d75f2..e6e4a92 100644 --- a/openbsc/src/libmsc/gsm_04_80.c +++ b/openbsc/src/libmsc/gsm_04_80.c @@ -39,6 +39,22 @@ #include #include +/* This function can handle ASN1 length up to 255 which is enough for USSD */ +static inline unsigned char *msgb_wrap_with_ASN1_TL(struct msgb *msgb, uint8_t tag) +{ + uint16_t origlen = msgb->len; + uint8_t *data = msgb_push(msgb, (origlen > 0x7f) ? 3 : 2); + data[0] = tag; + if (origlen > 0x7f) { + data[1] = 0x81; + data[2] = origlen; + } else { + data[1] = origlen; + } + return data; +} + + static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag) { uint8_t *data = msgb_push(msgb, 2); @@ -59,83 +75,111 @@ static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag, return data; } +static inline unsigned char *msgb_wrap_with_L(struct msgb *msgb) +{ + uint8_t *data = msgb_push(msgb, 1); -/* Send response to a mobile-originated ProcessUnstructuredSS-Request */ -int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn, - const struct msgb *in_msg, const char *response_text, - const struct ussd_request *req) + data[0] = msgb->len - 1; + return data; +} + +/* Compose universial USSD packet invoke/return_result payload */ +struct msgb *gsm0480_compose_ussd_component(struct ss_request* req) { struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD RSP"); - struct gsm48_hdr *gh; uint8_t *ptr8; - int response_len; /* First put the payload text into the message */ ptr8 = msgb_put(msg, 0); - gsm_7bit_encode_n_ussd(ptr8, msgb_tailroom(msg), response_text, &response_len); - msgb_put(msg, response_len); + + memcpy(ptr8, req->ussd_text, req->ussd_text_len); + msgb_put(msg, req->ussd_text_len); /* Then wrap it as an Octet String */ - msgb_wrap_with_TL(msg, ASN1_OCTET_STRING_TAG); + msgb_wrap_with_ASN1_TL(msg, ASN1_OCTET_STRING_TAG); /* Pre-pend the DCS octet string */ - msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, 0x0F); + msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, req->ussd_text_language); /* Then wrap these as a Sequence */ - msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); - - /* Pre-pend the operation code */ - msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, - GSM0480_OP_CODE_PROCESS_USS_REQ); - - /* Wrap the operation code and IA5 string as a sequence */ - msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); + msgb_wrap_with_ASN1_TL(msg, GSM_0480_SEQUENCE_TAG); + + if (req->component_type == GSM0480_CTYPE_RETURN_RESULT) { + /* Pre-pend the operation code */ + msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, req->opcode); + + /* Wrap the operation code and IA5 string as a sequence */ + msgb_wrap_with_ASN1_TL(msg, GSM_0480_SEQUENCE_TAG); + + /* Pre-pend the invoke ID */ + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id); + } else if (req->component_type == GSM0480_CTYPE_INVOKE) { + /* Pre-pend the operation code */ + msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, req->opcode); + + /* Pre-pend the invoke ID */ + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id); + } else { + abort(); + } + + /* Wrap this up as an Invoke or a Return Result component */ + msgb_wrap_with_ASN1_TL(msg, req->component_type); + return msg; +} - /* Pre-pend the invoke ID */ - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id); +#ifndef NO_GSM0480_SEND_FUNC - /* Wrap this up as a Return Result component */ - msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT); +int gsm0480_send_component(struct gsm_subscriber_connection *conn, + struct msgb *msg, + struct ss_header* reqhdr) +{ + struct gsm48_hdr *gh; - /* Wrap the component in a Facility message */ - msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); + if (reqhdr->message_type == GSM0480_MTYPE_REGISTER || + reqhdr->message_type == GSM0480_MTYPE_RELEASE_COMPLETE) { + /* Wrap the component in a Facility message, it's not ASN1 */ + msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); + } else if (reqhdr->message_type == GSM0480_MTYPE_FACILITY) { + /* For GSM0480_MTYPE_FACILITY it's LV not TLV */ + msgb_wrap_with_L(msg); + } else { + abort(); + } /* And finally pre-pend the L3 header */ gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh)); - gh->proto_discr = GSM48_PDISC_NC_SS | req->transaction_id + gh->proto_discr = GSM48_PDISC_NC_SS | reqhdr->transaction_id | (1<<7); /* TI direction = 1 */ - gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE; + gh->msg_type = reqhdr->message_type; + + DEBUGP(DSS, "Sending SS to mobile: %s\n", msgb_hexdump(msg)); return gsm0808_submit_dtap(conn, msg, 0, 0); } + int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn, - const struct msgb *in_msg, - const struct ussd_request *req) + uint8_t invoke_id, + uint8_t transaction_id) { struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD REJ"); - struct gsm48_hdr *gh; + struct ss_header ssh; /* First insert the problem code */ msgb_push_TLV1(msg, GSM_0480_PROBLEM_CODE_TAG_GENERAL, GSM_0480_GEN_PROB_CODE_UNRECOGNISED); /* Before it insert the invoke ID */ - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id); + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); /* Wrap this up as a Reject component */ - msgb_wrap_with_TL(msg, GSM0480_CTYPE_REJECT); - - /* Wrap the component in a Facility message */ - msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); + msgb_wrap_with_ASN1_TL(msg, GSM0480_CTYPE_REJECT); - /* And finally pre-pend the L3 header */ - gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh)); - gh->proto_discr = GSM48_PDISC_NC_SS; - gh->proto_discr |= req->transaction_id | (1<<7); /* TI direction = 1 */ - gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE; - - return gsm0808_submit_dtap(conn, msg, 0, 0); + /* Prepare data for L3 header */ + ssh.transaction_id = transaction_id; + ssh.message_type = GSM0480_MTYPE_RELEASE_COMPLETE; + return gsm0480_send_component(conn, msg, &ssh); } int gsm0480_send_ussdNotify(struct gsm_subscriber_connection *conn, int level, const char *text) @@ -173,3 +217,5 @@ int gsm0480_send_releaseComplete(struct gsm_subscriber_connection *conn) return gsm0808_submit_dtap(conn, msg, 0, 0); } + +#endif diff --git a/openbsc/src/libmsc/ussd.c b/openbsc/src/libmsc/ussd.c index 7f01eae..3cafe02 100644 --- a/openbsc/src/libmsc/ussd.c +++ b/openbsc/src/libmsc/ussd.c @@ -33,41 +33,71 @@ #include #include #include +#include +#include +#include /* Declarations of USSD strings to be recognised */ const char USSD_TEXT_OWN_NUMBER[] = "*#100#"; /* Forward declarations of network-specific handler functions */ -static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ussd_request *req); +static int send_own_number(struct gsm_subscriber_connection *conn, + const struct ss_header *reqhdr, + const struct ss_request *req); /* Entrypoint - handler function common to all mobile-originated USSDs */ int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg) { int rc; - struct ussd_request req; + struct ss_header reqhdr; + struct ss_request req; + char request_string[MAX_LEN_USSD_STRING + 1]; struct gsm48_hdr *gh; memset(&req, 0, sizeof(req)); + memset(&reqhdr, 0, sizeof(reqhdr)); gh = msgb_l3(msg); - rc = gsm0480_decode_ussd_request(gh, msgb_l3len(msg), &req); + rc = gsm0480_decode_ss_request(gh, msgb_l3len(msg), &reqhdr); if (!rc) { - DEBUGP(DMM, "Unhandled SS\n"); - rc = gsm0480_send_ussd_reject(conn, msg, &req); + DEBUGP(DSS, "Incorrect SS header\n"); msc_release_connection(conn); return rc; } - /* Release-Complete */ - if (req.text[0] == '\0') + rc = gsm0480_parse_ss_facility(gh->data + reqhdr.component_offset, + reqhdr.component_length, + &req); + if (!rc) { + DEBUGP(DSS, "Unhandled SS\n"); + /* TODO req.invoke_id may not be set!!! */ + rc = gsm0480_send_ussd_reject(conn, req.invoke_id, reqhdr.transaction_id); + msc_release_connection(conn); + return rc; + } + + if (reqhdr.message_type == GSM0480_MTYPE_RELEASE_COMPLETE) return 0; - if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)req.text)) { - DEBUGP(DMM, "USSD: Own number requested\n"); - rc = send_own_number(conn, msg, &req); + if (reqhdr.message_type != GSM0480_MTYPE_REGISTER || + req.component_type != GSM0480_CTYPE_INVOKE || + req.opcode != GSM0480_OP_CODE_PROCESS_USS_REQ || + req.ussd_text_language != 0x0f) + { + DEBUGP(DSS, "Unexpected SS\n"); + rc = gsm0480_send_ussd_reject(conn, req.invoke_id, reqhdr.transaction_id); + msc_release_connection(conn); + return rc; + } + + gsm_7bit_decode_n_ussd(request_string, MAX_LEN_USSD_STRING, req.ussd_text, req.ussd_text_len); + + if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)request_string)) { + DEBUGP(DSS, "USSD: Own number requested\n"); + rc = send_own_number(conn, &reqhdr, &req); } else { - DEBUGP(DMM, "Unhandled USSD %s\n", req.text); - rc = gsm0480_send_ussd_reject(conn, msg, &req); + DEBUGP(DSS, "Unhandled USSD %s\n", request_string); + rc = gsm0480_send_ussd_reject(conn, req.invoke_id, reqhdr.transaction_id); } /* check if we can release it */ @@ -76,12 +106,33 @@ int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg) } /* A network-specific handler function */ -static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ussd_request *req) +static int send_own_number(struct gsm_subscriber_connection *conn, + const struct ss_header *reqhdr, + const struct ss_request *req) { + struct ss_request rss; + struct ss_header rssh; + char *own_number = conn->subscr->extension; char response_string[GSM_EXTENSION_LENGTH + 20]; + int response_len; /* Need trailing CR as EOT character */ snprintf(response_string, sizeof(response_string), "Your extension is %s\r", own_number); - return gsm0480_send_ussd_response(conn, msg, response_string, req); + + memset(&rss, 0, sizeof(rss)); + gsm_7bit_encode_n_ussd(rss.ussd_text, MAX_LEN_USSD_STRING, response_string, &response_len); + rss.ussd_text_len = response_len; + rss.ussd_text_language = 0x0f; + + rss.component_type = GSM0480_CTYPE_RETURN_RESULT; + rss.invoke_id = req->invoke_id; + rss.opcode = GSM0480_OP_CODE_PROCESS_USS_REQ; + + rssh.message_type = GSM0480_MTYPE_RELEASE_COMPLETE; + rssh.transaction_id = reqhdr->transaction_id; + + return gsm0480_send_component(conn, + gsm0480_compose_ussd_component(&rss), + &rssh); } -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:33 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:33 +0200 Subject: [PATCH 4/9] libmsc: Add external USSD MAP interface In-Reply-To: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328898-8298-4-git-send-email-sergey.kostanbaev@gmail.com> From: Sergey Kostanbaev --- openbsc/include/openbsc/gsm_ussd_map.h | 14 ++ openbsc/include/openbsc/gsm_ussd_map_proto.h | 25 +++ openbsc/include/openbsc/transaction.h | 5 + openbsc/include/openbsc/ussd.h | 13 ++ openbsc/src/libmsc/Makefile.am | 3 +- openbsc/src/libmsc/gsm_ussd_map.c | 93 +++++++++++ openbsc/src/libmsc/gsm_ussd_map_proto.c | 212 ++++++++++++++++++++++++++ openbsc/src/libmsc/transaction.c | 4 + openbsc/src/libmsc/ussd.c | 220 +++++++++++++++++++++++++++ 9 files changed, 588 insertions(+), 1 deletion(-) create mode 100644 openbsc/include/openbsc/gsm_ussd_map.h create mode 100644 openbsc/include/openbsc/gsm_ussd_map_proto.h create mode 100644 openbsc/src/libmsc/gsm_ussd_map.c create mode 100644 openbsc/src/libmsc/gsm_ussd_map_proto.c diff --git a/openbsc/include/openbsc/gsm_ussd_map.h b/openbsc/include/openbsc/gsm_ussd_map.h new file mode 100644 index 0000000..72798b2 --- /dev/null +++ b/openbsc/include/openbsc/gsm_ussd_map.h @@ -0,0 +1,14 @@ +#ifndef _GSM_USSD_MAP_H +#define _GSM_USSD_MAP_H + +#include +#include +#include + +int ussd_map_read_cb(struct gprs_gsup_client *sup_client, + struct msgb *msg); + +int ussd_map_tx_message(struct gsm_network *net, struct ss_header *req, + const char *extension, uint32_t ref, const uint8_t *component_data); + +#endif /* _GSM_USSD_MAP_H */ diff --git a/openbsc/include/openbsc/gsm_ussd_map_proto.h b/openbsc/include/openbsc/gsm_ussd_map_proto.h new file mode 100644 index 0000000..7faa5b8 --- /dev/null +++ b/openbsc/include/openbsc/gsm_ussd_map_proto.h @@ -0,0 +1,25 @@ +#ifndef _GSM_USSD_MAP_PROTO_H +#define _GSM_USSD_MAP_PROTO_H + +#include + + +enum { + FMAP_MSISDN = 0x80 +}; + +int subscr_uss_message(struct msgb *msg, + struct ss_header *req, + const char* extension, + uint32_t ref, + const uint8_t *component_data); + +int rx_uss_message_parse(const uint8_t* data, + size_t len, + struct ss_header *ss, + uint32_t *ref, + char* extention, + size_t extention_len); + + +#endif /* _GSM_USSD_MAP_PROTO_H */ diff --git a/openbsc/include/openbsc/transaction.h b/openbsc/include/openbsc/transaction.h index 6ef1612..d82e576 100644 --- a/openbsc/include/openbsc/transaction.h +++ b/openbsc/include/openbsc/transaction.h @@ -56,6 +56,11 @@ struct gsm_trans { struct gsm_sms *sms; } sms; + struct { + uint8_t invoke_id; + uint8_t mo; + uint8_t dirty; + } ss; }; }; diff --git a/openbsc/include/openbsc/ussd.h b/openbsc/include/openbsc/ussd.h index 2665468..b5b073a 100644 --- a/openbsc/include/openbsc/ussd.h +++ b/openbsc/include/openbsc/ussd.h @@ -5,6 +5,19 @@ #include +#define USSD_MO 1 +#define USSD_MT 0 + int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg); + +int on_ussd_response(struct gsm_network *net, + uint32_t ref, + struct ss_header *reqhdr, + const uint8_t *component, + const char* extention); + + +void _ussd_trans_free(struct gsm_trans *trans); + #endif diff --git a/openbsc/src/libmsc/Makefile.am b/openbsc/src/libmsc/Makefile.am index 5195890..566efe2 100644 --- a/openbsc/src/libmsc/Makefile.am +++ b/openbsc/src/libmsc/Makefile.am @@ -19,7 +19,8 @@ libmsc_a_SOURCES = auth.c \ ussd.c \ vty_interface_layer3.c \ transaction.c \ - osmo_msc.c ctrl_commands.c meas_feed.c + osmo_msc.c ctrl_commands.c meas_feed.c \ + gsm_ussd_map_proto.c gsm_ussd_map.c if BUILD_SMPP noinst_HEADERS += smpp_smsc.h diff --git a/openbsc/src/libmsc/gsm_ussd_map.c b/openbsc/src/libmsc/gsm_ussd_map.c new file mode 100644 index 0000000..7ca84b1 --- /dev/null +++ b/openbsc/src/libmsc/gsm_ussd_map.c @@ -0,0 +1,93 @@ +/* GSM USSD external MAP interface */ + +/* (C) 2015 by Sergey Kostanbaev + * + * 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int ussd_map_tx_message(struct gsm_network* net, + struct ss_header *req, + const char* extension, + uint32_t ref, + const uint8_t* component_data) +{ + struct msgb *msg = gprs_gsup_msgb_alloc(); + if (!msg) + return -ENOMEM; + + subscr_uss_message(msg, req, extension, ref, component_data); + + return gprs_gsup_client_send(net->ussd_sup_client, msg); +} + + +static int ussd_map_rx_message_int(struct gsm_network *net, const uint8_t* data, size_t len) +{ + char extension[32] = {0}; + uint32_t ref; + struct ss_header ss; + memset(&ss, 0, sizeof(ss)); + + if (rx_uss_message_parse(data, len, &ss, &ref, extension, sizeof(extension))) { + LOGP(DSS, LOGL_ERROR, "Can't parse SUP MAP SS message\n"); + return -1; + } + + LOGP(DSS, LOGL_ERROR, "Got type=0x%02x len=%d\n", + ss.message_type, ss.component_length); + + return on_ussd_response(net, ref, &ss, data + ss.component_offset, extension); +} + +static int ussd_map_rx_message(struct gprs_gsup_client *sup_client, struct msgb *msg) +{ + uint8_t *data = msgb_l2(msg); + size_t data_len = msgb_l2len(msg); + struct gsm_network *gsmnet = (struct gsm_network *)sup_client->data; + + if (*data != GPRS_GSUP_MSGT_USSD_MAP) { + return -1; + } + + return ussd_map_rx_message_int(gsmnet, data, data_len); +} + +int ussd_map_read_cb(struct gprs_gsup_client *sup_client, struct msgb *msg) +{ + int rc; + + rc = ussd_map_rx_message(sup_client, msg); + msgb_free(msg); + if (rc < 0) + return -1; + + return rc; +} diff --git a/openbsc/src/libmsc/gsm_ussd_map_proto.c b/openbsc/src/libmsc/gsm_ussd_map_proto.c new file mode 100644 index 0000000..1d48efb --- /dev/null +++ b/openbsc/src/libmsc/gsm_ussd_map_proto.c @@ -0,0 +1,212 @@ +/* GSM USSD external MAP protocol on pseudo TCAP */ + +/* (C) 2015 by Sergey Kostanbaev + * + * 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +* 0 - GPRS_GSUP_MSGT_USSD_MAP constant +* 1 - LEN +* 2 - message_type [ REGISTER / FACILITY / RELEASE COMPLETE ] +* 3,4,5,6 - tid ID associated with the session +* 7 - FMAP_MSISDN constant +* 8 - extention_len +* 9..x - extention +* x+1 .. original MAP message +*/ + +int subscr_uss_message(struct msgb *msg, + struct ss_header *req, + const char* extension, + uint32_t ref, + const uint8_t* component_data) +{ + uint8_t bcd_lvlen; + uint8_t offset = 0; + uint8_t *gsup_indicator; + + gsup_indicator = msgb_put(msg, 7); + + /* First byte should always be GPRS_GSUP_MSGT_USSD_MAP */ + gsup_indicator[offset++] = GPRS_GSUP_MSGT_USSD_MAP; + gsup_indicator[offset++] = 0; // Total length + gsup_indicator[offset++] = req->message_type; + + gsup_indicator[offset++] = ref >> 24; + gsup_indicator[offset++] = ref >> 16; + gsup_indicator[offset++] = ref >> 8; + gsup_indicator[offset++] = ref; + + if (extension) { + gsup_indicator[offset++] = FMAP_MSISDN; + bcd_lvlen = gsm48_encode_bcd_number(gsup_indicator + offset, + 32, 0, extension); + + offset += bcd_lvlen; + msgb_put(msg, bcd_lvlen + 1); + } + + if (component_data) { + msgb_put(msg, req->component_length); + memcpy(gsup_indicator + offset, component_data, req->component_length); + } + + gsup_indicator[1] = offset + req->component_length - 2; //except GPRS_GSUP_MSGT_USSD_MAP and length field + return 0; +#if 0 + gsup_indicator[6] = req->component_type; + + /* invokeId */ + msgb_tlv_put(msg, GSM0480_COMPIDTAG_INVOKE_ID, 1, &req->invoke_id); + + /* opCode */ + msgb_tlv_put(msg, GSM0480_OPERATION_CODE, 1, &req->opcode); + + if (req->ussd_text_len > 0) { + msgb_tlv_put(msg, ASN1_OCTET_STRING_TAG, req->ussd_text_len + 1, &req->ussd_text_language); + } + + if (extension) { + uint8_t bcd_buf[32]; + bcd_len = gsm48_encode_bcd_number(bcd_buf, sizeof(bcd_buf), 0, + extension); + msgb_tlv_put(msg, FMAP_MSISDN, bcd_len - 1, &bcd_buf[1]); + } + + /* fill actual length */ + gsup_indicator[7] = 3 + 3 + (req->ussd_text_len + 1 + 2) + (bcd_len + 2);; + + /* wrap with GSM0480_CTYPE_INVOKE */ + // gsm0480_wrap_invoke(msg, req->opcode, invoke_id); + // gsup_indicator = msgb_push(msgb, 1); + // gsup_indicator[0] = GPRS_GSUP_MSGT_MAP; + return 0; +#endif +} + + + +int rx_uss_message_parse(const uint8_t* data, + size_t len, + struct ss_header *ss, + uint32_t *pref, + char* extention, + size_t extention_len) +{ + uint8_t ext_len; + const uint8_t* const_data = data + 1; // Skip constant + uint32_t ref; + int total_len; + + if (len < 7) + return -1; + + /* skip GPRS_GSUP_MSGT_MAP */ + total_len = *(const_data++); + ss->message_type = *(const_data++); + + ref = ((uint32_t)(*(const_data++))) << 24; + ref |= ((uint32_t)(*(const_data++))) << 16; + ref |= ((uint32_t)(*(const_data++))) << 8; + ref |= ((uint32_t)(*(const_data++))); + if (pref) + *pref = ref; + + total_len -= 4 + 1; // ref + sizeof(len) + + if (*const_data == FMAP_MSISDN) { + ext_len = *(++const_data); + if (extention) { + gsm48_decode_bcd_number(extention, + extention_len, + const_data, + 0); + } + const_data += ext_len + 1; + total_len -= ext_len + 2; // tag FMAP_MSISDN + sizeof(len) + } + + ss->component_offset = const_data - data; + ss->component_length = total_len; //data[ss->component_offset + 1]; + + return 0; +#if 0 + ss->component_type = *(++const_data); + + /* skip full len and move to component id */ + const_data += 2; + + if (*const_data != GSM0480_COMPIDTAG_INVOKE_ID) { + return -1; + } + const_data += 2; + ss->invoke_id = *const_data; + const_data++; + + // + if (*const_data != GSM0480_OPERATION_CODE) { + return -1; + } + const_data += 2; + ss->opcode = *const_data; + const_data++; + + + while (const_data - data < len) { + uint8_t len; + switch (*const_data) { + case ASN1_OCTET_STRING_TAG: + ss->ussd_text_len = len = (*(++const_data) - 1); + ss->ussd_text_language = *(++const_data); + memcpy(ss->ussd_text, + ++const_data, + (len > MAX_LEN_USSD_STRING) ? MAX_LEN_USSD_STRING : len); + const_data += len; + break; + + case FMAP_MSISDN: + len = *(++const_data); + gsm48_decode_bcd_number(extention, + extention_len, + const_data, + 0); + const_data += len + 1; + break; + default: + DEBUGP(DSS, "Unknown code: %d\n", *const_data); + return -1; + } + } + + return 0; +#endif +} diff --git a/openbsc/src/libmsc/transaction.c b/openbsc/src/libmsc/transaction.c index a750362..89cb2b5 100644 --- a/openbsc/src/libmsc/transaction.c +++ b/openbsc/src/libmsc/transaction.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,9 @@ void trans_free(struct gsm_trans *trans) case GSM48_PDISC_SMS: _gsm411_sms_trans_free(trans); break; + case GSM48_PDISC_NC_SS: + _ussd_trans_free(trans); + break; } if (trans->paging_request) { diff --git a/openbsc/src/libmsc/ussd.c b/openbsc/src/libmsc/ussd.c index 3cafe02..4f90149 100644 --- a/openbsc/src/libmsc/ussd.c +++ b/openbsc/src/libmsc/ussd.c @@ -33,9 +33,18 @@ #include #include #include +#include #include #include #include +#include +#include + +/* Last uniq generated session id */ +static uint32_t s_uniq_ussd_sessiod_id = 0; + +/* Forward declaration of USSD handler for USSD MAP interface */ +static int handle_rcv_ussd_sup(struct gsm_subscriber_connection *conn, struct msgb *msg); /* Declarations of USSD strings to be recognised */ const char USSD_TEXT_OWN_NUMBER[] = "*#100#"; @@ -55,6 +64,9 @@ int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg) char request_string[MAX_LEN_USSD_STRING + 1]; struct gsm48_hdr *gh; + if (conn->subscr->group->net->ussd_sup_client) + return handle_rcv_ussd_sup(conn, msg); + memset(&req, 0, sizeof(req)); memset(&reqhdr, 0, sizeof(reqhdr)); gh = msgb_l3(msg); @@ -136,3 +148,211 @@ static int send_own_number(struct gsm_subscriber_connection *conn, gsm0480_compose_ussd_component(&rss), &rssh); } + + +static int ussd_sup_send_reject(struct gsm_network *conn, uint32_t ref) +{ + struct ss_header rej; + rej.message_type = GSM0480_MTYPE_RELEASE_COMPLETE; + rej.component_length = 0; + + return ussd_map_tx_message(conn, &rej, NULL, ref, NULL); +} + +/* Callback from USSD MAP interface */ +int on_ussd_response(struct gsm_network *net, + uint32_t ref, + struct ss_header *reqhdr, + const uint8_t* component, + const char *extention) +{ + struct gsm_trans *trans = trans_find_by_callref(net, ref); + int rc = 0; + struct msgb *msg; + uint8_t *ptr8; + struct ss_header ssrep = *reqhdr; + + switch (reqhdr->message_type) { + case GSM0480_MTYPE_REGISTER: + DEBUGP(DSS, "Network originated USSD messages isn't supported yet!\n"); + + ussd_sup_send_reject(net, ref); + return 0; + + case GSM0480_MTYPE_FACILITY: + case GSM0480_MTYPE_RELEASE_COMPLETE: + if (!trans) { + DEBUGP(DSS, "No session was found for ref: %d!\n", + ref); + + ussd_sup_send_reject(net, ref); + return 0; + } + break; + default: + DEBUGP(DSS, "Unknown message type 0x%02x\n", reqhdr->message_type); + ussd_sup_send_reject(net, ref); + return 0; + } + + msg = gsm48_msgb_alloc(); + ptr8 = msgb_put(msg, 0); + + memcpy(ptr8, component, reqhdr->component_length); + msgb_put(msg, reqhdr->component_length); + + ssrep.transaction_id = (trans->transaction_id << 4) ^ 0x80; + rc = gsm0480_send_component(trans->conn, msg, &ssrep); + + if (reqhdr->message_type == GSM0480_MTYPE_RELEASE_COMPLETE) { + struct gsm_subscriber_connection* conn = trans->conn; + + trans_free(trans); + msc_release_connection(conn); + } + + return rc; +} + +static int get_invoke_id(const uint8_t* data, uint8_t len, uint8_t* pinvoke_id) +{ + /* 0: CTYPE tag + * 1..x: CTYPE len + * x: INVOKE_ID tag + * x+1: INVOKE_ID len + * x+2: INVOKE_ID value + */ + if (len < 5) + return 0; + + unsigned inv_offset = 2; + switch (data[0]) { + case GSM0480_CTYPE_INVOKE: + case GSM0480_CTYPE_RETURN_RESULT: + if (data[1] > 0x80) + inv_offset += data[1] & 0x7f; + if (inv_offset + 2 >= len) + return 0; + if (data[inv_offset] != GSM0480_COMPIDTAG_INVOKE_ID) + return 0; + *pinvoke_id = data[inv_offset + 2]; + return 1; + } + return 0; +} + +/* Handler function common to all mobile-originated USSDs in case if USSD MAP enabled */ +static int handle_rcv_ussd_sup(struct gsm_subscriber_connection *conn, struct msgb *msg) +{ + int rc = 0; + struct gsm48_hdr *gh = msgb_l3(msg); + struct ss_header reqhdr; + struct gsm_trans *trans = NULL; + uint8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */ + uint8_t invoke_id = 0; + + if (!conn->subscr) + return -EIO; + + memset(&reqhdr, 0, sizeof(reqhdr)); + + DEBUGP(DSS, "handle ussd tid=%d: %s\n", transaction_id, msgb_hexdump(msg)); + trans = trans_find_by_id(conn, GSM48_PDISC_NC_SS, transaction_id); + + rc = gsm0480_decode_ss_request(gh, msgb_l3len(msg), &reqhdr); + if (!rc) { + DEBUGP(DSS, "Incorrect SS header\n"); + if (!trans) { + goto release_conn; + } + + /* don't know how to process */ + goto failed_transaction; + } + + + switch (reqhdr.message_type) { + case GSM0480_MTYPE_REGISTER: + if (trans) { + /* we already have a transaction, ignore this message */ + goto release_conn; + } + if (!get_invoke_id(gh->data + reqhdr.component_offset, + reqhdr.component_length, + &invoke_id)) { + DEBUGP(DSS, "Incorrect InvokeID in transaction\n"); + goto release_conn; + } + + trans = trans_alloc(conn->bts->network, conn->subscr, + GSM48_PDISC_NC_SS, + transaction_id, s_uniq_ussd_sessiod_id++); + if (!trans) { + DEBUGP(DSS, "Failed to create new ussd transaction\n"); + goto transaction_not_found; + } + + trans->conn = conn; + trans->ss.invoke_id = invoke_id; + trans->ss.mo = 1; + trans->ss.dirty = 1; + break; + + case GSM0480_MTYPE_FACILITY: + if (!trans) { + DEBUGP(DSS, "No session found tid=%d\n", + transaction_id); + + if (!get_invoke_id(gh->data + reqhdr.component_offset, + reqhdr.component_length, + &invoke_id)) { + DEBUGP(DSS, "Incorrect InvokeID in transaction\n"); + goto release_conn; + } + + goto transaction_not_found; + } + break; + + case GSM0480_MTYPE_RELEASE_COMPLETE: + if (!trans) { + DEBUGP(DSS, "RELEASE_COMPLETE to non-existing transaction!\n"); + goto release_conn; + } + + trans_free(trans); + goto release_conn; + } + + rc = ussd_map_tx_message(conn->subscr->group->net, &reqhdr, + conn->subscr->extension, trans->callref, + gh->data + reqhdr.component_offset); + if (rc) { + /* do not send reject if we failed with the message */ + trans->ss.dirty = 0; + + DEBUGP(DSS, "Unable tp send uss over sup reason: %d\n", rc); + goto failed_transaction; + } + return 0; + +failed_transaction: + trans_free(trans); + +transaction_not_found: + gsm0480_send_ussd_reject(conn, invoke_id, transaction_id); + +release_conn: + msc_release_connection(conn); + return rc; +} + +void _ussd_trans_free(struct gsm_trans *trans) +{ + if (trans->ss.dirty) { + trans->ss.dirty = 0; + + ussd_sup_send_reject(trans->net, trans->callref); + } +} + -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:34 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:34 +0200 Subject: [PATCH 5/9] libmsc: Create a separate SUP socket for USSD MAP In-Reply-To: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328898-8298-5-git-send-email-sergey.kostanbaev@gmail.com> From: Sergey Kostanbaev --- openbsc/include/openbsc/gsm_data.h | 1 + openbsc/src/libmsc/vty_interface_layer3.c | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 6d7aba3..5800df7 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -244,6 +244,7 @@ struct gsm_network { struct llist_head upqueue; struct llist_head trans_list; struct bsc_api *bsc_api; + struct gprs_gsup_client *ussd_sup_client; unsigned int num_bts; struct llist_head bts_list; diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c index 790fedf..1a5b518 100644 --- a/openbsc/src/libmsc/vty_interface_layer3.c +++ b/openbsc/src/libmsc/vty_interface_layer3.c @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include @@ -993,6 +995,30 @@ DEFUN(meas_feed_scenario, meas_feed_scenario_cmd, return CMD_SUCCESS; } +DEFUN(sup_ussd_destination, sup_ussd_destination_cmd, + "sup-ussd destination ADDR <0-65535>", + "Enable SUP USSD socket to a given address/port" "destination\n" "address or hostname\n" "port number\n") +{ + struct gsm_network *gsmnet = gsmnet_from_vty(vty); + + if (gsmnet->ussd_sup_client) { + LOGP(DMM, LOGL_FATAL, "Can't create two USSD SUP clients\n"); + vty_out(vty, "%%USSD SUP client already configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + gsmnet->ussd_sup_client = gprs_gsup_client_create( + argv[0], atoi(argv[1]), &ussd_map_read_cb); + if (!gsmnet->ussd_sup_client) { + LOGP(DMM, LOGL_FATAL, "Cannot set up USSD SUP socket\n"); + vty_out(vty, "%%Cannot set up USSD SUP socket%s", VTY_NEWLINE); + return CMD_WARNING; + } + + gsmnet->ussd_sup_client->data = gsmnet; + return CMD_SUCCESS; +} + DEFUN(logging_fltr_imsi, logging_fltr_imsi_cmd, @@ -1130,6 +1156,7 @@ int bsc_vty_init_extra(void) install_element(NITB_NODE, &cfg_nitb_no_subscr_create_cmd); install_element(NITB_NODE, &cfg_nitb_assign_tmsi_cmd); install_element(NITB_NODE, &cfg_nitb_no_assign_tmsi_cmd); + install_element(NITB_NODE, &sup_ussd_destination_cmd); return 0; } -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:35 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:35 +0200 Subject: [PATCH 6/9] ussd_proxy: Add ussd_proxy utility converting SUP USSD MAP to SIP IMS In-Reply-To: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328898-8298-6-git-send-email-sergey.kostanbaev@gmail.com> From: Sergey Kostanbaev --- openbsc/src/ussd-proxy/Makefile.am | 17 + openbsc/src/ussd-proxy/ussd_proxy.c | 1544 +++++++++++++++++++++++++++++++++++ 2 files changed, 1561 insertions(+) create mode 100644 openbsc/src/ussd-proxy/Makefile.am create mode 100644 openbsc/src/ussd-proxy/ussd_proxy.c diff --git a/openbsc/src/ussd-proxy/Makefile.am b/openbsc/src/ussd-proxy/Makefile.am new file mode 100644 index 0000000..85f3e64 --- /dev/null +++ b/openbsc/src/ussd-proxy/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) +AM_CFLAGS=-Wall $(COVERAGE_CFLAGS) \ + $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) \ + $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOABIS_CFLAGS) \ + -I/usr/include/sofia-sip-1.12 -DNO_GSM0480_SEND_FUNC + +AM_LDFLAGS = $(COVERAGE_LDFLAGS) + +bin_PROGRAMS = ussd-proxy + +ussd_proxy_SOURCES = \ + ussd_proxy.c ../libmsc/gsm_ussd_map_proto.c ../libmsc/gsm_04_80.c + +ussd_proxy_LDADD = \ + -lsofia-sip-ua \ + $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCTRL_LIBS) $(LIBOSMOABIS_LIBS) diff --git a/openbsc/src/ussd-proxy/ussd_proxy.c b/openbsc/src/ussd-proxy/ussd_proxy.c new file mode 100644 index 0000000..a85e0fb --- /dev/null +++ b/openbsc/src/ussd-proxy/ussd_proxy.c @@ -0,0 +1,1544 @@ +#ifdef HAVE_CONFIG_H +//#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +typedef struct context_s context_t; +#define NTA_OUTGOING_MAGIC_T context_t +#define SU_ROOT_MAGIC_T context_t +#define NUA_MAGIC_T context_t + +typedef struct operation operation_t; +#define NUA_HMAGIC_T operation_t + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +typedef uint32_t sup_tcap_tid_t; + + +typedef struct isup_connection isup_connection_t; + +struct isup_connection { + context_t *ctx; + + su_socket_t isup_conn_socket; + su_wait_t isup_conn_event; + int isup_register_idx; + + /* osmocom data */ + + struct msgb *pending_msg; +}; + +typedef enum ss_type { + TYPE_USSD, + TYPE_SS_OTHER +} ss_type_t; + +struct ussd_session { + isup_connection_t *conn; + sup_tcap_tid_t ref; + + int ms_originated; + char extention[32]; + + ss_type_t type; + + uint8_t ss_code; + struct ss_request rigester_msg; +}; + +struct context_s { + su_home_t home[1]; + su_root_t *root; + + su_socket_t isup_acc_socket; + su_wait_t isup_acc_event; + + nua_t *nua; + + url_t *to_url; + url_t *self_url; + + su_timer_t *timer; + su_duration_t max_ussd_ses_duration; + + /* iconv data */ + iconv_t* utf8_to_ucs2; + iconv_t* ucs2_to_utf8; + + iconv_t* utf8_to_latin1; + iconv_t* latin1_to_utf8; + + /* Array of isup connections */ + struct isup_connection isup[1]; + + /* list of active operations */ + struct llist_head operation_list; + unsigned operation_count; + unsigned operations_max; +}; + + +/* Example of operation handle context information structure */ +struct operation +{ + struct llist_head list; + + nua_handle_t *handle; /* operation handle */ + context_t *ctx; + su_time_t tm_initiated; + + /* protocol specific sessions */ + struct ussd_session ussd; +}; + +static +int ussd_send_data(operation_t *op, int last, const char* lang, unsigned lang_len, + const char* msg, unsigned msg_len); +static +int ussd_send_data_ss(isup_connection_t *conn, + uint8_t message_type, + const uint8_t *component, + uint8_t component_len, + uint32_t ref); + +static +int ussd_send_reject(isup_connection_t *conn, uint32_t ref, uint8_t invoke_id); + +static const char* get_unknown_header(sip_t const *sip, const char *header) +{ + sip_header_t *h = (sip_header_t *)sip->sip_unknown; + for (; h; h = (sip_header_t *)h->sh_succ) { + if (strcasecmp(h->sh_unknown->un_name, header) == 0) { + return h->sh_unknown->un_value; + } + } + return NULL; +} + + +int sup_server_send(isup_connection_t *conn, struct msgb *msg) +{ + ssize_t sz; + + if (!conn) { + msgb_free(msg); + return -ENOTCONN; + } + + ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_GSUP); + ipa_msg_push_header(msg, IPAC_PROTO_OSMO); + + LOGP(DLCTRL, LOGL_ERROR, + "Sending wire, will send: %s\n", msgb_hexdump(msg)); + + // FIXME ugly hack!!! + // TODO place message in send queue !!!! + sz = send(conn->isup_conn_socket, msg->data, msg->len, 0); + msgb_free(msg); + + return ((unsigned)sz == msg->len) ? 0 : -1; +} + +static int ussd_parse_xml(const char *xml, + unsigned xml_len, + const char **lang, + unsigned *lang_len, + const char **msg, + unsigned *msg_len) +{ + /* Example of parsing XML + + + en + Test + + */ + + // tag + char* ussd_data_stag = strstr(xml, ""); + if (ussd_data_stag == NULL) + return 0; + + char* ussd_data_etag = strstr(ussd_data_stag, ""); + if (ussd_data_etag == NULL) + return 0; + + // tag + char* ussd_lang_stag = strstr(ussd_data_stag, ""); + if (ussd_lang_stag == NULL) + return 0; + + char* ussd_lang_etag = strstr(ussd_lang_stag, ""); + if (ussd_lang_etag == NULL) + return 0; + + // tag + char* ussd_ussd_stag = strstr(ussd_data_stag, ""); + if (ussd_ussd_stag == NULL) + return 0; + + char* ussd_ussd_etag = strstr(ussd_ussd_stag, ""); + if (ussd_ussd_etag == NULL) + return 0; + + if (ussd_ussd_etag - xml > xml_len || ussd_lang_etag - xml > xml_len) + return 0; + + *lang = ussd_lang_stag + strlen(""); + *lang_len = ussd_lang_etag - *lang; + + *msg = ussd_ussd_stag + strlen(""); + *msg_len = ussd_ussd_etag - *msg; + + return 1; +} + +// Operation APIs +static operation_t* operation_find_by_tid(context_t* ctx, sup_tcap_tid_t ref) +{ + operation_t* op; + llist_for_each_entry(op, &ctx->operation_list, list) { + if (op->ussd.ref == ref) + return op; + } + return NULL; +} + +static operation_t* operation_alloc(context_t* ctx) +{ + operation_t* op; + + if (ctx->operation_count >= ctx->operations_max) { + fprintf(stderr, "!!! maximum number of active session is reached: %d\n", + ctx->operation_count); + return NULL; + } + + /* create operation context information */ + op = su_zalloc(ctx->home, (sizeof *op)); + if (!op) { + return NULL; + } + + op->ctx = ctx; + op->tm_initiated = su_now(); + INIT_LLIST_HEAD(&op->list); + llist_add_tail(&op->list, &ctx->operation_list); + ctx->operation_count++; + + return op; +} + +static void operation_destroy(operation_t* op) +{ + /* release operation handle */ + nua_handle_destroy(op->handle); + op->handle = NULL; + + llist_del(&op->list); + op->ctx->operation_count--; + + if (op->ussd.type == TYPE_USSD) { + fprintf(stderr, "--- operation %*.s from %s destroyed (sessions: %d)\n", + op->ussd.rigester_msg.ussd_text_len, + op->ussd.rigester_msg.ussd_text, + op->ussd.extention, + op->ctx->operation_count); + } else { + fprintf(stderr, "--- operation 0x%02x from %s destroyed (sessions: %d)\n", + op->ussd.ss_code, + op->ussd.extention, + op->ctx->operation_count); + } + + /* release operation context information */ + su_free(op->ctx->home, op); +} + +void proxy_r_invite(int status, + char const *phrase, + nua_t *nua, + nua_magic_t *magic, + nua_handle_t *nh, + nua_hmagic_t *hmagic, + sip_t const *sip, + tagi_t tags[]) +{ + fprintf(stderr, "*** Got reply %d for INVITE\n", status); + if (status == 200) { + nua_ack(nh, TAG_END()); + } else if (hmagic->ussd.type == TYPE_USSD) { + printf("response to USSD INVITE: %03d %s\n", status, phrase); + + ussd_send_reject(hmagic->ussd.conn, + hmagic->ussd.ref, + hmagic->ussd.rigester_msg.invoke_id); + operation_destroy(hmagic); + } else { + printf("response to SS INVITE: %03d %s\n", status, phrase); + + ussd_send_data_ss(hmagic->ussd.conn, + GSM0480_MTYPE_RELEASE_COMPLETE, + NULL, + 0, + hmagic->ussd.ref); + operation_destroy(hmagic); + } +} + +void proxy_i_bye(int status, + char const *phrase, + nua_t *nua, + nua_magic_t *magic, + nua_handle_t *nh, + nua_hmagic_t *hmagic, + sip_t const *sip, + tagi_t tags[]) +{ + const char* ri; + int rc; + // printf("*** call released:\n%s\n", sip->sip_payload->pl_data); + + ri = get_unknown_header(sip, "Recv-Info"); + if (ri && (strcasecmp(ri, "g.3gpp.ussd") == 0)) { + /* Parse XML */ + const char *language; + const char *msg; + unsigned language_len; + unsigned msg_len; + + if (ussd_parse_xml(sip->sip_payload->pl_data, + sip->sip_payload->pl_len, + &language, &language_len, + &msg, &msg_len)) { + printf("=== USSD (%.*s): %.*s\n", + language_len, language, + msg_len, msg); + + /* Send reply back to SUP */ + // TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + rc = ussd_send_data(hmagic, 1, language, language_len, + msg, msg_len); + if (rc == 0) { + // Normal shutdown + operation_destroy(hmagic); + return; + } + + fprintf(stderr, "*** unable to send to SUP\n"); + } else { + fprintf(stderr, "*** unable to parse XML\n"); + } + } + + fprintf(stderr, "*** response BYE with %d satus is malformed, drop session\n", + status); + ussd_send_reject(hmagic->ussd.conn, + hmagic->ussd.ref, + hmagic->ussd.rigester_msg.invoke_id); + operation_destroy(hmagic); +} + +static +uint8_t get_nibble(uint8_t a) +{ + if (a >= '0' && a <= '9') + return a-'0'; + else if (a >= 'A' && a <= 'F') + return a-'A' + 10; + else if (a >= 'a' && a <= 'f') + return a-'a' + 10; + + fprintf(stderr, "*** Incorrect nibble deteced: %02x\n", a); + return 0xff; +} + +void proxy_i_bye_ss(int status, + char const *phrase, + nua_t *nua, + nua_magic_t *magic, + nua_handle_t *nh, + nua_hmagic_t *hmagic, + sip_t const *sip, + tagi_t tags[]) +{ + const char* pl_txt = sip->sip_payload->pl_data; + unsigned pl_txt_len = sip->sip_payload->pl_len; + uint8_t buffer[256]; + uint8_t buflen = 0; + int i; + + for (i = 0; i < pl_txt_len && buflen < sizeof(buffer) - 1; ) { + uint8_t hi_nibble = pl_txt[i++]; + if (hi_nibble == 0xff || i == pl_txt_len) + break; + uint8_t lo_nibble = pl_txt[i++]; + if (lo_nibble == 0xff) + break; + + buffer[buflen++] = (get_nibble(hi_nibble) << 4) | + get_nibble(lo_nibble); + } + + fprintf(stderr, "got bye_ss %d `%.*s` -> %d bytes\n", pl_txt_len, pl_txt_len, pl_txt, buflen); + + if (buflen > 1) { + /* ASN.1 length can be 1 or 2 bytes ( >2 isn't possible anyway here ) */ + unsigned len = (buffer[1] < 0x80) ? buffer[1] : ( (buflen > 2) ? buffer[2] : 0xff); + unsigned len_len = (buffer[1] < 0x80) ? 1 : buffer[1] - 0x80; + + if (len + 1 + len_len != buflen) { + fprintf(stderr, "*** parsed %d len, but should be %d (%s)", + buflen, len_len + 1 + len, pl_txt); + } + } + + ussd_send_data_ss(hmagic->ussd.conn, + GSM0480_MTYPE_RELEASE_COMPLETE, + buffer, + buflen, + hmagic->ussd.ref); + operation_destroy(hmagic); +} + +void proxy_r_bye(int status, + char const *phrase, + nua_t *nua, + nua_magic_t *magic, + nua_handle_t *nh, + nua_hmagic_t *hmagic, + sip_t const *sip, + tagi_t tags[]) +{ + fprintf(stderr, "*** Got reply %d for BUY\n", status); + operation_destroy(hmagic); +} + +void proxy_i_error(int status, + char const *phrase, + nua_t *nua, + nua_magic_t *magic, + nua_handle_t *nh, + nua_hmagic_t *hmagic, + sip_t const *sip, + tagi_t tags[]) +{ +#if 0 + if (!hmagic) { + return; + } + + fprintf(stderr, "*** error in session with %d satus\n", + status); + ussd_send_reject(hmagic->ussd.conn, + hmagic->ussd.rigester_msg.invoke_id, + hmagic->ussd.rigester_msg.opcode); + operation_destroy(hmagic); +#endif +} + +void proxy_info(int status, + char const *phrase, + nua_t *nua, + nua_magic_t *magic, + nua_handle_t *nh, + nua_hmagic_t *hmagic, + sip_t const *sip, + tagi_t tags[], + int response) +{ + const char* ri; + int rc; + + // Normal ACK is recieved + if (response == 1 && status == 200) + return; + + ri = get_unknown_header(sip, "Recv-Info"); + if (ri && (strcasecmp(ri, "g.3gpp.ussd") == 0)) { + /* Parse XML */ + const char *language; + const char *msg; + unsigned language_len; + unsigned msg_len; + + if (ussd_parse_xml(sip->sip_payload->pl_data, + sip->sip_payload->pl_len, + &language, &language_len, + &msg, &msg_len)) { + printf("%s USSD (%.*s): %.*s\n", + (response) ? ">>>" : "<<<", + language_len, language, + msg_len, msg); + + if (hmagic == 0) { + printf("*** unknown session, ignoring"); + + // FIXME this function works only with a dialog! + nua_respond(nh, 481, "INFO with no session", TAG_END()); + return; + } + + /* Send reply back to SUP */ + // TODO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + rc = ussd_send_data(hmagic, 0, language, language_len, + msg, msg_len); + if (rc == 0) + return; + + fprintf(stderr, "*** unable to send to SUP in INFO\n"); + } else { + fprintf(stderr, "*** unable to parse XML in INFO\n"); + } + } + + fprintf(stderr, "*** %s INFO with %d satus is malformed, drop session\n", + response ? "response" : "request", + status); + ussd_send_reject(hmagic->ussd.conn, + hmagic->ussd.ref, + hmagic->ussd.rigester_msg.invoke_id); + operation_destroy(hmagic); +} + +int ussd_create_xml_latin1(context_t* ctx, + char *content, size_t max_len, + const char* inbuf_latin1, int buf_len) +{ + const char *language = "en"; + char tmpbuf_utf8[2*MAX_LEN_USSD_STRING]; + unsigned tmpbuf_utf8_len; + + char* inbuf = (char*)inbuf_latin1; + size_t inleft = buf_len; + char* outbuf = tmpbuf_utf8; + size_t outleft = sizeof(tmpbuf_utf8); + size_t s; + + s = iconv(ctx->latin1_to_utf8, &inbuf, &inleft, &outbuf, &outleft); + if (s == (size_t)-1) { + LOGP(DLCTRL, LOGL_ERROR, "Unable to encode latin1 into utf8\n"); + return 0; + } + + tmpbuf_utf8_len = outbuf - tmpbuf_utf8; + + int content_len = snprintf(content, max_len, + "\n" + "\n" + "%s\n" + "%.*s\n" + "", + language, + tmpbuf_utf8_len, tmpbuf_utf8); + if (content_len > max_len) { + content[max_len - 1] = 0; + return 0; + } + return 1; +} + +static int decode_to_latin1(char* outbuf, unsigned size, + const uint8_t* msg, unsigned msg_len, uint8_t lang) +{ + if (lang == 0x0f) { + return gsm_7bit_decode_n_ussd(outbuf, size, msg, msg_len); + } else { + LOGP(DLCTRL, LOGL_ERROR, "Unknown language: 0x%02x\n", lang); + return 0; + } +} + +/* URL_RESERVED_CHARS in sofia is not strict enough as in RFC3986 */ +#define RFC3986_RESERVED_CHARS "!*'();:@&=+$,/?#[]" + +int ss_session_open_mo(operation_t *op, + isup_connection_t *conn, + const uint8_t* component, + uint8_t component_len, + uint32_t ref, + const char* extention) +{ + char buffer[512+1]; + int i; + context_t* ctx = op->ctx; + sip_to_t *to = NULL; + sip_to_t *from = NULL; + url_t to_url, from_url; + char* to_url_str; + char* from_url_str; + + op->ussd.ref = ref; + op->ussd.conn = conn; + op->ussd.ms_originated = 1; + op->ussd.type = TYPE_SS_OTHER; + + strncpy(op->ussd.extention, extention, sizeof(op->ussd.extention)); + + for (i = 0; i < component_len; ++i) { + uint8_t nibble_h = component[i] >> 4; + uint8_t nibble_l = component[i] & 0xf; + + buffer[2*i ] = (nibble_h < 10) ? '0' + nibble_h : 'a' + nibble_h - 10; + buffer[2*i + 1] = (nibble_l < 10) ? '0' + nibble_l : 'a' + nibble_l - 10; + } + buffer[2*i] = 0; + + /* Destination address */ + to_url = *ctx->to_url; + to_url.url_user = "mapss"; + to_url_str = url_as_string(ctx->home, &to_url); + if (to_url_str == NULL) { + goto failed_create_handle; + } + to = sip_to_create(ctx->home, (url_string_t *)to_url_str); + su_free(ctx->home, to_url_str); + if (!to) { + goto failed_create_handle; + } + + /* Source address */ + from_url = *ctx->self_url; + from_url.url_user = extention; + from_url_str = url_as_string(ctx->home, &from_url); + if (from_url_str == NULL) { + goto failed_create_handle; + } + from = sip_from_create(ctx->home, (url_string_t *)from_url_str); + su_free(ctx->home, from_url_str); + if (!to) { + goto failed_create_handle; + } + + /* create operation handle */ + op->handle = nua_handle(ctx->nua, + op, + SIPTAG_TO(to), + SIPTAG_FROM(from), + NUTAG_M_USERNAME(extention), + TAG_END()); + + su_free(ctx->home, from); + su_free(ctx->home, to); + from = NULL; + to = NULL; + + if (op->handle == NULL) { + goto failed_create_handle; + } + + nua_invite(op->handle, + SIPTAG_CONTENT_TYPE_STR("application/map-ss-binary"), + SIPTAG_PAYLOAD_STR(buffer), + TAG_END()); + return 0; + +failed_create_handle: + if (from != NULL) + su_free(ctx->home, from); + if (to != NULL) + su_free(ctx->home, to); + + return -1; +} + +int ussd_session_open_mo(operation_t *op, + isup_connection_t *conn, + struct ss_request* ss, + uint32_t ref, + const char* extention) +{ + char content[1024]; + char decoded[MAX_LEN_USSD_STRING + 1]; + char escaped_to[512]; + context_t* ctx = op->ctx; + sip_to_t *to = NULL; + sip_to_t *from = NULL; + url_t to_url, from_url; + char* to_url_str; + char* from_url_str; + + int decoded_len; + + op->ussd.ref = ref; + op->ussd.conn = conn; + op->ussd.ms_originated = 1; + op->ussd.type = TYPE_USSD; + op->ussd.rigester_msg = *ss; + strncpy(op->ussd.extention, extention, sizeof(op->ussd.extention)); + + decoded_len = decode_to_latin1(decoded, MAX_LEN_USSD_STRING, + op->ussd.rigester_msg.ussd_text, + op->ussd.rigester_msg.ussd_text_len, + op->ussd.rigester_msg.ussd_text_language); + if (decoded_len <= 0) { + goto failed_to_parse_xml; + } + decoded[decoded_len] = 0; + + if (!ussd_create_xml_latin1(ctx, content, sizeof(content), + decoded, decoded_len)) { + goto failed_to_parse_xml; + } + + + /* Destination address */ + url_escape(escaped_to, decoded, RFC3986_RESERVED_CHARS); + to_url = *ctx->to_url; + to_url.url_user = escaped_to; + to_url_str = url_as_string(ctx->home, &to_url); + if (to_url_str == NULL) { + goto failed_create_handle; + } + + to = sip_to_create(ctx->home, (url_string_t *)to_url_str); + su_free(ctx->home, to_url_str); + if (!to) { + goto failed_create_handle; + } + + /* Source address */ + from_url = *ctx->self_url; + from_url.url_user = extention; + from_url_str = url_as_string(ctx->home, &from_url); + if (from_url_str == NULL) { + goto failed_create_handle; + } + + from = sip_from_create(ctx->home, (url_string_t *)from_url_str); + su_free(ctx->home, from_url_str); + if (!to) { + goto failed_create_handle; + } + + /* create operation handle */ + op->handle = nua_handle(ctx->nua, + op, + SIPTAG_TO(to), + SIPTAG_FROM(from), + NUTAG_M_USERNAME(extention), + TAG_END()); + + su_free(ctx->home, from); + su_free(ctx->home, to); + from = NULL; + to = NULL; + + if (op->handle == NULL) { + goto failed_create_handle; + } + + nua_invite(op->handle, + SIPTAG_UNKNOWN_STR("Recv-Info: g.3gpp.ussd"), + SIPTAG_CONTENT_TYPE_STR("application/vnd.3gpp.ussd+xml"), + SIPTAG_PAYLOAD_STR(content), + TAG_END()); + return 0; + +failed_create_handle: + if (from != NULL) + su_free(ctx->home, from); + if (to != NULL) + su_free(ctx->home, to); +failed_to_parse_xml: + fprintf(stderr, "*** open_ussd_session failed!\n"); + return -1; +} + +int ussd_session_facility(operation_t *op, + struct ss_request* ss, + const char* extention) +{ + char content[1024]; + char decoded[MAX_LEN_USSD_STRING + 1]; + int decoded_len; + + decoded_len = decode_to_latin1(decoded, MAX_LEN_USSD_STRING, + op->ussd.rigester_msg.ussd_text, + op->ussd.rigester_msg.ussd_text_len, + op->ussd.rigester_msg.ussd_text_language); + if (decoded_len <= 0) { + return -1; + } + decoded[decoded_len] = 0; + + if (!ussd_create_xml_latin1(op->ctx, content, sizeof(content), + decoded, decoded_len)) { + return -1; + } + + nua_info(op->handle, + /* other tags as needed ... */ + SIPTAG_CONTENT_TYPE_STR("application/vnd.3gpp.ussd+xml"), + SIPTAG_UNKNOWN_STR("Recv-Info: g.3gpp.ussd"), + SIPTAG_PAYLOAD_STR(content), + TAG_END()); + + return 0; +} + +void context_callback(nua_event_t event, + int status, + char const *phrase, + nua_t *nua, + nua_magic_t *magic, + nua_handle_t *nh, + nua_hmagic_t *hmagic, + sip_t const *sip, + tagi_t tags[]) +{ + fprintf(stderr, "$$$ got event %d: status: %d (%s) : %p\n", event, status, phrase, hmagic); + + switch (event) { + case nua_i_error: + proxy_i_error(status, phrase, nua, magic, nh, hmagic, sip, tags); + break; + + case nua_i_info: + if (hmagic->ussd.type == TYPE_USSD) + proxy_info(status, phrase, nua, magic, nh, hmagic, sip, tags, 0); + break; + + case nua_r_info: + if (hmagic->ussd.type == TYPE_USSD) + proxy_info(status, phrase, nua, magic, nh, hmagic, sip, tags, 1); + break; + + case nua_i_bye: + if (hmagic->ussd.type == TYPE_USSD) + proxy_i_bye(status, phrase, nua, magic, nh, hmagic, sip, tags); + else + proxy_i_bye_ss(status, phrase, nua, magic, nh, hmagic, sip, tags); + break; + + case nua_i_invite: + //app_i_invite(status, phrase, nua, magic, nh, hmagic, sip, tags); + break; + + case nua_r_invite: + proxy_r_invite(status, phrase, nua, magic, nh, hmagic, sip, tags); + break; + + case nua_r_bye: + proxy_r_bye(status, phrase, nua, magic, nh, hmagic, sip, tags); + break; + + default: + /* unknown event -> print out error message */ + if (status > 100) { + printf("unknown event %d: %03d %s\n", + event, + status, + phrase); + } else { + printf("unknown event %d\n", event); + } + tl_print(stdout, "", tags); + break; + } +} + +static int rx_sup_uss_message(isup_connection_t *sup_conn, const uint8_t* data, size_t len) +{ + char extention[32] = {0}; + struct ss_header ss; + struct ss_request ssreq; + uint32_t ref; + operation_t* op; + int rc; + context_t *ctx = sup_conn->ctx; + memset(&ss, 0, sizeof(ss)); + + if (rx_uss_message_parse(data, len, &ss, &ref, extention, sizeof(extention))) { + LOGP(DLCTRL, LOGL_ERROR, "Can't parse uss message\n"); + goto err_bad_packet; + } + + memset(&ssreq, 0, sizeof(ssreq)); + rc = gsm0480_parse_ss_facility(data + ss.component_offset, + ss.component_length, + &ssreq); + if (!rc) { + LOGP(DLCTRL, LOGL_ERROR, "Can't parse facility message\n"); + goto err_bad_component; + } + + LOGP(DLCTRL, LOGL_ERROR, "Got ref=%d mtype=0x%02x invoke_id=0x%02x opcode=0x%02x ss_code=0x%02x component_type=0x%02x text=%s\n", ref, + ss.message_type, ssreq.invoke_id, ssreq.opcode, ssreq.ss_code, ssreq.component_type, ssreq.ussd_text); + + switch (ss.message_type) { + case GSM0480_MTYPE_REGISTER: + if (ssreq.component_type != GSM0480_CTYPE_INVOKE) { + LOGP(DLCTRL, LOGL_ERROR, "Non-INVOKE component type in REGISTER: 0x%02x\n", ssreq.component_type); + goto err_send_reject; + } + if (ssreq.opcode == GSM0480_OP_CODE_PROCESS_USS_DATA || + ssreq.opcode == GSM0480_OP_CODE_USS_NOTIFY || + ssreq.opcode == GSM0480_OP_CODE_USS_REQUEST) { + + LOGP(DLCTRL, LOGL_ERROR, "Don't know hot to handle this SS opcode: 0x%02x\n", ssreq.opcode); + goto err_send_reject; + } + /* Create new session */ + op = operation_alloc(ctx); + if (op == NULL) { + LOGP(DLCTRL, LOGL_ERROR, "Unable to allocate new session\n"); + goto err_send_reject; + } + + if (ssreq.opcode == GSM0480_OP_CODE_PROCESS_USS_REQ) { + LOGP(DLCTRL, LOGL_ERROR, "New session %.*s from %s, active: %d\n", + ssreq.ussd_text_len, + ssreq.ussd_text, + extention, + ctx->operation_count); + + op->ussd.ss_code = 0; + rc = ussd_session_open_mo(op, sup_conn, &ssreq, ref, extention); + if (rc < 0) { + operation_destroy(op); + goto err_send_reject; + } + } else { + LOGP(DLCTRL, LOGL_ERROR, "New session SS 0x%02x from %s, active: %d\n", + ssreq.opcode, + extention, + ctx->operation_count); + + op->ussd.ss_code = ssreq.ss_code; + op->ussd.rigester_msg = ssreq; + rc = ss_session_open_mo(op, + sup_conn, + data + ss.component_offset, + ss.component_length, + ref, + extention); + if (rc < 0) { + operation_destroy(op); + goto err_send_reject; + } + } + break; + + case GSM0480_MTYPE_FACILITY: + //Only MS-originated Menu session is supported, so we ignore INVOKE here + if (ssreq.component_type != GSM0480_CTYPE_RETURN_RESULT && + ssreq.component_type != GSM0480_CTYPE_RETURN_ERROR && + ssreq.component_type != GSM0480_CTYPE_REJECT) { + LOGP(DLCTRL, LOGL_ERROR, "Non-{RESULT/RETURN_ERROR/REJECT} component type in FACILITY: 0x%02x\n", ssreq.component_type); + goto err_send_reject; + } + // ///////////////////////////////////////////////// + // TODO handle RETURN_ERROR/REJECT + if (ssreq.component_type != GSM0480_CTYPE_RETURN_RESULT) { + LOGP(DLCTRL, LOGL_ERROR, "Component type in FACILITY: 0x%02x is not implemented yet\n", ssreq.component_type); + goto err_send_reject; + } + if (ssreq.opcode != GSM0480_OP_CODE_USS_REQUEST) { + LOGP(DLCTRL, LOGL_ERROR, "Don't know hot to handle this SS opcode: 0x%02x\n", ssreq.opcode); + goto err_send_reject; + } + op = operation_find_by_tid(ctx, ref); + if (op == NULL) { + LOGP(DLCTRL, LOGL_ERROR, "No active session with tid=%d were found\n", + ssreq.invoke_id); + goto err_send_reject; + } + + // TODO check result!! MO/MT error handling + rc = ussd_session_facility(op, &ssreq, extention); + if (rc < 0) { + operation_destroy(op); + goto err_send_reject; + } + break; + + case GSM0480_MTYPE_RELEASE_COMPLETE: + op = operation_find_by_tid(ctx, ref); + if (op == NULL) { + LOGP(DLCTRL, LOGL_ERROR, "No active session with tid=%d were found for RELEASE_COMPLETE\n", + ssreq.invoke_id); + return 0; + } + + nua_bye(op->handle, TAG_END()); + break; + + default: + LOGP(DLCTRL, LOGL_ERROR, "Unknown message type 0x%02x\n", ss.message_type); + goto err_send_reject; + } + + return 0; + +err_send_reject: + ussd_send_reject(sup_conn, ref, ssreq.invoke_id); + return -1; + +err_bad_component: + return ussd_send_data_ss(sup_conn, + GSM0480_MTYPE_RELEASE_COMPLETE, + NULL, + 0, + ref); + return -1; + +err_bad_packet: + // Disconnect ? + return -1; +} + +int ussd_send_reject(isup_connection_t *conn, uint32_t ref, uint8_t invoke_id) +{ + uint8_t buffer[2+3+3]; + + buffer[0] = GSM0480_CTYPE_REJECT; + buffer[1] = 3+3; + + buffer[2] = GSM0480_COMPIDTAG_INVOKE_ID; + buffer[3] = 1; + buffer[4] = invoke_id; + + buffer[5] = GSM_0480_PROBLEM_CODE_TAG_GENERAL; + buffer[6] = 1; + buffer[7] = GSM_0480_GEN_PROB_CODE_UNRECOGNISED; + + return ussd_send_data_ss(conn, + GSM0480_MTYPE_RELEASE_COMPLETE, + buffer, + sizeof(buffer), + ref); +} + +int ussd_send_data_ss(isup_connection_t *conn, + uint8_t message_type, + const uint8_t* component, + uint8_t component_len, + uint32_t ref) +{ + struct msgb *outmsg = msgb_alloc_headroom(4000, 64, __func__); + struct ss_header hdr; + + hdr.transaction_id = 0; + hdr.message_type = message_type; + hdr.component_length = component_len; + hdr.component_offset = 0; + + subscr_uss_message(outmsg, + &hdr, + NULL, + ref, + component); + + LOGP(DLCTRL, LOGL_ERROR, + "Sending USS, will send: %s\n", msgb_hexdump(outmsg)); + + return sup_server_send(conn, outmsg); +} + +int ussd_send_data(operation_t *op, int last, const char* lang, unsigned lang_len, + const char* msg, unsigned msg_len) +{ + struct msgb *buf; + struct ss_request ss; + int rc; + uint8_t message_type; + + memset(&ss, 0, sizeof(ss)); + + // TODO handle language + if (msg == NULL) { + message_type = GSM0480_MTYPE_RELEASE_COMPLETE; + ss.component_type = GSM0480_CTYPE_REJECT; + ss.opcode = op->ussd.rigester_msg.opcode; + } else if (last) { + message_type = GSM0480_MTYPE_RELEASE_COMPLETE; + ss.component_type = GSM0480_CTYPE_RETURN_RESULT; + ss.opcode = op->ussd.rigester_msg.opcode; + } else { + message_type = GSM0480_MTYPE_FACILITY; + ss.component_type = (op->ussd.ms_originated) ? GSM0480_CTYPE_INVOKE + : GSM0480_CTYPE_RETURN_RESULT; + ss.opcode = GSM0480_OP_CODE_USS_REQUEST; + } + + ss.invoke_id = op->ussd.rigester_msg.invoke_id; + + if (msg) { + char tmpbuf[MAX_LEN_USSD_STRING + 1]; + + char* inbuf = (char*)msg; + size_t inleft = msg_len; + char* outbuf = (char*)tmpbuf; + size_t outleft = sizeof(tmpbuf); + size_t s; + + // First of all try latin1 + s = iconv(op->ctx->utf8_to_latin1, + &inbuf, &inleft, + &outbuf, &outleft); + if (s == (size_t)-1) { + outbuf = (char*)ss.ussd_text; + outleft = MAX_ASN1_LEN_USSD_STRING; + + s = iconv(op->ctx->utf8_to_ucs2, + &inbuf, &inleft, + &outbuf, &outleft); + if (s == (size_t)-1) { + perror("can't convert string from utf8"); + } + // UCS-2 encoding + ss.ussd_text_language = 0x48; + ss.ussd_text_len = (uint8_t*)outbuf - ss.ussd_text; + + } else { + int outlen; + size_t len = (msg_len > MAX_LEN_USSD_STRING) ? + MAX_LEN_USSD_STRING : msg_len; + memcpy(tmpbuf, msg, len); + tmpbuf[len] = 0; + + gsm_7bit_encode_n_ussd(ss.ussd_text, + MAX_ASN1_LEN_USSD_STRING, tmpbuf, &outlen); + ss.ussd_text_len = outlen; + ss.ussd_text_language = 0x0f; + } + } else { + ss.ussd_text_len = 0; + ss.ussd_text_language = 0x0f; + ss.ussd_text[0] = 0; + } + + buf = gsm0480_compose_ussd_component(&ss); + if (!buf) { + return -1; + } + rc = ussd_send_data_ss(op->ussd.conn, message_type, + buf->data, msgb_length(buf), op->ussd.ref); + msgb_free(buf); + + return rc; +} + +static void timer_function(su_root_magic_t *magic, + su_timer_t *t, + su_timer_arg_t *arg) +{ + context_t *cli = (context_t*)arg; + su_time_t n = su_now(); + + operation_t *op, *tmp; + llist_for_each_entry_safe(op, tmp, &cli->operation_list, list) { + su_duration_t lasts = su_duration(n, op->tm_initiated); + if (lasts > cli->max_ussd_ses_duration) { + if (op->ussd.type == TYPE_USSD) { + fprintf(stderr, "!!! session %.*s from %s lasted %ld ms, more than thresold %ld ms, destroying\n", + op->ussd.rigester_msg.ussd_text_len, + op->ussd.rigester_msg.ussd_text, + op->ussd.extention, + lasts, + cli->max_ussd_ses_duration); + + + ussd_send_reject(op->ussd.conn, + op->ussd.ref, + op->ussd.rigester_msg.invoke_id); + } else { + fprintf(stderr, "!!! session 0x%02x from %s lasted %ld ms, more than thresold %ld ms, destroying\n", + op->ussd.ss_code, + op->ussd.extention, + lasts, + cli->max_ussd_ses_duration); + + ussd_send_data_ss(op->ussd.conn, + GSM0480_MTYPE_RELEASE_COMPLETE, + NULL, + 0, + op->ussd.ref); + } + operation_destroy(op); + } + } +} + +static int isup_handle_connection(context_t *cli, su_wait_t *w, void *p) +{ + int rc; + isup_connection_t *conn = (isup_connection_t*)p; + + int events = su_wait_events(w, conn->isup_conn_socket); + printf("*** connection; event=0x%x\n", events); + + if (events & (SU_WAIT_ERR | SU_WAIT_HUP)) { + printf("*** connection destroyed\n"); + goto err; + } else if (events & SU_WAIT_IN) { + /* Incoming data */ + + struct ipaccess_head *iph; + struct msgb *msg = NULL; + int ret = ipa_msg_recv_buffered(conn->isup_conn_socket, &msg, &conn->pending_msg); + if (ret <= 0) { + if (ret == -EAGAIN) + return 0; + if (ret == 0) + LOGP(DLCTRL, LOGL_INFO, "The control connection was closed\n"); + else + LOGP(DLCTRL, LOGL_ERROR, "Failed to parse ip access message: %d\n", ret); + + goto err; + } + + iph = (struct ipaccess_head *) msg->data; + switch (iph->proto) + { + case IPAC_PROTO_IPACCESS: + if (msg->l2h[0] == IPAC_MSGT_PING) { + printf("*** got PING\n"); + msg->l2h[0] = IPAC_MSGT_PONG; + send(conn->isup_conn_socket, msg->data, ntohs(iph->len) + sizeof(struct ipaccess_head), 0); + msgb_free(msg); + conn->pending_msg = NULL; + return 0; + } + + LOGP(DLCTRL, LOGL_ERROR, "Unknown IPAC_PROTO_IPACCESS msg 0x%x\n", msg->l2h[0]); + goto err; + case IPAC_PROTO_OSMO: + // TODO callback + if (msg->l2h[1] == GPRS_GSUP_MSGT_USSD_MAP) { + LOGP(DLCTRL, LOGL_ERROR, + "Receive USS: %s\n", msgb_hexdump(msg)); + + rc = rx_sup_uss_message(conn, &msg->l2h[1], msgb_l2len(msg) - 1); + if (rc < 0) { + /* TODO raise reject !!!!!!! */ + /* release complete */ + } + + msgb_free(msg); + conn->pending_msg = NULL; + return 0; + } + + /* TODO: handle gprs_gsup_decode() for other types */ + + LOGP(DLCTRL, LOGL_ERROR, "Unknown IPAC_PROTO_OSMO GPRS_GSUP_MSGT_* 0x%x\n", msg->l2h[1]); + msgb_free(msg); + conn->pending_msg = NULL; + goto err; + default: + LOGP(DLCTRL, LOGL_ERROR, "Protocol mismatch. We got 0x%x\n", iph->proto); + goto err; + } + } + + return 0; + +err: + close(conn->isup_conn_socket); + conn->isup_conn_socket = INVALID_SOCKET; + + su_wait_destroy(w); + + msgb_free(conn->pending_msg); + conn->pending_msg = NULL; + //su_root_deregister(cli, cli->isup_register_idx); + return 0; +} + +static int isup_handle_accept(context_t *cli, su_wait_t *w, void *p) +{ + su_sockaddr_t aaddr; + su_socket_t connection; + socklen_t len = sizeof(aaddr); + int rc; + + connection = accept(cli->isup_acc_socket, &aaddr.su_sa, &len); + if (connection == INVALID_SOCKET) { + perror("can't accept isup socket"); + return 0; + } + + printf("*** accepted from %s:%d\n", + inet_ntoa(aaddr.su_sin.sin_addr), + ntohs(aaddr.su_sin.sin_port)); + + /* TODO manage isup connection list, but just now use the single connection */ + isup_connection_t *conn = cli->isup; + if (conn->isup_conn_socket != INVALID_SOCKET) { + fprintf(stderr, "--- Can't accept, there's another connection\n"); + su_close(connection); + return 0; + } + + conn->ctx = cli; + conn->isup_conn_socket = connection; + conn->pending_msg = NULL; + + su_wait_init(&conn->isup_conn_event); + rc = su_wait_create(&conn->isup_conn_event, + conn->isup_conn_socket, + SU_WAIT_IN | /*SU_WAIT_OUT | */ SU_WAIT_HUP | SU_WAIT_ERR); + + conn->isup_register_idx = su_root_register(cli->root, + &conn->isup_conn_event, + isup_handle_connection, + conn, + 0); + return 0; +} + +#define DIPA_USSD_PROXY 0 + +struct log_info_cat ipa_proxy_test_cat[] = { + [DIPA_USSD_PROXY] = { + .name = "DIPA_USSD_PROXY", + .description = "USSD_PROXY", + .color = "\033[1;35m", + .enabled = 1, + .loglevel = LOGL_DEBUG, + }, +}; + +const struct log_info ipa_proxy_test_log_info = { + .filter_fn = NULL, + .cat = ipa_proxy_test_cat, + .num_cat = ARRAY_SIZE(ipa_proxy_test_cat), +}; + + +static void Usage(char* progname) +{ + fprintf(stderr, "Usage:\n" + "%s [options]\n" + "Options\n" + " -p TCP port to listen incoming SUP connection\n" + " (default: 8184)\n" + " -t Destination SIP URL (default: sip:127.0.0.1:5060)\n" + " -u User agent SIP URL (default: sip:127.0.0.1:5090)\n" + " -x Proxy SIP URL (default: )\n" + " -T Force using TCP instead trying UDP\n" + " -D Maximum period of open USSD session (default: 90)\n" + " -o Maximum number of concurrent USSD sessions\n" + " (default: 200)\n" + " -l <0-9> sip sofia loglevel, 0 - none; 9 - max\n" + , progname); +} + +int main(int argc, char *argv[]) +{ + su_home_t *home; + context_t context[1] = {{{SU_HOME_INIT(context)}}}; + su_sockaddr_t listen_addr; + int rc; + int sup_port = 8184; + const char* to_str = "sip:127.0.0.1:5060"; + const char* url_str = "sip:127.0.0.1:5090"; + const char* proxy_str = NULL; + int force_tcp = 0; + int max_ussd_ses_secs = 90; + int max_op_limit = 200; + int sip_loglevel = 1; + int c; + + while ((c = getopt (argc, argv, "x:p:t:u:D:To:l:L7?")) != -1) { + switch (c) + { + case 'x': + proxy_str = optarg; + break; + case 'p': + sup_port = atoi(optarg); + break; + case 't': + to_str = optarg; + break; + case 'u': + url_str = optarg; + break; + case 'T': + force_tcp = 1; + break; + case 'D': + max_ussd_ses_secs = atoi(optarg); + break; + case 'o': + max_op_limit = atoi(optarg); + break; + case 'l': + sip_loglevel = atoi(optarg); + break; + case 'L': + fprintf(stderr, " -L is now obsolete, ignored\n"); + break; + case '7': + fprintf(stderr, " -7 is now obsolete, ignored\n"); + break; + case '?': + default: + Usage(argv[0]); + return 2; + } + } + + osmo_init_logging(&ipa_proxy_test_log_info); + + su_init(); + su_home_init(home = context->home); + + context->root = su_root_create(context); + + su_log_set_level(NULL, sip_loglevel); + + /* Disable threading */ + su_root_threading(context->root, 0); + + if (!context->root) { + fprintf(stderr, "Unable to initialize sip-sofia context\n"); + return 1; + } + + context->utf8_to_latin1=iconv_open("iso8859-1", "utf-8"); + context->latin1_to_utf8=iconv_open("utf-8", "iso8859-1"); + context->utf8_to_ucs2=iconv_open("utf-16be", "utf-8"); + context->ucs2_to_utf8=iconv_open("utf-8", "utf-16be"); + + if (context->utf8_to_ucs2 == NULL || context->ucs2_to_utf8 == NULL || + context->utf8_to_latin1 == NULL || context->latin1_to_utf8 == NULL) { + fprintf(stderr, "Unable to initialize iconv\n"); + return 1; + } + + context->isup_acc_socket = su_socket(AF_INET, SOCK_STREAM, 0); + if (context->isup_acc_socket == INVALID_SOCKET) { + perror("unable to create socket\n"); + return 1; + } + su_setblocking(context->isup_acc_socket, 0); + su_setreuseaddr(context->isup_acc_socket, 1); + + context->isup->isup_conn_socket = INVALID_SOCKET; + + memset(&listen_addr, 0, sizeof(listen_addr)); + listen_addr.su_sin.sin_family = AF_INET; + listen_addr.su_sin.sin_addr.s_addr = INADDR_ANY; + listen_addr.su_sin.sin_port = htons(sup_port); + + rc = bind(context->isup_acc_socket, &listen_addr.su_sa, sizeof(listen_addr.su_sin)); + if (rc < 0) { + perror("cannot bind socket\n"); + return 2; + } + + rc = listen(context->isup_acc_socket, 1); + if (rc < 0) { + perror("cannot bind socket\n"); + return 2; + } + + su_wait_init(&context->isup_acc_event); + su_wait_create(&context->isup_acc_event, context->isup_acc_socket, SU_WAIT_ACCEPT); + su_root_register(context->root, + &context->isup_acc_event, + isup_handle_accept, + NULL, + 0); + + context->to_url = url_make(home, to_str); + context->self_url = url_make(home, url_str); + + if (context->to_url == NULL) { + fprintf(stderr, "Unable to parse destination URL\n"); + return 1; + } + if (context->self_url == NULL) { + fprintf(stderr, "Unable to parse our (source) URL\n"); + return 1; + } + + context->nua = nua_create(context->root, + context_callback, + context, + NUTAG_URL(url_str), + NUTAG_ENABLEINVITE(1), + NUTAG_AUTOALERT(1), + NUTAG_SESSION_TIMER(0), + NUTAG_AUTOANSWER(0), + NUTAG_MEDIA_ENABLE(0), + NUTAG_ALLOW("INVITE, ACK, BYE, CANCEL, INFO"), + TAG_NULL()); + if (context->nua == NULL) { + fprintf(stderr, "Unable to initialize sip-sofia nua\n"); + return 1; + } + + + if (proxy_str) { + nua_set_params(context->nua, + NUTAG_PROXY(proxy_str), + TAG_NULL()); + } + + if (force_tcp) { + nua_set_params(context->nua, + NTATAG_UDP_MTU(10), + TAG_NULL()); + } + + INIT_LLIST_HEAD(&context->operation_list); + context->operation_count = 0; + context->operations_max = max_op_limit; + + su_timer_t* tm = su_timer_create(su_root_task(context->root), 2000); + if (tm == NULL) { + fprintf(stderr, "Unable to initialize sip-sofia timer\n"); + return 1; + } + rc = su_timer_run(tm, timer_function, context); + if (rc < 0) { + fprintf(stderr, "Unable to start sip-sofia timer\n"); + return 1; + } + context->timer = tm; + context->max_ussd_ses_duration = max_ussd_ses_secs * 1000l; + + su_root_run(context->root); + nua_destroy(context->nua); + + return 0; +} + -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:36 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:36 +0200 Subject: [PATCH 7/9] ussd_proxy: Add to openbsc build system In-Reply-To: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328898-8298-7-git-send-email-sergey.kostanbaev@gmail.com> From: Sergey Kostanbaev --- openbsc/configure.ac | 12 ++++++++++++ openbsc/src/Makefile.am | 2 +- openbsc/src/ussd-proxy/Makefile.am | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/openbsc/configure.ac b/openbsc/configure.ac index 60601fe..b53eca6 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -177,6 +177,17 @@ AC_MSG_CHECKING([whether to enable VTY/CTRL tests]) AC_MSG_RESULT([$enable_ext_tests]) AM_CONDITIONAL(ENABLE_EXT_TESTS, test "x$enable_ext_tests" = "xyes") +# Enable/disable ussd_proxy utility +AC_ARG_ENABLE([ussd_proxy], [AS_HELP_STRING([--enable-ussd-proxy], [Build the USSD MAP SUP to SIP proxy])], + [osmo_ac_build_ussd_proxy="$enableval"],[osmo_ac_build_ussd_proxy="no"]) +if test "$osmo_ac_build_ussd_proxy" = "yes" ; then + PKG_CHECK_MODULES(LIBSOFIA_SIP_UA, sofia-sip-ua >= 1.10) + AC_DEFINE(BUILD_USSD_PROXY, 1, [Define if we want to build ussd_proxy]) +fi +AM_CONDITIONAL(BUILD_USSD_PROXY, test "x$osmo_ac_build_ussd_proxy" = "xyes") +AC_SUBST(osmo_ac_build_smpp) + + dnl Generate the output AM_CONFIG_HEADER(bscconfig.h) @@ -198,6 +209,7 @@ AC_OUTPUT( src/ipaccess/Makefile src/utils/Makefile src/gprs/Makefile + src/ussd-proxy/Makefile tests/Makefile tests/atlocal tests/gsm0408/Makefile diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am index 6f6174e..f12ed54 100644 --- a/openbsc/src/Makefile.am +++ b/openbsc/src/Makefile.am @@ -2,7 +2,7 @@ AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS) AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS) -SUBDIRS = libcommon libmgcp libbsc libmsc libtrau libfilter osmo-nitb osmo-bsc_mgcp utils ipaccess gprs +SUBDIRS = libcommon libmgcp libbsc libmsc libtrau libfilter osmo-nitb osmo-bsc_mgcp utils ipaccess gprs ussd-proxy # Conditional modules if BUILD_NAT diff --git a/openbsc/src/ussd-proxy/Makefile.am b/openbsc/src/ussd-proxy/Makefile.am index 85f3e64..0f9413a 100644 --- a/openbsc/src/ussd-proxy/Makefile.am +++ b/openbsc/src/ussd-proxy/Makefile.am @@ -1,3 +1,4 @@ +if BUILD_USSD_PROXY AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) AM_CFLAGS=-Wall $(COVERAGE_CFLAGS) \ $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) \ @@ -15,3 +16,4 @@ ussd_proxy_LDADD = \ -lsofia-sip-ua \ $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOCORE_LIBS) \ $(LIBOSMOCTRL_LIBS) $(LIBOSMOABIS_LIBS) +endif -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:37 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:37 +0200 Subject: [PATCH 8/9] libmsc: add gprs files for sup In-Reply-To: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328898-8298-8-git-send-email-sergey.kostanbaev@gmail.com> --- openbsc/src/libmsc/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openbsc/src/libmsc/Makefile.am b/openbsc/src/libmsc/Makefile.am index 566efe2..92483b3 100644 --- a/openbsc/src/libmsc/Makefile.am +++ b/openbsc/src/libmsc/Makefile.am @@ -10,6 +10,9 @@ libmsc_a_SOURCES = auth.c \ db.c \ gsm_04_08.c gsm_04_11.c gsm_04_11_helper.c \ gsm_04_80.c \ + ../gprs/gsm_04_08_gprs.c \ + ../gprs/gprs_utils.c \ + ../gprs/gprs_gsup_messages.c ../gprs/gprs_gsup_client.c \ gsm_subscriber.c \ mncc.c mncc_builtin.c mncc_sock.c \ rrlp.c \ -- 1.9.1 From sergey.kostanbaev at gmail.com Fri Apr 22 12:41:38 2016 From: sergey.kostanbaev at gmail.com (Sergey Kostanbaev) Date: Fri, 22 Apr 2016 14:41:38 +0200 Subject: [PATCH 9/9] ss: add test In-Reply-To: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <1461328898-8298-9-git-send-email-sergey.kostanbaev@gmail.com> --- openbsc/configure.ac | 1 + openbsc/tests/Makefile.am | 2 +- openbsc/tests/ussd/Makefile.am | 12 +++ openbsc/tests/ussd/ss_test.c | 199 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 openbsc/tests/ussd/Makefile.am create mode 100644 openbsc/tests/ussd/ss_test.c diff --git a/openbsc/configure.ac b/openbsc/configure.ac index b53eca6..6ea83de 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -229,6 +229,7 @@ AC_OUTPUT( tests/oap/Makefile tests/gtphub/Makefile tests/mm_auth/Makefile + tests/ussd/Makefile doc/Makefile doc/examples/Makefile Makefile) diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am index 09298a3..5732671 100644 --- a/openbsc/tests/Makefile.am +++ b/openbsc/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau subscr mm_auth +SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau subscr mm_auth ussd if BUILD_NAT SUBDIRS += bsc-nat bsc-nat-trie diff --git a/openbsc/tests/ussd/Makefile.am b/openbsc/tests/ussd/Makefile.am new file mode 100644 index 0000000..ecaa3db --- /dev/null +++ b/openbsc/tests/ussd/Makefile.am @@ -0,0 +1,12 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS) +noinst_PROGRAMS = ss_test + +# EXTRA_DIST = ss_test.ok + +ss_test_SOURCES = ss_test.c +ss_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \ + $(top_builddir)/src/libmsc/libmsc.a \ + $(top_builddir)/src/libbsc/libbsc.a \ + $(top_builddir)/src/libcommon/libcommon.a \ + $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -ldbi diff --git a/openbsc/tests/ussd/ss_test.c b/openbsc/tests/ussd/ss_test.c new file mode 100644 index 0000000..a59bd1b --- /dev/null +++ b/openbsc/tests/ussd/ss_test.c @@ -0,0 +1,199 @@ +/* simple test for the gsm0480 */ +/* + * 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 + +#define COMPARE(result, op, value) \ + if (!((result) op (value))) {\ + fprintf(stderr, "Compare failed. Was %x should be %x in %s:%d\n",result, value, __FILE__, __LINE__); \ + exit(-1); \ + } + +#define COMPARE_STR(result, value) \ + if (strcmp(result, value) != 0) { \ + fprintf(stderr, "Compare failed. Was %s should be %s in %s:%d\n",result, value, __FILE__, __LINE__); \ + exit(-1); \ + } + +#define DBG(...) + +#define VERIFY(res, cmp, wanted) \ + if (!(res cmp wanted)) { \ + printf("ASSERT failed: %s:%d Wanted: %d %s %d\n", \ + __FILE__, __LINE__, res, # cmp, wanted); \ + } + +const uint8_t test_ss_int_01[] = { +0xa1, 0x0e, 0x02, 0x01, 0x00, 0x02, 0x01, 0x0e, 0x30, 0x06, 0x04, 0x01, 0x21, 0x83, 0x01, 0x10 +}; + +const uint8_t test_ss_int_02[] = { +0xa1, 0x0b, 0x02, 0x01, 0x01, 0x02, 0x01, 0x0e, 0x30, 0x03, 0x04, 0x01, 0x21 +}; + +const uint8_t test_ss_int_03[] = { +0xa1, 0x17, 0x02, 0x01, 0x01, 0x02, 0x01, 0x0a, 0x30, 0x0f, 0x04, 0x01, 0x21, +0x83, 0x01, 0x10, 0x84, 0x07, 0x91, 0x52, 0x75, 0x89, 0x46, 0x36, 0x25 +}; + +const uint8_t test_ussd_01[] = { +0xa1, 0x81, 0x83, 0x02, 0x01, 0x01, 0x02, 0x01, 0x3c, 0x30, 0x7b, 0x04, 0x01, +0x0f, 0x04, 0x76, 0xd3, 0x66, 0x50, 0x4a, 0x55, 0xc4, 0x5c, 0x20, 0x6b, 0xda, +0x5c, 0x97, 0xd7, 0xe7, 0xe8, 0x34, 0xc8, 0x9e, 0x0f, 0x83, 0x68, 0x47, 0x50, +0xd2, 0x4d, 0x0f, 0xbb, 0xcb, 0xf4, 0xb4, 0x42, 0xe6, 0x02, 0x59, 0xd3, 0xe6, +0xba, 0xbc, 0x3e, 0x47, 0xa7, 0x41, 0xd6, 0x7c, 0x18, 0x34, 0x6d, 0x06, 0xa9, +0xc9, 0x65, 0x50, 0x31, 0x73, 0x81, 0xac, 0x69, 0x73, 0x5d, 0x5e, 0x9f, 0xa3, +0xd3, 0x20, 0x7b, 0x3e, 0x0c, 0x5a, 0xa7, 0xdb, 0x61, 0x7a, 0x38, 0x6d, 0x0e, +0xbb, 0x14, 0x34, 0x17, 0x68, 0xda, 0x0e, 0xcb, 0xe9, 0xa0, 0x6b, 0xb9, 0xbc, +0x2e, 0xbb, 0xc9, 0x8a, 0x9a, 0x0b, 0xd4, 0x4c, 0xb7, 0xd3, 0x20, 0x77, 0x18, +0x74, 0x2d, 0xdf, 0xcb, 0x20, 0x28, 0xbb, 0x3e, 0x57, 0xd8, 0x5c, 0x20, 0x7d, +0x38, 0x4d, 0x4e, 0x03 +}; + +const uint8_t test_ussd_02[] = { +0xa2, 0x10, 0x02, 0x01, 0x01, 0x30, 0x0b, 0x02, 0x01, 0x3c, 0x30, +0x06, 0x04, 0x01, 0x0f, 0x04, 0x01, 0x34 +}; + +static void test_uss_ser_deser(void) +{ + const uint32_t ref = 1234567890; + const char* ext = "555333444"; + struct msgb *data = msgb_alloc(4000, "test"); + struct ss_header ssh; + + uint32_t r_ref; + struct ss_header r_ssh; + char r_ext_buf[32]; + + int rc; + printf("testing serializing-deserializing\n"); + + ssh.component_length = sizeof(test_ussd_01); + ssh.component_offset = 0; + ssh.message_type = GSM0480_MTYPE_REGISTER; + ssh.transaction_id = 0; + + rc = subscr_uss_message(data, &ssh, ext, ref, test_ussd_01); + OSMO_ASSERT(rc == 0); + + printf("uss len:%d\n", msgb_length(data)); + + rc = rx_uss_message_parse(data->data, msgb_length(data), &r_ssh, &r_ref, r_ext_buf, sizeof(r_ext_buf)); + OSMO_ASSERT(rc == 0); + OSMO_ASSERT(ref == r_ref); + OSMO_ASSERT(ssh.message_type == r_ssh.message_type); + + rc = strcmp(ext, r_ext_buf); + printf("orig_ext:%s decoded_ext:%s\n", ext, r_ext_buf); + OSMO_ASSERT(rc == 0); + + printf("orig_clen:%d decoded_clen:%d\n", ssh.component_length, r_ssh.component_length); + OSMO_ASSERT(ssh.component_length == r_ssh.component_length); + + rc = memcmp(data->data + r_ssh.component_offset, test_ussd_01, sizeof(test_ussd_01)); + OSMO_ASSERT(rc == 0); + + + msgb_reset(data); + memset(&r_ssh, 0, sizeof(r_ssh)); + printf("testing serializing-deserializing small\n"); + + rc = subscr_uss_message(data, &ssh, NULL, ref, NULL); + OSMO_ASSERT(rc == 0); + + printf("uss len:%d\n", msgb_length(data)); + + rc = rx_uss_message_parse(data->data, msgb_length(data), &r_ssh, &r_ref, NULL, 0); + OSMO_ASSERT(rc == 0); + OSMO_ASSERT(ref == r_ref); + OSMO_ASSERT(ssh.message_type == r_ssh.message_type); + +} + +static void test_parse_ss(void) +{ + struct ss_request ss; + int rc; + printf("testing parsing ss\n"); + + // mark as uninitialized + memset(&ss, 0xcc, sizeof(ss)); + rc = gsm0480_parse_ss_facility(test_ussd_01, sizeof(test_ussd_01), &ss); + OSMO_ASSERT(rc == 1); + printf("Sample: test_ussd_01 ctype=%02x invoke_id=%02x opcode=%02x\n", + ss.component_type, ss.invoke_id, ss.opcode); + printf("- USSD: len:%d lang:%d\n", ss.ussd_text_len, ss.ussd_text_language); + + // mark as uninitialized + memset(&ss, 0xcc, sizeof(ss)); + rc = gsm0480_parse_ss_facility(test_ussd_02, sizeof(test_ussd_02), &ss); + OSMO_ASSERT(rc == 1); + printf("Sample: test_ussd_02 ctype=%02x invoke_id=%02x opcode=%02x\n", + ss.component_type, ss.invoke_id, ss.opcode); + + // mark as uninitialized + memset(&ss, 0xcc, sizeof(ss)); + rc = gsm0480_parse_ss_facility(test_ss_int_02, sizeof(test_ss_int_02), &ss); + OSMO_ASSERT(rc == 1); + printf("Sample: test_ss_int_02 ctype=%02x invoke_id=%02x opcode=%02x\n", + ss.component_type, ss.invoke_id, ss.opcode); + printf("- SS: code:%d\n", ss.ss_code); + + // mark as uninitialized + memset(&ss, 0xcc, sizeof(ss)); + rc = gsm0480_parse_ss_facility(test_ss_int_01, sizeof(test_ss_int_01), &ss); + OSMO_ASSERT(rc == 1); + printf("Sample: test_ss_int_01 ctype=%02x invoke_id=%02x opcode=%02x\n", + ss.component_type, ss.invoke_id, ss.opcode); + printf("- SS: code:%d\n", ss.ss_code); + + // mark as uninitialized + memset(&ss, 0xcc, sizeof(ss)); + rc = gsm0480_parse_ss_facility(test_ss_int_03, sizeof(test_ss_int_03), &ss); + OSMO_ASSERT(rc == 1); + printf("Sample: test_ss_int_01 ctype=%02x invoke_id=%02x opcode=%02x\n", + ss.component_type, ss.invoke_id, ss.opcode); + printf("- SS: code:%d\n", ss.ss_code); + +} + +int main(int argc, char **argv) +{ + osmo_init_logging(&log_info); + log_set_log_level(osmo_stderr_target, LOGL_INFO); + + test_uss_ser_deser(); + test_parse_ss(); + + printf("Done.\n"); + return EXIT_SUCCESS; +} -- 1.9.1 From holger at freyther.de Fri Apr 22 13:22:57 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 22 Apr 2016 15:22:57 +0200 Subject: [PATCH] Add function for appending range1024 to bitvec In-Reply-To: <1461074775-23946-1-git-send-email-msuraev@sysmocom.de> References: <1461074775-23946-1-git-send-email-msuraev@sysmocom.de> Message-ID: <59FE051D-61F4-4ACF-8CFF-99FD3796FC81@freyther.de> > On 19 Apr 2016, at 16:06, msuraev at sysmocom.de wrote: > > From: Max > > Add convenience function to append range1024 encoded data (see 3GPP TS > 44.018 Annex J) to a given bitvec. > --- > include/osmocom/core/bitvec.h | 3 +++ > src/bitvec.c | 36 ++++++++++++++++++++++++++++++++++++ > 2 files changed, 39 insertions(+) > > diff --git a/include/osmocom/core/bitvec.h b/include/osmocom/core/bitvec.h > index c3c1153..704573c 100644 > --- a/include/osmocom/core/bitvec.h > +++ b/include/osmocom/core/bitvec.h > @@ -44,6 +44,8 @@ > #include > #include > > +#include the code itself looks okay (adding lo+hi seems to result in 8 bits. But I think the place is wrong. The bit vector should not know about GSM (different layers, different library). Sure you are only using a data structure but let's keep our boundaries right. The closest we have as an example is msgb + tlv. One in GSM and one in Core. Can you add a bitvec_gsm.h or similar. holger From holger at freyther.de Fri Apr 22 13:35:23 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 22 Apr 2016 15:35:23 +0200 Subject: [PATCH 2/2] SysmoBTS: refactor code to simplify understanding In-Reply-To: <1461257007-22060-2-git-send-email-msuraev@sysmocom.de> References: <1461257007-22060-1-git-send-email-msuraev@sysmocom.de> <1461257007-22060-2-git-send-email-msuraev@sysmocom.de> Message-ID: <96FBF95A-2837-4BDC-AAC3-8C2A3D22C655@freyther.de> > On 21 Apr 2016, at 18:43, msuraev at sysmocom.de wrote: > > From: Max Hi Max, > > Use bool type for boolean values. > Move common code out of if.. else. is this worth our time? > - timeout_secs = 30; > } else { > SuperFemto_Prim_t *sysp = msgb_sysprim(msg); > > @@ -135,9 +134,10 @@ static int _l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, > wlc->is_sys_prim = 1; > wlc->conf_prim_id = femtobts_sysprim_req2conf[sysp->id]; > wqueue = &fl1h->write_q[MQ_SYS_WRITE]; > - timeout_secs = 30; > } > > + timeout_secs = 30; then make it const int timeout_secs = 30; From holger at freyther.de Fri Apr 22 13:39:20 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 22 Apr 2016 15:39:20 +0200 Subject: [PATCH] queue_new(): if calloc fails, abort (CID #57918) In-Reply-To: <20160418105619.GD1703@dub6> References: <1460644722-22972-1-git-send-email-nhofmeyr@sysmocom.de> <20160416113741.GK31766@nataraja> <20160418105619.GD1703@dub6> Message-ID: > On 18 Apr 2016, at 12:56, Neels Hofmeyr wrote: > > > (BTW, the only reason I didn't OSMO_ASSERT() was that there is no other use of > OSMO_ASSERT() anywhere else in OpenGGSN.) the GGSN has not used libosmocore before, so there will be many firsts. > > How should we handle this, I'd prefer not to spend time on that now. Commit the > patch with `return EOF' instead of abort()ing, as the old code suggests? I > don't know about that, EOF doesn't seem applicable at all. return EOF then. For commit messages we used to put "Fixes: CID#1234" at the bottom of the commit message. kind regards holger From holger at freyther.de Fri Apr 22 13:45:30 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 22 Apr 2016 15:45:30 +0200 Subject: [PATCH 0/4] take care of some coverity warnings In-Reply-To: <20160415215911.GA24964@dub6> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> <20160415210104.GD13168@dub6> <20160415215911.GA24964@dub6> Message-ID: <51FC829E-E0B8-4F54-B3B2-2BDEB99ACACD@freyther.de> > On 15 Apr 2016, at 23:59, Neels Hofmeyr wrote: > Neels, > if (ctx) > mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJ"); > - else > + else if (llme) > /* TLLI unassignment */ > gprs_llgmm_assign(llme, llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL); I don't think this is the right thing to do. There should always be a llme here. Please have a look at the coverity report it will tell where thos llme has been NULL. From holger at freyther.de Fri Apr 22 13:47:29 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 22 Apr 2016 15:47:29 +0200 Subject: [PATCH 1/4] gprs_gmm: ensure llme present upon Attach Req (CID #57686) In-Reply-To: <1460640093-22167-2-git-send-email-nhofmeyr@sysmocom.de> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> <1460640093-22167-2-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <80CFD1F8-469C-4224-8194-DB95432DFF8B@freyther.de> > On 14 Apr 2016, at 15:21, Neels Hofmeyr wrote: > > --- > openbsc/src/gprs/gprs_gmm.c | 4 ++++ > 1 file changed, 4 insertions(+) > > diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c > index 5f0a5fd..438e047 100644 > --- a/openbsc/src/gprs/gprs_gmm.c > +++ b/openbsc/src/gprs/gprs_gmm.c > @@ -838,6 +838,10 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg, > int rc; > > LOGMMCTXP(LOGL_INFO, ctx, "-> GMM ATTACH REQUEST "); > + if (!llme) { same as with my other mail. The lower layer should create a llme on the fly. So please have a look at the coverity user interface to see _where_ the llme is NULL and then we can have a look at that issue. holger From holger at freyther.de Fri Apr 22 13:50:01 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 22 Apr 2016 15:50:01 +0200 Subject: [PATCH 1/4] Add code generator for convolutional codes In-Reply-To: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> References: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: > On 18 Apr 2016, at 22:24, suraev at alumni.ntnu.no wrote: > > + self.block_len = block_len > + self.k = k > + self.n = n > + self.puncture = puncture > + self.rate_inv = len(polys) tabs vs. spaces? From holger at freyther.de Fri Apr 22 14:27:55 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 22 Apr 2016 16:27:55 +0200 Subject: [PATCH 1/4] gsm0480: RELEASE COMPLETE can be without any payload In-Reply-To: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <223D9476-9C06-4EFA-9CD6-C0E393E06518@freyther.de> > On 22 Apr 2016, at 14:41, Sergey Kostanbaev wrote: > > From: Sergey Kostanbaev > > --- > src/gsm/gsm0480.c | 6 ------ > 1 file changed, 6 deletions(-) > > diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c > index 8963b78..55bddd5 100644 > --- a/src/gsm/gsm0480.c > +++ b/src/gsm/gsm0480.c > @@ -248,12 +248,6 @@ int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len, > struct ss_request *req) > { > int rc = 0; > - > - if (len < sizeof(*hdr) + 2) { > - LOGP(0, LOGL_DEBUG, "SS Request is too short.\n"); > - return 0; > - } > - > if (gsm48_hdr_pdisc(hdr) == GSM48_PDISC_NC_SS) { > req->transaction_id = hdr->proto_discr & 0x70; > rc = parse_ss(hdr, len, req); static int parse_ss_info_elements(const uint8_t *ss_ie, uint16_t len, struct ss_request *req) { int rc = -1; /* Information Element Identifier - table 3.2 & GSM 04.08 section 10.5 */ uint8_t iei; uint8_t iei_length; iei = ss_ie[0]; iei_length = ss_ie[1]; /* If the data does not fit, report an error */ if (len - 2 < iei_length) return 0; so this code works with uint16_t and assumes there is at least two bytes after the header. I don't know best practices for integer underflow/overflow (shall we use ssize_t)? First we need a testcase Second we need to remove the assumptions about at least two bytes in payload. holger From holger at freyther.de Fri Apr 22 14:34:13 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 22 Apr 2016 16:34:13 +0200 Subject: [PATCH 2/4] gsm0480: Fix handling GSM0480_MTYPE_FACILITY, it has only LV and facility_ie In-Reply-To: <1461328875-8253-2-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> <1461328875-8253-2-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <518BB094-41E8-453B-BE54-E0EEFDCAE741@freyther.de> > On 22 Apr 2016, at 14:41, Sergey Kostanbaev wrote: > > + case GSM0480_MTYPE_FACILITY: > + rc &= parse_ss_facility(&hdr->data[0], len - sizeof(*hdr), req); > + break; > default: > LOGP(0, LOGL_DEBUG, "Unknown GSM 04.80 message-type field 0x%02x\n", > hdr->msg_type); > @@ -284,6 +288,18 @@ static int parse_ss(const struct gsm48_hdr *hdr, uint16_t len, struct ss_request > return rc; > } > > +static int parse_ss_facility(const uint8_t *ss_facility, uint16_t len, > + struct ss_request *req) > +{ > + uint8_t facility_length; > + > + facility_length = ss_facility[0]; > + if (len - 1 < facility_length) > + return 0; > + > + return parse_facility_ie(ss_facility + 1, facility_length, req); > +} > + > static int parse_ss_info_elements(const uint8_t *ss_ie, uint16_t len, > struct ss_request *req) same as with the previous commit. There is no guarantee that original_len - sizeof(*hdr) > 1 (as that was removed). So len - 1 can be UINT16_MAX here? From holger at freyther.de Fri Apr 22 14:51:24 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 22 Apr 2016 16:51:24 +0200 Subject: Half sided calls In-Reply-To: References: Message-ID: > On 22 Apr 2016, at 14:28, Pavel Balashov wrote: Hi pavel, > > Some clarification - my post was intended as a reply to this message : http://lists.osmocom.org/pipermail/openbsc/2015-September/000413.html > I'd inserted email header 'In-Reply-To: <864880037.819106.1442745090880.JavaMail.zimbra at kvk.uni-obuda.hu>' which points to message-id of the aforementioned post, hoping that my post will be glued to an existing thread of September 2015. > But looks like this naive approach doesn't work. thanks for having a look at it. Did you consider opening/discussion with oRTP upstream as well? In our application I don't think RTCP is a requirement so the -1 + 1 should not be a big issue. For a call which ports are actually being bound (ip+port)? What is being advertized on RSL? Where are the actual RTP frames going? holger From msuraev at sysmocom.de Fri Apr 22 16:19:49 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 22 Apr 2016 18:19:49 +0200 Subject: [PATCH] Add code generator for convolutional codes Message-ID: <1461341989-5140-1-git-send-email-msuraev@sysmocom.de> From: Max Add python utility to generate .c code with convolutional encoder/decoder based on polynomial description of the code. If argument given it'll be interpreted as intended output directory, otherwise current working directory is used. Codes for *CCH, CS2/3 and TCH/AFS are generated. Corresponding manual implementations are removed from tests. This introduce build-time dependency on python. The main work for this patch was generously contributed by Sylvain Munaut. Fixes: OS#1629 --- .gitignore | 1 + debian/control | 1 + include/Makefile.am | 1 + include/osmocom/gsm/gsm0503.h | 74 +++++++ src/gsm/Makefile.am | 8 + src/gsm/libosmogsm.map | 12 + tests/Makefile.am | 2 +- tests/conv/conv_test.c | 283 ++++++++---------------- utils/conv_gen.py | 494 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 681 insertions(+), 195 deletions(-) create mode 100644 include/osmocom/gsm/gsm0503.h create mode 100755 utils/conv_gen.py diff --git a/.gitignore b/.gitignore index f73a533..e3dbcac 100644 --- a/.gitignore +++ b/.gitignore @@ -100,6 +100,7 @@ doc/gsm doc/html.tar src/crc*gen.c +src/gsm/conv*gen.c include/osmocom/core/crc*gen.h include/osmocom/core/bit*gen.h diff --git a/debian/control b/debian/control index 459030b..42ebdba 100644 --- a/debian/control +++ b/debian/control @@ -39,6 +39,7 @@ Description: Osmo GPRS GB library Package: libosmogsm5 Section: libs Architecture: any +Build-Depends: python (>= 2.7.6) Depends: ${shlibs:Depends}, ${misc:Depends} Multi-Arch: same Description: Osmo GSM utility library diff --git a/include/Makefile.am b/include/Makefile.am index 0e5ed74..e7888c5 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -64,6 +64,7 @@ nobase_include_HEADERS = \ osmocom/gsm/gsm0411_utils.h \ osmocom/gsm/gsm0480.h \ osmocom/gsm/gsm0502.h \ + osmocom/gsm/gsm0503.h \ osmocom/gsm/gsm0808.h \ osmocom/gsm/gsm48.h \ osmocom/gsm/gsm48_ie.h \ diff --git a/include/osmocom/gsm/gsm0503.h b/include/osmocom/gsm/gsm0503.h new file mode 100644 index 0000000..cf1c976 --- /dev/null +++ b/include/osmocom/gsm/gsm0503.h @@ -0,0 +1,74 @@ +/* + * gsm0503.h + * + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include + +#include + +/*! \file conv_gen.h + * Osmocom convolutional encoder/decoder for xCCH channels, see 3GPP TS 05.03 + */ + +/*! \brief structure describing convolutional code xCCH + * + * Non-recursive code, flushed, not punctured code. + */ +extern const struct osmo_conv_code gsm0503_xcch; + +/*! \brief structures describing convolutional codes CS2/3 + */ +extern const struct osmo_conv_code gsm0503_cs2; +extern const struct osmo_conv_code gsm0503_cs3; + +/*! \brief structure describing convolutional code TCH/AFS 12.2 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_12_2; + +/*! \brief structure describing convolutional code TCH/AFS 10.2 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_10_2; + +/*! \brief structure describing convolutional code TCH/AFS 7.95 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_7_95; + +/*! \brief structure describing convolutional code TCH/AFS 7.4 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_7_4; + +/*! \brief structure describing convolutional code TCH/AFS 6.7 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_6_7; + +/*! \brief structure describing convolutional code TCH/AFS 5.9 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_5_9; + +/*! \brief structure describing convolutional code TCH/AFS 5.15 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_5_15; + +/*! \brief structure describing convolutional code TCH/AFS 4.75 + */ +extern const struct osmo_conv_code gsm0503_tch_afs_4_75; diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index b0ea643..1b186b1 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -18,6 +18,11 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \ gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \ gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \ lapd_core.c lapdm.c kasumi.c \ + conv_cs2_gen.c conv_cs3_gen.c conv_xcch_gen.c \ + conv_tch_afs_12_2_gen.c conv_tch_afs_10_2_gen.c \ + conv_tch_afs_7_95_gen.c conv_tch_afs_7_4_gen.c \ + conv_tch_afs_6_7_gen.c conv_tch_afs_5_9_gen.c \ + conv_tch_afs_5_15_gen.c conv_tch_afs_4_75_gen.c \ auth_core.c auth_comp128v1.c auth_comp128v23.c \ auth_milenage.c milenage/aes-encblock.c \ milenage/aes-internal.c milenage/aes-internal-enc.c \ @@ -30,3 +35,6 @@ libosmogsm_la_LDFLAGS = $(LTLDFLAGS_OSMOGSM) -version-info $(LIBVERSION) -no-und libosmogsm_la_LIBADD = libgsmint.la EXTRA_DIST = libosmogsm.map + +conv%gen.c: ../../utils/conv_gen.py + $(AM_V_GEN)python ../../utils/conv_gen.py diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 6886a6c..a75acc0 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -26,6 +26,18 @@ abis_nm_ipa_magic; osmo_sitype_strs; +gsm0503_xcch; +gsm0503_cs2; +gsm0503_cs3; +gsm0503_tch_afs_12_2; +gsm0503_tch_afs_10_2; +gsm0503_tch_afs_7_95; +gsm0503_tch_afs_7_4; +gsm0503_tch_afs_6_7; +gsm0503_tch_afs_5_9; +gsm0503_tch_afs_5_15; +gsm0503_tch_afs_4_75; + comp128; dbm2rxlev; diff --git a/tests/Makefile.am b/tests/Makefile.am index 03506af..3aaa99b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -47,7 +47,7 @@ bits_bitcomp_test_SOURCES = bits/bitcomp_test.c bits_bitcomp_test_LDADD = $(top_builddir)/src/libosmocore.la conv_conv_test_SOURCES = conv/conv_test.c -conv_conv_test_LDADD = $(top_builddir)/src/libosmocore.la +conv_conv_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libgsmint.la gsm0808_gsm0808_test_SOURCES = gsm0808/gsm0808_test.c gsm0808_gsm0808_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index de62f23..608f829 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -6,6 +6,7 @@ #include #include #include +#include #define MAX_LEN_BITS 512 #define MAX_LEN_BYTES (512/8) @@ -15,107 +16,6 @@ /* Test codes */ /* ------------------------------------------------------------------------ */ -/* GSM xCCH -> Non-recursive code, flushed, not punctured */ -static const uint8_t conv_gsm_xcch_next_output[][2] = { - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, -}; - -static const uint8_t conv_gsm_xcch_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, -}; - -static const struct osmo_conv_code conv_gsm_xcch = { - .N = 2, - .K = 5, - .len = 224, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, -}; - - -/* GSM TCH/AFS 7.95 -> Recursive code, flushed, with puncturing */ -static const uint8_t conv_gsm_tch_afs_7_95_next_output[][2] = { - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 5, 4 }, { 7, 6 }, - { 9, 8 }, { 11, 10 }, { 12, 13 }, { 14, 15 }, - { 16, 17 }, { 18, 19 }, { 21, 20 }, { 23, 22 }, - { 25, 24 }, { 27, 26 }, { 28, 29 }, { 30, 31 }, - { 33, 32 }, { 35, 34 }, { 36, 37 }, { 38, 39 }, - { 40, 41 }, { 42, 43 }, { 45, 44 }, { 47, 46 }, - { 49, 48 }, { 51, 50 }, { 52, 53 }, { 54, 55 }, - { 56, 57 }, { 58, 59 }, { 61, 60 }, { 63, 62 }, - { 1, 0 }, { 3, 2 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 13, 12 }, { 15, 14 }, - { 17, 16 }, { 19, 18 }, { 20, 21 }, { 22, 23 }, - { 24, 25 }, { 26, 27 }, { 29, 28 }, { 31, 30 }, - { 32, 33 }, { 34, 35 }, { 37, 36 }, { 39, 38 }, - { 41, 40 }, { 43, 42 }, { 44, 45 }, { 46, 47 }, - { 48, 49 }, { 50, 51 }, { 53, 52 }, { 55, 54 }, - { 57, 56 }, { 59, 58 }, { 60, 61 }, { 62, 63 }, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_term_output[] = { - 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5, 6, 5, 3, 0, - 4, 7, 1, 2, 1, 2, 4, 7, 7, 4, 2, 1, 2, 1, 7, 4, - 7, 4, 2, 1, 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7, - 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6, 5, 6, 0, 3, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_term_state[] = { - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, -}; - -static int conv_gsm_tch_afs_7_95_puncture[] = { - 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310, - 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367, - 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415, - 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463, - 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505, - 506, 508, 509, 511, 512, - -1, /* end */ -}; - -static const struct osmo_conv_code conv_gsm_tch_afs_7_95 = { - .N = 3, - .K = 7, - .len = 165, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_tch_afs_7_95_next_output, - .next_state = conv_gsm_tch_afs_7_95_next_state, - .next_term_output = conv_gsm_tch_afs_7_95_next_term_output, - .next_term_state = conv_gsm_tch_afs_7_95_next_term_state, - .puncture = conv_gsm_tch_afs_7_95_puncture, -}; - - /* GMR-1 TCH3 Speech -> Non recursive code, tail-biting, punctured */ static const uint8_t conv_gmr1_tch3_speech_next_output[][2] = { { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, @@ -220,18 +120,6 @@ static const struct osmo_conv_code conv_wimax_fch = { .next_state = conv_wimax_fch_next_state, }; - -/* Random code -> Non recursive code, direct truncation, non-punctured */ -static const struct osmo_conv_code conv_trunc = { - .N = 2, - .K = 5, - .len = 224, - .term = CONV_TERM_TRUNCATION, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, -}; - - /* ------------------------------------------------------------------------ */ /* Test vectors */ /* ------------------------------------------------------------------------ */ @@ -246,87 +134,6 @@ struct conv_test_vector { pbit_t vec_out[MAX_LEN_BYTES]; }; -static const struct conv_test_vector tests[] = { - { - .name = "GSM xCCH (non-recursive, flushed, not punctured)", - .code = &conv_gsm_xcch, - .in_len = 224, - .out_len = 456, - .has_vec = 1, - .vec_in = { 0xf3, 0x1d, 0xb4, 0x0c, 0x4d, 0x1d, 0x9d, 0xae, - 0xc0, 0x0a, 0x42, 0x57, 0x13, 0x60, 0x80, 0x96, - 0xef, 0x23, 0x7e, 0x4c, 0x1d, 0x96, 0x24, 0x19, - 0x17, 0xf2, 0x44, 0x99 }, - .vec_out = { 0xe9, 0x4d, 0x70, 0xab, 0xa2, 0x87, 0xf0, 0xe7, - 0x04, 0x14, 0x7c, 0xab, 0xaf, 0x6b, 0xa1, 0x16, - 0xeb, 0x30, 0x00, 0xde, 0xc8, 0xfd, 0x0b, 0x85, - 0x80, 0x41, 0x4a, 0xcc, 0xd3, 0xc0, 0xd0, 0xb6, - 0x26, 0xe5, 0x4e, 0x32, 0x49, 0x69, 0x38, 0x17, - 0x33, 0xab, 0xaf, 0xb6, 0xc1, 0x08, 0xf3, 0x9f, - 0x8c, 0x75, 0x6a, 0x4e, 0x08, 0xc4, 0x20, 0x5f, - 0x8f }, - }, - { - .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)", - .code = &conv_gsm_tch_afs_7_95, - .in_len = 165, - .out_len = 448, - .has_vec = 1, - .vec_in = { 0x87, 0x66, 0xc3, 0x58, 0x09, 0xd4, 0x06, 0x59, - 0x10, 0xbf, 0x6b, 0x7f, 0xc8, 0xed, 0x72, 0xaa, - 0xc1, 0x3d, 0xf3, 0x1e, 0xb0 }, - .vec_out = { 0x92, 0xbc, 0xde, 0xa0, 0xde, 0xbe, 0x01, 0x2f, - 0xbe, 0xe4, 0x61, 0x32, 0x4d, 0x4f, 0xdc, 0x41, - 0x43, 0x0d, 0x15, 0xe0, 0x23, 0xdd, 0x18, 0x91, - 0xe5, 0x36, 0x2d, 0xb7, 0xd9, 0x78, 0xb8, 0xb1, - 0xb7, 0xcb, 0x2f, 0xc0, 0x52, 0x8f, 0xe2, 0x8c, - 0x6f, 0xa6, 0x79, 0x88, 0xed, 0x0c, 0x2e, 0x9e, - 0xa1, 0x5f, 0x45, 0x4a, 0xfb, 0xe6, 0x5a, 0x9c }, - }, - { - .name = "GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)", - .code = &conv_gmr1_tch3_speech, - .in_len = 48, - .out_len = 72, - .has_vec = 1, - .vec_in = { 0x4d, 0xcb, 0xfc, 0x72, 0xf4, 0x8c }, - .vec_out = { 0xc0, 0x86, 0x63, 0x4b, 0x8b, 0xd4, 0x6a, 0x76, 0xb2 }, - }, - { - .name = "WiMax FCH (non-recursive, tail-biting, not punctured)", - .code = &conv_wimax_fch, - .in_len = 48, - .out_len = 96, - .has_vec = 1, - .vec_in = { 0xfc, 0xa0, 0xa0, 0xfc, 0xa0, 0xa0 }, - .vec_out = { 0x19, 0x42, 0x8a, 0xed, 0x21, 0xed, 0x19, 0x42, - 0x8a, 0xed, 0x21, 0xed }, - }, - { - .name = "??? (non-recursive, direct truncation, not punctured)", - .code = &conv_trunc, - .in_len = 224, - .out_len = 448, - .has_vec = 1, - .vec_in = { 0xe5, 0xe0, 0x85, 0x7e, 0xf7, 0x08, 0x19, 0x5a, - 0xb9, 0xad, 0x82, 0x37, 0x98, 0x8b, 0x26, 0xb9, - 0x81, 0x26, 0x9c, 0x75, 0xaf, 0xf3, 0xcb, 0x07, - 0xac, 0x63, 0xe2, 0x9c, - }, - .vec_out = { 0xea, 0x3b, 0x55, 0x0c, 0xd3, 0xf7, 0x85, 0x69, - 0xe5, 0x79, 0x83, 0xd3, 0xc3, 0x9f, 0xb8, 0x61, - 0x21, 0x63, 0x51, 0x18, 0xac, 0xcd, 0x32, 0x49, - 0x53, 0x5c, 0x13, 0x1d, 0xbe, 0x05, 0x11, 0x63, - 0x5c, 0xc3, 0x42, 0x05, 0x1c, 0x68, 0x0a, 0xb4, - 0x61, 0x15, 0xaa, 0x4d, 0x94, 0xed, 0xb3, 0x3a, - 0x5d, 0x1b, 0x09, 0xc2, 0x99, 0x01, 0xec, 0x68 }, - }, - { /* end */ }, -}; - - - - /* ------------------------------------------------------------------------ */ /* Main */ /* ------------------------------------------------------------------------ */ @@ -345,6 +152,94 @@ int main(int argc, char *argv[]) ubit_t *bu0, *bu1; sbit_t *bs; +/* Random code -> Non recursive code, direct truncation, non-punctured */ + const struct osmo_conv_code conv_trunc = { + .N = 2, + .K = 5, + .len = 224, + .term = CONV_TERM_TRUNCATION, + .next_output = gsm0503_xcch.next_output, + .next_state = gsm0503_xcch.next_state, + }; + + const struct conv_test_vector tests[] = { + { + .name = "GSM xCCH (non-recursive, flushed, not punctured)", + .code = &gsm0503_xcch, + .in_len = 224, + .out_len = 456, + .has_vec = 1, + .vec_in = { 0xf3, 0x1d, 0xb4, 0x0c, 0x4d, 0x1d, 0x9d, 0xae, + 0xc0, 0x0a, 0x42, 0x57, 0x13, 0x60, 0x80, 0x96, + 0xef, 0x23, 0x7e, 0x4c, 0x1d, 0x96, 0x24, 0x19, + 0x17, 0xf2, 0x44, 0x99 }, + .vec_out = { 0xe9, 0x4d, 0x70, 0xab, 0xa2, 0x87, 0xf0, 0xe7, + 0x04, 0x14, 0x7c, 0xab, 0xaf, 0x6b, 0xa1, 0x16, + 0xeb, 0x30, 0x00, 0xde, 0xc8, 0xfd, 0x0b, 0x85, + 0x80, 0x41, 0x4a, 0xcc, 0xd3, 0xc0, 0xd0, 0xb6, + 0x26, 0xe5, 0x4e, 0x32, 0x49, 0x69, 0x38, 0x17, + 0x33, 0xab, 0xaf, 0xb6, 0xc1, 0x08, 0xf3, 0x9f, + 0x8c, 0x75, 0x6a, 0x4e, 0x08, 0xc4, 0x20, 0x5f, + 0x8f }, + }, + { + .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)", + .code = &gsm0503_tch_afs_7_95, + .in_len = 165, + .out_len = 448, + .has_vec = 1, + .vec_in = { 0x87, 0x66, 0xc3, 0x58, 0x09, 0xd4, 0x06, 0x59, + 0x10, 0xbf, 0x6b, 0x7f, 0xc8, 0xed, 0x72, 0xaa, + 0xc1, 0x3d, 0xf3, 0x1e, 0xb0 }, + .vec_out = { 0x92, 0xbc, 0xde, 0xa0, 0xde, 0xbe, 0x01, 0x2f, + 0xbe, 0xe4, 0x61, 0x32, 0x4d, 0x4f, 0xdc, 0x41, + 0x43, 0x0d, 0x15, 0xe0, 0x23, 0xdd, 0x18, 0x91, + 0xe5, 0x36, 0x2d, 0xb7, 0xd9, 0x78, 0xb8, 0xb1, + 0xb7, 0xcb, 0x2f, 0xc0, 0x52, 0x8f, 0xe2, 0x8c, + 0x6f, 0xa6, 0x79, 0x88, 0xed, 0x0c, 0x2e, 0x9e, + 0xa1, 0x5f, 0x45, 0x4a, 0xfb, 0xe6, 0x5a, 0x9c }, + }, + { + .name = "GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)", + .code = &conv_gmr1_tch3_speech, + .in_len = 48, + .out_len = 72, + .has_vec = 1, + .vec_in = { 0x4d, 0xcb, 0xfc, 0x72, 0xf4, 0x8c }, + .vec_out = { 0xc0, 0x86, 0x63, 0x4b, 0x8b, 0xd4, 0x6a, 0x76, 0xb2 }, + }, + { + .name = "WiMax FCH (non-recursive, tail-biting, not punctured)", + .code = &conv_wimax_fch, + .in_len = 48, + .out_len = 96, + .has_vec = 1, + .vec_in = { 0xfc, 0xa0, 0xa0, 0xfc, 0xa0, 0xa0 }, + .vec_out = { 0x19, 0x42, 0x8a, 0xed, 0x21, 0xed, 0x19, 0x42, + 0x8a, 0xed, 0x21, 0xed }, + }, + { + .name = "??? (non-recursive, direct truncation, not punctured)", + .code = &conv_trunc, + .in_len = 224, + .out_len = 448, + .has_vec = 1, + .vec_in = { 0xe5, 0xe0, 0x85, 0x7e, 0xf7, 0x08, 0x19, 0x5a, + 0xb9, 0xad, 0x82, 0x37, 0x98, 0x8b, 0x26, 0xb9, + 0x81, 0x26, 0x9c, 0x75, 0xaf, 0xf3, 0xcb, 0x07, + 0xac, 0x63, 0xe2, 0x9c, + }, + .vec_out = { 0xea, 0x3b, 0x55, 0x0c, 0xd3, 0xf7, 0x85, 0x69, + 0xe5, 0x79, 0x83, 0xd3, 0xc3, 0x9f, 0xb8, 0x61, + 0x21, 0x63, 0x51, 0x18, 0xac, 0xcd, 0x32, 0x49, + 0x53, 0x5c, 0x13, 0x1d, 0xbe, 0x05, 0x11, 0x63, + 0x5c, 0xc3, 0x42, 0x05, 0x1c, 0x68, 0x0a, 0xb4, + 0x61, 0x15, 0xaa, 0x4d, 0x94, 0xed, 0xb3, 0x3a, + 0x5d, 0x1b, 0x09, 0xc2, 0x99, 0x01, 0xec, 0x68 }, + }, + { /* end */ }, + }; + srandom(time(NULL)); bu0 = malloc(sizeof(ubit_t) * MAX_LEN_BITS); diff --git a/utils/conv_gen.py b/utils/conv_gen.py new file mode 100755 index 0000000..1377fca --- /dev/null +++ b/utils/conv_gen.py @@ -0,0 +1,494 @@ +#!/usr/bin/python + +mod_license = """ +/* + * Copyright (C) 2011-2016 Sylvain Munaut + * Copyright (C) 2016 sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +""" + +import sys, os, math + +class ConvolutionalCode(object): + + def __init__(self, block_len, polys, name = "call-me", description = "LOL", puncture = []): + # Save simple params + self.block_len = block_len + self.k = 1 + self.puncture = puncture + self.rate_inv = len(polys) + + # Infos + self.name = name + self.description = description + + # Handle polynoms (and check for recursion) + self.polys = [(1, 1) if x[0] == x[1] else x for x in polys] + + # Determine the polynomial degree + for (x, y) in polys: + self.k = max(self.k, int(math.floor(math.log(max(x, y), 2)))) + self.k = self.k + 1 + + self.poly_divider = 1 + rp = [x[1] for x in self.polys if x[1] != 1] + if rp: + if not all([x == rp[0] for x in rp]): + raise ValueError("Bad polynoms: Can't have multiple different divider polynoms !") + if not all([x[0] == 1 for x in polys if x[1] == 1]): + raise ValueError("Bad polynoms: Can't have a '1' divider with a non '1' dividend in a recursive code") + self.poly_divider = rp[0] + + @property + def recursive(self): + return self.poly_divider != 1 + + @property + def _state_mask(self): + return (1 << (self.k - 1)) - 1 + + def next_state(self, state, bit): + nb = combine( + (state << 1) | bit, + self.poly_divider, + self.k, + ) + return ((state << 1) | nb) & self._state_mask + + def next_term_state(self, state): + return (state << 1) & self._state_mask + + def next_output(self, state, bit, ns = None): + # Next state bit + if ns is None: + ns = self.next_state(state, bit) + + src = (ns & 1) | (state << 1) + + # Scan polynoms + rv = [] + for p_n, p_d in self.polys: + if self.recursive and p_d == 1: + o = bit # No choice ... (systematic output in recursive case) + else: + o = combine(src, p_n, self.k) + rv.append(o) + + return rv + + def next_term_output(self, state, ns = None): + # Next state bit + if ns is None: + ns = self.next_term_state(state) + + src = (ns & 1) | (state << 1) + + # Scan polynoms + rv = [] + for p_n, p_d in self.polys: + if self.recursive and p_d == 1: + # Systematic output are replaced when in 'termination' mode + o = combine(src, self.poly_divider, self.k) + else: + o = combine(src, p_n, self.k) + rv.append(o) + + return rv + + def next(self, state, bit): + ns = self.next_state(state, bit) + nb = self.next_output(state, bit, ns = ns) + return ns, nb + + def next_term(self, state): + ns = self.next_term_state(state) + nb = self.next_term_output(state, ns = ns) + return ns, nb + + def _print_term(self, fi, num_states, pack = False): + d = [] + for state in range(num_states): + x = pack(self.next_term_output(state)) if pack else self.next_term_state(state) + d.append("%d, " % x) + print >>fi, "\t%s" % ''.join(d) + + def _print_x(self, fi, num_states, pack = False): + for state in range(num_states): + x0 = pack(self.next_output(state, 0)) if pack else self.next_state(state, 0) + x1 = pack(self.next_output(state, 1)) if pack else self.next_state(state, 1) + print >>fi, "\t{ %2d, %2d }," % (x0, x1) + + def gen_tables(self, pref, fi): + pack = lambda n: sum([x << (self.rate_inv - i - 1) for i, x in enumerate(n)]) + num_states = 1 << (self.k - 1) + print >>fi, "\nstatic const uint8_t %s_state[][2] = {" % self.name + self._print_x(fi, num_states) + print >>fi, "};\n\nstatic const uint8_t %s_output[][2] = {" % self.name + self._print_x(fi, num_states, pack) + print >>fi, "};" + + if self.recursive: + print >>fi, "\nstatic const uint8_t %s_term_state[] = {" % self.name + self._print_term(fi, num_states) + print >>fi, "};\n\nstatic const uint8_t %s_term_output[] = {" % self.name + self._print_term(fi, num_states, pack) + print >>fi, "};" + + if len(self.puncture): + print >>fi, "\nstatic const int %s_puncture[] = {" % self.name + for p in self.puncture: + print >>fi, "\t%d," % p + print >>fi, "};" + + print >>fi, "\n/* %s */" % self.description + print >>fi, "const struct osmo_conv_code %s_%s = {" % (pref, self.name) + print >>fi, "\t.N = %d," % self.rate_inv + print >>fi, "\t.K = %d," % self.k + print >>fi, "\t.len = %d," % self.block_len + print >>fi, "\t.next_output = %s_output," % self.name + print >>fi, "\t.next_state = %s_state," % self.name + if self.recursive: + print >>fi, "\t.next_term_output = %s_term_output," % self.name + print >>fi, "\t.next_term_state = %s_term_state," % self.name + if len(self.puncture): + print >>fi, "\t.puncture = %s_puncture," % self.name + print >>fi, "};" + +poly = lambda *args: sum([(1 << x) for x in args]) + +def combine(src, sel, nb): + x = src & sel + fn_xor = lambda x, y: x ^ y + return reduce(fn_xor, [(x >> n) & 1 for n in range(nb)]) + +# Polynomials according to 3GPP TS 05.03 Annex B +G0 = poly(0, 3, 4) +G1 = poly(0, 1, 3, 4) +G2 = poly(0, 2, 4) +G3 = poly(0, 1, 2, 3, 4) +G4 = poly(0, 2, 3, 5, 6) +G5 = poly(0, 1, 4, 6) +G6 = poly(0, 1, 2, 3, 4, 6) +G7 = poly(0, 1, 2, 3, 6) + +CCH_poly = [ + ( G0, 1 ), + ( G1, 1 ) +] + +xCCH = ConvolutionalCode( + 224, + CCH_poly, + name = "xcch", + description =""" *CCH convolutional code: + 228 bits blocks, rate 1/2, k = 5 + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 +""" +) + +CS2 = ConvolutionalCode( + 290, + CCH_poly, + puncture = [ + 15, 19, 23, 27, 31, 35, 43, 47, 51, 55, 59, 63, 67, 71, + 75, 79, 83, 91, 95, 99, 103, 107, 111, 115, 119, 123, 127, 131, + 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, 187, 191, 195, + 199, 203, 207, 211, 215, 219, 223, 227, 235, 239, 243, 247, 251, 255, + 259, 263, 267, 271, 275, 283, 287, 291, 295, 299, 303, 307, 311, 315, + 319, 323, 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 379, + 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 427, 431, 435, 439, + 443, 447, 451, 455, 459, 463, 467, 475, 479, 483, 487, 491, 495, 499, + 503, 507, 511, 515, 523, 527, 531, 535, 539, 543, 547, 551, 555, 559, + 563, 571, 575, 579, 583, 587, -1 + ], + name = "cs2", + description =""" CS2 convolutional code: + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 +""" +) + +CS3 = ConvolutionalCode( + 334, + CCH_poly, + puncture = [ + 15, 17, 21, 23, 27, 29, 33, 35, 39, 41, 45, 47, 51, 53, + 57, 59, 63, 65, 69, 71, 75, 77, 81, 83, 87, 89, 93, 95, + 99, 101, 105, 107, 111, 113, 117, 119, 123, 125, 129, 131, 135, 137, + 141, 143, 147, 149, 153, 155, 159, 161, 165, 167, 171, 173, 177, 179, + 183, 185, 189, 191, 195, 197, 201, 203, 207, 209, 213, 215, 219, 221, + 225, 227, 231, 233, 237, 239, 243, 245, 249, 251, 255, 257, 261, 263, + 267, 269, 273, 275, 279, 281, 285, 287, 291, 293, 297, 299, 303, 305, + 309, 311, 315, 317, 321, 323, 327, 329, 333, 335, 339, 341, 345, 347, + 351, 353, 357, 359, 363, 365, 369, 371, 375, 377, 381, 383, 387, 389, + 393, 395, 399, 401, 405, 407, 411, 413, 417, 419, 423, 425, 429, 431, + 435, 437, 441, 443, 447, 449, 453, 455, 459, 461, 465, 467, 471, 473, + 477, 479, 483, 485, 489, 491, 495, 497, 501, 503, 507, 509, 513, 515, + 519, 521, 525, 527, 531, 533, 537, 539, 543, 545, 549, 551, 555, 557, + 561, 563, 567, 569, 573, 575, 579, 581, 585, 587, 591, 593, 597, 599, + 603, 605, 609, 611, 615, 617, 621, 623, 627, 629, 633, 635, 639, 641, + 645, 647, 651, 653, 657, 659, 663, 665, 669, 671, -1 + ], + name = "cs3", + description =""" CS3 convolutional code: + G0 = 1 + D3 + D4 + G1 = 1 + D + D3 + D4 +""" +) + +TCH_AFS_12_2 = ConvolutionalCode( + 250, + [ + ( 1, 1 ), + ( G1, G0 ), + ], + puncture = [ + 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 363, + 365, 369, 373, 377, 379, 381, 385, 389, 393, 395, 397, 401, + 405, 409, 411, 413, 417, 421, 425, 427, 429, 433, 437, 441, + 443, 445, 449, 453, 457, 459, 461, 465, 469, 473, 475, 477, + 481, 485, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, + -1 + ], + name = 'tch_afs_12_2', + description = """TCH/AFS 12.2 convolutional code: + 250 bits block, rate 1/2, punctured + G0/G0 = 1 + G1/G0 = 1 + D + D3 + D4 / 1 + D3 + D4 +""" +) + +TCH_AFS_10_2 = ConvolutionalCode( + 210, + [ + ( G1, G3 ), + ( G2, G3 ), + ( 1, 1 ), + ], + puncture = [ + 1, 4, 7, 10, 16, 19, 22, 28, 31, 34, 40, 43, + 46, 52, 55, 58, 64, 67, 70, 76, 79, 82, 88, 91, + 94, 100, 103, 106, 112, 115, 118, 124, 127, 130, 136, 139, + 142, 148, 151, 154, 160, 163, 166, 172, 175, 178, 184, 187, + 190, 196, 199, 202, 208, 211, 214, 220, 223, 226, 232, 235, + 238, 244, 247, 250, 256, 259, 262, 268, 271, 274, 280, 283, + 286, 292, 295, 298, 304, 307, 310, 316, 319, 322, 325, 328, + 331, 334, 337, 340, 343, 346, 349, 352, 355, 358, 361, 364, + 367, 370, 373, 376, 379, 382, 385, 388, 391, 394, 397, 400, + 403, 406, 409, 412, 415, 418, 421, 424, 427, 430, 433, 436, + 439, 442, 445, 448, 451, 454, 457, 460, 463, 466, 469, 472, + 475, 478, 481, 484, 487, 490, 493, 496, 499, 502, 505, 508, + 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, + 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, + 583, 586, 589, 592, 595, 598, 601, 604, 607, 609, 610, 613, + 616, 619, 621, 622, 625, 627, 628, 631, 633, 634, 636, 637, + 639, 640, -1 + ], + name = 'tch_afs_10_2', + description = """TCH/AFS 10.2 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 +""" +) + +TCH_AFS_7_95 = ConvolutionalCode( + 165, + [ + ( 1, 1 ), + ( G5, G4 ), + ( G6, G4 ), + ], + puncture = [ + 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310, + 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367, + 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415, + 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463, + 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505, + 506, 508, 509, 511, 512, -1 + ], + name = 'tch_afs_7_95', + description = """TCH/AFS 7.95 kbits convolutional code: + G4/G4 = 1 + G5/G4 = 1 + D + D4 + D6 / 1 + D2 + D3 + D5 + D6 + G6/G4 = 1 + D + D2 + D3 + D4 + D6 / 1 + D2 + D3 + D5 + D6 +""" +) + +TCH_AFS_7_4 = ConvolutionalCode( + 154, + [ + ( G1, G3 ), + ( G2, G3 ), + ( 1, 1 ), + ], + puncture = [ + 0, 355, 361, 367, 373, 379, 385, 391, 397, 403, 409, 415, + 421, 427, 433, 439, 445, 451, 457, 460, 463, 466, 468, 469, + 471, 472, -1 + ], + name = 'tch_afs_7_4', + description = """TCH/AFS 7.4 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 +""" +) + +TCH_AFS_6_7 = ConvolutionalCode( + 140, + [ + ( G1, G3 ), + ( G2, G3 ), + ( 1, 1 ), + ( 1, 1 ), + ], + puncture = [ + 1, 3, 7, 11, 15, 27, 39, 55, 67, 79, 95, 107, + 119, 135, 147, 159, 175, 187, 199, 215, 227, 239, 255, 267, + 279, 287, 291, 295, 299, 303, 307, 311, 315, 319, 323, 327, + 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 369, 371, + 375, 377, 379, 383, 385, 387, 391, 393, 395, 399, 401, 403, + 407, 409, 411, 415, 417, 419, 423, 425, 427, 431, 433, 435, + 439, 441, 443, 447, 449, 451, 455, 457, 459, 463, 465, 467, + 471, 473, 475, 479, 481, 483, 487, 489, 491, 495, 497, 499, + 503, 505, 507, 511, 513, 515, 519, 521, 523, 527, 529, 531, + 535, 537, 539, 543, 545, 547, 549, 551, 553, 555, 557, 559, + 561, 563, 565, 567, 569, 571, 573, 575, -1 + ], + name = 'tch_afs_6_7', + description = """TCH/AFS 6.7 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 +""" +) + +TCH_AFS_5_9 = ConvolutionalCode( + 124, + [ + ( G4, G6 ), + ( G5, G6 ), + ( 1, 1), + ( 1, 1), + ], + puncture = [ + 0, 1, 3, 5, 7, 11, 15, 31, 47, 63, 79, 95, + 111, 127, 143, 159, 175, 191, 207, 223, 239, 255, 271, 287, + 303, 319, 327, 331, 335, 343, 347, 351, 359, 363, 367, 375, + 379, 383, 391, 395, 399, 407, 411, 415, 423, 427, 431, 439, + 443, 447, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, + 495, 499, 503, 507, 509, 511, 512, 513, 515, 516, 517, 519, + -1 + ], + name = 'tch_afs_5_9', + description = """TCH/AFS 5.9 kbits convolutional code: + 124 bits + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 +""" +) + +TCH_AFS_5_15 = ConvolutionalCode( + 109, + [ + ( G1, G3 ), + ( G1, G3 ), + ( G2, G3 ), + ( 1, 1 ), + ( 1, 1 ), + ], + puncture = [ + 0, 4, 5, 9, 10, 14, 15, 20, 25, 30, 35, 40, + 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, + 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, + 290, 300, 310, 315, 320, 325, 330, 334, 335, 340, 344, 345, + 350, 354, 355, 360, 364, 365, 370, 374, 375, 380, 384, 385, + 390, 394, 395, 400, 404, 405, 410, 414, 415, 420, 424, 425, + 430, 434, 435, 440, 444, 445, 450, 454, 455, 460, 464, 465, + 470, 474, 475, 480, 484, 485, 490, 494, 495, 500, 504, 505, + 510, 514, 515, 520, 524, 525, 529, 530, 534, 535, 539, 540, + 544, 545, 549, 550, 554, 555, 559, 560, 564, -1 + ], + name = 'tch_afs_5_15', + description = """TCH/AFS 5.15 kbits convolutional code: + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4 + G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4 + G3/G3 = 1 + G3/G3 = 1 +""" +) + +TCH_AFS_4_75 = ConvolutionalCode( + 101, + [ + ( G4, G6 ), + ( G4, G6 ), + ( G5, G6 ), + ( 1, 1 ), + ( 1, 1 ), + ], + puncture = [ + 0, 1, 2, 4, 5, 7, 9, 15, 25, 35, 45, 55, + 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, + 185, 195, 205, 215, 225, 235, 245, 255, 265, 275, 285, 295, + 305, 315, 325, 335, 345, 355, 365, 375, 385, 395, 400, 405, + 410, 415, 420, 425, 430, 435, 440, 445, 450, 455, 459, 460, + 465, 470, 475, 479, 480, 485, 490, 495, 499, 500, 505, 509, + 510, 515, 517, 519, 520, 522, 524, 525, 526, 527, 529, 530, + 531, 532, 534, -1 + ], + name = 'tch_afs_4_75', + description = """TCH/AFS 4.75 kbits convolutional code: + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6 + G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6 + G6/G6 = 1 + G6/G6 = 1 +""" +) + +def gen_c(dest, pref, code): + f = open(os.path.join(dest, 'conv_' + code.name + '_gen.c'), 'w') + print >>f, mod_license + print >>f, "#include " + print >>f, "#include " + code.gen_tables(pref, f) + +if __name__ == '__main__': + print >>sys.stderr, "Generating convolutional codes..." + prefix = "gsm0503" + path = sys.argv[1] if len(sys.argv) > 1 else os.getcwd() + gen_c(path, prefix, xCCH) + gen_c(path, prefix, CS2) + gen_c(path, prefix, CS3) + gen_c(path, prefix, TCH_AFS_12_2) + gen_c(path, prefix, TCH_AFS_10_2) + gen_c(path, prefix, TCH_AFS_7_95) + gen_c(path, prefix, TCH_AFS_7_4) + gen_c(path, prefix, TCH_AFS_6_7) + gen_c(path, prefix, TCH_AFS_5_9) + gen_c(path, prefix, TCH_AFS_5_15) + gen_c(path, prefix, TCH_AFS_4_75) + print >>sys.stderr, "\tdone." -- 2.8.1 From msuraev at sysmocom.de Fri Apr 22 17:28:09 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 22 Apr 2016 19:28:09 +0200 Subject: [PATCH] Add function for appending range1024 to bitvec Message-ID: <1461346089-9218-1-git-send-email-msuraev@sysmocom.de> From: Max Add convenience function to append range1024 encoded data (see 3GPP TS 44.018 Annex J) to a given bitvec. --- include/Makefile.am | 1 + include/osmocom/gsm/bitvec_gsm.h | 13 +++++++++++++ src/gsm/gsm_utils.c | 36 ++++++++++++++++++++++++++++++++++++ src/gsm/libosmogsm.map | 2 +- 4 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 include/osmocom/gsm/bitvec_gsm.h diff --git a/include/Makefile.am b/include/Makefile.am index 0e5ed74..86aaf72 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -57,6 +57,7 @@ nobase_include_HEADERS = \ osmocom/gsm/apn.h \ osmocom/gsm/comp128.h \ osmocom/gsm/comp128v23.h \ + osmocom/gsm/bitvec_gsm.h \ osmocom/gsm/gan.h \ osmocom/gsm/gsm0341.h \ osmocom/gsm/gsm0411_smc.h \ diff --git a/include/osmocom/gsm/bitvec_gsm.h b/include/osmocom/gsm/bitvec_gsm.h new file mode 100644 index 0000000..20741ef --- /dev/null +++ b/include/osmocom/gsm/bitvec_gsm.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +/*! \defgroup bitvec helpers for GSM + * @{ + */ +/*! \file bitvec_gsm.h */ + +void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r); + +/*! @} */ diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c index e8e452f..5002947 100644 --- a/src/gsm/gsm_utils.c +++ b/src/gsm/gsm_utils.c @@ -64,7 +64,9 @@ //#include #include +#include #include +#include #include #include @@ -655,6 +657,40 @@ uint32_t gsm_gsmtime2fn(struct gsm_time *time) return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1)); } +/*! \brief append range1024 encoded data to bit vector */ +void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r) +{ + bitvec_set_uint(bv, r->w1_hi, 2); + bitvec_set_uint(bv, r->w1_lo, 8); + bitvec_set_uint(bv, r->w2_hi, 8); + bitvec_set_uint(bv, r->w2_lo, 1); + bitvec_set_uint(bv, r->w3_hi, 7); + bitvec_set_uint(bv, r->w3_lo, 2); + bitvec_set_uint(bv, r->w4_hi, 6); + bitvec_set_uint(bv, r->w4_lo, 2); + bitvec_set_uint(bv, r->w5_hi, 6); + bitvec_set_uint(bv, r->w5_lo, 2); + bitvec_set_uint(bv, r->w6_hi, 6); + bitvec_set_uint(bv, r->w6_lo, 2); + bitvec_set_uint(bv, r->w7_hi, 6); + bitvec_set_uint(bv, r->w7_lo, 2); + bitvec_set_uint(bv, r->w8_hi, 6); + bitvec_set_uint(bv, r->w8_lo, 1); + bitvec_set_uint(bv, r->w9, 7); + bitvec_set_uint(bv, r->w10, 7); + bitvec_set_uint(bv, r->w11_hi, 1); + bitvec_set_uint(bv, r->w11_lo, 6); + bitvec_set_uint(bv, r->w12_hi, 2); + bitvec_set_uint(bv, r->w12_lo, 5); + bitvec_set_uint(bv, r->w13_hi, 3); + bitvec_set_uint(bv, r->w13_lo, 4); + bitvec_set_uint(bv, r->w14_hi, 4); + bitvec_set_uint(bv, r->w14_lo, 3); + bitvec_set_uint(bv, r->w15_hi, 5); + bitvec_set_uint(bv, r->w15_lo, 2); + bitvec_set_uint(bv, r->w16, 6); +} + /* TS 23.003 Chapter 2.6 */ int gprs_tlli_type(uint32_t tlli) { diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index a526756..f9a8369 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -25,7 +25,7 @@ abis_nm_osmo_magic; abis_nm_ipa_magic; osmo_sitype_strs; - +bitvec_add_range1024; comp128; dbm2rxlev; -- 2.8.1 From nhofmeyr at sysmocom.de Sat Apr 23 10:55:44 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Sat, 23 Apr 2016 12:55:44 +0200 Subject: greetings from the OsmoDevCon 2016 Message-ID: <20160423105544.GA4440@dub6> Greetings to everyone who can't be in Berlin these days! The third day of the OsmoDevCon 2016 is on. So far we have heard inspiring talks [1], had a chance to socialize in person, and hacked on using the Osmocom 3G stack in-the-making with a low-cost Iuh capable femto cell, among other things; usually gathering at 10 a.m., some of us are seen on-location at IN-Berlin's premises [2] up to midnight. We've just heard the introduction on Globalstar satellite telephony, and are heading into lunch break any minute now. Let me share the quotes of the day! the context being documentation charts and white-on-black terminals, the quotes as such do provide a surprisingly accurate description of the preferred dress code of one of our most prominent members: I hate colors. -- Harald Welte, 2016-04-23, 11:31 a.m. I always find white extremely disturbing. -- Harald Welte, 2016-04-23, 11:38 a.m. All the best from IN-Berlin and OsmoDevCon 2016! ~Neels [1] http://projects.osmocom.org/projects/openbsc/wiki/OsmoDevCon2016 [2] http://in-berlin.de/ -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From msuraev at sysmocom.de Sat Apr 23 15:59:29 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Sat, 23 Apr 2016 17:59:29 +0200 Subject: [PATCH] Fix unaligned access found by addr. sanitizer Message-ID: <1461427169-25465-1-git-send-email-msuraev@sysmocom.de> From: Max --- src/gb/gprs_bssgp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gb/gprs_bssgp.c b/src/gb/gprs_bssgp.c index d9d8ccd..8a6d2a1 100644 --- a/src/gb/gprs_bssgp.c +++ b/src/gb/gprs_bssgp.c @@ -416,7 +416,7 @@ static int bssgp_rx_suspend(struct msgb *msg, struct tlv_parsed *tp) return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } - tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI)); + tlli = tlvp_val32_unal(tp, BSSGP_IE_TLLI); DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=0x%08x Rx SUSPEND\n", ns_bvci, tlli); -- 2.8.1 From msuraev at sysmocom.de Sat Apr 23 16:00:18 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Sat, 23 Apr 2016 18:00:18 +0200 Subject: [PATCH] Add missing include Message-ID: <1461427218-25696-1-git-send-email-msuraev@sysmocom.de> From: Max --- openbsc/src/libbsc/rest_octets.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index b59430b..aa286e5 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include -- 2.8.1 From holger at freyther.de Sat Apr 23 16:09:54 2016 From: holger at freyther.de (Holger Freyther) Date: Sat, 23 Apr 2016 18:09:54 +0200 Subject: [PATCH] Fix unaligned access found by addr. sanitizer In-Reply-To: <1461427169-25465-1-git-send-email-msuraev@sysmocom.de> References: <1461427169-25465-1-git-send-email-msuraev@sysmocom.de> Message-ID: <3B1D2A1B-6FCF-4882-B10F-11104C1B9F59@freyther.de> Hi, please add the ubsan output to the commit message to show which kind of issue has been fixed, please fix the other GPRS issue as well. holger From alexander.chemeris at gmail.com Sat Apr 23 16:35:42 2016 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sat, 23 Apr 2016 18:35:42 +0200 Subject: osmo-combo build script Message-ID: Hi all, There has been a few questions recently about building OpenBSC/OsmoBTS, especially for SDR devices, so I decided to share a link to a "make world" style build script which may help newcomers to get started. The script was hacked together by Sergey Kostanbaev to build static binaries and was not meant for wide use, so it have rough edges and may not work for every setup, but I hope it'll be useful for someone. Check out this git repository for the source code and brief documentation: https://github.com/fairwaves/osmo-combo -- Regards, Alexander Chemeris. CEO, Fairwaves, Inc. https://fairwaves.co From msuraev at sysmocom.de Sat Apr 23 17:37:58 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Sat, 23 Apr 2016 19:37:58 +0200 Subject: [PATCH] Fix unaligned access found by addr. sanitizer Message-ID: <1461433078-6799-1-git-send-email-msuraev@sysmocom.de> From: Max gprs_bssgp.c:461:9: runtime error: load of misaligned address 0x62100001a66b for type 'uint32_t', which requires 4 byte alignment gprs_ns.c:937:16: runtime error: load of misaligned address 0x61d00002a97f for type 'uint16_t', which requires 2 byte alignment --- src/gb/gprs_bssgp.c | 4 ++-- src/gb/gprs_ns.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gb/gprs_bssgp.c b/src/gb/gprs_bssgp.c index d9d8ccd..3ad2f29 100644 --- a/src/gb/gprs_bssgp.c +++ b/src/gb/gprs_bssgp.c @@ -416,7 +416,7 @@ static int bssgp_rx_suspend(struct msgb *msg, struct tlv_parsed *tp) return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } - tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI)); + tlli = ntohl(tlvp_val32_unal(tp, BSSGP_IE_TLLI)); DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=0x%08x Rx SUSPEND\n", ns_bvci, tlli); @@ -458,7 +458,7 @@ static int bssgp_rx_resume(struct msgb *msg, struct tlv_parsed *tp) return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } - tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI)); + tlli = ntohl(tlvp_val32_unal(tp, BSSGP_IE_TLLI)); suspend_ref = *TLVP_VAL(tp, BSSGP_IE_SUSPEND_REF_NR); DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=0x%08x Rx RESUME\n", ns_bvci, tlli); diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index a29c946..6879c70 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -934,8 +934,8 @@ static int gprs_ns_rx_reset_ack(struct gprs_nsvc **nsvc, 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)); + nsvci = ntohs(tlvp_val16_unal(&tp, NS_IE_VCI)); + nsei = ntohs(tlvp_val16_unal(&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)", -- 2.8.1 From 246tnt at gmail.com Sat Apr 23 18:13:01 2016 From: 246tnt at gmail.com (Sylvain Munaut) Date: Sat, 23 Apr 2016 20:13:01 +0200 Subject: [PATCH 1/4] Add code generator for convolutional codes In-Reply-To: References: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: Hi >> + self.block_len = block_len >> + self.k = k >> + self.n = n >> + self.puncture = puncture >> + self.rate_inv = len(polys) > > tabs vs. spaces? Yeah, indeed. I have other things I'd fix up too. Looking at them now, I'll resend max an updated utility Cheers, Sylvain From holger at freyther.de Sun Apr 24 09:40:13 2016 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 24 Apr 2016 11:40:13 +0200 Subject: [PATCH] milenage/aes: Address undefined behavior on bitshift Message-ID: <1461490813-5032-1-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther Extend the u8 to u32 before going to shift it. Fixes: milenage/aes-internal.c:799:4: runtime error: left shift of 128 by 24 places cannot be represented in type 'int' #0 0x7f84e9fe86a2 in rijndaelKeySetupEnc (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xfa6a2) #1 0x7f84e9febad8 in aes_encrypt_init (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xfdad8) #2 0x7f84e9fe7d14 in aes_128_encrypt_block (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xf9d14) #3 0x7f84e9febe7d in milenage_f1 (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xfde7d) #4 0x7f84e9fee2ce in milenage_generate (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0x1002ce) #5 0x7f84e9fe76d7 in milenage_gen_vec (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xf96d7) #6 0x7f84e9fe6c08 in osmo_auth_gen_vec (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xf8c08) #7 0x401441 in main (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/tests/auth/.libs/lt-milenage_test+0x401441) #8 0x7f84e8e33a3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x20a3f) #9 0x400e58 in _start (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/tests/auth/.libs/lt-milenage_test+0x400e58) --- src/gsm/milenage/aes_i.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gsm/milenage/aes_i.h b/src/gsm/milenage/aes_i.h index c831757..5d89abc 100644 --- a/src/gsm/milenage/aes_i.h +++ b/src/gsm/milenage/aes_i.h @@ -66,7 +66,7 @@ extern const u8 rcons[10]; #else /* AES_SMALL_TABLES */ -#define RCON(i) (rcons[(i)] << 24) +#define RCON(i) ((u32)rcons[(i)] << 24) static inline u32 rotr(u32 val, int bits) { -- 2.6.3 From msuraev at sysmocom.de Sun Apr 24 09:46:12 2016 From: msuraev at sysmocom.de (Max) Date: Sun, 24 Apr 2016 11:46:12 +0200 Subject: [PATCH] milenage/aes: Address undefined behavior on bitshift In-Reply-To: <1461490813-5032-1-git-send-email-holger@freyther.de> References: <1461490813-5032-1-git-send-email-holger@freyther.de> Message-ID: <571C95E4.90605@sysmocom.de> I would feel more comfortable to just link (optionally) to external crypto library which is actively maintained (nettle? libgcrypt?) rather than fixing copy-pasted code. On 04/24/2016 11:40 AM, Holger Hans Peter Freyther wrote: > From: Holger Hans Peter Freyther > > Extend the u8 to u32 before going to shift it. > > Fixes: > milenage/aes-internal.c:799:4: runtime error: left shift of 128 by 24 places cannot be represented in type 'int' > #0 0x7f84e9fe86a2 in rijndaelKeySetupEnc (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xfa6a2) > #1 0x7f84e9febad8 in aes_encrypt_init (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xfdad8) > #2 0x7f84e9fe7d14 in aes_128_encrypt_block (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xf9d14) > #3 0x7f84e9febe7d in milenage_f1 (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xfde7d) > #4 0x7f84e9fee2ce in milenage_generate (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0x1002ce) > #5 0x7f84e9fe76d7 in milenage_gen_vec (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xf96d7) > #6 0x7f84e9fe6c08 in osmo_auth_gen_vec (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/src/gsm/.libs/libosmogsm.so.5+0xf8c08) > #7 0x401441 in main (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/tests/auth/.libs/lt-milenage_test+0x401441) > #8 0x7f84e8e33a3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x20a3f) > #9 0x400e58 in _start (/home/builder/jenkins/workspace/Osmocom_Sanitizer/source/libosmocore/tests/auth/.libs/lt-milenage_test+0x400e58) > --- > src/gsm/milenage/aes_i.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/src/gsm/milenage/aes_i.h b/src/gsm/milenage/aes_i.h > index c831757..5d89abc 100644 > --- a/src/gsm/milenage/aes_i.h > +++ b/src/gsm/milenage/aes_i.h > @@ -66,7 +66,7 @@ extern const u8 rcons[10]; > > #else /* AES_SMALL_TABLES */ > > -#define RCON(i) (rcons[(i)] << 24) > +#define RCON(i) ((u32)rcons[(i)] << 24) > > static inline u32 rotr(u32 val, int bits) > { -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Sun Apr 24 09:53:26 2016 From: msuraev at sysmocom.de (Max) Date: Sun, 24 Apr 2016 11:53:26 +0200 Subject: [PATCH 1/4] Add code generator for convolutional codes In-Reply-To: References: <1461011051-11657-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: <571C9796.7030105@sysmocom.de> Please make sure to use latest version from max/conv2 branch as a basis. Also, feel free to submit patch directly to list - there's no particular reason why I should be committer for this patch :) On 04/23/2016 08:13 PM, Sylvain Munaut wrote: > Hi > >>> + self.block_len = block_len >>> + self.k = k >>> + self.n = n >>> + self.puncture = puncture >>> + self.rate_inv = len(polys) >> tabs vs. spaces? > Yeah, indeed. > > I have other things I'd fix up too. > Looking at them now, I'll resend max an updated utility > > Cheers, > > Sylvain -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From msuraev at sysmocom.de Sun Apr 24 10:01:03 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Sun, 24 Apr 2016 12:01:03 +0200 Subject: [PATCH] Add static lib to -dev .deb package Message-ID: <1461492063-5336-1-git-send-email-msuraev@sysmocom.de> From: Max According to https://www.debian.org/doc/debian-policy/ch-sharedlibs.html and http://packaging.ubuntu.com/html/libraries.html that's where it belongs. --- debian/libosmocore-dev.install | 1 + debian/rules | 3 +++ 2 files changed, 4 insertions(+) diff --git a/debian/libosmocore-dev.install b/debian/libosmocore-dev.install index 7a62c6f..7c5a789 100644 --- a/debian/libosmocore-dev.install +++ b/debian/libosmocore-dev.install @@ -1,4 +1,5 @@ usr/include/* +usr/lib/*/lib*.a usr/lib/*/lib*.so usr/lib/*/lib*.la usr/lib/*/pkgconfig/* diff --git a/debian/rules b/debian/rules index a6a2cfc..3cce05e 100755 --- a/debian/rules +++ b/debian/rules @@ -35,3 +35,6 @@ override_dh_auto_test: override_dh_autoreconf: echo $(VERSION) > .tarball-version dh_autoreconf + +override_dh_auto_configure: + dh_auto_configure -- --enable-static -- 2.8.1 From msuraev at sysmocom.de Sun Apr 24 12:17:42 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Sun, 24 Apr 2016 14:17:42 +0200 Subject: [PATCH] Merge packaging changes from Debian Message-ID: <1461500262-16861-1-git-send-email-msuraev@sysmocom.de> From: Max This helps to get diff between upstream and distro significantly smaller. It also significantly reduces the number of warnings+errors reported by lintian from 42 to only 8. --- debian/control | 234 ++++++++++++++++++++++++++--- debian/copyright | 237 +++++++++++++++++++++++++----- debian/libosmocodec-doc.doc-base | 7 + debian/libosmocodec-doc.install | 1 + debian/libosmocodec-doc.lintian-overrides | 2 + debian/libosmocore-dev.install | 1 - debian/libosmocore-doc.doc-base | 7 + debian/libosmocore-doc.install | 1 + debian/libosmocore-doc.lintian-overrides | 2 + debian/libosmocore-utils.manpages | 1 + debian/libosmogsm-doc.doc-base | 7 + debian/libosmogsm-doc.install | 1 + debian/libosmogsm-doc.lintian-overrides | 2 + debian/libosmovty-doc.doc-base | 7 + debian/libosmovty-doc.install | 1 + debian/libosmovty-doc.lintian-overrides | 2 + debian/rules | 28 ++++ debian/watch | 2 + 18 files changed, 483 insertions(+), 60 deletions(-) create mode 100644 debian/libosmocodec-doc.doc-base create mode 100644 debian/libosmocodec-doc.install create mode 100644 debian/libosmocodec-doc.lintian-overrides create mode 100644 debian/libosmocore-doc.doc-base create mode 100644 debian/libosmocore-doc.install create mode 100644 debian/libosmocore-doc.lintian-overrides create mode 100644 debian/libosmocore-utils.manpages create mode 100644 debian/libosmogsm-doc.doc-base create mode 100644 debian/libosmogsm-doc.install create mode 100644 debian/libosmogsm-doc.lintian-overrides create mode 100644 debian/libosmovty-doc.doc-base create mode 100644 debian/libosmovty-doc.install create mode 100644 debian/libosmovty-doc.lintian-overrides create mode 100644 debian/watch diff --git a/debian/control b/debian/control index 459030b..f7138b5 100644 --- a/debian/control +++ b/debian/control @@ -1,86 +1,282 @@ Source: libosmocore +Maintainer: Harald Welte +Uploaders: Ruben Undheim Section: libs Priority: optional -Maintainer: Harald Welte -Build-Depends: debhelper (>= 9), autotools-dev, autoconf, automake, libtool, dh-autoreconf, libdpkg-perl, git, doxygen, libpcsclite-dev, pkg-config, libtalloc-dev -Standards-Version: 3.9.6 -Homepage: http://bb.osmocom.org/trac/wiki/libosmocore +Build-Depends: debhelper (>= 9), + autotools-dev, + dh-autoreconf, + doxygen, + txt2man, + libpcsclite-dev, + pkg-config, + autoconf, + automake, + libtool, + libdpkg-perl, + git, + libtalloc-dev +Standards-Version: 3.9.7 Vcs-Git: git://git.osmocom.org/libosmocore.git Vcs-Browser: http://git.osmocom.org/gitweb?p=libosmocore.git;a=summary +Homepage: http://bb.osmocom.org/trac/wiki/libosmocore Package: libosmocore Section: libs Architecture: any -Depends: libosmocodec0, libosmocore7, libosmogb4, libosmogsm5, libosmovty3, libosmoctrl0, ${misc:Depends} -Multi-Arch: foreign -Description: Open Source MObile COMmunications CORE library +Multi-Arch: same +Depends: libosmocodec0 (= ${binary:Version}), + libosmocore6 (= ${binary:Version}), + libosmogb4 (= ${binary:Version}), + libosmogsm5 (= ${binary:Version}), + libosmovty3 (= ${binary:Version}), + libosmoctrl0 (= ${binary:Version}), + libosmosim0 (= ${binary:Version}), + ${misc:Depends} +Description: Open Source MObile COMmunications CORE library (metapackage) + The libraries provided by this package contain various utility functions. + These were originally developed as part of the + OpenBSC project but are of a more generic nature and thus useful to (at + least) other programs that are developed in the sphere of Free Software / Open + Source mobile communication. Package: libosmocodec0 Section: libs Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} Multi-Arch: same +Depends: ${shlibs:Depends}, + ${misc:Depends} +Pre-Depends: ${misc:Pre-Depends} Description: Osmo codec library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + The libosmocodec library in particular contains the implementation of multiple + GSM codecs: + . + - GSM 06.10 - GSM FR Codec + - GSM 06.20 - GSM HR Codec + - GSM 06.60 - GSM EFR Codec + - GSM 06.90 - GSM AMR Codec + +Package: libosmocodec-doc +Architecture: all +Section: doc +Depends: ${misc:Depends}, + libosmocodec0, + libjs-jquery +Description: Documentation for the osmo codec library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + This package contains the documentation for the libosmocodec library. Package: libosmocore7 Section: libs Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} Multi-Arch: same +Depends: ${shlibs:Depends}, + ${misc:Depends} +Pre-Depends: ${misc:Pre-Depends} Description: Osmo Core library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + The libosmocore6 library in particular is a collection of common code used in + various sub-projects inside the Osmocom family of projects. + +Package: libosmocore-doc +Architecture: all +Section: doc +Depends: ${misc:Depends}, + libosmocore6, + libjs-jquery, + libosmocodec-doc, + libosmogsm-doc, + libosmovty-doc +Description: Documentation for the Osmo Core library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + This package contains the documentation for the libosmocore library. Package: libosmogb4 Section: libs Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} Multi-Arch: same +Depends: ${shlibs:Depends}, + ${misc:Depends} +Pre-Depends: ${misc:Pre-Depends} Description: Osmo GPRS GB library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + The libosmogb library in particular contains a GPRS BSSGP protocol + implementation. Package: libosmogsm5 Section: libs Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} Multi-Arch: same +Depends: ${shlibs:Depends}, + ${misc:Depends} +Pre-Depends: ${misc:Pre-Depends} Description: Osmo GSM utility library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + The libosmogsm library in particular is a collection of common code used in + various GSM related sub-projects inside the Osmocom family of projects. It + includes A5/1 and A5/2 ciphers, COMP128v1, a LAPDm implementation, a GSM TLV + parser, SMS utility routines as well as protocol definitions for a series of + protocols. + +Package: libosmogsm-doc +Architecture: all +Section: doc +Depends: ${misc:Depends}, + libosmogsm5, + libjs-jquery +Description: Documentation for the Osmo GSM utility library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + This package contains the documentation for the libosmogsm library. Package: libosmovty3 Section: libs Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} Multi-Arch: same +Depends: ${shlibs:Depends}, + ${misc:Depends} +Pre-Depends: ${misc:Pre-Depends} Description: Osmo VTY library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + The libosmovty library in particular implements the interactive command-line + on the VTY (Virtual TTY) as well as configuration file parsing. + +Package: libosmovty-doc +Architecture: all +Section: doc +Depends: ${misc:Depends}, + libosmovty3, + libjs-jquery +Description: Documentation for the Osmo VTY library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + This package contains the documentation for the libosmovty library. Package: libosmoctrl0 Section: libs Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} Multi-Arch: same +Depends: ${shlibs:Depends}, + ${misc:Depends} +Pre-Depends: ${misc:Pre-Depends} Description: Osmo control library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + The libosmoctrl library in particular contains an SNMP-like status interface. Package: libosmosim0 Section: libs Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} Multi-Arch: same +Depends: ${shlibs:Depends}, + ${misc:Depends} +Pre-Depends: ${misc:Pre-Depends} Description: Osmo SIM library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + The libosmosim library in particular contains routines for SIM card access. Package: libosmocore-dev -Section: libdevel Architecture: any -Depends: ${misc:Depends}, libosmocore, libtalloc-dev Multi-Arch: same +Section: libdevel +Depends: libosmocodec0 (= ${binary:Version}), + libosmocore7 (= ${binary:Version}), + libosmogb4 (= ${binary:Version}), + libosmogsm5 (= ${binary:Version}), + libosmovty3 (= ${binary:Version}), + libosmoctrl0 (= ${binary:Version}), + libosmosim0 (= ${binary:Version}), + ${misc:Depends}, + libtalloc-dev Description: Development headers for Open Source MObile COMmunications CORE library + The header files provided by this package may be used to develop + with any of the libosmocore libraries. + . + Also static libraries are installed with this package. Package: libosmocore-utils Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libosmocore Multi-Arch: same +Section: utils +Depends: ${shlibs:Depends}, + ${misc:Depends}, + libosmocore Description: Utilities for gsm + This package contains a program for frequency calculation for GSM called + 'osmo-arfcn' and a program called 'osmo-auc-gen' that is used for testing GSM + authentication. + . + They use the libosmocore library. The libosmocore library contain various + utility functions that were originally developed as part of the OpenBSC + project, but which are of a more generic nature and thus useful to (at least) + other programs that are developed in the sphere of Free Software / Open Source + mobile communication. Package: libosmocore-dbg Architecture: any +Multi-Arch: same Section: debug Priority: extra -Depends: libosmocore (= ${binary:Version}), ${misc:Depends} -Multi-Arch: same +Depends: libosmocore (= ${binary:Version}), + ${misc:Depends} Description: Debug symbols for Open Source MObile COMmunications CORE library + This proackage contains debug symbols for all the libraries that are part of + libosmocore. + . + The libosmocore library contain various utility functions that + were originally developed as part of the OpenBSC project, but which are of a + more generic nature and thus useful to (at least) other programs that are + developed in the sphere of Free Software / Open Source mobile communication. diff --git a/debian/copyright b/debian/copyright index c450be5..2991c85 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,54 +1,211 @@ -This work was packaged for Debian by: +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: libosmocore +Source: git://git.osmocom.org/libosmocore.git - Harald Welte on Tue, 24 Aug 2010 10:55:04 +0200 +Files: * +Copyright: 2008 Daniel Willmann + 2008-2010 Harald Welte + 2008-2010 Holger Hans Peter Freyther + 2009-2010 Sylvain Munaut + 2009-2010 On-Waves + 2010 Nico Golde +License: GPL-2+ -It was downloaded from: +Files: src/talloc.c include/osmocom/core/talloc.h +Copyright: 2004 Andrew Tridgell + 2006 Stefan Metzmacher +License: LGPL-3+ - git://git.osmocom.org/libosmocore.git +Files: include/osmocom/core/loggingrb.h + include/osmocom/core/strrb.h + src/strrb.c + src/loggingrb.c +Copyright: 2012-2013 Katerina Barone-Adesi +License: GPL-2+ -Upstream Author(s): +Files: include/osmocom/core/linuxrbtree.h + src/rbtree.c +Copyright: 1999 Andrea Arcangeli + 2002 David Woodhouse +License: GPL-2+ - Harald Welte - Holger Hans Peter Freyther - Sylvain Munaut - Daniel Willmann - Golde - For src/talloc.c and include/osmocore/talloc.h: - Andrew Tridgell - Stefan Metzmacher - For src/vty/* and include/osmocom/vty/* - Kunihiro Ishiguro +Files: include/osmocom/core/crc16.h +Copyright: 2005 Ben Gardner +License: GPL-2+ -Copyright: +Files: src/utils.c +Copyright: 2011 Harald Welte + 2011 Sylvain Munaut + 2014 Nils O. Sel?sdal +License: GPL-2+ - Copyright (C) 2008-2010 Harald Welte - Copyright (C) 2008-2010 Holger Hans Peter Freyther - Copyright (C) 2009-2010 Sylvain Munaut - Copyright (C) 2009-2010 On-Waves - Copyright (C) 2008 Daniel Willmann - Copyright (C) 2010 Nico Golde - For src/talloc.c and include/osmocore/talloc.h: - Copyright (C) 2004 Andrew Tridgell - Copyright (C) 2006 Stefan Metzmacher - For src/vty/* and include/osmocom/vty/* - Copyright (C) 1998 Kunihiro Ishiguro +Files: src/gsm/gsm48_ie.c + src/gsm/lapd_core.c + src/gsm/lapdm.c +Copyright: 2008,2010-2011 Harald Welte + 2009-2011 Andreas Eversberg +License: GPL-2+ -License: +Files: src/gsm/gsm0411_smc.c + src/gsm/gsm0411_smr.c + src/gsm/gsm0411_utils.c +Copyright: 2008 Daniel Willmann + 2009 Harald Welte + 2010-2013 Holger Hans Peter Freyther + 2010 On-Waves + 2011 Andreas Eversberg +License: GPL-2+ - GNU General Public License, Version 2 or later +Files: src/gsm/gsm0480.c +Copyright: 2009 Mike Haben + 2010 Holger Hans Peter Freyther +License: GPL-2+ -The Debian packaging is: +Files: src/gsm/milenage/aes-internal.c + src/gsm/milenage/aes-encblock.c + src/gsm/milenage/aes.h + src/gsm/milenage/milenage.c + src/gsm/milenage/aes_wrap.h + src/gsm/milenage/aes-internal-enc.c + src/gsm/milenage/aes_i.h +Copyright: 2003-2007 Jouni Malinen +License: GPL-2 +Comment: Most of the file aes-internal.c is public_domain - Copyright (C) 2010 Harald Welte +Files: include/osmocom/core/bitXXgen.h.tpl + src/gsm/kasumi.c +Copyright: 2013-2014 Max +License: GPL-2+ -# Please chose a license for your packaging work. If the program you package -# uses a mainstream license, using the same license is the safest choice. -# Please avoid to pick license terms that are more restrictive than the -# packaged work, as it may make Debian's contributions unacceptable upstream. -# If you just want it to be GPL version 3, leave the following lines in. +Files: src/gsm/auth_comp128v23.c +Copyright: 2010-2011 Harald Welte + 2013 K?vin Redon +License: GPL-2+ -and is licensed under the GPL version 3, -see "/usr/share/common-licenses/GPL-3". +Files: src/gsm/comp128v23.c +Copyright: 2013 K?vin Redon +License: GPL-2+ -# Please also look if there are files or directories which have a -# different copyright/license attached and list them here. +Files: tests/fr/fr_test.c + tests/logging/logging_test.c + tests/loggingrb/loggingrb_test.c +Copyright: 2008,2009,2012 Holger Hans Peter Freyther + 2012-2013 Katerina Barone-Adesi +License: AGPL-3+ + +Files: tests/strrb/strrb_test.c + tests/vty/vty_test.c +Copyright: 2012-2013 Katerina Barone-Adesi + 2013 Jacob Erlbeck +License: GPL-3+ + +Files: src/vty/* include/osmocom/vty/* +Copyright: 1997,1998 Kunihiro Ishiguro +License: GPL-2+ + +Files: include/osmocom/core/stats.h + src/stat_item.c + src/stats.c + src/vty/stats_vty.c + tests/stats/stats_test.c +Copyright: 2009-2010 by Harald Welte + 2009-2014 by Holger Hans Peter Freyther + 2015 Sysmocom s.f.m.c. GmbH +License: GPL-2+ + +Files: tests/gb/gprs_ns_test.c + tests/gb/gprs_bssgp_test.c +Copyright: 2013-2014 sysmocom s.f.m.c. GmbH +License: GPL-2+ +Comment: No license is listed in these files, but it is assumed that + the project specific license GPL-2+ applies since contributions by + sysmocom people to other files in this package are GPL licensed. + +Files: debian/* +Copyright: 2010-2015 Harald Welte + 2014-2015 Ruben Undheim +License: GPL-3+ + + +License: GPL-2+ + This package is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 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 General Public License + along with this program. If not, see . + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + +License: GPL-2 + This package is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2 of the License. + . + 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 General Public License + along with this program. If not, see . + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + +License: GPL-3+ + This package is free software: you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License + along with this program. If not, see . + . + On Debian systems, the complete text of the GNU General + Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". + + +License: LGPL-3+ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + . + This library 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 + Lesser General Public License for more details. + . + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . + . + On Debian systems, the complete text of the GNU Lesser General + Public License version 3 can be found in "/usr/share/common-licenses/LGPL-3". + + +License: AGPL-3+ + 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 . diff --git a/debian/libosmocodec-doc.doc-base b/debian/libosmocodec-doc.doc-base new file mode 100644 index 0000000..8480c73 --- /dev/null +++ b/debian/libosmocodec-doc.doc-base @@ -0,0 +1,7 @@ +Document: libosmocodec-doc +Title: Documentation for the libosmocodec library +Section: Programming + +Format: HTML +Index: /usr/share/doc/libosmocore/codec/html/index.html +Files: /usr/share/doc/libosmocore/codec/html/*.html diff --git a/debian/libosmocodec-doc.install b/debian/libosmocodec-doc.install new file mode 100644 index 0000000..be0255b --- /dev/null +++ b/debian/libosmocodec-doc.install @@ -0,0 +1 @@ +usr/share/doc/libosmocore/codec/ diff --git a/debian/libosmocodec-doc.lintian-overrides b/debian/libosmocodec-doc.lintian-overrides new file mode 100644 index 0000000..526d4f9 --- /dev/null +++ b/debian/libosmocodec-doc.lintian-overrides @@ -0,0 +1,2 @@ +# jquery.js is generated by doxygen. See http://bugs.debian.org/736360 +libosmocodec-doc binary: embedded-javascript-library usr/share/doc/libosmocore/codec/html/jquery.js please use libjs-jquery diff --git a/debian/libosmocore-dev.install b/debian/libosmocore-dev.install index 7c5a789..465f933 100644 --- a/debian/libosmocore-dev.install +++ b/debian/libosmocore-dev.install @@ -3,4 +3,3 @@ usr/lib/*/lib*.a usr/lib/*/lib*.so usr/lib/*/lib*.la usr/lib/*/pkgconfig/* -usr/share/doc/libosmocore/* diff --git a/debian/libosmocore-doc.doc-base b/debian/libosmocore-doc.doc-base new file mode 100644 index 0000000..b13b82d --- /dev/null +++ b/debian/libosmocore-doc.doc-base @@ -0,0 +1,7 @@ +Document: libosmocore-doc +Title: Documentation for the libosmocore library +Section: Programming + +Format: HTML +Index: /usr/share/doc/libosmocore/core/html/index.html +Files: /usr/share/doc/libosmocore/core/html/*.html diff --git a/debian/libosmocore-doc.install b/debian/libosmocore-doc.install new file mode 100644 index 0000000..fe4cb26 --- /dev/null +++ b/debian/libosmocore-doc.install @@ -0,0 +1 @@ +usr/share/doc/libosmocore/core/ diff --git a/debian/libosmocore-doc.lintian-overrides b/debian/libosmocore-doc.lintian-overrides new file mode 100644 index 0000000..345e48d --- /dev/null +++ b/debian/libosmocore-doc.lintian-overrides @@ -0,0 +1,2 @@ +# jquery.js is generated by doxygen. See http://bugs.debian.org/736360 +libosmocore-doc binary: embedded-javascript-library usr/share/doc/libosmocore/core/html/jquery.js please use libjs-jquery diff --git a/debian/libosmocore-utils.manpages b/debian/libosmocore-utils.manpages new file mode 100644 index 0000000..13cdaf4 --- /dev/null +++ b/debian/libosmocore-utils.manpages @@ -0,0 +1 @@ +debian/man/*.1 diff --git a/debian/libosmogsm-doc.doc-base b/debian/libosmogsm-doc.doc-base new file mode 100644 index 0000000..6318c1d --- /dev/null +++ b/debian/libosmogsm-doc.doc-base @@ -0,0 +1,7 @@ +Document: libosmogsm-doc +Title: Documentation for the libosmogsm library +Section: Programming + +Format: HTML +Index: /usr/share/doc/libosmocore/gsm/html/index.html +Files: /usr/share/doc/libosmocore/gsm/html/*.html diff --git a/debian/libosmogsm-doc.install b/debian/libosmogsm-doc.install new file mode 100644 index 0000000..a4300bc --- /dev/null +++ b/debian/libosmogsm-doc.install @@ -0,0 +1 @@ +usr/share/doc/libosmocore/gsm/ diff --git a/debian/libosmogsm-doc.lintian-overrides b/debian/libosmogsm-doc.lintian-overrides new file mode 100644 index 0000000..2db0404 --- /dev/null +++ b/debian/libosmogsm-doc.lintian-overrides @@ -0,0 +1,2 @@ +# jquery.js is generated by doxygen. See http://bugs.debian.org/736360 +libosmogsm-doc binary: embedded-javascript-library usr/share/doc/libosmocore/gsm/html/jquery.js please use libjs-jquery diff --git a/debian/libosmovty-doc.doc-base b/debian/libosmovty-doc.doc-base new file mode 100644 index 0000000..dde189c --- /dev/null +++ b/debian/libosmovty-doc.doc-base @@ -0,0 +1,7 @@ +Document: libosmovty-doc +Title: Documentation for the libosmovty library +Section: Programming + +Format: HTML +Index: /usr/share/doc/libosmocore/vty/html/index.html +Files: /usr/share/doc/libosmocore/vty/html/*.html diff --git a/debian/libosmovty-doc.install b/debian/libosmovty-doc.install new file mode 100644 index 0000000..634ba41 --- /dev/null +++ b/debian/libosmovty-doc.install @@ -0,0 +1 @@ +usr/share/doc/libosmocore/vty/ diff --git a/debian/libosmovty-doc.lintian-overrides b/debian/libosmovty-doc.lintian-overrides new file mode 100644 index 0000000..c10975e --- /dev/null +++ b/debian/libosmovty-doc.lintian-overrides @@ -0,0 +1,2 @@ +# jquery.js is generated by doxygen. See http://bugs.debian.org/736360 +libosmovty-doc binary: embedded-javascript-library usr/share/doc/libosmocore/vty/html/jquery.js please use libjs-jquery diff --git a/debian/rules b/debian/rules index 3cce05e..42222b2 100755 --- a/debian/rules +++ b/debian/rules @@ -12,6 +12,10 @@ DEBIAN := $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2) DEBVERS := $(shell echo '$(DEBIAN)' | cut -d- -f1) VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/[+-].*//' -e 's/~//g') +CHANGELOG_DATE := $(shell LC_ALL=C date -u -d "`dpkg-parsechangelog --show-field Date`" +"%d %B %Y") + +export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed +export DEB_BUILD_MAINT_OPTIONS = hardening=+all # Our tests want to override symbols, make it possible on Ubuntu export LDFLAGS := $(shell dpkg-buildflags --get LDFLAGS | sed -e 's/-Wl,-Bsymbolic-functions//') @@ -38,3 +42,27 @@ override_dh_autoreconf: override_dh_auto_configure: dh_auto_configure -- --enable-static + +override_dh_clean: + dh_clean + $(RM) .version + $(RM) debian/man/osmo-arfcn.1 + $(RM) debian/man/osmo-auc-gen.1 + $(RM) include/osmocom/core/bit16gen.h + $(RM) include/osmocom/core/bit32gen.h + $(RM) include/osmocom/core/bit64gen.h + $(RM) include/osmocom/core/crc16gen.h + $(RM) include/osmocom/core/crc32gen.h + $(RM) include/osmocom/core/crc64gen.h + $(RM) include/osmocom/core/crc8gen.h + $(RM) src/crc16gen.c + $(RM) src/crc32gen.c + $(RM) src/crc64gen.c + $(RM) src/crc8gen.c + $(RM) tests/package.m4 + $(RM) tests/testsuite + $(RM) -r doc/codec/ + $(RM) -r doc/core/ + $(RM) -r doc/gsm/ + $(RM) -r doc/vty/html/ + $(RM) -r doc/vty/latex/ diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..efce4b8 --- /dev/null +++ b/debian/watch @@ -0,0 +1,2 @@ +version=3 +https://github.com/osmocom/libosmocore/releases /osmocom/libosmocore/archive/(\d\S+)\.tar\.(?:bz2|gz|xz) -- 2.8.1 From 246tnt at gmail.com Sun Apr 24 13:05:45 2016 From: 246tnt at gmail.com (Sylvain Munaut) Date: Sun, 24 Apr 2016 15:05:45 +0200 Subject: [PATCH 2/2] Doxygen: enable tagfile generation and usage for cross-project references In-Reply-To: <1461503145-1127-1-git-send-email-246tnt@gmail.com> References: <1461503145-1127-1-git-send-email-246tnt@gmail.com> Message-ID: <1461503145-1127-2-git-send-email-246tnt@gmail.com> From: Sylvain Munaut Signed-off-by: Sylvain Munaut --- Doxyfile.codec.in | 4 ++-- Doxyfile.core.in | 2 +- Doxyfile.gsm.in | 4 ++-- Doxyfile.vty.in | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doxyfile.codec.in b/Doxyfile.codec.in index 00ab43a..8435379 100644 --- a/Doxyfile.codec.in +++ b/Doxyfile.codec.in @@ -1485,12 +1485,12 @@ SKIP_FUNCTION_MACROS = YES # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. -TAGFILES = +TAGFILES = doc/libosmocore.tag=../../core/html # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. -GENERATE_TAGFILE = +GENERATE_TAGFILE = doc/libosmocodec.tag # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes diff --git a/Doxyfile.core.in b/Doxyfile.core.in index 045402f..58d35be 100644 --- a/Doxyfile.core.in +++ b/Doxyfile.core.in @@ -1490,7 +1490,7 @@ TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. -GENERATE_TAGFILE = +GENERATE_TAGFILE = doc/libosmocore.tag # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes diff --git a/Doxyfile.gsm.in b/Doxyfile.gsm.in index 76c8f81..ed4ff47 100644 --- a/Doxyfile.gsm.in +++ b/Doxyfile.gsm.in @@ -1485,12 +1485,12 @@ SKIP_FUNCTION_MACROS = YES # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. -TAGFILES = +TAGFILES = doc/libosmocore.tag=../../core/html # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. -GENERATE_TAGFILE = +GENERATE_TAGFILE = doc/libosmogsm.tag # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes diff --git a/Doxyfile.vty.in b/Doxyfile.vty.in index 2763823..073ee0c 100644 --- a/Doxyfile.vty.in +++ b/Doxyfile.vty.in @@ -1485,12 +1485,12 @@ SKIP_FUNCTION_MACROS = YES # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. -TAGFILES = +TAGFILES = doc/libosmocore.tag=../../core/html # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. -GENERATE_TAGFILE = +GENERATE_TAGFILE = doc/libosmovty.tag # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes -- 2.7.3 From 246tnt at gmail.com Sun Apr 24 13:05:44 2016 From: 246tnt at gmail.com (Sylvain Munaut) Date: Sun, 24 Apr 2016 15:05:44 +0200 Subject: [PATCH 1/2] Doxygen: Enable client-based search engine Message-ID: <1461503145-1127-1-git-send-email-246tnt@gmail.com> From: Sylvain Munaut Signed-off-by: Sylvain Munaut --- Doxyfile.codec.in | 2 +- Doxyfile.core.in | 2 +- Doxyfile.gsm.in | 2 +- Doxyfile.vty.in | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doxyfile.codec.in b/Doxyfile.codec.in index 4f539c7..00ab43a 100644 --- a/Doxyfile.codec.in +++ b/Doxyfile.codec.in @@ -1141,7 +1141,7 @@ MATHJAX_RELPATH = http://www.mathjax.org/mathjax # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -SEARCHENGINE = NO +SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client diff --git a/Doxyfile.core.in b/Doxyfile.core.in index 71843cc..045402f 100644 --- a/Doxyfile.core.in +++ b/Doxyfile.core.in @@ -1141,7 +1141,7 @@ MATHJAX_RELPATH = http://www.mathjax.org/mathjax # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -SEARCHENGINE = NO +SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client diff --git a/Doxyfile.gsm.in b/Doxyfile.gsm.in index c4a837f..76c8f81 100644 --- a/Doxyfile.gsm.in +++ b/Doxyfile.gsm.in @@ -1141,7 +1141,7 @@ MATHJAX_RELPATH = http://www.mathjax.org/mathjax # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -SEARCHENGINE = NO +SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client diff --git a/Doxyfile.vty.in b/Doxyfile.vty.in index 5f7a158..2763823 100644 --- a/Doxyfile.vty.in +++ b/Doxyfile.vty.in @@ -1141,7 +1141,7 @@ MATHJAX_RELPATH = http://www.mathjax.org/mathjax # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -SEARCHENGINE = NO +SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client -- 2.7.3 From holger at freyther.de Sun Apr 24 13:29:12 2016 From: holger at freyther.de (Holger Freyther) Date: Sun, 24 Apr 2016 15:29:12 +0200 Subject: [PATCH] Merge packaging changes from Debian In-Reply-To: <1461500262-16861-1-git-send-email-msuraev@sysmocom.de> References: <1461500262-16861-1-git-send-email-msuraev@sysmocom.de> Message-ID: <07250FFC-45DE-47B0-8932-AAFFAD1D2799@freyther.de> > On 24 Apr 2016, at 14:17, msuraev at sysmocom.de wrote: > > +Files: src/gsm/milenage/aes-internal.c > + src/gsm/milenage/aes-encblock.c > + src/gsm/milenage/aes.h > + src/gsm/milenage/milenage.c > + src/gsm/milenage/aes_wrap.h > + src/gsm/milenage/aes-internal-enc.c > + src/gsm/milenage/aes_i.h > +Copyright: 2003-2007 Jouni Malinen > +License: GPL-2 this is dual licensed, hostapd upstream has removed GPLv2 and for AGPLv3+ compatibility of osmo-nitb or such this code needs to be used under the "BSD" (double check the actual license term) license. holger From msuraev at sysmocom.de Sun Apr 24 13:47:04 2016 From: msuraev at sysmocom.de (Max) Date: Sun, 24 Apr 2016 15:47:04 +0200 Subject: [PATCH] Merge packaging changes from Debian In-Reply-To: <07250FFC-45DE-47B0-8932-AAFFAD1D2799@freyther.de> References: <1461500262-16861-1-git-send-email-msuraev@sysmocom.de> <07250FFC-45DE-47B0-8932-AAFFAD1D2799@freyther.de> Message-ID: <571CCE58.5030205@sysmocom.de> I'm not expert on licensing terms but how can you remove GPL license from already published code? I thought you can publish new version under different license but once the code is published under GPL you can't simply revoke this. On 04/24/2016 03:29 PM, Holger Freyther wrote: >> On 24 Apr 2016, at 14:17, msuraev at sysmocom.de wrote: >> >> +Files: src/gsm/milenage/aes-internal.c >> + src/gsm/milenage/aes-encblock.c >> + src/gsm/milenage/aes.h >> + src/gsm/milenage/milenage.c >> + src/gsm/milenage/aes_wrap.h >> + src/gsm/milenage/aes-internal-enc.c >> + src/gsm/milenage/aes_i.h >> +Copyright: 2003-2007 Jouni Malinen >> +License: GPL-2 > this is dual licensed, hostapd upstream has removed GPLv2 and for AGPLv3+ compatibility of osmo-nitb or such this code needs to be used under the "BSD" (double check the actual license term) license. > > holger -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From holger at freyther.de Sun Apr 24 14:38:29 2016 From: holger at freyther.de (Holger Freyther) Date: Sun, 24 Apr 2016 16:38:29 +0200 Subject: [PATCH] Merge packaging changes from Debian In-Reply-To: <571CCE58.5030205@sysmocom.de> References: <1461500262-16861-1-git-send-email-msuraev@sysmocom.de> <07250FFC-45DE-47B0-8932-AAFFAD1D2799@freyther.de> <571CCE58.5030205@sysmocom.de> Message-ID: <749C05C0-5855-49FA-8B33-9B567A00A318@freyther.de> > On 24 Apr 2016, at 15:47, Max wrote: > > I'm not expert on licensing terms but how can you remove GPL license > from already published code? I thought you can publish new version under > different license but once the code is published under GPL you can't > simply revoke this. It starts by looking at the sourcecode: * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. The author has given us an option of A or B. In our case we have to pick option B (to align with AGPLv3+ of osmo-nitb and such). But in general any group of authors can decide to license past work under new terms (all authors need to agree, the old release will not vanish). holger From msuraev at sysmocom.de Mon Apr 25 10:22:17 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 25 Apr 2016 12:22:17 +0200 Subject: [PATCH] Refactor MNCC code Message-ID: <1461579737-28325-1-git-send-email-msuraev@sysmocom.de> From: Max * Explicitly use gsm_chan_t enum when checking for full rate channels. * Consistently use enums instead of (u)int, char etc. Note: because actual enum representation is up to compiler this might change the size of gsm_mncc struct so the MNCC protocol version is bumped. --- openbsc/include/openbsc/bsc_api.h | 6 +++- openbsc/include/openbsc/gsm_04_08.h | 2 +- openbsc/include/openbsc/mncc.h | 8 ++++-- openbsc/include/openbsc/mncc_int.h | 5 +++- openbsc/src/libbsc/bsc_api.c | 53 ++++++++++++++++++----------------- openbsc/src/libbsc/gsm_04_08_utils.c | 2 +- openbsc/src/libmsc/gsm_04_08.c | 5 ++-- openbsc/src/libmsc/mncc_builtin.c | 7 +++-- openbsc/src/osmo-bsc/osmo_bsc_bssap.c | 10 ++++--- 9 files changed, 56 insertions(+), 42 deletions(-) diff --git a/openbsc/include/openbsc/bsc_api.h b/openbsc/include/openbsc/bsc_api.h index a3d12f2..b2fc1ed 100644 --- a/openbsc/include/openbsc/bsc_api.h +++ b/openbsc/include/openbsc/bsc_api.h @@ -3,6 +3,8 @@ #ifndef OPENBSC_BSC_API_H #define OPENBSC_BSC_API_H +#include + #include "gsm_data.h" #define BSC_API_CONN_POL_ACCEPT 0 @@ -45,7 +47,9 @@ struct bsc_api { int bsc_api_init(struct gsm_network *network, struct bsc_api *api); int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id, int allow_sacch); -int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate); +int gsm0808_assign_req(struct gsm_subscriber_connection *conn, + enum gsm48_chan_mode chan_mode, + enum gsm_chan_t chan); int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher, const uint8_t *key, int len, int include_imeisv); int gsm0808_page(struct gsm_bts *bts, unsigned int page_group, diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index fd0b89d..d333e13 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -79,7 +79,7 @@ int gsm48_extract_mi(uint8_t *classmark2, int length, char *mi_string, uint8_t * int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char *mi_string, uint8_t *mi_type); int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn, struct msgb *msg, struct gsm_subscriber *subscr); -int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode); +int gsm48_lchan_modify(struct gsm_lchan *lchan, enum gsm48_chan_mode lchan_mode); int gsm48_rx_rr_modif_ack(struct msgb *msg); int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg); diff --git a/openbsc/include/openbsc/mncc.h b/openbsc/include/openbsc/mncc.h index 49f0c8b..70866fe 100644 --- a/openbsc/include/openbsc/mncc.h +++ b/openbsc/include/openbsc/mncc.h @@ -26,6 +26,8 @@ #include #include +#include +#include #include @@ -156,8 +158,8 @@ struct gsm_mncc { int emergency; char imsi[16]; - unsigned char lchan_type; - unsigned char lchan_mode; + enum gsm_chan_t lchan_type; + enum gsm48_chan_mode lchan_mode; }; struct gsm_data_frame { @@ -166,7 +168,7 @@ struct gsm_data_frame { unsigned char data[0]; }; -#define MNCC_SOCK_VERSION 5 +#define MNCC_SOCK_VERSION 6 struct gsm_mncc_hello { uint32_t msg_type; uint32_t version; diff --git a/openbsc/include/openbsc/mncc_int.h b/openbsc/include/openbsc/mncc_int.h index 213ce14..dafef25 100644 --- a/openbsc/include/openbsc/mncc_int.h +++ b/openbsc/include/openbsc/mncc_int.h @@ -3,12 +3,15 @@ #include +#include +#include + struct mncc_int { uint8_t def_codec[2]; }; extern struct mncc_int mncc_int; -uint8_t mncc_codec_for_mode(int lchan_type); +enum gsm48_chan_mode mncc_codec_for_mode(enum gsm_chan_t lchan_type); #endif diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c index b8b5967..2608504 100644 --- a/openbsc/src/libbsc/bsc_api.c +++ b/openbsc/src/libbsc/bsc_api.c @@ -34,8 +34,9 @@ #include #include - +#include #include +#include #define GSM0808_T10_VALUE 6, 0 @@ -155,7 +156,7 @@ static void assignment_t10_timeout(void *_conn) * Handle the multirate config */ static void handle_mr_config(struct gsm_subscriber_connection *conn, - struct gsm_lchan *lchan, int full_rate) + struct gsm_lchan *lchan, enum gsm_chan_t chan) { struct bsc_api *api; api = conn->bts->network->bsc_api; @@ -163,12 +164,13 @@ static void handle_mr_config(struct gsm_subscriber_connection *conn, struct gsm48_multi_rate_conf *mr_conf; if (api->mr_config) - return api->mr_config(conn, lchan, full_rate); + return api->mr_config(conn, lchan, + (GSM_LCHAN_TCH_H == chan) ? 0 : 1); - if (full_rate) - mr = &lchan->ts->trx->bts->mr_full; - else + if (GSM_LCHAN_TCH_H == chan) mr = &lchan->ts->trx->bts->mr_half; + else + mr = &lchan->ts->trx->bts->mr_full; mr_conf = (struct gsm48_multi_rate_conf *) mr->gsm48_ie; mr_conf->ver = 1; @@ -197,12 +199,11 @@ static void handle_mr_config(struct gsm_subscriber_connection *conn, * -> Assignment Complete/Assignment Failure * 5.) Release the SDCCH, continue signalling on the new link */ -static int handle_new_assignment(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate) +static int handle_new_assignment(struct gsm_subscriber_connection *conn, + enum gsm48_chan_mode chan_mode, + enum gsm_chan_t chan_type) { struct gsm_lchan *new_lchan; - int chan_type; - - chan_type = full_rate ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H; new_lchan = lchan_alloc(conn->bts, chan_type, 0); @@ -223,7 +224,7 @@ static int handle_new_assignment(struct gsm_subscriber_connection *conn, int cha /* handle AMR correctly */ if (chan_mode == GSM48_CMODE_SPEECH_AMR) - handle_mr_config(conn, new_lchan, full_rate); + handle_mr_config(conn, new_lchan, chan_type); if (rsl_chan_activate_lchan(new_lchan, 0x1, 0) < 0) { LOGP(DHO, LOGL_ERROR, "could not activate channel\n"); @@ -337,7 +338,9 @@ int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, /* * \brief Check if the given channel is compatible with the mode/fullrate */ -static int chan_compat_with_mode(struct gsm_lchan *lchan, int chan_mode, int full_rate) +static int chan_compat_with_mode(struct gsm_lchan *lchan, + enum gsm48_chan_mode chan_mode, + enum gsm_chan_t chan) { switch (chan_mode) { case GSM48_CMODE_SIGN: @@ -348,16 +351,14 @@ static int chan_compat_with_mode(struct gsm_lchan *lchan, int chan_mode, int ful case GSM48_CMODE_DATA_3k6: case GSM48_CMODE_DATA_6k0: /* these services can all run on TCH/H, but we may have - * an explicit override by the 'full_rate' argument */ + * an explicit override by the explicit chan argument */ switch (lchan->type) { case GSM_LCHAN_TCH_F: return 1; case GSM_LCHAN_TCH_H: - if (full_rate) - return 0; - else + if (GSM_LCHAN_TCH_H == chan) return 1; - break; + return 0; default: return 0; } @@ -368,9 +369,7 @@ static int chan_compat_with_mode(struct gsm_lchan *lchan, int chan_mode, int ful /* these services all explicitly require a TCH/F */ if (lchan->type == GSM_LCHAN_TCH_F) return 1; - else - return 0; - break; + return 0; } return 0; @@ -382,19 +381,21 @@ static int chan_compat_with_mode(struct gsm_lchan *lchan, int chan_mode, int ful * this is for audio handling only. In case the current channel does not allow * the selected mode a new one will be allocated. * + * If chan is not GSM_LCHAN_TCH_H than full rate is assumed. + * * TODO: Add multirate configuration, make it work for more than audio. */ -int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate) +int gsm0808_assign_req(struct gsm_subscriber_connection *conn, + enum gsm48_chan_mode chan_mode, enum gsm_chan_t chan) { - struct bsc_api *api; - api = conn->bts->network->bsc_api; + struct bsc_api *api = conn->bts->network->bsc_api; - if (!chan_compat_with_mode(conn->lchan, chan_mode, full_rate)) { - if (handle_new_assignment(conn, chan_mode, full_rate) != 0) + if (!chan_compat_with_mode(conn->lchan, chan_mode, chan)) { + if (handle_new_assignment(conn, chan_mode, chan) != 0) goto error; } else { if (chan_mode == GSM48_CMODE_SPEECH_AMR) - handle_mr_config(conn, conn->lchan, full_rate); + handle_mr_config(conn, conn->lchan, chan); LOGP(DMSC, LOGL_NOTICE, "Sending ChanModify for speech: %s on channel %s\n", diff --git a/openbsc/src/libbsc/gsm_04_08_utils.c b/openbsc/src/libbsc/gsm_04_08_utils.c index 635665a..327cff1 100644 --- a/openbsc/src/libbsc/gsm_04_08_utils.c +++ b/openbsc/src/libbsc/gsm_04_08_utils.c @@ -488,7 +488,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, } /* 9.1.5 Channel mode modify: Modify the mode on the MS side */ -int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode) +int gsm48_lchan_modify(struct gsm_lchan *lchan, enum gsm48_chan_mode mode) { struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CHN MOD"); struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 7b78d48..4de3477 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -2939,7 +2939,7 @@ static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg) return 0; return gsm0808_assign_req(trans->conn, mode->lchan_mode, - trans->conn->lchan->type != GSM_LCHAN_TCH_H); + trans->conn->lchan->type); } static void mncc_recv_rtp(struct gsm_network *net, uint32_t callref, @@ -3048,8 +3048,7 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref) LOGP(DMNCC, LOGL_DEBUG, "RTP create: codec=%s, chan_type=%s\n", get_value_string(gsm48_chan_mode_names, m), get_value_string(gsm_chan_t_names, lchan->type)); - return gsm0808_assign_req(trans->conn, m, - lchan->type != GSM_LCHAN_TCH_H); + return gsm0808_assign_req(trans->conn, m, lchan->type); } mncc_recv_rtp_sock(trans->net, trans, MNCC_RTP_CREATE); diff --git a/openbsc/src/libmsc/mncc_builtin.c b/openbsc/src/libmsc/mncc_builtin.c index ee98d2d..b879756 100644 --- a/openbsc/src/libmsc/mncc_builtin.c +++ b/openbsc/src/libmsc/mncc_builtin.c @@ -27,6 +27,9 @@ #include #include +#include +#include + #include #include #include @@ -65,7 +68,7 @@ static struct gsm_call *get_call_ref(uint32_t callref) return NULL; } -uint8_t mncc_codec_for_mode(int lchan_type) +enum gsm48_chan_mode mncc_codec_for_mode(enum gsm_chan_t lchan_type) { /* FIXME: check codec capabilities of the phone */ @@ -75,7 +78,7 @@ uint8_t mncc_codec_for_mode(int lchan_type) return mncc_int.def_codec[1]; } -static uint8_t determine_lchan_mode(struct gsm_mncc *setup) +static enum gsm48_chan_mode determine_lchan_mode(struct gsm_mncc *setup) { return mncc_codec_for_mode(setup->lchan_type); } diff --git a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c index a60940d..01105a8 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c @@ -28,6 +28,7 @@ #include #include +#include /* * helpers for the assignment command @@ -292,7 +293,8 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, uint8_t timeslot; uint8_t multiplex; enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN; - int i, supported, port, full_rate = -1; + enum gsm_chan_t chan = GSM_LCHAN_TCH_H; + int i, supported, port; if (!conn->conn) { LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n"); @@ -344,7 +346,6 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, * inner loop. The outer loop will exit due chan_mode having * the correct value. */ - full_rate = 0; msc = conn->msc; for (supported = 0; chan_mode == GSM48_CMODE_SIGN && supported < msc->audio_length; @@ -354,7 +355,8 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, for (i = 2; i < TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE); ++i) { if ((data[i] & 0x7f) == perm_val) { chan_mode = gsm88_to_chan_mode(perm_val); - full_rate = (data[i] & 0x4) == 0; + if (0 == (data[i] & 0x4)) + chan = GSM_LCHAN_TCH_F; break; } else if ((data[i] & 0x80) == 0x00) { break; @@ -371,7 +373,7 @@ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, port = mgcp_timeslot_to_endpoint(multiplex, timeslot); conn->rtp_port = rtp_calculate_port(port, msc->rtp_base); - return gsm0808_assign_req(conn->conn, chan_mode, full_rate); + return gsm0808_assign_req(conn->conn, chan_mode, chan); reject: resp = gsm0808_create_assignment_failure(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL); -- 2.8.1 From nhofmeyr at sysmocom.de Mon Apr 25 10:51:19 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 25 Apr 2016 12:51:19 +0200 Subject: [PATCH 1/4] gprs_gmm: ensure llme present upon Attach Req (CID #57686) In-Reply-To: <80CFD1F8-469C-4224-8194-DB95432DFF8B@freyther.de> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> <1460640093-22167-2-git-send-email-nhofmeyr@sysmocom.de> <80CFD1F8-469C-4224-8194-DB95432DFF8B@freyther.de> Message-ID: <20160425105119.GA2425@dub6> On Fri, Apr 22, 2016 at 03:47:29PM +0200, Holger Freyther wrote: > > > On 14 Apr 2016, at 15:21, Neels Hofmeyr wrote: > > > > --- > > openbsc/src/gprs/gprs_gmm.c | 4 ++++ > > 1 file changed, 4 insertions(+) > > > > diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c > > index 5f0a5fd..438e047 100644 > > --- a/openbsc/src/gprs/gprs_gmm.c > > +++ b/openbsc/src/gprs/gprs_gmm.c > > @@ -838,6 +838,10 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg, > > int rc; > > > > LOGMMCTXP(LOGL_INFO, ctx, "-> GMM ATTACH REQUEST "); > > + if (!llme) { > > same as with my other mail. The lower layer should create a llme on the fly. So please have a look at the coverity user interface to see _where_ the llme is NULL and then we can have a look at that issue. There is, obviously, an explicit NULL on the sysmocom/iu branch, where no LLME is applicable. openbsc/openbsc/src/gprs/gprs_gmm.c:2462: rc = gsm0408_rcv_gmm(mmctx, msg, NULL); Coverity concerns itself about a "Comparing llme to null implies that llme might be null." so no actual NULL is reported. (though coverity could have reported above explicit NULL which I found manually) Actually, the llme NULL check in gsm0408_rcv_gmm() is introduced in the sysmocom/iu branch along with mentioned explicit NULL: 1628 if (llme && !mmctx && 1629 gh->msg_type != GSM48_MT_GMM_ATTACH_REQ && 1630 gh->msg_type != GSM48_MT_GMM_RA_UPD_REQ) { 1631 LOGP(DMM, LOGL_NOTICE, "Cannot handle GMM for unknown MM CTX\n"); So my suggestion above to clean up llme only when it's not NULL does still make a lot of sense to me. Since I'm not familiar with GRPS code, maybe Daniel could have a quick look? I'm having a d?j? vu, didn't I write this before? Would be nice if I could stop banging my head against your wall now ;) ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Mon Apr 25 11:00:10 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 25 Apr 2016 13:00:10 +0200 Subject: [PATCH] queue_new(): fix NULL dereference on allocation failure Message-ID: <1461582010-3322-1-git-send-email-nhofmeyr@sysmocom.de> Coverity complains about a 'Dereference before null check' on *queue. So, push the NULL check further up. Though I doubt that 'return EOF' is the proper way to handle allocation failure, this patch is only about the NULL dereference. Fixes: CID#57918 --- gtp/queue.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gtp/queue.c b/gtp/queue.c index 7c971b0..5b4d849 100644 --- a/gtp/queue.c +++ b/gtp/queue.c @@ -127,16 +127,15 @@ int queue_new(struct queue_t **queue) if (QUEUE_DEBUG) printf("queue_new\n"); *queue = calloc(1, sizeof(struct queue_t)); + if (!(*queue)) + return EOF; (*queue)->next = 0; (*queue)->first = -1; (*queue)->last = -1; if (QUEUE_DEBUG) queue_print(*queue); - if (*queue) - return 0; - else - return EOF; + return 0; } /*! \brief Deallocates queue structure */ -- 2.1.4 From nhofmeyr at sysmocom.de Mon Apr 25 11:01:02 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 25 Apr 2016 13:01:02 +0200 Subject: [PATCH] queue_new(): if calloc fails, abort (CID #57918) In-Reply-To: References: <1460644722-22972-1-git-send-email-nhofmeyr@sysmocom.de> <20160416113741.GK31766@nataraja> <20160418105619.GD1703@dub6> Message-ID: <20160425110102.GB2425@dub6> On Fri, Apr 22, 2016 at 03:39:20PM +0200, Holger Freyther wrote: > return EOF then. For commit messages we used to put "Fixes: CID#1234" at the bottom of the commit message. submitting a new patch with subject "queue_new(): fix NULL dereference on allocation failure" ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Mon Apr 25 13:03:15 2016 From: laforge at gnumonks.org (Harald Welte) Date: Mon, 25 Apr 2016 15:03:15 +0200 Subject: [PATCH] Refactor MNCC code In-Reply-To: <1461579737-28325-1-git-send-email-msuraev@sysmocom.de> References: <1461579737-28325-1-git-send-email-msuraev@sysmocom.de> Message-ID: <20160425130315.GR25360@nataraja> Hi Max, On Mon, Apr 25, 2016 at 12:22:17PM +0200, msuraev at sysmocom.de wrote: > * Explicitly use gsm_chan_t enum when checking for full rate channels. > * Consistently use enums instead of (u)int, char etc. Is this supposed to be a pure cleanup patch (not changing behavior) or a bug fix (changing behavior)? This is currently not clear to me I'm not particularly happy that in many cases when there is a bug to fix, you first seem to restructure/cleanup the code and then address the bug. This adds the risk of introducing behavioral changes in the first step (particularly with lack of good test coverage), and it also means we're focussing less on the relevant topic. > Note: because actual enum representation is up to compiler this might > change the size of gsm_mncc struct so the MNCC protocol version is > bumped. I think this kind of change just creates more effort for everyone and I don't really see much benefit of it. You would have to merge related changes not only to the NITB but to all its users (lcr, mncc_python, osmo-sip-connector, ...) at the same time. Have you changed all the respective users and re-tested them? Do you think it is a good use of our time to do so for a merely stylistic improvement? In general I think it is a bad idea to have enum's in structures that describe an external interface / protocol betweeo two programs, exactly for the reason you stated. Alignment differences can be easily avoided with __attribute__ ((packed)), but enums have the inherent problem of '-fshort-enums', which might be default on some platform. and then you add a new enum value, and your structure size changes again. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From msuraev at sysmocom.de Mon Apr 25 13:22:00 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Mon, 25 Apr 2016 15:22:00 +0200 Subject: [PATCH] Disconnect calls with incompatible channels Message-ID: <1461590520-22197-1-git-send-email-msuraev@sysmocom.de> From: Max In case both TCH/H and TCH/F are configured and internal MNCC handler is used we might end up in a situation where call legs with incompatible channel types or codecs would be connected resulting in a broken audio. Disconnect such calls with appropriate error message. Fixes: OS#1663 --- openbsc/src/libmsc/gsm_04_08.c | 46 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 7b78d48..05cb886 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1600,6 +1600,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) struct gsm_bts *bts = lchan->ts->trx->bts; struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts; enum gsm_chan_t lt = lchan->type, rt = remote_lchan->type; + enum gsm48_chan_mode lm = lchan->tch_mode, rm = remote_lchan->tch_mode; int rc; DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u,%s) and " @@ -1614,6 +1615,22 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) return -EINVAL; } + if (lt != rt) { + LOGP(DCC, LOGL_ERROR, "Cannot patch through call with different" + " channel types: local = %s, remote = %s\n", + get_value_string(gsm_chan_t_names, lt), + get_value_string(gsm_chan_t_names, rt)); + return -EBADSLT; + } + + if (lm != rm) { + LOGP(DCC, LOGL_ERROR, "Cannot patch through call with different" + " channel modes: local = %s, remote = %s\n", + get_value_string(gsm48_chan_mode_names, lm), + get_value_string(gsm48_chan_mode_names, rm)); + return -EMEDIUMTYPE; + } + // todo: map between different bts types switch (bts->type) { case GSM_BTS_TYPE_NANOBTS: @@ -1851,6 +1868,30 @@ static void gsm48_cc_timeout(void *arg) } +/* disconnect both calls from the bridge */ +static inline void disconnect_bridge(struct gsm_network *net, + struct gsm_mncc_bridge *bridge, int err) +{ + struct gsm_trans *trans0 = trans_find_by_callref(net, bridge->callref[0]); + struct gsm_trans *trans1 = trans_find_by_callref(net, bridge->callref[1]); + struct gsm_mncc mx_rel; + if (!trans0 || !trans1) + return; + + DEBUGP(DCC, "Failed to bridge TCH for calls %x <-> %x :: %s \n", + trans0->callref, trans1->callref, strerror(err)); + + memset(&mx_rel, 0, sizeof(struct gsm_mncc)); + mncc_set_cause(&mx_rel, GSM48_CAUSE_LOC_INN_NET, + GSM48_CC_CAUSE_CHAN_UNACCEPT); + + mx_rel.callref = trans0->callref; + gsm48_cc_tx_disconnect(trans0, &mx_rel); + + mx_rel.callref = trans1->callref; + gsm48_cc_tx_disconnect(trans1, &mx_rel); +} + static void gsm48_start_cc_timer(struct gsm_trans *trans, int current, int sec, int micro) { @@ -3221,7 +3262,10 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) /* handle special messages */ switch(msg_type) { case MNCC_BRIDGE: - return tch_bridge(net, arg); + rc = tch_bridge(net, arg); + if (rc < 0) + disconnect_bridge(net, arg, -rc); + return rc; case MNCC_FRAME_DROP: return tch_recv_mncc(net, data->callref, 0); case MNCC_FRAME_RECV: -- 2.8.1 From msuraev at sysmocom.de Mon Apr 25 13:29:12 2016 From: msuraev at sysmocom.de (Max) Date: Mon, 25 Apr 2016 15:29:12 +0200 Subject: [PATCH] Refactor MNCC code In-Reply-To: <20160425130315.GR25360@nataraja> References: <1461579737-28325-1-git-send-email-msuraev@sysmocom.de> <20160425130315.GR25360@nataraja> Message-ID: <571E1BA8.5080709@sysmocom.de> Yes, it's just rewrite of a cleanup from before which was not accepted because it had booleans in function signature so it's safe to just drop. The actual fix for a bug is in separate patch which does not depend on this one. Before fixing a bug I've got to first understand what existing code does which is not always immediately clear, especially if comments are missing. While going over a code I sometimes change/simplify functions more as a "note to self" to make sure I easier understand particular part of the code when getting back to it. If I feel that such changes might be generally useful than I send it as a patch. Of course such feeling is not always 100% match with what others feel so not all the patches go through. On 04/25/2016 03:03 PM, Harald Welte wrote: > Hi Max, > > On Mon, Apr 25, 2016 at 12:22:17PM +0200, msuraev at sysmocom.de wrote: >> * Explicitly use gsm_chan_t enum when checking for full rate channels. >> * Consistently use enums instead of (u)int, char etc. > Is this supposed to be a pure cleanup patch (not changing behavior) or a > bug fix (changing behavior)? This is currently not clear to me > > I'm not particularly happy that in many cases when there is a bug to > fix, you first seem to restructure/cleanup the code and then address the > bug. This adds the risk of introducing behavioral changes in the first > step (particularly with lack of good test coverage), and it also means > we're focussing less on the relevant topic. > >> Note: because actual enum representation is up to compiler this might >> change the size of gsm_mncc struct so the MNCC protocol version is >> bumped. > I think this kind of change just creates more effort for everyone and I > don't really see much benefit of it. You would have to merge related > changes not only to the NITB but to all its users (lcr, mncc_python, > osmo-sip-connector, ...) at the same time. Have you changed all the > respective users and re-tested them? Do you think it is a good use of > our time to do so for a merely stylistic improvement? > > In general I think it is a bad idea to have enum's in structures that > describe an external interface / protocol betweeo two programs, exactly > for the reason you stated. Alignment differences can be easily avoided > with __attribute__ ((packed)), but enums have the inherent problem of > '-fshort-enums', which might be default on some platform. and then you > add a new enum value, and your structure size changes again. > > Regards, > Harald -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From holger at freyther.de Mon Apr 25 18:35:39 2016 From: holger at freyther.de (Holger Freyther) Date: Mon, 25 Apr 2016 20:35:39 +0200 Subject: [PATCH 1/4] gprs_gmm: ensure llme present upon Attach Req (CID #57686) In-Reply-To: <20160425105119.GA2425@dub6> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> <1460640093-22167-2-git-send-email-nhofmeyr@sysmocom.de> <80CFD1F8-469C-4224-8194-DB95432DFF8B@freyther.de> <20160425105119.GA2425@dub6> Message-ID: <0BDD2D53-668C-4133-B794-AE9065486337@freyther.de> > On 25 Apr 2016, at 12:51, Neels Hofmeyr wrote: > >> > > There is, obviously, an explicit NULL on the sysmocom/iu branch, where no LLME > is applicable. > > openbsc/openbsc/src/gprs/gprs_gmm.c:2462: rc = gsm0408_rcv_gmm(mmctx, msg, NULL); > when looking at the patch I thought you would be on master. > So my suggestion above to clean up llme only when it's not NULL does still make > a lot of sense to me. > > Since I'm not familiar with GRPS code, maybe Daniel could have a quick look? > I'm having a d?j? vu, didn't I write this before? > Would be nice if I could stop banging my head against your wall now ;) I would need to look at the code but if the GMM code is used on top of two different layers, then it should not look too much at the LLME? Specially as with send/receive it might not use the same LLME anyway? So yes, for your Iu branch add the NULL check, once we merge to master we need to see if there is valuable information inside the llme that we need to store somewhere else/or just log it. holger From nhofmeyr at sysmocom.de Tue Apr 26 11:14:37 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 26 Apr 2016 13:14:37 +0200 Subject: [PATCH] Deprecate comp128 In-Reply-To: <1461251560-23628-1-git-send-email-msuraev@sysmocom.de> References: <1461251560-23628-1-git-send-email-msuraev@sysmocom.de> Message-ID: <20160426111437.GC14118@ass40.sysmocom.de> On Thu, Apr 21, 2016 at 05:12:40PM +0200, msuraev at sysmocom.de wrote: > From: Max > > Mark function as deprecated to discourage its usage: people should use > generic API in osmocom/crypt/auth.h There is much more going on in this patch than your log message suggests... > --- > include/osmocom/gsm/comp128.h | 8 ++++++-- > src/gsm/auth_comp128v1.c | 2 +- > src/gsm/comp128.c | 7 ++++++- > 3 files changed, 13 insertions(+), 4 deletions(-) > > diff --git a/include/osmocom/gsm/comp128.h b/include/osmocom/gsm/comp128.h > index 33b997a..8ff76b1 100644 > --- a/include/osmocom/gsm/comp128.h > +++ b/include/osmocom/gsm/comp128.h > @@ -8,11 +8,15 @@ > > #include > > +#include > + > /* > - * Performs the COMP128 algorithm (used as A3/A8) > + * Performs the COMP128v1 algorithm (used as A3/A8) ...comments... > * ki : uint8_t [16] > * srand : uint8_t [16] > * sres : uint8_t [4] > * kc : uint8_t [8] > */ > -void comp128(const uint8_t *ki, const uint8_t *srand, uint8_t *sres, uint8_t *kc); > +void comp128v1(const uint8_t *ki, const uint8_t *srand, uint8_t *sres, uint8_t *kc); ...new function... > + > +void comp128(const uint8_t *ki, const uint8_t *srand, uint8_t *sres, uint8_t *kc) OSMO_DEPRECATED("Use generic API from osmocom/crypt/auth.h instead"); > diff --git a/src/gsm/auth_comp128v1.c b/src/gsm/auth_comp128v1.c > index 41aef71..c40027e 100644 > --- a/src/gsm/auth_comp128v1.c > +++ b/src/gsm/auth_comp128v1.c > @@ -28,7 +28,7 @@ static int c128v1_gen_vec(struct osmo_auth_vector *vec, > struct osmo_sub_auth_data *aud, > const uint8_t *_rand) > { > - comp128(aud->u.gsm.ki, _rand, vec->sres, vec->kc); > + comp128v1(aud->u.gsm.ki, _rand, vec->sres, vec->kc); ...or is it a rename after all... > vec->auth_types = OSMO_AUTH_TYPE_GSM; > > return 0; > diff --git a/src/gsm/comp128.c b/src/gsm/comp128.c > index b7a2382..abb4917 100644 > --- a/src/gsm/comp128.c > +++ b/src/gsm/comp128.c > @@ -185,7 +185,7 @@ _comp128_permutation(uint8_t *x, uint8_t *bits) > } > > void > -comp128(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc) > +comp128v1(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc) > { > int i; > uint8_t x[32], bits[128]; > @@ -228,3 +228,8 @@ comp128(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc) > kc[7] = 0; > } > > +void > +comp128(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc) > +{ > + comp128v1(ki, rand, sres, kc); > +} ...why add a deprecation but also add a shim to avoid it? These things should definitely be in the commit log message. Also the first log line looks like you were deprecating the algorithm comp128 itself, maybe say "comp128()" to illustrate it's just a function? ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Apr 26 11:19:01 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 26 Apr 2016 13:19:01 +0200 Subject: [PATCH 2/2] SysmoBTS: refactor code to simplify understanding In-Reply-To: <96FBF95A-2837-4BDC-AAC3-8C2A3D22C655@freyther.de> References: <1461257007-22060-1-git-send-email-msuraev@sysmocom.de> <1461257007-22060-2-git-send-email-msuraev@sysmocom.de> <96FBF95A-2837-4BDC-AAC3-8C2A3D22C655@freyther.de> Message-ID: <20160426111901.GD14118@ass40.sysmocom.de> On Fri, Apr 22, 2016 at 03:35:23PM +0200, Holger Freyther wrote: > > > On 21 Apr 2016, at 18:43, msuraev at sysmocom.de wrote: > > > > From: Max > > Hi Max, > > > > > > Use bool type for boolean values. > > Move common code out of if.. else. > > is this worth our time? I like API clarifications, IMHO they are "always" worth their time as they extend "infinitely" into the future for every user. I'd even prefer two separate commits though. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Apr 26 11:23:33 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 26 Apr 2016 13:23:33 +0200 Subject: OpenBSC relating IMSI/IMEI In-Reply-To: <4B1C20EA-7056-43EB-836C-FE43D9F91BDA@gmail.com> References: <4B1C20EA-7056-43EB-836C-FE43D9F91BDA@gmail.com> Message-ID: <20160426112333.GE14118@ass40.sysmocom.de> On Fri, Apr 22, 2016 at 10:57:25AM +0300, robert wrote: > Hi, > > I?m currently facing a strange issue where the number of entries in the subscriber table is different from the number of entries in the equipment table, therefore I cannot consistently relate each IMSI to its correct IMEI. I also had another issue where I have the same number of entries but the ID?s of the rows are different as shown below: > > Subscriber table Equipment table > > ID IMSI ID IMEI > 1 XXXX 1 XXXX > 2 XXXX 2 XXXX > 4 XXXX 14 XXXX > > Does anyone know why this is happening, and how can I correctly relate each IMSI to its corresponding IMEI ? Just guessing, maybe an MS tries to subscribe but the Location Update is rejected halfway through the dance of collecting IMSI and IMEI? So I would assume IMSI ID 4 and IMEI ID 14 are two separate subscribers. If you're certain they are the same MS that subscribed correctly then I'd expect this to be a bug... in which case it would be great if you could detail on the circumstances/reproducability etc. ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Apr 26 11:28:43 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 26 Apr 2016 13:28:43 +0200 Subject: [PATCH 1/4] gsm0480: RELEASE COMPLETE can be without any payload In-Reply-To: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328875-8253-1-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <20160426112843.GF14118@ass40.sysmocom.de> On Fri, Apr 22, 2016 at 02:41:12PM +0200, Sergey Kostanbaev wrote: > From: Sergey Kostanbaev > > --- > src/gsm/gsm0480.c | 6 ------ > 1 file changed, 6 deletions(-) > > diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c > index 8963b78..55bddd5 100644 > --- a/src/gsm/gsm0480.c > +++ b/src/gsm/gsm0480.c > @@ -248,12 +248,6 @@ int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len, > struct ss_request *req) > { > int rc = 0; > - > - if (len < sizeof(*hdr) + 2) { > - LOGP(0, LOGL_DEBUG, "SS Request is too short.\n"); > - return 0; > - } > - > if (gsm48_hdr_pdisc(hdr) == GSM48_PDISC_NC_SS) { I believe this should only remove the "+ 2" and still check for if (len < sizeof(*hdr)) { return 0; } since the code continues to dereference hdr, or is this the explicit responsibility of the caller? ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Apr 26 11:39:18 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 26 Apr 2016 13:39:18 +0200 Subject: [PATCH 2/9] libmsc: Add USSD MAP constant in gsup_message_type In-Reply-To: <1461328898-8298-2-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> <1461328898-8298-2-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <20160426113918.GG14118@ass40.sysmocom.de> Just minor remarks... IMHO it would be good to mention in the commit log the file/function in which the constant will be used, if not adding the constant along with its first use. Why are you adding the GPRS_GSUP_MSGT_USSD_MAP out of sequence? So far the constants are sorted by bit value, rather comply to that. ~Neels On Fri, Apr 22, 2016 at 02:41:31PM +0200, Sergey Kostanbaev wrote: > From: Sergey Kostanbaev > > --- > openbsc/include/openbsc/gprs_gsup_messages.h | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/openbsc/include/openbsc/gprs_gsup_messages.h b/openbsc/include/openbsc/gprs_gsup_messages.h > index 8cbc809..fb9c66e 100644 > --- a/openbsc/include/openbsc/gprs_gsup_messages.h > +++ b/openbsc/include/openbsc/gprs_gsup_messages.h > @@ -53,6 +53,8 @@ enum gprs_gsup_iei { > }; > > enum gprs_gsup_message_type { > + GPRS_GSUP_MSGT_USSD_MAP = 0b01111111, > + > GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST = 0b00000100, > GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR = 0b00000101, > GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT = 0b00000110, > -- > 1.9.1 > -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Apr 26 11:58:04 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 26 Apr 2016 13:58:04 +0200 Subject: [PATCH 3/9] libmsc: Update USSD to use new ss_request structure In-Reply-To: <1461328898-8298-3-git-send-email-sergey.kostanbaev@gmail.com> References: <1461328898-8298-1-git-send-email-sergey.kostanbaev@gmail.com> <1461328898-8298-3-git-send-email-sergey.kostanbaev@gmail.com> Message-ID: <20160426115804.GH14118@ass40.sysmocom.de> On Fri, Apr 22, 2016 at 02:41:32PM +0200, Sergey Kostanbaev wrote: > --- > openbsc/include/openbsc/gsm_04_80.h | 15 +++-- > openbsc/src/libmsc/gsm_04_80.c | 128 ++++++++++++++++++++++++------------ > openbsc/src/libmsc/ussd.c | 79 ++++++++++++++++++---- > 3 files changed, 162 insertions(+), 60 deletions(-) > > diff --git a/openbsc/include/openbsc/gsm_04_80.h b/openbsc/include/openbsc/gsm_04_80.h > index 0a60652..371bc17 100644 > --- a/openbsc/include/openbsc/gsm_04_80.h > +++ b/openbsc/include/openbsc/gsm_04_80.h > @@ -7,12 +7,17 @@ > > struct gsm_subscriber_connection; > > -int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn, > - const struct msgb *in_msg, const char* response_text, > - const struct ussd_request *req); > +int gsm0480_send_component(struct gsm_subscriber_connection *conn, Why remove the '_ussd_' name component here while you keep it in the other functions? IMHO you should also describe function renames in the log message. > + struct msgb *msg, > + struct ss_header* reqhdr); > + > int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn, > - const struct msgb *msg, > - const struct ussd_request *request); > + uint8_t invoke_id, > + uint8_t transaction_id); > + > +struct msgb *gsm0480_compose_ussd_component(struct ss_request* req); ...and additions/out-factorings as well. > + > + ^ osmo* is usually sparse on whitespace ;) > > int gsm0480_send_ussdNotify(struct gsm_subscriber_connection *conn, int level, const char *text); > int gsm0480_send_releaseComplete(struct gsm_subscriber_connection *conn); > diff --git a/openbsc/src/libmsc/gsm_04_80.c b/openbsc/src/libmsc/gsm_04_80.c > index f1d75f2..e6e4a92 100644 > --- a/openbsc/src/libmsc/gsm_04_80.c > +++ b/openbsc/src/libmsc/gsm_04_80.c > @@ -39,6 +39,22 @@ > #include > #include > > +/* This function can handle ASN1 length up to 255 which is enough for USSD */ > +static inline unsigned char *msgb_wrap_with_ASN1_TL(struct msgb *msgb, uint8_t tag) > +{ > + uint16_t origlen = msgb->len; > + uint8_t *data = msgb_push(msgb, (origlen > 0x7f) ? 3 : 2); > + data[0] = tag; > + if (origlen > 0x7f) { > + data[1] = 0x81; > + data[2] = origlen; > + } else { > + data[1] = origlen; > + } > + return data; > +} Would be good to use constants instead of the two magic values, which would also improve readability; otherwise I would like to see comments describing the semantics to the uninformed reader. > + > + ^ Again, a single line of whitespace would be usual in osmo*. ... This patch is rather large, especially for a one-liner commit log; would it be possible to break this patch down into smaller changes that are easier to review? That would be great! Unfortunately I have to redirect my attention to other tasks now and cannot look at the remaining changes... Thanks! ~Neels > static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag) > { > uint8_t *data = msgb_push(msgb, 2); > @@ -59,83 +75,111 @@ static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag, > return data; > } > > +static inline unsigned char *msgb_wrap_with_L(struct msgb *msgb) > +{ > + uint8_t *data = msgb_push(msgb, 1); > > -/* Send response to a mobile-originated ProcessUnstructuredSS-Request */ > -int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn, > - const struct msgb *in_msg, const char *response_text, > - const struct ussd_request *req) > + data[0] = msgb->len - 1; > + return data; > +} > + > +/* Compose universial USSD packet invoke/return_result payload */ > +struct msgb *gsm0480_compose_ussd_component(struct ss_request* req) > { > struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD RSP"); > - struct gsm48_hdr *gh; > uint8_t *ptr8; > - int response_len; > > /* First put the payload text into the message */ > ptr8 = msgb_put(msg, 0); > - gsm_7bit_encode_n_ussd(ptr8, msgb_tailroom(msg), response_text, &response_len); > - msgb_put(msg, response_len); > + > + memcpy(ptr8, req->ussd_text, req->ussd_text_len); > + msgb_put(msg, req->ussd_text_len); > > /* Then wrap it as an Octet String */ > - msgb_wrap_with_TL(msg, ASN1_OCTET_STRING_TAG); > + msgb_wrap_with_ASN1_TL(msg, ASN1_OCTET_STRING_TAG); > > /* Pre-pend the DCS octet string */ > - msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, 0x0F); > + msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, req->ussd_text_language); > > /* Then wrap these as a Sequence */ > - msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); > - > - /* Pre-pend the operation code */ > - msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, > - GSM0480_OP_CODE_PROCESS_USS_REQ); > - > - /* Wrap the operation code and IA5 string as a sequence */ > - msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); > + msgb_wrap_with_ASN1_TL(msg, GSM_0480_SEQUENCE_TAG); > + > + if (req->component_type == GSM0480_CTYPE_RETURN_RESULT) { > + /* Pre-pend the operation code */ > + msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, req->opcode); > + > + /* Wrap the operation code and IA5 string as a sequence */ > + msgb_wrap_with_ASN1_TL(msg, GSM_0480_SEQUENCE_TAG); > + > + /* Pre-pend the invoke ID */ > + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id); > + } else if (req->component_type == GSM0480_CTYPE_INVOKE) { > + /* Pre-pend the operation code */ > + msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, req->opcode); > + > + /* Pre-pend the invoke ID */ > + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id); > + } else { > + abort(); > + } > + > + /* Wrap this up as an Invoke or a Return Result component */ > + msgb_wrap_with_ASN1_TL(msg, req->component_type); > + return msg; > +} > > - /* Pre-pend the invoke ID */ > - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id); > +#ifndef NO_GSM0480_SEND_FUNC > > - /* Wrap this up as a Return Result component */ > - msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT); > +int gsm0480_send_component(struct gsm_subscriber_connection *conn, > + struct msgb *msg, > + struct ss_header* reqhdr) > +{ > + struct gsm48_hdr *gh; > > - /* Wrap the component in a Facility message */ > - msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); > + if (reqhdr->message_type == GSM0480_MTYPE_REGISTER || > + reqhdr->message_type == GSM0480_MTYPE_RELEASE_COMPLETE) { > + /* Wrap the component in a Facility message, it's not ASN1 */ > + msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); > + } else if (reqhdr->message_type == GSM0480_MTYPE_FACILITY) { > + /* For GSM0480_MTYPE_FACILITY it's LV not TLV */ > + msgb_wrap_with_L(msg); > + } else { > + abort(); > + } > > /* And finally pre-pend the L3 header */ > gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh)); > - gh->proto_discr = GSM48_PDISC_NC_SS | req->transaction_id > + gh->proto_discr = GSM48_PDISC_NC_SS | reqhdr->transaction_id > | (1<<7); /* TI direction = 1 */ > - gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE; > + gh->msg_type = reqhdr->message_type; > + > + DEBUGP(DSS, "Sending SS to mobile: %s\n", msgb_hexdump(msg)); > > return gsm0808_submit_dtap(conn, msg, 0, 0); > } > > + > int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn, > - const struct msgb *in_msg, > - const struct ussd_request *req) > + uint8_t invoke_id, > + uint8_t transaction_id) > { > struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD REJ"); > - struct gsm48_hdr *gh; > + struct ss_header ssh; > > /* First insert the problem code */ > msgb_push_TLV1(msg, GSM_0480_PROBLEM_CODE_TAG_GENERAL, > GSM_0480_GEN_PROB_CODE_UNRECOGNISED); > > /* Before it insert the invoke ID */ > - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id); > + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); > > /* Wrap this up as a Reject component */ > - msgb_wrap_with_TL(msg, GSM0480_CTYPE_REJECT); > - > - /* Wrap the component in a Facility message */ > - msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); > + msgb_wrap_with_ASN1_TL(msg, GSM0480_CTYPE_REJECT); > > - /* And finally pre-pend the L3 header */ > - gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh)); > - gh->proto_discr = GSM48_PDISC_NC_SS; > - gh->proto_discr |= req->transaction_id | (1<<7); /* TI direction = 1 */ > - gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE; > - > - return gsm0808_submit_dtap(conn, msg, 0, 0); > + /* Prepare data for L3 header */ > + ssh.transaction_id = transaction_id; > + ssh.message_type = GSM0480_MTYPE_RELEASE_COMPLETE; > + return gsm0480_send_component(conn, msg, &ssh); > } > > int gsm0480_send_ussdNotify(struct gsm_subscriber_connection *conn, int level, const char *text) > @@ -173,3 +217,5 @@ int gsm0480_send_releaseComplete(struct gsm_subscriber_connection *conn) > > return gsm0808_submit_dtap(conn, msg, 0, 0); > } > + > +#endif > diff --git a/openbsc/src/libmsc/ussd.c b/openbsc/src/libmsc/ussd.c > index 7f01eae..3cafe02 100644 > --- a/openbsc/src/libmsc/ussd.c > +++ b/openbsc/src/libmsc/ussd.c > @@ -33,41 +33,71 @@ > #include > #include > #include > +#include > +#include > +#include > > /* Declarations of USSD strings to be recognised */ > const char USSD_TEXT_OWN_NUMBER[] = "*#100#"; > > /* Forward declarations of network-specific handler functions */ > -static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ussd_request *req); > +static int send_own_number(struct gsm_subscriber_connection *conn, > + const struct ss_header *reqhdr, > + const struct ss_request *req); > > > /* Entrypoint - handler function common to all mobile-originated USSDs */ > int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg) > { > int rc; > - struct ussd_request req; > + struct ss_header reqhdr; > + struct ss_request req; > + char request_string[MAX_LEN_USSD_STRING + 1]; > struct gsm48_hdr *gh; > > memset(&req, 0, sizeof(req)); > + memset(&reqhdr, 0, sizeof(reqhdr)); > gh = msgb_l3(msg); > - rc = gsm0480_decode_ussd_request(gh, msgb_l3len(msg), &req); > + rc = gsm0480_decode_ss_request(gh, msgb_l3len(msg), &reqhdr); > if (!rc) { > - DEBUGP(DMM, "Unhandled SS\n"); > - rc = gsm0480_send_ussd_reject(conn, msg, &req); > + DEBUGP(DSS, "Incorrect SS header\n"); > msc_release_connection(conn); > return rc; > } > > - /* Release-Complete */ > - if (req.text[0] == '\0') > + rc = gsm0480_parse_ss_facility(gh->data + reqhdr.component_offset, > + reqhdr.component_length, > + &req); > + if (!rc) { > + DEBUGP(DSS, "Unhandled SS\n"); > + /* TODO req.invoke_id may not be set!!! */ > + rc = gsm0480_send_ussd_reject(conn, req.invoke_id, reqhdr.transaction_id); > + msc_release_connection(conn); > + return rc; > + } > + > + if (reqhdr.message_type == GSM0480_MTYPE_RELEASE_COMPLETE) > return 0; > > - if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)req.text)) { > - DEBUGP(DMM, "USSD: Own number requested\n"); > - rc = send_own_number(conn, msg, &req); > + if (reqhdr.message_type != GSM0480_MTYPE_REGISTER || > + req.component_type != GSM0480_CTYPE_INVOKE || > + req.opcode != GSM0480_OP_CODE_PROCESS_USS_REQ || > + req.ussd_text_language != 0x0f) > + { > + DEBUGP(DSS, "Unexpected SS\n"); > + rc = gsm0480_send_ussd_reject(conn, req.invoke_id, reqhdr.transaction_id); > + msc_release_connection(conn); > + return rc; > + } > + > + gsm_7bit_decode_n_ussd(request_string, MAX_LEN_USSD_STRING, req.ussd_text, req.ussd_text_len); > + > + if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)request_string)) { > + DEBUGP(DSS, "USSD: Own number requested\n"); > + rc = send_own_number(conn, &reqhdr, &req); > } else { > - DEBUGP(DMM, "Unhandled USSD %s\n", req.text); > - rc = gsm0480_send_ussd_reject(conn, msg, &req); > + DEBUGP(DSS, "Unhandled USSD %s\n", request_string); > + rc = gsm0480_send_ussd_reject(conn, req.invoke_id, reqhdr.transaction_id); > } > > /* check if we can release it */ > @@ -76,12 +106,33 @@ int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg) > } > > /* A network-specific handler function */ > -static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ussd_request *req) > +static int send_own_number(struct gsm_subscriber_connection *conn, > + const struct ss_header *reqhdr, > + const struct ss_request *req) > { > + struct ss_request rss; > + struct ss_header rssh; > + > char *own_number = conn->subscr->extension; > char response_string[GSM_EXTENSION_LENGTH + 20]; > + int response_len; > > /* Need trailing CR as EOT character */ > snprintf(response_string, sizeof(response_string), "Your extension is %s\r", own_number); > - return gsm0480_send_ussd_response(conn, msg, response_string, req); > + > + memset(&rss, 0, sizeof(rss)); > + gsm_7bit_encode_n_ussd(rss.ussd_text, MAX_LEN_USSD_STRING, response_string, &response_len); > + rss.ussd_text_len = response_len; > + rss.ussd_text_language = 0x0f; > + > + rss.component_type = GSM0480_CTYPE_RETURN_RESULT; > + rss.invoke_id = req->invoke_id; > + rss.opcode = GSM0480_OP_CODE_PROCESS_USS_REQ; > + > + rssh.message_type = GSM0480_MTYPE_RELEASE_COMPLETE; > + rssh.transaction_id = reqhdr->transaction_id; > + > + return gsm0480_send_component(conn, > + gsm0480_compose_ussd_component(&rss), > + &rssh); > } > -- > 1.9.1 > -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Apr 26 12:04:20 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 26 Apr 2016 14:04:20 +0200 Subject: osmo-combo build script In-Reply-To: References: Message-ID: <20160426120420.GI14118@ass40.sysmocom.de> On Sat, Apr 23, 2016 at 06:35:42PM +0200, Alexander Chemeris wrote: > Hi all, > > There has been a few questions recently about building > OpenBSC/OsmoBTS, especially for SDR devices, so I decided to share a > link to a "make world" style build script which may help newcomers to > get started. > > The script was hacked together by Sergey Kostanbaev to build static > binaries and was not meant for wide use, so it have rough edges and > may not work for every setup, but I hope it'll be useful for someone. > > Check out this git repository for the source code and brief documentation: > https://github.com/fairwaves/osmo-combo Nice, thanks! I do have a build-all shell script for the 3G stack that I heavily use to ensure clean builds. Maybe I can translate it into a Makefile like this one... But, hold on, are you actually mirroring the osmo* source trees in that repository? Makes it kind of hard to contribute back to upstream, right? I'd prefer to have just the Makefile, which (as a rainbow unicorn) could also clone the git sources if not present... Anyway, thanks for sharing! ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From tom at tsou.cc Tue Apr 26 18:44:56 2016 From: tom at tsou.cc (Tom Tsou) Date: Tue, 26 Apr 2016 11:44:56 -0700 Subject: [PATCH 0/4] core/conv: Fast Viterbi decoding In-Reply-To: References: <20140429041352.GA5213@phenom.hsd1.va.comcast.net> <67121C8F-38EA-4835-AA8E-025DD0C024F4@freyther.de> Message-ID: On Wed, Apr 20, 2016 at 3:55 AM, Alexander Chemeris wrote: > Recent activity around convolutional coding has reminded me about this > lost diamond. Just wondering if there is a chance to resolve the > critical issues and get this merged? I'm quite backed up at this point, but, yes, I'm aware that the Viterbi patchset is outstanding. I've been working on EDGE coding schemes lately, so this is a good time to get the patch issues addressed. -TT From alexander.chemeris at gmail.com Tue Apr 26 19:27:36 2016 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 26 Apr 2016 21:27:36 +0200 Subject: osmo-combo build script In-Reply-To: <20160426120420.GI14118@ass40.sysmocom.de> References: <20160426120420.GI14118@ass40.sysmocom.de> Message-ID: On Apr 26, 2016 2:04 PM, "Neels Hofmeyr" wrote: > > On Sat, Apr 23, 2016 at 06:35:42PM +0200, Alexander Chemeris wrote: > But, hold on, are you actually mirroring the osmo* source trees in that > repository? Makes it kind of hard to contribute back to upstream, right? > > I'd prefer to have just the Makefile, which (as a rainbow unicorn) could > also clone the git sources if not present... Not sure you can call it a unicorn, may be rather a gnucorn.. This script is using git submodules to "symlink" all dependencies. So subdirectories look like normal git repos and you can work with them individually, as well as perform batch operations. You can google details, but here are a couple links which come up on the top of my google search and have relevant information: https://chrisjean.com/git-submodules-adding-using-removing-and-updating/ http://stackoverflow.com/questions/5542910/how-do-i-commit-changes-in-a-git-submodule -- Regards, Alexander Chemeris CEO Fairwaves, Inc. https://fairwaves.co -------------- next part -------------- An HTML attachment was scrubbed... URL: From choukoumoun at gmail.com Wed Apr 27 17:10:11 2016 From: choukoumoun at gmail.com (Choukou Moun) Date: Wed, 27 Apr 2016 19:10:11 +0200 Subject: osmo-combo build script In-Reply-To: References: <20160426120420.GI14118@ass40.sysmocom.de> Message-ID: hello, What is the Linux distribution that you advocated for this script ? Thank you for the great job. 2016-04-26 21:27 GMT+02:00 Alexander Chemeris : > > On Apr 26, 2016 2:04 PM, "Neels Hofmeyr" wrote: > > > > On Sat, Apr 23, 2016 at 06:35:42PM +0200, Alexander Chemeris wrote: > > But, hold on, are you actually mirroring the osmo* source trees in that > > repository? Makes it kind of hard to contribute back to upstream, right? > > > > I'd prefer to have just the Makefile, which (as a rainbow unicorn) could > > also clone the git sources if not present... > > Not sure you can call it a unicorn, may be rather a gnucorn.. > > This script is using git submodules to "symlink" all dependencies. So > subdirectories look like normal git repos and you can work with them > individually, as well as perform batch operations. > > You can google details, but here are a couple links which come up on the > top of my google search and have relevant information: > https://chrisjean.com/git-submodules-adding-using-removing-and-updating/ > > http://stackoverflow.com/questions/5542910/how-do-i-commit-changes-in-a-git-submodule > > -- > Regards, > Alexander Chemeris > CEO Fairwaves, Inc. > https://fairwaves.co > -------------- next part -------------- An HTML attachment was scrubbed... URL: From msuraev at sysmocom.de Wed Apr 27 17:18:14 2016 From: msuraev at sysmocom.de (Max) Date: Wed, 27 Apr 2016 19:18:14 +0200 Subject: Half sided calls In-Reply-To: References: Message-ID: <5720F456.3050902@sysmocom.de> Thanks for looking into this. Some comments are inline. On 04/22/2016 01:40 PM, Pavel Balashov wrote: > Hello! > I can confirm a compatiblity issue with LibORTP >= 0.24.0. > > Here are some of my findings: > > In /osmo-bts/src/common/rsl.c in /rsl_rx_ipac_XXcx/ there is a call to > libosmo-abis function:/osmo_rtp_socket_bind(lchan->abis_ip.rtp_socket, > ipstr, -1)./ I assume, that last argument "-1" means that the random > udp port should be selected for socket. > > in /libosmo-abis/src/trau/osmo-rtp.c in a function /int > osmo_rtp_socket_bind(struct osmo_rtp_socket *rs, const char *ip, int > port)/ there is a call to LibORTP > /rtp_session_set_local_addr(rs->sess, ip, port, port+1)/. So as result > this function calls rtp_session_set_local_addr with last arguments > being equal to "-1" and "0". > / > /The LibORTP function///int rtp_session_set_local_addr (RtpSession * > session, const char * addr, int rtp_port, int rtcp_port)/ has a > folollowing description:/ > /** > *rtp_session_set_local_addr: > *@session: a rtp session freshly created. > *@addr: a local IP address in the xxx.xxx.xxx.xxx form. > *@rtp_port: a local port or -1 to let oRTP choose the port > randomly > *@rtcp_port: a local port or -1 to let oRTP choose the port > randomly > * > ... > **/ > > /So this results in calling////osmo_rtp_socket_bind/(...,-1) //-> > ///rtp_session_set_local_addr(...,-1,0) //what tries to bind rtp to > random udp port and rtcp to 0th udp port, but not to random port./ > /I guess that rtcp socket is never created regardless of LibORTP > version. (there are periodic osmo-ortp(): network_error osmo-bts log > messages due to ICMP port unreachable messages received, besides those > mentioned in https://osmocom.org/issues/1662). So I suppose the > correct code should check port value and either calling > /rtp_session_set_local_addr(rs->sess, ip, port, port+1) /if port >0 or > else > calling /rtp_session_set_local_addr(rs->sess, ip, port, port) /? > / > / Your're right. I've fixed that in max/ortp branch. Not yet in master because there seems to be more issues in play - I'm still unable to hear audio with ortp 0.25. The RTCP is not that important for our use-case - even if it fails (as indicated by ICMP messages) it should not affect actual voice in RTP streams. Anyway, I'll keep digging :) > //Also, after inspecting sources of LibORTP it seems that the > implementation//of /rtp_session_set_local_addr/ has changed for > LibORTP >= 0.24.0/./ As I understand the functionality of selecting a > random UDP port is broken. What makes you think that? I can see random UDP ports selected by oRTP just fine in my test setup. Do you see it in pcap trace? > What results is one way audio. Could you please share some more details on your test setup? Are you calling between 2 phones connected to the same BTS? Or using echo test? That 1-way audio you hear - which way does it come from? -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From alexander.chemeris at gmail.com Wed Apr 27 17:30:01 2016 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Wed, 27 Apr 2016 20:30:01 +0300 Subject: osmo-combo build script In-Reply-To: References: <20160426120420.GI14118@ass40.sysmocom.de> Message-ID: On Apr 27, 2016 20:10, "Choukou Moun" wrote: > > What is the Linux distribution that you advocated for this script ? I don't think it matters for the build script, but we've been testing it under Ubuntu 14.04 64-bit -- Regards, Alexander Chemeris CEO Fairwaves, Inc. https://fairwaves.co -------------- next part -------------- An HTML attachment was scrubbed... URL: From choukoumoun at gmail.com Wed Apr 27 19:16:33 2016 From: choukoumoun at gmail.com (Choukou Moun) Date: Wed, 27 Apr 2016 21:16:33 +0200 Subject: osmo-combo build script In-Reply-To: References: <20160426120420.GI14118@ass40.sysmocom.de> Message-ID: Ok. But i think your script doesn't install UHD and UMTRX/UHD lib and driver ? 2016-04-27 19:30 GMT+02:00 Alexander Chemeris : > > On Apr 27, 2016 20:10, "Choukou Moun" wrote: > > > > What is the Linux distribution that you advocated for this script ? > > I don't think it matters for the build script, but we've been testing it > under Ubuntu 14.04 64-bit > > -- > Regards, > Alexander Chemeris > CEO Fairwaves, Inc. > https://fairwaves.co > -------------- next part -------------- An HTML attachment was scrubbed... URL: From choukoumoun at gmail.com Wed Apr 27 20:24:48 2016 From: choukoumoun at gmail.com (Choukou Moun) Date: Wed, 27 Apr 2016 22:24:48 +0200 Subject: osmo-combo build script In-Reply-To: References: <20160426120420.GI14118@ass40.sysmocom.de> Message-ID: Its work Thank you Le 27 avr. 2016 21:16, "Choukou Moun" a ?crit : > Ok. > > But i think your script doesn't install UHD and UMTRX/UHD lib and driver ? > > > > 2016-04-27 19:30 GMT+02:00 Alexander Chemeris < > alexander.chemeris at gmail.com>: > >> >> On Apr 27, 2016 20:10, "Choukou Moun" wrote: >> > >> > What is the Linux distribution that you advocated for this script ? >> >> I don't think it matters for the build script, but we've been testing it >> under Ubuntu 14.04 64-bit >> >> -- >> Regards, >> Alexander Chemeris >> CEO Fairwaves, Inc. >> https://fairwaves.co >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexander.chemeris at gmail.com Wed Apr 27 20:30:33 2016 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Wed, 27 Apr 2016 23:30:33 +0300 Subject: osmo-combo build script In-Reply-To: References: <20160426120420.GI14118@ass40.sysmocom.de> Message-ID: On Wed, Apr 27, 2016 at 10:16 PM, Choukou Moun wrote: > But i think your script doesn't install UHD and UMTRX/UHD lib and driver ? The script doesn't install any dependencies - it only build Osmocom part of things. This is mentioned in the README. -- Regards, Alexander Chemeris. CEO, Fairwaves, Inc. https://fairwaves.co From nhofmeyr at sysmocom.de Thu Apr 28 11:27:11 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 28 Apr 2016 13:27:11 +0200 Subject: [PATCH 1/4] gprs_gmm: ensure llme present upon Attach Req (CID #57686) In-Reply-To: <0BDD2D53-668C-4133-B794-AE9065486337@freyther.de> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> <1460640093-22167-2-git-send-email-nhofmeyr@sysmocom.de> <80CFD1F8-469C-4224-8194-DB95432DFF8B@freyther.de> <20160425105119.GA2425@dub6> <0BDD2D53-668C-4133-B794-AE9065486337@freyther.de> Message-ID: <20160428112711.GF2164@ass40.sysmocom.de> On Mon, Apr 25, 2016 at 08:35:39PM +0200, Holger Freyther wrote: > > > On 25 Apr 2016, at 12:51, Neels Hofmeyr wrote: > > > >> > > > > There is, obviously, an explicit NULL on the sysmocom/iu branch, where no LLME > > is applicable. > > > > openbsc/openbsc/src/gprs/gprs_gmm.c:2462: rc = gsm0408_rcv_gmm(mmctx, msg, NULL); > > > > when looking at the patch I thought you would be on master. IIUC the coverity build uses the iu branches? But right, I submitted the patch against master, while on the iu branches I would normally just commit. So, a mixup from my side, sorry! I'm still glad you found this issue; I do in general highly esteem your reviews, pretty much always of pinnacle quality in an amazingly short time. Kudos! > So yes, for your Iu branch add the NULL check, once we merge to master we need to see if there is valuable information inside the llme that we need to store somewhere else/or just log it. My guess is that for Iu subscriptions, there will simply be no LLME, and there won't be information in an LLME that is NULL ;) But agreed. The merge-Iu-to-master review will be ... extreme, probably. Daniel and I should at some point take a look at refactoring the commit sequence to group by semantics and iron out trial-and-error commits. But it won't happen without an A-interface, I guess, so it is quite far down the line at this point (unless we keep NITB somehow, which would probably also be a bit of work). ~Neels -- - Neels Hofmeyr http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Gesch?ftsf?hrer / Managing Directors: Holger Freyther, Harald Welte -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Thu Apr 28 11:43:54 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 28 Apr 2016 13:43:54 +0200 Subject: osmo-combo build script In-Reply-To: References: <20160426120420.GI14118@ass40.sysmocom.de> Message-ID: <20160428114354.GI2164@ass40.sysmocom.de> On Tue, Apr 26, 2016 at 09:27:36PM +0200, Alexander Chemeris wrote: > On Apr 26, 2016 2:04 PM, "Neels Hofmeyr" wrote: > > > > On Sat, Apr 23, 2016 at 06:35:42PM +0200, Alexander Chemeris wrote: > > But, hold on, are you actually mirroring the osmo* source trees in that > > repository? Makes it kind of hard to contribute back to upstream, right? > > > > I'd prefer to have just the Makefile, which (as a rainbow unicorn) could > > also clone the git sources if not present... > > Not sure you can call it a unicorn, may be rather a gnucorn.. LOL, a gnunicorn :) > This script is using git submodules to "symlink" all dependencies. So ah of course, thanks. In github's tree listing it's easy to assume that they are copies of the original git sources, but now I noticed the .gitmodules file... ...and I see that libosmocore and openbsc are in fact included from the fairwaves github repositories. I think this is worth a mention in the README file. I'll post a pull request when I get around to it... Thanks! ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Thu Apr 28 12:57:13 2016 From: laforge at gnumonks.org (Harald Welte) Date: Thu, 28 Apr 2016 14:57:13 +0200 Subject: proliferation of repositories + branches (Re: osmo-combo build script) In-Reply-To: <20160428114354.GI2164@ass40.sysmocom.de> References: <20160426120420.GI14118@ass40.sysmocom.de> <20160428114354.GI2164@ass40.sysmocom.de> Message-ID: <20160428125713.GU4035@nataraja> An unrelated note: On Thu, Apr 28, 2016 at 01:43:54PM +0200, Neels Hofmeyr wrote: > ...and I see that libosmocore and openbsc are in fact included from the > fairwaves github repositories. Can we please work together to skip further proliferation of branches, let alone repositories? This really troubles me. fairwaves have full commit access to the respective projects on git.osmocom.org, so I don't really think it is wise to further proliferate different repositories. The work should be focussed on merging and unifying the codebase, rather than further forking and confusing every single user and developer. We need one version of the code that works for everyone, particularly for core components like the libraries. Thanks for your attention. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Thu Apr 28 12:52:12 2016 From: laforge at gnumonks.org (Harald Welte) Date: Thu, 28 Apr 2016 14:52:12 +0200 Subject: Future of Iu branches (was Re: [PATCH 1/4] gprs_gmm: ensure llme present upon Attach Req) #57686) In-Reply-To: <20160428112711.GF2164@ass40.sysmocom.de> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> <1460640093-22167-2-git-send-email-nhofmeyr@sysmocom.de> <80CFD1F8-469C-4224-8194-DB95432DFF8B@freyther.de> <20160425105119.GA2425@dub6> <0BDD2D53-668C-4133-B794-AE9065486337@freyther.de> <20160428112711.GF2164@ass40.sysmocom.de> Message-ID: <20160428125212.GT4035@nataraja> Hi Neels, I'm a bit troubled by the following statements: On Thu, Apr 28, 2016 at 01:27:11PM +0200, Neels Hofmeyr wrote: > The merge-Iu-to-master review will be ... extreme, probably. Daniel and I > should at some point take a look at refactoring the commit sequence to > group by semantics and iron out trial-and-error commits. > > But it won't happen without an A-interface, I guess, so it is quite far > down the line at this point (unless we keep NITB somehow, which would > probably also be a bit of work). It was clearly not the intention to keep the code out of master for more than the time it takes to implement those features. So yes, very clearly, for the CS side the NITB has to stay intact after a merge of the Iu, until the A interface is implemented. So please don't think of this as something "far down the line". For the PS side, I don't see any reason at all why a merge to master should be postponed much longer (after it works end-to-end, with GSUP and external HLR). The newly-introduced libiu should be easy to add without any risk to break existing code. And the decisions about Gb vs. IuPS are all made at runtime when looking at the respective subscriber / mm_context. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From psb1979 at hotmail.com Thu Apr 28 13:50:01 2016 From: psb1979 at hotmail.com (Pavel Balashov) Date: Thu, 28 Apr 2016 13:50:01 +0000 Subject: Half sided calls In-Reply-To: <5720F456.3050902@sysmocom.de> References: <5720F456.3050902@sysmocom.de> Message-ID: Hello, Sorry for having kept silent for so long. I see how rtcp is not that important for this use-case - even if it fails. But this causes "osmo-ortp(): network_error" error messages which are confusing the user. Just my opinion. My statement about broken LibORTP was somewhat futile. Just a guess. I see that an 0.23.0 implementation of rtp_session_set_local_addr uses create_and_bind(addr,rtcp_port,&sockfamily,session->reuseaddr) if (rtp_port>0) and create_and_bind_random(addr,&sockfamily,&rtcp_port) elsewise. Whereas an 0.24.0+ implementation of rtp_session_set_local_addr differs significantly. Looks like there was an attempt to merge (?), maybe this functionality got lost in transition ? I am calling from cell phone to SIP phone via LCR+FreeSWITCH. The audio is heard on mobile but not on SIP phone. Regards, Pavel. On 04/27/2016 08:18 PM, Max wrote: Thanks for looking into this. Some comments are inline. On 04/22/2016 01:40 PM, Pavel Balashov wrote: Hello! I can confirm a compatiblity issue with LibORTP >= 0.24.0. Here are some of my findings: In /osmo-bts/src/common/rsl.c in /rsl_rx_ipac_XXcx/ there is a call to libosmo-abis function:/osmo_rtp_socket_bind(lchan->abis_ip.rtp_socket, ipstr, -1)./ I assume, that last argument "-1" means that the random udp port should be selected for socket. in /libosmo-abis/src/trau/osmo-rtp.c in a function /int osmo_rtp_socket_bind(struct osmo_rtp_socket *rs, const char *ip, int port)/ there is a call to LibORTP /rtp_session_set_local_addr(rs->sess, ip, port, port+1)/. So as result this function calls rtp_session_set_local_addr with last arguments being equal to "-1" and "0". / /The LibORTP function///int rtp_session_set_local_addr (RtpSession * session, const char * addr, int rtp_port, int rtcp_port)/ has a folollowing description:/ /** *rtp_session_set_local_addr: *@session: a rtp session freshly created. *@addr: a local IP address in the xxx.xxx.xxx.xxx form. *@rtp_port: a local port or -1 to let oRTP choose the port randomly *@rtcp_port: a local port or -1 to let oRTP choose the port randomly * ... **/ /So this results in calling////osmo_rtp_socket_bind/(...,-1) //-> ///rtp_session_set_local_addr(...,-1,0) //what tries to bind rtp to random udp port and rtcp to 0th udp port, but not to random port./ /I guess that rtcp socket is never created regardless of LibORTP version. (there are periodic osmo-ortp(): network_error osmo-bts log messages due to ICMP port unreachable messages received, besides those mentioned in https://osmocom.org/issues/1662). So I suppose the correct code should check port value and either calling /rtp_session_set_local_addr(rs->sess, ip, port, port+1) /if port >0 or else calling /rtp_session_set_local_addr(rs->sess, ip, port, port) /? / / Your're right. I've fixed that in max/ortp branch. Not yet in master because there seems to be more issues in play - I'm still unable to hear audio with ortp 0.25. The RTCP is not that important for our use-case - even if it fails (as indicated by ICMP messages) it should not affect actual voice in RTP streams. Anyway, I'll keep digging :) //Also, after inspecting sources of LibORTP it seems that the implementation//of /rtp_session_set_local_addr/ has changed for LibORTP >= 0.24.0/./ As I understand the functionality of selecting a random UDP port is broken. What makes you think that? I can see random UDP ports selected by oRTP just fine in my test setup. Do you see it in pcap trace? What results is one way audio. Could you please share some more details on your test setup? Are you calling between 2 phones connected to the same BTS? Or using echo test? That 1-way audio you hear - which way does it come from? -------------- next part -------------- An HTML attachment was scrubbed... URL: From Ivan.Kluchnikov at fairwaves.ru Thu Apr 28 15:18:14 2016 From: Ivan.Kluchnikov at fairwaves.ru (Ivan Kluchnikov) Date: Thu, 28 Apr 2016 18:18:14 +0300 Subject: OsmoNITB async HLR/VLR Message-ID: Dear Harald, I want to discuss this topic in mailing list, because I think we should coordinate our efforts when we work on the same part of project. As I found out from Alex, several important points were discussed at osmodevcon: * reuse gsup protocol for implementing location and authentication interface for osmo-nitb * get rid of using internal osmo-nitb database and use only subscriber list on osmo-nitb side Could you please confirm and/or enhance this list? I see that you moved all gsup related code from openbsc to libosmocore in laforge/pending branches. Do you have any further plans to continue this development? As you know, we implemented interface based on gsup for exporting LU from osmo-nitb (fairwaves/sup branch), but in our implementation we didn't get rid of using internal database. Despite this I guess that our code could be updated and reused for this implementation. -- Regards, Ivan Kluchnikov. http://fairwaves.ru -------------- next part -------------- An HTML attachment was scrubbed... URL: From suraev at alumni.ntnu.no Thu Apr 28 15:51:14 2016 From: suraev at alumni.ntnu.no (suraev at alumni.ntnu.no) Date: Thu, 28 Apr 2016 17:51:14 +0200 Subject: [PATCH 1/2] Adjust si2quater ranges Message-ID: <1461858675-6510-1-git-send-email-suraev@alumni.ntnu.no> From: Max Change ranges of arguments for si2quater neighbor lists to more convenient values. --- openbsc/src/libbsc/bsc_vty.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index e81308b..b928738 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2766,9 +2766,10 @@ DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd, return CMD_SUCCESS; } + DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, - "si2quater neighbor-list add earfcn <1900-2200> threshold <0-1000> " - "[<0-255>]", "SI2quater Neighbor List\n" + "si2quater neighbor-list add earfcn <0-65535> threshold <0-31> " + "[<0-7>]", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" "EARFCN of neighbor\n" "EARFCN of neighbor\n" "threshold high bits\n" "threshold high bits\n" "measurement bandwidth\n") @@ -2805,7 +2806,7 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, } DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, - "si2quater neighbor-list del earfcn <1900-2200>", + "si2quater neighbor-list del earfcn <0-65535>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" @@ -2826,7 +2827,7 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, } DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, - "si2quater neighbor-list add uarfcn <1900-2200> <0-511> <0-1>", + "si2quater neighbor-list add uarfcn <0-16383> <0-511> <0-1>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" "UARFCN of neighbor\n" "UARFCN of neighbor\n" "scrambling code\n" @@ -2852,7 +2853,7 @@ DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, } DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd, - "si2quater neighbor-list del uarfcn <1900-2200> <0-511>", + "si2quater neighbor-list del uarfcn <0-16383> <0-511>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" -- 2.7.4 From suraev at alumni.ntnu.no Thu Apr 28 15:51:15 2016 From: suraev at alumni.ntnu.no (suraev at alumni.ntnu.no) Date: Thu, 28 Apr 2016 17:51:15 +0200 Subject: [PATCH 2/2] Fix comment typo In-Reply-To: <1461858675-6510-1-git-send-email-suraev@alumni.ntnu.no> References: <1461858675-6510-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: <1461858675-6510-2-git-send-email-suraev@alumni.ntnu.no> From: Max --- openbsc/src/libbsc/system_information.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 3b0f889..0d96621 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -68,7 +68,7 @@ static int is_dcs_net(const struct gsm_bts *bts) return 1; } -/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */ +/* Return p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */ unsigned range1024_p(unsigned n) { switch (n) { -- 2.7.4 From laforge at gnumonks.org Thu Apr 28 16:11:30 2016 From: laforge at gnumonks.org (Harald Welte) Date: Thu, 28 Apr 2016 18:11:30 +0200 Subject: [PATCH 1/2] Adjust si2quater ranges In-Reply-To: <1461858675-6510-1-git-send-email-suraev@alumni.ntnu.no> References: <1461858675-6510-1-git-send-email-suraev@alumni.ntnu.no> Message-ID: <20160428161129.GA4035@nataraja> Hi Max, On Thu, Apr 28, 2016 at 05:51:14PM +0200, suraev at alumni.ntnu.no wrote: > Change ranges of arguments for si2quater neighbor lists to more > convenient values. this commit is not about 'convenience' but about 'correctness in terms of the ranges permitted for the respective values under the applicable 3GPP specification'. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Thu Apr 28 19:24:31 2016 From: laforge at gnumonks.org (Harald Welte) Date: Thu, 28 Apr 2016 21:24:31 +0200 Subject: OsmoNITB async HLR/VLR In-Reply-To: References: Message-ID: <20160428192431.GN4035@nataraja> Hi Ivan, On Thu, Apr 28, 2016 at 06:18:14PM +0300, Ivan Kluchnikov wrote: > I want to discuss this topic in mailing list, because I think we should > coordinate our efforts when we work on the same part of project. sure. > As I found out from Alex, several important points were discussed at > osmodevcon: > * reuse gsup protocol for implementing location and authentication > interface for osmo-nitb > * get rid of using internal osmo-nitb database and use only subscriber list > on osmo-nitb side this is correct. > Could you please confirm and/or enhance this list? The goals of my current work are as follows: 1) get rid of synchronous database access from OsmoNITB, which can cause various problems in loaded setups, or with slow disk: http://projects.osmocom.org/issues/1592 2) get rid of libdbi, which is buggy and slow: http://projects.osmocom.org/issues/1591 3) improve concurrent accesses to the database http://projects.osmocom.org/issues/30 4) UMTS AKA support (can be used over 2G) http://projects.osmocom.org/issues/1593 At the same time, I aim for reducing code differences and code duplication between the "VLR part" that is effectively inside both the OsmoNITB/CSCN as well as OsmoSGSN. So basically, SGSN, NITB and CSCN should all link + use a new "libvlr", which includes the GSUP client and takes care of SendAuthInfo/UpdateLocation/InsertSubscriberData on the MSC/SGSN. > I see that you moved all gsup related code from openbsc to libosmocore in > laforge/pending branches. correct. > Do you have any further plans to continue this development? yes, I'm working on it every day since just before OsmoDevCon. > As you know, we implemented interface based on gsup for exporting LU from > osmo-nitb (fairwaves/sup branch), but in our implementation we didn't get > rid of using internal database. Unfortunately there are many features in some branches that have never been pushed to the mailing list for review. As a result, it is hard to know what is going on, and also not clear in which status certain code is. Yes, there's the commitlog mailing list, but that doesn't answer the question about the status of the code :/ > Despite this I guess that our code could be updated and reused for this > implementation. This would indeed be great. So far, my work has been focussing on: * moving GSUP message parsing to libosmocore * extending GSUP with code for UMTS AKA * removing openbsc dependency from GSUP client code * implementing GSUP server code * using GSUP server code to implement minimal osmo-gsup-hlr (for historic reasons still in osmo-auc.git, will probbably be moved eventually). AUC part (SendAuthInfo) has been implemented for 2G+3G, UpdateLocation, UpdateLocationGPRS and InsertSubscriberData is still pending. So as you can see, this is so far completely outside the NITB, so I haven't yet touched that side. If you can propose a set of changes that removes the existing related code in the NITB and introduces the asynchronous-ness of the thre relevant operations, I would appreciate that. Also, any patches related to unification between the 'VLR-like' functionality on NITB and CSCN would be appreciated. If you have any modifications/improvements on the GSUP protocol or related encode/decode/client functions, please also send them by all means. Thanks! Regards, Harlad -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From alexander.chemeris at gmail.com Thu Apr 28 20:31:12 2016 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Thu, 28 Apr 2016 23:31:12 +0300 Subject: proliferation of repositories + branches (Re: osmo-combo build script) In-Reply-To: <20160428125713.GU4035@nataraja> References: <20160426120420.GI14118@ass40.sysmocom.de> <20160428114354.GI2164@ass40.sysmocom.de> <20160428125713.GU4035@nataraja> Message-ID: Hi Harald, On Thu, Apr 28, 2016 at 3:57 PM, Harald Welte wrote: > On Thu, Apr 28, 2016 at 01:43:54PM +0200, Neels Hofmeyr wrote: >> ...and I see that libosmocore and openbsc are in fact included from the >> fairwaves github repositories. > > fairwaves have full commit access to the respective projects on > git.osmocom.org, so I don't really think it is wise to further > proliferate different repositories. I was actually going to write that the only reason for this is historical. Sergey didn't have commit access originally and was doing development in our github clone. Now that he has commit access and branches are pushed to git.osmocom.org, there is no real reason to point to our github. I've updated the .gitmodules to point to git.osmocom.org. > The work should be focussed on merging and unifying the codebase, rather > than further forking and confusing every single user and developer. > > We need one version of the code that works for everyone, particularly > for core components like the libraries. I'm totally with you on this. -- Regards, Alexander Chemeris. CEO, Fairwaves, Inc. https://fairwaves.co From laforge at gnumonks.org Thu Apr 28 20:47:46 2016 From: laforge at gnumonks.org (Harald Welte) Date: Thu, 28 Apr 2016 22:47:46 +0200 Subject: proliferation of repositories + branches (Re: osmo-combo build script) In-Reply-To: References: <20160426120420.GI14118@ass40.sysmocom.de> <20160428114354.GI2164@ass40.sysmocom.de> <20160428125713.GU4035@nataraja> Message-ID: <20160428204746.GQ4035@nataraja> On Thu, Apr 28, 2016 at 11:31:12PM +0300, Alexander Chemeris wrote: > I've updated the .gitmodules to point to git.osmocom.org. thanks. > I'm totally with you on this. thanks, too. In terms of branches: What would also be useful is some consolidated overview about what kind of bugs/features/... are missing in master from the fairwave point of view, i.e. what prevents you from using master for each project where you're not using master. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From alexander.chemeris at gmail.com Fri Apr 29 07:12:20 2016 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 29 Apr 2016 10:12:20 +0300 Subject: proliferation of repositories + branches (Re: osmo-combo build script) In-Reply-To: <20160428204746.GQ4035@nataraja> References: <20160426120420.GI14118@ass40.sysmocom.de> <20160428114354.GI2164@ass40.sysmocom.de> <20160428125713.GU4035@nataraja> <20160428204746.GQ4035@nataraja> Message-ID: On Apr 29, 2016 9:15 AM, "Harald Welte" wrote: > > On Thu, Apr 28, 2016 at 11:31:12PM +0300, Alexander Chemeris wrote: > > In terms of branches: What would also be useful is some consolidated > overview about what kind of bugs/features/... are missing in master from > the fairwave point of view, i.e. what prevents you from using master for > each project where you're not using master. That is a good idea. Let me look into what we have on our branches. -- Regards, Alexander Chemeris CEO Fairwaves, Inc. https://fairwaves.co -------------- next part -------------- An HTML attachment was scrubbed... URL: From laforge at gnumonks.org Fri Apr 29 09:50:06 2016 From: laforge at gnumonks.org (Harald Welte) Date: Fri, 29 Apr 2016 11:50:06 +0200 Subject: GSUP design questions Message-ID: <20160429095006.GV4035@nataraja> Hi! I have some questions regarding GSUP design and current implementation in ordre to help me undestand the rationale behind some of the decisions. 1) why are the fields like msisdn, vlr address, hlr address,, sgsn address still in their encoded form as part of struct osmo_gsup_message? If there is a decoding/encoding function, why does it not go all the way? Would anyone object if I was to change this? 2) osmo_gsup_message conatains multiple fields + associated length fields. Wy not have a 'struct osmo_buflen { char *buf; size_t len }' which is re-used for all such fields that have buffer + length? Then the respective code for dealing with such types could be generalized and shared. 3) why is the INSERT SUBSCRIBER DATA ignored by the SGSN, but rather it seems to expect the subscribe data piggy-backed onto the LOCATION UPDATE RESULT? This seems to break the idea of staying as close as possible to the MAP level transactions while avoiding the encoding/decoding and underlying signalling protocol complexities. Thanks in advance. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From msuraev at sysmocom.de Fri Apr 29 10:39:34 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 29 Apr 2016 12:39:34 +0200 Subject: [PATCH 2/3] Fix RTCP port allocation In-Reply-To: <1461926375-18893-1-git-send-email-msuraev@sysmocom.de> References: <1461926375-18893-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1461926375-18893-2-git-send-email-msuraev@sysmocom.de> From: Max Force use of random RTCP port if random RTP port is used. Before port 0 could be selected for RTCP. --- src/trau/osmo_ortp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/trau/osmo_ortp.c b/src/trau/osmo_ortp.c index 22c5856..5ab5bf5 100644 --- a/src/trau/osmo_ortp.c +++ b/src/trau/osmo_ortp.c @@ -357,7 +357,8 @@ int osmo_rtp_socket_bind(struct osmo_rtp_socket *rs, const char *ip, int port) { int rc; #if HAVE_ORTP_021 - rc = rtp_session_set_local_addr(rs->sess, ip, port, port+1); + int rtcp = (-1 != port) ? port + 1 : -1; + rc = rtp_session_set_local_addr(rs->sess, ip, port, rtcp); #else rc = rtp_session_set_local_addr(rs->sess, ip, port); #endif -- 2.8.1 From msuraev at sysmocom.de Fri Apr 29 10:39:35 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 29 Apr 2016 12:39:35 +0200 Subject: [PATCH 3/3] Set connected mode after setting remote address In-Reply-To: <1461926375-18893-1-git-send-email-msuraev@sysmocom.de> References: <1461926375-18893-1-git-send-email-msuraev@sysmocom.de> Message-ID: <1461926375-18893-3-git-send-email-msuraev@sysmocom.de> From: Max ortp: according to oRTP documentation rtp_session_set_connected_mode() uses the address set by rtp_session_set_remote_addr() - move the function call accordingly. Fixes: OS#1661 --- src/trau/osmo_ortp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/trau/osmo_ortp.c b/src/trau/osmo_ortp.c index 5ab5bf5..3313798 100644 --- a/src/trau/osmo_ortp.c +++ b/src/trau/osmo_ortp.c @@ -390,16 +390,17 @@ int osmo_rtp_socket_connect(struct osmo_rtp_socket *rs, const char *ip, uint16_t "set remote %s:%u\n", ip, port); return 0; } + + rc = rtp_session_set_remote_addr(rs->sess, ip, port); + if (rc < 0) + return rc; + /* enable the use of connect() so later getsockname() will * actually return the IP address that was chosen for the local * sid of the connection */ rtp_session_set_connected_mode(rs->sess, 1); rs->flags &= ~OSMO_RTP_F_DISABLED; - rc = rtp_session_set_remote_addr(rs->sess, ip, port); - if (rc < 0) - return rc; - if (rs->flags & OSMO_RTP_F_POLL) return rc; else -- 2.8.1 From msuraev at sysmocom.de Fri Apr 29 10:39:33 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 29 Apr 2016 12:39:33 +0200 Subject: [PATCH 1/3] Do not send RTP to port 0 Message-ID: <1461926375-18893-1-git-send-email-msuraev@sysmocom.de> From: Max Previously it was possible to send RTP data to port 0. This produce multiple errors during the beginning of RTP transmission. To address this OSMO_RTP_F_DISABLED flag was introduced. It's set by default for all new RTP sessions. It can be manually unset after the call to osmo_rtp_socket_create(). When the flag is set it prevents transmission and reception of RTP frames for the session. The flag is unset automatically in osmo_rtp_socket_connect() when session is bound to non-zero remote port. Fixes: OS#1662 --- include/osmocom/trau/osmo_ortp.h | 1 + src/trau/osmo_ortp.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/osmocom/trau/osmo_ortp.h b/include/osmocom/trau/osmo_ortp.h index c02cca8..2ca9cfc 100644 --- a/include/osmocom/trau/osmo_ortp.h +++ b/include/osmocom/trau/osmo_ortp.h @@ -29,6 +29,7 @@ enum osmo_rtp_param { /*! \brief Flag to indicate the socket is in polling-only mode */ #define OSMO_RTP_F_POLL 0x0001 +#define OSMO_RTP_F_DISABLED 2 /*! \brief A structure representing one RTP socket */ struct osmo_rtp_socket { diff --git a/src/trau/osmo_ortp.c b/src/trau/osmo_ortp.c index 65ec269..22c5856 100644 --- a/src/trau/osmo_ortp.c +++ b/src/trau/osmo_ortp.c @@ -149,6 +149,8 @@ static void ortp_sig_cb_ts(RtpSession *rs, void *data) int osmo_rtp_socket_poll(struct osmo_rtp_socket *rs) { mblk_t *mblk; + if (rs->flags & OSMO_RTP_F_DISABLED) + return 0; mblk = rtp_session_recvm_with_ts(rs->sess, rs->rx_user_ts); if (mblk) { @@ -313,7 +315,7 @@ struct osmo_rtp_socket *osmo_rtp_socket_create(void *talloc_ctx, unsigned int fl if (!rs) return NULL; - rs->flags = flags; + rs->flags = OSMO_RTP_F_DISABLED | flags; rs->sess = rtp_session_new(RTP_SESSION_SENDRECV); if (!rs->sess) { talloc_free(rs); @@ -382,11 +384,16 @@ int osmo_rtp_socket_bind(struct osmo_rtp_socket *rs, const char *ip, int port) int osmo_rtp_socket_connect(struct osmo_rtp_socket *rs, const char *ip, uint16_t port) { int rc; - + if (!port) { + LOGP(DLMIB, LOGL_INFO, "osmo_rtp_socket_connect() refused to " + "set remote %s:%u\n", ip, port); + return 0; + } /* enable the use of connect() so later getsockname() will * actually return the IP address that was chosen for the local * sid of the connection */ rtp_session_set_connected_mode(rs->sess, 1); + rs->flags &= ~OSMO_RTP_F_DISABLED; rc = rtp_session_set_remote_addr(rs->sess, ip, port); if (rc < 0) @@ -411,6 +418,9 @@ int osmo_rtp_send_frame(struct osmo_rtp_socket *rs, const uint8_t *payload, mblk_t *mblk; int rc; + if (rs->flags & OSMO_RTP_F_DISABLED) + return 0; + mblk = rtp_session_create_packet(rs->sess, RTP_FIXED_HEADER_SIZE, payload, payload_len); if (!mblk) -- 2.8.1 From msuraev at sysmocom.de Fri Apr 29 10:51:31 2016 From: msuraev at sysmocom.de (msuraev at sysmocom.de) Date: Fri, 29 Apr 2016 12:51:31 +0200 Subject: [PATCH] Adjust si2quater ranges Message-ID: <1461927091-19956-1-git-send-email-msuraev@sysmocom.de> From: Max Change ranges of arguments for si2quater neighbor lists to proper values according to 3GPP spec. --- openbsc/src/libbsc/bsc_vty.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index e81308b..b928738 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2766,9 +2766,10 @@ DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd, return CMD_SUCCESS; } + DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, - "si2quater neighbor-list add earfcn <1900-2200> threshold <0-1000> " - "[<0-255>]", "SI2quater Neighbor List\n" + "si2quater neighbor-list add earfcn <0-65535> threshold <0-31> " + "[<0-7>]", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" "EARFCN of neighbor\n" "EARFCN of neighbor\n" "threshold high bits\n" "threshold high bits\n" "measurement bandwidth\n") @@ -2805,7 +2806,7 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, } DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, - "si2quater neighbor-list del earfcn <1900-2200>", + "si2quater neighbor-list del earfcn <0-65535>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" @@ -2826,7 +2827,7 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, } DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, - "si2quater neighbor-list add uarfcn <1900-2200> <0-511> <0-1>", + "si2quater neighbor-list add uarfcn <0-16383> <0-511> <0-1>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" "UARFCN of neighbor\n" "UARFCN of neighbor\n" "scrambling code\n" @@ -2852,7 +2853,7 @@ DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, } DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd, - "si2quater neighbor-list del uarfcn <1900-2200> <0-511>", + "si2quater neighbor-list del uarfcn <0-16383> <0-511>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" -- 2.8.1 From ivan.kluchnikov at fairwaves.co Fri Apr 29 10:57:05 2016 From: ivan.kluchnikov at fairwaves.co (Ivan Kluchnikov) Date: Fri, 29 Apr 2016 13:57:05 +0300 Subject: OsmoNITB async HLR/VLR In-Reply-To: <20160428192431.GN4035@nataraja> References: <20160428192431.GN4035@nataraja> Message-ID: Hi Harald, Thank you for detailed clarification. As I understood from your description, the following changes should be also implemented on osmo-nitb/osmo-sgsn side: * authentication policy handling will be moved from osmo-nitb/osmo-sgsn side to osmo-gsup-hlr * osmo-nitb/osmo-sgsn will not be able to work independently (without connection with osmo-gsup-hlr). Are these points correct? 2016-04-28 22:24 GMT+03:00 Harald Welte : > Hi Ivan, > > On Thu, Apr 28, 2016 at 06:18:14PM +0300, Ivan Kluchnikov wrote: > > I want to discuss this topic in mailing list, because I think we should > > coordinate our efforts when we work on the same part of project. > > sure. > > > As I found out from Alex, several important points were discussed at > > osmodevcon: > > * reuse gsup protocol for implementing location and authentication > > interface for osmo-nitb > > * get rid of using internal osmo-nitb database and use only subscriber > list > > on osmo-nitb side > > this is correct. > > > Could you please confirm and/or enhance this list? > > The goals of my current work are as follows: > > 1) get rid of synchronous database access from OsmoNITB, which can cause > various problems in loaded setups, or with slow disk: > http://projects.osmocom.org/issues/1592 > > 2) get rid of libdbi, which is buggy and slow: > http://projects.osmocom.org/issues/1591 > > 3) improve concurrent accesses to the database > http://projects.osmocom.org/issues/30 > > 4) UMTS AKA support (can be used over 2G) > http://projects.osmocom.org/issues/1593 > > At the same time, I aim for reducing code differences and code > duplication between the "VLR part" that is effectively inside both the > OsmoNITB/CSCN as well as OsmoSGSN. So basically, SGSN, NITB and CSCN > should all link + use a new "libvlr", which includes the GSUP client and > takes care of SendAuthInfo/UpdateLocation/InsertSubscriberData on the > MSC/SGSN. > > > I see that you moved all gsup related code from openbsc to libosmocore in > > laforge/pending branches. > > correct. > > > Do you have any further plans to continue this development? > > yes, I'm working on it every day since just before OsmoDevCon. > > > As you know, we implemented interface based on gsup for exporting LU from > > osmo-nitb (fairwaves/sup branch), but in our implementation we didn't get > > rid of using internal database. > > Unfortunately there are many features in some branches that have never > been pushed to the mailing list for review. As a result, it is hard to > know what is going on, and also not clear in which status certain code > is. Yes, there's the commitlog mailing list, but that doesn't answer > the question about the status of the code :/ > > > Despite this I guess that our code could be updated and reused for this > > implementation. > > This would indeed be great. > > So far, my work has been focussing on: > > * moving GSUP message parsing to libosmocore > * extending GSUP with code for UMTS AKA > * removing openbsc dependency from GSUP client code > * implementing GSUP server code > * using GSUP server code to implement minimal osmo-gsup-hlr (for historic > reasons still in osmo-auc.git, will probbably be moved eventually). > AUC part (SendAuthInfo) has been implemented for 2G+3G, > UpdateLocation, UpdateLocationGPRS and InsertSubscriberData is still > pending. > > So as you can see, this is so far completely outside the NITB, so I > haven't yet touched that side. If you can propose a set of changes that > removes the existing related code in the NITB and introduces the > asynchronous-ness of the thre relevant operations, I would appreciate > that. Also, any patches related to unification between the 'VLR-like' > functionality on NITB and CSCN would be appreciated. > > If you have any modifications/improvements on the GSUP protocol or > related encode/decode/client functions, please also send them by all > means. Thanks! > > Regards, > Harlad > > -- > - Harald Welte > http://laforge.gnumonks.org/ > > ============================================================================ > "Privacy in residential applications is a desirable marketing option." > (ETSI EN 300 175-7 Ch. > A6) > -------------- next part -------------- An HTML attachment was scrubbed... URL: From holger at freyther.de Fri Apr 29 11:57:31 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 29 Apr 2016 13:57:31 +0200 Subject: GSUP design questions In-Reply-To: <20160429095006.GV4035@nataraja> References: <20160429095006.GV4035@nataraja> Message-ID: <62866438-4C99-4A03-8394-5FF11EA7D102@freyther.de> > On 29 Apr 2016, at 11:50, Harald Welte wrote: > > Hi! > > > 1) why are the fields like msisdn, vlr address, hlr address,, sgsn > address still in their encoded form as part of struct > osmo_gsup_message? If there is a decoding/encoding function, why > does it not go all the way? Would anyone object if I was to change > this? I don't remember Jacob's reason but my first reaction is that when using these fields one needs them encoded and decoded at the same time (e.g. decode the vlr address, encode the number as GT in SCCP, but for MSISDN and MO-SMS one might just copy the encoded data). But right now I don't remember anything that prevents a "deep" decode for convenience. > > 2) osmo_gsup_message conatains multiple fields + associated length > fields. Wy not have a 'struct osmo_buflen { char *buf; size_t len }' > which is re-used for all such fields that have buffer + length? Then > the respective code for dealing with such types could be generalized > and shared. yes, makes sense to re-use this. > 3) why is the INSERT SUBSCRIBER DATA ignored by the SGSN, but rather it > seems to expect the subscribe data piggy-backed onto the LOCATION > UPDATE RESULT? This seems to break the idea of staying as close as > possible to the MAP level transactions while avoiding the > encoding/decoding and underlying signalling protocol complexities. The reason to piggy-back was that I wanted to make it easier for the SGSN to deal with multiple invocations of subscriber data and only be presented with the entire set at once. We can argue that by going from E1/SCCP to TCP we can avoid this layer7 segmentation. In spirit it aligns the protocol with the move to SIGTRAN. Not handling stand-alone ISD is a limitation that should be easy to fix as well. From holger at freyther.de Fri Apr 29 11:58:18 2016 From: holger at freyther.de (Holger Freyther) Date: Fri, 29 Apr 2016 13:58:18 +0200 Subject: [PATCH 1/3] Do not send RTP to port 0 In-Reply-To: <1461926375-18893-1-git-send-email-msuraev@sysmocom.de> References: <1461926375-18893-1-git-send-email-msuraev@sysmocom.de> Message-ID: <69C19DC9-1F0A-431B-B101-D5A852859039@freyther.de> > On 29 Apr 2016, at 12:39, msuraev at sysmocom.de wrote: > > From: Max > did you test: * sysmoBTS with old oRTP after your change? What was the result? holger From msuraev at sysmocom.de Fri Apr 29 12:37:12 2016 From: msuraev at sysmocom.de (Max) Date: Fri, 29 Apr 2016 14:37:12 +0200 Subject: [PATCH 1/3] Do not send RTP to port 0 In-Reply-To: <69C19DC9-1F0A-431B-B101-D5A852859039@freyther.de> References: <1461926375-18893-1-git-send-email-msuraev@sysmocom.de> <69C19DC9-1F0A-431B-B101-D5A852859039@freyther.de> Message-ID: <57235578.6030702@sysmocom.de> Yes, sure. The voice was working as expected. On 04/29/2016 01:58 PM, Holger Freyther wrote: >> On 29 Apr 2016, at 12:39, msuraev at sysmocom.de wrote: >> >> From: Max >> > did you test: > > * sysmoBTS with old oRTP after your change? What was the result? > > holger > -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From nhofmeyr at sysmocom.de Fri Apr 29 14:17:09 2016 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 29 Apr 2016 16:17:09 +0200 Subject: Future of Iu branches present upon Attach Req) #57686) In-Reply-To: <20160428125212.GT4035@nataraja> References: <1460640093-22167-1-git-send-email-nhofmeyr@sysmocom.de> <1460640093-22167-2-git-send-email-nhofmeyr@sysmocom.de> <80CFD1F8-469C-4224-8194-DB95432DFF8B@freyther.de> <20160425105119.GA2425@dub6> <0BDD2D53-668C-4133-B794-AE9065486337@freyther.de> <20160428112711.GF2164@ass40.sysmocom.de> <20160428125212.GT4035@nataraja> Message-ID: <20160429141709.GA5887@dub6> On Thu, Apr 28, 2016 at 02:52:12PM +0200, Harald Welte wrote: > It was clearly not the intention to keep the code out of master for more > than the time it takes to implement those features. > > So yes, very clearly, for the CS side the NITB has to stay intact after > a merge of the Iu, until the A interface is implemented. So please > don't think of this as something "far down the line". This is a very high level decision. So far the explicit goal was to replace CSCN's libbsc with a proper A interface. So instead of placing junctures to decide whether to use BSC land structures (like the bts pointer) or not, I removed BSC land references. The A-interface aim is more neat in the sense that we will have explicit junctures that can decide whether to send a given message to A or IuCS. This obviously removes some NITB direct-BSC-access features. OTOH, the NITB-with-IuCS would be more like the tightly connected MSC+BSC with an IuCS side channel "stuck to its side". It's then questionnable whether to remove the direct-BSC-access features at all. Implementing the A-interface is clearly more work before being able to merge. But if we are going to sacrifice NITB for an A-interface anyway, it would be overall less work to keep NITB and IuCS separate until A is done. Keeping the NITB requires some un-rewiring, talking about the changes to gsm_subscriber_connection and reverting a few clear cuts from the previous code paths that I so far have in the iu branch. Shouldn't be too much work really. However, to me, keeping the NITB along with IuCS does sound like a complete change of direction compared to the previous instructions you gave me, i.e. to go for an A. Either way is fine, but let's be clear on which is the goal! Thinkable would also be to have all three: IuCS, NITB and a future A interface. That is to a degree sacrificing the neat clarity of separating MSC and BSC for good, and it would be the non-UNIX style "Eierlegende Wollmilchsau" [1]. These are my thoughts on CS so far, I am happy to go whichever way the community prefers. Let's establish consensus on the goal/roadmap as soon as possible. My wish to review the branch diff so far is still valid and probably goes hand in hand with this decision. It might be good if I have a look at the key junctures in the code paths and send a report/overview to this list? > For the PS side, I don't see any reason at all why a merge to master > should be postponed much longer. Yes, of course depending on Daniel's opinion, this is a completely different thing and merging is less of a complex decision. ~Neels [1] https://en.wiktionary.org/wiki/eierlegende_Wollmilchsau -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From msuraev at sysmocom.de Fri Apr 29 14:21:03 2016 From: msuraev at sysmocom.de (Max) Date: Fri, 29 Apr 2016 16:21:03 +0200 Subject: Half sided calls In-Reply-To: References: <5720F456.3050902@sysmocom.de> Message-ID: <57236DCF.9080307@sysmocom.de> Thanks for your feedback. It should be fixed in libosmo-abis now. Let me know if it still doesn't work for you. On 04/28/2016 03:50 PM, Pavel Balashov wrote: > Hello, > > Sorry for having kept silent for so long. > I see how rtcp is not that important for this use-case - even if it > fails. But this causes "osmo-ortp(): network_error" error messages > which are confusing the user. Just my opinion. This one is not covered by the fix above so you'll occasionally will see icmp reports for rtcp messages. Feel free to open separate ticket at http://projects.osmocom.org/issues if you think this got to be fixed as well. > > My statement about broken LibORTP was somewhat futile. Just a guess. I > see that an 0.23.0 implementation of /rtp_session_set_local_addr/ > uses > /create_and_bind/(addr,rtcp_port,&sockfamily,session->reuseaddr) if > (rtp_port>0) and /create_and_bind_random/(addr,&sockfamily,&rtcp_port) > elsewise. Whereas an 0.24.0+ implementation of > /rtp_session_set_local_addr /differs significantly. Looks like there > was an attempt to merge (?), maybe this functionality got lost in > transition ? > > I am calling from cell phone to SIP phone via LCR+FreeSWITCH. The > audio is heard on mobile but not on SIP phone. > > > Regards, > Pavel. > > > > > On 04/27/2016 08:18 PM, Max wrote: >> Thanks for looking into this. Some comments are inline. >> >> On 04/22/2016 01:40 PM, Pavel Balashov wrote: >>> Hello! >>> I can confirm a compatiblity issue with LibORTP >= 0.24.0. >>> >>> Here are some of my findings: >>> >>> In /osmo-bts/src/common/rsl.c in /rsl_rx_ipac_XXcx/ there is a call to >>> libosmo-abis function:/osmo_rtp_socket_bind(lchan->abis_ip.rtp_socket, >>> ipstr, -1)./ I assume, that last argument "-1" means that the random >>> udp port should be selected for socket. >>> >>> in /libosmo-abis/src/trau/osmo-rtp.c in a function /int >>> osmo_rtp_socket_bind(struct osmo_rtp_socket *rs, const char *ip, int >>> port)/ there is a call to LibORTP >>> /rtp_session_set_local_addr(rs->sess, ip, port, port+1)/. So as result >>> this function calls rtp_session_set_local_addr with last arguments >>> being equal to "-1" and "0". >>> / >>> /The LibORTP function///int rtp_session_set_local_addr (RtpSession * >>> session, const char * addr, int rtp_port, int rtcp_port)/ has a >>> folollowing description:/ >>> /** >>> *rtp_session_set_local_addr: >>> *@session: a rtp session freshly created. >>> *@addr: a local IP address in the xxx.xxx.xxx.xxx form. >>> *@rtp_port: a local port or -1 to let oRTP choose the port >>> randomly >>> *@rtcp_port: a local port or -1 to let oRTP choose the port >>> randomly >>> * >>> ... >>> **/ >>> >>> /So this results in calling////osmo_rtp_socket_bind/(...,-1) //-> >>> ///rtp_session_set_local_addr(...,-1,0) //what tries to bind rtp to >>> random udp port and rtcp to 0th udp port, but not to random port./ >>> /I guess that rtcp socket is never created regardless of LibORTP >>> version. (there are periodic osmo-ortp(): network_error osmo-bts log >>> messages due to ICMP port unreachable messages received, besides those >>> mentioned in https://osmocom.org/issues/1662). So I suppose the >>> correct code should check port value and either calling >>> /rtp_session_set_local_addr(rs->sess, ip, port, port+1) /if port >0 or >>> else >>> calling /rtp_session_set_local_addr(rs->sess, ip, port, port) /? >>> / >>> / >> Your're right. I've fixed that in max/ortp branch. Not yet in master >> because there seems to be more issues in play - I'm still unable to hear >> audio with ortp 0.25. The RTCP is not that important for our use-case - >> even if it fails (as indicated by ICMP messages) it should not affect >> actual voice in RTP streams. Anyway, I'll keep digging :) >> >>> //Also, after inspecting sources of LibORTP it seems that the >>> implementation//of /rtp_session_set_local_addr/ has changed for >>> LibORTP >= 0.24.0/./ As I understand the functionality of selecting a >>> random UDP port is broken. >> What makes you think that? I can see random UDP ports selected by oRTP >> just fine in my test setup. Do you see it in pcap trace? >> >>> What results is one way audio. >> Could you please share some more details on your test setup? Are you >> calling between 2 phones connected to the same BTS? Or using echo test? >> That 1-way audio you hear - which way does it come from? >> > -- Max Suraev http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From robert.steve07 at gmail.com Sat Apr 30 07:38:09 2016 From: robert.steve07 at gmail.com (robert) Date: Sat, 30 Apr 2016 10:38:09 +0300 Subject: Running apps on Motorola automatically after power ON Message-ID: <8D2A0C67-CE8E-4358-AAEB-62AD2AF0C90C@gmail.com> Hi, Is there a way to have an application (ex: trx for calypso BTS) run over the motorola phone immediately after turning the phone ON. In other words, if I flash it to the firmware I want the phone start working as a BTS without having to select it manually from the menu. Best regards, Robert, From loay.razek at gmail.com Mon Apr 18 16:27:37 2016 From: loay.razek at gmail.com (loay abdelrazek) Date: Mon, 18 Apr 2016 12:27:37 -0400 Subject: osmo-nitb Message-ID: Dears, hope this finds you well, kiindly i need to know how to configure the GT and PC for the various simulated nodes in osmo-nitb as am testing some security scripts to simulate different roaming attacks using the MAP protocol appreciate your support best regards -------------- next part -------------- An HTML attachment was scrubbed... URL: