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
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 <osmocom/core/crc8gen.h>
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 <stdint.h>
#include <osmocom/core/msgb.h>
@@ -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 <stdint.h>
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 <errno.h>
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
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 <kat.obsc(a)gmail.com>
+ * 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 <kat.obsc(a)gmail.com>
+ * 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 <unistd.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <osmocom/core/talloc.h>
+
+/*! \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 <osmocom/core/ringbuffer.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/loggingrb.h>
+
+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 <kat.obsc(a)gmail.com>
+ * 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 <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+#include <osmocom/core/ringbuffer.h>
+
+/* 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 <osmocom/core/talloc.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/utils.h>
-
-//#include <openbsc/vty.h>
+#include <osmocom/core/ringbuffer.h>
+#include <osmocom/core/loggingrb.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/buffer.h>
@@ -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 <zecke(a)selfish.org>
+ * (C) 2012-2013 by Katerina Barone-Adesi <kat.obsc(a)gmail.com>
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <assert.h>
+
+#include <osmocom/core/logging.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/ringb.h>
+#include <osmocom/vty/logging_rbvty.h>
+
+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 <kat.obsc(a)gmail.com>
+ * 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 <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#include <osmocom/core/ringbuffer.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/logging.h>
+
+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
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 <kat.obsc(a)gmail.com>
+ * 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 <kat.obsc(a)gmail.com>
+ * 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 <unistd.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <osmocom/core/talloc.h>
+
+/*! \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 <osmocom/core/ringbuffer.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/loggingrb.h>
+
+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 <kat.obsc(a)gmail.com>
+ * 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 <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+#include <osmocom/core/ringbuffer.h>
+
+/* 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 <osmocom/core/talloc.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/utils.h>
-
-//#include <openbsc/vty.h>
+#include <osmocom/core/ringbuffer.h>
+#include <osmocom/core/loggingrb.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/buffer.h>
@@ -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 <zecke(a)selfish.org>
+ * (C) 2012-2013 by Katerina Barone-Adesi <kat.obsc(a)gmail.com>
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <assert.h>
+
+#include <osmocom/core/logging.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/ringb.h>
+#include <osmocom/vty/logging_rbvty.h>
+
+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 <kat.obsc(a)gmail.com>
+ * 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 <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#include <osmocom/core/ringbuffer.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/logging.h>
+
+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
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.
From: Pablo Neira Ayuso <pablo(a)gnumonks.org>
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
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 <laforge(a)gnumonks.org> http://laforge.gnumonks.org/
============================================================================
"Privacy in residential applications is a desirable marketing option."
(ETSI EN 300 175-7 Ch. A6)