From zero-kelvin at gmx.de Sun Feb 3 20:50:49 2013 From: zero-kelvin at gmx.de (dexter) Date: Sun, 03 Feb 2013 21:50:49 +0100 Subject: Osmocom Berlin User Group meeting In-Reply-To: <20120818115942.GV29525@prithivi.gnumonks.org> References: <502d01a9.mirider@mirider.augusta.de> <20120818115942.GV29525@prithivi.gnumonks.org> Message-ID: <510ECDA9.6050009@gmx.de> Hi folks. This is the announcement for the next Osmocom Berlin meeting. Feb 6, 8pm @ CCC Berlin, Marienstr. 11, 10117 Berlin There is no formal presentation scheduled for this meeting. If you are interested to show up, feel free to do so. There is no registration required. The meeting is free as in "free beer", despite no actual free beer being around. Regards, Philipp Maier From zero-kelvin at gmx.de Tue Feb 19 18:08:42 2013 From: zero-kelvin at gmx.de (dexter) Date: Tue, 19 Feb 2013 19:08:42 +0100 Subject: Osmocom Berlin User Group meeting In-Reply-To: <20120818115942.GV29525@prithivi.gnumonks.org> References: <502d01a9.mirider@mirider.augusta.de> <20120818115942.GV29525@prithivi.gnumonks.org> Message-ID: <5123BFAA.4090602@gmx.de> Hi folks. This is the announcement for the next Osmocom Berlin meeting. Feb 20, 8pm @ CCC Berlin, Marienstr. 11, 10117 Berlin There is no formal presentation scheduled for this meeting. If you are interested to show up, feel free to do so. There is no registration required. The meeting is free as in "free beer", despite no actual free beer being around. Regards, Philipp Maier From holger at freyther.de Tue Feb 5 20:03:22 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 5 Feb 2013 21:03:22 +0100 Subject: Please review the osmo-bts zecke/request-queuing branch Message-ID: <20130205200322.GA29421@xiaoyu.lan> Hi LaF0rge, all, please review the zecke/request-queuing branch up to commit 18d42b6845f22131a. I would like to get this part of my patch series merged. The code begins to remove the data pointer for the l1if_gsm_req_compl call and will alaways pass the trx to the callback. The lchan is found through the hLayer3 pointer. holger From andreas at eversberg.eu Thu Feb 7 10:58:14 2013 From: andreas at eversberg.eu (jolly) Date: Thu, 07 Feb 2013 11:58:14 +0100 Subject: Fix of IMMIDIATE ASSIGNMENT REJECT Message-ID: <511388C6.9030301@eversberg.eu> hi, this patch fixes the IMMIDIATE ASSIGNMENT REJECT message of OpenBSC. it is tested and works. regards, andreas -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: 0001-Fix-of-IMMIDIATE-ASSIGNMENT-REJECT-message.patch URL: From jolly at eversberg.eu Thu Feb 7 10:51:16 2013 From: jolly at eversberg.eu (Andreas Eversberg) Date: Thu, 7 Feb 2013 11:51:16 +0100 Subject: [PATCH] Fix of IMMIDIATE ASSIGNMENT REJECT message Message-ID: The message was corrupt at several points. They are fixed now and successfully tested. A default T3122 timer value of 10 is defined by default now. If set to 0, the reject message will not be sent. Note that when using existing configs with T3122 value set to 0. --- openbsc/include/openbsc/gsm_data.h | 1 + openbsc/src/libbsc/abis_rsl.c | 7 +++++-- openbsc/src/libcommon/gsm_data.c | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index feb692f..a4c6fbc 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -192,6 +192,7 @@ enum gsm_auth_policy { #define GSM_T3101_DEFAULT 10 #define GSM_T3105_DEFAULT 40 #define GSM_T3113_DEFAULT 60 +#define GSM_T3122_DEFAULT 10 struct gsm_network { /* global parameters */ diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 03ad8da..8aa151b 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -1295,7 +1295,7 @@ static int rsl_send_imm_ass_rej(struct gsm_bts *bts, /* create IMMEDIATE ASSIGN REJECT 04.08 message */ memset(iar, 0, sizeof(*iar)); iar->proto_discr = GSM48_PDISC_RR; - iar->msg_type = GSM48_MT_RR_IMM_ASS; + iar->msg_type = GSM48_MT_RR_IMM_ASS_REJ; iar->page_mode = GSM48_PM_SAME; memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1)); @@ -1319,7 +1319,10 @@ static int rsl_send_imm_ass_rej(struct gsm_bts *bts, memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4)); iar->wait_ind4 = wait_ind; - return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar); + /* we need to subtract 1 byte from sizeof(*iar) since ia includes the l2_plen field */ + iar->l2_plen = GSM48_LEN2PLEN((sizeof(*iar)-1)); + + return rsl_imm_assign_cmd(bts, sizeof(*iar), (uint8_t *) iar); } /* MS has requested a channel on the RACH */ diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index c9f41fc..dd1d93b 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -97,6 +97,7 @@ struct gsm_network *gsm_network_init(uint16_t country_code, uint16_t network_cod net->T3101 = GSM_T3101_DEFAULT; net->T3105 = GSM_T3105_DEFAULT; net->T3113 = GSM_T3113_DEFAULT; + net->T3122 = GSM_T3122_DEFAULT; /* FIXME: initialize all other timers! */ /* default set of handover parameters */ -- 1.7.3.4 --------------050108030306090500080205-- From holger at freyther.de Thu Feb 7 14:46:19 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 7 Feb 2013 15:46:19 +0100 Subject: Fix of IMMIDIATE ASSIGNMENT REJECT In-Reply-To: <511388C6.9030301@eversberg.eu> References: <511388C6.9030301@eversberg.eu> Message-ID: <20130207144619.GL27288@xiaoyu.lan> On Thu, Feb 07, 2013 at 11:58:14AM +0100, jolly wrote: > this patch fixes the IMMIDIATE ASSIGNMENT REJECT message of OpenBSC. it > is tested and works. what and how was it tested? But yes, it is pretty obvious that the reject is message was wrong. thanks for spotting it. > A default T3122 timer value of 10 is defined by default now. If set to 0, > the reject message will not be sent. Note that when using existing configs > with T3122 value set to 0. What I have done in the past is to update the example configuration files. Could you please do that? From andreas at eversberg.eu Thu Feb 7 15:32:54 2013 From: andreas at eversberg.eu (jolly) Date: Thu, 07 Feb 2013 16:32:54 +0100 Subject: Fix of IMMIDIATE ASSIGNMENT REJECT In-Reply-To: <20130207144619.GL27288@xiaoyu.lan> References: <511388C6.9030301@eversberg.eu> <20130207144619.GL27288@xiaoyu.lan> Message-ID: <5113C926.40703@eversberg.eu> Holger Hans Peter Freyther wrote: > what and how was it tested? But yes, it is pretty obvious that the reject > is message was wrong. thanks for spotting it. i used a bts with only one singe timeslot for BCCH+SDCCH4 :) i tried to make a call and the phone got a reject, so it waits 10 seconds (as defined in my local config) until it tried again. (as the specs say) > What I have done in the past is to update the example configuration files. > Could you please do that? > i checked the only example configuration file in osmo-nitb directory. it does not have t3122 defined, so the default value of 10 is used. i would suggest to remove default values from configuration files anyway, so a fix of a default value must not be done to the configuration file too. From holger at freyther.de Thu Feb 7 16:46:49 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 7 Feb 2013 17:46:49 +0100 Subject: Fix of IMMIDIATE ASSIGNMENT REJECT In-Reply-To: <5113C926.40703@eversberg.eu> References: <511388C6.9030301@eversberg.eu> <20130207144619.GL27288@xiaoyu.lan> <5113C926.40703@eversberg.eu> Message-ID: <20130207164649.GN27288@xiaoyu.lan> On Thu, Feb 07, 2013 at 04:32:54PM +0100, jolly wrote: > i checked the only example configuration file in osmo-nitb directory. it > does not have t3122 defined, so the default value of 10 is used. i would > suggest to remove default values from configuration files anyway, so a > fix of a default value must not be done to the configuration file too. that is a good idea, please go ahead. I had the same issue when introducing the timeout for the SACCH deactivation/release indication. From laforge at gnumonks.org Fri Feb 8 07:26:02 2013 From: laforge at gnumonks.org (Harald Welte) Date: Fri, 8 Feb 2013 08:26:02 +0100 Subject: Fix of IMMIDIATE ASSIGNMENT REJECT In-Reply-To: <511388C6.9030301@eversberg.eu> References: <511388C6.9030301@eversberg.eu> Message-ID: <20130208072602.GX21324@prithivi.gnumonks.org> Hi Jolly, On Thu, Feb 07, 2013 at 11:58:14AM +0100, jolly wrote: > this patch fixes the IMMIDIATE ASSIGNMENT REJECT message of OpenBSC. it > is tested and works. thaks, I've merged it now that there was no issue about the timer / default configuration files anymore. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From sega at unix.lv Thu Feb 7 17:22:43 2013 From: sega at unix.lv (Sergei Oleinikov) Date: Thu, 07 Feb 2013 19:22:43 +0200 Subject: nanoBTS for sale Message-ID: <1360257763.10268.10.camel@segamza> Hi All, maybe somebody is selling nanoBTS ? I'm from Latvia (Riga). Please send to sega at unix.lv Br, Sergei -------------- next part -------------- An HTML attachment was scrubbed... URL: From laforge at gnumonks.org Sun Feb 10 06:46:10 2013 From: laforge at gnumonks.org (Harald Welte) Date: Sun, 10 Feb 2013 07:46:10 +0100 Subject: libosmo-abis questions Message-ID: <20130210064610.GJ21324@prithivi.gnumonks.org> Hi Pablo, I am currently experimenting with porting osmo-bts over to libosmo-abis for the OML/RSL links. However, it seems that libosmo-abis might not be as complete as I was assuming. Maybe you have some ideas how to address the issue. As you probably know, upon start of the BTS only the OML link is established to the BSC. It is then via OML that the BSC instructs the BTS to establish a RSL link to a specified address. In the case of current OpenBSC, those IP addressee for OML and RSL are identical, but we cannot make that an assumption. Furthermore, in the case of a multi-TRX BTS, there will be one OML connection but multiplt RSL connections (one for each TRX). Those RSL connections will originate from different BTS hardware units. So far I've been using e1inp_ipa_bts_test.c as a template for the BTS side, but it seems that it * establishes OML and RSL at the same time, without waiting for the OML command to establish the RSL link * uses the same destination IP for OML and RSL without option for configuring this. Do you have any ideas how to best implement this? There is of course the option to bypass the entire e1inp_line / e1inp_sign_link abstraction and to use the ipa.c code directly (ipa_client_conn_create() and friends). But then I get only the multiplex without the andling of the ID_GET/ID_RESP/ID_ACK contained in ipaccess.c. 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 pablo at gnumonks.org Sun Feb 10 20:27:51 2013 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Sun, 10 Feb 2013 21:27:51 +0100 Subject: libosmo-abis questions In-Reply-To: <20130210064610.GJ21324@prithivi.gnumonks.org> References: <20130210064610.GJ21324@prithivi.gnumonks.org> Message-ID: <20130210202751.GA29134@localhost> Hi Harald, On Sun, Feb 10, 2013 at 07:46:10AM +0100, Harald Welte wrote: > Hi Pablo, > > I am currently experimenting with porting osmo-bts over to libosmo-abis > for the OML/RSL links. However, it seems that libosmo-abis might not be > as complete as I was assuming. Maybe you have some ideas how to address > the issue. > > As you probably know, upon start of the BTS only the OML link is > established to the BSC. It is then via OML that the BSC instructs the > BTS to establish a RSL link to a specified address. In the case of > current OpenBSC, those IP addressee for OML and RSL are identical, but > we cannot make that an assumption. > > Furthermore, in the case of a multi-TRX BTS, there will be one OML > connection but multiplt RSL connections (one for each TRX). Those RSL > connections will originate from different BTS hardware units. > > So far I've been using e1inp_ipa_bts_test.c as a template for the BTS > side, but it seems that it > * establishes OML and RSL at the same time, without waiting for the OML > command to establish the RSL link Just sent you a patch for this. What I'm proposing is that you call e1inp_line_update twice, once to get the OML link up and another to get the RSL link up. So you control when the RSL becomes up. The patch has been tested with the example templates. > * uses the same destination IP for OML and RSL without option for > configuring this. Hm, let me check this, will try to get back to you with anything asap. > Do you have any ideas how to best implement this? There is of course > the option to bypass the entire e1inp_line / e1inp_sign_link abstraction > and to use the ipa.c code directly (ipa_client_conn_create() and > friends). But then I get only the multiplex without the andling of the > ID_GET/ID_RESP/ID_ACK contained in ipaccess.c. Oh, I would be happy if you use that abstraction, let me try to fix it. If I fail to provide anything that you like, you can default on that, of course. Regards. From nikpakar at gmail.com Sun Feb 10 16:35:04 2013 From: nikpakar at gmail.com (Nik Pakar) Date: Sun, 10 Feb 2013 22:05:04 +0530 Subject: Using sip registrar for authentication Message-ID: Hello friends, Is there a way to use NITB/LCR alone with a sip registrar like freeswitch or yate and authenticate gsm user from sip registrar probably using the imsi as username ? Thanks for any feedback. Nik -------------- next part -------------- An HTML attachment was scrubbed... URL: From peter at stuge.se Sun Feb 10 17:13:18 2013 From: peter at stuge.se (Peter Stuge) Date: Sun, 10 Feb 2013 18:13:18 +0100 Subject: Using sip registrar for authentication In-Reply-To: References: Message-ID: <20130210171318.22045.qmail@stuge.se> Nik Pakar wrote: > Is there a way to use NITB/LCR alone with a sip registrar like > freeswitch or yate and authenticate gsm user from sip registrar > probably using the imsi as username ? No. If you have some ideas for how to use the secret then go on and implement it, and publish some code. //Peter From holger at freyther.de Sun Feb 10 17:35:44 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 10 Feb 2013 18:35:44 +0100 Subject: Using sip registrar for authentication In-Reply-To: References: Message-ID: <20130210173544.GL24522@xiaoyu.lan> On Sun, Feb 10, 2013 at 10:05:04PM +0530, Nik Pakar wrote: Hi, you had promised to edit the wiki. Have you done any editing so far? holger From pablo at gnumonks.org Sun Feb 10 20:23:59 2013 From: pablo at gnumonks.org (pablo at gnumonks.org) Date: Sun, 10 Feb 2013 21:23:59 +0100 Subject: [PATCH] ipaccess: bts: don't get OML and RSL links up at the same time Message-ID: <1360527839-29218-1-git-send-email-pablo@gnumonks.org> From: Pablo Neira Ayuso Harald reported that he needs that the RSL link becomes up once the OML link has been fully established, not both at the same time as it is currently happening. This patch changes the existing behaviour to control when the RSL link becomes up. Basically, you have to have to call e1inp_line_update once to get the OML link up. Then, once the OML link has been fully established, you call e1inp_line_update again to get the RSL link up. I have updates the examples files as well to adapt them to the new semantics. --- src/input/ipaccess.c | 141 ++++++++++++++++++++++++++++---------------- tests/e1inp_ipa_bts_test.c | 22 +++++-- 2 files changed, 107 insertions(+), 56 deletions(-) diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c index 5e76a09..b8c1e7a 100644 --- a/src/input/ipaccess.c +++ b/src/input/ipaccess.c @@ -894,8 +894,73 @@ err: return ret; } +static int ipaccess_bts_oml_link_up(struct e1inp_line *line) +{ + struct ipa_client_conn *link; + + link = ipa_client_conn_create(tall_ipa_ctx, + &line->ts[E1INP_SIGN_OML-1], + E1INP_SIGN_OML, + line->ops->cfg.ipa.addr, + IPA_TCP_PORT_OML, + NULL, + ipaccess_bts_cb, + ipaccess_bts_write_cb, + NULL); + if (link == NULL) { + LOGP(DLINP, LOGL_ERROR, "cannot create OML " + "BTS link: %s\n", strerror(errno)); + return -ENOMEM; + } + if (ipa_client_conn_open(link) < 0) { + LOGP(DLINP, LOGL_ERROR, "cannot open OML BTS link: %s\n", + strerror(errno)); + ipa_client_conn_close(link); + ipa_client_conn_destroy(link); + return -EIO; + } + + return 0; +} + +static int ipaccess_bts_rsl_link_up(struct e1inp_line *line) +{ + struct ipa_client_conn *rsl_link; + + rsl_link = ipa_client_conn_create(tall_ipa_ctx, + &line->ts[E1INP_SIGN_RSL-1], + E1INP_SIGN_RSL, + line->ops->cfg.ipa.addr, + IPA_TCP_PORT_RSL, + NULL, + ipaccess_bts_cb, + ipaccess_bts_write_cb, + NULL); + if (rsl_link == NULL) { + LOGP(DLINP, LOGL_ERROR, "cannot create RSL " + "BTS link: %s\n", strerror(errno)); + return -ENOMEM; + } + if (ipa_client_conn_open(rsl_link) < 0) { + LOGP(DLINP, LOGL_ERROR, "cannot open RSL BTS link: %s\n", + strerror(errno)); + ipa_client_conn_close(rsl_link); + ipa_client_conn_destroy(rsl_link); + return -EIO; + } + + return 0; +} + +enum ipaccess_line_state { + NONE, + OML_UP, + RSL_UP, + ALL_UP = RSL_UP, +}; + struct ipaccess_line { - int line_already_initialized; + enum ipaccess_line_state state; }; static int ipaccess_line_update(struct e1inp_line *line) @@ -913,11 +978,9 @@ static int ipaccess_line_update(struct e1inp_line *line) il = line->driver_data; /* We only initialize this line once. */ - if (il->line_already_initialized) + if (il->state == ALL_UP) return 0; - il->line_already_initialized = 1; - switch(line->ops->cfg.ipa.role) { case E1INP_LINE_R_BSC: { struct ipa_server_link *oml_link, *rsl_link; @@ -952,58 +1015,34 @@ static int ipaccess_line_update(struct e1inp_line *line) ipa_server_link_destroy(rsl_link); return -EIO; } + il->state = ALL_UP; ret = 0; break; } case E1INP_LINE_R_BTS: { - struct ipa_client_conn *link, *rsl_link; - - LOGP(DLINP, LOGL_NOTICE, "enabling ipaccess BTS mode\n"); - - link = ipa_client_conn_create(tall_ipa_ctx, - &line->ts[E1INP_SIGN_OML-1], - E1INP_SIGN_OML, - line->ops->cfg.ipa.addr, - IPA_TCP_PORT_OML, - NULL, - ipaccess_bts_cb, - ipaccess_bts_write_cb, - NULL); - if (link == NULL) { - LOGP(DLINP, LOGL_ERROR, "cannot create OML " - "BTS link: %s\n", strerror(errno)); - return -ENOMEM; - } - if (ipa_client_conn_open(link) < 0) { - LOGP(DLINP, LOGL_ERROR, "cannot open OML BTS link: %s\n", - strerror(errno)); - ipa_client_conn_close(link); - ipa_client_conn_destroy(link); - return -EIO; - } - rsl_link = ipa_client_conn_create(tall_ipa_ctx, - &line->ts[E1INP_SIGN_RSL-1], - E1INP_SIGN_RSL, - line->ops->cfg.ipa.addr, - IPA_TCP_PORT_RSL, - NULL, - ipaccess_bts_cb, - ipaccess_bts_write_cb, - NULL); - if (rsl_link == NULL) { - LOGP(DLINP, LOGL_ERROR, "cannot create RSL " - "BTS link: %s\n", strerror(errno)); - return -ENOMEM; - } - if (ipa_client_conn_open(rsl_link) < 0) { - LOGP(DLINP, LOGL_ERROR, "cannot open RSL BTS link: %s\n", - strerror(errno)); - ipa_client_conn_close(rsl_link); - ipa_client_conn_destroy(rsl_link); - return -EIO; - } - ret = 0; + /* The first call e1inp_line_update, this gets OML link up. + * Once the OML link has been fully established, you call + * e1inp_line_update again to get the RSL link up. + */ + switch(il->state) { + case NONE: + LOGP(DLINP, LOGL_NOTICE, "enabling ipaccess BTS mode\n"); + LOGP(DLINP, LOGL_NOTICE, "getting up OML link\n"); + ret = ipaccess_bts_oml_link_up(line); + il->state = OML_UP; + break; + case OML_UP: + LOGP(DLINP, LOGL_NOTICE, "getting up RSL link\n"); + ret = ipaccess_bts_rsl_link_up(line); + il->state = ALL_UP; + break; + default: + LOGP(DLINP, LOGL_ERROR, "ipaccess BTS links already " + "up and running\n"); + ret = -EBUSY; + break; break; + } } default: break; diff --git a/tests/e1inp_ipa_bts_test.c b/tests/e1inp_ipa_bts_test.c index 31aac95..112af65 100644 --- a/tests/e1inp_ipa_bts_test.c +++ b/tests/e1inp_ipa_bts_test.c @@ -57,8 +57,7 @@ sign_link_up(void *unit, struct e1inp_line *line, enum e1inp_sign_type type) if (!oml_sign_link) { LOGP(DBTSTEST, LOGL_ERROR, "cannot create OML sign link\n"); - } - if (oml_sign_link) { + } else { unsigned int event_type = 0; /* tell GSM 12.21 that we're ready via our eventfd. */ @@ -69,6 +68,20 @@ sign_link_up(void *unit, struct e1inp_line *line, enum e1inp_sign_type type) } /* Now we can send OML messages to the BSC. */ bts_state = BTS_TEST_OML_SIGN_LINK_UP; + + /* Well, way more OML messages actually happen before + * we can say that the OML link is fully established, + * but this is a test after all... + */ + LOGP(DBTSTEST, LOGL_NOTICE, "OML link is up.\n"); + + /* Next stage: get RSL link up. */ + if (e1inp_line_update(line) < 0) { + LOGP(DBTSTEST, LOGL_ERROR, "problem enabling " + "E1 line\n"); + exit(EXIT_FAILURE); + } + } break; case E1INP_SIGN_RSL: @@ -82,13 +95,12 @@ sign_link_up(void *unit, struct e1inp_line *line, enum e1inp_sign_type type) if (!rsl_sign_link) { LOGP(DBTSTEST, LOGL_ERROR, "cannot create RSL sign link\n"); - } + } else + LOGP(DBTSTEST, LOGL_NOTICE, "RSL link is up.\n"); break; default: return NULL; } - if (sign_link) - LOGP(DBTSTEST, LOGL_NOTICE, "signal link has been set up.\n"); return sign_link; } -- 1.7.10.4 From pablo at gnumonks.org Sun Feb 10 22:02:37 2013 From: pablo at gnumonks.org (pablo at gnumonks.org) Date: Sun, 10 Feb 2013 23:02:37 +0100 Subject: [PATCH 0/2] more updates to address existing ipa BTS limitations Message-ID: <1360533759-9511-1-git-send-email-pablo@gnumonks.org> From: Pablo Neira Ayuso Hi Harald, Please, review these patchset and let me know if this is enough to resolve the existing limitations that you found. Thanks. Pablo Neira Ayuso (2): ipaccess: bts: OML and RSL links may use different address bts: add E1INP_LINE_R_BTS_RSL_ONLY mode include/osmocom/abis/e1_input.h | 8 +++++++- src/input/hsl.c | 4 ++-- src/input/ipaccess.c | 19 +++++++++++++++++-- tests/e1inp_ipa_bts_test.c | 7 ++++++- 4 files changed, 32 insertions(+), 6 deletions(-) -- 1.7.10.4 From pablo at gnumonks.org Sun Feb 10 22:02:38 2013 From: pablo at gnumonks.org (pablo at gnumonks.org) Date: Sun, 10 Feb 2013 23:02:38 +0100 Subject: [PATCH 1/2] ipaccess: bts: OML and RSL links may use different address In-Reply-To: <1360533759-9511-1-git-send-email-pablo@gnumonks.org> References: <1360533759-9511-1-git-send-email-pablo@gnumonks.org> Message-ID: <1360533759-9511-2-git-send-email-pablo@gnumonks.org> From: Pablo Neira Ayuso This patch allows you to set different addresses for the OML and RSL links. You can set the RSL address anytime via line->ops->cfg.ipa.rsl.addr before the second call to e1inp_line_update() that brings the RSL link up. --- include/osmocom/abis/e1_input.h | 7 ++++++- src/input/hsl.c | 4 ++-- src/input/ipaccess.c | 4 ++-- tests/e1inp_ipa_bts_test.c | 7 ++++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/osmocom/abis/e1_input.h b/include/osmocom/abis/e1_input.h index 16e7f8b..fac7bac 100644 --- a/include/osmocom/abis/e1_input.h +++ b/include/osmocom/abis/e1_input.h @@ -140,8 +140,13 @@ struct e1inp_line_ops { union { struct { enum e1inp_line_role role; /* BSC or BTS mode. */ - const char *addr; /* IP address .*/ void *dev; /* device parameters. */ + struct { + const char *addr; /* IP address .*/ + } oml; + struct { + const char *addr; + } rsl; } ipa; struct { const char *port; /* e.g. /dev/ttyUSB0 */ diff --git a/src/input/hsl.c b/src/input/hsl.c index 1a60c2b..cfe7157 100644 --- a/src/input/hsl.c +++ b/src/input/hsl.c @@ -476,7 +476,7 @@ static int hsl_line_update(struct e1inp_line *line) LOGP(DLINP, LOGL_NOTICE, "enabling hsl BSC mode\n"); ret = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP, - line->ops->cfg.ipa.addr, + line->ops->cfg.ipa.oml.addr, HSL_TCP_PORT, OSMO_SOCK_F_BIND); if (ret < 0) return ret; @@ -499,7 +499,7 @@ static int hsl_line_update(struct e1inp_line *line) link = ipa_client_conn_create(tall_hsl_ctx, &line->ts[E1INP_SIGN_OML-1], E1INP_SIGN_OML, - line->ops->cfg.ipa.addr, + line->ops->cfg.ipa.oml.addr, HSL_TCP_PORT, hsl_bts_connect, hsl_bts_process, diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c index b8c1e7a..0fce15e 100644 --- a/src/input/ipaccess.c +++ b/src/input/ipaccess.c @@ -901,7 +901,7 @@ static int ipaccess_bts_oml_link_up(struct e1inp_line *line) link = ipa_client_conn_create(tall_ipa_ctx, &line->ts[E1INP_SIGN_OML-1], E1INP_SIGN_OML, - line->ops->cfg.ipa.addr, + line->ops->cfg.ipa.oml.addr, IPA_TCP_PORT_OML, NULL, ipaccess_bts_cb, @@ -930,7 +930,7 @@ static int ipaccess_bts_rsl_link_up(struct e1inp_line *line) rsl_link = ipa_client_conn_create(tall_ipa_ctx, &line->ts[E1INP_SIGN_RSL-1], E1INP_SIGN_RSL, - line->ops->cfg.ipa.addr, + line->ops->cfg.ipa.rsl.addr, IPA_TCP_PORT_RSL, NULL, ipaccess_bts_cb, diff --git a/tests/e1inp_ipa_bts_test.c b/tests/e1inp_ipa_bts_test.c index 112af65..46c6483 100644 --- a/tests/e1inp_ipa_bts_test.c +++ b/tests/e1inp_ipa_bts_test.c @@ -282,8 +282,13 @@ int main(void) .cfg = { .ipa = { .role = E1INP_LINE_R_BTS, - .addr = "127.0.0.1", .dev = &bts_dev_info, + .oml = { + .addr = "127.0.0.1", + }, + .rsl = { + .addr = "127.0.0.1", + }, }, }, .sign_link_up = sign_link_up, -- 1.7.10.4 From pablo at gnumonks.org Sun Feb 10 22:02:39 2013 From: pablo at gnumonks.org (pablo at gnumonks.org) Date: Sun, 10 Feb 2013 23:02:39 +0100 Subject: [PATCH 2/2] bts: add E1INP_LINE_R_BTS_RSL_ONLY mode In-Reply-To: <1360533759-9511-1-git-send-email-pablo@gnumonks.org> References: <1360533759-9511-1-git-send-email-pablo@gnumonks.org> Message-ID: <1360533759-9511-3-git-send-email-pablo@gnumonks.org> From: Pablo Neira Ayuso This patch adds the E1INP_LINE_R_BTS_RSL_ONLY that brings the RSL link without the OML link. This mode is useful for the multi-TRX BTS setup. --- include/osmocom/abis/e1_input.h | 1 + src/input/ipaccess.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/osmocom/abis/e1_input.h b/include/osmocom/abis/e1_input.h index fac7bac..037e353 100644 --- a/include/osmocom/abis/e1_input.h +++ b/include/osmocom/abis/e1_input.h @@ -123,6 +123,7 @@ enum e1inp_line_role { E1INP_LINE_R_NONE, E1INP_LINE_R_BSC, E1INP_LINE_R_BTS, + E1INP_LINE_R_BTS_RSL_ONLY, E1INP_LINE_R_MAX }; diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c index 0fce15e..0f995e7 100644 --- a/src/input/ipaccess.c +++ b/src/input/ipaccess.c @@ -1044,6 +1044,21 @@ static int ipaccess_line_update(struct e1inp_line *line) break; } } + case E1INP_LINE_R_BTS_RSL_ONLY: + switch(il->state) { + case NONE: + LOGP(DLINP, LOGL_NOTICE, "enabling ipaccess BTS mode " + "in RSL mode only\n"); + ret = ipaccess_bts_rsl_link_up(line); + il->state = ALL_UP; + break; + default: + LOGP(DLINP, LOGL_ERROR, "ipaccess BTS RSL link already " + "up and running\n"); + ret = -EBUSY; + break; + break; + } default: break; } -- 1.7.10.4 From admin at manateeshome.com Wed Feb 13 15:08:14 2013 From: admin at manateeshome.com (Pierre Kim) Date: Thu, 14 Feb 2013 00:08:14 +0900 Subject: OpenBSC LCR tutorial Message-ID: <30d701ce09fb$f34304e0$d9c90ea0$@manateeshome.com> hello, I've wrote a little tutorial on how to configure OpenBSC for use with LCR. Other docs I found were outdated so I decided to write one by myself. Please check the attachment. I hope someone would find it useful. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Building and Running OpenBSC with Asterisk__v1.0.pdf Type: application/pdf Size: 162533 bytes Desc: not available URL: From holger at freyther.de Wed Feb 13 15:51:25 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Wed, 13 Feb 2013 16:51:25 +0100 Subject: OpenBSC LCR tutorial In-Reply-To: <30d701ce09fb$f34304e0$d9c90ea0$@manateeshome.com> References: <30d701ce09fb$f34304e0$d9c90ea0$@manateeshome.com> Message-ID: <20130213155125.GA26641@xiaoyu.lan> On Thu, Feb 14, 2013 at 12:08:14AM +0900, Pierre Kim wrote: > hello, I've wrote a little tutorial on how to configure OpenBSC for use > with LCR. > > Other docs I found were outdated so I decided to write one by myself. Dear Pierre, thanks a lot. Would you be interested to update this information in the wiki? This way someone else can modify package names, versions, etc. without having to start from scratch. thanks holger From peter at stuge.se Wed Feb 13 17:58:00 2013 From: peter at stuge.se (Peter Stuge) Date: Wed, 13 Feb 2013 18:58:00 +0100 Subject: OpenBSC LCR tutorial In-Reply-To: <30d701ce09fb$f34304e0$d9c90ea0$@manateeshome.com> References: <30d701ce09fb$f34304e0$d9c90ea0$@manateeshome.com> Message-ID: <20130213175800.15955.qmail@stuge.se> Pierre Kim wrote: > hello, I've wrote a little tutorial on how to configure OpenBSC for > use with LCR. > > Other docs I found were outdated so I decided to write one by myself. These are useful instructions, although it is possible to make some simplifcations: * LCR can be built with SIP support to let a SIP interface talk to asterisk. * Neither mISDN nor mISDNuser is needed to build LCR with only GSM and SIP support. I will repeat Holger's request to please publish the document in some way that allows collaboration. A wiki page is a great idea, or you could publish the PDF source code using a version control system. Thanks! //Peter From kat.obsc at gmail.com Thu Feb 14 04:24:23 2013 From: kat.obsc at gmail.com (Katerina Barone-Adesi) Date: Thu, 14 Feb 2013 05:24:23 +0100 Subject: [PATCH] Added a ring buffer log target to store the last N log messages. Message-ID: The log target can be used via log alarms and show alarms. Why? This feature was proposed/requested at http://openbsc.osmocom.org/trac/wiki/Tasks/ErrorLogTarget All messages use the same amount of space, prioritizing simplicity. --- .gitignore | 2 + include/osmocom/core/logging.h | 5 + include/osmocom/core/loggingrb.h | 40 +++++++ include/osmocom/core/ringbuffer.h | 58 +++++++++ src/Makefile.am | 4 +- src/loggingrb.c | 98 +++++++++++++++ src/ringbuffer.c | 173 +++++++++++++++++++++++++++ src/vty/logging_vty.c | 85 ++++++++++++- tests/Makefile.am | 13 +- tests/loggingrb/logging_test.err | 3 + tests/loggingrb/loggingrb_test.c | 83 +++++++++++++ tests/ringbuffer/ringbuffer_test.c | 225 +++++++++++++++++++++++++++++++++++ tests/ringbuffer/ringbuffer_test.ok | 1 + tests/testsuite.at | 13 ++ 14 files changed, 795 insertions(+), 8 deletions(-) create mode 100644 include/osmocom/core/loggingrb.h create mode 100644 include/osmocom/core/ringbuffer.h create mode 100644 src/loggingrb.c create mode 100644 src/ringbuffer.c create mode 100644 tests/loggingrb/logging_test.err create mode 100644 tests/loggingrb/logging_test.ok create mode 100644 tests/loggingrb/loggingrb_test.c create mode 100644 tests/ringbuffer/ringbuffer_test.c create mode 100644 tests/ringbuffer/ringbuffer_test.ok diff --git a/.gitignore b/.gitignore index 24ca677..aedd9fd 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,8 @@ tests/gb/bssgp_fc_test tests/gsm0408/gsm0408_test tests/logging/logging_test tests/fr/fr_test +tests/loggingrb/loggingrb_test +tests/ringbuf/ringbuf_test utils/osmo-arfcn utils/osmo-auc-gen diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index 655f7a4..dc55d37 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -114,6 +114,7 @@ enum log_target_type { LOG_TGT_TYPE_SYSLOG, /*!< \brief syslog based logging */ LOG_TGT_TYPE_FILE, /*!< \brief text file logging */ LOG_TGT_TYPE_STDERR, /*!< \brief stderr logging */ + LOG_TGT_TYPE_RINGBUF, /*!< \brief ringbuffer-backed logging */ }; /*! \brief structure representing a logging target */ @@ -154,6 +155,10 @@ struct log_target { struct { void *vty; } tgt_vty; + + struct { + void *rb; + } tgt_rb; }; /*! \brief call-back function to be called when the logging framework diff --git a/include/osmocom/core/loggingrb.h b/include/osmocom/core/loggingrb.h new file mode 100644 index 0000000..a6f377b --- /dev/null +++ b/include/osmocom/core/loggingrb.h @@ -0,0 +1,40 @@ +#ifndef _LOGGINGRB_H +#define _LOGGINGRB_H + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + + +/*! \defgroup loggingrb Osmocom ringbuffer-backed logging + * @{ + */ + +/*! \file loggingrb.h + */ + +struct log_info; + +size_t log_target_rb_used_size(struct log_target const *target); +size_t log_target_rb_avail_size(struct log_target const *target); +const char *log_target_rb_get(struct log_target const *target, size_t logindex); +struct log_target *log_target_create_rb(size_t size); + +/*! @} */ + +#endif /* _LOGGINGRB_H */ diff --git a/include/osmocom/core/ringbuffer.h b/include/osmocom/core/ringbuffer.h new file mode 100644 index 0000000..7e16af7 --- /dev/null +++ b/include/osmocom/core/ringbuffer.h @@ -0,0 +1,58 @@ +#ifndef _RINGBUFFER_H +#define _RINGBUFFER_H + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + +/*! \defgroup ringbuffer Osmocom ringbuffers + * @{ + */ + +/*! \file ringbuffer.h + * \brief Osmocom ringbuffer handling routines + */ + +#include +#include +#include + +#include + +/*! \brief A structure representing a ringbuffer */ + +#define RB_MAX_MESSAGE_SIZE 240 +struct ringbuffer { + uint16_t start; /*!< \brief index of the first slot */ + uint16_t end; /*!< \brief index of the last slot */ + uint16_t size; /*!< \brief max number of messages to store */ + char **buffer; /*!< \brief storage for messages */ +}; + +struct ringbuffer *ringbuffer_create(TALLOC_CTX * ctx, size_t rb_size); +bool ringbuffer_is_empty(const struct ringbuffer *rb); +const char *ringbuffer_get_nth(const struct ringbuffer *rb, + unsigned int string_index); +bool _ringbuffer_is_bufindex_valid(const struct ringbuffer *rb, + unsigned int offset); +size_t ringbuffer_elements(const struct ringbuffer *rb); +int ringbuffer_add(struct ringbuffer *rb, const char *data); + +/*! @} */ + +#endif /* _RINGBUFFER_H */ diff --git a/src/Makefile.am b/src/Makefile.am index b425ea1..1a0f621 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,8 +11,8 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.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 \ - crc8gen.c crc16gen.c crc32gen.c crc64gen.c + conv.c application.c rbtree.c ringbuffer.c \ + loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c diff --git a/src/loggingrb.c b/src/loggingrb.c new file mode 100644 index 0000000..87cdddd --- /dev/null +++ b/src/loggingrb.c @@ -0,0 +1,98 @@ +/* Ringbuffer-backed logging support code */ + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + +/*! \addtogroup logging + * @{ + */ + +/*! \file loggingrb.c */ + +#include +#include +#include + +static void _rb_output(struct log_target *target, + unsigned int level, const char *log) +{ + ringbuffer_add(target->tgt_rb.rb, log); +} + +/*! \brief Return the number of log strings in the ringbuffer-backed target. + * \param[in] target The target to search. + * + * \return The number of log strings in the ringbuffer-backed target. + */ +size_t log_target_rb_used_size(struct log_target const *target) +{ + return ringbuffer_elements(target->tgt_rb.rb); +} + +/*! \brief Return the capacity of the ringbuffer-backed target. + * \param[in] target The target to search. + * + * Note that this is the capacity (aka max number of messages +1). + * It is not the number of unused message slots. + * \return The number of log strings in the ringbuffer-backed target. + */ +size_t log_target_rb_avail_size(struct log_target const *target) +{ + struct ringbuffer *rb = target->tgt_rb.rb; + return rb->size; +} + +/*! \brief Return the nth log entry in a target. + * \param[in] target The target to search. + * \param[in] logindex The index of the log entry/error message. + * + * \return A pointer to the nth message, or NULL if logindex is invalid. + */ +const char *log_target_rb_get(struct log_target const *target, size_t logindex) +{ + return ringbuffer_get_nth(target->tgt_rb.rb, logindex); +} + +/*! \brief Create a new logging target for ringbuffer logging. + * \param[in] size The size of the internal backing ringbuffer. + * \returns A log target in case of success, NULL in case of error. + */ +struct log_target *log_target_create_rb(size_t size) +{ + struct log_target *target; + struct ringbuffer *rb; + + target = log_target_create(); + if (!target) + return NULL; + + rb = ringbuffer_create(target, size); + if (!rb) { + log_target_destroy(target); + return NULL; + } + + target->tgt_rb.rb = rb; + target->type = LOG_TGT_TYPE_RINGBUF; + target->output = _rb_output; + + return target; +} + +/* @} */ diff --git a/src/ringbuffer.c b/src/ringbuffer.c new file mode 100644 index 0000000..3e882b1 --- /dev/null +++ b/src/ringbuffer.c @@ -0,0 +1,173 @@ +/* Ringbuffer implementation, tailored for logging. + * This is a lossy ringbuffer. It keeps up to N of the newest messages, + * overwriting the oldest as newer ones come in. + * + * (C) 2012-2013, Katerina Barone-Adesi + * 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. + * + */ + +/*! \file ringb.c + * \brief Lossy ringbuffer for logging; keeps newest messages. + */ + +#include +#include +#include + +#include + +/* Ringbuffer assumptions, invarients, and notes: + * - start is the index of the first used index slot in the ring buffer. + * - end is the index of the next index slot in the ring buffer. + * - start == end => buffer is empty + * - Consequence: the buffer can hold at most size - 1 messages + * (if this were not the case, full and empty buffers would be indistinguishable + * given the conventions in this implementation). + * - Whenever the ringbuffer is full, start is advanced. The second oldest + * message becomes unreachable by valid indexes (end is not a valid index) + * and the oldest message is overwritten (if there was a message there, which + * is the case unless this is the first time the ringbuffer becomes full). +*/ + +/*! \brief Create an empty, initialized ringbuffer. + * \param[in] ctx The talloc memory context which should own this. + * \param[in] rb_size The number of message slots in the ringbuffer. + * \returns A struct ringbuffer* on success, NULL in case of error. + * + * This function creates and initializes a ringbuffer. + * Note that the ringbuffer stores at most rb_size - 1 messages. + */ + +/* http://talloc.samba.org/talloc/doc/html/libtalloc__bestpractices.html + * recommends functions that return dynamically allocated values use this style + */ + +struct ringbuffer *ringbuffer_create(TALLOC_CTX * ctx, size_t rb_size) +{ + struct ringbuffer *rb = NULL; + unsigned int i; + + rb = talloc_zero(ctx, struct ringbuffer); + if (!rb) + goto alloc_error; + rb->buffer = talloc_array(rb, char *, rb_size); + if (!rb->buffer) + goto alloc_error; + for (i = 0; i < rb_size; i++) { + rb->buffer[i] = + talloc_zero_size(rb->buffer, RB_MAX_MESSAGE_SIZE); + if (!rb->buffer[i]) + goto alloc_error; + } + + /* start and end are zero already, which is correct */ + rb->size = rb_size; + return rb; + +alloc_error: /* talloc_free(NULL) is safe */ + talloc_free(rb); + return NULL; +} + +/*! \brief Check if a ringbuffer is empty. + * \param[in] rb The ringbuffer to check. + * \returns True if the buffer is empty, false otherwise. + */ +bool ringbuffer_is_empty(const struct ringbuffer *rb) +{ + return rb->end == rb->start; +} + +/*! \brief Return a pointer to the Nth string in the ringbuffer. + * \param[in] rb The ringbuffer to search. + * \param[in] string_index The index sought (N), zero-indexed. + * + * Return a pointer to the Nth string in the ringbuffer. + * Return NULL if there is no Nth string. + * Note that N is zero-indexed. + * \returns A pointer to the target string on success, NULL in case of error. + */ +const char *ringbuffer_get_nth(const struct ringbuffer *rb, + unsigned int string_index) +{ + unsigned int offset = string_index + rb->start; + + if ((offset >= rb->size) && (rb->start > rb->end)) + offset -= rb->size; + if (_ringbuffer_is_bufindex_valid(rb, offset)) + return rb->buffer[offset]; + + return NULL; +} + +bool _ringbuffer_is_bufindex_valid(const struct ringbuffer *rb, + unsigned int bufi) +{ + if (ringbuffer_is_empty(rb)) + return 0; + if ((bufi >= rb->size) || (bufi < 0)) + return 0; + if (rb->start < rb->end) + return (bufi >= rb->start) && (bufi < rb->end); + return (bufi < rb->end) || (bufi >= rb->start); +} + +/*! \brief Count the number of log messages in a ringbuffer. + * \param[in] rb The ringbuffer to count the elements of. + * + * \returns The number of log messages in the ringbuffer. + */ +size_t ringbuffer_elements(const struct ringbuffer *rb) +{ + if (rb->end < rb->start) + return rb->end + (rb->size - rb->start); + + return rb->end - rb->start; +} + +/*! \brief Add a string to the ringbuffer. + * \param[in] rb The ringbuffer to add to. + * \param[in] data The string to add. + * + * Add a message to the ring buffer. + * Older messages will be overwritten as necessary. + * \returns 0 normally, 1 as a warning (ie, if data was truncated). + */ +int ringbuffer_add(struct ringbuffer *rb, const char *data) +{ + size_t len = strlen(data); + int ret = 0; + + if (len >= RB_MAX_MESSAGE_SIZE) { + len = RB_MAX_MESSAGE_SIZE - 1; + ret = 1; + } + + memcpy(rb->buffer[rb->end], data, len); + rb->buffer[rb->end][len] = '\0'; + + rb->end += 1; + rb->end %= rb->size; + + /* The buffer is full; oldest message is forgotten - see notes above */ + if (rb->end == rb->start) { + rb->start += 1; + rb->start %= rb->size; + } + return ret; +} diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index d473f12..3051974 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -27,8 +27,8 @@ #include #include #include - -//#include +#include +#include #include #include @@ -252,8 +252,8 @@ static void vty_print_logtarget(struct vty *vty, const struct log_info *info, #define SHOW_LOG_STR "Show current logging configuration\n" DEFUN(show_logging_vty, - show_logging_vty_cmd, - "show logging vty", + show_logging_vty_cmd, + "show logging vty", SHOW_STR SHOW_LOG_STR "Show current logging configuration for this vty\n") { @@ -267,6 +267,33 @@ DEFUN(show_logging_vty, return CMD_SUCCESS; } +DEFUN(show_alarms, + show_alarms_cmd, + "show alarms", + SHOW_STR SHOW_LOG_STR + "Show the contents of the logging ringbuffer\n") +{ + int i, num_alarms; + struct ringbuffer *rb; + struct log_target *tgt = log_target_find(LOG_TGT_TYPE_RINGBUF, NULL); + if (!tgt) { + vty_out(vty, "%% No alarms, run 'log alarms <2-32767>'%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + rb = tgt->tgt_rb.rb; + num_alarms = ringbuffer_elements(rb); + + vty_out(vty, "%% Showing %i alarms%s", num_alarms, VTY_NEWLINE); + + for (i = 0; i < num_alarms; i++) + vty_out(vty, "%% %s%s", ringbuffer_get_nth(rb, i), + VTY_NEWLINE); + + return CMD_SUCCESS; +} + gDEFUN(cfg_description, cfg_description_cmd, "description .TEXT", "Save human-readable decription of the object\n" @@ -510,6 +537,49 @@ DEFUN(cfg_no_log_file, cfg_no_log_file_cmd, return CMD_SUCCESS; } +DEFUN(cfg_log_alarms, cfg_log_alarms_cmd, + "log alarms <2-32767>", + LOG_STR "Logging alarms to ringbuffer\n" + "Maximum number of messages to log (+1)\n") +{ + struct log_target *tgt; + unsigned int rbsize = atoi(argv[0]); + + tgt = log_target_find(LOG_TGT_TYPE_RINGBUF, NULL); + if (tgt) + log_target_destroy(tgt); + + tgt = log_target_create_rb(rbsize); + if (!tgt) { + vty_out(vty, "%% Unable to create ringbuffer (size %u)%s", + rbsize, VTY_NEWLINE); + return CMD_WARNING; + } + log_add_target(tgt); + + vty->index = tgt; + vty->node = CFG_LOG_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_no_log_alarms, cfg_no_log_alarms_cmd, + "no log alarms", + NO_STR LOG_STR "Logging alarms to ringbuffer\n") +{ + struct log_target *tgt; + + tgt = log_target_find(LOG_TGT_TYPE_RINGBUF, NULL); + if (!tgt) { + vty_out(vty, "%% No ringbuffer target found%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_target_destroy(tgt); + + return CMD_SUCCESS; +} + static int config_write_log_single(struct vty *vty, struct log_target *tgt) { int i; @@ -533,6 +603,10 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) case LOG_TGT_TYPE_FILE: vty_out(vty, "log file %s%s", tgt->tgt_file.fname, VTY_NEWLINE); break; + case LOG_TGT_TYPE_RINGBUF: + vty_out(vty, "log alarms %zu%s", + log_target_rb_avail_size(tgt), VTY_NEWLINE); + break; } vty_out(vty, " logging filter all %u%s", @@ -590,6 +664,7 @@ void logging_vty_add_cmds(const struct log_info *cat) logging_level_cmd.doc = log_vty_command_description(cat); install_element_ve(&logging_level_cmd); install_element_ve(&show_logging_vty_cmd); + install_element_ve(&show_alarms_cmd); install_node(&cfg_log_node, config_write_log); install_default(CFG_LOG_NODE); @@ -603,6 +678,8 @@ void logging_vty_add_cmds(const struct log_info *cat) install_element(CONFIG_NODE, &cfg_no_log_stderr_cmd); install_element(CONFIG_NODE, &cfg_log_file_cmd); install_element(CONFIG_NODE, &cfg_no_log_file_cmd); + install_element(CONFIG_NODE, &cfg_log_alarms_cmd); + install_element(CONFIG_NODE, &cfg_no_log_alarms_cmd); #ifdef HAVE_SYSLOG_H install_element(CONFIG_NODE, &cfg_log_syslog_cmd); install_element(CONFIG_NODE, &cfg_log_syslog_local_cmd); diff --git a/tests/Makefile.am b/tests/Makefile.am index be0b5f4..21ba88d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,7 +4,9 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \ smscb/smscb_test bits/bitrev_test a5/a5_test \ conv/conv_test auth/milenage_test lapd/lapd_test \ gsm0808/gsm0808_test gsm0408/gsm0408_test \ - gb/bssgp_fc_test logging/logging_test fr/fr_test + gb/bssgp_fc_test logging/logging_test fr/fr_test \ + loggingrb/loggingrb_test ringbuffer/ringbuffer_test + if ENABLE_MSGFILE check_PROGRAMS += msgfile/msgfile_test endif @@ -54,6 +56,12 @@ logging_logging_test_LDADD = $(top_builddir)/src/libosmocore.la fr_fr_test_SOURCES = fr/fr_test.c fr_fr_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gb/libosmogb.la +loggingrb_loggingrb_test_SOURCES = logging/logging_test.c +loggingrb_loggingrb_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/vty/libosmovty.la + +ringbuffer_ringbuffer_test_SOURCES = ringbuffer/ringbuffer_test.c +ringbuffer_ringbuffer_test_LDADD = $(top_builddir)/src/libosmocore.la + # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac @@ -82,7 +90,8 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \ gb/bssgp_fc_tests.ok gb/bssgp_fc_tests.sh \ msgfile/msgfile_test.ok msgfile/msgconfig.cfg \ logging/logging_test.ok logging/logging_test.err \ - fr/fr_test.ok + fr/fr_test.ok loggingrb/logging_test.ok \ + loggingrb/logging_test.err ringbuffer/ringbuffer_test.ok DISTCLEANFILES = atconfig diff --git a/tests/loggingrb/logging_test.err b/tests/loggingrb/logging_test.err new file mode 100644 index 0000000..b59d2e8 --- /dev/null +++ b/tests/loggingrb/logging_test.err @@ -0,0 +1,3 @@ + [1;31mYou should see this + [0;m [1;32mYou should see this + [0;m \ No newline at end of file diff --git a/tests/loggingrb/logging_test.ok b/tests/loggingrb/logging_test.ok new file mode 100644 index 0000000..e69de29 diff --git a/tests/loggingrb/loggingrb_test.c b/tests/loggingrb/loggingrb_test.c new file mode 100644 index 0000000..1ab5212 --- /dev/null +++ b/tests/loggingrb/loggingrb_test.c @@ -0,0 +1,83 @@ +/* simple test for the debug interface */ +/* + * (C) 2008, 2009 by Holger Hans Peter Freyther + * (C) 2012-2013 by Katerina Barone-Adesi + * 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 + +enum { + DRLL, + DCC, + DMM, +}; + +static const struct log_info_cat default_categories[] = { + [DRLL] = { + .name = "DRLL", + .description = "A-bis Radio Link Layer (RLL)", + .color = "\033[1;31m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DCC] = { + .name = "DCC", + .description = "Layer3 Call Control (CC)", + .color = "\033[1;32m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMM] = { + .name = NULL, + .description = "Layer3 Mobility Management (MM)", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, +}; + +const struct log_info log_info = { + .cat = default_categories, + .num_cat = ARRAY_SIZE(default_categories), +}; + +int main(int argc, char **argv) +{ + struct log_target *ringbuf_target; + + log_init(&log_info, NULL); + ringbuf_target = log_target_create_rbvty(NULL, 0x1000); + log_add_target(ringbuf_target); + log_set_all_filter(ringbuf_target, 1); + log_set_print_filename(ringbuf_target, 0); + + log_parse_category_mask(ringbuf_target, "DRLL:DCC"); + log_parse_category_mask(ringbuf_target, "DRLL"); + DEBUGP(DCC, "You should not see this\n"); + + log_parse_category_mask(ringbuf_target, "DRLL:DCC"); + DEBUGP(DRLL, "You should see this\n"); + DEBUGP(DCC, "You should see this\n"); + DEBUGP(DMM, "You should not see this\n"); + fprintf(stderr, ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 0)); + fprintf(stderr, ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 1)); + assert(!ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 2)); + + return 0; +} diff --git a/tests/ringbuffer/ringbuffer_test.c b/tests/ringbuffer/ringbuffer_test.c new file mode 100644 index 0000000..b7563ca --- /dev/null +++ b/tests/ringbuffer/ringbuffer_test.c @@ -0,0 +1,225 @@ +/* (C) 2012-2013 by Katerina Barone-Adesi + * All Rights Reserved + * + * This program is iree 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 +#include + +#include +#include +#include + +struct ringbuffer *rb0, *rb1, *rb2, *rb3, *rb4, *rb5; + +#define STR0 "hello" +#define STR1 "a" +#define STR2 "world" +#define STR3 "sky" +#define STR4 "moon" + +#define TESTSIZE 3 + +void init_rbs(void) +{ + rb0 = ringbuffer_create(NULL, TESTSIZE); + + rb1 = ringbuffer_create(NULL, TESTSIZE); + ringbuffer_add(rb1, STR0); + + rb2 = ringbuffer_create(NULL, TESTSIZE); + ringbuffer_add(rb2, STR0); + ringbuffer_add(rb2, STR1); + + rb3 = ringbuffer_create(NULL, TESTSIZE); + ringbuffer_add(rb3, STR0); + ringbuffer_add(rb3, STR1); + ringbuffer_add(rb3, STR2); + + rb4 = ringbuffer_create(NULL, TESTSIZE); + ringbuffer_add(rb4, STR0); + ringbuffer_add(rb4, STR1); + ringbuffer_add(rb4, STR2); + ringbuffer_add(rb4, STR3); + + rb5 = ringbuffer_create(NULL, TESTSIZE); + ringbuffer_add(rb5, STR0); + ringbuffer_add(rb5, STR1); + ringbuffer_add(rb5, STR2); + ringbuffer_add(rb5, STR3); + ringbuffer_add(rb5, STR4); +} + +void free_rbs(void) +{ + talloc_free(rb0); + talloc_free(rb1); + talloc_free(rb2); + talloc_free(rb3); + talloc_free(rb4); + talloc_free(rb5); +} + +void test_offset_valid(void) +{ + assert(_ringbuffer_is_bufindex_valid(rb1, 0)); + assert(!_ringbuffer_is_bufindex_valid(rb1, 1)); + assert(!_ringbuffer_is_bufindex_valid(rb1, 2)); + + assert(!_ringbuffer_is_bufindex_valid(rb3, 0)); + assert(_ringbuffer_is_bufindex_valid(rb3, 1)); + assert(_ringbuffer_is_bufindex_valid(rb3, 2)); + + assert(_ringbuffer_is_bufindex_valid(rb4, 0)); + assert(!_ringbuffer_is_bufindex_valid(rb4, 1)); + assert(_ringbuffer_is_bufindex_valid(rb4, 2)); + + assert(_ringbuffer_is_bufindex_valid(rb5, 0)); + assert(_ringbuffer_is_bufindex_valid(rb5, 1)); + assert(!_ringbuffer_is_bufindex_valid(rb5, 2)); +} + +void test_elems(void) +{ + assert(ringbuffer_elements(rb0) == 0); + assert(ringbuffer_elements(rb1) == 1); + assert(ringbuffer_elements(rb2) == 2); + assert(ringbuffer_elements(rb3) == 2); +} + +void test_getn(void) +{ + assert(!ringbuffer_get_nth(rb0, 0)); + assert(!strcmp(STR0, ringbuffer_get_nth(rb2, 0))); + assert(!strcmp(STR1, ringbuffer_get_nth(rb2, 1))); + assert(!strcmp(STR1, ringbuffer_get_nth(rb3, 0))); + assert(!strcmp(STR2, ringbuffer_get_nth(rb3, 1))); + assert(!ringbuffer_get_nth(rb3, 2)); +} + +void test_getn_wrap(void) +{ + assert(!strcmp(STR2, ringbuffer_get_nth(rb4, 0))); + assert(!strcmp(STR3, ringbuffer_get_nth(rb4, 1))); + + assert(!strcmp(STR3, ringbuffer_get_nth(rb5, 0))); + assert(!strcmp(STR4, ringbuffer_get_nth(rb5, 1))); +} + +void test_add(void) +{ + struct ringbuffer *rb = ringbuffer_create(NULL, 4); + assert(rb->start == 0); + assert(rb->end == 0); + + ringbuffer_add(rb, "a"); + ringbuffer_add(rb, "b"); + ringbuffer_add(rb, "c"); + assert(rb->start == 0); + assert(rb->end == 3); + assert(ringbuffer_elements(rb) == 3); + + ringbuffer_add(rb, "d"); + assert(rb->start == 1); + assert(rb->end == 0); + assert(ringbuffer_elements(rb) == 3); + assert(!strcmp("b", ringbuffer_get_nth(rb, 0))); + assert(!strcmp("c", ringbuffer_get_nth(rb, 1))); + assert(!strcmp("d", ringbuffer_get_nth(rb, 2))); + + ringbuffer_add(rb, "e"); + assert(rb->start == 2); + assert(rb->end == 1); + assert(!strcmp("c", ringbuffer_get_nth(rb, 0))); + assert(!strcmp("d", ringbuffer_get_nth(rb, 1))); + assert(!strcmp("e", ringbuffer_get_nth(rb, 2))); + + ringbuffer_add(rb, "f"); + assert(rb->start == 3); + assert(rb->end == 2); + assert(!strcmp("d", ringbuffer_get_nth(rb, 0))); + assert(!strcmp("e", ringbuffer_get_nth(rb, 1))); + assert(!strcmp("f", ringbuffer_get_nth(rb, 2))); + + ringbuffer_add(rb, "g"); + assert(rb->start == 0); + assert(rb->end == 3); + assert(!strcmp("e", ringbuffer_get_nth(rb, 0))); + assert(!strcmp("f", ringbuffer_get_nth(rb, 1))); + assert(!strcmp("g", ringbuffer_get_nth(rb, 2))); + + ringbuffer_add(rb, "h"); + assert(rb->start == 1); + assert(rb->end == 0); + assert(!strcmp("f", ringbuffer_get_nth(rb, 0))); + assert(!strcmp("g", ringbuffer_get_nth(rb, 1))); + assert(!strcmp("h", ringbuffer_get_nth(rb, 2))); + + talloc_free(rb); +} + +void test_long_msg(void) +{ + struct ringbuffer *rb = ringbuffer_create(NULL, 2); + int test_size = RB_MAX_MESSAGE_SIZE + 7; + char *tests1, *tests2; + const char *rb_content; + int i; + + tests1 = malloc(test_size); + tests2 = malloc(test_size); + /* Be certain allocating memory worked before continuing */ + assert(tests1); + assert(tests2); + + for (i = 0; i < RB_MAX_MESSAGE_SIZE; i += 2) { + tests1[i] = 'a'; + tests1[i + 1] = 'b'; + } + tests1[i] = '\0'; + + ringbuffer_add(rb, tests1); + strcpy(tests2, tests1); + + /* Verify that no stale data from test1 is lingering... */ + bzero(tests1, test_size); + free(tests1); + + rb_content = ringbuffer_get_nth(rb, 0); + assert(!strncmp(tests2, rb_content, RB_MAX_MESSAGE_SIZE - 1)); + assert(!rb_content[RB_MAX_MESSAGE_SIZE - 1]); + assert(strlen(rb_content) == RB_MAX_MESSAGE_SIZE - 1); + + free(tests2); + talloc_free(rb); +} + +int main(int argc, char **argv) +{ + init_rbs(); + test_offset_valid(); + test_elems(); + test_getn(); + test_getn_wrap(); + test_add(); + test_long_msg(); + printf("All tests passed\n"); + + free_rbs(); + return 0; +} diff --git a/tests/ringbuffer/ringbuffer_test.ok b/tests/ringbuffer/ringbuffer_test.ok new file mode 100644 index 0000000..9ac5124 --- /dev/null +++ b/tests/ringbuffer/ringbuffer_test.ok @@ -0,0 +1 @@ +All tests passed diff --git a/tests/testsuite.at b/tests/testsuite.at index 5029b9e..74dd214 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -99,3 +99,16 @@ cat $abs_srcdir/fr/fr_test.err > experr AT_CHECK([$abs_top_builddir/tests/fr/fr_test], [], [expout], [experr]) AT_CLEANUP + +AT_SETUP([loggingrb]) +AT_KEYWORDS([loggingrb]) +cat $abs_srcdir/loggingrb/logging_test.ok > expout +cat $abs_srcdir/loggingrb/logging_test.err > experr +AT_CHECK([$abs_top_builddir/tests/loggingrb/loggingrb_test], [], [expout], [experr]) +AT_CLEANUP + +AT_SETUP([ringbuffer]) +AT_KEYWORDS([ringbuffer]) +cat $abs_srcdir/ringbuffer/ringbuffer_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/ringbuffer/ringbuffer_test], [], [expout], [ignore]) +AT_CLEANUP -- 1.7.9.5 From 246tnt at gmail.com Thu Feb 14 10:09:28 2013 From: 246tnt at gmail.com (Sylvain Munaut) Date: Thu, 14 Feb 2013 11:09:28 +0100 Subject: [PATCH] Added a ring buffer log target to store the last N log messages. In-Reply-To: References: Message-ID: Hi, I didn't dig in the code deep yet, but one quick comment about the naming: 'ringbuffer' sounds a bit too generic to me when this implementation is dedicated to strings. I would try to find something that illustrate this specialization in the name (so that we don't conflict if we ever have data ringbuffer or msgb ring buffer or whatever). I think it should also have the osmo_ prefix in the function / struct names. Just my 2ct. Cheers, Sylvain From kat.obsc at gmail.com Thu Feb 14 05:45:57 2013 From: kat.obsc at gmail.com (Katerina Barone-Adesi) Date: Thu, 14 Feb 2013 06:45:57 +0100 Subject: [PATCH] Doxygen tweaks: fixed some typos and minor errors Message-ID: Doxygen generates quite a lot of warnings on libosmocore. Some of them are obvious typos - this patch aims to fix such low-hanging fruit. --- include/osmocom/core/conv.h | 2 +- include/osmocom/core/crcXXgen.h.tpl | 2 +- include/osmocom/core/crcgen.h | 2 +- include/osmocom/core/gsmtap_util.h | 2 ++ include/osmocom/core/logging.h | 2 +- include/osmocom/core/msgb.h | 2 +- include/osmocom/core/prim.h | 6 ++++-- include/osmocom/core/serial.h | 2 +- include/osmocom/core/statistics.h | 2 +- src/bits.c | 4 ++-- src/bitvec.c | 2 +- src/conv.c | 2 +- src/crcXXgen.c.tpl | 2 +- src/gsmtap_util.c | 6 +++--- src/msgb.c | 6 +++--- src/serial.c | 2 +- src/socket.c | 2 +- src/timer.c | 2 +- 18 files changed, 27 insertions(+), 23 deletions(-) diff --git a/include/osmocom/core/conv.h b/include/osmocom/core/conv.h index e5b2a97..4cc791f 100644 --- a/include/osmocom/core/conv.h +++ b/include/osmocom/core/conv.h @@ -25,7 +25,7 @@ */ /*! \file conv.h - * \file Osmocom convolutional encoder and decoder + * Osmocom convolutional encoder and decoder */ #ifndef __OSMO_CONV_H__ diff --git a/include/osmocom/core/crcXXgen.h.tpl b/include/osmocom/core/crcXXgen.h.tpl index 89d083a..a931bc3 100644 --- a/include/osmocom/core/crcXXgen.h.tpl +++ b/include/osmocom/core/crcXXgen.h.tpl @@ -28,7 +28,7 @@ */ /*! \file crcXXgen.h - * \file Osmocom generic CRC routines (for max XX bits poly) header + * Osmocom generic CRC routines (for max XX bits poly) header */ diff --git a/include/osmocom/core/crcgen.h b/include/osmocom/core/crcgen.h index 8e208a7..69cef04 100644 --- a/include/osmocom/core/crcgen.h +++ b/include/osmocom/core/crcgen.h @@ -28,7 +28,7 @@ */ /*! \file crcgen.h - * \file Osmocom generic CRC routines global header + * Osmocom generic CRC routines global header */ #include diff --git a/include/osmocom/core/gsmtap_util.h b/include/osmocom/core/gsmtap_util.h index 5609381..eaa32a0 100644 --- a/include/osmocom/core/gsmtap_util.h +++ b/include/osmocom/core/gsmtap_util.h @@ -54,4 +54,6 @@ int gsmtap_send(struct gsmtap_inst *gti, uint16_t arfcn, uint8_t ts, int8_t signal_dbm, uint8_t snr, const uint8_t *data, unsigned int len); +/*! @} */ + #endif /* _GSMTAP_UTIL_H */ diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index dc55d37..19f35b2 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -163,7 +163,7 @@ struct log_target { /*! \brief call-back function to be called when the logging framework * wants to log somethnig. - * \param[[in] target logging target + * \param[in] target logging target * \param[in] level log level of currnet message * \param[in] string the string that is to be written to the log */ diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h index a1939ab..fe2733b 100644 --- a/include/osmocom/core/msgb.h +++ b/include/osmocom/core/msgb.h @@ -361,7 +361,7 @@ static inline int msgb_trim(struct msgb *msg, int len) } /*! \brief Trim the msgb to a given layer3 length - * \pram[in] msg message buffer + * \param[in] msg message buffer * \param[in] l3len new layer3 length * \returns 0 in case of success, negative in case of error */ diff --git a/include/osmocom/core/prim.h b/include/osmocom/core/prim.h index b1026fe..f61d808 100644 --- a/include/osmocom/core/prim.h +++ b/include/osmocom/core/prim.h @@ -5,7 +5,7 @@ * @{ */ -/*! \file prim.c */ +/*! \file prim.h */ #include #include @@ -37,7 +37,7 @@ struct osmo_prim_hdr { /*! \brief initialize a primitive header * \param[in,out] oph primitive header * \param[in] sap Service Access Point - * \param[in] primtive Primitive Number + * \param[in] primitive Primitive Number * \param[in] operation Primitive Operation (REQ/RESP/IND/CONF) * \param[in] msg Message */ @@ -55,4 +55,6 @@ osmo_prim_init(struct osmo_prim_hdr *oph, unsigned int sap, /*! \brief primitive handler callback type */ typedef int (*osmo_prim_cb)(struct osmo_prim_hdr *oph, void *ctx); +/*! @} */ + #endif /* OSMO_PRIMITIVE_H */ diff --git a/include/osmocom/core/serial.h b/include/osmocom/core/serial.h index 889bd8a..1640a6d 100644 --- a/include/osmocom/core/serial.h +++ b/include/osmocom/core/serial.h @@ -25,7 +25,7 @@ */ /*! \file serial.h - * \file Osmocom serial port helpers + * Osmocom serial port helpers */ #ifndef __OSMO_SERIAL_H__ diff --git a/include/osmocom/core/statistics.h b/include/osmocom/core/statistics.h index 04816c1..ade0074 100644 --- a/include/osmocom/core/statistics.h +++ b/include/osmocom/core/statistics.h @@ -34,7 +34,7 @@ static inline void osmo_counter_reset(struct osmo_counter *ctr) struct osmo_counter *osmo_counter_alloc(const char *name); /*! \brief Free the specified counter - * \param[ctr] Counter + * \param[in] ctr Counter */ void osmo_counter_free(struct osmo_counter *ctr); diff --git a/src/bits.c b/src/bits.c index f3453e5..6be6d7a 100644 --- a/src/bits.c +++ b/src/bits.c @@ -180,8 +180,8 @@ uint32_t osmo_revbytebits_8(uint8_t x) } /*! \brief reverse bit-order of each byte in a buffer - * \param buf buffer containing bytes to be bit-reversed - * \param[in] length of buffer in bytes + * \param[in] buf buffer containing bytes to be bit-reversed + * \param[in] len length of buffer in bytes * * This function reverses the bits in each byte of the buffer */ diff --git a/src/bitvec.c b/src/bitvec.c index 714c11b..8da5a48 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -132,7 +132,7 @@ unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n) /*! \brief set a bit at given position in a bit vector * \param[in] bv bit vector on which to operate - * \param[in] bitnum number of bit to be set + * \param[in] bitnr number of bit to be set * \param[in] bit value to which the bit is to be set */ int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr, diff --git a/src/conv.c b/src/conv.c index ebc3eda..f13deef 100644 --- a/src/conv.c +++ b/src/conv.c @@ -27,7 +27,7 @@ */ /*! \file conv.c - * \file Osmocom convolutional encoder and decoder + * Osmocom convolutional encoder and decoder */ #include "config.h" #ifdef HAVE_ALLOCA_H diff --git a/src/crcXXgen.c.tpl b/src/crcXXgen.c.tpl index 2a4bf21..7e45c11 100644 --- a/src/crcXXgen.c.tpl +++ b/src/crcXXgen.c.tpl @@ -27,7 +27,7 @@ */ /*! \file crcXXgen.c - * \file Osmocom generic CRC routines (for max XX bits poly) + * Osmocom generic CRC routines (for max XX bits poly) */ #include diff --git a/src/gsmtap_util.c b/src/gsmtap_util.c index 77ab0c6..82690a9 100644 --- a/src/gsmtap_util.c +++ b/src/gsmtap_util.c @@ -49,7 +49,7 @@ /*! \brief convert RSL channel number to GSMTAP channel type - * \param[in] rsl_cantype RSL channel type + * \param[in] rsl_chantype RSL channel type * \param[in] link_id RSL link identifier * \returns GSMTAP channel type */ @@ -216,7 +216,7 @@ int gsmtap_source_add_sink_fd(int gsmtap_fd) /*! \brief Send a \ref msgb through a GSMTAP source * \param[in] gti GSMTAP instance - * \param[in] msgb message buffer + * \param[in] msg message buffer */ int gsmtap_sendmsg(struct gsmtap_inst *gti, struct msgb *msg) { @@ -339,7 +339,7 @@ int gsmtap_source_add_sink(struct gsmtap_inst *gti) /*! \brief Open GSMTAP source socket, connect and register osmo_fd * \param[in] host host name or IP address in string format * \param[in] port UDP port number in host byte order - * \param[in] osmo_wq_mode Register \ref osmo_wqueue (1) or not (0) + * \param[in] ofd_wq_mode Register \ref osmo_wqueue (1) or not (0) * * Open GSMTAP source (sending) socket, connect it to host/port, * allocate 'struct gsmtap_inst' and optionally osmo_fd/osmo_wqueue diff --git a/src/msgb.c b/src/msgb.c index c8564db..359a545 100644 --- a/src/msgb.c +++ b/src/msgb.c @@ -74,7 +74,7 @@ void msgb_free(struct msgb *m) /*! \brief Enqueue message buffer to tail of a queue * \param[in] queue linked list header of queue - * \param[in] msgb message buffer to be added to the queue + * \param[in] msg message buffer to be added to the queue * * The function will append the specified message buffer \a msg to the * queue implemented by \ref llist_head \a queue @@ -89,7 +89,7 @@ void msgb_enqueue(struct llist_head *queue, struct msgb *msg) * \returns message buffer (if any) or NULL if queue empty * * The function will remove the first message buffer from the queue - * implemented by 'ref llist_head \a queue. + * implemented by \ref llist_head \a queue. */ struct msgb *msgb_dequeue(struct llist_head *queue) { @@ -105,7 +105,7 @@ struct msgb *msgb_dequeue(struct llist_head *queue) } /*! \brief Re-set all message buffer pointers - * \param[in] m message buffer that is to be resetted + * \param[in] msg message buffer that is to be resetted * * This will re-set the various internal pointers into the underlying * message buffer, i.e. remvoe all headroom and treat the msgb as diff --git a/src/serial.c b/src/serial.c index a025ae9..66ee756 100644 --- a/src/serial.c +++ b/src/serial.c @@ -27,7 +27,7 @@ */ /*! \file serial.c - * \file Osmocom serial port helpers + * Osmocom serial port helpers */ #include diff --git a/src/socket.c b/src/socket.c index a5530d0..6ff00f0 100644 --- a/src/socket.c +++ b/src/socket.c @@ -129,7 +129,7 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, } /*! \brief Initialize a socket and fill \ref osmo_fd - * \param[out] osmocom file descriptor (will be filled in) + * \param[out] ofd file descriptor (will be filled in) * \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC * \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM * \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP diff --git a/src/timer.c b/src/timer.c index 98cbf6e..5988aef 100644 --- a/src/timer.c +++ b/src/timer.c @@ -128,7 +128,7 @@ int osmo_timer_pending(struct osmo_timer_list *timer) /*! \brief compute the remaining time of a timer * \param[in] timer the to-be-checked timer - * \param[in] the current time (NULL if not known) + * \param[in] now the current time (NULL if not known) * \param[out] remaining remaining time until timer fires * \return 0 if timer has not expired yet, -1 if it has * -- 1.7.9.5 From kat.obsc at gmail.com Thu Feb 14 06:08:39 2013 From: kat.obsc at gmail.com (Katerina Barone-Adesi) Date: Thu, 14 Feb 2013 07:08:39 +0100 Subject: [PATCH] Added a ring buffer log target to store the last N log messages (amended) Message-ID: Amended patch: this version fixes a minor doxygen error. The log target can be used via log alarms and show alarms. Why? This feature was proposed/requested at http://openbsc.osmocom.org/trac/wiki/Tasks/ErrorLogTarget All messages use the same amount of space, prioritizing simplicity. --- .gitignore | 2 + include/osmocom/core/logging.h | 5 + include/osmocom/core/loggingrb.h | 40 +++++++ include/osmocom/core/ringbuffer.h | 58 +++++++++ src/Makefile.am | 4 +- src/loggingrb.c | 98 +++++++++++++++ src/ringbuffer.c | 173 +++++++++++++++++++++++++++ src/vty/logging_vty.c | 85 ++++++++++++- tests/Makefile.am | 13 +- tests/loggingrb/logging_test.err | 3 + tests/loggingrb/loggingrb_test.c | 83 +++++++++++++ tests/ringbuffer/ringbuffer_test.c | 225 +++++++++++++++++++++++++++++++++++ tests/ringbuffer/ringbuffer_test.ok | 1 + tests/testsuite.at | 13 ++ 14 files changed, 795 insertions(+), 8 deletions(-) create mode 100644 include/osmocom/core/loggingrb.h create mode 100644 include/osmocom/core/ringbuffer.h create mode 100644 src/loggingrb.c create mode 100644 src/ringbuffer.c create mode 100644 tests/loggingrb/logging_test.err create mode 100644 tests/loggingrb/logging_test.ok create mode 100644 tests/loggingrb/loggingrb_test.c create mode 100644 tests/ringbuffer/ringbuffer_test.c create mode 100644 tests/ringbuffer/ringbuffer_test.ok diff --git a/.gitignore b/.gitignore index 24ca677..aedd9fd 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,8 @@ tests/gb/bssgp_fc_test tests/gsm0408/gsm0408_test tests/logging/logging_test tests/fr/fr_test +tests/loggingrb/loggingrb_test +tests/ringbuf/ringbuf_test utils/osmo-arfcn utils/osmo-auc-gen diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index 655f7a4..dc55d37 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -114,6 +114,7 @@ enum log_target_type { LOG_TGT_TYPE_SYSLOG, /*!< \brief syslog based logging */ LOG_TGT_TYPE_FILE, /*!< \brief text file logging */ LOG_TGT_TYPE_STDERR, /*!< \brief stderr logging */ + LOG_TGT_TYPE_RINGBUF, /*!< \brief ringbuffer-backed logging */ }; /*! \brief structure representing a logging target */ @@ -154,6 +155,10 @@ struct log_target { struct { void *vty; } tgt_vty; + + struct { + void *rb; + } tgt_rb; }; /*! \brief call-back function to be called when the logging framework diff --git a/include/osmocom/core/loggingrb.h b/include/osmocom/core/loggingrb.h new file mode 100644 index 0000000..a6f377b --- /dev/null +++ b/include/osmocom/core/loggingrb.h @@ -0,0 +1,40 @@ +#ifndef _LOGGINGRB_H +#define _LOGGINGRB_H + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + + +/*! \defgroup loggingrb Osmocom ringbuffer-backed logging + * @{ + */ + +/*! \file loggingrb.h + */ + +struct log_info; + +size_t log_target_rb_used_size(struct log_target const *target); +size_t log_target_rb_avail_size(struct log_target const *target); +const char *log_target_rb_get(struct log_target const *target, size_t logindex); +struct log_target *log_target_create_rb(size_t size); + +/*! @} */ + +#endif /* _LOGGINGRB_H */ diff --git a/include/osmocom/core/ringbuffer.h b/include/osmocom/core/ringbuffer.h new file mode 100644 index 0000000..7e16af7 --- /dev/null +++ b/include/osmocom/core/ringbuffer.h @@ -0,0 +1,58 @@ +#ifndef _RINGBUFFER_H +#define _RINGBUFFER_H + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + +/*! \defgroup ringbuffer Osmocom ringbuffers + * @{ + */ + +/*! \file ringbuffer.h + * \brief Osmocom ringbuffer handling routines + */ + +#include +#include +#include + +#include + +/*! \brief A structure representing a ringbuffer */ + +#define RB_MAX_MESSAGE_SIZE 240 +struct ringbuffer { + uint16_t start; /*!< \brief index of the first slot */ + uint16_t end; /*!< \brief index of the last slot */ + uint16_t size; /*!< \brief max number of messages to store */ + char **buffer; /*!< \brief storage for messages */ +}; + +struct ringbuffer *ringbuffer_create(TALLOC_CTX * ctx, size_t rb_size); +bool ringbuffer_is_empty(const struct ringbuffer *rb); +const char *ringbuffer_get_nth(const struct ringbuffer *rb, + unsigned int string_index); +bool _ringbuffer_is_bufindex_valid(const struct ringbuffer *rb, + unsigned int offset); +size_t ringbuffer_elements(const struct ringbuffer *rb); +int ringbuffer_add(struct ringbuffer *rb, const char *data); + +/*! @} */ + +#endif /* _RINGBUFFER_H */ diff --git a/src/Makefile.am b/src/Makefile.am index b425ea1..1a0f621 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,8 +11,8 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.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 \ - crc8gen.c crc16gen.c crc32gen.c crc64gen.c + conv.c application.c rbtree.c ringbuffer.c \ + loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c diff --git a/src/loggingrb.c b/src/loggingrb.c new file mode 100644 index 0000000..87cdddd --- /dev/null +++ b/src/loggingrb.c @@ -0,0 +1,98 @@ +/* Ringbuffer-backed logging support code */ + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + +/*! \addtogroup logging + * @{ + */ + +/*! \file loggingrb.c */ + +#include +#include +#include + +static void _rb_output(struct log_target *target, + unsigned int level, const char *log) +{ + ringbuffer_add(target->tgt_rb.rb, log); +} + +/*! \brief Return the number of log strings in the ringbuffer-backed target. + * \param[in] target The target to search. + * + * \return The number of log strings in the ringbuffer-backed target. + */ +size_t log_target_rb_used_size(struct log_target const *target) +{ + return ringbuffer_elements(target->tgt_rb.rb); +} + +/*! \brief Return the capacity of the ringbuffer-backed target. + * \param[in] target The target to search. + * + * Note that this is the capacity (aka max number of messages +1). + * It is not the number of unused message slots. + * \return The number of log strings in the ringbuffer-backed target. + */ +size_t log_target_rb_avail_size(struct log_target const *target) +{ + struct ringbuffer *rb = target->tgt_rb.rb; + return rb->size; +} + +/*! \brief Return the nth log entry in a target. + * \param[in] target The target to search. + * \param[in] logindex The index of the log entry/error message. + * + * \return A pointer to the nth message, or NULL if logindex is invalid. + */ +const char *log_target_rb_get(struct log_target const *target, size_t logindex) +{ + return ringbuffer_get_nth(target->tgt_rb.rb, logindex); +} + +/*! \brief Create a new logging target for ringbuffer logging. + * \param[in] size The size of the internal backing ringbuffer. + * \returns A log target in case of success, NULL in case of error. + */ +struct log_target *log_target_create_rb(size_t size) +{ + struct log_target *target; + struct ringbuffer *rb; + + target = log_target_create(); + if (!target) + return NULL; + + rb = ringbuffer_create(target, size); + if (!rb) { + log_target_destroy(target); + return NULL; + } + + target->tgt_rb.rb = rb; + target->type = LOG_TGT_TYPE_RINGBUF; + target->output = _rb_output; + + return target; +} + +/* @} */ diff --git a/src/ringbuffer.c b/src/ringbuffer.c new file mode 100644 index 0000000..95528dd --- /dev/null +++ b/src/ringbuffer.c @@ -0,0 +1,173 @@ +/* Ringbuffer implementation, tailored for logging. + * This is a lossy ringbuffer. It keeps up to N of the newest messages, + * overwriting the oldest as newer ones come in. + * + * (C) 2012-2013, Katerina Barone-Adesi + * 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. + * + */ + +/*! \file ringbuffer.c + * \brief Lossy ringbuffer for logging; keeps newest messages. + */ + +#include +#include +#include + +#include + +/* Ringbuffer assumptions, invarients, and notes: + * - start is the index of the first used index slot in the ring buffer. + * - end is the index of the next index slot in the ring buffer. + * - start == end => buffer is empty + * - Consequence: the buffer can hold at most size - 1 messages + * (if this were not the case, full and empty buffers would be indistinguishable + * given the conventions in this implementation). + * - Whenever the ringbuffer is full, start is advanced. The second oldest + * message becomes unreachable by valid indexes (end is not a valid index) + * and the oldest message is overwritten (if there was a message there, which + * is the case unless this is the first time the ringbuffer becomes full). +*/ + +/*! \brief Create an empty, initialized ringbuffer. + * \param[in] ctx The talloc memory context which should own this. + * \param[in] rb_size The number of message slots in the ringbuffer. + * \returns A struct ringbuffer* on success, NULL in case of error. + * + * This function creates and initializes a ringbuffer. + * Note that the ringbuffer stores at most rb_size - 1 messages. + */ + +/* http://talloc.samba.org/talloc/doc/html/libtalloc__bestpractices.html + * recommends functions that return dynamically allocated values use this style + */ + +struct ringbuffer *ringbuffer_create(TALLOC_CTX * ctx, size_t rb_size) +{ + struct ringbuffer *rb = NULL; + unsigned int i; + + rb = talloc_zero(ctx, struct ringbuffer); + if (!rb) + goto alloc_error; + rb->buffer = talloc_array(rb, char *, rb_size); + if (!rb->buffer) + goto alloc_error; + for (i = 0; i < rb_size; i++) { + rb->buffer[i] = + talloc_zero_size(rb->buffer, RB_MAX_MESSAGE_SIZE); + if (!rb->buffer[i]) + goto alloc_error; + } + + /* start and end are zero already, which is correct */ + rb->size = rb_size; + return rb; + +alloc_error: /* talloc_free(NULL) is safe */ + talloc_free(rb); + return NULL; +} + +/*! \brief Check if a ringbuffer is empty. + * \param[in] rb The ringbuffer to check. + * \returns True if the buffer is empty, false otherwise. + */ +bool ringbuffer_is_empty(const struct ringbuffer *rb) +{ + return rb->end == rb->start; +} + +/*! \brief Return a pointer to the Nth string in the ringbuffer. + * \param[in] rb The ringbuffer to search. + * \param[in] string_index The index sought (N), zero-indexed. + * + * Return a pointer to the Nth string in the ringbuffer. + * Return NULL if there is no Nth string. + * Note that N is zero-indexed. + * \returns A pointer to the target string on success, NULL in case of error. + */ +const char *ringbuffer_get_nth(const struct ringbuffer *rb, + unsigned int string_index) +{ + unsigned int offset = string_index + rb->start; + + if ((offset >= rb->size) && (rb->start > rb->end)) + offset -= rb->size; + if (_ringbuffer_is_bufindex_valid(rb, offset)) + return rb->buffer[offset]; + + return NULL; +} + +bool _ringbuffer_is_bufindex_valid(const struct ringbuffer *rb, + unsigned int bufi) +{ + if (ringbuffer_is_empty(rb)) + return 0; + if ((bufi >= rb->size) || (bufi < 0)) + return 0; + if (rb->start < rb->end) + return (bufi >= rb->start) && (bufi < rb->end); + return (bufi < rb->end) || (bufi >= rb->start); +} + +/*! \brief Count the number of log messages in a ringbuffer. + * \param[in] rb The ringbuffer to count the elements of. + * + * \returns The number of log messages in the ringbuffer. + */ +size_t ringbuffer_elements(const struct ringbuffer *rb) +{ + if (rb->end < rb->start) + return rb->end + (rb->size - rb->start); + + return rb->end - rb->start; +} + +/*! \brief Add a string to the ringbuffer. + * \param[in] rb The ringbuffer to add to. + * \param[in] data The string to add. + * + * Add a message to the ring buffer. + * Older messages will be overwritten as necessary. + * \returns 0 normally, 1 as a warning (ie, if data was truncated). + */ +int ringbuffer_add(struct ringbuffer *rb, const char *data) +{ + size_t len = strlen(data); + int ret = 0; + + if (len >= RB_MAX_MESSAGE_SIZE) { + len = RB_MAX_MESSAGE_SIZE - 1; + ret = 1; + } + + memcpy(rb->buffer[rb->end], data, len); + rb->buffer[rb->end][len] = '\0'; + + rb->end += 1; + rb->end %= rb->size; + + /* The buffer is full; oldest message is forgotten - see notes above */ + if (rb->end == rb->start) { + rb->start += 1; + rb->start %= rb->size; + } + return ret; +} diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index d473f12..3051974 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -27,8 +27,8 @@ #include #include #include - -//#include +#include +#include #include #include @@ -252,8 +252,8 @@ static void vty_print_logtarget(struct vty *vty, const struct log_info *info, #define SHOW_LOG_STR "Show current logging configuration\n" DEFUN(show_logging_vty, - show_logging_vty_cmd, - "show logging vty", + show_logging_vty_cmd, + "show logging vty", SHOW_STR SHOW_LOG_STR "Show current logging configuration for this vty\n") { @@ -267,6 +267,33 @@ DEFUN(show_logging_vty, return CMD_SUCCESS; } +DEFUN(show_alarms, + show_alarms_cmd, + "show alarms", + SHOW_STR SHOW_LOG_STR + "Show the contents of the logging ringbuffer\n") +{ + int i, num_alarms; + struct ringbuffer *rb; + struct log_target *tgt = log_target_find(LOG_TGT_TYPE_RINGBUF, NULL); + if (!tgt) { + vty_out(vty, "%% No alarms, run 'log alarms <2-32767>'%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + rb = tgt->tgt_rb.rb; + num_alarms = ringbuffer_elements(rb); + + vty_out(vty, "%% Showing %i alarms%s", num_alarms, VTY_NEWLINE); + + for (i = 0; i < num_alarms; i++) + vty_out(vty, "%% %s%s", ringbuffer_get_nth(rb, i), + VTY_NEWLINE); + + return CMD_SUCCESS; +} + gDEFUN(cfg_description, cfg_description_cmd, "description .TEXT", "Save human-readable decription of the object\n" @@ -510,6 +537,49 @@ DEFUN(cfg_no_log_file, cfg_no_log_file_cmd, return CMD_SUCCESS; } +DEFUN(cfg_log_alarms, cfg_log_alarms_cmd, + "log alarms <2-32767>", + LOG_STR "Logging alarms to ringbuffer\n" + "Maximum number of messages to log (+1)\n") +{ + struct log_target *tgt; + unsigned int rbsize = atoi(argv[0]); + + tgt = log_target_find(LOG_TGT_TYPE_RINGBUF, NULL); + if (tgt) + log_target_destroy(tgt); + + tgt = log_target_create_rb(rbsize); + if (!tgt) { + vty_out(vty, "%% Unable to create ringbuffer (size %u)%s", + rbsize, VTY_NEWLINE); + return CMD_WARNING; + } + log_add_target(tgt); + + vty->index = tgt; + vty->node = CFG_LOG_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_no_log_alarms, cfg_no_log_alarms_cmd, + "no log alarms", + NO_STR LOG_STR "Logging alarms to ringbuffer\n") +{ + struct log_target *tgt; + + tgt = log_target_find(LOG_TGT_TYPE_RINGBUF, NULL); + if (!tgt) { + vty_out(vty, "%% No ringbuffer target found%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_target_destroy(tgt); + + return CMD_SUCCESS; +} + static int config_write_log_single(struct vty *vty, struct log_target *tgt) { int i; @@ -533,6 +603,10 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) case LOG_TGT_TYPE_FILE: vty_out(vty, "log file %s%s", tgt->tgt_file.fname, VTY_NEWLINE); break; + case LOG_TGT_TYPE_RINGBUF: + vty_out(vty, "log alarms %zu%s", + log_target_rb_avail_size(tgt), VTY_NEWLINE); + break; } vty_out(vty, " logging filter all %u%s", @@ -590,6 +664,7 @@ void logging_vty_add_cmds(const struct log_info *cat) logging_level_cmd.doc = log_vty_command_description(cat); install_element_ve(&logging_level_cmd); install_element_ve(&show_logging_vty_cmd); + install_element_ve(&show_alarms_cmd); install_node(&cfg_log_node, config_write_log); install_default(CFG_LOG_NODE); @@ -603,6 +678,8 @@ void logging_vty_add_cmds(const struct log_info *cat) install_element(CONFIG_NODE, &cfg_no_log_stderr_cmd); install_element(CONFIG_NODE, &cfg_log_file_cmd); install_element(CONFIG_NODE, &cfg_no_log_file_cmd); + install_element(CONFIG_NODE, &cfg_log_alarms_cmd); + install_element(CONFIG_NODE, &cfg_no_log_alarms_cmd); #ifdef HAVE_SYSLOG_H install_element(CONFIG_NODE, &cfg_log_syslog_cmd); install_element(CONFIG_NODE, &cfg_log_syslog_local_cmd); diff --git a/tests/Makefile.am b/tests/Makefile.am index be0b5f4..21ba88d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,7 +4,9 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \ smscb/smscb_test bits/bitrev_test a5/a5_test \ conv/conv_test auth/milenage_test lapd/lapd_test \ gsm0808/gsm0808_test gsm0408/gsm0408_test \ - gb/bssgp_fc_test logging/logging_test fr/fr_test + gb/bssgp_fc_test logging/logging_test fr/fr_test \ + loggingrb/loggingrb_test ringbuffer/ringbuffer_test + if ENABLE_MSGFILE check_PROGRAMS += msgfile/msgfile_test endif @@ -54,6 +56,12 @@ logging_logging_test_LDADD = $(top_builddir)/src/libosmocore.la fr_fr_test_SOURCES = fr/fr_test.c fr_fr_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gb/libosmogb.la +loggingrb_loggingrb_test_SOURCES = logging/logging_test.c +loggingrb_loggingrb_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/vty/libosmovty.la + +ringbuffer_ringbuffer_test_SOURCES = ringbuffer/ringbuffer_test.c +ringbuffer_ringbuffer_test_LDADD = $(top_builddir)/src/libosmocore.la + # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac @@ -82,7 +90,8 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \ gb/bssgp_fc_tests.ok gb/bssgp_fc_tests.sh \ msgfile/msgfile_test.ok msgfile/msgconfig.cfg \ logging/logging_test.ok logging/logging_test.err \ - fr/fr_test.ok + fr/fr_test.ok loggingrb/logging_test.ok \ + loggingrb/logging_test.err ringbuffer/ringbuffer_test.ok DISTCLEANFILES = atconfig diff --git a/tests/loggingrb/logging_test.err b/tests/loggingrb/logging_test.err new file mode 100644 index 0000000..b59d2e8 --- /dev/null +++ b/tests/loggingrb/logging_test.err @@ -0,0 +1,3 @@ +You should see this +You should see this + \ No newline at end of file diff --git a/tests/loggingrb/logging_test.ok b/tests/loggingrb/logging_test.ok new file mode 100644 index 0000000..e69de29 diff --git a/tests/loggingrb/loggingrb_test.c b/tests/loggingrb/loggingrb_test.c new file mode 100644 index 0000000..1ab5212 --- /dev/null +++ b/tests/loggingrb/loggingrb_test.c @@ -0,0 +1,83 @@ +/* simple test for the debug interface */ +/* + * (C) 2008, 2009 by Holger Hans Peter Freyther + * (C) 2012-2013 by Katerina Barone-Adesi + * 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 + +enum { + DRLL, + DCC, + DMM, +}; + +static const struct log_info_cat default_categories[] = { + [DRLL] = { + .name = "DRLL", + .description = "A-bis Radio Link Layer (RLL)", + .color = "\033[1;31m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DCC] = { + .name = "DCC", + .description = "Layer3 Call Control (CC)", + .color = "\033[1;32m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMM] = { + .name = NULL, + .description = "Layer3 Mobility Management (MM)", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, +}; + +const struct log_info log_info = { + .cat = default_categories, + .num_cat = ARRAY_SIZE(default_categories), +}; + +int main(int argc, char **argv) +{ + struct log_target *ringbuf_target; + + log_init(&log_info, NULL); + ringbuf_target = log_target_create_rbvty(NULL, 0x1000); + log_add_target(ringbuf_target); + log_set_all_filter(ringbuf_target, 1); + log_set_print_filename(ringbuf_target, 0); + + log_parse_category_mask(ringbuf_target, "DRLL:DCC"); + log_parse_category_mask(ringbuf_target, "DRLL"); + DEBUGP(DCC, "You should not see this\n"); + + log_parse_category_mask(ringbuf_target, "DRLL:DCC"); + DEBUGP(DRLL, "You should see this\n"); + DEBUGP(DCC, "You should see this\n"); + DEBUGP(DMM, "You should not see this\n"); + fprintf(stderr, ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 0)); + fprintf(stderr, ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 1)); + assert(!ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 2)); + + return 0; +} diff --git a/tests/ringbuffer/ringbuffer_test.c b/tests/ringbuffer/ringbuffer_test.c new file mode 100644 index 0000000..b7563ca --- /dev/null +++ b/tests/ringbuffer/ringbuffer_test.c @@ -0,0 +1,225 @@ +/* (C) 2012-2013 by Katerina Barone-Adesi + * All Rights Reserved + * + * This program is iree 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 +#include + +#include +#include +#include + +struct ringbuffer *rb0, *rb1, *rb2, *rb3, *rb4, *rb5; + +#define STR0 "hello" +#define STR1 "a" +#define STR2 "world" +#define STR3 "sky" +#define STR4 "moon" + +#define TESTSIZE 3 + +void init_rbs(void) +{ + rb0 = ringbuffer_create(NULL, TESTSIZE); + + rb1 = ringbuffer_create(NULL, TESTSIZE); + ringbuffer_add(rb1, STR0); + + rb2 = ringbuffer_create(NULL, TESTSIZE); + ringbuffer_add(rb2, STR0); + ringbuffer_add(rb2, STR1); + + rb3 = ringbuffer_create(NULL, TESTSIZE); + ringbuffer_add(rb3, STR0); + ringbuffer_add(rb3, STR1); + ringbuffer_add(rb3, STR2); + + rb4 = ringbuffer_create(NULL, TESTSIZE); + ringbuffer_add(rb4, STR0); + ringbuffer_add(rb4, STR1); + ringbuffer_add(rb4, STR2); + ringbuffer_add(rb4, STR3); + + rb5 = ringbuffer_create(NULL, TESTSIZE); + ringbuffer_add(rb5, STR0); + ringbuffer_add(rb5, STR1); + ringbuffer_add(rb5, STR2); + ringbuffer_add(rb5, STR3); + ringbuffer_add(rb5, STR4); +} + +void free_rbs(void) +{ + talloc_free(rb0); + talloc_free(rb1); + talloc_free(rb2); + talloc_free(rb3); + talloc_free(rb4); + talloc_free(rb5); +} + +void test_offset_valid(void) +{ + assert(_ringbuffer_is_bufindex_valid(rb1, 0)); + assert(!_ringbuffer_is_bufindex_valid(rb1, 1)); + assert(!_ringbuffer_is_bufindex_valid(rb1, 2)); + + assert(!_ringbuffer_is_bufindex_valid(rb3, 0)); + assert(_ringbuffer_is_bufindex_valid(rb3, 1)); + assert(_ringbuffer_is_bufindex_valid(rb3, 2)); + + assert(_ringbuffer_is_bufindex_valid(rb4, 0)); + assert(!_ringbuffer_is_bufindex_valid(rb4, 1)); + assert(_ringbuffer_is_bufindex_valid(rb4, 2)); + + assert(_ringbuffer_is_bufindex_valid(rb5, 0)); + assert(_ringbuffer_is_bufindex_valid(rb5, 1)); + assert(!_ringbuffer_is_bufindex_valid(rb5, 2)); +} + +void test_elems(void) +{ + assert(ringbuffer_elements(rb0) == 0); + assert(ringbuffer_elements(rb1) == 1); + assert(ringbuffer_elements(rb2) == 2); + assert(ringbuffer_elements(rb3) == 2); +} + +void test_getn(void) +{ + assert(!ringbuffer_get_nth(rb0, 0)); + assert(!strcmp(STR0, ringbuffer_get_nth(rb2, 0))); + assert(!strcmp(STR1, ringbuffer_get_nth(rb2, 1))); + assert(!strcmp(STR1, ringbuffer_get_nth(rb3, 0))); + assert(!strcmp(STR2, ringbuffer_get_nth(rb3, 1))); + assert(!ringbuffer_get_nth(rb3, 2)); +} + +void test_getn_wrap(void) +{ + assert(!strcmp(STR2, ringbuffer_get_nth(rb4, 0))); + assert(!strcmp(STR3, ringbuffer_get_nth(rb4, 1))); + + assert(!strcmp(STR3, ringbuffer_get_nth(rb5, 0))); + assert(!strcmp(STR4, ringbuffer_get_nth(rb5, 1))); +} + +void test_add(void) +{ + struct ringbuffer *rb = ringbuffer_create(NULL, 4); + assert(rb->start == 0); + assert(rb->end == 0); + + ringbuffer_add(rb, "a"); + ringbuffer_add(rb, "b"); + ringbuffer_add(rb, "c"); + assert(rb->start == 0); + assert(rb->end == 3); + assert(ringbuffer_elements(rb) == 3); + + ringbuffer_add(rb, "d"); + assert(rb->start == 1); + assert(rb->end == 0); + assert(ringbuffer_elements(rb) == 3); + assert(!strcmp("b", ringbuffer_get_nth(rb, 0))); + assert(!strcmp("c", ringbuffer_get_nth(rb, 1))); + assert(!strcmp("d", ringbuffer_get_nth(rb, 2))); + + ringbuffer_add(rb, "e"); + assert(rb->start == 2); + assert(rb->end == 1); + assert(!strcmp("c", ringbuffer_get_nth(rb, 0))); + assert(!strcmp("d", ringbuffer_get_nth(rb, 1))); + assert(!strcmp("e", ringbuffer_get_nth(rb, 2))); + + ringbuffer_add(rb, "f"); + assert(rb->start == 3); + assert(rb->end == 2); + assert(!strcmp("d", ringbuffer_get_nth(rb, 0))); + assert(!strcmp("e", ringbuffer_get_nth(rb, 1))); + assert(!strcmp("f", ringbuffer_get_nth(rb, 2))); + + ringbuffer_add(rb, "g"); + assert(rb->start == 0); + assert(rb->end == 3); + assert(!strcmp("e", ringbuffer_get_nth(rb, 0))); + assert(!strcmp("f", ringbuffer_get_nth(rb, 1))); + assert(!strcmp("g", ringbuffer_get_nth(rb, 2))); + + ringbuffer_add(rb, "h"); + assert(rb->start == 1); + assert(rb->end == 0); + assert(!strcmp("f", ringbuffer_get_nth(rb, 0))); + assert(!strcmp("g", ringbuffer_get_nth(rb, 1))); + assert(!strcmp("h", ringbuffer_get_nth(rb, 2))); + + talloc_free(rb); +} + +void test_long_msg(void) +{ + struct ringbuffer *rb = ringbuffer_create(NULL, 2); + int test_size = RB_MAX_MESSAGE_SIZE + 7; + char *tests1, *tests2; + const char *rb_content; + int i; + + tests1 = malloc(test_size); + tests2 = malloc(test_size); + /* Be certain allocating memory worked before continuing */ + assert(tests1); + assert(tests2); + + for (i = 0; i < RB_MAX_MESSAGE_SIZE; i += 2) { + tests1[i] = 'a'; + tests1[i + 1] = 'b'; + } + tests1[i] = '\0'; + + ringbuffer_add(rb, tests1); + strcpy(tests2, tests1); + + /* Verify that no stale data from test1 is lingering... */ + bzero(tests1, test_size); + free(tests1); + + rb_content = ringbuffer_get_nth(rb, 0); + assert(!strncmp(tests2, rb_content, RB_MAX_MESSAGE_SIZE - 1)); + assert(!rb_content[RB_MAX_MESSAGE_SIZE - 1]); + assert(strlen(rb_content) == RB_MAX_MESSAGE_SIZE - 1); + + free(tests2); + talloc_free(rb); +} + +int main(int argc, char **argv) +{ + init_rbs(); + test_offset_valid(); + test_elems(); + test_getn(); + test_getn_wrap(); + test_add(); + test_long_msg(); + printf("All tests passed\n"); + + free_rbs(); + return 0; +} diff --git a/tests/ringbuffer/ringbuffer_test.ok b/tests/ringbuffer/ringbuffer_test.ok new file mode 100644 index 0000000..9ac5124 --- /dev/null +++ b/tests/ringbuffer/ringbuffer_test.ok @@ -0,0 +1 @@ +All tests passed diff --git a/tests/testsuite.at b/tests/testsuite.at index 5029b9e..74dd214 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -99,3 +99,16 @@ cat $abs_srcdir/fr/fr_test.err > experr AT_CHECK([$abs_top_builddir/tests/fr/fr_test], [], [expout], [experr]) AT_CLEANUP + +AT_SETUP([loggingrb]) +AT_KEYWORDS([loggingrb]) +cat $abs_srcdir/loggingrb/logging_test.ok > expout +cat $abs_srcdir/loggingrb/logging_test.err > experr +AT_CHECK([$abs_top_builddir/tests/loggingrb/loggingrb_test], [], [expout], [experr]) +AT_CLEANUP + +AT_SETUP([ringbuffer]) +AT_KEYWORDS([ringbuffer]) +cat $abs_srcdir/ringbuffer/ringbuffer_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/ringbuffer/ringbuffer_test], [], [expout], [ignore]) +AT_CLEANUP -- 1.7.9.5 From kat.obsc at gmail.com Thu Feb 14 06:12:43 2013 From: kat.obsc at gmail.com (Katerina Barone-Adesi) Date: Thu, 14 Feb 2013 07:12:43 +0100 Subject: [PATCH] Doxygen tweaks: fixed a lot of typos and minor errors (amended) Message-ID: This patch supersedes the previous doxygen patch of today. --- Doxyfile.codec.in | 4 ++-- Doxyfile.core.in | 4 ++-- Doxyfile.gsm.in | 4 ++-- Doxyfile.vty.in | 4 ++-- include/osmocom/core/conv.h | 2 +- include/osmocom/core/crcXXgen.h.tpl | 2 +- include/osmocom/core/crcgen.h | 2 +- include/osmocom/core/gsmtap_util.h | 2 ++ include/osmocom/core/logging.h | 2 +- include/osmocom/core/msgb.h | 2 +- include/osmocom/core/prim.h | 6 ++++-- include/osmocom/core/serial.h | 2 +- include/osmocom/core/statistics.h | 2 +- include/osmocom/gsm/lapd_core.h | 8 +++++--- src/bits.c | 4 ++-- src/bitvec.c | 2 +- src/conv.c | 2 +- src/crcXXgen.c.tpl | 2 +- src/gsm/auth_core.c | 4 ++-- src/gsm/lapd_core.c | 3 ++- src/gsm/tlv_parser.c | 2 +- src/gsmtap_util.c | 6 +++--- src/msgb.c | 6 +++--- src/serial.c | 2 +- src/socket.c | 2 +- src/timer.c | 2 +- 26 files changed, 45 insertions(+), 38 deletions(-) diff --git a/Doxyfile.codec.in b/Doxyfile.codec.in index 1b0df5e..4f539c7 100644 --- a/Doxyfile.codec.in +++ b/Doxyfile.codec.in @@ -688,7 +688,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = images/ +# IMAGE_PATH = images/ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -1406,7 +1406,7 @@ PERLMOD_MAKEVAR_PREFIX = # evaluate all C-preprocessor directives found in the sources and include # files. -ENABLE_PREPROCESSING = NO +ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional diff --git a/Doxyfile.core.in b/Doxyfile.core.in index 4baa3d5..71843cc 100644 --- a/Doxyfile.core.in +++ b/Doxyfile.core.in @@ -688,7 +688,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = images/ +# IMAGE_PATH = images/ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -1406,7 +1406,7 @@ PERLMOD_MAKEVAR_PREFIX = # evaluate all C-preprocessor directives found in the sources and include # files. -ENABLE_PREPROCESSING = NO +ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional diff --git a/Doxyfile.gsm.in b/Doxyfile.gsm.in index 36a6ae2..c4a837f 100644 --- a/Doxyfile.gsm.in +++ b/Doxyfile.gsm.in @@ -688,7 +688,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = images/ +# IMAGE_PATH = images/ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -1406,7 +1406,7 @@ PERLMOD_MAKEVAR_PREFIX = # evaluate all C-preprocessor directives found in the sources and include # files. -ENABLE_PREPROCESSING = NO +ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional diff --git a/Doxyfile.vty.in b/Doxyfile.vty.in index 527cdb2..5f7a158 100644 --- a/Doxyfile.vty.in +++ b/Doxyfile.vty.in @@ -688,7 +688,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = images/ +# IMAGE_PATH = images/ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -1406,7 +1406,7 @@ PERLMOD_MAKEVAR_PREFIX = # evaluate all C-preprocessor directives found in the sources and include # files. -ENABLE_PREPROCESSING = NO +ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional diff --git a/include/osmocom/core/conv.h b/include/osmocom/core/conv.h index e5b2a97..4cc791f 100644 --- a/include/osmocom/core/conv.h +++ b/include/osmocom/core/conv.h @@ -25,7 +25,7 @@ */ /*! \file conv.h - * \file Osmocom convolutional encoder and decoder + * Osmocom convolutional encoder and decoder */ #ifndef __OSMO_CONV_H__ diff --git a/include/osmocom/core/crcXXgen.h.tpl b/include/osmocom/core/crcXXgen.h.tpl index 89d083a..a931bc3 100644 --- a/include/osmocom/core/crcXXgen.h.tpl +++ b/include/osmocom/core/crcXXgen.h.tpl @@ -28,7 +28,7 @@ */ /*! \file crcXXgen.h - * \file Osmocom generic CRC routines (for max XX bits poly) header + * Osmocom generic CRC routines (for max XX bits poly) header */ diff --git a/include/osmocom/core/crcgen.h b/include/osmocom/core/crcgen.h index 8e208a7..69cef04 100644 --- a/include/osmocom/core/crcgen.h +++ b/include/osmocom/core/crcgen.h @@ -28,7 +28,7 @@ */ /*! \file crcgen.h - * \file Osmocom generic CRC routines global header + * Osmocom generic CRC routines global header */ #include diff --git a/include/osmocom/core/gsmtap_util.h b/include/osmocom/core/gsmtap_util.h index 5609381..eaa32a0 100644 --- a/include/osmocom/core/gsmtap_util.h +++ b/include/osmocom/core/gsmtap_util.h @@ -54,4 +54,6 @@ int gsmtap_send(struct gsmtap_inst *gti, uint16_t arfcn, uint8_t ts, int8_t signal_dbm, uint8_t snr, const uint8_t *data, unsigned int len); +/*! @} */ + #endif /* _GSMTAP_UTIL_H */ diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index dc55d37..19f35b2 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -163,7 +163,7 @@ struct log_target { /*! \brief call-back function to be called when the logging framework * wants to log somethnig. - * \param[[in] target logging target + * \param[in] target logging target * \param[in] level log level of currnet message * \param[in] string the string that is to be written to the log */ diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h index a1939ab..fe2733b 100644 --- a/include/osmocom/core/msgb.h +++ b/include/osmocom/core/msgb.h @@ -361,7 +361,7 @@ static inline int msgb_trim(struct msgb *msg, int len) } /*! \brief Trim the msgb to a given layer3 length - * \pram[in] msg message buffer + * \param[in] msg message buffer * \param[in] l3len new layer3 length * \returns 0 in case of success, negative in case of error */ diff --git a/include/osmocom/core/prim.h b/include/osmocom/core/prim.h index b1026fe..f61d808 100644 --- a/include/osmocom/core/prim.h +++ b/include/osmocom/core/prim.h @@ -5,7 +5,7 @@ * @{ */ -/*! \file prim.c */ +/*! \file prim.h */ #include #include @@ -37,7 +37,7 @@ struct osmo_prim_hdr { /*! \brief initialize a primitive header * \param[in,out] oph primitive header * \param[in] sap Service Access Point - * \param[in] primtive Primitive Number + * \param[in] primitive Primitive Number * \param[in] operation Primitive Operation (REQ/RESP/IND/CONF) * \param[in] msg Message */ @@ -55,4 +55,6 @@ osmo_prim_init(struct osmo_prim_hdr *oph, unsigned int sap, /*! \brief primitive handler callback type */ typedef int (*osmo_prim_cb)(struct osmo_prim_hdr *oph, void *ctx); +/*! @} */ + #endif /* OSMO_PRIMITIVE_H */ diff --git a/include/osmocom/core/serial.h b/include/osmocom/core/serial.h index 889bd8a..1640a6d 100644 --- a/include/osmocom/core/serial.h +++ b/include/osmocom/core/serial.h @@ -25,7 +25,7 @@ */ /*! \file serial.h - * \file Osmocom serial port helpers + * Osmocom serial port helpers */ #ifndef __OSMO_SERIAL_H__ diff --git a/include/osmocom/core/statistics.h b/include/osmocom/core/statistics.h index 04816c1..ade0074 100644 --- a/include/osmocom/core/statistics.h +++ b/include/osmocom/core/statistics.h @@ -34,7 +34,7 @@ static inline void osmo_counter_reset(struct osmo_counter *ctr) struct osmo_counter *osmo_counter_alloc(const char *name); /*! \brief Free the specified counter - * \param[ctr] Counter + * \param[in] ctr Counter */ void osmo_counter_free(struct osmo_counter *ctr); diff --git a/include/osmocom/gsm/lapd_core.h b/include/osmocom/gsm/lapd_core.h index 0f4e889..c2fdc62 100644 --- a/include/osmocom/gsm/lapd_core.h +++ b/include/osmocom/gsm/lapd_core.h @@ -11,9 +11,9 @@ * @{ */ -/*! \file lapd.h */ - -/* primitive related sutff */ +/*! \file lapd_core.h + * primitive related stuff + */ /*! \brief LAPD related primitives (L2<->L3 SAP)*/ enum osmo_dl_prim { @@ -168,4 +168,6 @@ int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode); int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx); int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx); +/*! @} */ + #endif /* _OSMOCOM_LAPD_H */ diff --git a/src/bits.c b/src/bits.c index f3453e5..6be6d7a 100644 --- a/src/bits.c +++ b/src/bits.c @@ -180,8 +180,8 @@ uint32_t osmo_revbytebits_8(uint8_t x) } /*! \brief reverse bit-order of each byte in a buffer - * \param buf buffer containing bytes to be bit-reversed - * \param[in] length of buffer in bytes + * \param[in] buf buffer containing bytes to be bit-reversed + * \param[in] len length of buffer in bytes * * This function reverses the bits in each byte of the buffer */ diff --git a/src/bitvec.c b/src/bitvec.c index 714c11b..8da5a48 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -132,7 +132,7 @@ unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n) /*! \brief set a bit at given position in a bit vector * \param[in] bv bit vector on which to operate - * \param[in] bitnum number of bit to be set + * \param[in] bitnr number of bit to be set * \param[in] bit value to which the bit is to be set */ int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr, diff --git a/src/conv.c b/src/conv.c index ebc3eda..f13deef 100644 --- a/src/conv.c +++ b/src/conv.c @@ -27,7 +27,7 @@ */ /*! \file conv.c - * \file Osmocom convolutional encoder and decoder + * Osmocom convolutional encoder and decoder */ #include "config.h" #ifdef HAVE_ALLOCA_H diff --git a/src/crcXXgen.c.tpl b/src/crcXXgen.c.tpl index 2a4bf21..7e45c11 100644 --- a/src/crcXXgen.c.tpl +++ b/src/crcXXgen.c.tpl @@ -27,7 +27,7 @@ */ /*! \file crcXXgen.c - * \file Osmocom generic CRC routines (for max XX bits poly) + * Osmocom generic CRC routines (for max XX bits poly) */ #include diff --git a/src/gsm/auth_core.c b/src/gsm/auth_core.c index 5cf8dfc..3a0866b 100644 --- a/src/gsm/auth_core.c +++ b/src/gsm/auth_core.c @@ -93,7 +93,7 @@ int osmo_auth_supported(enum osmo_auth_algo algo) /*! \brief Generate authentication vector * \param[out] vec Generated authentication vector * \param[in] aud Subscriber-specific key material - * \param[in] rand Random challenge to be used + * \param[in] _rand Random challenge to be used * * This function performs the core cryptographic function of the AUC, * computing authentication triples/quintuples based on the permanent @@ -125,7 +125,7 @@ int osmo_auth_gen_vec(struct osmo_auth_vector *vec, * \param[in] aud Subscriber-specific key material * \param[in] rand_auts RAND value sent by the SIM/MS * \param[in] auts AUTS value sent by the SIM/MS - * \param[in] rand Random challenge to be used to generate vector + * \param[in] _rand Random challenge to be used to generate vector * * This function performs a special variant of the core cryptographic * function of the AUC: computing authentication triples/quintuples diff --git a/src/gsm/lapd_core.c b/src/gsm/lapd_core.c index 0dc78eb..b33cf6e 100644 --- a/src/gsm/lapd_core.c +++ b/src/gsm/lapd_core.c @@ -25,7 +25,7 @@ * @{ */ -/*! \file lapd.c */ +/*! \file lapd_core.c */ /*! * Notes on Buffering: rcv_buffer, tx_queue, tx_hist, send_buffer, send_queue @@ -2167,3 +2167,4 @@ int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx) return rc; } +/*! @} */ diff --git a/src/gsm/tlv_parser.c b/src/gsm/tlv_parser.c index d18a6bf..8cb2139 100644 --- a/src/gsm/tlv_parser.c +++ b/src/gsm/tlv_parser.c @@ -6,7 +6,7 @@ /*! \addtogroup tlv * @{ */ -/*! \file tlv.c */ +/*! \file tlv_parser.c */ struct tlv_definition tvlv_att_def; struct tlv_definition vtvlv_gan_att_def; diff --git a/src/gsmtap_util.c b/src/gsmtap_util.c index 77ab0c6..82690a9 100644 --- a/src/gsmtap_util.c +++ b/src/gsmtap_util.c @@ -49,7 +49,7 @@ /*! \brief convert RSL channel number to GSMTAP channel type - * \param[in] rsl_cantype RSL channel type + * \param[in] rsl_chantype RSL channel type * \param[in] link_id RSL link identifier * \returns GSMTAP channel type */ @@ -216,7 +216,7 @@ int gsmtap_source_add_sink_fd(int gsmtap_fd) /*! \brief Send a \ref msgb through a GSMTAP source * \param[in] gti GSMTAP instance - * \param[in] msgb message buffer + * \param[in] msg message buffer */ int gsmtap_sendmsg(struct gsmtap_inst *gti, struct msgb *msg) { @@ -339,7 +339,7 @@ int gsmtap_source_add_sink(struct gsmtap_inst *gti) /*! \brief Open GSMTAP source socket, connect and register osmo_fd * \param[in] host host name or IP address in string format * \param[in] port UDP port number in host byte order - * \param[in] osmo_wq_mode Register \ref osmo_wqueue (1) or not (0) + * \param[in] ofd_wq_mode Register \ref osmo_wqueue (1) or not (0) * * Open GSMTAP source (sending) socket, connect it to host/port, * allocate 'struct gsmtap_inst' and optionally osmo_fd/osmo_wqueue diff --git a/src/msgb.c b/src/msgb.c index c8564db..359a545 100644 --- a/src/msgb.c +++ b/src/msgb.c @@ -74,7 +74,7 @@ void msgb_free(struct msgb *m) /*! \brief Enqueue message buffer to tail of a queue * \param[in] queue linked list header of queue - * \param[in] msgb message buffer to be added to the queue + * \param[in] msg message buffer to be added to the queue * * The function will append the specified message buffer \a msg to the * queue implemented by \ref llist_head \a queue @@ -89,7 +89,7 @@ void msgb_enqueue(struct llist_head *queue, struct msgb *msg) * \returns message buffer (if any) or NULL if queue empty * * The function will remove the first message buffer from the queue - * implemented by 'ref llist_head \a queue. + * implemented by \ref llist_head \a queue. */ struct msgb *msgb_dequeue(struct llist_head *queue) { @@ -105,7 +105,7 @@ struct msgb *msgb_dequeue(struct llist_head *queue) } /*! \brief Re-set all message buffer pointers - * \param[in] m message buffer that is to be resetted + * \param[in] msg message buffer that is to be resetted * * This will re-set the various internal pointers into the underlying * message buffer, i.e. remvoe all headroom and treat the msgb as diff --git a/src/serial.c b/src/serial.c index a025ae9..66ee756 100644 --- a/src/serial.c +++ b/src/serial.c @@ -27,7 +27,7 @@ */ /*! \file serial.c - * \file Osmocom serial port helpers + * Osmocom serial port helpers */ #include diff --git a/src/socket.c b/src/socket.c index a5530d0..6ff00f0 100644 --- a/src/socket.c +++ b/src/socket.c @@ -129,7 +129,7 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, } /*! \brief Initialize a socket and fill \ref osmo_fd - * \param[out] osmocom file descriptor (will be filled in) + * \param[out] ofd file descriptor (will be filled in) * \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC * \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM * \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP diff --git a/src/timer.c b/src/timer.c index 98cbf6e..5988aef 100644 --- a/src/timer.c +++ b/src/timer.c @@ -128,7 +128,7 @@ int osmo_timer_pending(struct osmo_timer_list *timer) /*! \brief compute the remaining time of a timer * \param[in] timer the to-be-checked timer - * \param[in] the current time (NULL if not known) + * \param[in] now the current time (NULL if not known) * \param[out] remaining remaining time until timer fires * \return 0 if timer has not expired yet, -1 if it has * -- 1.7.9.5 From holger at freyther.de Fri Feb 15 12:19:57 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Fri, 15 Feb 2013 13:19:57 +0100 Subject: [PATCH] Doxygen tweaks: fixed a lot of typos and minor errors (amended) In-Reply-To: References: Message-ID: <20130215121957.GF615@xiaoyu.lan> On Thu, Feb 14, 2013 at 07:12:43AM +0100, Katerina Barone-Adesi wrote: Dear Katerina, thanks a lot for the patience to walk through these errors. There appears to be a minor technical issue with the way you sent the patch (it probably applies to the previous patches too) > @@ -54,4 +54,6 @@ int gsmtap_send(struct gsmtap_inst *gti, uint16_t > arfcn, uint8_t ts, Someone decided to wrap the line here, e.g. it could be gmail. The easiest for us would be to either send the patches as attachment (making it a bit more difficult to comment) or use git send-email and submit directly via SMTP. kind regards holger PS: I will fix the patch by hand, no need to resend it From andreas at eversberg.eu Thu Feb 14 10:10:11 2013 From: andreas at eversberg.eu (jolly) Date: Thu, 14 Feb 2013 11:10:11 +0100 Subject: disable jitter RTP buffer at libosmo-abis Message-ID: <511CB803.5000709@eversberg.eu> hi, just had problems with jitter of RTP via wireless lan. changing size of jitter buffer did not solve the problems, packets got dropped. this patch allows to disables the jitter buffer, if a jitter value of 0 is given. regards, andreas -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: 0001-RTP-Allow-disabling-jitter-buffer-by-setting-a-buffe.patch URL: From jolly at eversberg.eu Thu Feb 14 10:03:26 2013 From: jolly at eversberg.eu (Andreas Eversberg) Date: Thu, 14 Feb 2013 11:03:26 +0100 Subject: [PATCH] RTP: Allow disabling jitter buffer by setting a buffer size of 0 Message-ID: --- src/trau/osmo_ortp.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/src/trau/osmo_ortp.c b/src/trau/osmo_ortp.c index a9503ea..6d3db58 100644 --- a/src/trau/osmo_ortp.c +++ b/src/trau/osmo_ortp.c @@ -258,7 +258,10 @@ int osmo_rtp_socket_set_param(struct osmo_rtp_socket *rs, switch (param) { case OSMO_RTP_P_JITBUF: - rtp_session_set_jitter_compensation(rs->sess, val); + rtp_session_enable_jitter_buffer(rs->sess, + (val) ? TRUE : FALSE); + if (val) + rtp_session_set_jitter_compensation(rs->sess, val); break; #if 0 case OSMO_RTP_P_JIT_ADAP: -- 1.7.3.4 --------------090702060102080101070403-- From laforge at gnumonks.org Thu Feb 14 16:23:17 2013 From: laforge at gnumonks.org (Harald Welte) Date: Thu, 14 Feb 2013 17:23:17 +0100 Subject: disable jitter RTP buffer at libosmo-abis In-Reply-To: <511CB803.5000709@eversberg.eu> References: <511CB803.5000709@eversberg.eu> Message-ID: <20130214162317.GA24802@prithivi.gnumonks.org> On Thu, Feb 14, 2013 at 11:10:11AM +0100, jolly wrote: > just had problems with jitter of RTP via wireless lan. changing size of > jitter buffer did not solve the problems, packets got dropped. this > patch allows to disables the jitter buffer, if a jitter value of 0 is given. 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 holger at freyther.de Fri Feb 15 12:09:38 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Fri, 15 Feb 2013 13:09:38 +0100 Subject: disable jitter RTP buffer at libosmo-abis In-Reply-To: <511CB803.5000709@eversberg.eu> References: <511CB803.5000709@eversberg.eu> Message-ID: <20130215120938.GE615@xiaoyu.lan> On Thu, Feb 14, 2013 at 11:10:11AM +0100, jolly wrote: > hi, > > just had problems with jitter of RTP via wireless lan. changing size of > jitter buffer did not solve the problems, packets got dropped. this > patch allows to disables the jitter buffer, if a jitter value of 0 is given. Dear Andreas, do you happen to have a PCAP file of the stream arriving at the BTS? I had a lot of issues with FreeSWITCH and their jitter buffer and as a minimum I would like to at least have the right inspection/logging to detect/analyze these issues. holger From andreas at eversberg.eu Fri Feb 15 18:27:16 2013 From: andreas at eversberg.eu (Andreas Eversberg) Date: Fri, 15 Feb 2013 19:27:16 +0100 Subject: disable jitter RTP buffer at libosmo-abis In-Reply-To: <20130215120938.GE615@xiaoyu.lan> References: <511CB803.5000709@eversberg.eu> <20130215120938.GE615@xiaoyu.lan> Message-ID: <511E7E04.7090004@eversberg.eu> Holger Hans Peter Freyther wrote: > do you happen to have a PCAP file of the stream arriving at the BTS? I > had a lot of issues with FreeSWITCH and their jitter buffer and as a > minimum I would like to at least have the right inspection/logging to > detect/analyze these issues. hi holger, i traced data between openbsc and osmo-bts. i put a sequence number in the payload to see, if packets get dropped. i could see that the wireshark actually showed the missing frames. also i put debug into libortp to see if they arrive there, they do! the jitter algorithm just dropped them. for my case (lcr) i did a 30 minutes call today using osmo-bts (calypso-bts) and openbsc-lcr. it worked best, without any raising delay. i think that my setup (slow netbook, many processes) does not get well with jitter buffer of libortp. regards, andreas From sega at unix.lv Sun Feb 17 16:42:58 2013 From: sega at unix.lv (Sergei Oleinikov) Date: Sun, 17 Feb 2013 18:42:58 +0200 Subject: GPRS not coming up on NanoBTS 140 Message-ID: <1361119378.31327.11.camel@segamza> Hello All, can not run GPRS on nanoBTS 140 (1900 version) everything looks good, but it is impossible to connect .. do not see any new messages between nanoBTS and SGSN, only some keep-alives ? (please find attached PCAP file) everything you can find below, please sorry for flood :( part of OpeBSC config: gprs mode gprs gprs routing area 10 gprs cell bvci 2 gprs nsei 101 gprs nsvc 0 nsvci 101 gprs nsvc 0 local udp port 23000 gprs nsvc 0 remote udp port 23000 gprs nsvc 0 remote ip 192.168.24.26 trx 0 rf_locked 0 arfcn 560 nominal power 23 max_power_red 0 rsl e1 tei 0 timeslot 0 phys_chan_config CCCH+SDCCH4 timeslot 1 phys_chan_config SDCCH8 timeslot 2 phys_chan_config TCH/F timeslot 3 phys_chan_config PDCH timeslot 4 phys_chan_config PDCH timeslot 5 phys_chan_config PDCH timeslot 6 phys_chan_config PDCH timeslot 7 phys_chan_config PDCH part of OpenBSC console: <0019> input/ipa.c:322 accept()ed new link from 192.168.24.162 to port 3003 <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,00) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=BTS(01) INST=(00,ff,ff) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=BASEBAND-TRANSCEIVER(04) INST=(00,00,ff) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=RADIO-CARRIER(02) INST=(00,00,ff) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,00) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,01) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,01) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,01) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,02) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,02) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,02) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,03) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,03) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,03) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=GPRS-CELL(f1) INST=(00,00,ff) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=GPRS-CELL(f1) INST=(00,00,ff) STATE CHG: OP_STATE=Disabled AVAIL=Failed(01) ADM=Unlocked <0005> abis_nm.c:315 OC=GPRS-CELL(f1) INST=(00,00,ff) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:1757 OC=GPRS-CELL(f1) INST=(00,00,ff) Sending OPSTART <0005> abis_nm.c:315 OC=GPRS-CELL(f1) INST=(00,00,ff) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=GPRS-CELL(f1) INST=(00,00,ff) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,04) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,04) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,04) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,05) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,05) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,05) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,06) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,06) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,06) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,07) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,07) STATE CHG: OP_STATE=Disabled AVAIL=Dependency(05) ADM=Unlocked <0005> abis_nm.c:315 OC=CHANNEL(03) INST=(00,00,07) STATE CHG: OP_STATE=Enabled ADM=Unlocked <0005> abis_nm.c:2418 OC=GPRS-CELL(f1) INST=(00,00,ff) IPACCESS(0xf6): SET ATTR ACK SGSN config: sgsn gtp local-ip 192.168.24.26 ggsn 0 remote-ip 192.168.24.25 ggsn 0 gtp-version 1 ns timer tns-block 3 timer tns-block-retries 3 timer tns-reset 3 timer tns-reset-retries 3 timer tns-test 30 timer tns-alive 3 timer tns-alive-retries 10 encapsulation udp local-ip 192.168.24.26 encapsulation udp local-port 23000 encapsulation framerelay-gre enabled 0 bssgp SGSN console: <0010> gprs_ns.c:679 NSEI=101 Rx NS RESET (NSVCI=101, cause=O&M intervention) <0010> gprs_ns.c:538 NSEI=101 Tx NS RESET ACK (NSVCI=101) <0010> gprs_ns.c:679 NSEI=101 Rx NS RESET (NSVCI=101, cause=O&M intervention) <0010> gprs_ns.c:538 NSEI=101 Tx NS RESET ACK (NSVCI=101) <0010> gprs_ns.c:865 NSEI=101 Rx NS UNBLOCK <0011> gprs_bssgp.c:249 BSSGP BVCI=0 Rx RESET cause=Transmission capacity modified <0011> gprs_bssgp.c:249 BSSGP BVCI=2 Rx RESET cause=O&M intervention <0011> gprs_bssgp.c:272 Cell 247-9-10-10 CI 10201 on BVCI 2 <0011> gprs_bssgp.c:306 BSSGP Rx BVCI=2 BVC-BLOCK <0011> gprs_bssgp.c:344 BSSGP BVCI=2 Rx BVC-UNBLOCK <0011> gprs_bssgp.c:747 BSSGP BVCI=2 Rx Flow Control BVC nanoBTS: MAC_Address='00:02:95:00:0b:8d' IP_Address='192.168.24.162' Unit_ID='1/0/0' Location_1='' Location_2='BTS_NBT131G' Equipment_Version='140_029_24' Software_Version='120a002_v149b44d0' nanoBTS Boot messages: 4050:DBG:CLI_SKT:Remote client 192.168.24.25 connected 4103:DBG:IP_CHAN_SERVER:Created server listening on port 80 4470:DBG:OAM_IM:Started "Primary OML Fallback Client" 4470:DBG:OAM_IM:Started "Secondary OML Server" 4470:DBG:OAM_IM:"IML Site Server": not starting 4470:DBG:OAM_IM:(Not started "IML Site Server") 4470:DBG:OAM_IM:"IML Bts Server": not starting 4470:DBG:OAM_IM:(Not started "IML Bts Server") 4470:DBG:OAM_IM:"IRL Patched Routing Link": not starting 4470:DBG:OAM_IM:(Not started "IRL Patched Routing Link") 4473:DBG:IP_CHANNEL:Assigning RX Client A 4474:DBG:IP_CHAN_RX_A:Attempting connection to 192.168.24.25:3002 4482:DBG:IP_CHAN_SERVER:Created server listening on port 3006 4497:DBG:IDLE:All tasks activated. 5289:DBG:OAM_IM:Set SYSTEM LINK to 40.255 5332:DBG:OAM_MOI:Can Activate?=TRUE 5332:DBG:OAM_MOI:Sw Activate - activating BH idx=0 5332:DBG:OAM_MOI:Sw Activate - BH(def=0 act=0) TRX(def=0 act=157) 5333:DBG:OAM_IM:roleInstanceProcClearContaineeFlags: BTS:0 flag 3 not setting or set! 5333:DBG:OAM_IM:roleInstanceProcClearContaineeFlags: GPRS NSE:0 flag 3 not setting or set! 5344:DBG:OAM_MOI:Can Activate?=TRUE 5344:DBG:OAM_MOI:Sw Activate - already activated BH idx=0 5344:DBG:OAM_MOI:Sw Activate - BH(def=0 act=0) TRX(def=0 act=29) 5345:DBG:OAM_MOI:Can Activate?=TRUE 5345:DBG:OAM_MOI:Sw Activate - already activated BH idx=0 5345:DBG:OAM_MOI:Sw Activate - BH(def=0 act=0) TRX(def=0 act=157) 5347:DBG:GB_OAM:Received OPEN_REQ for NSE 0. 5356:DBG:OAM_MOI:oid=BTS:0 publisher attributes set 5358:DBG:OAM_MOI:Can Activate?=TRUE 5358:DBG:OAM_MOI:Sw Activate - already activated BH idx=0 5358:DBG:OAM_MOI:Sw Activate - sending trx boot request to activate TRX idx=0 5358:DBG:OAM_MOI:Sw Activate - BH(def=0 act=0) TRX(def=0 act=0) 5359:DBG:OAM_MOI:Can Activate?=TRUE 5359:DBG:OAM_MOI:Sw Activate - already activated BH idx=0 5359:DBG:OAM_MOI:Sw Activate - already activated TRX idx=0 5359:DBG:OAM_MOI:Sw Activate - BH(def=0 act=0) TRX(def=0 act=0) 5362:DBG:OAM_MOI:Can Activate?=TRUE 5362:DBG:OAM_MOI:Sw Activate - already activated BH idx=0 5362:DBG:OAM_MOI:Sw Activate - BH(def=0 act=0) TRX(def=0 act=0) 5367:DBG:GB_OAM:PDU_GPRS_HEADER_SIZE = 24 5367:DBG:GB_OAM:PDU_GPRS_HEADER_PADDING (paramStart) = 4 5367:DBG:GB_OAM:PDU_GPRS_OUR_HSS_HEADER_SIZE = 28 5367:DBG:GB_OAM:PDU_GPRS_HSS_MALLOC_PADDING = 0 5367:DBG:GB_OAM:PDU_GPRS_UL_HEAD_RESERVED_BYTES = 24 5367:DBG:GB_OAM:PDU_GPRS_UL_TAIL_RESERVED_BYTES = 0 5367:DBG:GB_OAM:PDU_GPRS_DL_HEAD_RESERVED_BYTES = 0 5367:DBG:GB_OAM:PDU_GPRS_DL_TAIL_RESERVED_BYTES = 0 5368:DBG:GBHSS_STACK:Fixing PDU 4371 length: paramSize = 5, totalSize = 4 5371:DBG:OAM_MOI:oid=GPRS NSE:0 subscriber attributes set 5371:DBG:OAM_MOI:oid=GPRS NSE:0 publisher attributes set 5372:DBG:OAM_MOI:Can Activate?=TRUE 5372:DBG:OAM_MOI:Sw Activate - already activated BH idx=0 5372:DBG:OAM_MOI:Sw Activate - BH(def=0 act=0) TRX(def=0 act=0) 5373:DBG:OAM_MOI:Can Activate?=TRUE 5373:DBG:OAM_MOI:Sw Activate - already activated BH idx=0 5373:DBG:OAM_MOI:Sw Activate - BH(def=0 act=0) TRX(def=0 act=0) 5375:DBG:OAM_MOI:oid=GPRS Cell:0-0 publisher attributes set 5376:DBG:GB_OAM:Received OPEN_REQ for NSVC 0. 5376:DBG:GB_OAM:Received OPEN_REQ for NSVC 1. 5377:DBG:TRX_BOOT:CLI Uart disabled during TRX boot procedure, in 5... 5402:DBG:GBHSS_STACK:nsvc = [101], src_ip = [C0A818A2], src_port = [23000], dst_ip = [C0A8181A],dst_port = [23000], 5402:DBG:GBHSS_STACK:A new socket created for (IP,Port) 5403:DBG:OAM_MOI:oid=GPRS NSVC:0-0 subscriber attributes set 5403:DBG:OAM_MOI:oid=GPRS NSVC:0-0 publisher attributes set 5415:DBG:GB_OAM:oamDeviceSendOnCnf(6,0). 5415:DBG:OAM_RES:[RES_MGR]<--ResOnCnf--[RES] not sent. 5416:DBG:GB_OAM:oamDeviceSendOnCnf(7,0). 5416:DBG:OAM_RES:[RES_MGR]<--ResOnCnf--[RES] not sent. 6459:DBG:TRX_BOOT:Booting TRX image idx=0 6656:DBG:TRX_BOOT:Got ACK from ULM 8336:DBG:TRX_BOOT:Downloaded ChangeBaudMst to ULM 8439:DBG:TRX_BOOT:DEBUG from TRX: ChangeBaudMst. 9228:DBG:TRX_BOOT:DEBUG from TRX: FPGA Reports (Ver: 0x0300) 10216:DBG:TRX_BOOT:DEBUG from TRX: FPGA SRAM pass=1 10385:DBG:TRX_BOOT:DEBUG from TRX: FPGA HDLC Loopback finished: Packet Errors=0 Byte Errors=0 10398:DBG:TRX_BOOT:Got POST msg for ULM: All OK 10416:DBG:TRX_BOOT:Got Image Req msg ImageId [0x1004] 10517:DBG:TRX_BOOT:ULM has requested baud rate change to 38400 10535:DBG:TRX_BOOT:Changed baud OK 10574:DBG:TRX_BOOT:DEBUG from TRX: Masterloader. 12949:DBG:TRX_BOOT:DEBUG from TRX: ChangeBaudSlv downloaded to ULS 12994:DBG:TRX_BOOT:DEBUG from TRX: Changed baud OK 15291:DBG:TRX_BOOT:DEBUG from TRX: ChangeBaudSlv downloaded to DLP 15337:DBG:TRX_BOOT:DEBUG from TRX: Changed baud OK 15350:DBG:TRX_BOOT:Got POST msg for ULS: All OK 16028:DBG:TRX_BOOT:Got POST msg for DLP: All OK 16115:DBG:TRX_BOOT:DEBUG from TRX: Got Image Req msg ImageId [0x1003] 16308:DBG:TRX_BOOT:DEBUG from TRX: Got Image Req msg ImageId [0x1003] 16477:DBG:TRX_BOOT:DEBUG from TRX: Changed baud OK 16564:DBG:TRX_BOOT:DEBUG from TRX: Got Image Req msg ImageId [0x1009] 16581:DBG:TRX_BOOT:Got Image Req msg ImageId [0x1008] 17038:DBG:TRX_BOOT:DEBUG from TRX: Changed baud OK 17125:DBG:TRX_BOOT:DEBUG from TRX: Got Image Req msg ImageId [0x1009] 17142:DBG:TRX_BOOT:Got Image Req msg ImageId [0x1009] 17654:DBG:TRX_BOOT:Got Image Req msg ImageId [0x1007] 18100:DBG:TRX_BOOT:TRX status report: Application code activated 18280:DBG:TRX_BOOT:Booted TRX idx=0 18280:DBG:RSL:478:rsl: EVENT 0x00000bc9 rxd in STATE initial 18280:DBG:RSL:478:rsl: ENTERING open 19266:DBG:GENIE_SERVER:TRX now ready for genie signals. 19613:DBG:RSL:714:rsl: EVENT 0x00000bca rxd in STATE opennotconnected 19617:DBG:OAM_MOI:oid=BBTRX:0-0 subscriber attributes set 19617:DBG:OAM_MOI:oid=BBTRX:0-0 publisher attributes set 19620:DBG:OAM_MOI:oid=GPRS Cell:0-0 subscriber attributes set 19621:DBG:OAM_MOI:oid=Carrier:0-0 subscriber attributes set 19621:DBG:OAM_MOI:oid=Carrier:0-0 publisher attributes set 19637:DBG:RSL:871:rsl: EVENT 0x00000bc8 rxd in STATE offnotconnected 19637:DBG:RSL:871:rsl: ENTERING on nanoBTS console: >res::info ----- TRX Status ----- activated=1 attempts(num=07 peak=07 max=25) responding=1 attempts(num=00 peak=01 max=05) ----- Resources ----- [Baseband Transceiver][0] on [ Channel][0] on [ Channel][1] on [ Channel][2] on [ Channel][3] on [ Channel][4] on [ Channel][5] on [ Channel][6] on [ Channel][7] on [ Radio Carrier][0] on [ RSL][0] on [ Alarm][0] on [ TIB][0] on [ GPRS NSE][0] on [ GPRS NSVC][0] on [ GPRS NSVC][1] off [ GPRS Cell][0] on [ GPRS PDCH][0] off [ GPRS PDCH][1] off [ GPRS PDCH][2] off [ GPRS PDCH][3] on [ GPRS PDCH][4] on [ GPRS PDCH][5] on [ GPRS PDCH][6] on [ GPRS PDCH][7] on >moi::info ----- MOI Info ----- [ Site] 4 (noadminstatenotinproc) (active) [ BTS:0] 6 (unlockednotinproc) band="PCS 1900" arfcn=560 (valid=1) bsic=63 (active) [ BBTRX:0-0] 11 (unlockednotinproc) (active) [ Channel:0-0-0] 17 (unlockednotinproc) BCCH (Combined) (other) [ Channel:0-0-1] 24 (unlockednotinproc) SDCCH (other) [ Channel:0-0-2] 31 (unlockednotinproc) TCH (Full) (other) [ Channel:0-0-3] 38 (unlockednotinproc) PDCH (pdch) [ Channel:0-0-4] 45 (unlockednotinproc) PDCH (pdch) [ Channel:0-0-5] 52 (unlockednotinproc) PDCH (pdch) [ Channel:0-0-6] 59 (unlockednotinproc) PDCH (pdch) [ Channel:0-0-7] 66 (unlockednotinproc) PDCH (pdch) [ Carrier:0-0] 73 (unlockednotinproc) (active) [ GPRS NSE:0] 82 (unlockednotinproc) (active) [ GPRS Cell:0-0] 89 (unlockednotinproc) (active) [ GPRS NSVC:0-0] 104 (unlockednotinproc) (active) [ GPRS NSVC:0-1] 109 (lockednotinproc) (active) > > >moi::states ----- MOI States ----- [ Site] (invalid), Enabled, [ BTS:0] Unlocked, Enabled, [ BBTRX:0-0] Unlocked, Enabled, [ Channel:0-0-0] Unlocked, Enabled, [ Channel:0-0-1] Unlocked, Enabled, [ Channel:0-0-2] Unlocked, Enabled, [ Channel:0-0-3] Unlocked, Enabled, [ Channel:0-0-4] Unlocked, Enabled, [ Channel:0-0-5] Unlocked, Enabled, [ Channel:0-0-6] Unlocked, Enabled, [ Channel:0-0-7] Unlocked, Enabled, [ Carrier:0-0] Unlocked, Enabled, [ GPRS NSE:0] Unlocked, Enabled, [ GPRS Cell:0-0] Unlocked, Enabled, [ GPRS NSVC:0-0] Unlocked, Enabled, [ GPRS NSVC:0-1] (invalid), Disabled, > nanoBTS debug info: PktResReq 0xffb9027f = 17 df 41 9a cf e8 f4 a2 ae 57 .?A?? ????W 0xffb90289 = ef 90 90 04 01 10 00 07 e0 08 ?.. ...?. 0xffb90293 = 8b 2b b3 00 00 c3 68 00 00 fc ?+?.. ?h..? 12121:DBG:RM:!!! unpackPacketResourceRequest() : -2147483647 : General function failure 12731:DBG:RM:!!! bitUnpackRadioAccessCapability() - numRaCap=0 12732:DBG:RM:!!! bitUnpackRadioAccessCapability() : -2147483647 : General function failure PktResReq 0xffb92697 = 17 df 41 9a cf e8 f4 a2 ae 57 .?A?? ????W 0xffb926a1 = ef 90 90 04 01 10 00 07 e0 08 ?.. ...?. 0xffb926ab = 8b 2b 86 00 00 c3 68 00 00 fc ?+?.. ?h..? 12732:DBG:RM:!!! unpackPacketResourceRequest() : -2147483647 : General function failure 13142:DBG:RM:TBF=88 (U/L) - STATS: Immediate Assignment failure (timeout). 13342:DBG:RM:!!! bitUnpackRadioAccessCapability() - numRaCap=0 13343:DBG:RM:!!! bitUnpackRadioAccessCapability() : -2147483647 : General function failure PktResReq 0xffb91f5f = 17 df 41 9a cf e8 f4 a2 ae 57 .?A?? ????W 0xffb91f69 = ef 90 90 04 01 10 00 07 e0 08 ?.. ...?. 0xffb91f73 = 8b 2b a5 a5 a5 a5 a5 a5 a5 a5 ?+??? ????? 13343:DBG:RM:!!! unpackPacketResourceRequest() : -2147483647 : General function failure 13752:DBG:RM:TBF=89 (U/L) - STATS: Immediate Assignment failure (timeout). 13953:DBG:RM:!!! bitUnpackRadioAccessCapability() - numRaCap=0 13954:DBG:RM:!!! bitUnpackRadioAccessCapability() : -2147483647 : General function failure PktResReq 0xffb91827 = 17 df 41 9a cf e8 f4 a2 ae 57 .?A?? ????W 0xffb91831 = ef 90 90 04 01 10 00 07 e0 08 ?.. ...?. 0xffb9183b = 8b 2b 00 10 5b a5 a5 a5 a5 a5 ?+..[ ????? 13954:DBG:RM:!!! unpackPacketResourceRequest() : -2147483647 : General function failure 14366:DBG:RM:TBF=90 (U/L) - STATS: Immediate Assignment failure (timeout). 14977:DBG:RM:TBF=91 (U/L) - STATS: Immediate Assignment failure (timeout). Br, Sergei -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: face-sad.png Type: image/png Size: 1592 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: sgsn_nanobts.pcap Type: application/vnd.tcpdump.pcap Size: 11224 bytes Desc: not available URL: From jengelh at inai.de Sun Feb 17 19:42:55 2013 From: jengelh at inai.de (Jan Engelhardt) Date: Sun, 17 Feb 2013 20:42:55 +0100 Subject: [PATCH] build: resolve link failure in libosmogsm when --disable-talloc is used Message-ID: <1361130175-2331-1-git-send-email-jengelh@inai.de> The link stage fails at some point. libosmogsm.so:lapd-core.c uses talloc_free, but does not link to libtalloc.so. Correct this. CCLD osmo-arfcn ../src/gsm/.libs/libosmogsm.so: undefined reference to `talloc_free' collect2: error: ld returned 1 exit status make[2]: *** [osmo-arfcn] Error 1 --- src/gsm/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index b72a8d4..237e134 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -23,5 +23,8 @@ libosmogsm_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c gsm_utils.c \ libosmogsm_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libosmogsm.map -version-info $(LIBVERSION) libosmogsm_la_LIBADD = $(top_builddir)/src/libosmocore.la +if !ENABLE_TALLOC +libosmogsm_la_LIBDADD = -ltalloc +endif EXTRA_DIST = libosmogsm.map -- 1.7.10.4 From holger at freyther.de Mon Feb 18 14:47:27 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Mon, 18 Feb 2013 15:47:27 +0100 Subject: [PATCH] build: resolve link failure in libosmogsm when --disable-talloc is used In-Reply-To: <1361130175-2331-1-git-send-email-jengelh@inai.de> References: <1361130175-2331-1-git-send-email-jengelh@inai.de> Message-ID: <20130218144727.GA12835@xiaoyu.lan> On Sun, Feb 17, 2013 at 08:42:55PM +0100, Jan Engelhardt wrote: Hi, > The link stage fails at some point. libosmogsm.so:lapd-core.c uses > talloc_free, but does not link to libtalloc.so. Correct this. Disabling talloc is only supported for the OsmocomBB use case. I understand that many distributions ship a standalone libtalloc by now and we should find ways to support it but your patch doesn't look like the solution to the problem. E.g. a solution would include: * Detecting the system talloc * Not installing the osmocom/core/talloc.h or finding a header file that will just include_next talloc.h for the real talloc. This is important as there is no gurantee that osmocom/core/talloc.h and talloc.h are compatible with each other. thanks holger From peter at stuge.se Mon Feb 18 14:57:15 2013 From: peter at stuge.se (Peter Stuge) Date: Mon, 18 Feb 2013 15:57:15 +0100 Subject: [PATCH] build: resolve link failure in libosmogsm when --disable-talloc is used In-Reply-To: <1361130175-2331-1-git-send-email-jengelh@inai.de> References: <1361130175-2331-1-git-send-email-jengelh@inai.de> Message-ID: <20130218145715.18568.qmail@stuge.se> Jan Engelhardt wrote: > diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am > index b72a8d4..237e134 100644 > --- a/src/gsm/Makefile.am > +++ b/src/gsm/Makefile.am > @@ -23,5 +23,8 @@ libosmogsm_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c gsm_utils.c \ > > libosmogsm_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libosmogsm.map -version-info $(LIBVERSION) > libosmogsm_la_LIBADD = $(top_builddir)/src/libosmocore.la > +if !ENABLE_TALLOC > +libosmogsm_la_LIBDADD = -ltalloc > +endif It seems wrong to use libtalloc when --disable-talloc is used? Why not fix the code to not use talloc_free() instead? And another thing, was there only an error about talloc_free()? That would mean an imbalance in the code which should be fixed.. //Peter From kat.obsc at gmail.com Sun Feb 17 19:44:01 2013 From: kat.obsc at gmail.com (Katerina Barone-Adesi) Date: Sun, 17 Feb 2013 19:44:01 +0000 Subject: [PATCH] Added a ring buffer log target to store the last N log messages. Message-ID: <1361130241-1817-1-git-send-email-kat.obsc@gmail.com> The log target can be used via log alarms and show alarms. Why? This feature was proposed/requested at http://openbsc.osmocom.org/trac/wiki/Tasks/ErrorLogTarget All messages use the same amount of space, prioritizing simplicity. Renames as per tnt's request. --- .gitignore | 2 + include/osmocom/core/logging.h | 5 + include/osmocom/core/loggingrb.h | 40 +++++++ include/osmocom/core/strrb.h | 58 ++++++++++ src/Makefile.am | 4 +- src/loggingrb.c | 98 +++++++++++++++++ src/strrb.c | 169 +++++++++++++++++++++++++++++ src/vty/logging_vty.c | 85 ++++++++++++++- tests/Makefile.am | 13 ++- tests/loggingrb/logging_test.err | 3 + tests/loggingrb/logging_test.ok | 0 tests/loggingrb/loggingrb_test.c | 83 +++++++++++++++ tests/strrb/strrb_test.c | 225 +++++++++++++++++++++++++++++++++++++++ tests/strrb/strrb_test.ok | 1 + tests/testsuite.at | 13 +++ 15 files changed, 791 insertions(+), 8 deletions(-) create mode 100644 include/osmocom/core/loggingrb.h create mode 100644 include/osmocom/core/strrb.h create mode 100644 src/loggingrb.c create mode 100644 src/strrb.c create mode 100644 tests/loggingrb/logging_test.err create mode 100644 tests/loggingrb/logging_test.ok create mode 100644 tests/loggingrb/loggingrb_test.c create mode 100644 tests/strrb/strrb_test.c create mode 100644 tests/strrb/strrb_test.ok diff --git a/.gitignore b/.gitignore index 24ca677..aedd9fd 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,8 @@ tests/gb/bssgp_fc_test tests/gsm0408/gsm0408_test tests/logging/logging_test tests/fr/fr_test +tests/loggingrb/loggingrb_test +tests/ringbuf/ringbuf_test utils/osmo-arfcn utils/osmo-auc-gen diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index 655f7a4..c8413af 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -114,6 +114,7 @@ enum log_target_type { LOG_TGT_TYPE_SYSLOG, /*!< \brief syslog based logging */ LOG_TGT_TYPE_FILE, /*!< \brief text file logging */ LOG_TGT_TYPE_STDERR, /*!< \brief stderr logging */ + LOG_TGT_TYPE_STRRB, /*!< \brief osmo_strrb-backed logging */ }; /*! \brief structure representing a logging target */ @@ -154,6 +155,10 @@ struct log_target { struct { void *vty; } tgt_vty; + + struct { + void *rb; + } tgt_rb; }; /*! \brief call-back function to be called when the logging framework diff --git a/include/osmocom/core/loggingrb.h b/include/osmocom/core/loggingrb.h new file mode 100644 index 0000000..a6f377b --- /dev/null +++ b/include/osmocom/core/loggingrb.h @@ -0,0 +1,40 @@ +#ifndef _LOGGINGRB_H +#define _LOGGINGRB_H + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + + +/*! \defgroup loggingrb Osmocom ringbuffer-backed logging + * @{ + */ + +/*! \file loggingrb.h + */ + +struct log_info; + +size_t log_target_rb_used_size(struct log_target const *target); +size_t log_target_rb_avail_size(struct log_target const *target); +const char *log_target_rb_get(struct log_target const *target, size_t logindex); +struct log_target *log_target_create_rb(size_t size); + +/*! @} */ + +#endif /* _LOGGINGRB_H */ diff --git a/include/osmocom/core/strrb.h b/include/osmocom/core/strrb.h new file mode 100644 index 0000000..cfc56dc --- /dev/null +++ b/include/osmocom/core/strrb.h @@ -0,0 +1,58 @@ +#ifndef _STRRB_H +#define _STRRB_H + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + +/*! \defgroup osmo_strrb Osmocom ringbuffers for log strings + * @{ + */ + +/*! \file strrb.h + * \brief Osmocom string ringbuffer handling routines + */ + +#include +#include +#include + +#include + +/*! \brief A structure representing an osmocom string ringbuffer */ + +#define RB_MAX_MESSAGE_SIZE 240 +struct osmo_strrb { + uint16_t start; /*!< \brief index of the first slot */ + uint16_t end; /*!< \brief index of the last slot */ + uint16_t size; /*!< \brief max number of messages to store */ + char **buffer; /*!< \brief storage for messages */ +}; + +struct osmo_strrb *osmo_strrb_create(TALLOC_CTX * ctx, size_t rb_size); +bool osmo_strrb_is_empty(const struct osmo_strrb *rb); +const char *osmo_strrb_get_nth(const struct osmo_strrb *rb, + unsigned int string_index); +bool _osmo_strrb_is_bufindex_valid(const struct osmo_strrb *rb, + unsigned int offset); +size_t osmo_strrb_elements(const struct osmo_strrb *rb); +int osmo_strrb_add(struct osmo_strrb *rb, const char *data); + +/*! @} */ + +#endif /* _STRRB_H */ diff --git a/src/Makefile.am b/src/Makefile.am index b425ea1..081be96 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,8 +11,8 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.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 \ - crc8gen.c crc16gen.c crc32gen.c crc64gen.c + conv.c application.c rbtree.c strrb.c \ + loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c diff --git a/src/loggingrb.c b/src/loggingrb.c new file mode 100644 index 0000000..bb339eb --- /dev/null +++ b/src/loggingrb.c @@ -0,0 +1,98 @@ +/* Ringbuffer-backed logging support code */ + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + +/*! \addtogroup logging + * @{ + */ + +/*! \file loggingrb.c */ + +#include +#include +#include + +static void _rb_output(struct log_target *target, + unsigned int level, const char *log) +{ + osmo_strrb_add(target->tgt_rb.rb, log); +} + +/*! \brief Return the number of log strings in the osmo_strrb-backed target. + * \param[in] target The target to search. + * + * \return The number of log strings in the osmo_strrb-backed target. + */ +size_t log_target_rb_used_size(struct log_target const *target) +{ + return osmo_strrb_elements(target->tgt_rb.rb); +} + +/*! \brief Return the capacity of the osmo_strrb-backed target. + * \param[in] target The target to search. + * + * Note that this is the capacity (aka max number of messages +1). + * It is not the number of unused message slots. + * \return The number of log strings in the osmo_strrb-backed target. + */ +size_t log_target_rb_avail_size(struct log_target const *target) +{ + struct osmo_strrb *rb = target->tgt_rb.rb; + return rb->size; +} + +/*! \brief Return the nth log entry in a target. + * \param[in] target The target to search. + * \param[in] logindex The index of the log entry/error message. + * + * \return A pointer to the nth message, or NULL if logindex is invalid. + */ +const char *log_target_rb_get(struct log_target const *target, size_t logindex) +{ + return osmo_strrb_get_nth(target->tgt_rb.rb, logindex); +} + +/*! \brief Create a new logging target for ringbuffer-backed logging. + * \param[in] size The size of the internal backing osmo_strrb (messages +1). + * \returns A log target in case of success, NULL in case of error. + */ +struct log_target *log_target_create_rb(size_t size) +{ + struct log_target *target; + struct osmo_strrb *rb; + + target = log_target_create(); + if (!target) + return NULL; + + rb = osmo_strrb_create(target, size); + if (!rb) { + log_target_destroy(target); + return NULL; + } + + target->tgt_rb.rb = rb; + target->type = LOG_TGT_TYPE_STRRB; + target->output = _rb_output; + + return target; +} + +/* @} */ diff --git a/src/strrb.c b/src/strrb.c new file mode 100644 index 0000000..bed09c5 --- /dev/null +++ b/src/strrb.c @@ -0,0 +1,169 @@ +/* Ringbuffer implementation, tailored for logging. + * This is a lossy ringbuffer. It keeps up to N of the newest messages, + * overwriting the oldest as newer ones come in. + * + * (C) 2012-2013, Katerina Barone-Adesi + * 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. + * + */ + +/*! \file strrb.c + * \brief Lossy string ringbuffer for logging; keeps newest messages. + */ + +#include +#include +#include + +#include + +/* Ringbuffer assumptions, invarients, and notes: + * - start is the index of the first used index slot in the ring buffer. + * - end is the index of the next index slot in the ring buffer. + * - start == end => buffer is empty + * - Consequence: the buffer can hold at most size - 1 messages + * (if this were not the case, full and empty buffers would be indistinguishable + * given the conventions in this implementation). + * - Whenever the ringbuffer is full, start is advanced. The second oldest + * message becomes unreachable by valid indexes (end is not a valid index) + * and the oldest message is overwritten (if there was a message there, which + * is the case unless this is the first time the ringbuffer becomes full). +*/ + +/*! \brief Create an empty, initialized osmo_strrb. + * \param[in] ctx The talloc memory context which should own this. + * \param[in] rb_size The number of message slots in the osmo_strrb. + * \returns A struct osmo_strrb* on success, NULL in case of error. + * + * This function creates and initializes a ringbuffer. + * Note that the ringbuffer stores at most rb_size - 1 messages. + */ + +struct osmo_strrb *osmo_strrb_create(TALLOC_CTX * ctx, size_t rb_size) +{ + struct osmo_strrb *rb = NULL; + unsigned int i; + + rb = talloc_zero(ctx, struct osmo_strrb); + if (!rb) + goto alloc_error; + rb->buffer = talloc_array(rb, char *, rb_size); + if (!rb->buffer) + goto alloc_error; + for (i = 0; i < rb_size; i++) { + rb->buffer[i] = + talloc_zero_size(rb->buffer, RB_MAX_MESSAGE_SIZE); + if (!rb->buffer[i]) + goto alloc_error; + } + + /* start and end are zero already, which is correct */ + rb->size = rb_size; + return rb; + +alloc_error: /* talloc_free(NULL) is safe */ + talloc_free(rb); + return NULL; +} + +/*! \brief Check if an osmo_strrb is empty. + * \param[in] rb The osmo_strrb to check. + * \returns True if the osmo_strrb is empty, false otherwise. + */ +bool osmo_strrb_is_empty(const struct osmo_strrb *rb) +{ + return rb->end == rb->start; +} + +/*! \brief Return a pointer to the Nth string in the osmo_strrb. + * \param[in] rb The osmo_strrb to search. + * \param[in] string_index The index sought (N), zero-indexed. + * + * Return a pointer to the Nth string in the osmo_strrb. + * Return NULL if there is no Nth string. + * Note that N is zero-indexed. + * \returns A pointer to the target string on success, NULL in case of error. + */ +const char *osmo_strrb_get_nth(const struct osmo_strrb *rb, + unsigned int string_index) +{ + unsigned int offset = string_index + rb->start; + + if ((offset >= rb->size) && (rb->start > rb->end)) + offset -= rb->size; + if (_osmo_strrb_is_bufindex_valid(rb, offset)) + return rb->buffer[offset]; + + return NULL; +} + +bool _osmo_strrb_is_bufindex_valid(const struct osmo_strrb *rb, + unsigned int bufi) +{ + if (osmo_strrb_is_empty(rb)) + return 0; + if ((bufi >= rb->size) || (bufi < 0)) + return 0; + if (rb->start < rb->end) + return (bufi >= rb->start) && (bufi < rb->end); + return (bufi < rb->end) || (bufi >= rb->start); +} + +/*! \brief Count the number of log messages in an osmo_strrb. + * \param[in] rb The osmo_strrb to count the elements of. + * + * \returns The number of log messages in the osmo_strrb. + */ +size_t osmo_strrb_elements(const struct osmo_strrb *rb) +{ + if (rb->end < rb->start) + return rb->end + (rb->size - rb->start); + + return rb->end - rb->start; +} + +/*! \brief Add a string to the osmo_strrb. + * \param[in] rb The osmo_strrb to add to. + * \param[in] data The string to add. + * + * Add a message to the osmo_strrb. + * Older messages will be overwritten as necessary. + * \returns 0 normally, 1 as a warning (ie, if data was truncated). + */ +int osmo_strrb_add(struct osmo_strrb *rb, const char *data) +{ + size_t len = strlen(data); + int ret = 0; + + if (len >= RB_MAX_MESSAGE_SIZE) { + len = RB_MAX_MESSAGE_SIZE - 1; + ret = 1; + } + + memcpy(rb->buffer[rb->end], data, len); + rb->buffer[rb->end][len] = '\0'; + + rb->end += 1; + rb->end %= rb->size; + + /* The buffer is full; oldest message is forgotten - see notes above */ + if (rb->end == rb->start) { + rb->start += 1; + rb->start %= rb->size; + } + return ret; +} diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index d473f12..c2ca041 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -27,8 +27,8 @@ #include #include #include - -//#include +#include +#include #include #include @@ -252,8 +252,8 @@ static void vty_print_logtarget(struct vty *vty, const struct log_info *info, #define SHOW_LOG_STR "Show current logging configuration\n" DEFUN(show_logging_vty, - show_logging_vty_cmd, - "show logging vty", + show_logging_vty_cmd, + "show logging vty", SHOW_STR SHOW_LOG_STR "Show current logging configuration for this vty\n") { @@ -267,6 +267,33 @@ DEFUN(show_logging_vty, return CMD_SUCCESS; } +DEFUN(show_alarms, + show_alarms_cmd, + "show alarms", + SHOW_STR SHOW_LOG_STR + "Show the contents of the logging ringbuffer\n") +{ + int i, num_alarms; + struct osmo_strrb *rb; + struct log_target *tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL); + if (!tgt) { + vty_out(vty, "%% No alarms, run 'log alarms <2-32767>'%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + rb = tgt->tgt_rb.rb; + num_alarms = osmo_strrb_elements(rb); + + vty_out(vty, "%% Showing %i alarms%s", num_alarms, VTY_NEWLINE); + + for (i = 0; i < num_alarms; i++) + vty_out(vty, "%% %s%s", osmo_strrb_get_nth(rb, i), + VTY_NEWLINE); + + return CMD_SUCCESS; +} + gDEFUN(cfg_description, cfg_description_cmd, "description .TEXT", "Save human-readable decription of the object\n" @@ -510,6 +537,49 @@ DEFUN(cfg_no_log_file, cfg_no_log_file_cmd, return CMD_SUCCESS; } +DEFUN(cfg_log_alarms, cfg_log_alarms_cmd, + "log alarms <2-32767>", + LOG_STR "Logging alarms to osmo_strrb\n" + "Maximum number of messages to log (+1)\n") +{ + struct log_target *tgt; + unsigned int rbsize = atoi(argv[0]); + + tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL); + if (tgt) + log_target_destroy(tgt); + + tgt = log_target_create_rb(rbsize); + if (!tgt) { + vty_out(vty, "%% Unable to create osmo_strrb (size %u)%s", + rbsize, VTY_NEWLINE); + return CMD_WARNING; + } + log_add_target(tgt); + + vty->index = tgt; + vty->node = CFG_LOG_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_no_log_alarms, cfg_no_log_alarms_cmd, + "no log alarms", + NO_STR LOG_STR "Logging alarms to osmo_strrb\n") +{ + struct log_target *tgt; + + tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL); + if (!tgt) { + vty_out(vty, "%% No osmo_strrb target found%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_target_destroy(tgt); + + return CMD_SUCCESS; +} + static int config_write_log_single(struct vty *vty, struct log_target *tgt) { int i; @@ -533,6 +603,10 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) case LOG_TGT_TYPE_FILE: vty_out(vty, "log file %s%s", tgt->tgt_file.fname, VTY_NEWLINE); break; + case LOG_TGT_TYPE_STRRB: + vty_out(vty, "log alarms %zu%s", + log_target_rb_avail_size(tgt), VTY_NEWLINE); + break; } vty_out(vty, " logging filter all %u%s", @@ -590,6 +664,7 @@ void logging_vty_add_cmds(const struct log_info *cat) logging_level_cmd.doc = log_vty_command_description(cat); install_element_ve(&logging_level_cmd); install_element_ve(&show_logging_vty_cmd); + install_element_ve(&show_alarms_cmd); install_node(&cfg_log_node, config_write_log); install_default(CFG_LOG_NODE); @@ -603,6 +678,8 @@ void logging_vty_add_cmds(const struct log_info *cat) install_element(CONFIG_NODE, &cfg_no_log_stderr_cmd); install_element(CONFIG_NODE, &cfg_log_file_cmd); install_element(CONFIG_NODE, &cfg_no_log_file_cmd); + install_element(CONFIG_NODE, &cfg_log_alarms_cmd); + install_element(CONFIG_NODE, &cfg_no_log_alarms_cmd); #ifdef HAVE_SYSLOG_H install_element(CONFIG_NODE, &cfg_log_syslog_cmd); install_element(CONFIG_NODE, &cfg_log_syslog_local_cmd); diff --git a/tests/Makefile.am b/tests/Makefile.am index be0b5f4..bc9b7de 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,7 +4,9 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \ smscb/smscb_test bits/bitrev_test a5/a5_test \ conv/conv_test auth/milenage_test lapd/lapd_test \ gsm0808/gsm0808_test gsm0408/gsm0408_test \ - gb/bssgp_fc_test logging/logging_test fr/fr_test + gb/bssgp_fc_test logging/logging_test fr/fr_test \ + loggingrb/loggingrb_test strrb/strrb_test + if ENABLE_MSGFILE check_PROGRAMS += msgfile/msgfile_test endif @@ -54,6 +56,12 @@ logging_logging_test_LDADD = $(top_builddir)/src/libosmocore.la fr_fr_test_SOURCES = fr/fr_test.c fr_fr_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gb/libosmogb.la +loggingrb_loggingrb_test_SOURCES = logging/logging_test.c +loggingrb_loggingrb_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/vty/libosmovty.la + +strrb_strrb_test_SOURCES = strrb/strrb_test.c +strrb_strrb_test_LDADD = $(top_builddir)/src/libosmocore.la + # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac @@ -82,7 +90,8 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \ gb/bssgp_fc_tests.ok gb/bssgp_fc_tests.sh \ msgfile/msgfile_test.ok msgfile/msgconfig.cfg \ logging/logging_test.ok logging/logging_test.err \ - fr/fr_test.ok + fr/fr_test.ok loggingrb/logging_test.ok \ + loggingrb/logging_test.err strrb/strrb_test.ok DISTCLEANFILES = atconfig diff --git a/tests/loggingrb/logging_test.err b/tests/loggingrb/logging_test.err new file mode 100644 index 0000000..b59d2e8 --- /dev/null +++ b/tests/loggingrb/logging_test.err @@ -0,0 +1,3 @@ +You should see this +You should see this + \ No newline at end of file diff --git a/tests/loggingrb/logging_test.ok b/tests/loggingrb/logging_test.ok new file mode 100644 index 0000000..e69de29 diff --git a/tests/loggingrb/loggingrb_test.c b/tests/loggingrb/loggingrb_test.c new file mode 100644 index 0000000..1ab5212 --- /dev/null +++ b/tests/loggingrb/loggingrb_test.c @@ -0,0 +1,83 @@ +/* simple test for the debug interface */ +/* + * (C) 2008, 2009 by Holger Hans Peter Freyther + * (C) 2012-2013 by Katerina Barone-Adesi + * 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 + +enum { + DRLL, + DCC, + DMM, +}; + +static const struct log_info_cat default_categories[] = { + [DRLL] = { + .name = "DRLL", + .description = "A-bis Radio Link Layer (RLL)", + .color = "\033[1;31m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DCC] = { + .name = "DCC", + .description = "Layer3 Call Control (CC)", + .color = "\033[1;32m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMM] = { + .name = NULL, + .description = "Layer3 Mobility Management (MM)", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, +}; + +const struct log_info log_info = { + .cat = default_categories, + .num_cat = ARRAY_SIZE(default_categories), +}; + +int main(int argc, char **argv) +{ + struct log_target *ringbuf_target; + + log_init(&log_info, NULL); + ringbuf_target = log_target_create_rbvty(NULL, 0x1000); + log_add_target(ringbuf_target); + log_set_all_filter(ringbuf_target, 1); + log_set_print_filename(ringbuf_target, 0); + + log_parse_category_mask(ringbuf_target, "DRLL:DCC"); + log_parse_category_mask(ringbuf_target, "DRLL"); + DEBUGP(DCC, "You should not see this\n"); + + log_parse_category_mask(ringbuf_target, "DRLL:DCC"); + DEBUGP(DRLL, "You should see this\n"); + DEBUGP(DCC, "You should see this\n"); + DEBUGP(DMM, "You should not see this\n"); + fprintf(stderr, ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 0)); + fprintf(stderr, ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 1)); + assert(!ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 2)); + + return 0; +} diff --git a/tests/strrb/strrb_test.c b/tests/strrb/strrb_test.c new file mode 100644 index 0000000..abe649f --- /dev/null +++ b/tests/strrb/strrb_test.c @@ -0,0 +1,225 @@ +/* (C) 2012-2013 by Katerina Barone-Adesi + * All Rights Reserved + * + * This program is iree 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 +#include + +#include +#include +#include + +struct osmo_strrb *rb0, *rb1, *rb2, *rb3, *rb4, *rb5; + +#define STR0 "hello" +#define STR1 "a" +#define STR2 "world" +#define STR3 "sky" +#define STR4 "moon" + +#define TESTSIZE 3 + +void init_rbs(void) +{ + rb0 = osmo_strrb_create(NULL, TESTSIZE); + + rb1 = osmo_strrb_create(NULL, TESTSIZE); + osmo_strrb_add(rb1, STR0); + + rb2 = osmo_strrb_create(NULL, TESTSIZE); + osmo_strrb_add(rb2, STR0); + osmo_strrb_add(rb2, STR1); + + rb3 = osmo_strrb_create(NULL, TESTSIZE); + osmo_strrb_add(rb3, STR0); + osmo_strrb_add(rb3, STR1); + osmo_strrb_add(rb3, STR2); + + rb4 = osmo_strrb_create(NULL, TESTSIZE); + osmo_strrb_add(rb4, STR0); + osmo_strrb_add(rb4, STR1); + osmo_strrb_add(rb4, STR2); + osmo_strrb_add(rb4, STR3); + + rb5 = osmo_strrb_create(NULL, TESTSIZE); + osmo_strrb_add(rb5, STR0); + osmo_strrb_add(rb5, STR1); + osmo_strrb_add(rb5, STR2); + osmo_strrb_add(rb5, STR3); + osmo_strrb_add(rb5, STR4); +} + +void free_rbs(void) +{ + talloc_free(rb0); + talloc_free(rb1); + talloc_free(rb2); + talloc_free(rb3); + talloc_free(rb4); + talloc_free(rb5); +} + +void test_offset_valid(void) +{ + assert(_osmo_strrb_is_bufindex_valid(rb1, 0)); + assert(!_osmo_strrb_is_bufindex_valid(rb1, 1)); + assert(!_osmo_strrb_is_bufindex_valid(rb1, 2)); + + assert(!_osmo_strrb_is_bufindex_valid(rb3, 0)); + assert(_osmo_strrb_is_bufindex_valid(rb3, 1)); + assert(_osmo_strrb_is_bufindex_valid(rb3, 2)); + + assert(_osmo_strrb_is_bufindex_valid(rb4, 0)); + assert(!_osmo_strrb_is_bufindex_valid(rb4, 1)); + assert(_osmo_strrb_is_bufindex_valid(rb4, 2)); + + assert(_osmo_strrb_is_bufindex_valid(rb5, 0)); + assert(_osmo_strrb_is_bufindex_valid(rb5, 1)); + assert(!_osmo_strrb_is_bufindex_valid(rb5, 2)); +} + +void test_elems(void) +{ + assert(osmo_strrb_elements(rb0) == 0); + assert(osmo_strrb_elements(rb1) == 1); + assert(osmo_strrb_elements(rb2) == 2); + assert(osmo_strrb_elements(rb3) == 2); +} + +void test_getn(void) +{ + assert(!osmo_strrb_get_nth(rb0, 0)); + assert(!strcmp(STR0, osmo_strrb_get_nth(rb2, 0))); + assert(!strcmp(STR1, osmo_strrb_get_nth(rb2, 1))); + assert(!strcmp(STR1, osmo_strrb_get_nth(rb3, 0))); + assert(!strcmp(STR2, osmo_strrb_get_nth(rb3, 1))); + assert(!osmo_strrb_get_nth(rb3, 2)); +} + +void test_getn_wrap(void) +{ + assert(!strcmp(STR2, osmo_strrb_get_nth(rb4, 0))); + assert(!strcmp(STR3, osmo_strrb_get_nth(rb4, 1))); + + assert(!strcmp(STR3, osmo_strrb_get_nth(rb5, 0))); + assert(!strcmp(STR4, osmo_strrb_get_nth(rb5, 1))); +} + +void test_add(void) +{ + struct osmo_strrb *rb = osmo_strrb_create(NULL, 4); + assert(rb->start == 0); + assert(rb->end == 0); + + osmo_strrb_add(rb, "a"); + osmo_strrb_add(rb, "b"); + osmo_strrb_add(rb, "c"); + assert(rb->start == 0); + assert(rb->end == 3); + assert(osmo_strrb_elements(rb) == 3); + + osmo_strrb_add(rb, "d"); + assert(rb->start == 1); + assert(rb->end == 0); + assert(osmo_strrb_elements(rb) == 3); + assert(!strcmp("b", osmo_strrb_get_nth(rb, 0))); + assert(!strcmp("c", osmo_strrb_get_nth(rb, 1))); + assert(!strcmp("d", osmo_strrb_get_nth(rb, 2))); + + osmo_strrb_add(rb, "e"); + assert(rb->start == 2); + assert(rb->end == 1); + assert(!strcmp("c", osmo_strrb_get_nth(rb, 0))); + assert(!strcmp("d", osmo_strrb_get_nth(rb, 1))); + assert(!strcmp("e", osmo_strrb_get_nth(rb, 2))); + + osmo_strrb_add(rb, "f"); + assert(rb->start == 3); + assert(rb->end == 2); + assert(!strcmp("d", osmo_strrb_get_nth(rb, 0))); + assert(!strcmp("e", osmo_strrb_get_nth(rb, 1))); + assert(!strcmp("f", osmo_strrb_get_nth(rb, 2))); + + osmo_strrb_add(rb, "g"); + assert(rb->start == 0); + assert(rb->end == 3); + assert(!strcmp("e", osmo_strrb_get_nth(rb, 0))); + assert(!strcmp("f", osmo_strrb_get_nth(rb, 1))); + assert(!strcmp("g", osmo_strrb_get_nth(rb, 2))); + + osmo_strrb_add(rb, "h"); + assert(rb->start == 1); + assert(rb->end == 0); + assert(!strcmp("f", osmo_strrb_get_nth(rb, 0))); + assert(!strcmp("g", osmo_strrb_get_nth(rb, 1))); + assert(!strcmp("h", osmo_strrb_get_nth(rb, 2))); + + talloc_free(rb); +} + +void test_long_msg(void) +{ + struct osmo_strrb *rb = osmo_strrb_create(NULL, 2); + int test_size = RB_MAX_MESSAGE_SIZE + 7; + char *tests1, *tests2; + const char *rb_content; + int i; + + tests1 = malloc(test_size); + tests2 = malloc(test_size); + /* Be certain allocating memory worked before continuing */ + assert(tests1); + assert(tests2); + + for (i = 0; i < RB_MAX_MESSAGE_SIZE; i += 2) { + tests1[i] = 'a'; + tests1[i + 1] = 'b'; + } + tests1[i] = '\0'; + + osmo_strrb_add(rb, tests1); + strcpy(tests2, tests1); + + /* Verify that no stale data from test1 is lingering... */ + bzero(tests1, test_size); + free(tests1); + + rb_content = osmo_strrb_get_nth(rb, 0); + assert(!strncmp(tests2, rb_content, RB_MAX_MESSAGE_SIZE - 1)); + assert(!rb_content[RB_MAX_MESSAGE_SIZE - 1]); + assert(strlen(rb_content) == RB_MAX_MESSAGE_SIZE - 1); + + free(tests2); + talloc_free(rb); +} + +int main(int argc, char **argv) +{ + init_rbs(); + test_offset_valid(); + test_elems(); + test_getn(); + test_getn_wrap(); + test_add(); + test_long_msg(); + printf("All tests passed\n"); + + free_rbs(); + return 0; +} diff --git a/tests/strrb/strrb_test.ok b/tests/strrb/strrb_test.ok new file mode 100644 index 0000000..9ac5124 --- /dev/null +++ b/tests/strrb/strrb_test.ok @@ -0,0 +1 @@ +All tests passed diff --git a/tests/testsuite.at b/tests/testsuite.at index 5029b9e..21fad1d 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -99,3 +99,16 @@ cat $abs_srcdir/fr/fr_test.err > experr AT_CHECK([$abs_top_builddir/tests/fr/fr_test], [], [expout], [experr]) AT_CLEANUP + +AT_SETUP([loggingrb]) +AT_KEYWORDS([loggingrb]) +cat $abs_srcdir/loggingrb/logging_test.ok > expout +cat $abs_srcdir/loggingrb/logging_test.err > experr +AT_CHECK([$abs_top_builddir/tests/loggingrb/loggingrb_test], [], [expout], [experr]) +AT_CLEANUP + +AT_SETUP([strrb]) +AT_KEYWORDS([strrb]) +cat $abs_srcdir/strrb/strrb_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/strrb/strrb_test], [], [expout], [ignore]) +AT_CLEANUP -- 1.8.1.2 From holger at freyther.de Tue Feb 19 19:11:44 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 19 Feb 2013 20:11:44 +0100 Subject: [PATCH] Added a ring buffer log target to store the last N log messages. In-Reply-To: <1361130241-1817-1-git-send-email-kat.obsc@gmail.com> References: <1361130241-1817-1-git-send-email-kat.obsc@gmail.com> Message-ID: <20130219191144.GG3975@xiaoyu.lan> On Sun, Feb 17, 2013 at 07:44:01PM +0000, Katerina Barone-Adesi wrote: Dear Katerina, one minor detail. I think if someone is using "log alarms 2" it should be able to hold two entries. If we internally need an array with three elements then that is okay. Could you please update the patch? thanks holger From kat.obsc at gmail.com Thu Feb 21 05:16:29 2013 From: kat.obsc at gmail.com (Katerina Barone-Adesi) Date: Thu, 21 Feb 2013 05:16:29 +0000 Subject: [PATCH] Added a ring buffer log target to store the last N log messages. Message-ID: <1361423789-19842-1-git-send-email-kat.obsc@gmail.com> The log target can be used via log alarms and show alarms. Why? This feature was proposed/requested at http://openbsc.osmocom.org/trac/wiki/Tasks/ErrorLogTarget All messages use the same amount of space, prioritizing simplicity. Renames as per tnt's request. UI changed to reflect number of usable messages, as per zecke's request. --- .gitignore | 2 + include/osmocom/core/logging.h | 5 + include/osmocom/core/loggingrb.h | 40 +++++++ include/osmocom/core/strrb.h | 58 ++++++++++ src/Makefile.am | 4 +- src/loggingrb.c | 98 +++++++++++++++++ src/strrb.c | 170 +++++++++++++++++++++++++++++ src/vty/logging_vty.c | 85 ++++++++++++++- tests/Makefile.am | 13 ++- tests/loggingrb/logging_test.err | 3 + tests/loggingrb/logging_test.ok | 0 tests/loggingrb/loggingrb_test.c | 83 +++++++++++++++ tests/strrb/strrb_test.c | 225 +++++++++++++++++++++++++++++++++++++++ tests/strrb/strrb_test.ok | 1 + tests/testsuite.at | 13 +++ 15 files changed, 792 insertions(+), 8 deletions(-) create mode 100644 include/osmocom/core/loggingrb.h create mode 100644 include/osmocom/core/strrb.h create mode 100644 src/loggingrb.c create mode 100644 src/strrb.c create mode 100644 tests/loggingrb/logging_test.err create mode 100644 tests/loggingrb/logging_test.ok create mode 100644 tests/loggingrb/loggingrb_test.c create mode 100644 tests/strrb/strrb_test.c create mode 100644 tests/strrb/strrb_test.ok diff --git a/.gitignore b/.gitignore index 24ca677..aedd9fd 100644 --- a/.gitignore +++ b/.gitignore @@ -69,6 +69,8 @@ tests/gb/bssgp_fc_test tests/gsm0408/gsm0408_test tests/logging/logging_test tests/fr/fr_test +tests/loggingrb/loggingrb_test +tests/ringbuf/ringbuf_test utils/osmo-arfcn utils/osmo-auc-gen diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index 54262b7..fa3365a 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -114,6 +114,7 @@ enum log_target_type { LOG_TGT_TYPE_SYSLOG, /*!< \brief syslog based logging */ LOG_TGT_TYPE_FILE, /*!< \brief text file logging */ LOG_TGT_TYPE_STDERR, /*!< \brief stderr logging */ + LOG_TGT_TYPE_STRRB, /*!< \brief osmo_strrb-backed logging */ }; /*! \brief structure representing a logging target */ @@ -154,6 +155,10 @@ struct log_target { struct { void *vty; } tgt_vty; + + struct { + void *rb; + } tgt_rb; }; /*! \brief call-back function to be called when the logging framework diff --git a/include/osmocom/core/loggingrb.h b/include/osmocom/core/loggingrb.h new file mode 100644 index 0000000..a6f377b --- /dev/null +++ b/include/osmocom/core/loggingrb.h @@ -0,0 +1,40 @@ +#ifndef _LOGGINGRB_H +#define _LOGGINGRB_H + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + + +/*! \defgroup loggingrb Osmocom ringbuffer-backed logging + * @{ + */ + +/*! \file loggingrb.h + */ + +struct log_info; + +size_t log_target_rb_used_size(struct log_target const *target); +size_t log_target_rb_avail_size(struct log_target const *target); +const char *log_target_rb_get(struct log_target const *target, size_t logindex); +struct log_target *log_target_create_rb(size_t size); + +/*! @} */ + +#endif /* _LOGGINGRB_H */ diff --git a/include/osmocom/core/strrb.h b/include/osmocom/core/strrb.h new file mode 100644 index 0000000..cfc56dc --- /dev/null +++ b/include/osmocom/core/strrb.h @@ -0,0 +1,58 @@ +#ifndef _STRRB_H +#define _STRRB_H + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + +/*! \defgroup osmo_strrb Osmocom ringbuffers for log strings + * @{ + */ + +/*! \file strrb.h + * \brief Osmocom string ringbuffer handling routines + */ + +#include +#include +#include + +#include + +/*! \brief A structure representing an osmocom string ringbuffer */ + +#define RB_MAX_MESSAGE_SIZE 240 +struct osmo_strrb { + uint16_t start; /*!< \brief index of the first slot */ + uint16_t end; /*!< \brief index of the last slot */ + uint16_t size; /*!< \brief max number of messages to store */ + char **buffer; /*!< \brief storage for messages */ +}; + +struct osmo_strrb *osmo_strrb_create(TALLOC_CTX * ctx, size_t rb_size); +bool osmo_strrb_is_empty(const struct osmo_strrb *rb); +const char *osmo_strrb_get_nth(const struct osmo_strrb *rb, + unsigned int string_index); +bool _osmo_strrb_is_bufindex_valid(const struct osmo_strrb *rb, + unsigned int offset); +size_t osmo_strrb_elements(const struct osmo_strrb *rb); +int osmo_strrb_add(struct osmo_strrb *rb, const char *data); + +/*! @} */ + +#endif /* _STRRB_H */ diff --git a/src/Makefile.am b/src/Makefile.am index b425ea1..081be96 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,8 +11,8 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.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 \ - crc8gen.c crc16gen.c crc32gen.c crc64gen.c + conv.c application.c rbtree.c strrb.c \ + loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c diff --git a/src/loggingrb.c b/src/loggingrb.c new file mode 100644 index 0000000..bb339eb --- /dev/null +++ b/src/loggingrb.c @@ -0,0 +1,98 @@ +/* Ringbuffer-backed logging support code */ + +/* (C) 2012-2013 by Katerina Barone-Adesi + * 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. + * + */ + +/*! \addtogroup logging + * @{ + */ + +/*! \file loggingrb.c */ + +#include +#include +#include + +static void _rb_output(struct log_target *target, + unsigned int level, const char *log) +{ + osmo_strrb_add(target->tgt_rb.rb, log); +} + +/*! \brief Return the number of log strings in the osmo_strrb-backed target. + * \param[in] target The target to search. + * + * \return The number of log strings in the osmo_strrb-backed target. + */ +size_t log_target_rb_used_size(struct log_target const *target) +{ + return osmo_strrb_elements(target->tgt_rb.rb); +} + +/*! \brief Return the capacity of the osmo_strrb-backed target. + * \param[in] target The target to search. + * + * Note that this is the capacity (aka max number of messages +1). + * It is not the number of unused message slots. + * \return The number of log strings in the osmo_strrb-backed target. + */ +size_t log_target_rb_avail_size(struct log_target const *target) +{ + struct osmo_strrb *rb = target->tgt_rb.rb; + return rb->size; +} + +/*! \brief Return the nth log entry in a target. + * \param[in] target The target to search. + * \param[in] logindex The index of the log entry/error message. + * + * \return A pointer to the nth message, or NULL if logindex is invalid. + */ +const char *log_target_rb_get(struct log_target const *target, size_t logindex) +{ + return osmo_strrb_get_nth(target->tgt_rb.rb, logindex); +} + +/*! \brief Create a new logging target for ringbuffer-backed logging. + * \param[in] size The size of the internal backing osmo_strrb (messages +1). + * \returns A log target in case of success, NULL in case of error. + */ +struct log_target *log_target_create_rb(size_t size) +{ + struct log_target *target; + struct osmo_strrb *rb; + + target = log_target_create(); + if (!target) + return NULL; + + rb = osmo_strrb_create(target, size); + if (!rb) { + log_target_destroy(target); + return NULL; + } + + target->tgt_rb.rb = rb; + target->type = LOG_TGT_TYPE_STRRB; + target->output = _rb_output; + + return target; +} + +/* @} */ diff --git a/src/strrb.c b/src/strrb.c new file mode 100644 index 0000000..580c65c --- /dev/null +++ b/src/strrb.c @@ -0,0 +1,170 @@ +/* Ringbuffer implementation, tailored for logging. + * This is a lossy ringbuffer. It keeps up to N of the newest messages, + * overwriting the oldest as newer ones come in. + * + * (C) 2012-2013, Katerina Barone-Adesi + * 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. + * + */ + +/*! \file strrb.c + * \brief Lossy string ringbuffer for logging; keeps newest messages. + */ + +#include +#include +#include + +#include + +/* Ringbuffer assumptions, invarients, and notes: + * - start is the index of the first used index slot in the ring buffer. + * - end is the index of the next index slot in the ring buffer. + * - start == end => buffer is empty + * - Consequence: the buffer can hold at most size - 1 messages + * (if this were not the case, full and empty buffers would be indistinguishable + * given the conventions in this implementation). + * - Whenever the ringbuffer is full, start is advanced. The second oldest + * message becomes unreachable by valid indexes (end is not a valid index) + * and the oldest message is overwritten (if there was a message there, which + * is the case unless this is the first time the ringbuffer becomes full). +*/ + +/*! \brief Create an empty, initialized osmo_strrb. + * \param[in] ctx The talloc memory context which should own this. + * \param[in] rb_size The number of messages the osmo_strrb can hold. + * \returns A struct osmo_strrb* on success, NULL in case of error. + * + * This function creates and initializes a ringbuffer. + */ + +struct osmo_strrb *osmo_strrb_create(TALLOC_CTX * ctx, size_t rb_size) +{ + struct osmo_strrb *rb = NULL; + unsigned int i; + + rb = talloc_zero(ctx, struct osmo_strrb); + if (!rb) + goto alloc_error; + + /* start and end are zero already, which is correct */ + rb->size = rb_size + 1; /* one space is overhead */ + + rb->buffer = talloc_array(rb, char *, rb->size); + if (!rb->buffer) + goto alloc_error; + for (i = 0; i < rb->size; i++) { + rb->buffer[i] = + talloc_zero_size(rb->buffer, RB_MAX_MESSAGE_SIZE); + if (!rb->buffer[i]) + goto alloc_error; + } + + return rb; + +alloc_error: /* talloc_free(NULL) is safe */ + talloc_free(rb); + return NULL; +} + +/*! \brief Check if an osmo_strrb is empty. + * \param[in] rb The osmo_strrb to check. + * \returns True if the osmo_strrb is empty, false otherwise. + */ +bool osmo_strrb_is_empty(const struct osmo_strrb *rb) +{ + return rb->end == rb->start; +} + +/*! \brief Return a pointer to the Nth string in the osmo_strrb. + * \param[in] rb The osmo_strrb to search. + * \param[in] string_index The index sought (N), zero-indexed. + * + * Return a pointer to the Nth string in the osmo_strrb. + * Return NULL if there is no Nth string. + * Note that N is zero-indexed. + * \returns A pointer to the target string on success, NULL in case of error. + */ +const char *osmo_strrb_get_nth(const struct osmo_strrb *rb, + unsigned int string_index) +{ + unsigned int offset = string_index + rb->start; + + if ((offset >= rb->size) && (rb->start > rb->end)) + offset -= rb->size; + if (_osmo_strrb_is_bufindex_valid(rb, offset)) + return rb->buffer[offset]; + + return NULL; +} + +bool _osmo_strrb_is_bufindex_valid(const struct osmo_strrb *rb, + unsigned int bufi) +{ + if (osmo_strrb_is_empty(rb)) + return 0; + if ((bufi >= rb->size) || (bufi < 0)) + return 0; + if (rb->start < rb->end) + return (bufi >= rb->start) && (bufi < rb->end); + return (bufi < rb->end) || (bufi >= rb->start); +} + +/*! \brief Count the number of log messages in an osmo_strrb. + * \param[in] rb The osmo_strrb to count the elements of. + * + * \returns The number of log messages in the osmo_strrb. + */ +size_t osmo_strrb_elements(const struct osmo_strrb *rb) +{ + if (rb->end < rb->start) + return rb->end + (rb->size - rb->start); + + return rb->end - rb->start; +} + +/*! \brief Add a string to the osmo_strrb. + * \param[in] rb The osmo_strrb to add to. + * \param[in] data The string to add. + * + * Add a message to the osmo_strrb. + * Older messages will be overwritten as necessary. + * \returns 0 normally, 1 as a warning (ie, if data was truncated). + */ +int osmo_strrb_add(struct osmo_strrb *rb, const char *data) +{ + size_t len = strlen(data); + int ret = 0; + + if (len >= RB_MAX_MESSAGE_SIZE) { + len = RB_MAX_MESSAGE_SIZE - 1; + ret = 1; + } + + memcpy(rb->buffer[rb->end], data, len); + rb->buffer[rb->end][len] = '\0'; + + rb->end += 1; + rb->end %= rb->size; + + /* The buffer is full; oldest message is forgotten - see notes above */ + if (rb->end == rb->start) { + rb->start += 1; + rb->start %= rb->size; + } + return ret; +} diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index d473f12..ace346a 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -27,8 +27,8 @@ #include #include #include - -//#include +#include +#include #include #include @@ -252,8 +252,8 @@ static void vty_print_logtarget(struct vty *vty, const struct log_info *info, #define SHOW_LOG_STR "Show current logging configuration\n" DEFUN(show_logging_vty, - show_logging_vty_cmd, - "show logging vty", + show_logging_vty_cmd, + "show logging vty", SHOW_STR SHOW_LOG_STR "Show current logging configuration for this vty\n") { @@ -267,6 +267,33 @@ DEFUN(show_logging_vty, return CMD_SUCCESS; } +DEFUN(show_alarms, + show_alarms_cmd, + "show alarms", + SHOW_STR SHOW_LOG_STR + "Show the contents of the logging ringbuffer\n") +{ + int i, num_alarms; + struct osmo_strrb *rb; + struct log_target *tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL); + if (!tgt) { + vty_out(vty, "%% No alarms, run 'log alarms <2-32700>'%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + rb = tgt->tgt_rb.rb; + num_alarms = osmo_strrb_elements(rb); + + vty_out(vty, "%% Showing %i alarms%s", num_alarms, VTY_NEWLINE); + + for (i = 0; i < num_alarms; i++) + vty_out(vty, "%% %s%s", osmo_strrb_get_nth(rb, i), + VTY_NEWLINE); + + return CMD_SUCCESS; +} + gDEFUN(cfg_description, cfg_description_cmd, "description .TEXT", "Save human-readable decription of the object\n" @@ -510,6 +537,49 @@ DEFUN(cfg_no_log_file, cfg_no_log_file_cmd, return CMD_SUCCESS; } +DEFUN(cfg_log_alarms, cfg_log_alarms_cmd, + "log alarms <2-32700>", + LOG_STR "Logging alarms to osmo_strrb\n" + "Maximum number of messages to log\n") +{ + struct log_target *tgt; + unsigned int rbsize = atoi(argv[0]); + + tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL); + if (tgt) + log_target_destroy(tgt); + + tgt = log_target_create_rb(rbsize); + if (!tgt) { + vty_out(vty, "%% Unable to create osmo_strrb (size %u)%s", + rbsize, VTY_NEWLINE); + return CMD_WARNING; + } + log_add_target(tgt); + + vty->index = tgt; + vty->node = CFG_LOG_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_no_log_alarms, cfg_no_log_alarms_cmd, + "no log alarms", + NO_STR LOG_STR "Logging alarms to osmo_strrb\n") +{ + struct log_target *tgt; + + tgt = log_target_find(LOG_TGT_TYPE_STRRB, NULL); + if (!tgt) { + vty_out(vty, "%% No osmo_strrb target found%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_target_destroy(tgt); + + return CMD_SUCCESS; +} + static int config_write_log_single(struct vty *vty, struct log_target *tgt) { int i; @@ -533,6 +603,10 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) case LOG_TGT_TYPE_FILE: vty_out(vty, "log file %s%s", tgt->tgt_file.fname, VTY_NEWLINE); break; + case LOG_TGT_TYPE_STRRB: + vty_out(vty, "log alarms %zu%s", + log_target_rb_avail_size(tgt), VTY_NEWLINE); + break; } vty_out(vty, " logging filter all %u%s", @@ -590,6 +664,7 @@ void logging_vty_add_cmds(const struct log_info *cat) logging_level_cmd.doc = log_vty_command_description(cat); install_element_ve(&logging_level_cmd); install_element_ve(&show_logging_vty_cmd); + install_element_ve(&show_alarms_cmd); install_node(&cfg_log_node, config_write_log); install_default(CFG_LOG_NODE); @@ -603,6 +678,8 @@ void logging_vty_add_cmds(const struct log_info *cat) install_element(CONFIG_NODE, &cfg_no_log_stderr_cmd); install_element(CONFIG_NODE, &cfg_log_file_cmd); install_element(CONFIG_NODE, &cfg_no_log_file_cmd); + install_element(CONFIG_NODE, &cfg_log_alarms_cmd); + install_element(CONFIG_NODE, &cfg_no_log_alarms_cmd); #ifdef HAVE_SYSLOG_H install_element(CONFIG_NODE, &cfg_log_syslog_cmd); install_element(CONFIG_NODE, &cfg_log_syslog_local_cmd); diff --git a/tests/Makefile.am b/tests/Makefile.am index be0b5f4..bc9b7de 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,7 +4,9 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \ smscb/smscb_test bits/bitrev_test a5/a5_test \ conv/conv_test auth/milenage_test lapd/lapd_test \ gsm0808/gsm0808_test gsm0408/gsm0408_test \ - gb/bssgp_fc_test logging/logging_test fr/fr_test + gb/bssgp_fc_test logging/logging_test fr/fr_test \ + loggingrb/loggingrb_test strrb/strrb_test + if ENABLE_MSGFILE check_PROGRAMS += msgfile/msgfile_test endif @@ -54,6 +56,12 @@ logging_logging_test_LDADD = $(top_builddir)/src/libosmocore.la fr_fr_test_SOURCES = fr/fr_test.c fr_fr_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gb/libosmogb.la +loggingrb_loggingrb_test_SOURCES = logging/logging_test.c +loggingrb_loggingrb_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/vty/libosmovty.la + +strrb_strrb_test_SOURCES = strrb/strrb_test.c +strrb_strrb_test_LDADD = $(top_builddir)/src/libosmocore.la + # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac @@ -82,7 +90,8 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \ gb/bssgp_fc_tests.ok gb/bssgp_fc_tests.sh \ msgfile/msgfile_test.ok msgfile/msgconfig.cfg \ logging/logging_test.ok logging/logging_test.err \ - fr/fr_test.ok + fr/fr_test.ok loggingrb/logging_test.ok \ + loggingrb/logging_test.err strrb/strrb_test.ok DISTCLEANFILES = atconfig diff --git a/tests/loggingrb/logging_test.err b/tests/loggingrb/logging_test.err new file mode 100644 index 0000000..b59d2e8 --- /dev/null +++ b/tests/loggingrb/logging_test.err @@ -0,0 +1,3 @@ +You should see this +You should see this + \ No newline at end of file diff --git a/tests/loggingrb/logging_test.ok b/tests/loggingrb/logging_test.ok new file mode 100644 index 0000000..e69de29 diff --git a/tests/loggingrb/loggingrb_test.c b/tests/loggingrb/loggingrb_test.c new file mode 100644 index 0000000..1ab5212 --- /dev/null +++ b/tests/loggingrb/loggingrb_test.c @@ -0,0 +1,83 @@ +/* simple test for the debug interface */ +/* + * (C) 2008, 2009 by Holger Hans Peter Freyther + * (C) 2012-2013 by Katerina Barone-Adesi + * 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 + +enum { + DRLL, + DCC, + DMM, +}; + +static const struct log_info_cat default_categories[] = { + [DRLL] = { + .name = "DRLL", + .description = "A-bis Radio Link Layer (RLL)", + .color = "\033[1;31m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DCC] = { + .name = "DCC", + .description = "Layer3 Call Control (CC)", + .color = "\033[1;32m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMM] = { + .name = NULL, + .description = "Layer3 Mobility Management (MM)", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, +}; + +const struct log_info log_info = { + .cat = default_categories, + .num_cat = ARRAY_SIZE(default_categories), +}; + +int main(int argc, char **argv) +{ + struct log_target *ringbuf_target; + + log_init(&log_info, NULL); + ringbuf_target = log_target_create_rbvty(NULL, 0x1000); + log_add_target(ringbuf_target); + log_set_all_filter(ringbuf_target, 1); + log_set_print_filename(ringbuf_target, 0); + + log_parse_category_mask(ringbuf_target, "DRLL:DCC"); + log_parse_category_mask(ringbuf_target, "DRLL"); + DEBUGP(DCC, "You should not see this\n"); + + log_parse_category_mask(ringbuf_target, "DRLL:DCC"); + DEBUGP(DRLL, "You should see this\n"); + DEBUGP(DCC, "You should see this\n"); + DEBUGP(DMM, "You should not see this\n"); + fprintf(stderr, ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 0)); + fprintf(stderr, ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 1)); + assert(!ringbuffer_get_nth(ringbuf_target->tgt_rbvty.rb, 2)); + + return 0; +} diff --git a/tests/strrb/strrb_test.c b/tests/strrb/strrb_test.c new file mode 100644 index 0000000..b7c5e27 --- /dev/null +++ b/tests/strrb/strrb_test.c @@ -0,0 +1,225 @@ +/* (C) 2012-2013 by Katerina Barone-Adesi + * All Rights Reserved + * + * This program is iree 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 +#include + +#include +#include +#include + +struct osmo_strrb *rb0, *rb1, *rb2, *rb3, *rb4, *rb5; + +#define STR0 "hello" +#define STR1 "a" +#define STR2 "world" +#define STR3 "sky" +#define STR4 "moon" + +#define TESTSIZE 2 + +void init_rbs(void) +{ + rb0 = osmo_strrb_create(NULL, TESTSIZE); + + rb1 = osmo_strrb_create(NULL, TESTSIZE); + osmo_strrb_add(rb1, STR0); + + rb2 = osmo_strrb_create(NULL, TESTSIZE); + osmo_strrb_add(rb2, STR0); + osmo_strrb_add(rb2, STR1); + + rb3 = osmo_strrb_create(NULL, TESTSIZE); + osmo_strrb_add(rb3, STR0); + osmo_strrb_add(rb3, STR1); + osmo_strrb_add(rb3, STR2); + + rb4 = osmo_strrb_create(NULL, TESTSIZE); + osmo_strrb_add(rb4, STR0); + osmo_strrb_add(rb4, STR1); + osmo_strrb_add(rb4, STR2); + osmo_strrb_add(rb4, STR3); + + rb5 = osmo_strrb_create(NULL, TESTSIZE); + osmo_strrb_add(rb5, STR0); + osmo_strrb_add(rb5, STR1); + osmo_strrb_add(rb5, STR2); + osmo_strrb_add(rb5, STR3); + osmo_strrb_add(rb5, STR4); +} + +void free_rbs(void) +{ + talloc_free(rb0); + talloc_free(rb1); + talloc_free(rb2); + talloc_free(rb3); + talloc_free(rb4); + talloc_free(rb5); +} + +void test_offset_valid(void) +{ + assert(_osmo_strrb_is_bufindex_valid(rb1, 0)); + assert(!_osmo_strrb_is_bufindex_valid(rb1, 1)); + assert(!_osmo_strrb_is_bufindex_valid(rb1, 2)); + + assert(!_osmo_strrb_is_bufindex_valid(rb3, 0)); + assert(_osmo_strrb_is_bufindex_valid(rb3, 1)); + assert(_osmo_strrb_is_bufindex_valid(rb3, 2)); + + assert(_osmo_strrb_is_bufindex_valid(rb4, 0)); + assert(!_osmo_strrb_is_bufindex_valid(rb4, 1)); + assert(_osmo_strrb_is_bufindex_valid(rb4, 2)); + + assert(_osmo_strrb_is_bufindex_valid(rb5, 0)); + assert(_osmo_strrb_is_bufindex_valid(rb5, 1)); + assert(!_osmo_strrb_is_bufindex_valid(rb5, 2)); +} + +void test_elems(void) +{ + assert(osmo_strrb_elements(rb0) == 0); + assert(osmo_strrb_elements(rb1) == 1); + assert(osmo_strrb_elements(rb2) == 2); + assert(osmo_strrb_elements(rb3) == 2); +} + +void test_getn(void) +{ + assert(!osmo_strrb_get_nth(rb0, 0)); + assert(!strcmp(STR0, osmo_strrb_get_nth(rb2, 0))); + assert(!strcmp(STR1, osmo_strrb_get_nth(rb2, 1))); + assert(!strcmp(STR1, osmo_strrb_get_nth(rb3, 0))); + assert(!strcmp(STR2, osmo_strrb_get_nth(rb3, 1))); + assert(!osmo_strrb_get_nth(rb3, 2)); +} + +void test_getn_wrap(void) +{ + assert(!strcmp(STR2, osmo_strrb_get_nth(rb4, 0))); + assert(!strcmp(STR3, osmo_strrb_get_nth(rb4, 1))); + + assert(!strcmp(STR3, osmo_strrb_get_nth(rb5, 0))); + assert(!strcmp(STR4, osmo_strrb_get_nth(rb5, 1))); +} + +void test_add(void) +{ + struct osmo_strrb *rb = osmo_strrb_create(NULL, 3); + assert(rb->start == 0); + assert(rb->end == 0); + + osmo_strrb_add(rb, "a"); + osmo_strrb_add(rb, "b"); + osmo_strrb_add(rb, "c"); + assert(rb->start == 0); + assert(rb->end == 3); + assert(osmo_strrb_elements(rb) == 3); + + osmo_strrb_add(rb, "d"); + assert(rb->start == 1); + assert(rb->end == 0); + assert(osmo_strrb_elements(rb) == 3); + assert(!strcmp("b", osmo_strrb_get_nth(rb, 0))); + assert(!strcmp("c", osmo_strrb_get_nth(rb, 1))); + assert(!strcmp("d", osmo_strrb_get_nth(rb, 2))); + + osmo_strrb_add(rb, "e"); + assert(rb->start == 2); + assert(rb->end == 1); + assert(!strcmp("c", osmo_strrb_get_nth(rb, 0))); + assert(!strcmp("d", osmo_strrb_get_nth(rb, 1))); + assert(!strcmp("e", osmo_strrb_get_nth(rb, 2))); + + osmo_strrb_add(rb, "f"); + assert(rb->start == 3); + assert(rb->end == 2); + assert(!strcmp("d", osmo_strrb_get_nth(rb, 0))); + assert(!strcmp("e", osmo_strrb_get_nth(rb, 1))); + assert(!strcmp("f", osmo_strrb_get_nth(rb, 2))); + + osmo_strrb_add(rb, "g"); + assert(rb->start == 0); + assert(rb->end == 3); + assert(!strcmp("e", osmo_strrb_get_nth(rb, 0))); + assert(!strcmp("f", osmo_strrb_get_nth(rb, 1))); + assert(!strcmp("g", osmo_strrb_get_nth(rb, 2))); + + osmo_strrb_add(rb, "h"); + assert(rb->start == 1); + assert(rb->end == 0); + assert(!strcmp("f", osmo_strrb_get_nth(rb, 0))); + assert(!strcmp("g", osmo_strrb_get_nth(rb, 1))); + assert(!strcmp("h", osmo_strrb_get_nth(rb, 2))); + + talloc_free(rb); +} + +void test_long_msg(void) +{ + struct osmo_strrb *rb = osmo_strrb_create(NULL, 2); + int test_size = RB_MAX_MESSAGE_SIZE + 7; + char *tests1, *tests2; + const char *rb_content; + int i; + + tests1 = malloc(test_size); + tests2 = malloc(test_size); + /* Be certain allocating memory worked before continuing */ + assert(tests1); + assert(tests2); + + for (i = 0; i < RB_MAX_MESSAGE_SIZE; i += 2) { + tests1[i] = 'a'; + tests1[i + 1] = 'b'; + } + tests1[i] = '\0'; + + osmo_strrb_add(rb, tests1); + strcpy(tests2, tests1); + + /* Verify that no stale data from test1 is lingering... */ + bzero(tests1, test_size); + free(tests1); + + rb_content = osmo_strrb_get_nth(rb, 0); + assert(!strncmp(tests2, rb_content, RB_MAX_MESSAGE_SIZE - 1)); + assert(!rb_content[RB_MAX_MESSAGE_SIZE - 1]); + assert(strlen(rb_content) == RB_MAX_MESSAGE_SIZE - 1); + + free(tests2); + talloc_free(rb); +} + +int main(int argc, char **argv) +{ + init_rbs(); + test_offset_valid(); + test_elems(); + test_getn(); + test_getn_wrap(); + test_add(); + test_long_msg(); + printf("All tests passed\n"); + + free_rbs(); + return 0; +} diff --git a/tests/strrb/strrb_test.ok b/tests/strrb/strrb_test.ok new file mode 100644 index 0000000..9ac5124 --- /dev/null +++ b/tests/strrb/strrb_test.ok @@ -0,0 +1 @@ +All tests passed diff --git a/tests/testsuite.at b/tests/testsuite.at index 5029b9e..21fad1d 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -99,3 +99,16 @@ cat $abs_srcdir/fr/fr_test.err > experr AT_CHECK([$abs_top_builddir/tests/fr/fr_test], [], [expout], [experr]) AT_CLEANUP + +AT_SETUP([loggingrb]) +AT_KEYWORDS([loggingrb]) +cat $abs_srcdir/loggingrb/logging_test.ok > expout +cat $abs_srcdir/loggingrb/logging_test.err > experr +AT_CHECK([$abs_top_builddir/tests/loggingrb/loggingrb_test], [], [expout], [experr]) +AT_CLEANUP + +AT_SETUP([strrb]) +AT_KEYWORDS([strrb]) +cat $abs_srcdir/strrb/strrb_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/strrb/strrb_test], [], [expout], [ignore]) +AT_CLEANUP -- 1.8.1.2 From holger at freyther.de Wed Feb 27 14:21:38 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Wed, 27 Feb 2013 15:21:38 +0100 Subject: [PATCH] Added a ring buffer log target to store the last N log messages. In-Reply-To: <1361423789-19842-1-git-send-email-kat.obsc@gmail.com> References: <1361423789-19842-1-git-send-email-kat.obsc@gmail.com> Message-ID: <20130227142138.GC11463@xiaoyu.lan> On Thu, Feb 21, 2013 at 05:16:29AM +0000, Katerina Barone-Adesi wrote: Dear Katerina, thanks for the patch. There was one issue left, I tried to fix it myself, pushed it and only made it worse. So much for following the process. :) Your fixed version made "log alarms 2" have be able to hold two entries but "write terminal" was emitting "log alarms 3". So I have decided to move the +1/-1 into the loggingrb.c. I have attempted to update the API docs at the places. Please have another look if I have done it correctly. For new header files one needs to add them to the include/**Makefile.am files, otherwise a "make dist" will not package these files. This kind of error is caught on our jenkins system (which runs make distcheck). One thing I didn't notice during the review is the usage of assert(). We are not checking if NDEBUG is in the CPPFLAGS/CFLAGS or not. This is why I normally come up with my own assertion macro to make sure that the assertion code is always enabled. It would be nice if you could come up with a patch to do that. My hint would be to take a look at cocci to do semantic patching. The diff between your patch and my fixup attempt is attached to this emails. thanks a lot for your contribution holger -------------- next part -------------- A non-text attachment was scrubbed... Name: logging.diff Type: text/x-diff Size: 4259 bytes Desc: not available URL: From vervelak at gmail.com Thu Feb 21 20:07:38 2013 From: vervelak at gmail.com (./Vervelak) Date: Thu, 21 Feb 2013 22:07:38 +0200 Subject: OpenBSC and Half Rate support on ip.access. Message-ID: <51267E8A.3020700@gmail.com> Hello List I'm trying to make my openbsc installation work in half rate mode but I'm facing some errors. I'm wondering if someone could provide me with more info or help me to configure openbsc. I have changed in openbsc.cfg the timeslots 2 to 7 from phys_chan_config TCH/F into phys_chan_config TCH/H also I have tested changing neci bit and change audio codecs but no luck. Am I missed something? Is there any way to run osmo-nitb with gsmtap? openbsc.cfg is attached Thanks in advance. -------------- next part -------------- ! ! OpenBSC configuration saved from vty ! ! password foo ! line vty no login ! e1_input e1_line 0 driver ipa network network country code 01 mobile network code 001 short name **** long name **** auth policy closed location updating reject cause 13 encryption a5 0 neci 1 rrlp mode none mm info 1 handover 0 handover window rxlev averaging 10 handover window rxqual averaging 1 handover window rxlev neighbor averaging 10 handover power budget interval 6 handover power budget hysteresis 3 handover maximum distance 9999 timer t3101 10 timer t3103 0 timer t3105 0 timer t3107 0 timer t3109 4 timer t3111 0 timer t3113 60 timer t3115 0 timer t3117 0 timer t3119 0 timer t3141 0 bts 0 type nanobts band DCS900 cell_identity 0 location_area_code 1 training_sequence_code 7 base_station_id_code 63 ms max power 33 cell reselection hysteresis 4 rxlev access min 0 channel allocator ascending rach tx integer 9 rach max transmission 7 ip.access unit_id 1 0 oml ip.access stream_id 255 line 0 gprs mode none trx 0 rf_locked 0 arfcn 53 nominal power 23 max_power_red 20 rsl e1 tei 0 timeslot 0 phys_chan_config CCCH+SDCCH4 timeslot 1 phys_chan_config SDCCH8 timeslot 2 phys_chan_config TCH/H timeslot 3 phys_chan_config TCH/H timeslot 4 phys_chan_config TCH/H timeslot 5 phys_chan_config TCH/H timeslot 6 phys_chan_config TCH/H timeslot 7 phys_chan_config TCH/H From 246tnt at gmail.com Thu Feb 21 23:18:59 2013 From: 246tnt at gmail.com (Sylvain Munaut) Date: Fri, 22 Feb 2013 00:18:59 +0100 Subject: OpenBSC and Half Rate support on ip.access. In-Reply-To: <51267E8A.3020700@gmail.com> References: <51267E8A.3020700@gmail.com> Message-ID: > I'm trying to make my openbsc installation work in half rate mode but I don't think nanoBTS support HR codec at all ... Cheers, Sylvain From vervelak at gmail.com Fri Feb 22 12:15:21 2013 From: vervelak at gmail.com (./Vervelak) Date: Fri, 22 Feb 2013 14:15:21 +0200 Subject: OpenBSC and Half Rate support on ip.access. In-Reply-To: References: <51267E8A.3020700@gmail.com> Message-ID: <51276159.1060704@gmail.com> On 02/22/2013 01:18 AM, Sylvain Munaut wrote: >> I'm trying to make my openbsc installation work in half rate mode but > I don't think nanoBTS support HR codec at all ... > > > Cheers, > > Sylvain Thanks for the immediate response. Is your answer based on hands-on experience, feedback from other developers/users or something else? In the nanoGSM? EDGE 900 datasheet is not mentioned the TCH/H support, but the nanoGSM? EDGE 1800 model seems to support it. Do you believe that the 1800 model could work? Also I noticed in the OpenBSC wiki that TCH/H is not implemented in osmo-nitb but only in osmo-bsc, is this information correct? Thanks for your time. ./Vervelak -------------- next part -------------- An HTML attachment was scrubbed... URL: From andreas at eversberg.eu Fri Feb 22 13:55:40 2013 From: andreas at eversberg.eu (jolly) Date: Fri, 22 Feb 2013 14:55:40 +0100 Subject: OpenBSC and Half Rate support on ip.access. In-Reply-To: <51276159.1060704@gmail.com> References: <51267E8A.3020700@gmail.com> <51276159.1060704@gmail.com> Message-ID: <512778DC.9020906@eversberg.eu> ./Vervelak wrote: > Also I noticed in the OpenBSC wiki that TCH/H is not implemented in > osmo-nitb but only in osmo-bsc, is this information correct? there are several reasons why TCH/H is not currently working with osmo-nitb. i plan to make it work soon, but it still requires BTS to support it. -------------- next part -------------- An HTML attachment was scrubbed... URL: From 246tnt at gmail.com Fri Feb 22 15:59:35 2013 From: 246tnt at gmail.com (Sylvain Munaut) Date: Fri, 22 Feb 2013 16:59:35 +0100 Subject: OpenBSC and Half Rate support on ip.access. In-Reply-To: <51276159.1060704@gmail.com> References: <51267E8A.3020700@gmail.com> <51276159.1060704@gmail.com> Message-ID: > Is your answer based on hands-on experience, feedback from other > developers/users or something else? hands-on experience. > In the nanoGSM? EDGE 900 datasheet is not mentioned the TCH/H support, but > the nanoGSM? EDGE 1800 model seems to support it. TCH/H != HR The EDGE models do support AMR-HR. But that's different from HR. And not supported by osmo-nitb currently. Cheers, Sylvain From vervelak at gmail.com Wed Feb 27 19:31:38 2013 From: vervelak at gmail.com (N.v) Date: Wed, 27 Feb 2013 21:31:38 +0200 Subject: OpenBSC and Half Rate support on ip.access. In-Reply-To: References: <51267E8A.3020700@gmail.com> <51276159.1060704@gmail.com> Message-ID: <512E5F1A.2040409@gmail.com> On 2/22/13 5:59 PM, Sylvain Munaut wrote: >> Is your answer based on hands-on experience, feedback from other >> developers/users or something else? > hands-on experience. > >> In the nanoGSM? EDGE 900 datasheet is not mentioned the TCH/H support, but >> the nanoGSM? EDGE 1800 model seems to support it. > TCH/H != HR > > The EDGE models do support AMR-HR. But that's different from HR. And > not supported by osmo-nitb currently. > > Cheers, > > Sylvain So, the nanoBTS support AMR speech codec but don't support HR speech codec and in osmo-bsc TCH/H is supported unlike osmo-nitb? and if i write code in osmo-nitb that support TCH/H i will have 14 simulate calls in my setup? are there any guidelines for new openBSC developers or can someone provide me with some highlights about porting TCH/H from osmo-bsc to osmo-nitb? Thanks again for your time. From andreas at eversberg.eu Thu Feb 28 07:12:03 2013 From: andreas at eversberg.eu (jolly) Date: Thu, 28 Feb 2013 08:12:03 +0100 Subject: OpenBSC and Half Rate support on ip.access. In-Reply-To: <512E5F1A.2040409@gmail.com> References: <51267E8A.3020700@gmail.com> <51276159.1060704@gmail.com> <512E5F1A.2040409@gmail.com> Message-ID: <512F0343.6090106@eversberg.eu> N.v wrote: > are there any guidelines for new openBSC developers or can someone > provide me with some > highlights about porting TCH/H from osmo-bsc to osmo-nitb? hi, there are several things that need to be done to support TCH/H as well as AMR codec at osmo-nitb. as i said before, i am working on it. regards, andreas From laforge at gnumonks.org Tue Feb 26 20:30:28 2013 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 26 Feb 2013 21:30:28 +0100 Subject: [ANNOUNCE] OsmoDevCon 2013-04-04 till 2013-04-07, Berlin Message-ID: <20130226203028.GK1262@prithivi.gnumonks.org> Dear fellow Osmcoom developers, it is my pleasure to finally announce the date + venue of OsmoDevCon 2013: Date: April 04 through April 07, 2013 Place: IN-Berlin, Lehrter Str. 53, Berlin Like last year, this is an event for developers of the various Osmocom proejects. Reservation and confirmation of reservation is required. The event is free of charge. The Room is made available by IN-Berlin e.V., an Internet related non-profit organization. Lunch catering will be sponsored (so far by sysmocom GmbH, but if any other sponsors come up, we are happy to share the cost). So all you have to cover is your own travel + accomodation costs, as well as breakfast and dinner. If you are an active developer and cannot afford travel/accomodation, please let me know and I'll see if we can do something about it. If you would like to attend, please send a message to laforge at gnumonks.org applying for registration of the event. The registration deadline is March 5, i.e. one week from now. There is no detailed schedule of talks yet. I will start a separate discussion suggesting / collecting topics in the next couple of days. More information is (and will be made) available at http://openbsc.osmocom.org/trac/wiki/OsmoDevCon2013 Further discussion regarding the event should be directed at the osmocom-event-orga at lists.osmocom.org mailing list, to avoid cross-posting over the various project-specific lists. Best regards and happy hacking, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 190 bytes Desc: Digital signature URL: From mvanbiez at gmail.com Thu Feb 28 15:33:41 2013 From: mvanbiez at gmail.com (Max van Biezen) Date: Thu, 28 Feb 2013 16:33:41 +0100 Subject: unclear behaviour LAC authorization Message-ID: Hi, I am using osmo-nitb version 0.12.0.264-b02f. When I set value to authorized to 1 for ID 1 via the telnet console then I do not see the this value change with "show subscriber". The "authorized" field value in the DB did change from 0 to 1. - start with new DB freshly initialized by osmo-nitb running in foreground as root (auth policy closed) - SIM tries to register and fails as it is not authorized: (1|2013-02-28 14:57:43|2013-02-28 14:57:43|901700000001198||38178|0||0|1970-01-01 00:00:00) - set auth with: subscriber id 1 authorized 1 console shows: <000d> db.c:161 DBI: -7: The requested variable type does not match what libdbi thinks it should be <000d> db.c:161 DBI: -7: The requested variable type does not match what libdbi thinks it should be <000d> db.c:713 Found Subscriber: ID 0, IMSI 901700000001198, NAME '', TMSI 4294967295, EXTEN '38178', LAC 0, AUTH 0 - DB shows: 1|2013-02-28 14:57:43|2013-02-28 15:06:11|901700000001198||38178|1||0|1970-01-01 00:00:00 - however in the console it is not changing its state: OpenBSC# show subscriber id 1 ID: 0, Authorized: 0 - using "subscriber id 1 update" has no effect. I can see the auth value change in the console after I set auth policy to accept-all, then let the IMSI update its location, then set auth-policy back to auth policy closed. And then "subscriber id 1 authorize 1". After this sequence IMSI can update its location value. Why can I not get the auth value activated from the DB? Is it related to the db.c about the variable type message? Once the SIM is registered all is working well and I can make calls. Regards, Max From holger at freyther.de Thu Feb 28 18:22:31 2013 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 28 Feb 2013 19:22:31 +0100 Subject: unclear behaviour LAC authorization In-Reply-To: References: Message-ID: <20130228182231.GC26531@xiaoyu.lan> On Thu, Feb 28, 2013 at 04:33:41PM +0100, Max van Biezen wrote: Hi, > <000d> db.c:161 DBI: -7: The requested variable type does not match > what libdbi thinks it should be I have never seen this error message. Maybe it is related to the failure you are seeing? holger From ivanmikey2 at gmail.com Thu Feb 28 21:50:41 2013 From: ivanmikey2 at gmail.com (Ivan Mikey) Date: Thu, 28 Feb 2013 13:50:41 -0800 Subject: Fwd: ASN1C In-Reply-To: References: Message-ID: Hi, I sent previous message but didn't get anything, so I'm sending this group. Thanks, ---------- Forwarded message ---------- From: Ivan Mikey Date: Thu, Feb 28, 2013 at 1:32 PM Subject: ASN1C To: baseband-devel at lists.osmocom.org Hi, I've been searching for help regarding the ASN1C in http://cgit.osmocom.org/cgit/. I'm not sure if this is the right group to contact or not, if not please let me know and I apologize for it. I've installed the following SS7/MAP asn1c libasn1c libosmo-asn1-map libosmo-asn1-tcap libosmo-tcap libsu osmo-tcap-map and then did the below and I got the following errors. /osmo-tcap-map/test$ make cc -lasn1c -losmo-asn1-map -losmo-asn1-tcap -lm -o gprs_update gprs_update.o gprs_update.o: In function `create_map_invoke': gprs_update.c:(.text+0xf0): undefined reference to `asn_long2INTEGER' gprs_update.c:(.text+0x111): undefined reference to `ANY_new_fromType' gprs_update.o: In function `upd_gprs_loc_invoke': gprs_update.c:(.text+0x160): undefined reference to `OCTET_STRING_fromBuf' gprs_update.c:(.text+0x17d): undefined reference to `OCTET_STRING_fromBuf' gprs_update.c:(.text+0x19a): undefined reference to `OCTET_STRING_fromBuf' gprs_update.c:(.text+0x1ad): undefined reference to `asn_DEF_UpdateGprsLocationArg' gprs_update.c:(.text+0x1b5): undefined reference to `xer_fprint' gprs_update.c:(.text+0x1c4): undefined reference to `asn_DEF_UpdateGprsLocationArg' gprs_update.c:(.text+0x1e2): undefined reference to `asn_DEF_Component' gprs_update.c:(.text+0x1ea): undefined reference to `xer_fprint' gprs_update.o: In function `upd_gprs_loc_aarq': gprs_update.c:(.text+0x2d7): undefined reference to `OBJECT_IDENTIFIER_set_arcs' gprs_update.c:(.text+0x2e7): undefined reference to `asn_DEF_DialoguePDU' gprs_update.c:(.text+0x2ef): undefined reference to `xer_fprint' gprs_update.o: In function `tcap_msg': gprs_update.c:(.text+0x3e9): undefined reference to `OCTET_STRING_fromBuf' gprs_update.c:(.text+0x415): undefined reference to `OBJECT_IDENTIFIER_set_arcs' gprs_update.c:(.text+0x42c): undefined reference to `asn_DEF_DialoguePDU' gprs_update.c:(.text+0x434): undefined reference to `ANY_fromType' gprs_update.c:(.text+0x443): undefined reference to `asn_DEF_ExternalPDU' gprs_update.c:(.text+0x448): undefined reference to `ANY_new_fromType' gprs_update.c:(.text+0x492): undefined reference to `asn_set_add' gprs_update.c:(.text+0x4a2): undefined reference to `asn_DEF_TCMessage' gprs_update.c:(.text+0x4aa): undefined reference to `xer_fprint' collect2: ld returned 1 exit status make: *** [gprs_update] Error 1 Thanks Ivan -------------- next part -------------- An HTML attachment was scrubbed... URL: From jolly at eversberg.eu Tue Feb 5 10:04:00 2013 From: jolly at eversberg.eu (Andreas Eversberg) Date: Tue, 5 Feb 2013 11:04:00 +0100 Subject: [PATCH 2/7] Add PH-/MPH-/TCH-SAP interface to common part of osmo-bts Message-ID: Instead of handling primitives directly at layer 1 specific code, osmo-bts handles primitives at common code. Therefore a new file 'l1sap.c' is added and integrated. The l1sap.c file: - receives PH-DATA indications and forwards them to layer 2. - checks for RF link loss and notifies BSC. - receives TCH indications and forwards them via RTP. - receives PH-RTS indications and sends PH-DATA requests with content according to its logical channel. - receives TCH-RTS indications and sends TCH requests with content received via RTP or loopback from TCH indications. - send MPH-INFO requests to activate, deactivate and modify logical channels and handles their confirms. - receives MPH-INFO indications with measurements from tranceiver. - forwards received and transmitted PH-DATA to GSMTAP. Therefore some obsolete bts_model_* calls have been replaced by bts_model_l1sap_down to send primitves down to layer 1 specific code. --- include/osmo-bts/Makefile.am | 3 +- include/osmo-bts/bts.h | 2 + include/osmo-bts/bts_model.h | 12 +- include/osmo-bts/gsm_data.h | 1 + include/osmo-bts/l1sap.h | 71 +++ include/osmo-bts/rsl.h | 2 +- include/osmo-bts/vty.h | 4 +- src/common/Makefile.am | 2 +- src/common/bts.c | 8 + src/common/l1sap.c | 948 +++++++++++++++++++++++++++++++++++++ src/common/logging.c | 4 +- src/common/measurement.c | 5 + src/common/pcu_sock.c | 15 +- src/common/rsl.c | 29 +- src/common/vty.c | 131 +++++- src/osmo-bts-sysmo/l1_if.c | 6 + src/osmo-bts-sysmo/main.c | 2 +- src/osmo-bts-sysmo/oml.c | 4 +- src/osmo-bts-sysmo/sysmobts_vty.c | 27 - tests/stubs.c | 3 + 20 files changed, 1206 insertions(+), 73 deletions(-) create mode 100644 include/osmo-bts/l1sap.h create mode 100644 src/common/l1sap.c diff --git a/include/osmo-bts/Makefile.am b/include/osmo-bts/Makefile.am index 456d416..d8c0002 100644 --- a/include/osmo-bts/Makefile.am +++ b/include/osmo-bts/Makefile.am @@ -1,2 +1,3 @@ noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h logging.h measurement.h \ - oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h + oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h \ + pcuif_proto.h l1sap.h diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h index 583c1eb..6b91c82 100644 --- a/include/osmo-bts/bts.h +++ b/include/osmo-bts/bts.h @@ -27,5 +27,7 @@ int lchan_init_lapdm(struct gsm_lchan *lchan); void load_timer_start(struct gsm_bts *bts); +struct gsm_time *get_time(struct gsm_bts *bts); + #endif /* _BTS_H */ diff --git a/include/osmo-bts/bts_model.h b/include/osmo-bts/bts_model.h index bfa6bd8..3b2855a 100644 --- a/include/osmo-bts/bts_model.h +++ b/include/osmo-bts/bts_model.h @@ -12,8 +12,6 @@ int bts_model_init(struct gsm_bts *bts); -struct gsm_time *bts_model_get_time(struct gsm_bts *bts); - int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type, struct tlv_parsed *old_attr, struct tlv_parsed *new_attr, void *obj); @@ -27,20 +25,14 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj, uint8_t adm_state); -int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp); -int bts_model_rsl_chan_rel(struct gsm_lchan *lchan); -int bts_model_rsl_deact_sacch(struct gsm_lchan *lchan); -int bts_model_rsl_mode_modify(struct gsm_lchan *lchan); - int bts_model_trx_deact_rf(struct gsm_bts_trx *trx); int bts_model_trx_close(struct gsm_bts_trx *trx); -void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl, - unsigned int rtp_pl_len); - int bts_model_vty_init(struct gsm_bts *bts); void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts); void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx); +int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); + #endif diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h index c6cd7e4..980f8ef 100644 --- a/include/osmo-bts/gsm_data.h +++ b/include/osmo-bts/gsm_data.h @@ -58,6 +58,7 @@ struct gsm_bts_role_bts { struct { uint8_t tc4_ctr; } si; + struct gsm_time gsm_time; uint8_t radio_link_timeout; /* used by the sysmoBTS to adjust band */ diff --git a/include/osmo-bts/l1sap.h b/include/osmo-bts/l1sap.h new file mode 100644 index 0000000..a1dc303 --- /dev/null +++ b/include/osmo-bts/l1sap.h @@ -0,0 +1,71 @@ +#ifndef L1SAP_H +#define L1SAP_H + +/* timeslot and subslot from chan_nr */ +#define L1SAP_CHAN2TS(chan_nr) (chan_nr & 7) +#define L1SAP_CHAN2SS_TCHH(chan_nr) ((chan_nr >> 3) & 1) +#define L1SAP_CHAN2SS_SDCCH4(chan_nr) ((chan_nr >> 3) & 3) +#define L1SAP_CHAN2SS_SDCCH8(chan_nr) ((chan_nr >> 3) & 7) + +/* logical channel from chan_nr + link_id */ +#define L1SAP_IS_LINK_SACCH(link_id) ((link_id & 0xC0) == 0x40) +#define L1SAP_IS_CHAN_TCHF(chan_nr) ((chan_nr & 0xf8) == 0x08) +#define L1SAP_IS_CHAN_TCHH(chan_nr) ((chan_nr & 0xf0) == 0x10) +#define L1SAP_IS_CHAN_SDCCH4(chan_nr) ((chan_nr & 0xe0) == 0x20) +#define L1SAP_IS_CHAN_SDCCH8(chan_nr) ((chan_nr & 0xc0) == 0x40) +#define L1SAP_IS_CHAN_BCCH(chan_nr) ((chan_nr & 0xf8) == 0x80) +#define L1SAP_IS_CHAN_RACH(chan_nr) ((chan_nr & 0xf8) == 0x88) +#define L1SAP_IS_CHAN_AGCH_PCH(chan_nr) ((chan_nr & 0xf8) == 0x90) + +/* rach type from ra */ +#define L1SAP_IS_PACKET_RACH(ra) ((ra & 0xf0) == 0x70) + +/* CCCH block from frame number */ +#define L1SAP_FN2CCCHBLOCK(fn) ((fn % 51) / 5 - 1) + +/* PTCH layout from frame number */ +#define L1SAP_FN2MACBLOCK(fn) ((fn % 52) / 4) +#define L1SAP_FN2PTCCHBLOCK(fn) ((fn / 52) & 7) +#define L1SAP_IS_PTCCH(fn) ((fn % 52) == 12) + +/* subslot from any chan_nr */ +static inline uint8_t l1sap_chan2ss(uint8_t chan_nr) +{ + if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) + return L1SAP_CHAN2SS_SDCCH8(chan_nr); + if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) + return L1SAP_CHAN2SS_SDCCH4(chan_nr); + if (L1SAP_IS_CHAN_TCHH(chan_nr)) + return L1SAP_CHAN2SS_TCHH(chan_nr); + return 0; +} + + +/* allocate a msgb containing a osmo_phsap_prim + optional l2 data */ +struct msgb *l1sap_msgb_alloc(unsigned int l2_len); + +/* any L1 prim received from bts model */ +int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); + +/* pcu (socket interface) sends us a data request primitive */ +int l1sap_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn, + uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len); + +/* call-back function for incoming RTP */ +void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl, + unsigned int rtp_pl_len); + +/* channel control */ +int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr); +int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr); +int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr); +int l1sap_chan_modify(struct gsm_bts_trx *trx, uint8_t chan_nr); + +extern const struct value_string gsmtap_sapi_names[]; +extern struct gsmtap_inst *gsmtap; +extern uint32_t gsmtap_sapi_mask; +extern uint8_t gsmtap_sapi_acch; + +#define msgb_l1sap_prim(msg) ((struct osmo_phsap_prim *)(msg)->l1h) + +#endif /* L1SAP_H */ diff --git a/include/osmo-bts/rsl.h b/include/osmo-bts/rsl.h index 251cd23..eae7845 100644 --- a/include/osmo-bts/rsl.h +++ b/include/osmo-bts/rsl.h @@ -7,7 +7,7 @@ int rsl_tx_chan_rqd(struct gsm_bts_trx *trx, struct gsm_time *gtime, uint8_t ra, uint8_t acc_delay); int rsl_tx_est_ind(struct gsm_lchan *lchan, uint8_t link_id, uint8_t *data, int len); -int rsl_tx_chan_act_ack(struct gsm_lchan *lchan, struct gsm_time *gtime); +int rsl_tx_chan_act_ack(struct gsm_lchan *lchan); int rsl_tx_chan_act_nack(struct gsm_lchan *lchan, uint8_t cause); int rsl_tx_conn_fail(struct gsm_lchan *lchan, uint8_t cause); int rsl_tx_rf_rel_ack(struct gsm_lchan *lchan); diff --git a/include/osmo-bts/vty.h b/include/osmo-bts/vty.h index 1bc7e71..9b113a8 100644 --- a/include/osmo-bts/vty.h +++ b/include/osmo-bts/vty.h @@ -15,8 +15,10 @@ extern struct cmd_element ournode_end_cmd; enum node_type bts_vty_go_parent(struct vty *vty); int bts_vty_is_config_node(struct vty *vty, int node); -int bts_vty_init(const struct log_info *cat); +int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat); extern struct vty_app_info bts_vty_info; +char *osmo_str_tolower(const char *in); + #endif diff --git a/src/common/Makefile.am b/src/common/Makefile.am index b2f6f8e..1c6ff9e 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -5,4 +5,4 @@ LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS) noinst_LIBRARIES = libbts.a libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \ rsl.c vty.c paging.c measurement.c amr.c lchan.c \ - load_indication.c pcu_sock.c + load_indication.c pcu_sock.c l1sap.c diff --git a/src/common/bts.c b/src/common/bts.c index e899ebd..c495fcd 100644 --- a/src/common/bts.c +++ b/src/common/bts.c @@ -239,3 +239,11 @@ int bts_supports_cipher(struct gsm_bts_role_bts *bts, int rsl_cipher) sup = (1 << (rsl_cipher - 2)) & bts->support.ciphers; return sup > 0; } + +struct gsm_time *get_time(struct gsm_bts *bts) +{ + struct gsm_bts_role_bts *btsb = bts->role; + + return &btsb->gsm_time; +} + diff --git a/src/common/l1sap.c b/src/common/l1sap.c new file mode 100644 index 0000000..ad833ea --- /dev/null +++ b/src/common/l1sap.c @@ -0,0 +1,948 @@ +/* L1 SAP primitives */ + +/* (C) 2011 by Harald Welte + * (C) 2013 by Andreas Eversberg + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); + +static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = { + 0x03, 0x03, 0x01, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, + 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, + 0x2B, 0x2B, 0x2B +}; + +/* allocate a msgb containing a osmo_phsap_prim + optional l2 data */ +struct msgb *l1sap_msgb_alloc(unsigned int l2_len) +{ + struct msgb *msg = msgb_alloc(sizeof(struct osmo_phsap_prim) + l2_len, + "l1sap_prim"); + + if (!msg) + return NULL; + + msg->l1h = msgb_put(msg, sizeof(struct osmo_phsap_prim)); + + return msg; +} + +static int l1sap_tx_ciph_req(struct gsm_bts_trx *trx, uint8_t chan_nr, + uint8_t downlink, uint8_t uplink) +{ + struct osmo_phsap_prim l1sap_ciph; + + osmo_prim_init(&l1sap_ciph.oph, SAP_GSM_PH, PRIM_MPH_INFO, + PRIM_OP_REQUEST, NULL); + l1sap_ciph.u.info.type = PRIM_INFO_ACT_CIPH; + l1sap_ciph.u.info.u.ciph_req.chan_nr = chan_nr; + l1sap_ciph.u.info.u.ciph_req.downlink = downlink; + l1sap_ciph.u.info.u.ciph_req.uplink = uplink; + + return l1sap_down(trx, &l1sap_ciph); +} + + +/* check if the message is a GSM48_MT_RR_CIPH_M_CMD, and if yes, enable + * uni-directional de-cryption on the uplink. We need this ugly layering + * violation as we have no way of passing down L3 metadata (RSL CIPHERING CMD) + * to this point in L1 */ +static int check_for_ciph_cmd(struct msgb *msg, struct gsm_lchan *lchan, + uint8_t chan_nr) +{ + + /* only do this if we are in the right state */ + switch (lchan->ciph_state) { + case LCHAN_CIPH_NONE: + case LCHAN_CIPH_RX_REQ: + break; + default: + return 0; + } + + /* First byte (Address Field) of LAPDm header) */ + if (msg->data[0] != 0x03) + return 0; + /* First byte (protocol discriminator) of RR */ + if ((msg->data[3] & 0xF) != GSM48_PDISC_RR) + return 0; + /* 2nd byte (msg type) of RR */ + if ((msg->data[4] & 0x3F) != GSM48_MT_RR_CIPH_M_CMD) + return 0; + + l1sap_tx_ciph_req(lchan->ts->trx, chan_nr, 0, 1); + + return 1; +} + +struct gsmtap_inst *gsmtap = NULL; +uint32_t gsmtap_sapi_mask = 0; +uint8_t gsmtap_sapi_acch = 0; + +const struct value_string gsmtap_sapi_names[] = { + { GSMTAP_CHANNEL_BCCH, "BCCH" }, + { GSMTAP_CHANNEL_CCCH, "CCCH" }, + { GSMTAP_CHANNEL_RACH, "RACH" }, + { GSMTAP_CHANNEL_AGCH, "AGCH" }, + { GSMTAP_CHANNEL_PCH, "PCH" }, + { GSMTAP_CHANNEL_SDCCH, "SDCCH" }, + { GSMTAP_CHANNEL_TCH_F, "TCH/F" }, + { GSMTAP_CHANNEL_TCH_H, "TCH/H" }, + { GSMTAP_CHANNEL_PACCH, "PACCH" }, + { GSMTAP_CHANNEL_PDCH, "PDTCH" }, + { GSMTAP_CHANNEL_PTCCH, "PTCCH" }, + { GSMTAP_CHANNEL_CBCH51,"CBCH" }, + { GSMTAP_CHANNEL_ACCH, "SACCH" }, + { 0, NULL } +}; + +static int to_gsmtap(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) +{ + struct msgb *msg = l1sap->oph.msg; + uint8_t *data; + int len; + uint8_t chan_type = 0, tn = 0, ss = 0; + uint32_t fn; + uint8_t chan_nr, link_id; + uint16_t uplink = GSMTAP_ARFCN_F_UPLINK; + + if (!gsmtap) + return 0; + + switch (OSMO_PRIM_HDR(&l1sap->oph)) { + case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST): + uplink = 0; + /* fall through */ + case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_INDICATION): + data = msg->data + sizeof(struct osmo_phsap_prim); + len = msg->len - sizeof(struct osmo_phsap_prim); + fn = l1sap->u.data.fn; + tn = L1SAP_CHAN2TS(l1sap->u.data.chan_nr); + chan_nr = l1sap->u.data.chan_nr; + link_id = l1sap->u.data.link_id; + if (L1SAP_IS_CHAN_TCHF(chan_nr)) { + if (trx->ts[tn].pchan == GSM_PCHAN_PDCH) { + if (L1SAP_IS_PTCCH(fn)) { + chan_type = GSMTAP_CHANNEL_PTCCH; + ss = L1SAP_FN2PTCCHBLOCK(fn); + if (l1sap->oph.primitive + == PRIM_OP_INDICATION) { + if (data[0] == 7) + return -EINVAL; + data++; + len--; + } + } else { + chan_type = GSMTAP_CHANNEL_PACCH; + } + } else + chan_type = GSMTAP_CHANNEL_TCH_F; + } else if (L1SAP_IS_CHAN_TCHH(chan_nr)) { + ss = L1SAP_CHAN2SS_TCHH(chan_nr); + chan_type = GSMTAP_CHANNEL_TCH_H; + } else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) { + ss = L1SAP_CHAN2SS_SDCCH4(chan_nr); + chan_type = GSMTAP_CHANNEL_SDCCH; + } else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) { + ss = L1SAP_CHAN2SS_SDCCH8(chan_nr); + chan_type = GSMTAP_CHANNEL_SDCCH; + } else if (L1SAP_IS_CHAN_BCCH(chan_nr)) { + chan_type = GSMTAP_CHANNEL_BCCH; + } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { +#warning Set BS_AG_BLKS_RES + /* The sapi depends on DSP configuration, not + * on the actual SYSTEM INFORMATION 3. */ + if (L1SAP_FN2CCCHBLOCK(fn) >= 1) + chan_type = GSMTAP_CHANNEL_PCH; + else + chan_type = GSMTAP_CHANNEL_AGCH; + } + if (L1SAP_IS_LINK_SACCH(link_id)) + chan_type |= GSMTAP_CHANNEL_ACCH; + break; + case OSMO_PRIM(PRIM_PH_RACH, PRIM_OP_INDICATION): + chan_type = GSMTAP_CHANNEL_RACH; + fn = l1sap->u.rach_ind.fn; + tn = L1SAP_CHAN2TS(l1sap->u.rach_ind.chan_nr); + chan_nr = l1sap->u.rach_ind.chan_nr; + if (L1SAP_IS_CHAN_TCHH(chan_nr)) + ss = L1SAP_CHAN2SS_TCHH(chan_nr); + else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) + ss = L1SAP_CHAN2SS_SDCCH4(chan_nr); + else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) + ss = L1SAP_CHAN2SS_SDCCH8(chan_nr); + data = &l1sap->u.rach_ind.ra; + len = 1; + break; + default: + return -ENOTSUP; + } + + if (len == 0) + return 0; + if ((chan_type & GSMTAP_CHANNEL_ACCH)) { + if (!gsmtap_sapi_acch) + return 0; + } else { + if (!((1 << (chan_type & 31)) & gsmtap_sapi_mask)) + return 0; + } + + gsmtap_send(gsmtap, trx->arfcn | uplink, tn, chan_type, ss, fn, 0, 0, + data, len); + + return 0; +} + +/* time information received from bts model */ +static int l1sap_info_time_ind(struct gsm_bts_trx *trx, + struct osmo_phsap_prim *l1sap, + struct info_time_ind_param *info_time_ind) +{ + struct gsm_bts *bts = trx->bts; + struct gsm_bts_role_bts *btsb = bts->role; + + DEBUGP(DL1P, "MPH_INFO time ind %u\n", info_time_ind->fn); + + /* Update our data structures with the current GSM time */ + gsm_fn2gsmtime(&btsb->gsm_time, info_time_ind->fn); + + /* Update time on PCU interface */ + pcu_tx_time_ind(info_time_ind->fn); + + /* check if the measurement period of some lchan has ended + * and pre-compute the respective measurement */ + trx_meas_check_compute(trx, info_time_ind->fn - 1); + + /* increment 'total' for every possible rach */ + if (bts->c0->ts[0].pchan != GSM_PCHAN_CCCH_SDCCH4 + || (info_time_ind->fn % 51) < 27) + btsb->load.rach.total++; + + return 0; +} + +/* measurement information received from bts model */ +static int l1sap_info_meas_ind(struct gsm_bts_trx *trx, + struct osmo_phsap_prim *l1sap, + struct info_meas_ind_param *info_meas_ind) +{ + struct bts_ul_meas ulm; + struct gsm_lchan *lchan; + + DEBUGP(DL1P, "MPH_INFO meas ind chan_nr=%02x\n", + info_meas_ind->chan_nr); + + lchan = &trx->ts[L1SAP_CHAN2TS(info_meas_ind->chan_nr)] + .lchan[l1sap_chan2ss(info_meas_ind->chan_nr)]; + + /* in the GPRS case we are not interested in measurement + * processing. The PCU will take care of it */ + if (lchan->type == GSM_LCHAN_PDTCH) + return 0; + + memset(&ulm, 0, sizeof(ulm)); + ulm.ta_offs_qbits = info_meas_ind->ta_offs_qbits; + ulm.ber10k = info_meas_ind->ber10k; + ulm.inv_rssi = info_meas_ind->inv_rssi; + + lchan_new_ul_meas(lchan, &ulm); + + return 0; +} + +/* any L1 MPH_INFO indication prim recevied from bts model */ +static int l1sap_mph_info_ind(struct gsm_bts_trx *trx, + struct osmo_phsap_prim *l1sap, struct mph_info_param *info) +{ + int rc = 0; + + switch (info->type) { + case PRIM_INFO_TIME: + rc = l1sap_info_time_ind(trx, l1sap, &info->u.time_ind); + break; + case PRIM_INFO_MEAS: + rc = l1sap_info_meas_ind(trx, l1sap, &info->u.meas_ind); + break; + default: + LOGP(DL1P, LOGL_NOTICE, "unknown MPH_INFO ind type %d\n", + info->type); + break; + } + + return rc; +} + +/* activation confirm received from bts model */ +static int l1sap_info_act_cnf(struct gsm_bts_trx *trx, + struct osmo_phsap_prim *l1sap, + struct info_act_cnf_param *info_act_cnf) +{ + struct gsm_lchan *lchan; + + LOGP(DL1P, LOGL_INFO, "activate confirm chan_nr=%02x trx=%d\n", + info_act_cnf->chan_nr, trx->nr); + + lchan = &trx->ts[L1SAP_CHAN2TS(info_act_cnf->chan_nr)] + .lchan[l1sap_chan2ss(info_act_cnf->chan_nr)]; + + if (info_act_cnf->cause) + rsl_tx_chan_act_nack(lchan, info_act_cnf->cause); + else + rsl_tx_chan_act_ack(lchan); + + return 0; +} + +/* activation confirm received from bts model */ +static int l1sap_info_rel_cnf(struct gsm_bts_trx *trx, + struct osmo_phsap_prim *l1sap, + struct info_act_cnf_param *info_act_cnf) +{ + struct gsm_lchan *lchan; + + LOGP(DL1P, LOGL_INFO, "deactivate confirm chan_nr=%02x trx=%d\n", + info_act_cnf->chan_nr, trx->nr); + + lchan = &trx->ts[L1SAP_CHAN2TS(info_act_cnf->chan_nr)] + .lchan[l1sap_chan2ss(info_act_cnf->chan_nr)]; + + rsl_tx_rf_rel_ack(lchan); + + return 0; +} + +/* any L1 MPH_INFO confirm prim recevied from bts model */ +static int l1sap_mph_info_cnf(struct gsm_bts_trx *trx, + struct osmo_phsap_prim *l1sap, struct mph_info_param *info) +{ + int rc = 0; + + switch (info->type) { + case PRIM_INFO_ACTIVATE: + rc = l1sap_info_act_cnf(trx, l1sap, &info->u.act_cnf); + break; + case PRIM_INFO_DEACTIVATE: + rc = l1sap_info_rel_cnf(trx, l1sap, &info->u.act_cnf); + break; + default: + LOGP(DL1P, LOGL_NOTICE, "unknown MPH_INFO cnf type %d\n", + info->type); + break; + } + + return rc; +} + +/* PH-RTS-IND prim recevied from bts model */ +static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx, + struct osmo_phsap_prim *l1sap, struct ph_data_param *rts_ind) +{ + struct msgb *msg = l1sap->oph.msg; + struct gsm_time g_time; + struct gsm_lchan *lchan; + uint8_t chan_nr, link_id; + uint8_t tn, ss; + uint32_t fn; + uint8_t *p, *si; + struct lapdm_entity *le; + struct osmo_phsap_prim pp; + int rc; + + chan_nr = rts_ind->chan_nr; + link_id = rts_ind->link_id; + fn = rts_ind->fn; + tn = L1SAP_CHAN2TS(chan_nr); + + gsm_fn2gsmtime(&g_time, fn); + + DEBUGP(DL1P, "Rx PH-RTS.ind %02u/%02u/%02u chan_nr=%d link_id=%d\n", + g_time.t1, g_time.t2, g_time.t3, chan_nr, link_id); + + if (trx->ts[tn].pchan == GSM_PCHAN_PDCH) { + if (L1SAP_IS_PTCCH(rts_ind->fn)) { + pcu_tx_rts_req(&trx->ts[tn], 1, fn, 1 /* ARFCN */, + L1SAP_FN2PTCCHBLOCK(fn)); + + return 0; + } + pcu_tx_rts_req(&trx->ts[tn], 0, fn, 0 /* ARFCN */, + L1SAP_FN2MACBLOCK(fn)); + + return 0; + } + + /* reuse PH-RTS.ind for PH-DATA.req */ + if (!msg) { + LOGP(DL1P, LOGL_FATAL, "RTS without msg to be reused. Please " + "fix!\n"); + abort(); + } + msgb_trim(msg, sizeof(*l1sap)); + osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, PRIM_OP_REQUEST, + msg); + msg->l2h = msg->l1h + sizeof(*l1sap); + + if (L1SAP_IS_CHAN_BCCH(chan_nr)) { + p = msgb_put(msg, GSM_MACBLOCK_LEN); + /* get them from bts->si_buf[] */ + si = bts_sysinfo_get(trx->bts, &g_time); + if (si) + memcpy(p, si, GSM_MACBLOCK_LEN); + else + memcpy(p, fill_frame, GSM_MACBLOCK_LEN); + } else if (!(chan_nr & 0x80)) { /* only TCH/F, TCH/H, SDCCH/4 and SDCCH/8 have C5 bit cleared */ + if (L1SAP_IS_CHAN_TCHH(chan_nr)) + ss = L1SAP_CHAN2SS_TCHH(chan_nr); /* TCH/H */ + else if (L1SAP_IS_CHAN_SDCCH4(chan_nr)) + ss = L1SAP_CHAN2SS_SDCCH4(chan_nr); /* SDCCH/4 */ + else if (L1SAP_IS_CHAN_SDCCH8(chan_nr)) + ss = L1SAP_CHAN2SS_SDCCH8(chan_nr); /* SDCCH/8 */ + else + ss = 0; /* TCH/F */ + lchan = &trx->ts[tn].lchan[ss]; + if (L1SAP_IS_LINK_SACCH(link_id)) { + p = msgb_put(msg, GSM_MACBLOCK_LEN); + /* L1-header, if not set/modified by layer 1 */ + p[0] = lchan->ms_power; + p[1] = lchan->rqd_ta; + le = &lchan->lapdm_ch.lapdm_acch; + } else + le = &lchan->lapdm_ch.lapdm_dcch; + rc = lapdm_phsap_dequeue_prim(le, &pp); + if (rc < 0) { + if (L1SAP_IS_LINK_SACCH(link_id)) { + /* No SACCH data from LAPDM pending, send SACCH filling */ + uint8_t *si = lchan_sacch_get(lchan, &g_time); + if (si) { + /* The +2 is empty space where the DSP inserts the L1 hdr */ + memcpy(p + 2, si, GSM_MACBLOCK_LEN - 2); + } else + memcpy(p + 2, fill_frame, GSM_MACBLOCK_LEN - 2); + } else if ((!L1SAP_IS_CHAN_TCHF(chan_nr) && !L1SAP_IS_CHAN_TCHH(chan_nr)) + || lchan->rsl_cmode == RSL_CMOD_SPD_SIGN) { + /* send fill frame only, if not TCH/x != Signalling, otherwise send empty frame */ + p = msgb_put(msg, GSM_MACBLOCK_LEN); + memcpy(p, fill_frame, GSM_MACBLOCK_LEN); + } /* else the message remains empty, so TCH frames are sent */ + } else { + /* The +2 is empty space where the DSP inserts the L1 hdr */ + if (L1SAP_IS_LINK_SACCH(link_id)) + memcpy(p + 2, pp.oph.msg->data + 2, GSM_MACBLOCK_LEN - 2); + else { + p = msgb_put(msg, GSM_MACBLOCK_LEN); + memcpy(p, pp.oph.msg->data, GSM_MACBLOCK_LEN); + /* check if it is a RR CIPH MODE CMD. if yes, enable RX ciphering */ + check_for_ciph_cmd(pp.oph.msg, lchan, chan_nr); + } + msgb_free(pp.oph.msg); + } + } else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) { + p = msgb_put(msg, GSM_MACBLOCK_LEN); +#warning Set BS_AG_BLKS_RES + /* The sapi depends on DSP configuration, not + * on the actual SYSTEM INFORMATION 3. */ + struct gsm_bts_role_bts *btsb = trx->bts->role; + if (L1SAP_FN2CCCHBLOCK(fn) >= 1) { + /* PCH */ + paging_gen_msg(btsb->paging_state, p, &g_time); + } else { + /* AGCH */ + /* special queue of messages from IMM ASS CMD */ + struct msgb *amsg = bts_agch_dequeue(trx->bts); + if (!amsg) + memcpy(p, fill_frame, GSM_MACBLOCK_LEN); + else { + memcpy(p, amsg->data, amsg->len); + msgb_free(amsg); + } + } + } + + DEBUGP(DL1P, "Tx PH-DATA.req %02u/%02u/%02u chan_nr=%d link_id=%d\n", + g_time.t1, g_time.t2, g_time.t3, chan_nr, link_id); + + l1sap_down(trx, l1sap); + + /* don't free, because we forwarded data */ + return 1; +} + +/* TCH-RTS-IND prim recevied from bts model */ +static int l1sap_tch_rts_ind(struct gsm_bts_trx *trx, + struct osmo_phsap_prim *l1sap, struct ph_tch_param *rts_ind) +{ + struct msgb *resp_msg; + struct osmo_phsap_prim *resp_l1sap, empty_l1sap; + struct gsm_time g_time; + struct gsm_lchan *lchan; + uint8_t chan_nr; + uint8_t tn, ss; + uint32_t fn; + + chan_nr = rts_ind->chan_nr; + fn = rts_ind->fn; + tn = L1SAP_CHAN2TS(chan_nr); + + gsm_fn2gsmtime(&g_time, fn); + + DEBUGP(DL1P, "Rx TCH-RTS.ind %02u/%02u/%02u chan_nr=%d\n", + g_time.t1, g_time.t2, g_time.t3, chan_nr); + + /* get timeslot and subslot */ + tn = L1SAP_CHAN2TS(chan_nr); + if (L1SAP_IS_CHAN_TCHH(chan_nr)) + ss = L1SAP_CHAN2SS_TCHH(chan_nr); /* TCH/H */ + else + ss = 0; /* TCH/F */ + lchan = &trx->ts[tn].lchan[ss]; + + if (!lchan->loopback && lchan->abis_ip.rtp_socket) { + osmo_rtp_socket_poll(lchan->abis_ip.rtp_socket); + /* FIXME: we _assume_ that we never miss TDMA + * frames and that we always get to this point + * for every to-be-transmitted voice frame. A + * better solution would be to compute + * rx_user_ts based on how many TDMA frames have + * elapsed since the last call */ + lchan->abis_ip.rtp_socket->rx_user_ts += GSM_RTP_DURATION; + } + /* get a msgb from the dl_tx_queue */ + resp_msg = msgb_dequeue(&lchan->dl_tch_queue); + if (!resp_msg) { + LOGP(DL1P, LOGL_DEBUG, "%s DL TCH Tx queue underrun\n", + gsm_lchan_name(lchan)); + resp_l1sap = &empty_l1sap; + } else { + resp_msg->l2h = resp_msg->data; + msgb_push(resp_msg, sizeof(*resp_l1sap)); + resp_msg->l1h = resp_msg->data; + resp_l1sap = msgb_l1sap_prim(resp_msg); + } + + memset(resp_l1sap, 0, sizeof(*resp_l1sap)); + osmo_prim_init(&resp_l1sap->oph, SAP_GSM_PH, PRIM_TCH, PRIM_OP_REQUEST, + resp_msg); + resp_l1sap->u.tch.chan_nr = chan_nr; + resp_l1sap->u.tch.fn = fn; + + DEBUGP(DL1P, "Tx TCH.req %02u/%02u/%02u chan_nr=%d\n", + g_time.t1, g_time.t2, g_time.t3, chan_nr); + + l1sap_down(trx, resp_l1sap); + + return 0; +} + +/* DATA received from bts model */ +static int l1sap_ph_data_ind(struct gsm_bts_trx *trx, + struct osmo_phsap_prim *l1sap, struct ph_data_param *data_ind) +{ + struct msgb *msg = l1sap->oph.msg; + struct gsm_time g_time; + struct gsm_lchan *lchan; + struct lapdm_entity *le; + uint8_t *data = msg->l2h; + int len = msgb_l2len(msg); + uint8_t chan_nr, link_id; + uint8_t tn, ss; + uint32_t fn; + int8_t rssi; + + rssi = data_ind->rssi; + chan_nr = data_ind->chan_nr; + link_id = data_ind->link_id; + fn = data_ind->fn; + tn = L1SAP_CHAN2TS(chan_nr); + ss = l1sap_chan2ss(chan_nr); + + gsm_fn2gsmtime(&g_time, fn); + + DEBUGP(DL1P, "Rx PH-DATA.ind %02u/%02u/%02u chan_nr=%d link_id=%d\n", + g_time.t1, g_time.t2, g_time.t3, chan_nr, link_id); + + if (trx->ts[tn].pchan == GSM_PCHAN_PDCH) { + if (len == 0) + return -EINVAL; + if (L1SAP_IS_PTCCH(fn)) { + pcu_tx_data_ind(&trx->ts[tn], 1, fn, + 0 /* ARFCN */, L1SAP_FN2PTCCHBLOCK(fn), + data, len, rssi); + + return 0; + } + /* drop incomplete UL block */ + if (data[0] != 7) + return 0; + /* PDTCH / PACCH frame handling */ + pcu_tx_data_ind(&trx->ts[tn], 0, fn, 0 /* ARFCN */, + L1SAP_FN2MACBLOCK(fn), data + 1, len - 1, rssi); + + return 0; + } + + lchan = &trx->ts[tn].lchan[ss]; + + /* bad frame */ + if (len == 0) { + if (L1SAP_IS_LINK_SACCH(link_id) && lchan->s > 0) { + /* count down radio link counter S */ + lchan->s--; + DEBUGP(DMEAS, "counting down radio link counter S=%d\n", + lchan->s); + if (lchan->s == 0) + rsl_tx_conn_fail(lchan, + RSL_ERR_RADIO_LINK_FAIL); + } + + return -EINVAL; + } + + if (L1SAP_IS_LINK_SACCH(link_id)) { + struct gsm_bts_role_bts *btsb = trx->bts->role; + + le = &lchan->lapdm_ch.lapdm_acch; + /* count up radio link counter S */ + if (lchan->s < btsb->radio_link_timeout) { + lchan->s += 2; + if (lchan->s > btsb->radio_link_timeout) + lchan->s = btsb->radio_link_timeout; + DEBUGP(DMEAS, "counting up radio link counter S=%d\n", + lchan->s); + } + /* save the SACCH L1 header in the lchan struct for RSL MEAS RES */ + if (len < 2) { + LOGP(DL1P, LOGL_NOTICE, "SACCH with size %u<2 !?!\n", + len); + return -EINVAL; + } + /* Some brilliant engineer decided that the ordering of + * fields on the Um interface is different from the + * order of fields in RLS. See TS 04.04 (Chapter 7.2) + * vs. TS 08.58 (Chapter 9.3.10). */ + lchan->meas.l1_info[0] = data[0] << 3; + lchan->meas.l1_info[0] |= ((data[0] >> 5) & 1) << 2; + lchan->meas.l1_info[1] = data[1]; + lchan->meas.flags |= LC_UL_M_F_L1_VALID; + } else + le = &lchan->lapdm_ch.lapdm_dcch; + + /* if this is the first valid message after enabling Rx + * decryption, we have to enable Tx encryption */ + if (lchan->ciph_state == LCHAN_CIPH_RX_CONF) { + /* HACK: check if it's an I frame, in order to + * ignore some still buffered/queued UI frames received + * before decryption was enabled */ + if (data[0] == 0x01 && (data[1] & 0x01) == 0) { + l1sap_tx_ciph_req(trx, chan_nr, 1, 0); + } + } + + /* SDCCH, SACCH and FACCH all go to LAPDm */ + msgb_pull(msg, (msg->l2h - msg->data)); + msg->l1h = NULL; + lapdm_phsap_up(&l1sap->oph, le); + + /* don't free, because we forwarded data */ + return 1; +} + +/* TCH received from bts model */ +static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap, + struct ph_tch_param *tch_ind) +{ + struct msgb *msg = l1sap->oph.msg; + struct gsm_time g_time; + struct gsm_lchan *lchan; + uint8_t tn, ss, chan_nr; + uint32_t fn; + + chan_nr = tch_ind->chan_nr; + fn = tch_ind->fn; + tn = L1SAP_CHAN2TS(chan_nr); + if (L1SAP_IS_CHAN_TCHH(chan_nr)) + ss = L1SAP_CHAN2SS_TCHH(chan_nr); + else + ss = 0; + lchan = &trx->ts[tn].lchan[ss]; + + gsm_fn2gsmtime(&g_time, fn); + + DEBUGP(DL1P, "Rx TCH.ind %02u/%02u/%02u chan_nr=%d\n", + g_time.t1, g_time.t2, g_time.t3, chan_nr); + + msgb_pull(msg, sizeof(*l1sap)); + + /* hand msg to RTP code for transmission */ + if (lchan->abis_ip.rtp_socket) + osmo_rtp_send_frame(lchan->abis_ip.rtp_socket, + msg->data, msg->len, 160); + + /* if loopback is enabled, also queue received RTP data */ + if (lchan->loopback) { + struct msgb *tmp; + int count = 0; + + /* make sure the queue doesn't get too long */ + llist_for_each_entry(tmp, &lchan->dl_tch_queue, list) + count++; + while (count >= 1) { + tmp = msgb_dequeue(&lchan->dl_tch_queue); + msgb_free(tmp); + count--; + } + + msgb_enqueue(&lchan->dl_tch_queue, msg); + } + + return 0; +} + +/* RACH received from bts model */ +static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx, + struct osmo_phsap_prim *l1sap, struct ph_rach_ind_param *rach_ind) +{ + struct gsm_bts *bts = trx->bts; + struct gsm_bts_role_bts *btsb = bts->role; + struct lapdm_channel *lc; + + DEBUGP(DL1P, "Rx PH-RA.ind"); + + lc = &trx->ts[0].lchan[4].lapdm_ch; + if (!lc) { + LOGP(DL1P, LOGL_ERROR, "unable to resolve LAPD channel\n"); + return -ENODEV; + } + + /* check for under/overflow / sign */ + if (rach_ind->acc_delay > btsb->max_ta) { + LOGP(DL1P, LOGL_INFO, "ignoring RACH request %u > max_ta(%u)\n", + rach_ind->acc_delay, btsb->max_ta); + return 0; + } + + /* check for packet access */ + if (trx == bts->c0 + && L1SAP_IS_PACKET_RACH(rach_ind->ra)) { + LOGP(DL1P, LOGL_INFO, "RACH for packet access\n"); + pcu_tx_rach_ind(bts, rach_ind->acc_delay << 2, + rach_ind->ra, rach_ind->fn); + + return 0; + } + + LOGP(DL1P, LOGL_INFO, "RACH for RR access (toa=%d, ra=%d)\n", + rach_ind->acc_delay, rach_ind->ra); + lapdm_phsap_up(&l1sap->oph, &lc->lapdm_dcch); + + return 0; +} + +/* any L1 prim received from bts model */ +int l1sap_up(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) +{ + struct msgb *msg = l1sap->oph.msg; + int rc = 0; + + switch (OSMO_PRIM_HDR(&l1sap->oph)) { + case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_INDICATION): + rc = l1sap_mph_info_ind(trx, l1sap, &l1sap->u.info); + break; + case OSMO_PRIM(PRIM_MPH_INFO, PRIM_OP_CONFIRM): + rc = l1sap_mph_info_cnf(trx, l1sap, &l1sap->u.info); + break; + case OSMO_PRIM(PRIM_PH_RTS, PRIM_OP_INDICATION): + rc = l1sap_ph_rts_ind(trx, l1sap, &l1sap->u.data); + break; + case OSMO_PRIM(PRIM_TCH_RTS, PRIM_OP_INDICATION): + rc = l1sap_tch_rts_ind(trx, l1sap, &l1sap->u.tch); + break; + case OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_INDICATION): + to_gsmtap(trx, l1sap); + rc = l1sap_ph_data_ind(trx, l1sap, &l1sap->u.data); + break; + case OSMO_PRIM(PRIM_TCH, PRIM_OP_INDICATION): + rc = l1sap_tch_ind(trx, l1sap, &l1sap->u.tch); + break; + case OSMO_PRIM(PRIM_PH_RACH, PRIM_OP_INDICATION): + to_gsmtap(trx, l1sap); + rc = l1sap_ph_rach_ind(trx, l1sap, &l1sap->u.rach_ind); + break; + default: + LOGP(DL1P, LOGL_NOTICE, "unknown prim %d op %d\n", + l1sap->oph.primitive, l1sap->oph.operation); + break; + } + + /* Special return value '1' means: do not free */ + if (rc != 1 && msg) + msgb_free(msg); + + return rc; +} + +/* any L1 prim sent to bts model */ +static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) +{ + if (OSMO_PRIM_HDR(&l1sap->oph) == + OSMO_PRIM(PRIM_PH_DATA, PRIM_OP_REQUEST)) + to_gsmtap(trx, l1sap); + + return bts_model_l1sap_down(trx, l1sap); +} + +/* pcu (socket interface) sends us a data request primitive */ +int l1sap_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn, + uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len) +{ + struct msgb *msg; + struct osmo_phsap_prim *l1sap; + struct gsm_time g_time; + + gsm_fn2gsmtime(&g_time, fn); + + DEBUGP(DL1P, "TX packet data %02u/%02u/%02u is_ptcch=%d trx=%d ts=%d " + "block_nr=%d, arfcn=%d, len=%d\n", g_time.t1, g_time.t2, + g_time.t3, is_ptcch, ts->trx->nr, ts->nr, block_nr, arfcn, len); + + msg = l1sap_msgb_alloc(len); + l1sap = msgb_l1sap_prim(msg); + osmo_prim_init(&l1sap->oph, SAP_GSM_PH, PRIM_PH_DATA, PRIM_OP_REQUEST, + msg); + l1sap->u.data.chan_nr = 0x08 | ts->nr; + l1sap->u.data.link_id = 0x00; + l1sap->u.data.fn = fn; + msg->l2h = msgb_put(msg, len); + memcpy(msg->l2h, data, len); + + return l1sap_down(ts->trx, l1sap); +} + +/*! \brief call-back function for incoming RTP */ +void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl, + unsigned int rtp_pl_len) +{ + struct gsm_lchan *lchan = rs->priv; + struct msgb *msg, *tmp; + struct osmo_phsap_prim *l1sap; + int count = 0; + + msg = l1sap_msgb_alloc(rtp_pl_len); + if (!msg) + return; + memcpy(msgb_put(msg, rtp_pl_len), rtp_pl, rtp_pl_len); + msgb_pull(msg, sizeof(*l1sap)); + + + /* make sure the queue doesn't get too long */ + llist_for_each_entry(tmp, &lchan->dl_tch_queue, list) + count++; + while (count >= 2) { + tmp = msgb_dequeue(&lchan->dl_tch_queue); + msgb_free(tmp); + count--; + } + + msgb_enqueue(&lchan->dl_tch_queue, msg); +} + +static int l1sap_chan_act_dact_modify(struct gsm_bts_trx *trx, uint8_t chan_nr, + enum osmo_mph_info_type type, uint8_t sacch_only) +{ + struct osmo_phsap_prim l1sap; + + memset(&l1sap, 0, sizeof(l1sap)); + osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO, PRIM_OP_REQUEST, + NULL); + l1sap.u.info.type = type; + l1sap.u.info.u.act_req.chan_nr = chan_nr; + l1sap.u.info.u.act_req.sacch_only = sacch_only; + + return l1sap_down(trx, &l1sap); +} + +int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr) +{ + struct gsm_bts_role_bts *btsb = trx->bts->role; + struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)] + .lchan[l1sap_chan2ss(chan_nr)]; + + LOGP(DL1P, LOGL_INFO, "activating channel chan_nr=%02x trx=%d\n", + chan_nr, trx->nr); + + lchan->sacch_deact = 0; + lchan->s = btsb->radio_link_timeout; + + return l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_ACTIVATE, 0); +} + +int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr) +{ + LOGP(DL1P, LOGL_INFO, "deactivating channel chan_nr=%02x trx=%d\n", + chan_nr, trx->nr); + + return l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_DEACTIVATE, + 0); +} + +int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr) +{ + struct gsm_lchan *lchan = &trx->ts[L1SAP_CHAN2TS(chan_nr)] + .lchan[l1sap_chan2ss(chan_nr)]; + + LOGP(DL1P, LOGL_INFO, "deactivating sacch chan_nr=%02x trx=%d\n", + chan_nr, trx->nr); + + lchan->sacch_deact = 1; + + return l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_DEACTIVATE, + 1); +} + +int l1sap_chan_modify(struct gsm_bts_trx *trx, uint8_t chan_nr) +{ + LOGP(DL1P, LOGL_INFO, "modifying channel chan_nr=%02x trx=%d\n", + chan_nr, trx->nr); + + return l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_MODIFY, 0); +} diff --git a/src/common/logging.c b/src/common/logging.c index 98fd205..f56846e 100644 --- a/src/common/logging.c +++ b/src/common/logging.c @@ -69,8 +69,8 @@ static struct log_info_cat bts_log_info_cat[] = { [DL1C] = { .name = "DL1C", .description = "Layer 1", - .loglevel = LOGL_INFO, - .enabled = 1, + .color = "\033[1;32m", + .enabled = 1, .loglevel = LOGL_NOTICE, }, [DL1P] = { .name = "DL1P", diff --git a/src/common/measurement.c b/src/common/measurement.c index 774962d..ff80a9f 100644 --- a/src/common/measurement.c +++ b/src/common/measurement.c @@ -89,6 +89,11 @@ static int is_meas_complete(enum gsm_phys_chan_config pchan, unsigned int ts, /* receive a L1 uplink measurement from L1 */ int lchan_new_ul_meas(struct gsm_lchan *lchan, struct bts_ul_meas *ulm) { + /* in the GPRS case we are not interested in measurement + * processing. The PCU will take care of it */ + if (lchan->type == GSM_LCHAN_PDTCH) + return 0; + DEBUGP(DMEAS, "%s adding measurement, num_ul_meas=%d\n", gsm_lchan_name(lchan), lchan->meas.num_ul_meas); diff --git a/src/common/pcu_sock.c b/src/common/pcu_sock.c index a90caac..76ecf22 100644 --- a/src/common/pcu_sock.c +++ b/src/common/pcu_sock.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx); @@ -57,10 +57,6 @@ static const char *sapi_string[] = { [PCU_IF_SAPI_PTCCH] = "PTCCH", }; -/* FIXME: common l1if include ? */ -int l1if_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn, - uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len); - static int pcu_sock_send(struct gsm_network *net, struct msgb *msg); /* FIXME: move this to libosmocore */ int osmo_unixsock_listen(struct osmo_fd *bfd, int type, const char *path); @@ -511,7 +507,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type, } ts = &trx->ts[data_req->ts_nr]; is_ptcch = (data_req->sapi == PCU_IF_SAPI_PTCCH); - rc = l1if_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn, + rc = l1sap_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn, data_req->block_nr, data_req->data, data_req->len); break; default: @@ -544,9 +540,9 @@ static int pcu_rx_act_req(struct gsm_bts *bts, return -EINVAL; } if (act_req->activate) - bts_model_rsl_chan_act(lchan, NULL); + l1sap_chan_act(trx, gsm_lchan2chan_nr(lchan)); else - bts_model_rsl_chan_rel(lchan); + l1sap_chan_rel(trx, gsm_lchan2chan_nr(lchan)); return 0; } @@ -650,7 +646,8 @@ static void pcu_sock_close(struct pcu_sock_state *state) ts = &trx->ts[j]; if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED && ts->pchan == GSM_PCHAN_PDCH) - bts_model_rsl_chan_rel(ts->lchan); + l1sap_chan_rel(trx, + gsm_lchan2chan_nr(ts->lchan)); } } diff --git a/src/common/rsl.c b/src/common/rsl.c index 616ae0d..150f686 100644 --- a/src/common/rsl.c +++ b/src/common/rsl.c @@ -41,9 +41,9 @@ #include #include #include -#include #include #include +#include //#define FAKE_CIPH_MODE_COMPL @@ -499,8 +499,9 @@ int rsl_tx_rf_rel_ack(struct gsm_lchan *lchan) } /* 8.4.2 sending CHANnel ACTIVation ACKnowledge */ -int rsl_tx_chan_act_ack(struct gsm_lchan *lchan, struct gsm_time *gtime) +int rsl_tx_chan_act_ack(struct gsm_lchan *lchan) { + struct gsm_time *gtime = get_time(lchan->ts->trx->bts); struct msgb *msg; uint8_t chan_nr = gsm_lchan2chan_nr(lchan); uint8_t ie[2]; @@ -760,14 +761,12 @@ static int rsl_rx_chan_activ(struct msgb *msg) dch->chan_nr, type, lchan->tch_mode); /* actually activate the channel in the BTS */ - return bts_model_rsl_chan_act(msg->lchan, &tp); + return l1sap_chan_act(lchan->ts->trx, dch->chan_nr); } /* 8.4.14 RF CHANnel RELease is received */ -static int rsl_rx_rf_chan_rel(struct gsm_lchan *lchan) +static int rsl_rx_rf_chan_rel(struct gsm_lchan *lchan, uint8_t chan_nr) { - int rc; - if (lchan->abis_ip.rtp_socket) { rsl_tx_ipac_dlcx_ind(lchan, RSL_ERR_NORMAL_UNSPEC); osmo_rtp_socket_free(lchan->abis_ip.rtp_socket); @@ -775,11 +774,11 @@ static int rsl_rx_rf_chan_rel(struct gsm_lchan *lchan) msgb_queue_flush(&lchan->dl_tch_queue); } - rc = bts_model_rsl_chan_rel(lchan); + l1sap_chan_rel(lchan->ts->trx, chan_nr); lapdm_channel_exit(&lchan->lapdm_ch); - return rc; + return 0; } #ifdef FAKE_CIPH_MODE_COMPL @@ -962,10 +961,10 @@ static int rsl_tx_mode_modif_ack(struct gsm_lchan *lchan) /* 8.4.9 MODE MODIFY */ static int rsl_rx_mode_modif(struct msgb *msg) { + struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); struct gsm_lchan *lchan = msg->lchan; struct rsl_ie_chan_mode *cm; struct tlv_parsed tp; - int rc; rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); @@ -1005,12 +1004,12 @@ static int rsl_rx_mode_modif(struct msgb *msg) /* 9.3.53 MultiRate Control */ /* 9.3.54 Supported Codec Types */ - rc = bts_model_rsl_mode_modify(msg->lchan); + l1sap_chan_modify(lchan->ts->trx, dch->chan_nr); /* FIXME: delay this until L1 says OK? */ - rsl_tx_mode_modif_ack(msg->lchan); + rsl_tx_mode_modif_ack(lchan); - return rc; + return 0; } /* 8.4.20 SACCH INFO MODify */ @@ -1314,7 +1313,7 @@ static int rsl_rx_ipac_XXcx(struct msgb *msg) OSMO_RTP_P_JITBUF, btsb->rtp_jitter_buf_ms); lchan->abis_ip.rtp_socket->priv = lchan; - lchan->abis_ip.rtp_socket->rx_cb = &bts_model_rtp_rx_cb; + lchan->abis_ip.rtp_socket->rx_cb = &l1sap_rtp_rx_cb; if (connect_ip && connect_port) { /* if CRCX specifies a remote IP, we can bind() @@ -1646,13 +1645,13 @@ static int rsl_rx_dchan(struct gsm_bts_trx *trx, struct msgb *msg) ret = rsl_rx_chan_activ(msg); break; case RSL_MT_RF_CHAN_REL: - ret = rsl_rx_rf_chan_rel(msg->lchan); + ret = rsl_rx_rf_chan_rel(msg->lchan, dch->chan_nr); break; case RSL_MT_SACCH_INFO_MODIFY: ret = rsl_rx_sacch_inf_mod(msg); break; case RSL_MT_DEACTIVATE_SACCH: - ret = bts_model_rsl_deact_sacch(msg->lchan); + ret = l1sap_chan_deact_sacch(trx, dch->chan_nr); break; case RSL_MT_ENCR_CMD: ret = rsl_rx_encr_cmd(msg); diff --git a/src/common/vty.c b/src/common/vty.c index 5eddc8d..4daa92c 100644 --- a/src/common/vty.c +++ b/src/common/vty.c @@ -22,12 +22,15 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include @@ -42,7 +45,7 @@ #include #include #include - +#include enum node_type bts_vty_go_parent(struct vty *vty) { @@ -171,10 +174,38 @@ DEFUN(cfg_bts_trx, cfg_bts_trx_cmd, return CMD_SUCCESS; } +/* FIXME: move to libosmocore ? */ +static char buf_casecnvt[256]; +char *osmo_str_tolower(const char *in) +{ + int len, i; + + if (!in) + return NULL; + + len = strlen(in); + if (len > sizeof(buf_casecnvt)) + len = sizeof(buf_casecnvt); + + for (i = 0; i < len; i++) { + buf_casecnvt[i] = tolower(in[i]); + if (in[i] == '\0') + break; + } + if (i < sizeof(buf_casecnvt)) + buf_casecnvt[i] = '\0'; + + /* just to make sure we're always zero-terminated */ + buf_casecnvt[sizeof(buf_casecnvt)-1] = '\0'; + + return buf_casecnvt; +} + static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) { struct gsm_bts_role_bts *btsb = bts_role_bts(bts); struct gsm_bts_trx *trx; + int i; vty_out(vty, "bts %u%s", bts->nr, VTY_NEWLINE); if (bts->description) @@ -190,6 +221,17 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " paging lifetime %u%s", paging_get_lifetime(btsb->paging_state), VTY_NEWLINE); + for (i = 0; i < 32; i++) { + if (gsmtap_sapi_mask & (1 << i)) { + const char *name = get_value_string(gsmtap_sapi_names, i); + vty_out(vty, " gsmtap-sapi %s%s", osmo_str_tolower(name), VTY_NEWLINE); + } + } + if (gsmtap_sapi_acch) { + const char *name = get_value_string(gsmtap_sapi_names, GSMTAP_CHANNEL_ACCH); + vty_out(vty, " gsmtap-sapi %s%s", osmo_str_tolower(name), VTY_NEWLINE); + } + bts_model_config_write_bts(vty, bts); llist_for_each_entry(trx, &bts->trx_list, list) { @@ -475,6 +517,36 @@ static struct gsm_lchan *resolve_lchan(struct gsm_network *net, "logical channel commands\n" \ "logical channel number\n" +DEFUN(cfg_trx_gsmtap_sapi, cfg_trx_gsmtap_sapi_cmd, + "HIDDEN", "HIDDEN") +{ + int sapi; + + sapi = get_string_value(gsmtap_sapi_names, argv[0]); + + if (sapi == GSMTAP_CHANNEL_ACCH) + gsmtap_sapi_acch = 1; + else + gsmtap_sapi_mask |= (1 << sapi); + + return CMD_SUCCESS; +} + +DEFUN(cfg_trx_no_gsmtap_sapi, cfg_trx_no_gsmtap_sapi_cmd, + "HIDDEN", "HIDDEN") +{ + int sapi; + + sapi = get_string_value(gsmtap_sapi_names, argv[0]); + + if (sapi == GSMTAP_CHANNEL_ACCH) + gsmtap_sapi_acch = 0; + else + gsmtap_sapi_mask &= ~(1 << sapi); + + return CMD_SUCCESS; +} + DEFUN(bts_t_t_l_jitter_buf, bts_t_t_l_jitter_buf_cmd, "bts <0-0> trx <0-0> ts <0-7> lchan <0-1> rtp jitter-buffer <0-10000>", @@ -501,8 +573,58 @@ DEFUN(bts_t_t_l_jitter_buf, return CMD_SUCCESS; } -int bts_vty_init(const struct log_info *cat) +DEFUN(bts_t_t_l_loopback, + bts_t_t_l_loopback_cmd, + "bts <0-0> trx <0-0> ts <0-7> lchan <0-1> loopback", + BTS_T_T_L_STR "Set loopback\n") { + struct gsm_network *net = gsmnet_from_vty(vty); + struct gsm_lchan *lchan; + + lchan = resolve_lchan(net, argv, 0); + if (!lchan) { + vty_out(vty, "%% can't find BTS%s", VTY_NEWLINE); + return CMD_WARNING; + } + lchan->loopback = 1; + + return CMD_SUCCESS; +} + +DEFUN(no_bts_t_t_l_loopback, + no_bts_t_t_l_loopback_cmd, + "no bts <0-0> trx <0-0> ts <0-7> lchan <0-1> loopback", + NO_STR BTS_T_T_L_STR "Set loopback\n") +{ + struct gsm_network *net = gsmnet_from_vty(vty); + struct gsm_lchan *lchan; + + lchan = resolve_lchan(net, argv, 0); + if (!lchan) { + vty_out(vty, "%% can't find BTS%s", VTY_NEWLINE); + return CMD_WARNING; + } + lchan->loopback = 0; + + return CMD_SUCCESS; +} + +int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat) +{ + cfg_trx_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names, + "gsmtap-sapi (", + "|",")", VTY_DO_LOWER); + cfg_trx_gsmtap_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names, + "GSMTAP SAPI\n", + "\n", "", 0); + + cfg_trx_no_gsmtap_sapi_cmd.string = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names, + "no gsmtap-sapi (", + "|",")", VTY_DO_LOWER); + cfg_trx_no_gsmtap_sapi_cmd.doc = vty_cmd_string_from_valstr(bts, gsmtap_sapi_names, + NO_STR "GSMTAP SAPI\n", + "\n", "", 0); + install_element_ve(&show_bts_cmd); logging_vty_add_cmds(cat); @@ -520,12 +642,17 @@ int bts_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_paging_queue_size_cmd); install_element(BTS_NODE, &cfg_bts_paging_lifetime_cmd); + install_element(BTS_NODE, &cfg_trx_gsmtap_sapi_cmd); + install_element(BTS_NODE, &cfg_trx_no_gsmtap_sapi_cmd); + /* add and link to TRX config node */ install_element(BTS_NODE, &cfg_bts_trx_cmd); install_node(&trx_node, config_write_dummy); install_default(TRX_NODE); install_element(ENABLE_NODE, &bts_t_t_l_jitter_buf_cmd); + install_element(ENABLE_NODE, &bts_t_t_l_loopback_cmd); + install_element(ENABLE_NODE, &no_bts_t_t_l_loopback_cmd); return 0; } diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c index 16f1523..6efb9d6 100644 --- a/src/osmo-bts-sysmo/l1_if.c +++ b/src/osmo-bts-sysmo/l1_if.c @@ -1303,3 +1303,9 @@ int l1if_close(struct femtol1_hdl *fl1h) l1if_transport_close(MQ_SYS_WRITE, fl1h); return 0; } + +/* temporary stub to make this patch compile */ +int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) +{ + return -ENOTSUP; +} diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 595a6eb..7e7f761 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -255,7 +255,7 @@ int main(int argc, char **argv) bts_log_init(NULL); vty_init(&bts_vty_info); - bts_vty_init(&bts_log_info); + bts_vty_init(bts, &bts_log_info); handle_options(argc, argv); diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c index faef025..aeddad7 100644 --- a/src/osmo-bts-sysmo/oml.c +++ b/src/osmo-bts-sysmo/oml.c @@ -868,10 +868,8 @@ static int sapi_activate_cb(struct gsm_lchan *lchan, int status) if (lchan->state != LCHAN_S_ACT_REQ) return 0; - struct gsm_time *time; lchan_set_state(lchan, LCHAN_S_ACTIVE); - time = bts_model_get_time(lchan->ts->trx->bts); - rsl_tx_chan_act_ack(lchan, time); + rsl_tx_chan_act_ack(lchan); /* set the initial ciphering parameters for both directions */ l1if_set_ciphering(fl1h, lchan, 0); diff --git a/src/osmo-bts-sysmo/sysmobts_vty.c b/src/osmo-bts-sysmo/sysmobts_vty.c index 5bc948e..61deda4 100644 --- a/src/osmo-bts-sysmo/sysmobts_vty.c +++ b/src/osmo-bts-sysmo/sysmobts_vty.c @@ -444,33 +444,6 @@ void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " auto-band%s", VTY_NEWLINE); } -/* FIXME: move to libosmocore ? */ -static char buf_casecnvt[256]; -char *osmo_str_tolower(const char *in) -{ - int len, i; - - if (!in) - return NULL; - - len = strlen(in); - if (len > sizeof(buf_casecnvt)) - len = sizeof(buf_casecnvt); - - for (i = 0; i < len; i++) { - buf_casecnvt[i] = tolower(in[i]); - if (in[i] == '\0') - break; - } - if (i < sizeof(buf_casecnvt)) - buf_casecnvt[i] = '\0'; - - /* just to make sure we're always zero-terminated */ - buf_casecnvt[sizeof(buf_casecnvt)-1] = '\0'; - - return buf_casecnvt; -} - void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx) { struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); diff --git a/tests/stubs.c b/tests/stubs.c index c46bb4a..c0089c5 100644 --- a/tests/stubs.c +++ b/tests/stubs.c @@ -46,3 +46,6 @@ int l1if_pdch_req(struct gsm_bts_trx_ts *ts, int is_ptcch, uint32_t fn, uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx) { return 0; } + +int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) +{ return 0; } -- 1.7.3.4 --------------010307000202050200040407--