From holger at freyther.de Thu Apr 17 21:29:45 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 17 Apr 2014 23:29:45 +0200 Subject: [PATCH 4/9] Add support for AMR frames to MNCC/RTP interface In-Reply-To: <20140320214603.GA11963@xiaoyu.lan> References: <1392793078-30854-1-git-send-email-jolly@eversberg.eu> <1392793078-30854-4-git-send-email-jolly@eversberg.eu> <20140320214603.GA11963@xiaoyu.lan> Message-ID: <20140417212945.GB31314@xiaoyu.lan> On Thu, Mar 20, 2014 at 10:46:03PM +0100, Holger Hans Peter Freyther wrote: dear andreas, do you intend to finish your patches? happy easter holger From andreas at eversberg.eu Fri Apr 18 10:07:51 2014 From: andreas at eversberg.eu (Andreas Eversberg) Date: Fri, 18 Apr 2014 12:07:51 +0200 Subject: [PATCH 4/9] Add support for AMR frames to MNCC/RTP interface In-Reply-To: <20140417212945.GB31314@xiaoyu.lan> References: <1392793078-30854-1-git-send-email-jolly@eversberg.eu> <1392793078-30854-4-git-send-email-jolly@eversberg.eu> <20140320214603.GA11963@xiaoyu.lan> <20140417212945.GB31314@xiaoyu.lan> Message-ID: <5350F977.6060201@eversberg.eu> Holger Hans Peter Freyther wrote: > On Thu, Mar 20, 2014 at 10:46:03PM +0100, Holger Hans Peter Freyther wrote: > > dear andreas, > > do you intend to finish your patches? > > happy easter > holger dear holger, i had that patch done already. (see attachment) happy easter andreas From holger at freyther.de Sun Apr 20 14:30:20 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 20 Apr 2014 16:30:20 +0200 Subject: [PATCH 4/9] Add support for AMR frames to MNCC/RTP interface In-Reply-To: <5350F977.6060201@eversberg.eu> References: <1392793078-30854-1-git-send-email-jolly@eversberg.eu> <1392793078-30854-4-git-send-email-jolly@eversberg.eu> <20140320214603.GA11963@xiaoyu.lan> <20140417212945.GB31314@xiaoyu.lan> <5350F977.6060201@eversberg.eu> Message-ID: <20140420143020.GD14607@xiaoyu.lan> On Fri, Apr 18, 2014 at 12:07:51PM +0200, Andreas Eversberg wrote: hi, > i had that patch done already. (see attachment) what was the message id? I didn't see it. > happy easter happy easter to you too. > + if (rtph->payload_type == RTP_PT_AMR) { > + new_msg = msgb_alloc(sizeof(struct gsm_data_frame) + 1 > + + payload_len, "GSM-DATA"); > + } else { > + new_msg = msgb_alloc(sizeof(struct gsm_data_frame) > + + payload_len, "GSM-DATA"); > + } I think the coding style asks us to ommit the {} here. Maybe use different strings too in case we search for a memory leak? > @@ -305,7 +324,13 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame) > rtph->timestamp = htonl(rs->transmit.timestamp); > rs->transmit.timestamp += duration; > rtph->ssrc = htonl(rs->transmit.ssrc); > - memcpy(msg->data + sizeof(struct rtp_hdr), frame->data, payload_len); > + if (frame->msg_type == GSM_TCH_FRAME_AMR) { > + memcpy(msg->data + sizeof(struct rtp_hdr), frame->data + 1, > + payload_len); > + } else { > + memcpy(msg->data + sizeof(struct rtp_hdr), frame->data, > + payload_len); > + } This lacks input validation. The code needs to check that the data we read is within the bounds of the msgb and the data we write is within the bounds too. From holger at freyther.de Tue Apr 29 06:52:19 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 29 Apr 2014 08:52:19 +0200 Subject: [PATCH 4/9] Add support for AMR frames to MNCC/RTP interface In-Reply-To: <20140420143020.GD14607@xiaoyu.lan> References: <1392793078-30854-1-git-send-email-jolly@eversberg.eu> <1392793078-30854-4-git-send-email-jolly@eversberg.eu> <20140320214603.GA11963@xiaoyu.lan> <20140417212945.GB31314@xiaoyu.lan> <5350F977.6060201@eversberg.eu> <20140420143020.GD14607@xiaoyu.lan> Message-ID: <20140429065219.GA3544@xiaoyu.lan> On Sun, Apr 20, 2014 at 04:30:20PM +0200, Holger Hans Peter Freyther wrote: ping? > > i had that patch done already. (see attachment) > > what was the message id? I didn't see it. Could you please answer this one? > This lacks input validation. The code needs to check that the data > we read is within the bounds of the msgb and the data we write is within > the bounds too. Do you understand the severity? It is this kind of issue that OpenSSL had with hearbleed. In this case our length is only a uint8_t and our msgb is most likely over-allocated so we might be lucky that nothing else will be leaked from the application. holger From holger at freyther.de Thu Apr 17 21:29:08 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 17 Apr 2014 23:29:08 +0200 Subject: [PATCH 6/9] Add traffic forwarding via RTP to remote application In-Reply-To: <20140320214938.GB11963@xiaoyu.lan> References: <1392793078-30854-1-git-send-email-jolly@eversberg.eu> <1392793078-30854-6-git-send-email-jolly@eversberg.eu> <20140309161952.GC6167@xiaoyu.lan> <531EAD2D.6000702@eversberg.eu> <20140314064042.GJ31238@xiaoyu.lan> <53242052.1070401@eversberg.eu> <20140316071240.GD27189@xiaoyu.lan> <53269940.7050101@eversberg.eu> <20140320214938.GB11963@xiaoyu.lan> Message-ID: <20140417212908.GA31314@xiaoyu.lan> On Thu, Mar 20, 2014 at 10:49:38PM +0100, Holger Hans Peter Freyther wrote: > is that more clear? I currently can't merge this patch as it > breaks the NAT compilation. ping? Do you intend to finish your patches? From andreas at eversberg.eu Fri Apr 18 10:22:31 2014 From: andreas at eversberg.eu (Andreas Eversberg) Date: Fri, 18 Apr 2014 12:22:31 +0200 Subject: [PATCH 6/9] Add traffic forwarding via RTP to remote application In-Reply-To: <20140417212908.GA31314@xiaoyu.lan> References: <1392793078-30854-1-git-send-email-jolly@eversberg.eu> <1392793078-30854-6-git-send-email-jolly@eversberg.eu> <20140309161952.GC6167@xiaoyu.lan> <531EAD2D.6000702@eversberg.eu> <20140314064042.GJ31238@xiaoyu.lan> <53242052.1070401@eversberg.eu> <20140316071240.GD27189@xiaoyu.lan> <53269940.7050101@eversberg.eu> <20140320214938.GB11963@xiaoyu.lan> <20140417212908.GA31314@xiaoyu.lan> Message-ID: <5350FCE7.9030401@eversberg.eu> Holger Hans Peter Freyther wrote: > On Thu, Mar 20, 2014 at 10:49:38PM +0100, Holger Hans Peter Freyther wrote: > >> is that more clear? I currently can't merge this patch as it >> breaks the NAT compilation. > ping? Do you intend to finish your patches? this patch is not yet tested. it uses signal to remove dependency between libmsc and libbsc. any comments? From jolly at eversberg.eu Fri Apr 18 09:03:50 2014 From: jolly at eversberg.eu (Andreas Eversberg) Date: Fri, 18 Apr 2014 11:03:50 +0200 Subject: [PATCH] Move rtp_proxy.c from libtrau to libmsc Message-ID: In order to free RTP socket when lchan_free() or lchan_reset() is called, a signal is used between libbsc and rtp_proxy. --- openbsc/include/openbsc/signal.h | 1 + openbsc/src/libbsc/chan_alloc.c | 14 +- openbsc/src/libmsc/Makefile.am | 3 +- openbsc/src/libmsc/rtp_proxy.c | 847 +++++++++++++++++++++++++++++++++++++++ openbsc/src/libtrau/Makefile.am | 2 +- openbsc/src/libtrau/rtp_proxy.c | 816 ------------------------------------- 6 files changed, 863 insertions(+), 820 deletions(-) create mode 100644 openbsc/src/libmsc/rtp_proxy.c delete mode 100644 openbsc/src/libtrau/rtp_proxy.c diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 39319f1..4e7a71a 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -99,6 +99,7 @@ enum signal_lchan { S_LCHAN_HANDOVER_FAIL, /* 04.08 Handover Failed */ S_LCHAN_HANDOVER_DETECT, /* 08.58 Handover Detect */ S_LCHAN_MEAS_REP, /* 08.58 Measurement Report */ + S_LCHAN_RTP_SOCKET_FREE, }; /* SS_CHALLOC signals */ diff --git a/openbsc/src/libbsc/chan_alloc.c b/openbsc/src/libbsc/chan_alloc.c index 9b74329..7bf6477 100644 --- a/openbsc/src/libbsc/chan_alloc.c +++ b/openbsc/src/libbsc/chan_alloc.c @@ -311,9 +311,13 @@ void lchan_free(struct gsm_lchan *lchan) } if (lchan->abis_ip.rtp_socket) { + struct lchan_signal_data sig; + LOGP(DRLL, LOGL_ERROR, "%s RTP Proxy Socket remained open.\n", gsm_lchan_name(lchan)); - rtp_socket_free(lchan->abis_ip.rtp_socket); + sig.lchan = lchan; + sig.mr = NULL; + osmo_signal_dispatch(SS_LCHAN, S_LCHAN_RTP_SOCKET_FREE, &sig); lchan->abis_ip.rtp_socket = NULL; } @@ -369,7 +373,13 @@ void lchan_reset(struct gsm_lchan *lchan) lchan->state = LCHAN_S_NONE; if (lchan->abis_ip.rtp_socket) { - rtp_socket_free(lchan->abis_ip.rtp_socket); + struct lchan_signal_data sig; + + LOGP(DRLL, LOGL_ERROR, "%s RTP Proxy Socket remained open.\n", + gsm_lchan_name(lchan)); + sig.lchan = lchan; + sig.mr = NULL; + osmo_signal_dispatch(SS_LCHAN, S_LCHAN_RTP_SOCKET_FREE, &sig); lchan->abis_ip.rtp_socket = NULL; } } diff --git a/openbsc/src/libmsc/Makefile.am b/openbsc/src/libmsc/Makefile.am index 24db2c2..4d44a62 100644 --- a/openbsc/src/libmsc/Makefile.am +++ b/openbsc/src/libmsc/Makefile.am @@ -17,7 +17,8 @@ libmsc_a_SOURCES = auth.c \ ussd.c \ vty_interface_layer3.c \ transaction.c \ - osmo_msc.c ctrl_commands.c + osmo_msc.c ctrl_commands.c \ + rtp_proxy.c if BUILD_SMPP noinst_HEADERS = smpp_smsc.h diff --git a/openbsc/src/libmsc/rtp_proxy.c b/openbsc/src/libmsc/rtp_proxy.c new file mode 100644 index 0000000..a950a72 --- /dev/null +++ b/openbsc/src/libmsc/rtp_proxy.c @@ -0,0 +1,847 @@ +/* RTP proxy handling for ip.access nanoBTS */ + +/* (C) 2009-2013 by Harald Welte + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include /* gettimeofday() */ +#include /* get..() */ +#include /* clock() */ +#include /* uname() */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* attempt to determine byte order */ +#include +#include + +#ifndef __BYTE_ORDER +# ifdef __APPLE__ +# define __BYTE_ORDER __DARWIN_BYTE_ORDER +# define __LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN +# define __BIG_ENDIAN __DARWIN_BIG_ENDIAN +# else +# error "__BYTE_ORDER should be defined by someone" +# endif +#endif + +static LLIST_HEAD(rtp_sockets); + +/* should we mangle the CNAME inside SDES of RTCP packets? We disable + * this by default, as it seems to be not needed */ +static int mangle_rtcp_cname = 0; + +enum rtp_bfd_priv { + RTP_PRIV_NONE, + RTP_PRIV_RTP, + RTP_PRIV_RTCP +}; + +#define RTP_ALLOC_SIZE 1500 + +/* according to RFC 1889 */ +struct rtcp_hdr { + uint8_t byte0; + uint8_t type; + uint16_t length; +} __attribute__((packed)); + +#define RTCP_TYPE_SDES 202 + +#define RTCP_IE_CNAME 1 + +/* according to RFC 3550 */ +struct rtp_hdr { +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t csrc_count:4, + extension:1, + padding:1, + version:2; + uint8_t payload_type:7, + marker:1; +#elif __BYTE_ORDER == __BIG_ENDIAN + uint8_t version:2, + padding:1, + extension:1, + csrc_count:4; + uint8_t marker:1, + payload_type:7; +#endif + uint16_t sequence; + uint32_t timestamp; + uint32_t ssrc; +} __attribute__((packed)); + +struct rtp_x_hdr { + uint16_t by_profile; + uint16_t length; +} __attribute__((packed)); + +#define RTP_VERSION 2 + +/* decode an rtp frame and create a new buffer with payload */ +static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data) +{ + struct msgb *new_msg; + struct gsm_data_frame *frame; + struct rtp_hdr *rtph = (struct rtp_hdr *)msg->data; + struct rtp_x_hdr *rtpxh; + uint8_t *payload; + int payload_len; + int msg_type; + int x_len; + + if (msg->len < 12) { + DEBUGPC(DLMUX, "received RTP frame too short (len = %d)\n", + msg->len); + return -EINVAL; + } + if (rtph->version != RTP_VERSION) { + DEBUGPC(DLMUX, "received RTP version %d not supported.\n", + rtph->version); + return -EINVAL; + } + payload = msg->data + sizeof(struct rtp_hdr) + (rtph->csrc_count << 2); + payload_len = msg->len - sizeof(struct rtp_hdr) - (rtph->csrc_count << 2); + if (payload_len < 0) { + DEBUGPC(DLMUX, "received RTP frame too short (len = %d, " + "csrc count = %d)\n", msg->len, rtph->csrc_count); + return -EINVAL; + } + if (rtph->extension) { + if (payload_len < sizeof(struct rtp_x_hdr)) { + DEBUGPC(DLMUX, "received RTP frame too short for " + "extension header\n"); + return -EINVAL; + } + rtpxh = (struct rtp_x_hdr *)payload; + x_len = ntohs(rtpxh->length) * 4 + sizeof(struct rtp_x_hdr); + payload += x_len; + payload_len -= x_len; + if (payload_len < 0) { + DEBUGPC(DLMUX, "received RTP frame too short, " + "extension header exceeds frame length\n"); + return -EINVAL; + } + } + if (rtph->padding) { + if (payload_len < 1) { + DEBUGPC(DLMUX, "received RTP frame too short for " + "padding length\n"); + return -EINVAL; + } + payload_len -= payload[payload_len - 1]; + if (payload_len < 0) { + DEBUGPC(DLMUX, "received RTP frame with padding " + "greater than payload\n"); + return -EINVAL; + } + } + + switch (rtph->payload_type) { + case RTP_PT_GSM_FULL: + msg_type = GSM_TCHF_FRAME; + if (payload_len != RTP_LEN_GSM_FULL) { + DEBUGPC(DLMUX, "received RTP full rate frame with " + "payload length != %d (len = %d)\n", + RTP_LEN_GSM_FULL, payload_len); + return -EINVAL; + } + break; + case RTP_PT_GSM_EFR: + msg_type = GSM_TCHF_FRAME_EFR; + if (payload_len != RTP_LEN_GSM_EFR) { + DEBUGPC(DLMUX, "received RTP extended full rate frame " + "with payload length != %d (len = %d)\n", + RTP_LEN_GSM_EFR, payload_len); + return -EINVAL; + } + break; + case RTP_PT_GSM_HALF: + msg_type = GSM_TCHH_FRAME; + if (payload_len != RTP_LEN_GSM_HALF) { + DEBUGPC(DLMUX, "received RTP half rate frame with " + "payload length != %d (len = %d)\n", + RTP_LEN_GSM_HALF, payload_len); + return -EINVAL; + } + break; + case RTP_PT_AMR: + break; + default: + DEBUGPC(DLMUX, "received RTP frame with unknown payload " + "type %d\n", rtph->payload_type); + return -EINVAL; + } + + if (rtph->payload_type == RTP_PT_AMR) { + new_msg = msgb_alloc(sizeof(struct gsm_data_frame) + 1 + + payload_len, "GSM-DATA"); + } else { + new_msg = msgb_alloc(sizeof(struct gsm_data_frame) + + payload_len, "GSM-DATA"); + } + if (!new_msg) + return -ENOMEM; + frame = (struct gsm_data_frame *)(new_msg->data); + frame->msg_type = msg_type; + frame->callref = callref; + if (rtph->payload_type == RTP_PT_AMR) { + frame->data[0] = payload_len; + msgb_put(new_msg, sizeof(struct gsm_data_frame) + 1 + + payload_len); + memcpy(frame->data + 1, payload, payload_len); + } else { + msgb_put(new_msg, sizeof(struct gsm_data_frame) + payload_len); + memcpy(frame->data, payload, payload_len); + } + + *data = new_msg; + return 0; +} + +/* "to - from" */ +static void tv_difference(struct timeval *diff, const struct timeval *from, + const struct timeval *__to) +{ + struct timeval _to = *__to, *to = &_to; + + if (to->tv_usec < from->tv_usec) { + to->tv_sec -= 1; + to->tv_usec += 1000000; + } + + diff->tv_usec = to->tv_usec - from->tv_usec; + diff->tv_sec = to->tv_sec - from->tv_sec; +} + +/*! \brief encode and send a rtp frame + * \param[in] rs RTP socket through which we shall send + * \param[in] frame GSM RTP frame to be sent + */ +int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame) +{ + struct rtp_sub_socket *rss = &rs->rtp; + struct msgb *msg; + struct rtp_hdr *rtph; + int payload_type; + int payload_len; + int duration; /* in samples */ + int is_bfi = 0; + + if (rs->tx_action != RTP_SEND_DOWNSTREAM) { + /* initialize sequences */ + rs->tx_action = RTP_SEND_DOWNSTREAM; + rs->transmit.ssrc = rand(); + rs->transmit.sequence = random(); + rs->transmit.timestamp = random(); + } + + switch (frame->msg_type) { + case GSM_TCHF_FRAME: + payload_type = RTP_PT_GSM_FULL; + payload_len = RTP_LEN_GSM_FULL; + duration = RTP_GSM_DURATION; + break; + case GSM_TCHF_FRAME_EFR: + payload_type = RTP_PT_GSM_EFR; + payload_len = RTP_LEN_GSM_EFR; + duration = RTP_GSM_DURATION; + break; + case GSM_TCHH_FRAME: + payload_type = RTP_PT_GSM_HALF; + payload_len = RTP_LEN_GSM_HALF; + duration = RTP_GSM_DURATION; + break; + case GSM_TCH_FRAME_AMR: + payload_type = RTP_PT_AMR; + payload_len = frame->data[0]; + duration = RTP_GSM_DURATION; + break; + case GSM_BAD_FRAME: + payload_type = 0; + payload_len = 0; + duration = RTP_GSM_DURATION; + is_bfi = 1; + break; + default: + DEBUGPC(DLMUX, "unsupported message type %d\n", + frame->msg_type); + return -EINVAL; + } + + { + struct timeval tv, tv_diff; + long int usec_diff, frame_diff; + + gettimeofday(&tv, NULL); + tv_difference(&tv_diff, &rs->transmit.last_tv, &tv); + rs->transmit.last_tv = tv; + + usec_diff = tv_diff.tv_sec * 1000000 + tv_diff.tv_usec; + frame_diff = (usec_diff / 20000); + + if (abs(frame_diff) > 1) { + long int frame_diff_excess = frame_diff - 1; + + LOGP(DLMUX, LOGL_NOTICE, + "Correcting frame difference of %ld frames\n", frame_diff_excess); + rs->transmit.sequence += frame_diff_excess; + rs->transmit.timestamp += frame_diff_excess * duration; + } + } + + if (is_bfi) { + /* In case of a bad frame, just count and drop packt. */ + rs->transmit.timestamp += duration; + rs->transmit.sequence++; + return 0; + } + + msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len, "RTP-GSM-FULL"); + if (!msg) + return -ENOMEM; + rtph = (struct rtp_hdr *)msg->data; + rtph->version = RTP_VERSION; + rtph->padding = 0; + rtph->extension = 0; + rtph->csrc_count = 0; + rtph->marker = 0; + rtph->payload_type = payload_type; + rtph->sequence = htons(rs->transmit.sequence++); + rtph->timestamp = htonl(rs->transmit.timestamp); + rs->transmit.timestamp += duration; + rtph->ssrc = htonl(rs->transmit.ssrc); + if (frame->msg_type == GSM_TCH_FRAME_AMR) { + memcpy(msg->data + sizeof(struct rtp_hdr), frame->data + 1, + payload_len); + } else { + memcpy(msg->data + sizeof(struct rtp_hdr), frame->data, + payload_len); + } + msgb_put(msg, sizeof(struct rtp_hdr) + payload_len); + msgb_enqueue(&rss->tx_queue, msg); + rss->bfd.when |= BSC_FD_WRITE; + + return 0; +} + +/* iterate over all chunks in one RTCP message, look for CNAME IEs and + * replace all of those with 'new_cname' */ +static int rtcp_sdes_cname_mangle(struct msgb *msg, struct rtcp_hdr *rh, + uint16_t *rtcp_len, const char *new_cname) +{ + uint8_t *rtcp_end; + uint8_t *cur = (uint8_t *) rh; + uint8_t tag, len = 0; + + rtcp_end = cur + *rtcp_len; + /* move cur to end of RTP header */ + cur += sizeof(*rh); + + /* iterate over Chunks */ + while (cur+4 < rtcp_end) { + /* skip four bytes SSRC/CSRC */ + cur += 4; + + /* iterate over IE's inside the chunk */ + while (cur+1 < rtcp_end) { + tag = *cur++; + if (tag == 0) { + /* end of chunk, skip additional zero */ + while (*cur++ == 0) { } + break; + } + len = *cur++; + + if (tag == RTCP_IE_CNAME) { + /* we've found the CNAME, lets mangle it */ + if (len < strlen(new_cname)) { + /* we need to make more space */ + int increase = strlen(new_cname) - len; + + msgb_push(msg, increase); + memmove(cur+len+increase, cur+len, + rtcp_end - (cur+len)); + /* FIXME: we have to respect RTCP + * padding/alignment rules! */ + len += increase; + *(cur-1) += increase; + rtcp_end += increase; + *rtcp_len += increase; + } + /* copy new CNAME into message */ + memcpy(cur, new_cname, strlen(new_cname)); + /* FIXME: zero the padding in case new CNAME + * is smaller than old one !!! */ + } + cur += len; + } + } + + return 0; +} + +static int rtcp_mangle(struct msgb *msg, struct rtp_socket *rs) +{ + struct rtp_sub_socket *rss = &rs->rtcp; + struct rtcp_hdr *rtph; + uint16_t old_len; + int rc; + + if (!mangle_rtcp_cname) + return 0; + + printf("RTCP\n"); + /* iterate over list of RTCP messages */ + rtph = (struct rtcp_hdr *)msg->data; + while ((void *)rtph + sizeof(*rtph) <= (void *)msg->data + msg->len) { + old_len = (ntohs(rtph->length) + 1) * 4; + if ((void *)rtph + old_len > (void *)msg->data + msg->len) { + DEBUGPC(DLMUX, "received RTCP packet too short for " + "length element\n"); + return -EINVAL; + } + if (rtph->type == RTCP_TYPE_SDES) { + char new_cname[255]; + strncpy(new_cname, inet_ntoa(rss->sin_local.sin_addr), + sizeof(new_cname)); + new_cname[sizeof(new_cname)-1] = '\0'; + rc = rtcp_sdes_cname_mangle(msg, rtph, &old_len, + new_cname); + if (rc < 0) + return rc; + } + rtph = (void *)rtph + old_len; + } + + return 0; +} + +/* read from incoming RTP/RTCP socket */ +static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss) +{ + int rc; + struct msgb *msg = msgb_alloc(RTP_ALLOC_SIZE, "RTP/RTCP"); + struct msgb *new_msg; + struct rtp_sub_socket *other_rss; + + if (!msg) + return -ENOMEM; + + rc = read(rss->bfd.fd, msg->data, RTP_ALLOC_SIZE); + if (rc <= 0) { + rss->bfd.when &= ~BSC_FD_READ; + return rc; + } + + msgb_put(msg, rc); + + switch (rs->rx_action) { + case RTP_PROXY: + if (!rs->proxy.other_sock) { + rc = -EIO; + goto out_free; + } + if (rss->bfd.priv_nr == RTP_PRIV_RTP) + other_rss = &rs->proxy.other_sock->rtp; + else if (rss->bfd.priv_nr == RTP_PRIV_RTCP) { + other_rss = &rs->proxy.other_sock->rtcp; + /* modify RTCP SDES CNAME */ + rc = rtcp_mangle(msg, rs); + if (rc < 0) + goto out_free; + } else { + rc = -EINVAL; + goto out_free; + } + msgb_enqueue(&other_rss->tx_queue, msg); + other_rss->bfd.when |= BSC_FD_WRITE; + break; + + case RTP_RECV_UPSTREAM: + if (!rs->receive.callref || !rs->receive.net) { + rc = -EIO; + goto out_free; + } + if (rss->bfd.priv_nr == RTP_PRIV_RTCP) { + if (!mangle_rtcp_cname) { + msgb_free(msg); + break; + } + /* modify RTCP SDES CNAME */ + rc = rtcp_mangle(msg, rs); + if (rc < 0) + goto out_free; + msgb_enqueue(&rss->tx_queue, msg); + rss->bfd.when |= BSC_FD_WRITE; + break; + } + if (rss->bfd.priv_nr != RTP_PRIV_RTP) { + rc = -EINVAL; + goto out_free; + } + rc = rtp_decode(msg, rs->receive.callref, &new_msg); + if (rc < 0) + goto out_free; + msgb_free(msg); + trau_tx_to_mncc(rs->receive.net, new_msg); + break; + + case RTP_NONE: /* if socket exists, but disabled by app */ + msgb_free(msg); + break; + } + + return 0; + +out_free: + msgb_free(msg); + return rc; +} + +/* \brief write from tx_queue to RTP/RTCP socket */ +static int rtp_socket_write(struct rtp_socket *rs, struct rtp_sub_socket *rss) +{ + struct msgb *msg; + int written; + + msg = msgb_dequeue(&rss->tx_queue); + if (!msg) { + rss->bfd.when &= ~BSC_FD_WRITE; + return 0; + } + + written = write(rss->bfd.fd, msg->data, msg->len); + if (written < msg->len) { + LOGP(DLMIB, LOGL_ERROR, "short write"); + msgb_free(msg); + return -EIO; + } + + msgb_free(msg); + + return 0; +} + + +/*! \brief callback for the select.c:bfd_* layer */ +static int rtp_bfd_cb(struct osmo_fd *bfd, unsigned int flags) +{ + struct rtp_socket *rs = bfd->data; + struct rtp_sub_socket *rss; + + switch (bfd->priv_nr) { + case RTP_PRIV_RTP: + rss = &rs->rtp; + break; + case RTP_PRIV_RTCP: + rss = &rs->rtcp; + break; + default: + return -EINVAL; + } + + if (flags & BSC_FD_READ) + rtp_socket_read(rs, rss); + + if (flags & BSC_FD_WRITE) + rtp_socket_write(rs, rss); + + return 0; +} + +/*! \brief initialize one rtp sub-socket */ +static void init_rss(struct rtp_sub_socket *rss, + struct rtp_socket *rs, int fd, int priv_nr) +{ + /* initialize bfd */ + rss->bfd.fd = fd; + rss->bfd.data = rs; + rss->bfd.priv_nr = priv_nr; + rss->bfd.cb = rtp_bfd_cb; +} + +/*! \brief create a new RTP/RTCP socket and bind it */ +struct rtp_socket *rtp_socket_create(void) +{ + int rc; + struct rtp_socket *rs; + + DEBUGP(DLMUX, "rtp_socket_create(): "); + + rs = talloc_zero(tall_bsc_ctx, struct rtp_socket); + if (!rs) + return NULL; + + INIT_LLIST_HEAD(&rs->rtp.tx_queue); + INIT_LLIST_HEAD(&rs->rtcp.tx_queue); + + rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (rc < 0) + goto out_free; + + init_rss(&rs->rtp, rs, rc, RTP_PRIV_RTP); + rc = osmo_fd_register(&rs->rtp.bfd); + if (rc < 0) + goto out_rtp_socket; + + rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (rc < 0) + goto out_rtp_bfd; + + init_rss(&rs->rtcp, rs, rc, RTP_PRIV_RTCP); + rc = osmo_fd_register(&rs->rtcp.bfd); + if (rc < 0) + goto out_rtcp_socket; + + DEBUGPC(DLMUX, "success\n"); + + rc = rtp_socket_bind(rs, INADDR_ANY); + if (rc < 0) + goto out_rtcp_bfd; + + return rs; + +out_rtcp_bfd: + osmo_fd_unregister(&rs->rtcp.bfd); +out_rtcp_socket: + close(rs->rtcp.bfd.fd); +out_rtp_bfd: + osmo_fd_unregister(&rs->rtp.bfd); +out_rtp_socket: + close(rs->rtp.bfd.fd); +out_free: + talloc_free(rs); + DEBUGPC(DLMUX, "failed\n"); + return NULL; +} + +static int rtp_sub_socket_bind(struct rtp_sub_socket *rss, uint32_t ip, + uint16_t port) +{ + int rc; + socklen_t alen = sizeof(rss->sin_local); + + rss->sin_local.sin_family = AF_INET; + rss->sin_local.sin_addr.s_addr = htonl(ip); + rss->sin_local.sin_port = htons(port); + rss->bfd.when |= BSC_FD_READ; + + rc = bind(rss->bfd.fd, (struct sockaddr *)&rss->sin_local, + sizeof(rss->sin_local)); + if (rc < 0) + return rc; + + /* retrieve the address we actually bound to, in case we + * passed INADDR_ANY as IP address */ + return getsockname(rss->bfd.fd, (struct sockaddr *)&rss->sin_local, + &alen); +} + +#define RTP_PORT_BASE 30000 +static unsigned int next_udp_port = RTP_PORT_BASE; + +/*! \brief bind a RTP socket to a specific local address + * \param[in] rs RTP socket to be bound + * \param[in] ip local IP address to which socket is to be bound + */ +int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip) +{ + int rc = -EIO; + struct in_addr ia; + + ia.s_addr = htonl(ip); + DEBUGP(DLMUX, "rtp_socket_bind(rs=%p, IP=%s): ", rs, + inet_ntoa(ia)); + + /* try to bind to a consecutive pair of ports */ + for (next_udp_port = next_udp_port % 0xffff; + next_udp_port < 0xffff; next_udp_port += 2) { + rc = rtp_sub_socket_bind(&rs->rtp, ip, next_udp_port); + if (rc != 0) + continue; + + rc = rtp_sub_socket_bind(&rs->rtcp, ip, next_udp_port+1); + if (rc == 0) + break; + } + if (rc < 0) { + DEBUGPC(DLMUX, "failed\n"); + return rc; + } + + ia.s_addr = rs->rtp.sin_local.sin_addr.s_addr; + DEBUGPC(DLMUX, "BOUND_IP=%s, BOUND_PORT=%u\n", + inet_ntoa(ia), ntohs(rs->rtp.sin_local.sin_port)); + return ntohs(rs->rtp.sin_local.sin_port); +} + +static int rtp_sub_socket_connect(struct rtp_sub_socket *rss, + uint32_t ip, uint16_t port) +{ + int rc; + socklen_t alen = sizeof(rss->sin_local); + + rss->sin_remote.sin_family = AF_INET; + rss->sin_remote.sin_addr.s_addr = htonl(ip); + rss->sin_remote.sin_port = htons(port); + + rc = connect(rss->bfd.fd, (struct sockaddr *) &rss->sin_remote, + sizeof(rss->sin_remote)); + if (rc < 0) + return rc; + + return getsockname(rss->bfd.fd, (struct sockaddr *)&rss->sin_local, + &alen); +} + +/*! \brief 'connect' a RTP socket to a remote peer + * \param[in] rs RTP socket to be connected + * \param[in] ip remote IP address to which to connect + * \param[in] port remote UDP port number to which to connect + */ +int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port) +{ + int rc; + struct in_addr ia; + + ia.s_addr = htonl(ip); + DEBUGP(DLMUX, "rtp_socket_connect(rs=%p, ip=%s, port=%u)\n", + rs, inet_ntoa(ia), port); + + rc = rtp_sub_socket_connect(&rs->rtp, ip, port); + if (rc < 0) + return rc; + + return rtp_sub_socket_connect(&rs->rtcp, ip, port+1); +} + +/*! \brief bind two RTP/RTCP sockets together in the proxy + * \param[in] this First RTP socket + * \param[in] other Second RTP socket + */ +int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other) +{ + DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, other=%p)\n", + this, other); + + this->rx_action = RTP_PROXY; + this->proxy.other_sock = other; + + other->rx_action = RTP_PROXY; + other->proxy.other_sock = this; + + return 0; +} + +/*! \brief bind RTP/RTCP socket to application, disabling proxy + * \param[in] this RTP socket + * \param[in] net gsm_network argument to trau_tx_to_mncc() + * \param[in] callref callref argument to trau_tx_to_mncc() + */ +int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net, + uint32_t callref) +{ + DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, callref=%u)\n", + this, callref); + + if (callref) { + this->rx_action = RTP_RECV_UPSTREAM; + this->receive.net = net; + this->receive.callref = callref; + } else + this->rx_action = RTP_NONE; + + return 0; +} + +static void free_tx_queue(struct rtp_sub_socket *rss) +{ + struct msgb *msg; + + while ((msg = msgb_dequeue(&rss->tx_queue))) + msgb_free(msg); +} + +/*! \brief Free/release a previously allocated RTP socket + * \param[in[] rs RTP/RTCP socket to be released + */ +int rtp_socket_free(struct rtp_socket *rs) +{ + DEBUGP(DLMUX, "rtp_socket_free(rs=%p)\n", rs); + + /* make sure we don't leave references dangling to us */ + if (rs->rx_action == RTP_PROXY && + rs->proxy.other_sock) + rs->proxy.other_sock->proxy.other_sock = NULL; + + osmo_fd_unregister(&rs->rtp.bfd); + close(rs->rtp.bfd.fd); + free_tx_queue(&rs->rtp); + + osmo_fd_unregister(&rs->rtcp.bfd); + close(rs->rtcp.bfd.fd); + free_tx_queue(&rs->rtcp); + + talloc_free(rs); + + return 0; +} + +static int rtp_handle_lchan_signal(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct gsm_lchan *lchan; + struct lchan_signal_data *lchan_data; + + if (subsys != SS_LCHAN) + return 0; + + + lchan_data = signal_data; + if (!lchan_data->lchan || !lchan_data->lchan->conn) + return 0; + + lchan = lchan_data->lchan; + + switch (signal) { + case S_LCHAN_RTP_SOCKET_FREE: + rtp_socket_free(lchan->abis_ip.rtp_socket); + break; + } + + return 0; +} + +static __attribute__((constructor)) void on_dso_load_rtp_proxy(void) +{ + osmo_signal_register_handler(SS_LCHAN, rtp_handle_lchan_signal, NULL); +} diff --git a/openbsc/src/libtrau/Makefile.am b/openbsc/src/libtrau/Makefile.am index 0c8cf17..7b71417 100644 --- a/openbsc/src/libtrau/Makefile.am +++ b/openbsc/src/libtrau/Makefile.am @@ -4,4 +4,4 @@ AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOABIS_LIBS) $(COVERA noinst_LIBRARIES = libtrau.a -libtrau_a_SOURCES = rtp_proxy.c trau_mux.c trau_upqueue.c +libtrau_a_SOURCES = trau_mux.c trau_upqueue.c diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c deleted file mode 100644 index c011765..0000000 --- a/openbsc/src/libtrau/rtp_proxy.c +++ /dev/null @@ -1,816 +0,0 @@ -/* RTP proxy handling for ip.access nanoBTS */ - -/* (C) 2009-2013 by Harald Welte - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -#include -#include -#include -#include -#include -#include /* gettimeofday() */ -#include /* get..() */ -#include /* clock() */ -#include /* uname() */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* attempt to determine byte order */ -#include -#include - -#ifndef __BYTE_ORDER -# ifdef __APPLE__ -# define __BYTE_ORDER __DARWIN_BYTE_ORDER -# define __LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN -# define __BIG_ENDIAN __DARWIN_BIG_ENDIAN -# else -# error "__BYTE_ORDER should be defined by someone" -# endif -#endif - -static LLIST_HEAD(rtp_sockets); - -/* should we mangle the CNAME inside SDES of RTCP packets? We disable - * this by default, as it seems to be not needed */ -static int mangle_rtcp_cname = 0; - -enum rtp_bfd_priv { - RTP_PRIV_NONE, - RTP_PRIV_RTP, - RTP_PRIV_RTCP -}; - -#define RTP_ALLOC_SIZE 1500 - -/* according to RFC 1889 */ -struct rtcp_hdr { - uint8_t byte0; - uint8_t type; - uint16_t length; -} __attribute__((packed)); - -#define RTCP_TYPE_SDES 202 - -#define RTCP_IE_CNAME 1 - -/* according to RFC 3550 */ -struct rtp_hdr { -#if __BYTE_ORDER == __LITTLE_ENDIAN - uint8_t csrc_count:4, - extension:1, - padding:1, - version:2; - uint8_t payload_type:7, - marker:1; -#elif __BYTE_ORDER == __BIG_ENDIAN - uint8_t version:2, - padding:1, - extension:1, - csrc_count:4; - uint8_t marker:1, - payload_type:7; -#endif - uint16_t sequence; - uint32_t timestamp; - uint32_t ssrc; -} __attribute__((packed)); - -struct rtp_x_hdr { - uint16_t by_profile; - uint16_t length; -} __attribute__((packed)); - -#define RTP_VERSION 2 - -/* decode an rtp frame and create a new buffer with payload */ -static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data) -{ - struct msgb *new_msg; - struct gsm_data_frame *frame; - struct rtp_hdr *rtph = (struct rtp_hdr *)msg->data; - struct rtp_x_hdr *rtpxh; - uint8_t *payload; - int payload_len; - int msg_type; - int x_len; - - if (msg->len < 12) { - DEBUGPC(DLMUX, "received RTP frame too short (len = %d)\n", - msg->len); - return -EINVAL; - } - if (rtph->version != RTP_VERSION) { - DEBUGPC(DLMUX, "received RTP version %d not supported.\n", - rtph->version); - return -EINVAL; - } - payload = msg->data + sizeof(struct rtp_hdr) + (rtph->csrc_count << 2); - payload_len = msg->len - sizeof(struct rtp_hdr) - (rtph->csrc_count << 2); - if (payload_len < 0) { - DEBUGPC(DLMUX, "received RTP frame too short (len = %d, " - "csrc count = %d)\n", msg->len, rtph->csrc_count); - return -EINVAL; - } - if (rtph->extension) { - if (payload_len < sizeof(struct rtp_x_hdr)) { - DEBUGPC(DLMUX, "received RTP frame too short for " - "extension header\n"); - return -EINVAL; - } - rtpxh = (struct rtp_x_hdr *)payload; - x_len = ntohs(rtpxh->length) * 4 + sizeof(struct rtp_x_hdr); - payload += x_len; - payload_len -= x_len; - if (payload_len < 0) { - DEBUGPC(DLMUX, "received RTP frame too short, " - "extension header exceeds frame length\n"); - return -EINVAL; - } - } - if (rtph->padding) { - if (payload_len < 1) { - DEBUGPC(DLMUX, "received RTP frame too short for " - "padding length\n"); - return -EINVAL; - } - payload_len -= payload[payload_len - 1]; - if (payload_len < 0) { - DEBUGPC(DLMUX, "received RTP frame with padding " - "greater than payload\n"); - return -EINVAL; - } - } - - switch (rtph->payload_type) { - case RTP_PT_GSM_FULL: - msg_type = GSM_TCHF_FRAME; - if (payload_len != RTP_LEN_GSM_FULL) { - DEBUGPC(DLMUX, "received RTP full rate frame with " - "payload length != %d (len = %d)\n", - RTP_LEN_GSM_FULL, payload_len); - return -EINVAL; - } - break; - case RTP_PT_GSM_EFR: - msg_type = GSM_TCHF_FRAME_EFR; - if (payload_len != RTP_LEN_GSM_EFR) { - DEBUGPC(DLMUX, "received RTP extended full rate frame " - "with payload length != %d (len = %d)\n", - RTP_LEN_GSM_EFR, payload_len); - return -EINVAL; - } - break; - case RTP_PT_GSM_HALF: - msg_type = GSM_TCHH_FRAME; - if (payload_len != RTP_LEN_GSM_HALF) { - DEBUGPC(DLMUX, "received RTP half rate frame with " - "payload length != %d (len = %d)\n", - RTP_LEN_GSM_HALF, payload_len); - return -EINVAL; - } - break; - case RTP_PT_AMR: - break; - default: - DEBUGPC(DLMUX, "received RTP frame with unknown payload " - "type %d\n", rtph->payload_type); - return -EINVAL; - } - - if (rtph->payload_type == RTP_PT_AMR) { - new_msg = msgb_alloc(sizeof(struct gsm_data_frame) + 1 - + payload_len, "GSM-DATA"); - } else { - new_msg = msgb_alloc(sizeof(struct gsm_data_frame) - + payload_len, "GSM-DATA"); - } - if (!new_msg) - return -ENOMEM; - frame = (struct gsm_data_frame *)(new_msg->data); - frame->msg_type = msg_type; - frame->callref = callref; - if (rtph->payload_type == RTP_PT_AMR) { - frame->data[0] = payload_len; - msgb_put(new_msg, sizeof(struct gsm_data_frame) + 1 - + payload_len); - memcpy(frame->data + 1, payload, payload_len); - } else { - msgb_put(new_msg, sizeof(struct gsm_data_frame) + payload_len); - memcpy(frame->data, payload, payload_len); - } - - *data = new_msg; - return 0; -} - -/* "to - from" */ -static void tv_difference(struct timeval *diff, const struct timeval *from, - const struct timeval *__to) -{ - struct timeval _to = *__to, *to = &_to; - - if (to->tv_usec < from->tv_usec) { - to->tv_sec -= 1; - to->tv_usec += 1000000; - } - - diff->tv_usec = to->tv_usec - from->tv_usec; - diff->tv_sec = to->tv_sec - from->tv_sec; -} - -/*! \brief encode and send a rtp frame - * \param[in] rs RTP socket through which we shall send - * \param[in] frame GSM RTP frame to be sent - */ -int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame) -{ - struct rtp_sub_socket *rss = &rs->rtp; - struct msgb *msg; - struct rtp_hdr *rtph; - int payload_type; - int payload_len; - int duration; /* in samples */ - int is_bfi = 0; - - if (rs->tx_action != RTP_SEND_DOWNSTREAM) { - /* initialize sequences */ - rs->tx_action = RTP_SEND_DOWNSTREAM; - rs->transmit.ssrc = rand(); - rs->transmit.sequence = random(); - rs->transmit.timestamp = random(); - } - - switch (frame->msg_type) { - case GSM_TCHF_FRAME: - payload_type = RTP_PT_GSM_FULL; - payload_len = RTP_LEN_GSM_FULL; - duration = RTP_GSM_DURATION; - break; - case GSM_TCHF_FRAME_EFR: - payload_type = RTP_PT_GSM_EFR; - payload_len = RTP_LEN_GSM_EFR; - duration = RTP_GSM_DURATION; - break; - case GSM_TCHH_FRAME: - payload_type = RTP_PT_GSM_HALF; - payload_len = RTP_LEN_GSM_HALF; - duration = RTP_GSM_DURATION; - break; - case GSM_TCH_FRAME_AMR: - payload_type = RTP_PT_AMR; - payload_len = frame->data[0]; - duration = RTP_GSM_DURATION; - break; - case GSM_BAD_FRAME: - payload_type = 0; - payload_len = 0; - duration = RTP_GSM_DURATION; - is_bfi = 1; - break; - default: - DEBUGPC(DLMUX, "unsupported message type %d\n", - frame->msg_type); - return -EINVAL; - } - - { - struct timeval tv, tv_diff; - long int usec_diff, frame_diff; - - gettimeofday(&tv, NULL); - tv_difference(&tv_diff, &rs->transmit.last_tv, &tv); - rs->transmit.last_tv = tv; - - usec_diff = tv_diff.tv_sec * 1000000 + tv_diff.tv_usec; - frame_diff = (usec_diff / 20000); - - if (abs(frame_diff) > 1) { - long int frame_diff_excess = frame_diff - 1; - - LOGP(DLMUX, LOGL_NOTICE, - "Correcting frame difference of %ld frames\n", frame_diff_excess); - rs->transmit.sequence += frame_diff_excess; - rs->transmit.timestamp += frame_diff_excess * duration; - } - } - - if (is_bfi) { - /* In case of a bad frame, just count and drop packt. */ - rs->transmit.timestamp += duration; - rs->transmit.sequence++; - return 0; - } - - msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len, "RTP-GSM-FULL"); - if (!msg) - return -ENOMEM; - rtph = (struct rtp_hdr *)msg->data; - rtph->version = RTP_VERSION; - rtph->padding = 0; - rtph->extension = 0; - rtph->csrc_count = 0; - rtph->marker = 0; - rtph->payload_type = payload_type; - rtph->sequence = htons(rs->transmit.sequence++); - rtph->timestamp = htonl(rs->transmit.timestamp); - rs->transmit.timestamp += duration; - rtph->ssrc = htonl(rs->transmit.ssrc); - if (frame->msg_type == GSM_TCH_FRAME_AMR) { - memcpy(msg->data + sizeof(struct rtp_hdr), frame->data + 1, - payload_len); - } else { - memcpy(msg->data + sizeof(struct rtp_hdr), frame->data, - payload_len); - } - msgb_put(msg, sizeof(struct rtp_hdr) + payload_len); - msgb_enqueue(&rss->tx_queue, msg); - rss->bfd.when |= BSC_FD_WRITE; - - return 0; -} - -/* iterate over all chunks in one RTCP message, look for CNAME IEs and - * replace all of those with 'new_cname' */ -static int rtcp_sdes_cname_mangle(struct msgb *msg, struct rtcp_hdr *rh, - uint16_t *rtcp_len, const char *new_cname) -{ - uint8_t *rtcp_end; - uint8_t *cur = (uint8_t *) rh; - uint8_t tag, len = 0; - - rtcp_end = cur + *rtcp_len; - /* move cur to end of RTP header */ - cur += sizeof(*rh); - - /* iterate over Chunks */ - while (cur+4 < rtcp_end) { - /* skip four bytes SSRC/CSRC */ - cur += 4; - - /* iterate over IE's inside the chunk */ - while (cur+1 < rtcp_end) { - tag = *cur++; - if (tag == 0) { - /* end of chunk, skip additional zero */ - while (*cur++ == 0) { } - break; - } - len = *cur++; - - if (tag == RTCP_IE_CNAME) { - /* we've found the CNAME, lets mangle it */ - if (len < strlen(new_cname)) { - /* we need to make more space */ - int increase = strlen(new_cname) - len; - - msgb_push(msg, increase); - memmove(cur+len+increase, cur+len, - rtcp_end - (cur+len)); - /* FIXME: we have to respect RTCP - * padding/alignment rules! */ - len += increase; - *(cur-1) += increase; - rtcp_end += increase; - *rtcp_len += increase; - } - /* copy new CNAME into message */ - memcpy(cur, new_cname, strlen(new_cname)); - /* FIXME: zero the padding in case new CNAME - * is smaller than old one !!! */ - } - cur += len; - } - } - - return 0; -} - -static int rtcp_mangle(struct msgb *msg, struct rtp_socket *rs) -{ - struct rtp_sub_socket *rss = &rs->rtcp; - struct rtcp_hdr *rtph; - uint16_t old_len; - int rc; - - if (!mangle_rtcp_cname) - return 0; - - printf("RTCP\n"); - /* iterate over list of RTCP messages */ - rtph = (struct rtcp_hdr *)msg->data; - while ((void *)rtph + sizeof(*rtph) <= (void *)msg->data + msg->len) { - old_len = (ntohs(rtph->length) + 1) * 4; - if ((void *)rtph + old_len > (void *)msg->data + msg->len) { - DEBUGPC(DLMUX, "received RTCP packet too short for " - "length element\n"); - return -EINVAL; - } - if (rtph->type == RTCP_TYPE_SDES) { - char new_cname[255]; - strncpy(new_cname, inet_ntoa(rss->sin_local.sin_addr), - sizeof(new_cname)); - new_cname[sizeof(new_cname)-1] = '\0'; - rc = rtcp_sdes_cname_mangle(msg, rtph, &old_len, - new_cname); - if (rc < 0) - return rc; - } - rtph = (void *)rtph + old_len; - } - - return 0; -} - -/* read from incoming RTP/RTCP socket */ -static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss) -{ - int rc; - struct msgb *msg = msgb_alloc(RTP_ALLOC_SIZE, "RTP/RTCP"); - struct msgb *new_msg; - struct rtp_sub_socket *other_rss; - - if (!msg) - return -ENOMEM; - - rc = read(rss->bfd.fd, msg->data, RTP_ALLOC_SIZE); - if (rc <= 0) { - rss->bfd.when &= ~BSC_FD_READ; - return rc; - } - - msgb_put(msg, rc); - - switch (rs->rx_action) { - case RTP_PROXY: - if (!rs->proxy.other_sock) { - rc = -EIO; - goto out_free; - } - if (rss->bfd.priv_nr == RTP_PRIV_RTP) - other_rss = &rs->proxy.other_sock->rtp; - else if (rss->bfd.priv_nr == RTP_PRIV_RTCP) { - other_rss = &rs->proxy.other_sock->rtcp; - /* modify RTCP SDES CNAME */ - rc = rtcp_mangle(msg, rs); - if (rc < 0) - goto out_free; - } else { - rc = -EINVAL; - goto out_free; - } - msgb_enqueue(&other_rss->tx_queue, msg); - other_rss->bfd.when |= BSC_FD_WRITE; - break; - - case RTP_RECV_UPSTREAM: - if (!rs->receive.callref || !rs->receive.net) { - rc = -EIO; - goto out_free; - } - if (rss->bfd.priv_nr == RTP_PRIV_RTCP) { - if (!mangle_rtcp_cname) { - msgb_free(msg); - break; - } - /* modify RTCP SDES CNAME */ - rc = rtcp_mangle(msg, rs); - if (rc < 0) - goto out_free; - msgb_enqueue(&rss->tx_queue, msg); - rss->bfd.when |= BSC_FD_WRITE; - break; - } - if (rss->bfd.priv_nr != RTP_PRIV_RTP) { - rc = -EINVAL; - goto out_free; - } - rc = rtp_decode(msg, rs->receive.callref, &new_msg); - if (rc < 0) - goto out_free; - msgb_free(msg); - trau_tx_to_mncc(rs->receive.net, new_msg); - break; - - case RTP_NONE: /* if socket exists, but disabled by app */ - msgb_free(msg); - break; - } - - return 0; - -out_free: - msgb_free(msg); - return rc; -} - -/* \brief write from tx_queue to RTP/RTCP socket */ -static int rtp_socket_write(struct rtp_socket *rs, struct rtp_sub_socket *rss) -{ - struct msgb *msg; - int written; - - msg = msgb_dequeue(&rss->tx_queue); - if (!msg) { - rss->bfd.when &= ~BSC_FD_WRITE; - return 0; - } - - written = write(rss->bfd.fd, msg->data, msg->len); - if (written < msg->len) { - LOGP(DLMIB, LOGL_ERROR, "short write"); - msgb_free(msg); - return -EIO; - } - - msgb_free(msg); - - return 0; -} - - -/*! \brief callback for the select.c:bfd_* layer */ -static int rtp_bfd_cb(struct osmo_fd *bfd, unsigned int flags) -{ - struct rtp_socket *rs = bfd->data; - struct rtp_sub_socket *rss; - - switch (bfd->priv_nr) { - case RTP_PRIV_RTP: - rss = &rs->rtp; - break; - case RTP_PRIV_RTCP: - rss = &rs->rtcp; - break; - default: - return -EINVAL; - } - - if (flags & BSC_FD_READ) - rtp_socket_read(rs, rss); - - if (flags & BSC_FD_WRITE) - rtp_socket_write(rs, rss); - - return 0; -} - -/*! \brief initialize one rtp sub-socket */ -static void init_rss(struct rtp_sub_socket *rss, - struct rtp_socket *rs, int fd, int priv_nr) -{ - /* initialize bfd */ - rss->bfd.fd = fd; - rss->bfd.data = rs; - rss->bfd.priv_nr = priv_nr; - rss->bfd.cb = rtp_bfd_cb; -} - -/*! \brief create a new RTP/RTCP socket and bind it */ -struct rtp_socket *rtp_socket_create(void) -{ - int rc; - struct rtp_socket *rs; - - DEBUGP(DLMUX, "rtp_socket_create(): "); - - rs = talloc_zero(tall_bsc_ctx, struct rtp_socket); - if (!rs) - return NULL; - - INIT_LLIST_HEAD(&rs->rtp.tx_queue); - INIT_LLIST_HEAD(&rs->rtcp.tx_queue); - - rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (rc < 0) - goto out_free; - - init_rss(&rs->rtp, rs, rc, RTP_PRIV_RTP); - rc = osmo_fd_register(&rs->rtp.bfd); - if (rc < 0) - goto out_rtp_socket; - - rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (rc < 0) - goto out_rtp_bfd; - - init_rss(&rs->rtcp, rs, rc, RTP_PRIV_RTCP); - rc = osmo_fd_register(&rs->rtcp.bfd); - if (rc < 0) - goto out_rtcp_socket; - - DEBUGPC(DLMUX, "success\n"); - - rc = rtp_socket_bind(rs, INADDR_ANY); - if (rc < 0) - goto out_rtcp_bfd; - - return rs; - -out_rtcp_bfd: - osmo_fd_unregister(&rs->rtcp.bfd); -out_rtcp_socket: - close(rs->rtcp.bfd.fd); -out_rtp_bfd: - osmo_fd_unregister(&rs->rtp.bfd); -out_rtp_socket: - close(rs->rtp.bfd.fd); -out_free: - talloc_free(rs); - DEBUGPC(DLMUX, "failed\n"); - return NULL; -} - -static int rtp_sub_socket_bind(struct rtp_sub_socket *rss, uint32_t ip, - uint16_t port) -{ - int rc; - socklen_t alen = sizeof(rss->sin_local); - - rss->sin_local.sin_family = AF_INET; - rss->sin_local.sin_addr.s_addr = htonl(ip); - rss->sin_local.sin_port = htons(port); - rss->bfd.when |= BSC_FD_READ; - - rc = bind(rss->bfd.fd, (struct sockaddr *)&rss->sin_local, - sizeof(rss->sin_local)); - if (rc < 0) - return rc; - - /* retrieve the address we actually bound to, in case we - * passed INADDR_ANY as IP address */ - return getsockname(rss->bfd.fd, (struct sockaddr *)&rss->sin_local, - &alen); -} - -#define RTP_PORT_BASE 30000 -static unsigned int next_udp_port = RTP_PORT_BASE; - -/*! \brief bind a RTP socket to a specific local address - * \param[in] rs RTP socket to be bound - * \param[in] ip local IP address to which socket is to be bound - */ -int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip) -{ - int rc = -EIO; - struct in_addr ia; - - ia.s_addr = htonl(ip); - DEBUGP(DLMUX, "rtp_socket_bind(rs=%p, IP=%s): ", rs, - inet_ntoa(ia)); - - /* try to bind to a consecutive pair of ports */ - for (next_udp_port = next_udp_port % 0xffff; - next_udp_port < 0xffff; next_udp_port += 2) { - rc = rtp_sub_socket_bind(&rs->rtp, ip, next_udp_port); - if (rc != 0) - continue; - - rc = rtp_sub_socket_bind(&rs->rtcp, ip, next_udp_port+1); - if (rc == 0) - break; - } - if (rc < 0) { - DEBUGPC(DLMUX, "failed\n"); - return rc; - } - - ia.s_addr = rs->rtp.sin_local.sin_addr.s_addr; - DEBUGPC(DLMUX, "BOUND_IP=%s, BOUND_PORT=%u\n", - inet_ntoa(ia), ntohs(rs->rtp.sin_local.sin_port)); - return ntohs(rs->rtp.sin_local.sin_port); -} - -static int rtp_sub_socket_connect(struct rtp_sub_socket *rss, - uint32_t ip, uint16_t port) -{ - int rc; - socklen_t alen = sizeof(rss->sin_local); - - rss->sin_remote.sin_family = AF_INET; - rss->sin_remote.sin_addr.s_addr = htonl(ip); - rss->sin_remote.sin_port = htons(port); - - rc = connect(rss->bfd.fd, (struct sockaddr *) &rss->sin_remote, - sizeof(rss->sin_remote)); - if (rc < 0) - return rc; - - return getsockname(rss->bfd.fd, (struct sockaddr *)&rss->sin_local, - &alen); -} - -/*! \brief 'connect' a RTP socket to a remote peer - * \param[in] rs RTP socket to be connected - * \param[in] ip remote IP address to which to connect - * \param[in] port remote UDP port number to which to connect - */ -int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port) -{ - int rc; - struct in_addr ia; - - ia.s_addr = htonl(ip); - DEBUGP(DLMUX, "rtp_socket_connect(rs=%p, ip=%s, port=%u)\n", - rs, inet_ntoa(ia), port); - - rc = rtp_sub_socket_connect(&rs->rtp, ip, port); - if (rc < 0) - return rc; - - return rtp_sub_socket_connect(&rs->rtcp, ip, port+1); -} - -/*! \brief bind two RTP/RTCP sockets together in the proxy - * \param[in] this First RTP socket - * \param[in] other Second RTP socket - */ -int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other) -{ - DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, other=%p)\n", - this, other); - - this->rx_action = RTP_PROXY; - this->proxy.other_sock = other; - - other->rx_action = RTP_PROXY; - other->proxy.other_sock = this; - - return 0; -} - -/*! \brief bind RTP/RTCP socket to application, disabling proxy - * \param[in] this RTP socket - * \param[in] net gsm_network argument to trau_tx_to_mncc() - * \param[in] callref callref argument to trau_tx_to_mncc() - */ -int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net, - uint32_t callref) -{ - DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, callref=%u)\n", - this, callref); - - if (callref) { - this->rx_action = RTP_RECV_UPSTREAM; - this->receive.net = net; - this->receive.callref = callref; - } else - this->rx_action = RTP_NONE; - - return 0; -} - -static void free_tx_queue(struct rtp_sub_socket *rss) -{ - struct msgb *msg; - - while ((msg = msgb_dequeue(&rss->tx_queue))) - msgb_free(msg); -} - -/*! \brief Free/release a previously allocated RTP socket - * \param[in[] rs RTP/RTCP socket to be released - */ -int rtp_socket_free(struct rtp_socket *rs) -{ - DEBUGP(DLMUX, "rtp_socket_free(rs=%p)\n", rs); - - /* make sure we don't leave references dangling to us */ - if (rs->rx_action == RTP_PROXY && - rs->proxy.other_sock) - rs->proxy.other_sock->proxy.other_sock = NULL; - - osmo_fd_unregister(&rs->rtp.bfd); - close(rs->rtp.bfd.fd); - free_tx_queue(&rs->rtp); - - osmo_fd_unregister(&rs->rtcp.bfd); - close(rs->rtcp.bfd.fd); - free_tx_queue(&rs->rtcp); - - talloc_free(rs); - - return 0; -} -- 1.8.1.5 --------------010802080805090906090602-- From holger at freyther.de Sun Apr 20 14:33:57 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 20 Apr 2014 16:33:57 +0200 Subject: [PATCH 6/9] Add traffic forwarding via RTP to remote application In-Reply-To: <5350FCE7.9030401@eversberg.eu> References: <1392793078-30854-6-git-send-email-jolly@eversberg.eu> <20140309161952.GC6167@xiaoyu.lan> <531EAD2D.6000702@eversberg.eu> <20140314064042.GJ31238@xiaoyu.lan> <53242052.1070401@eversberg.eu> <20140316071240.GD27189@xiaoyu.lan> <53269940.7050101@eversberg.eu> <20140320214938.GB11963@xiaoyu.lan> <20140417212908.GA31314@xiaoyu.lan> <5350FCE7.9030401@eversberg.eu> Message-ID: <20140420143357.GE14607@xiaoyu.lan> On Fri, Apr 18, 2014 at 12:22:31PM +0200, Andreas Eversberg wrote: > S_LCHAN_HANDOVER_FAIL, /* 04.08 Handover Failed */ > S_LCHAN_HANDOVER_DETECT, /* 08.58 Handover Detect */ > S_LCHAN_MEAS_REP, /* 08.58 Measurement Report */ > + S_LCHAN_RTP_SOCKET_FREE, Use the opportunity to write a bit of information here? Or maybe just use S_CHALLOC_FREED to free rtp_socket and introduce a S_CHALLOC_RESET to do it in the later case? > + struct lchan_signal_data sig; please either use memset on sign or the 0 initializer of C99. > diff --git a/openbsc/src/libmsc/rtp_proxy.c b/openbsc/src/libmsc/rtp_proxy.c Please use the -M option on git format-patch/send-email to properly detect renames. thanks holger From jolly at eversberg.eu Fri Apr 18 09:03:50 2014 From: jolly at eversberg.eu (Andreas Eversberg) Date: Fri, 18 Apr 2014 11:03:50 +0200 Subject: [PATCH] Move rtp_proxy.c from libtrau to libmsc Message-ID: In order to free RTP socket when lchan_free() or lchan_reset() is called, a signal is used between libbsc and rtp_proxy. --- openbsc/include/openbsc/signal.h | 1 + openbsc/src/libbsc/chan_alloc.c | 19 +++++++--------- openbsc/src/libmsc/Makefile.am | 3 ++- openbsc/src/{libtrau => libmsc}/rtp_proxy.c | 35 +++++++++++++++++++++++++++++ openbsc/src/libtrau/Makefile.am | 2 +- 5 files changed, 47 insertions(+), 13 deletions(-) rename openbsc/src/{libtrau => libmsc}/rtp_proxy.c (96%) diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 39319f1..31c9187 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -105,6 +105,7 @@ enum signal_lchan { enum signal_challoc { S_CHALLOC_ALLOC_FAIL, /* allocation of lchan has failed */ S_CHALLOC_FREED, /* lchan has been successfully freed */ + S_CHALLOC_RESET, /* lchan has been reset */ }; /* SS_SUBSCR signals */ diff --git a/openbsc/src/libbsc/chan_alloc.c b/openbsc/src/libbsc/chan_alloc.c index 9b74329..18ffa93 100644 --- a/openbsc/src/libbsc/chan_alloc.c +++ b/openbsc/src/libbsc/chan_alloc.c @@ -310,13 +310,6 @@ void lchan_free(struct gsm_lchan *lchan) osmo_signal_dispatch(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, &sig); } - if (lchan->abis_ip.rtp_socket) { - LOGP(DRLL, LOGL_ERROR, "%s RTP Proxy Socket remained open.\n", - gsm_lchan_name(lchan)); - rtp_socket_free(lchan->abis_ip.rtp_socket); - lchan->abis_ip.rtp_socket = NULL; - } - /* stop the timer */ osmo_timer_del(&lchan->T3101); @@ -360,18 +353,22 @@ void lchan_free(struct gsm_lchan *lchan) */ void lchan_reset(struct gsm_lchan *lchan) { + struct challoc_signal_data sig; + osmo_timer_del(&lchan->T3101); osmo_timer_del(&lchan->T3109); osmo_timer_del(&lchan->T3111); osmo_timer_del(&lchan->error_timer); + memset(&sig, 0, sizeof(sig)); + sig.type = lchan->type; + lchan->type = GSM_LCHAN_NONE; lchan->state = LCHAN_S_NONE; - if (lchan->abis_ip.rtp_socket) { - rtp_socket_free(lchan->abis_ip.rtp_socket); - lchan->abis_ip.rtp_socket = NULL; - } + sig.lchan = lchan; + sig.bts = lchan->ts->trx->bts; + osmo_signal_dispatch(SS_CHALLOC, S_CHALLOC_RESET, &sig); } /* Drive the release process of the lchan */ diff --git a/openbsc/src/libmsc/Makefile.am b/openbsc/src/libmsc/Makefile.am index 24db2c2..4d44a62 100644 --- a/openbsc/src/libmsc/Makefile.am +++ b/openbsc/src/libmsc/Makefile.am @@ -17,7 +17,8 @@ libmsc_a_SOURCES = auth.c \ ussd.c \ vty_interface_layer3.c \ transaction.c \ - osmo_msc.c ctrl_commands.c + osmo_msc.c ctrl_commands.c \ + rtp_proxy.c if BUILD_SMPP noinst_HEADERS = smpp_smsc.h diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libmsc/rtp_proxy.c similarity index 96% rename from openbsc/src/libtrau/rtp_proxy.c rename to openbsc/src/libmsc/rtp_proxy.c index 82d50ae..b86d228 100644 --- a/openbsc/src/libtrau/rtp_proxy.c +++ b/openbsc/src/libmsc/rtp_proxy.c @@ -36,6 +36,7 @@ #include #include #include +#include /* attempt to determine byte order */ #include @@ -830,3 +831,37 @@ int rtp_socket_free(struct rtp_socket *rs) return 0; } + +static int rtp_handle_challoc_signal(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct gsm_lchan *lchan; + struct challoc_signal_data *sig; + + if (subsys != SS_CHALLOC) + return 0; + + + sig = signal_data; + if (!sig->lchan || !sig->lchan->conn) + return 0; + + lchan = sig->lchan; + + switch (signal) { + case S_CHALLOC_FREED: + case S_CHALLOC_RESET: + if (lchan->abis_ip.rtp_socket) { + rtp_socket_free(lchan->abis_ip.rtp_socket); + lchan->abis_ip.rtp_socket = NULL; + } + break; + } + + return 0; +} + +static __attribute__((constructor)) void on_dso_load_rtp_proxy(void) +{ + osmo_signal_register_handler(SS_CHALLOC, rtp_handle_challoc_signal, NULL); +} diff --git a/openbsc/src/libtrau/Makefile.am b/openbsc/src/libtrau/Makefile.am index 0c8cf17..7b71417 100644 --- a/openbsc/src/libtrau/Makefile.am +++ b/openbsc/src/libtrau/Makefile.am @@ -4,4 +4,4 @@ AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOABIS_LIBS) $(COVERA noinst_LIBRARIES = libtrau.a -libtrau_a_SOURCES = rtp_proxy.c trau_mux.c trau_upqueue.c +libtrau_a_SOURCES = trau_mux.c trau_upqueue.c -- 1.8.1.5 --------------040603060708080405050707-- From holger at freyther.de Thu Apr 17 21:30:23 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Thu, 17 Apr 2014 23:30:23 +0200 Subject: [PATCH] sms: Rename gsm340_gen_oa() to gsm340_gen_address_field(). In-Reply-To: References: <20140309182323.GA17965@xiaoyu.lan> <20140311142626.GH17965@xiaoyu.lan> <20140312123702.GD2460@xiaoyu.lan> <20140326192222.GA769@xiaoyu.lan> Message-ID: <20140417213023.GC31314@xiaoyu.lan> On Thu, Mar 27, 2014 at 09:14:26AM +0400, Alexander Chemeris wrote: > Good idea. I'll update the patch during the next week. Did I miss your follow-up patch? From alexander.chemeris at gmail.com Fri Apr 18 05:46:55 2014 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Fri, 18 Apr 2014 09:46:55 +0400 Subject: [PATCH] sms: Rename gsm340_gen_oa() to gsm340_gen_address_field(). In-Reply-To: <20140417213023.GC31314@xiaoyu.lan> References: <20140309182323.GA17965@xiaoyu.lan> <20140311142626.GH17965@xiaoyu.lan> <20140312123702.GD2460@xiaoyu.lan> <20140326192222.GA769@xiaoyu.lan> <20140417213023.GC31314@xiaoyu.lan> Message-ID: Hi Holger, I was busy recently, sorry. I plan to get back to this patch set soon. Please excuse typos. Written with a touchscreen keyboard. -- Regards, Alexander Chemeris CEO/Founder Fairwaves LLC https://fairwaves.co 18 ???. 2014 ?. 1:30 ???????????? "Holger Hans Peter Freyther" < holger at freyther.de> ???????: > On Thu, Mar 27, 2014 at 09:14:26AM +0400, Alexander Chemeris wrote: > > > Good idea. I'll update the patch during the next week. > > Did I miss your follow-up patch? > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From george.news at gmx.net Tue Apr 1 07:15:02 2014 From: george.news at gmx.net (George News) Date: Tue, 01 Apr 2014 09:15:02 +0200 Subject: SMPP + OpenBSC In-Reply-To: <20140331164809.4b774dfb@2cb> References: <931401DD-14B4-452B-A34C-9E0B99F0BE44@gmail.com> <20140331164809.4b774dfb@2cb> Message-ID: <533A6776.3080405@gmx.net> Is with this configuration possible to send GSM 03.48 messages to a SIM card as for OTA programming? On 31/03/2014 23:48, tele wrote: > Hi, > > An example configuration for SMPP is the following: > > smpp > local-tcp-port 2775 > policy closed > esme OSMPP > password YOURPWD > default-route > > You do need an external SMSC that binds to OpenBSC using SMPP. > > Please note that only SMS that are not for subscribers will go through > the SMPP interface, osmo-nitb check if the extension exists in the HLR > if not the SMS is sent through SMPP. > You can do prefix matching but it will still apply only for numbers not > in the HLR. > > We did a dirty workaround in order to force all the SMS through SMPP to > a SMSC based on Kannel. > > http://cgit.osmocom.org/openbsc/commit/?h=ciaby/rhizomatica&id=112393a6109ade98b997e6bc3d221d5a2e9dd402 > > Kannel is configured with a TX/RX bind towards OpenBSC. You may use > only a TRX. If you need help with Kannel config let me know > > :tele > > > > > > > > On Mon, 31 Mar 2014 18:42:25 +0200 > "Jes?s Vega Diaz" wrote: > >> Hi all; >> >> I have deployed one ipaccess nanoBTS 1800, with OpenBSC (osmo-nitb) >> and all the osmocom suite apps. >> >> I have already make succesfully GSM calls, SMS, and GPRS/EDGE packet >> data connections. >> >> I now want support for sending binary SMS, i have read that with SMPP >> i would can. >> >> I have compiled OpenBSC with SMPP but now I don?t know how to use it, >> i think it is in the OpenBSC vty, but i don?t know the commands or >> how to use the interface. >> >> If you can give me some light in this thread i will grant you. >> >> Sorry for my English >> Best Regards >> >> Jes?s Vega Diaz > > > From tele at rhizomatica.org Tue Apr 1 20:17:24 2014 From: tele at rhizomatica.org (tele) Date: Tue, 1 Apr 2014 15:17:24 -0500 Subject: SMPP + OpenBSC In-Reply-To: <533A6776.3080405@gmx.net> References: <931401DD-14B4-452B-A34C-9E0B99F0BE44@gmail.com> <20140331164809.4b774dfb@2cb> <533A6776.3080405@gmx.net> Message-ID: <20140401151724.621f5868@2cb> I would say yes. OTA Gateway <-> Kannel <-(smpp)-> OpenBSC Kannel has different interfaces including a HTTP API interface. :tele On Tue, 01 Apr 2014 09:15:02 +0200 George News wrote: > Is with this configuration possible to send GSM 03.48 messages to a > SIM card as for OTA programming? > > > > On 31/03/2014 23:48, tele wrote: > > Hi, > > > > An example configuration for SMPP is the following: > > > > smpp > > local-tcp-port 2775 > > policy closed > > esme OSMPP > > password YOURPWD > > default-route > > > > You do need an external SMSC that binds to OpenBSC using SMPP. > > > > Please note that only SMS that are not for subscribers will go > > through the SMPP interface, osmo-nitb check if the extension exists > > in the HLR if not the SMS is sent through SMPP. > > You can do prefix matching but it will still apply only for numbers > > not in the HLR. > > > > We did a dirty workaround in order to force all the SMS through > > SMPP to a SMSC based on Kannel. > > > > http://cgit.osmocom.org/openbsc/commit/?h=ciaby/rhizomatica&id=112393a6109ade98b997e6bc3d221d5a2e9dd402 > > > > Kannel is configured with a TX/RX bind towards OpenBSC. You may use > > only a TRX. If you need help with Kannel config let me know > > > > :tele > > > > > > > > > > > > > > > > On Mon, 31 Mar 2014 18:42:25 +0200 > > "Jes?s Vega Diaz" wrote: > > > >> Hi all; > >> > >> I have deployed one ipaccess nanoBTS 1800, with OpenBSC (osmo-nitb) > >> and all the osmocom suite apps. > >> > >> I have already make succesfully GSM calls, SMS, and GPRS/EDGE > >> packet data connections. > >> > >> I now want support for sending binary SMS, i have read that with > >> SMPP i would can. > >> > >> I have compiled OpenBSC with SMPP but now I don?t know how to use > >> it, i think it is in the OpenBSC vty, but i don?t know the > >> commands or how to use the interface. > >> > >> If you can give me some light in this thread i will grant you. > >> > >> Sorry for my English > >> Best Regards > >> > >> Jes?s Vega Diaz > > > > > > From george.news at gmx.net Wed Apr 2 09:12:00 2014 From: george.news at gmx.net (George News) Date: Wed, 02 Apr 2014 11:12:00 +0200 Subject: SMPP + OpenBSC In-Reply-To: <20140401151724.621f5868@2cb> References: <931401DD-14B4-452B-A34C-9E0B99F0BE44@gmail.com> <20140331164809.4b774dfb@2cb> <533A6776.3080405@gmx.net> <20140401151724.621f5868@2cb> Message-ID: <533BD460.3010209@gmx.net> The idea is to use a mobile phone on an OpenBSC network to send a GSM 03.48 message to it from OpenBSC. I will further look at Kannel and have an idea on can I interact with SMPP, although using SMPP can be also a choice, can't be? Any tip on sending the SMS directly using SMPP? On 01/04/2014 22:17, tele wrote: > I would say yes. > > OTA Gateway <-> Kannel <-(smpp)-> OpenBSC > > Kannel has different interfaces including a HTTP API interface. > > :tele > > On Tue, 01 Apr 2014 09:15:02 +0200 > George News wrote: > >> Is with this configuration possible to send GSM 03.48 messages to a >> SIM card as for OTA programming? >> >> >> >> On 31/03/2014 23:48, tele wrote: >>> Hi, >>> >>> An example configuration for SMPP is the following: >>> >>> smpp >>> local-tcp-port 2775 >>> policy closed >>> esme OSMPP >>> password YOURPWD >>> default-route >>> >>> You do need an external SMSC that binds to OpenBSC using SMPP. >>> >>> Please note that only SMS that are not for subscribers will go >>> through the SMPP interface, osmo-nitb check if the extension exists >>> in the HLR if not the SMS is sent through SMPP. >>> You can do prefix matching but it will still apply only for numbers >>> not in the HLR. >>> >>> We did a dirty workaround in order to force all the SMS through >>> SMPP to a SMSC based on Kannel. >>> >>> http://cgit.osmocom.org/openbsc/commit/?h=ciaby/rhizomatica&id=112393a6109ade98b997e6bc3d221d5a2e9dd402 >>> >>> Kannel is configured with a TX/RX bind towards OpenBSC. You may use >>> only a TRX. If you need help with Kannel config let me know >>> >>> :tele >>> >>> >>> >>> >>> >>> >>> >>> On Mon, 31 Mar 2014 18:42:25 +0200 >>> "Jes?s Vega Diaz" wrote: >>> >>>> Hi all; >>>> >>>> I have deployed one ipaccess nanoBTS 1800, with OpenBSC (osmo-nitb) >>>> and all the osmocom suite apps. >>>> >>>> I have already make succesfully GSM calls, SMS, and GPRS/EDGE >>>> packet data connections. >>>> >>>> I now want support for sending binary SMS, i have read that with >>>> SMPP i would can. >>>> >>>> I have compiled OpenBSC with SMPP but now I don?t know how to use >>>> it, i think it is in the OpenBSC vty, but i don?t know the >>>> commands or how to use the interface. >>>> >>>> If you can give me some light in this thread i will grant you. >>>> >>>> Sorry for my English >>>> Best Regards >>>> >>>> Jes?s Vega Diaz >>> >>> >>> > > > From anayuso at sysmocom.de Wed Apr 2 09:56:10 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Wed, 2 Apr 2014 11:56:10 +0200 Subject: [osmo-bts PATCH v3] src: Add OML support for sending failure message from manager In-Reply-To: <1396258737-10396-1-git-send-email-anayuso@sysmocom.de> References: <1396258737-10396-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1396432570-24379-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso With this patch, the manager monitors the sensors and send OML Failure message from the Manager to the BTS and the BTS to BSC, for having a report system of the sensors. Signed-off-by: Alvaro Neira Ayuso --- v3: Changed the unix domain socket path for having an appropriate location src/osmo-bts-sysmo/main.c | 65 ++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 77 +++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 140 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 ++++++++ 4 files changed, 314 insertions(+), 1 deletion(-) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..2992e5b 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -45,8 +46,10 @@ #include #include #include +#include #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" +#define SOCKET_PATH "/var/run/bts_oml" #include "utils.h" #include "eeprom.h" @@ -258,6 +261,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT"); + unlink(SOCKET_PATH); break; case SIGABRT: case SIGUSR1: @@ -288,6 +292,55 @@ static int write_pid_file(char *procname) return 0; } +static int read_sock(struct osmo_fd *fd, unsigned int what) +{ + struct msgb *msg; + struct gsm_abis_mo *mo; + int rc; + + msg = oml_msgb_alloc(); + if (msg == NULL) + return -1; + + rc = recv(fd->fd, msg->tail, msg->data_len, 0); + if (rc <= 0) { + close(fd->fd); + osmo_fd_unregister(fd); + return -1; + } + + msgb_put(msg, rc); + + /*Remove the IPA header for removing the conflict with the new IPA + * header*/ + msgb_pull(msg, sizeof(struct ipaccess_head *)-1); + + mo = &bts->mo; + msg->trx = mo->bts->c0; + msg->l2h = msg->data; + msg->l3h = msg->data + sizeof(struct abis_om_fom_hdr); + + return abis_oml_sendmsg(msg); +} + +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *ofd = (struct osmo_fd *)fd->data; + + cl = accept(sfd, NULL, NULL); + if (cl < 0) + return -1; + + ofd->fd = cl; + if (osmo_fd_register(ofd) != 0) { + close(cl); + return -1; + } + + return 0; +} + int main(int argc, char **argv) { struct stat st; @@ -295,6 +348,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; + struct osmo_fd fd, rfd; int rc; tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -370,6 +424,17 @@ int main(int argc, char **argv) fprintf(stderr, "unable to connect to BSC\n"); exit(1); } + fd.cb = accept_unix_sock; + rfd.cb = read_sock; + rfd.when = BSC_FD_READ; + fd.data = &rfd; + + rc = osmo_sock_unix_init_ofd(&fd, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(3); + } if (daemonize) { rc = osmo_daemonize(); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..525e526 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,11 @@ static int no_eeprom_write = 0; static int daemonize = 0; +static int trx_nr = -1; +static int fd_unix = -1; +static int state_connection = 0; void *tall_mgr_ctx; +static struct sbts2050_config_info confinfo; /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -55,7 +60,29 @@ void *tall_mgr_ctx; /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ #define HOURS_TIMER_SECS (1 * 3600) +/* every 5 minutes try to reconnect if we have a problem in the communication*/ +#define CONNECT_TIMER_SECS (300) + +/* unix domain socket file descriptor */ +#define SOCKET_PATH "/var/run/bts_oml" + #ifdef BUILD_SBTS2050 +static struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + if (state_connection == 0) { + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + LOGP(DTEMP, LOGL_ERROR, "Error creating unix socket\n"); + return; + } + + state_connection = 1; + } + osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0); +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +91,50 @@ static void check_uctemp_timer_cb(void *data) sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); + confinfo.temp_pa_cur = temp_pa; + confinfo.temp_board_cur = temp_board; + + if (confinfo.temp_min_pa_warn_limit > temp_pa || + confinfo.temp_max_pa_warn_limit < temp_pa) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_WARN_ALERT, + SBTS2050_TEMP_PA, + &confinfo, trx_nr); + } else if (confinfo.temp_min_pa_sever_limit > temp_pa || + confinfo.temp_max_pa_sever_limit < temp_pa) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_SEVER_ALERT, + SBTS2050_TEMP_PA, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_MASTER), + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_SLAVE), + confinfo.pa_power_act); + } + + if (confinfo.temp_min_board_warn_limit > temp_board || + confinfo.temp_max_board_warn_limit < temp_board) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_WARN_ALERT, + SBTS2050_TEMP_BOARD, + &confinfo, trx_nr); + } else if (confinfo.temp_min_board_sever_limit > temp_board || + confinfo.temp_max_board_sever_limit < temp_board) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_SEVER_ALERT, + SBTS2050_TEMP_BOARD, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_PA)); + } + + if (state_connection == 0) + close(fd_unix); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +164,7 @@ static void initialize_sbts2050(void) if (val != 0) return; } + trx_nr = val; ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); if (ucontrol0.fd < 0) { @@ -169,6 +241,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write); + close(fd_unix); exit(0); break; case SIGABRT: @@ -363,6 +436,10 @@ int main(int argc, char **argv) hours_timer.cb = hours_timer_cb; hours_timer_cb(NULL); + /*start handle for reconnect the socket in case of error*/ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + /* start uc temperature check timer */ initialize_sbts2050(); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..0e89da6 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c @@ -29,13 +29,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include +#include #include "btsconfig.h" #include "sysmobts_misc.h" @@ -49,10 +53,144 @@ #define SERIAL_ALLOC_SIZE 300 #define SIZE_HEADER_RSP 5 #define SIZE_HEADER_CMD 4 - +#define OM_ALLOC_SIZE 1024 +#define OM_HEADROOM_SIZE 128 +#define IPA_OML_PROTO 0xFF #ifdef BUILD_SBTS2050 /********************************************************************** + * Function send information to OsmoBts + *********************************************************************/ +static void add_sw_descr(struct msgb *msg) +{ + char file_version[255]; + char file_id[255]; + + strcpy(file_id, "sysmomgr"); + strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)); + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), + (uint8_t *)file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), + (uint8_t *)file_version); +} + +static void add_probable_cause(struct msgb *msg) +{ + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); + msgb_v_put(msg, 0); + msgb_v_put(msg, 0); +} + +static void add_ipa_header(struct msgb *msg) +{ + struct ipaccess_head *hh; + + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); + hh->proto = IPA_OML_PROTO; + hh->len = htons(msg->len); +} + +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, + uint8_t obj_class, uint8_t bts_nr, + uint8_t trx_nr, uint8_t ts_nr) +{ + struct abis_om_fom_hdr *foh; + struct abis_om_hdr *omh; + + msg->l3h = msgb_push(msg, sizeof(*foh)); + foh = (struct abis_om_fom_hdr *) msg->l3h; + + foh->msg_type = msg_type; + foh->obj_class = obj_class; + foh->obj_inst.bts_nr = bts_nr; + foh->obj_inst.trx_nr = trx_nr; + foh->obj_inst.ts_nr = ts_nr; + + msg->l2h = msgb_push(msg, sizeof(*omh)); + omh = (struct abis_om_hdr *) msg->l2h; + + omh->mdisc = ABIS_OM_MDISC_FOM; + omh->placement = ABIS_OM_PLACEMENT_ONLY; + omh->sequence = 0; + omh->length = msgb_l3len(msg); +} + +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr) +{ + int rc; + struct msgb *msg; + const char *buf, *nsensor; + + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); + if (msg == NULL) { + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); + goto err; + } + + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0); + + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); + + switch (alert) { + case SBTS2050_WARN_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); + break; + case SBTS2050_SEVER_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); + break; + default: + goto err; + } + + add_probable_cause(msg); + + add_sw_descr(msg); + + switch (sensor) { + case SBTS2050_TEMP_BOARD: + buf = "Unusual temperature on the Board"; + nsensor = "Board"; + break; + case SBTS2050_TEMP_PA: + buf = "Unusual temperature on the PA"; + nsensor = "PA"; + break; + default: + return -1; + } + memset(add_info->name_sensor, 0, sizeof(add_info->name_sensor)); + strncpy(add_info->name_sensor, nsensor, strlen(nsensor)); + + msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf); + + /*If we need to send this structure to other machine, we need to pass + the integer inside the structure to internet format (big endian)*/ + msgb_tl16v_put(msg, NM_ATT_ADD_INFO, + sizeof(struct sbts2050_config_info), + (const uint8_t *)add_info); + + add_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0) { + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); + close(fd_unix); + msgb_free(msg); + return 0; + } + + msgb_free(msg); + return 1; +err: + msgb_free(msg); + return -1; +} + +/********************************************************************** * Functions read/write from serial interface *********************************************************************/ static int hand_serial_read(int fd, struct msgb *msg, int numbytes) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index 01878f2..b19606e 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -32,6 +32,34 @@ struct ucinfo { int pa; }; +enum sbts2050_alert_lvl { + SBTS2050_WARN_ALERT, + SBTS2050_SEVER_ALERT +}; + +enum sbts2050_temp_sensor { + SBTS2050_TEMP_BOARD, + SBTS2050_TEMP_PA +}; + +struct sbts2050_config_info { + char name_sensor[8]; + int temp_max_pa_warn_limit; + int temp_min_pa_warn_limit; + int temp_max_pa_sever_limit; + int temp_min_pa_sever_limit; + int temp_max_board_warn_limit; + int temp_min_board_warn_limit; + int temp_max_board_sever_limit; + int temp_min_board_sever_limit; + int pa_power; + int slave_power_act; + int master_power_act; + int pa_power_act; + int temp_pa_cur; + int temp_board_cur; +}; + int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, enum sysmobts_temp_type type); @@ -43,6 +71,11 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa); int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status); +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr); + int sysmobts_update_hours(int no_epprom_write); enum sysmobts_firmware_type { -- 1.7.10.4 From anayuso at sysmocom.de Wed Apr 2 11:36:57 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Wed, 2 Apr 2014 13:36:57 +0200 Subject: [osmo-bts PATCH v4] src: Add OML support for sending failure message from manager In-Reply-To: <1396432570-24379-1-git-send-email-anayuso@sysmocom.de> References: <1396432570-24379-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1396438617-5911-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso With this patch, the manager monitors the sensors and send OML Failure message from the Manager to the BTS and the BTS to BSC, for having a report system of the sensors. Signed-off-by: Alvaro Neira Ayuso --- v4: Fixed situation that we have a connection opened with the manager and we have other connection with other manager. src/osmo-bts-sysmo/main.c | 73 ++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 77 +++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 140 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 ++++++++ 4 files changed, 322 insertions(+), 1 deletion(-) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..269f442 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -45,8 +46,10 @@ #include #include #include +#include #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" +#define SOCKET_PATH "/var/run/bts_oml" #include "utils.h" #include "eeprom.h" @@ -258,6 +261,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT"); + unlink(SOCKET_PATH); break; case SIGABRT: case SIGUSR1: @@ -288,6 +292,62 @@ static int write_pid_file(char *procname) return 0; } +static int read_sock(struct osmo_fd *fd, unsigned int what) +{ + struct msgb *msg; + struct gsm_abis_mo *mo; + int rc; + + msg = oml_msgb_alloc(); + if (msg == NULL) + return -1; + + rc = recv(fd->fd, msg->tail, msg->data_len, 0); + if (rc <= 0) { + close(fd->fd); + osmo_fd_unregister(fd); + fd->fd = -1; + return -1; + } + + msgb_put(msg, rc); + + /*Remove the IPA header for removing the conflict with the new IPA + * header*/ + msgb_pull(msg, sizeof(struct ipaccess_head *)-1); + + mo = &bts->mo; + msg->trx = mo->bts->c0; + msg->l2h = msg->data; + msg->l3h = msg->data + sizeof(struct abis_om_fom_hdr); + + return abis_oml_sendmsg(msg); +} + +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *ofd = (struct osmo_fd *)fd->data; + + if (ofd->fd > -1) { + close(ofd->fd); + osmo_fd_unregister(ofd); + ofd->fd = -1; + } + + cl = accept(sfd, NULL, NULL); + if (cl < 0) + return -1; + + ofd->fd = cl; + if (osmo_fd_register(ofd) != 0) { + close(cl); + return -1; + } + + return 0; +} + int main(int argc, char **argv) { struct stat st; @@ -295,6 +355,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; + struct osmo_fd fd, rfd; int rc; tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -370,6 +431,18 @@ int main(int argc, char **argv) fprintf(stderr, "unable to connect to BSC\n"); exit(1); } + fd.cb = accept_unix_sock; + rfd.cb = read_sock; + rfd.when = BSC_FD_READ; + rfd.fd = -1; + fd.data = &rfd; + + rc = osmo_sock_unix_init_ofd(&fd, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(3); + } if (daemonize) { rc = osmo_daemonize(); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..525e526 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,11 @@ static int no_eeprom_write = 0; static int daemonize = 0; +static int trx_nr = -1; +static int fd_unix = -1; +static int state_connection = 0; void *tall_mgr_ctx; +static struct sbts2050_config_info confinfo; /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -55,7 +60,29 @@ void *tall_mgr_ctx; /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ #define HOURS_TIMER_SECS (1 * 3600) +/* every 5 minutes try to reconnect if we have a problem in the communication*/ +#define CONNECT_TIMER_SECS (300) + +/* unix domain socket file descriptor */ +#define SOCKET_PATH "/var/run/bts_oml" + #ifdef BUILD_SBTS2050 +static struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + if (state_connection == 0) { + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + LOGP(DTEMP, LOGL_ERROR, "Error creating unix socket\n"); + return; + } + + state_connection = 1; + } + osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0); +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +91,50 @@ static void check_uctemp_timer_cb(void *data) sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); + confinfo.temp_pa_cur = temp_pa; + confinfo.temp_board_cur = temp_board; + + if (confinfo.temp_min_pa_warn_limit > temp_pa || + confinfo.temp_max_pa_warn_limit < temp_pa) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_WARN_ALERT, + SBTS2050_TEMP_PA, + &confinfo, trx_nr); + } else if (confinfo.temp_min_pa_sever_limit > temp_pa || + confinfo.temp_max_pa_sever_limit < temp_pa) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_SEVER_ALERT, + SBTS2050_TEMP_PA, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_MASTER), + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_SLAVE), + confinfo.pa_power_act); + } + + if (confinfo.temp_min_board_warn_limit > temp_board || + confinfo.temp_max_board_warn_limit < temp_board) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_WARN_ALERT, + SBTS2050_TEMP_BOARD, + &confinfo, trx_nr); + } else if (confinfo.temp_min_board_sever_limit > temp_board || + confinfo.temp_max_board_sever_limit < temp_board) { + state_connection = sendto_osmobts(fd_unix, ucontrol0, + SBTS2050_SEVER_ALERT, + SBTS2050_TEMP_BOARD, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + sbts2050_uc_status(ucontrol0, + SBTS2050_STATUS_PA)); + } + + if (state_connection == 0) + close(fd_unix); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +164,7 @@ static void initialize_sbts2050(void) if (val != 0) return; } + trx_nr = val; ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); if (ucontrol0.fd < 0) { @@ -169,6 +241,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write); + close(fd_unix); exit(0); break; case SIGABRT: @@ -363,6 +436,10 @@ int main(int argc, char **argv) hours_timer.cb = hours_timer_cb; hours_timer_cb(NULL); + /*start handle for reconnect the socket in case of error*/ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + /* start uc temperature check timer */ initialize_sbts2050(); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..0e89da6 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c @@ -29,13 +29,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include +#include #include "btsconfig.h" #include "sysmobts_misc.h" @@ -49,10 +53,144 @@ #define SERIAL_ALLOC_SIZE 300 #define SIZE_HEADER_RSP 5 #define SIZE_HEADER_CMD 4 - +#define OM_ALLOC_SIZE 1024 +#define OM_HEADROOM_SIZE 128 +#define IPA_OML_PROTO 0xFF #ifdef BUILD_SBTS2050 /********************************************************************** + * Function send information to OsmoBts + *********************************************************************/ +static void add_sw_descr(struct msgb *msg) +{ + char file_version[255]; + char file_id[255]; + + strcpy(file_id, "sysmomgr"); + strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)); + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), + (uint8_t *)file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), + (uint8_t *)file_version); +} + +static void add_probable_cause(struct msgb *msg) +{ + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); + msgb_v_put(msg, 0); + msgb_v_put(msg, 0); +} + +static void add_ipa_header(struct msgb *msg) +{ + struct ipaccess_head *hh; + + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); + hh->proto = IPA_OML_PROTO; + hh->len = htons(msg->len); +} + +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, + uint8_t obj_class, uint8_t bts_nr, + uint8_t trx_nr, uint8_t ts_nr) +{ + struct abis_om_fom_hdr *foh; + struct abis_om_hdr *omh; + + msg->l3h = msgb_push(msg, sizeof(*foh)); + foh = (struct abis_om_fom_hdr *) msg->l3h; + + foh->msg_type = msg_type; + foh->obj_class = obj_class; + foh->obj_inst.bts_nr = bts_nr; + foh->obj_inst.trx_nr = trx_nr; + foh->obj_inst.ts_nr = ts_nr; + + msg->l2h = msgb_push(msg, sizeof(*omh)); + omh = (struct abis_om_hdr *) msg->l2h; + + omh->mdisc = ABIS_OM_MDISC_FOM; + omh->placement = ABIS_OM_PLACEMENT_ONLY; + omh->sequence = 0; + omh->length = msgb_l3len(msg); +} + +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr) +{ + int rc; + struct msgb *msg; + const char *buf, *nsensor; + + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); + if (msg == NULL) { + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); + goto err; + } + + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0); + + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); + + switch (alert) { + case SBTS2050_WARN_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); + break; + case SBTS2050_SEVER_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); + break; + default: + goto err; + } + + add_probable_cause(msg); + + add_sw_descr(msg); + + switch (sensor) { + case SBTS2050_TEMP_BOARD: + buf = "Unusual temperature on the Board"; + nsensor = "Board"; + break; + case SBTS2050_TEMP_PA: + buf = "Unusual temperature on the PA"; + nsensor = "PA"; + break; + default: + return -1; + } + memset(add_info->name_sensor, 0, sizeof(add_info->name_sensor)); + strncpy(add_info->name_sensor, nsensor, strlen(nsensor)); + + msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf); + + /*If we need to send this structure to other machine, we need to pass + the integer inside the structure to internet format (big endian)*/ + msgb_tl16v_put(msg, NM_ATT_ADD_INFO, + sizeof(struct sbts2050_config_info), + (const uint8_t *)add_info); + + add_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0) { + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); + close(fd_unix); + msgb_free(msg); + return 0; + } + + msgb_free(msg); + return 1; +err: + msgb_free(msg); + return -1; +} + +/********************************************************************** * Functions read/write from serial interface *********************************************************************/ static int hand_serial_read(int fd, struct msgb *msg, int numbytes) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index 01878f2..b19606e 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -32,6 +32,34 @@ struct ucinfo { int pa; }; +enum sbts2050_alert_lvl { + SBTS2050_WARN_ALERT, + SBTS2050_SEVER_ALERT +}; + +enum sbts2050_temp_sensor { + SBTS2050_TEMP_BOARD, + SBTS2050_TEMP_PA +}; + +struct sbts2050_config_info { + char name_sensor[8]; + int temp_max_pa_warn_limit; + int temp_min_pa_warn_limit; + int temp_max_pa_sever_limit; + int temp_min_pa_sever_limit; + int temp_max_board_warn_limit; + int temp_min_board_warn_limit; + int temp_max_board_sever_limit; + int temp_min_board_sever_limit; + int pa_power; + int slave_power_act; + int master_power_act; + int pa_power_act; + int temp_pa_cur; + int temp_board_cur; +}; + int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, enum sysmobts_temp_type type); @@ -43,6 +71,11 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa); int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status); +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr); + int sysmobts_update_hours(int no_epprom_write); enum sysmobts_firmware_type { -- 1.7.10.4 From pablo at gnumonks.org Sat Apr 5 17:12:04 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Sat, 5 Apr 2014 19:12:04 +0200 Subject: [osmo-bts PATCH v4] src: Add OML support for sending failure message from manager In-Reply-To: <1396438617-5911-1-git-send-email-anayuso@sysmocom.de> References: <1396432570-24379-1-git-send-email-anayuso@sysmocom.de> <1396438617-5911-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140405171204.GA5174@localhost> Hi Alvaro, A couple of comments below. On Wed, Apr 02, 2014 at 01:36:57PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > > With this patch, the manager monitors the sensors and send > OML Failure message from the Manager to the BTS and the BTS > to BSC, for having a report system of the sensors. > > Signed-off-by: Alvaro Neira Ayuso > --- > v4: Fixed situation that we have a connection opened with the manager and we > have other connection with other manager. > > src/osmo-bts-sysmo/main.c | 73 ++++++++++++++++ > src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 77 +++++++++++++++++ > src/osmo-bts-sysmo/misc/sysmobts_misc.c | 140 ++++++++++++++++++++++++++++++- > src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 ++++++++ > 4 files changed, 322 insertions(+), 1 deletion(-) > > diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c > index 74ee47f..269f442 100644 > --- a/src/osmo-bts-sysmo/main.c > +++ b/src/osmo-bts-sysmo/main.c > @@ -35,6 +35,7 @@ > > #include > #include > +#include > #include > #include > > @@ -45,8 +46,10 @@ > #include > #include > #include > +#include > > #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" > +#define SOCKET_PATH "/var/run/bts_oml" > > #include "utils.h" > #include "eeprom.h" > @@ -258,6 +261,7 @@ static void signal_handler(int signal) > case SIGINT: > //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); > bts_shutdown(bts, "SIGINT"); > + unlink(SOCKET_PATH); > break; > case SIGABRT: > case SIGUSR1: > @@ -288,6 +292,62 @@ static int write_pid_file(char *procname) > return 0; > } > > +static int read_sock(struct osmo_fd *fd, unsigned int what) > +{ > + struct msgb *msg; > + struct gsm_abis_mo *mo; > + int rc; > + > + msg = oml_msgb_alloc(); > + if (msg == NULL) > + return -1; > + > + rc = recv(fd->fd, msg->tail, msg->data_len, 0); > + if (rc <= 0) { > + close(fd->fd); > + osmo_fd_unregister(fd); > + fd->fd = -1; > + return -1; > + } > + > + msgb_put(msg, rc); > + > + /*Remove the IPA header for removing the conflict with the new IPA > + * header*/ > + msgb_pull(msg, sizeof(struct ipaccess_head *)-1); > + > + mo = &bts->mo; > + msg->trx = mo->bts->c0; > + msg->l2h = msg->data; > + msg->l3h = msg->data + sizeof(struct abis_om_fom_hdr); > + > + return abis_oml_sendmsg(msg); > +} > + > +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) > +{ > + int sfd = fd->fd, cl; > + struct osmo_fd *ofd = (struct osmo_fd *)fd->data; > + > + if (ofd->fd > -1) { > + close(ofd->fd); > + osmo_fd_unregister(ofd); > + ofd->fd = -1; > + } > + > + cl = accept(sfd, NULL, NULL); > + if (cl < 0) > + return -1; > + > + ofd->fd = cl; > + if (osmo_fd_register(ofd) != 0) { > + close(cl); > + return -1; > + } > + > + return 0; > +} > + > int main(int argc, char **argv) > { > struct stat st; > @@ -295,6 +355,7 @@ int main(int argc, char **argv) > struct gsm_bts_role_bts *btsb; > struct e1inp_line *line; > void *tall_msgb_ctx; > + struct osmo_fd fd, rfd; Perhaps you can rename fd and rfd to something a bit more descriptive, eg. accept_ofd and ofd. > int rc; > > tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); > @@ -370,6 +431,18 @@ int main(int argc, char **argv) > fprintf(stderr, "unable to connect to BSC\n"); > exit(1); > } > + fd.cb = accept_unix_sock; > + rfd.cb = read_sock; > + rfd.when = BSC_FD_READ; > + rfd.fd = -1; > + fd.data = &rfd; > + > + rc = osmo_sock_unix_init_ofd(&fd, SOCK_SEQPACKET, 0, SOCKET_PATH, > + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); > + if (rc < 0) { > + perror("Error creating socket domain creation"); > + exit(3); > + } > > if (daemonize) { > rc = osmo_daemonize(); > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > index 6c64d0f..525e526 100644 > --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > @@ -36,6 +36,7 @@ > #include > #include > #include > +#include > #include > #include > > @@ -47,7 +48,11 @@ > > static int no_eeprom_write = 0; > static int daemonize = 0; > +static int trx_nr = -1; > +static int fd_unix = -1; > +static int state_connection = 0; Please, use some enum for this small state machine, eg. enum { SYSMO_MGR_DISCONNECTED = 0, SYSMO_MGR_CONNECTED, }; It should help to make the code a bit more readable. > void *tall_mgr_ctx; > +static struct sbts2050_config_info confinfo; > > /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ > #define TEMP_TIMER_SECS (6 * 3600) > @@ -55,7 +60,29 @@ void *tall_mgr_ctx; > /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ > #define HOURS_TIMER_SECS (1 * 3600) > > +/* every 5 minutes try to reconnect if we have a problem in the communication*/ > +#define CONNECT_TIMER_SECS (300) ^ ^ You can remove those parenthesis. > + > +/* unix domain socket file descriptor */ > +#define SOCKET_PATH "/var/run/bts_oml" > + > #ifdef BUILD_SBTS2050 > +static struct osmo_timer_list connect_timer; > +static void socket_connect_cb(void *data) > +{ > + if (state_connection == 0) { > + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, > + OSMO_SOCK_F_CONNECT); > + if (fd_unix < 0) { > + LOGP(DTEMP, LOGL_ERROR, "Error creating unix socket\n"); > + return; > + } > + > + state_connection = 1; > + } > + osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0); This timer keeps running even if we're connected. I think you should enable it only if we are in disconnected state. > +} > + > static struct osmo_timer_list temp_uc_timer; > static void check_uctemp_timer_cb(void *data) > { > @@ -64,6 +91,50 @@ static void check_uctemp_timer_cb(void *data) > > sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); > > + confinfo.temp_pa_cur = temp_pa; > + confinfo.temp_board_cur = temp_board; > + > + if (confinfo.temp_min_pa_warn_limit > temp_pa || > + confinfo.temp_max_pa_warn_limit < temp_pa) { Should this be >= and <= ? > + state_connection = sendto_osmobts(fd_unix, ucontrol0, > + SBTS2050_WARN_ALERT, > + SBTS2050_TEMP_PA, > + &confinfo, trx_nr); > + } else if (confinfo.temp_min_pa_sever_limit > temp_pa || > + confinfo.temp_max_pa_sever_limit < temp_pa) { Same here. > + state_connection = sendto_osmobts(fd_unix, ucontrol0, > + SBTS2050_SEVER_ALERT, > + SBTS2050_TEMP_PA, > + &confinfo, trx_nr); > + sbts2050_uc_power(ucontrol0, > + sbts2050_uc_status(ucontrol0, > + SBTS2050_STATUS_MASTER), > + sbts2050_uc_status(ucontrol0, > + SBTS2050_STATUS_SLAVE), > + confinfo.pa_power_act); > + } > + > + if (confinfo.temp_min_board_warn_limit > temp_board || > + confinfo.temp_max_board_warn_limit < temp_board) { > + state_connection = sendto_osmobts(fd_unix, ucontrol0, > + SBTS2050_WARN_ALERT, > + SBTS2050_TEMP_BOARD, > + &confinfo, trx_nr); This code looks very similar, perhaps you can encapsulate it in a function, ie. check_temperature(confinfo.temp_min_board_warn_limit, confinfo.temp_max_board_warn_limit, temp_board, SBTS2050_TEMP_BOARD); > + } else if (confinfo.temp_min_board_sever_limit > temp_board || > + confinfo.temp_max_board_sever_limit < temp_board) { > + state_connection = sendto_osmobts(fd_unix, ucontrol0, > + SBTS2050_SEVER_ALERT, > + SBTS2050_TEMP_BOARD, > + &confinfo, trx_nr); > + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, > + confinfo.slave_power_act, > + sbts2050_uc_status(ucontrol0, > + SBTS2050_STATUS_PA)); > + } > + > + if (state_connection == 0) > + close(fd_unix); > + > osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); > } > #endif > @@ -93,6 +164,7 @@ static void initialize_sbts2050(void) > if (val != 0) > return; > } > + trx_nr = val; > > ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); > if (ucontrol0.fd < 0) { > @@ -169,6 +241,7 @@ static void signal_handler(int signal) > case SIGINT: > sysmobts_check_temp(no_eeprom_write); > sysmobts_update_hours(no_eeprom_write); > + close(fd_unix); > exit(0); > break; > case SIGABRT: > @@ -363,6 +436,10 @@ int main(int argc, char **argv) > hours_timer.cb = hours_timer_cb; > hours_timer_cb(NULL); > > + /*start handle for reconnect the socket in case of error*/ ^ ^ Missing spaces. /* Start handle ... */ > + connect_timer.cb = socket_connect_cb; > + socket_connect_cb(NULL); > + > /* start uc temperature check timer */ > initialize_sbts2050(); > > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c > index 9ea26c2..0e89da6 100644 > --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c > +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c > @@ -29,13 +29,17 @@ > #include > #include > #include > +#include > > #include > #include > #include > +#include > #include > #include > #include > +#include > +#include > > #include "btsconfig.h" > #include "sysmobts_misc.h" > @@ -49,10 +53,144 @@ > #define SERIAL_ALLOC_SIZE 300 > #define SIZE_HEADER_RSP 5 > #define SIZE_HEADER_CMD 4 > - > +#define OM_ALLOC_SIZE 1024 > +#define OM_HEADROOM_SIZE 128 > +#define IPA_OML_PROTO 0xFF > > #ifdef BUILD_SBTS2050 > /********************************************************************** > + * Function send information to OsmoBts > + *********************************************************************/ > +static void add_sw_descr(struct msgb *msg) > +{ > + char file_version[255]; > + char file_id[255]; > + > + strcpy(file_id, "sysmomgr"); Better use strncpy here. > + strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)); And make sure you nul-terminate these strings. file_version[strlen(PACKAGE_VERSION)-1] = '\0'; As strncpy doesn't append the \0. I remember you couldn't use strlcpy, right? > + msgb_v_put(msg, NM_ATT_SW_DESCR); > + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), > + (uint8_t *)file_id); Coding style nitpick, perhaps: msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), (uint8_t *)file_id); From jerlbeck at sysmocom.de Mon Apr 7 07:34:10 2014 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Mon, 07 Apr 2014 09:34:10 +0200 Subject: [osmo-bts PATCH v4] src: Add OML support for sending failure message from manager In-Reply-To: <20140405171204.GA5174@localhost> References: <1396432570-24379-1-git-send-email-anayuso@sysmocom.de> <1396438617-5911-1-git-send-email-anayuso@sysmocom.de> <20140405171204.GA5174@localhost> Message-ID: <534254F2.7000005@sysmocom.de> Hi On 05.04.2014 19:12, Pablo Neira Ayuso wrote: > On Wed, Apr 02, 2014 at 01:36:57PM +0200, Alvaro Neira Ayuso wrote: >> From: ?lvaro Neira Ayuso >> >> diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c >> index 9ea26c2..0e89da6 100644 >> --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c >> +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc. >> @@ -49,10 +53,144 @@ >> #define SERIAL_ALLOC_SIZE 300 >> #define SIZE_HEADER_RSP 5 >> #define SIZE_HEADER_CMD 4 >> - >> +#define OM_ALLOC_SIZE 1024 >> +#define OM_HEADROOM_SIZE 128 >> +#define IPA_OML_PROTO 0xFF >> >> #ifdef BUILD_SBTS2050 >> /********************************************************************** >> + * Function send information to OsmoBts >> + *********************************************************************/ >> +static void add_sw_descr(struct msgb *msg) >> +{ >> + char file_version[255]; >> + char file_id[255]; >> + >> + strcpy(file_id, "sysmomgr"); > > Better use strncpy here. > >> + strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)); > > And make sure you nul-terminate these strings. > > file_version[strlen(PACKAGE_VERSION)-1] = '\0'; This just the same like strcpy(file_version, PACKAGE_VERSION). I'd rather expect strncpy(file_version, PACKAGE_VERSION, sizeof(file_version)); file_version[sizeof(file_version)-1] = '\0'; > > As strncpy doesn't append the \0. Jacob -- - Jacob Erlbeck http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Schivelbeiner Str. 5 * 10439 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From pablo at gnumonks.org Mon Apr 7 09:31:51 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Mon, 7 Apr 2014 11:31:51 +0200 Subject: [osmo-bts PATCH v4] src: Add OML support for sending failure message from manager In-Reply-To: <534254F2.7000005@sysmocom.de> References: <1396432570-24379-1-git-send-email-anayuso@sysmocom.de> <1396438617-5911-1-git-send-email-anayuso@sysmocom.de> <20140405171204.GA5174@localhost> <534254F2.7000005@sysmocom.de> Message-ID: <20140407093151.GA10314@localhost> On Mon, Apr 07, 2014 at 09:34:10AM +0200, Jacob Erlbeck wrote: > Hi > > On 05.04.2014 19:12, Pablo Neira Ayuso wrote: > > On Wed, Apr 02, 2014 at 01:36:57PM +0200, Alvaro Neira Ayuso wrote: > >> From: ?lvaro Neira Ayuso > >> > > >> diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c > >> index 9ea26c2..0e89da6 100644 > >> --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c > >> +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc. > >> @@ -49,10 +53,144 @@ > >> #define SERIAL_ALLOC_SIZE 300 > >> #define SIZE_HEADER_RSP 5 > >> #define SIZE_HEADER_CMD 4 > >> - > >> +#define OM_ALLOC_SIZE 1024 > >> +#define OM_HEADROOM_SIZE 128 > >> +#define IPA_OML_PROTO 0xFF > >> > >> #ifdef BUILD_SBTS2050 > >> /********************************************************************** > >> + * Function send information to OsmoBts > >> + *********************************************************************/ > >> +static void add_sw_descr(struct msgb *msg) > >> +{ > >> + char file_version[255]; > >> + char file_id[255]; > >> + > >> + strcpy(file_id, "sysmomgr"); > > > > Better use strncpy here. > > > >> + strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)); > > > > And make sure you nul-terminate these strings. > > > > file_version[strlen(PACKAGE_VERSION)-1] = '\0'; > > This just the same like strcpy(file_version, PACKAGE_VERSION). > > I'd rather expect > > strncpy(file_version, PACKAGE_VERSION, sizeof(file_version)); Ah I see, you mean the sizeof(...) instead strlen(...). I didn't notice. Indeed, that needs to be fixed Alvaro, thanks for spotting it :). > file_version[sizeof(file_version)-1] = '\0'; > > > > > As strncpy doesn't append the \0. From alvaroneay at gmail.com Tue Apr 8 12:43:17 2014 From: alvaroneay at gmail.com (=?ISO-8859-1?Q?=C1lvaro_Neira_Ayuso?=) Date: Tue, 08 Apr 2014 14:43:17 +0200 Subject: [osmo-bts PATCH v4] src: Add OML support for sending failure message from manager In-Reply-To: <534254F2.7000005@sysmocom.de> References: <1396432570-24379-1-git-send-email-anayuso@sysmocom.de> <1396438617-5911-1-git-send-email-anayuso@sysmocom.de> <20140405171204.GA5174@localhost> <534254F2.7000005@sysmocom.de> Message-ID: <5343EEE5.6030405@gmail.com> El 07/04/14 09:34, Jacob Erlbeck escribi?: > Hi > > On 05.04.2014 19:12, Pablo Neira Ayuso wrote: >> On Wed, Apr 02, 2014 at 01:36:57PM +0200, Alvaro Neira Ayuso wrote: >>> From: ?lvaro Neira Ayuso >>> > >>> diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c >>> index 9ea26c2..0e89da6 100644 >>> --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c >>> +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc. >>> @@ -49,10 +53,144 @@ >>> #define SERIAL_ALLOC_SIZE 300 >>> #define SIZE_HEADER_RSP 5 >>> #define SIZE_HEADER_CMD 4 >>> - >>> +#define OM_ALLOC_SIZE 1024 >>> +#define OM_HEADROOM_SIZE 128 >>> +#define IPA_OML_PROTO 0xFF >>> >>> #ifdef BUILD_SBTS2050 >>> /********************************************************************** >>> + * Function send information to OsmoBts >>> + *********************************************************************/ >>> +static void add_sw_descr(struct msgb *msg) >>> +{ >>> + char file_version[255]; >>> + char file_id[255]; >>> + >>> + strcpy(file_id, "sysmomgr"); >> >> Better use strncpy here. >> >>> + strncpy(file_version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)); >> >> And make sure you nul-terminate these strings. >> >> file_version[strlen(PACKAGE_VERSION)-1] = '\0'; > > This just the same like strcpy(file_version, PACKAGE_VERSION). > > I'd rather expect > > strncpy(file_version, PACKAGE_VERSION, sizeof(file_version)); > file_version[sizeof(file_version)-1] = '\0'; > >> >> As strncpy doesn't append the \0. Sorry for don't answering the email before, but I have preferred answer you after send another version. Thanks a lot Pablo and Jacob, I have applied yours corrections in my new patch. From anayuso at sysmocom.de Tue Apr 8 12:31:33 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Tue, 8 Apr 2014 14:31:33 +0200 Subject: [osmo-bts PATCH 1/3 v5] src: Add OML support for sending failure message from manager In-Reply-To: <1396438617-5911-1-git-send-email-anayuso@sysmocom.de> References: <1396438617-5911-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1396960294-13943-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso With this patch, the manager monitors the sensors and send OML Failure message from the Manager to the BTS and the BTS to BSC, for having a report system of the sensors. Signed-off-by: Alvaro Neira Ayuso --- v5: Changed the osmo_fd name variables for using anothers more clear. Used enum for declaring states in the connections. Refactored some code for doing some functions for having a code more short and clear. Changed the function connect for only using the timer in the case that the socket is disconnected. Changed some fails when i have used strncpy. And changed some coding style fails. src/osmo-bts-sysmo/main.c | 115 +++++++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 90 ++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 142 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 +++++++ 4 files changed, 379 insertions(+), 1 deletion(-) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..61a5716 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,8 +35,10 @@ #include #include +#include #include #include +#include #include #include @@ -45,13 +47,19 @@ #include #include #include +#include #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" +#define SOCKET_PATH "/var/run/bts_oml" + +#define IPA_HEADER_SIZE 3 +#define IPA_OML_PROTO 0xFF #include "utils.h" #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" +#include "btsconfig.h" /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -258,6 +266,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT"); + unlink(SOCKET_PATH); break; case SIGABRT: case SIGUSR1: @@ -287,6 +296,95 @@ static int write_pid_file(char *procname) return 0; } +#ifdef BUILD_SBTS2050 +static int test_recv_msg(struct msgb *msg) +{ + struct ipaccess_head *hh = (struct ipaccess_head *)msg->data; + struct abis_om_hdr *omh; + + if (hh->proto != IPA_OML_PROTO) + return -1; + + if (ntohs(hh->len) != msg->len) + return -1; + + msgb_pull(msg, IPA_HEADER_SIZE); + + msg->l2h = msg->data; + msg->l3h = msg->data + sizeof(struct abis_om_hdr); + + omh = (struct abis_om_hdr *) msg->l2h; + + if (omh->mdisc != ABIS_OM_MDISC_FOM) + return -1; + + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) + return -1; + + if (omh->sequence != 0) + return -1; + + if (omh->length != sizeof(struct abis_om_fom_hdr)) + return -1; + + return 0; +} + +static int read_sock(struct osmo_fd *fd, unsigned int what) +{ + struct msgb *msg; + struct gsm_abis_mo *mo; + int rc; + + msg = oml_msgb_alloc(); + if (msg == NULL) + return -1; + + rc = recv(fd->fd, msg->tail, msg->data_len, 0); + if (rc <= 0) { + close(fd->fd); + osmo_fd_unregister(fd); + fd->fd = -1; + return -1; + } + + msgb_put(msg, rc); + + if (test_recv_msg(msg) < 0) { + LOGP(DL1C, LOGL_NOTICE, "Failed: Malformed receive message"); + return -1; + } + + mo = &bts->mo; + msg->trx = mo->bts->c0; + + return abis_oml_sendmsg(msg); +} + +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *read_fd = (struct osmo_fd *)fd->data; + + if (read_fd->fd > -1) { + close(read_fd->fd); + osmo_fd_unregister(read_fd); + read_fd->fd = -1; + } + + cl = accept(sfd, NULL, NULL); + if (cl < 0) + return -1; + + read_fd->fd = cl; + if (osmo_fd_register(read_fd) != 0) { + close(cl); + return -1; + } + + return 0; +} +#endif int main(int argc, char **argv) { @@ -295,6 +393,9 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; +#ifdef BUILD_SBTS2050 + struct osmo_fd accept_fd, read_fd; +#endif int rc; tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -370,6 +471,20 @@ int main(int argc, char **argv) fprintf(stderr, "unable to connect to BSC\n"); exit(1); } +#ifdef BUILD_SBTS2050 + accept_fd.cb = accept_unix_sock; + read_fd.cb = read_sock; + read_fd.when = BSC_FD_READ; + read_fd.fd = -1; + accept_fd.data = &read_fd; + + rc = osmo_sock_unix_init_ofd(&accept_fd, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(3); + } +#endif if (daemonize) { rc = osmo_daemonize(); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..b8813f0 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -45,9 +46,16 @@ #include "misc/sysmobts_nl.h" #include "misc/sysmobts_par.h" +enum { + SYSMO_MGR_DISCONNECTED = 0, + SYSMO_MGR_CONNECTED, +}; + static int no_eeprom_write = 0; static int daemonize = 0; +static int fd_unix = -1; void *tall_mgr_ctx; +static struct sbts2050_config_info confinfo; /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -55,7 +63,63 @@ void *tall_mgr_ctx; /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ #define HOURS_TIMER_SECS (1 * 3600) +/* every 5 minutes try to reconnect if we have a problem in the communication*/ +#define CONNECT_TIMER_SECS 300 + +/* unix domain socket file descriptor */ +#define SOCKET_PATH "/var/run/bts_oml" + #ifdef BUILD_SBTS2050 +static int trx_nr = -1; +static int state_connection = 0; + +static struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + if (state_connection == SYSMO_MGR_DISCONNECTED) { + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + osmo_timer_schedule(&connect_timer, + CONNECT_TIMER_SECS, 0); + return; + } + + state_connection = SYSMO_MGR_CONNECTED; + } +} + +static void check_temperature(struct uc *ucontrol0, int downlimit, int uplimit, + int current_temp, + enum sbts2050_temp_sensor sensor, + enum sbts2050_alert_lvl alert) +{ + int rc; + + if (downlimit >= current_temp || uplimit <= current_temp) { + switch (alert) { + case SBTS2050_WARN_ALERT: + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, + &confinfo, trx_nr); + break; + case SBTS2050_SEVER_ALERT: + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + confinfo.pa_power_act); + break; + } + } + + state_connection = rc; + + if (state_connection == SYSMO_MGR_DISCONNECTED) { + close(fd_unix); + socket_connect_cb(NULL); + } +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +128,26 @@ static void check_uctemp_timer_cb(void *data) sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); + confinfo.temp_pa_cur = temp_pa; + confinfo.temp_board_cur = temp_board; + + check_temperature(ucontrol0, confinfo.temp_min_pa_warn_limit, + confinfo.temp_max_pa_warn_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_pa_sever_limit, + confinfo.temp_max_pa_sever_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVER_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_warn_limit, + confinfo.temp_max_board_warn_limit, + temp_board, SBTS2050_TEMP_BOARD, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_sever_limit, + confinfo.temp_min_board_sever_limit, + temp_board, SBTS2050_TEMP_BOARD, + SBTS2050_SEVER_ALERT); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +177,7 @@ static void initialize_sbts2050(void) if (val != 0) return; } + trx_nr = val; ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); if (ucontrol0.fd < 0) { @@ -101,6 +186,10 @@ static void initialize_sbts2050(void) return; } + /* start handle for reconnect the socket in case of error */ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + temp_uc_timer.cb = check_uctemp_timer_cb; temp_uc_timer.data = &ucontrol0; check_uctemp_timer_cb(&ucontrol0); @@ -169,6 +258,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write); + close(fd_unix); exit(0); break; case SIGABRT: diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..20f7ea7 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c @@ -29,13 +29,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include +#include #include "btsconfig.h" #include "sysmobts_misc.h" @@ -49,10 +53,146 @@ #define SERIAL_ALLOC_SIZE 300 #define SIZE_HEADER_RSP 5 #define SIZE_HEADER_CMD 4 - +#define OM_ALLOC_SIZE 1024 +#define OM_HEADROOM_SIZE 128 +#define IPA_OML_PROTO 0xFF #ifdef BUILD_SBTS2050 /********************************************************************** + * Function send information to OsmoBts + *********************************************************************/ +static void add_sw_descr(struct msgb *msg) +{ + char file_version[255]; + char file_id[255]; + + strncpy(file_id, "sysmomgr", sizeof("sysmomgr")); + file_id[sizeof(file_id)-1] = '\0'; + strncpy(file_version, PACKAGE_VERSION, sizeof(PACKAGE_VERSION)); + file_version[sizeof(file_version)-1] = '\0'; + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), + (uint8_t *)file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), + (uint8_t *)file_version); +} + +static void add_probable_cause(struct msgb *msg) +{ + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); + msgb_v_put(msg, 0); + msgb_v_put(msg, 0); +} + +static void add_ipa_header(struct msgb *msg) +{ + struct ipaccess_head *hh; + + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); + hh->proto = IPA_OML_PROTO; + hh->len = htons(msg->len); +} + +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, + uint8_t obj_class, uint8_t bts_nr, + uint8_t trx_nr, uint8_t ts_nr) +{ + struct abis_om_fom_hdr *foh; + struct abis_om_hdr *omh; + + msg->l3h = msgb_push(msg, sizeof(*foh)); + foh = (struct abis_om_fom_hdr *) msg->l3h; + + foh->msg_type = msg_type; + foh->obj_class = obj_class; + foh->obj_inst.bts_nr = bts_nr; + foh->obj_inst.trx_nr = trx_nr; + foh->obj_inst.ts_nr = ts_nr; + + msg->l2h = msgb_push(msg, sizeof(*omh)); + omh = (struct abis_om_hdr *) msg->l2h; + + omh->mdisc = ABIS_OM_MDISC_FOM; + omh->placement = ABIS_OM_PLACEMENT_ONLY; + omh->sequence = 0; + omh->length = msgb_l3len(msg); +} + +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr) +{ + int rc; + struct msgb *msg; + const char *buf, *nsensor; + + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); + if (msg == NULL) { + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); + goto err; + } + + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0); + + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); + + switch (alert) { + case SBTS2050_WARN_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); + break; + case SBTS2050_SEVER_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); + break; + default: + goto err; + } + + add_probable_cause(msg); + + add_sw_descr(msg); + + switch (sensor) { + case SBTS2050_TEMP_BOARD: + buf = "Unusual temperature on the Board"; + nsensor = "Board"; + break; + case SBTS2050_TEMP_PA: + buf = "Unusual temperature on the PA"; + nsensor = "PA"; + break; + default: + return -1; + } + memset(add_info->name_sensor, 0, sizeof(add_info->name_sensor)); + strncpy(add_info->name_sensor, nsensor, strlen(nsensor)); + + msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf); + + /*If we need to send this structure to other machine, we need to pass + the integer inside the structure to internet format (big endian)*/ + msgb_tl16v_put(msg, NM_ATT_ADD_INFO, + sizeof(struct sbts2050_config_info), + (const uint8_t *)add_info); + + add_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0) { + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); + close(fd_unix); + msgb_free(msg); + return 0; + } + + msgb_free(msg); + return 1; +err: + msgb_free(msg); + return -1; +} + +/********************************************************************** * Functions read/write from serial interface *********************************************************************/ static int hand_serial_read(int fd, struct msgb *msg, int numbytes) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index 01878f2..2654348 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -32,6 +32,34 @@ struct ucinfo { int pa; }; +enum sbts2050_alert_lvl { + SBTS2050_WARN_ALERT, + SBTS2050_SEVER_ALERT +}; + +enum sbts2050_temp_sensor { + SBTS2050_TEMP_BOARD, + SBTS2050_TEMP_PA +}; + +struct sbts2050_config_info { + char name_sensor[8]; + int temp_max_pa_warn_limit; + int temp_min_pa_warn_limit; + int temp_max_pa_sever_limit; + int temp_min_pa_sever_limit; + int temp_max_board_warn_limit; + int temp_min_board_warn_limit; + int temp_max_board_sever_limit; + int temp_min_board_sever_limit; + int max_power_red; + int slave_power_act; + int master_power_act; + int pa_power_act; + int temp_pa_cur; + int temp_board_cur; +}; + int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, enum sysmobts_temp_type type); @@ -43,6 +71,11 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa); int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status); +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr); + int sysmobts_update_hours(int no_epprom_write); enum sysmobts_firmware_type { -- 1.7.10.4 From pablo at gnumonks.org Wed Apr 9 08:34:09 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Wed, 9 Apr 2014 10:34:09 +0200 Subject: [osmo-bts PATCH 1/3 v5] src: Add OML support for sending failure message from manager In-Reply-To: <1396960294-13943-1-git-send-email-anayuso@sysmocom.de> References: <1396438617-5911-1-git-send-email-anayuso@sysmocom.de> <1396960294-13943-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140409083409.GA5744@localhost> Hi Alvaro, Several comments below. On Tue, Apr 08, 2014 at 02:31:33PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > > With this patch, the manager monitors the sensors and send > OML Failure message from the Manager to the BTS and the BTS > to BSC, for having a report system of the sensors. > > Signed-off-by: Alvaro Neira Ayuso > --- > v5: Changed the osmo_fd name variables for using anothers more clear. Used enum > for declaring states in the connections. Refactored some code for doing some > functions for having a code more short and clear. Changed the function > connect for only using the timer in the case that the socket is disconnected. > Changed some fails when i have used strncpy. And changed some coding style > fails. Please, use a item list next time. It's a bit more readable. > src/osmo-bts-sysmo/main.c | 115 +++++++++++++++++++++++++ > src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 90 ++++++++++++++++++++ > src/osmo-bts-sysmo/misc/sysmobts_misc.c | 142 ++++++++++++++++++++++++++++++- > src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 +++++++ > 4 files changed, 379 insertions(+), 1 deletion(-) > > diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c > index 74ee47f..61a5716 100644 > --- a/src/osmo-bts-sysmo/main.c > +++ b/src/osmo-bts-sysmo/main.c > @@ -35,8 +35,10 @@ > > #include > #include > +#include > #include > #include > +#include > > #include > #include > @@ -45,13 +47,19 @@ > #include > #include > #include > +#include > > #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" > +#define SOCKET_PATH "/var/run/bts_oml" ^^^^^ I can see spaces here, this should be indented with tabs. > + > +#define IPA_HEADER_SIZE 3 Please, better use sizeof(struct ipaccess_head) instead of this constant. > +#define IPA_OML_PROTO 0xFF > > #include "utils.h" > #include "eeprom.h" > #include "l1_if.h" > #include "hw_misc.h" > +#include "btsconfig.h" > > /* FIXME: read from real hardware */ > const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; > @@ -258,6 +266,7 @@ static void signal_handler(int signal) > case SIGINT: > //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); > bts_shutdown(bts, "SIGINT"); > + unlink(SOCKET_PATH); > break; > case SIGABRT: > case SIGUSR1: > @@ -287,6 +296,95 @@ static int write_pid_file(char *procname) > > return 0; > } > +#ifdef BUILD_SBTS2050 > +static int test_recv_msg(struct msgb *msg) > +{ > + struct ipaccess_head *hh = (struct ipaccess_head *)msg->data; > + struct abis_om_hdr *omh; Insufficiente sanity checks here: if (msg->len < sizeof(struct ipaccess_head)) return -1; Now you can safely access the content of the ipa header. hh = (struct ipaccess_head *)msg->data; > + if (hh->proto != IPA_OML_PROTO) > + return -1; > + > + if (ntohs(hh->len) != msg->len) > + return -1; > + > + msgb_pull(msg, IPA_HEADER_SIZE); OK, now you can pull the ipa header. > + > + msg->l2h = msg->data; > + msg->l3h = msg->data + sizeof(struct abis_om_hdr); Now you have to sanity check the abis OM header before you can access it, is there room for this? > + omh = (struct abis_om_hdr *) msg->l2h; > + > + if (omh->mdisc != ABIS_OM_MDISC_FOM) > + return -1; > + > + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) > + return -1; > + > + if (omh->sequence != 0) > + return -1; > + > + if (omh->length != sizeof(struct abis_om_fom_hdr)) > + return -1; Use logging to inform about malformed messages? > + > + return 0; > +} > + > +static int read_sock(struct osmo_fd *fd, unsigned int what) > +{ > + struct msgb *msg; > + struct gsm_abis_mo *mo; > + int rc; > + > + msg = oml_msgb_alloc(); > + if (msg == NULL) > + return -1; > + > + rc = recv(fd->fd, msg->tail, msg->data_len, 0); > + if (rc <= 0) { > + close(fd->fd); > + osmo_fd_unregister(fd); > + fd->fd = -1; You're leaking msg. msgb_free(msg) > + return -1; > + } > + > + msgb_put(msg, rc); > + > + if (test_recv_msg(msg) < 0) { > + LOGP(DL1C, LOGL_NOTICE, "Failed: Malformed receive message"); Same here, please release the msg. > + return -1; > + } > + > + mo = &bts->mo; > + msg->trx = mo->bts->c0; > + > + return abis_oml_sendmsg(msg); > +} > + > +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) > +{ > + int sfd = fd->fd, cl; > + struct osmo_fd *read_fd = (struct osmo_fd *)fd->data; > + > + if (read_fd->fd > -1) { > + close(read_fd->fd); > + osmo_fd_unregister(read_fd); > + read_fd->fd = -1; > + } > + > + cl = accept(sfd, NULL, NULL); > + if (cl < 0) > + return -1; > + > + read_fd->fd = cl; > + if (osmo_fd_register(read_fd) != 0) { > + close(cl); > + return -1; > + } > + > + return 0; > +} > +#endif > > int main(int argc, char **argv) > { > @@ -295,6 +393,9 @@ int main(int argc, char **argv) > struct gsm_bts_role_bts *btsb; > struct e1inp_line *line; > void *tall_msgb_ctx; > +#ifdef BUILD_SBTS2050 > + struct osmo_fd accept_fd, read_fd; > +#endif > int rc; > > tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); > @@ -370,6 +471,20 @@ int main(int argc, char **argv) > fprintf(stderr, "unable to connect to BSC\n"); > exit(1); > } > +#ifdef BUILD_SBTS2050 > + accept_fd.cb = accept_unix_sock; > + read_fd.cb = read_sock; > + read_fd.when = BSC_FD_READ; > + read_fd.fd = -1; > + accept_fd.data = &read_fd; > + > + rc = osmo_sock_unix_init_ofd(&accept_fd, SOCK_SEQPACKET, 0, SOCKET_PATH, > + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); > + if (rc < 0) { > + perror("Error creating socket domain creation"); > + exit(3); > + } > +#endif You can probably encapsulate this in a function: rc = sbts2050_sock_unix_init(...); Then in this function you can do: int sbts2050_sock_unix_init(...) { #ifdef BUILD_SBTS2050 ... #else return 0; #endif } > > if (daemonize) { > rc = osmo_daemonize(); > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > index 6c64d0f..b8813f0 100644 > --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > @@ -36,6 +36,7 @@ > #include > #include > #include > +#include > #include > #include > > @@ -45,9 +46,16 @@ > #include "misc/sysmobts_nl.h" > #include "misc/sysmobts_par.h" > > +enum { > + SYSMO_MGR_DISCONNECTED = 0, > + SYSMO_MGR_CONNECTED, > +}; > + > static int no_eeprom_write = 0; > static int daemonize = 0; > +static int fd_unix = -1; > void *tall_mgr_ctx; > +static struct sbts2050_config_info confinfo; > > /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ > #define TEMP_TIMER_SECS (6 * 3600) > @@ -55,7 +63,63 @@ void *tall_mgr_ctx; > /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ > #define HOURS_TIMER_SECS (1 * 3600) > > +/* every 5 minutes try to reconnect if we have a problem in the communication*/ > +#define CONNECT_TIMER_SECS 300 This is quite a lot, you should retry a bit more often, at least every 30 seconds I'd say. > +/* unix domain socket file descriptor */ > +#define SOCKET_PATH "/var/run/bts_oml" > + > #ifdef BUILD_SBTS2050 > +static int trx_nr = -1; > +static int state_connection = 0; > + > +static struct osmo_timer_list connect_timer; > +static void socket_connect_cb(void *data) > +{ > + if (state_connection == SYSMO_MGR_DISCONNECTED) { Is it possible to run socket_connect_cb in connected state? I don't think so, so you can remove this if branch. > + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, > + OSMO_SOCK_F_CONNECT); > + if (fd_unix < 0) { > + osmo_timer_schedule(&connect_timer, > + CONNECT_TIMER_SECS, 0); > + return; > + } > + > + state_connection = SYSMO_MGR_CONNECTED; > + } > +} > + > +static void check_temperature(struct uc *ucontrol0, int downlimit, int uplimit, > + int current_temp, > + enum sbts2050_temp_sensor sensor, > + enum sbts2050_alert_lvl alert) > +{ > + int rc; > + > + if (downlimit >= current_temp || uplimit <= current_temp) { > + switch (alert) { > + case SBTS2050_WARN_ALERT: > + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, > + &confinfo, trx_nr); > + break; > + case SBTS2050_SEVER_ALERT: > + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, > + &confinfo, trx_nr); > + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, > + confinfo.slave_power_act, > + confinfo.pa_power_act); > + break; > + } > + } > + > + state_connection = rc; > + > + if (state_connection == SYSMO_MGR_DISCONNECTED) { > + close(fd_unix); > + socket_connect_cb(NULL); > + } > +} > + > static struct osmo_timer_list temp_uc_timer; > static void check_uctemp_timer_cb(void *data) > { > @@ -64,6 +128,26 @@ static void check_uctemp_timer_cb(void *data) > > sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); > > + confinfo.temp_pa_cur = temp_pa; > + confinfo.temp_board_cur = temp_board; > + > + check_temperature(ucontrol0, confinfo.temp_min_pa_warn_limit, > + confinfo.temp_max_pa_warn_limit, > + temp_pa, SBTS2050_TEMP_PA, SBTS2050_WARN_ALERT); > + > + check_temperature(ucontrol0, confinfo.temp_min_pa_sever_limit, > + confinfo.temp_max_pa_sever_limit, > + temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVER_ALERT); > + > + check_temperature(ucontrol0, confinfo.temp_min_board_warn_limit, > + confinfo.temp_max_board_warn_limit, > + temp_board, SBTS2050_TEMP_BOARD, SBTS2050_WARN_ALERT); > + > + check_temperature(ucontrol0, confinfo.temp_min_board_sever_limit, > + confinfo.temp_min_board_sever_limit, > + temp_board, SBTS2050_TEMP_BOARD, > + SBTS2050_SEVER_ALERT); > + > osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); > } > #endif > @@ -93,6 +177,7 @@ static void initialize_sbts2050(void) > if (val != 0) > return; > } > + trx_nr = val; > > ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); > if (ucontrol0.fd < 0) { > @@ -101,6 +186,10 @@ static void initialize_sbts2050(void) > return; > } > > + /* start handle for reconnect the socket in case of error */ > + connect_timer.cb = socket_connect_cb; > + socket_connect_cb(NULL); > + > temp_uc_timer.cb = check_uctemp_timer_cb; > temp_uc_timer.data = &ucontrol0; > check_uctemp_timer_cb(&ucontrol0); > @@ -169,6 +258,7 @@ static void signal_handler(int signal) > case SIGINT: > sysmobts_check_temp(no_eeprom_write); > sysmobts_update_hours(no_eeprom_write); > + close(fd_unix); > exit(0); > break; > case SIGABRT: > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c > index 9ea26c2..20f7ea7 100644 > --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c > +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c > @@ -29,13 +29,17 @@ > #include > #include > #include > +#include > > #include > #include > #include > +#include > #include > #include > #include > +#include > +#include > > #include "btsconfig.h" > #include "sysmobts_misc.h" > @@ -49,10 +53,146 @@ > #define SERIAL_ALLOC_SIZE 300 > #define SIZE_HEADER_RSP 5 > #define SIZE_HEADER_CMD 4 > - > +#define OM_ALLOC_SIZE 1024 > +#define OM_HEADROOM_SIZE 128 > +#define IPA_OML_PROTO 0xFF > > #ifdef BUILD_SBTS2050 > /********************************************************************** > + * Function send information to OsmoBts > + *********************************************************************/ > +static void add_sw_descr(struct msgb *msg) > +{ > + char file_version[255]; > + char file_id[255]; > + > + strncpy(file_id, "sysmomgr", sizeof("sysmomgr")); > + file_id[sizeof(file_id)-1] = '\0'; Comestic nitpick, I prefer: file_id[sizeof(file_id) - 1] = '\0'; It's debatable anyway. > + strncpy(file_version, PACKAGE_VERSION, sizeof(PACKAGE_VERSION)); > + file_version[sizeof(file_version)-1] = '\0'; > + msgb_v_put(msg, NM_ATT_SW_DESCR); > + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), > + (uint8_t *)file_id); > + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), > + (uint8_t *)file_version); > +} > + > +static void add_probable_cause(struct msgb *msg) > +{ > + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); > + msgb_v_put(msg, 0); > + msgb_v_put(msg, 0); > +} > + > +static void add_ipa_header(struct msgb *msg) > +{ > + struct ipaccess_head *hh; > + > + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); > + hh->proto = IPA_OML_PROTO; > + hh->len = htons(msg->len); > +} > + > +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, > + uint8_t obj_class, uint8_t bts_nr, > + uint8_t trx_nr, uint8_t ts_nr) > +{ > + struct abis_om_fom_hdr *foh; > + struct abis_om_hdr *omh; > + > + msg->l3h = msgb_push(msg, sizeof(*foh)); > + foh = (struct abis_om_fom_hdr *) msg->l3h; > + > + foh->msg_type = msg_type; > + foh->obj_class = obj_class; > + foh->obj_inst.bts_nr = bts_nr; > + foh->obj_inst.trx_nr = trx_nr; > + foh->obj_inst.ts_nr = ts_nr; > + > + msg->l2h = msgb_push(msg, sizeof(*omh)); > + omh = (struct abis_om_hdr *) msg->l2h; > + > + omh->mdisc = ABIS_OM_MDISC_FOM; > + omh->placement = ABIS_OM_PLACEMENT_ONLY; > + omh->sequence = 0; > + omh->length = msgb_l3len(msg); > +} > + > +int sendto_osmobts(int fd_unix, struct uc *ucontrol, > + enum sbts2050_alert_lvl alert, > + enum sbts2050_temp_sensor sensor, > + struct sbts2050_config_info *add_info, int trx_nr) > +{ > + int rc; > + struct msgb *msg; > + const char *buf, *nsensor; > + > + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); > + if (msg == NULL) { > + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); > + goto err; > + } > + > + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0); > + > + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); > + > + switch (alert) { > + case SBTS2050_WARN_ALERT: > + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); > + break; > + case SBTS2050_SEVER_ALERT: > + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); > + break; > + default: > + goto err; > + } > + > + add_probable_cause(msg); > + > + add_sw_descr(msg); > + > + switch (sensor) { > + case SBTS2050_TEMP_BOARD: > + buf = "Unusual temperature on the Board"; > + nsensor = "Board"; > + break; > + case SBTS2050_TEMP_PA: > + buf = "Unusual temperature on the PA"; > + nsensor = "PA"; > + break; > + default: > + return -1; > + } > + memset(add_info->name_sensor, 0, sizeof(add_info->name_sensor)); You don't need to memset this to zero if you ... > + strncpy(add_info->name_sensor, nsensor, strlen(nsensor)); ^............^ use sizeof up there and nul-terminate this. add_info->name_sensor[sizeof(add_info->name_sensor) - 1] = '\0'; > + > + msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf); > + > + /*If we need to send this structure to other machine, we need to pass > + the integer inside the structure to internet format (big endian)*/ Two comment styles: /* Blah blah blah */ or, for multi-lines comments: /* Blah ... * Blah ... */ That is preferred. > + msgb_tl16v_put(msg, NM_ATT_ADD_INFO, > + sizeof(struct sbts2050_config_info), > + (const uint8_t *)add_info); > + > + add_ipa_header(msg); > + > + rc = send(fd_unix, msg->data, msg->len, 0); > + if (rc < 0) { > + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); > + close(fd_unix); > + msgb_free(msg); > + return 0; > + } > + > + msgb_free(msg); > + return 1; > +err: > + msgb_free(msg); > + return -1; > +} > + > +/********************************************************************** > * Functions read/write from serial interface > *********************************************************************/ > static int hand_serial_read(int fd, struct msgb *msg, int numbytes) > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h > index 01878f2..2654348 100644 > --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h > +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h > @@ -32,6 +32,34 @@ struct ucinfo { > int pa; > }; > > +enum sbts2050_alert_lvl { > + SBTS2050_WARN_ALERT, > + SBTS2050_SEVER_ALERT > +}; > + > +enum sbts2050_temp_sensor { > + SBTS2050_TEMP_BOARD, > + SBTS2050_TEMP_PA > +}; > + > +struct sbts2050_config_info { > + char name_sensor[8]; > + int temp_max_pa_warn_limit; > + int temp_min_pa_warn_limit; > + int temp_max_pa_sever_limit; > + int temp_min_pa_sever_limit; > + int temp_max_board_warn_limit; > + int temp_min_board_warn_limit; > + int temp_max_board_sever_limit; > + int temp_min_board_sever_limit; > + int max_power_red; > + int slave_power_act; > + int master_power_act; > + int pa_power_act; > + int temp_pa_cur; > + int temp_board_cur; > +}; > + > int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, > enum sysmobts_temp_type type); > > @@ -43,6 +71,11 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa); > > int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status); > > +int sendto_osmobts(int fd_unix, struct uc *ucontrol, > + enum sbts2050_alert_lvl alert, > + enum sbts2050_temp_sensor sensor, > + struct sbts2050_config_info *add_info, int trx_nr); > + > int sysmobts_update_hours(int no_epprom_write); > > enum sysmobts_firmware_type { > -- > 1.7.10.4 > > From anayuso at sysmocom.de Thu Apr 10 10:23:47 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Thu, 10 Apr 2014 12:23:47 +0200 Subject: [osmo-bts PATCH 1/3 v6] src: Add OML support for sending failure message from manager In-Reply-To: <1396960294-13943-1-git-send-email-anayuso@sysmocom.de> References: <1396960294-13943-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397125427-28274-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso With this patch, the manager monitors the sensors and send OML Failure message from the Manager to the BTS and the BTS to BSC, for having a report system of the sensors. Signed-off-by: Alvaro Neira Ayuso --- [changes in v6] * Fixed some coding style errors. * Used the function sizeof for removing the constant IPA_HEADER_SIZE. * Checked that the message receive from the unix domain socket connetion isn't malformed and added logging. * Fixed some memory leaks. * Removed the disconnect verification in the function connect. src/osmo-bts-sysmo/main.c | 149 +++++++++++++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 88 ++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 143 ++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 +++++++ 4 files changed, 412 insertions(+), 1 deletion(-) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..7e332ad 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,8 +35,10 @@ #include #include +#include #include #include +#include #include #include @@ -45,13 +47,18 @@ #include #include #include +#include #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" +#define SOCKET_PATH "/var/run/bts_oml" + +#define IPA_OML_PROTO 0xFF #include "utils.h" #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" +#include "btsconfig.h" /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -258,6 +265,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT"); + unlink(SOCKET_PATH); break; case SIGABRT: case SIGUSR1: @@ -288,6 +296,140 @@ static int write_pid_file(char *procname) return 0; } +#ifdef BUILD_SBTS2050 +static int test_recv_msg(struct msgb *msg) +{ + struct ipaccess_head *hh; + struct abis_om_hdr *omh; + + if (msg->len < sizeof(struct ipaccess_head)) + goto err_ipa; + + hh = (struct ipaccess_head *)msg->data; + + if (hh->proto != IPA_OML_PROTO) + goto err_ipa; + + if (ntohs(hh->len) != msg->len) + goto err_ipa; + + msgb_pull(msg, sizeof(struct ipaccess_head)); + + if (msg->len < sizeof(struct abis_om_hdr)) + goto err_om; + + msg->l2h = msg->data; + + if (msg->len < + sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr)) { + LOGP(DL1C, LOGL_NOTICE, "Failed: fom headermalformed message"); + } + + msg->l3h = msg->data + sizeof(struct abis_om_hdr); + + omh = (struct abis_om_hdr *) msg->l2h; + + if (omh->mdisc != ABIS_OM_MDISC_FOM) + goto err_om; + + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) + goto err_om; + + if (omh->sequence != 0) + goto err_om; + + if (omh->length != sizeof(struct abis_om_fom_hdr)) + goto err_om; + + return 0; + +err_ipa: + LOGP(DL1C, LOGL_NOTICE, "Failed: ipacess header malformed message"); + return -1; +err_om: + LOGP(DL1C, LOGL_NOTICE, "Failed: om header malformed message"); + return -1; +} + +static int read_sock(struct osmo_fd *fd, unsigned int what) +{ + struct msgb *msg; + struct gsm_abis_mo *mo; + int rc; + + msg = oml_msgb_alloc(); + if (msg == NULL) + return -1; + + rc = recv(fd->fd, msg->tail, msg->data_len, 0); + if (rc <= 0) { + close(fd->fd); + osmo_fd_unregister(fd); + fd->fd = -1; + goto err; + } + + msgb_put(msg, rc); + + if (test_recv_msg(msg) < 0) { + LOGP(DL1C, LOGL_NOTICE, "Failed: Malformed receive message"); + goto err; + } + + mo = &bts->mo; + msg->trx = mo->bts->c0; + + return abis_oml_sendmsg(msg); + +err: + msgb_free(msg); + return -1; +} + +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *read_fd = (struct osmo_fd *)fd->data; + + if (read_fd->fd > -1) { + close(read_fd->fd); + osmo_fd_unregister(read_fd); + read_fd->fd = -1; + } + + cl = accept(sfd, NULL, NULL); + if (cl < 0) + return -1; + + read_fd->fd = cl; + if (osmo_fd_register(read_fd) != 0) { + close(cl); + return -1; + } + + return 0; +} +#endif + +static int sbts2050_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) +{ +#ifdef BUILD_SBTS2050 + int rc; + + accept->cb = accept_unix_sock; + read->cb = read_sock; + read->when = BSC_FD_READ; + read->fd = -1; + accept->data = read; + + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + return rc; +#else + return 0; +#endif +} + int main(int argc, char **argv) { struct stat st; @@ -295,6 +437,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; + struct osmo_fd accept_fd, read_fd; int rc; tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -371,6 +514,12 @@ int main(int argc, char **argv) exit(1); } + rc = sbts2050_sock_unix_init(&accept_fd, &read_fd); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(3); + } + if (daemonize) { rc = osmo_daemonize(); if (rc < 0) { diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..7a50bdc 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -45,9 +46,16 @@ #include "misc/sysmobts_nl.h" #include "misc/sysmobts_par.h" +enum { + SYSMO_MGR_DISCONNECTED = 0, + SYSMO_MGR_CONNECTED, +}; + static int no_eeprom_write = 0; static int daemonize = 0; +static int fd_unix = -1; void *tall_mgr_ctx; +static struct sbts2050_config_info confinfo; /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -55,7 +63,61 @@ void *tall_mgr_ctx; /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ #define HOURS_TIMER_SECS (1 * 3600) +/* every 5 minutes try to reconnect if we have a problem in the communication*/ +#define CONNECT_TIMER_SECS 300 + +/* unix domain socket file descriptor */ +#define SOCKET_PATH "/var/run/bts_oml" + #ifdef BUILD_SBTS2050 +static int trx_nr = -1; +static int state_connection = 0; + +static struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + osmo_timer_schedule(&connect_timer, + CONNECT_TIMER_SECS, 0); + return; + } + + state_connection = SYSMO_MGR_CONNECTED; +} + +static void check_temperature(struct uc *ucontrol0, int downlimit, int uplimit, + int current_temp, + enum sbts2050_temp_sensor sensor, + enum sbts2050_alert_lvl alert) +{ + int rc; + + if (downlimit >= current_temp || uplimit <= current_temp) { + switch (alert) { + case SBTS2050_WARN_ALERT: + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, + &confinfo, trx_nr); + break; + case SBTS2050_SEVER_ALERT: + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + confinfo.pa_power_act); + break; + } + } + + state_connection = rc; + + if (state_connection == SYSMO_MGR_DISCONNECTED) { + close(fd_unix); + socket_connect_cb(NULL); + } +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +126,26 @@ static void check_uctemp_timer_cb(void *data) sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); + confinfo.temp_pa_cur = temp_pa; + confinfo.temp_board_cur = temp_board; + + check_temperature(ucontrol0, confinfo.temp_min_pa_warn_limit, + confinfo.temp_max_pa_warn_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_pa_sever_limit, + confinfo.temp_max_pa_sever_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVER_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_warn_limit, + confinfo.temp_max_board_warn_limit, + temp_board, SBTS2050_TEMP_BOARD, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_sever_limit, + confinfo.temp_min_board_sever_limit, + temp_board, SBTS2050_TEMP_BOARD, + SBTS2050_SEVER_ALERT); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +175,7 @@ static void initialize_sbts2050(void) if (val != 0) return; } + trx_nr = val; ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); if (ucontrol0.fd < 0) { @@ -101,6 +184,10 @@ static void initialize_sbts2050(void) return; } + /* start handle for reconnect the socket in case of error */ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + temp_uc_timer.cb = check_uctemp_timer_cb; temp_uc_timer.data = &ucontrol0; check_uctemp_timer_cb(&ucontrol0); @@ -169,6 +256,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write); + close(fd_unix); exit(0); break; case SIGABRT: diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..8f708b6 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c @@ -29,13 +29,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include +#include #include "btsconfig.h" #include "sysmobts_misc.h" @@ -49,10 +53,147 @@ #define SERIAL_ALLOC_SIZE 300 #define SIZE_HEADER_RSP 5 #define SIZE_HEADER_CMD 4 - +#define OM_ALLOC_SIZE 1024 +#define OM_HEADROOM_SIZE 128 +#define IPA_OML_PROTO 0xFF #ifdef BUILD_SBTS2050 /********************************************************************** + * Function send information to OsmoBts + *********************************************************************/ +static void add_sw_descr(struct msgb *msg) +{ + char file_version[255]; + char file_id[255]; + + strncpy(file_id, "sysmomgr", sizeof("sysmomgr")); + file_id[sizeof(file_id) - 1] = '\0'; + strncpy(file_version, PACKAGE_VERSION, sizeof(PACKAGE_VERSION)); + file_version[sizeof(file_version) - 1] = '\0'; + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), + (uint8_t *)file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), + (uint8_t *)file_version); +} + +static void add_probable_cause(struct msgb *msg) +{ + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); + msgb_v_put(msg, 0); + msgb_v_put(msg, 0); +} + +static void add_ipa_header(struct msgb *msg) +{ + struct ipaccess_head *hh; + + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); + hh->proto = IPA_OML_PROTO; + hh->len = htons(msg->len); +} + +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, + uint8_t obj_class, uint8_t bts_nr, + uint8_t trx_nr, uint8_t ts_nr) +{ + struct abis_om_fom_hdr *foh; + struct abis_om_hdr *omh; + + msg->l3h = msgb_push(msg, sizeof(*foh)); + foh = (struct abis_om_fom_hdr *) msg->l3h; + + foh->msg_type = msg_type; + foh->obj_class = obj_class; + foh->obj_inst.bts_nr = bts_nr; + foh->obj_inst.trx_nr = trx_nr; + foh->obj_inst.ts_nr = ts_nr; + + msg->l2h = msgb_push(msg, sizeof(*omh)); + omh = (struct abis_om_hdr *) msg->l2h; + + omh->mdisc = ABIS_OM_MDISC_FOM; + omh->placement = ABIS_OM_PLACEMENT_ONLY; + omh->sequence = 0; + omh->length = msgb_l3len(msg); +} + +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr) +{ + int rc; + struct msgb *msg; + const char *buf, *nsensor; + + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); + if (msg == NULL) { + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); + goto err; + } + + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0); + + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); + + switch (alert) { + case SBTS2050_WARN_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); + break; + case SBTS2050_SEVER_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); + break; + default: + goto err; + } + + add_probable_cause(msg); + + add_sw_descr(msg); + + switch (sensor) { + case SBTS2050_TEMP_BOARD: + buf = "Unusual temperature on the Board"; + nsensor = "Board"; + break; + case SBTS2050_TEMP_PA: + buf = "Unusual temperature on the PA"; + nsensor = "PA"; + break; + default: + return -1; + } + strncpy(add_info->name_sensor, nsensor, sizeof(add_info->name_sensor)); + add_info->name_sensor[sizeof(add_info->name_sensor) - 1] = '\0'; + + msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf); + + /* If we need to send this structure to other machine, we need to pass + * the integer inside the structure to internet format (big endian) + */ + msgb_tl16v_put(msg, NM_ATT_ADD_INFO, + sizeof(struct sbts2050_config_info), + (const uint8_t *)add_info); + + add_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0) { + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); + close(fd_unix); + msgb_free(msg); + return 0; + } + + msgb_free(msg); + return 1; +err: + msgb_free(msg); + return -1; +} + +/********************************************************************** * Functions read/write from serial interface *********************************************************************/ static int hand_serial_read(int fd, struct msgb *msg, int numbytes) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index 01878f2..2654348 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -32,6 +32,34 @@ struct ucinfo { int pa; }; +enum sbts2050_alert_lvl { + SBTS2050_WARN_ALERT, + SBTS2050_SEVER_ALERT +}; + +enum sbts2050_temp_sensor { + SBTS2050_TEMP_BOARD, + SBTS2050_TEMP_PA +}; + +struct sbts2050_config_info { + char name_sensor[8]; + int temp_max_pa_warn_limit; + int temp_min_pa_warn_limit; + int temp_max_pa_sever_limit; + int temp_min_pa_sever_limit; + int temp_max_board_warn_limit; + int temp_min_board_warn_limit; + int temp_max_board_sever_limit; + int temp_min_board_sever_limit; + int max_power_red; + int slave_power_act; + int master_power_act; + int pa_power_act; + int temp_pa_cur; + int temp_board_cur; +}; + int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, enum sysmobts_temp_type type); @@ -43,6 +71,11 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa); int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status); +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr); + int sysmobts_update_hours(int no_epprom_write); enum sysmobts_firmware_type { -- 1.7.10.4 From pablo at gnumonks.org Thu Apr 10 11:12:20 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Thu, 10 Apr 2014 13:12:20 +0200 Subject: [osmo-bts PATCH 1/3 v6] src: Add OML support for sending failure message from manager In-Reply-To: <1397125427-28274-1-git-send-email-anayuso@sysmocom.de> References: <1396960294-13943-1-git-send-email-anayuso@sysmocom.de> <1397125427-28274-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140410111220.GA3530@localhost> On Thu, Apr 10, 2014 at 12:23:47PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > > With this patch, the manager monitors the sensors and send > OML Failure message from the Manager to the BTS and the BTS > to BSC, for having a report system of the sensors. > > Signed-off-by: Alvaro Neira Ayuso > --- > [changes in v6] > * Fixed some coding style errors. > * Used the function sizeof for removing the constant IPA_HEADER_SIZE. > * Checked that the message receive from the unix domain socket connetion > isn't malformed and added logging. > * Fixed some memory leaks. > * Removed the disconnect verification in the function connect. > > src/osmo-bts-sysmo/main.c | 149 +++++++++++++++++++++++++++++++ > src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 88 ++++++++++++++++++ > src/osmo-bts-sysmo/misc/sysmobts_misc.c | 143 ++++++++++++++++++++++++++++- > src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 +++++++ > 4 files changed, 412 insertions(+), 1 deletion(-) > > diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c > index 74ee47f..7e332ad 100644 > --- a/src/osmo-bts-sysmo/main.c > +++ b/src/osmo-bts-sysmo/main.c > @@ -35,8 +35,10 @@ > > #include > #include > +#include > #include > #include > +#include > > #include > #include > @@ -45,13 +47,18 @@ > #include > #include > #include > +#include > > #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" > +#define SOCKET_PATH "/var/run/bts_oml" > + > +#define IPA_OML_PROTO 0xFF > > #include "utils.h" > #include "eeprom.h" > #include "l1_if.h" > #include "hw_misc.h" > +#include "btsconfig.h" > > /* FIXME: read from real hardware */ > const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; > @@ -258,6 +265,7 @@ static void signal_handler(int signal) > case SIGINT: > //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); > bts_shutdown(bts, "SIGINT"); > + unlink(SOCKET_PATH); > break; > case SIGABRT: > case SIGUSR1: > @@ -288,6 +296,140 @@ static int write_pid_file(char *procname) > return 0; > } > > +#ifdef BUILD_SBTS2050 > +static int test_recv_msg(struct msgb *msg) > +{ > + struct ipaccess_head *hh; > + struct abis_om_hdr *omh; > + > + if (msg->len < sizeof(struct ipaccess_head)) > + goto err_ipa; > + > + hh = (struct ipaccess_head *)msg->data; > + > + if (hh->proto != IPA_OML_PROTO) > + goto err_ipa; > + > + if (ntohs(hh->len) != msg->len) > + goto err_ipa; I'm not convinced this is a good way to report errors. If you ever have to debug problems, you will not know what condition has exactly triggered the error message, so please better make one LOGP per condition. > + msgb_pull(msg, sizeof(struct ipaccess_head)); > + I'd suggest to add: int abis_oml_hdr_len; then abis_om_hdr_len = sizeof(struct abis_om_hdr); > + if (msg->len < sizeof(struct abis_om_hdr)) > + goto err_om; > + > + msg->l2h = msg->data; > + abis_om_hdr_len += sizeof(struct abis_om_fom_hdr); > + if (msg->len < > + sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr)) { if (msg->len < abis_om_hdr_len) { ... > + LOGP(DL1C, LOGL_NOTICE, "Failed: fom headermalformed message"); ^^^^^^ ^^^^^^ Use LOGL_ERROR and remove the failed. Moreover, return -1 here. > + } > + > + msg->l3h = msg->data + sizeof(struct abis_om_hdr); > + > + omh = (struct abis_om_hdr *) msg->l2h; > + > + if (omh->mdisc != ABIS_OM_MDISC_FOM) > + goto err_om; I prefer specific error messages. > + > + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) > + goto err_om; > + > + if (omh->sequence != 0) > + goto err_om; > + > + if (omh->length != sizeof(struct abis_om_fom_hdr)) > + goto err_om; > + > + return 0; > + > +err_ipa: > + LOGP(DL1C, LOGL_NOTICE, "Failed: ipacess header malformed message"); > + return -1; > +err_om: > + LOGP(DL1C, LOGL_NOTICE, "Failed: om header malformed message"); > + return -1; > +} > + > +static int read_sock(struct osmo_fd *fd, unsigned int what) > +{ > + struct msgb *msg; > + struct gsm_abis_mo *mo; > + int rc; > + > + msg = oml_msgb_alloc(); > + if (msg == NULL) > + return -1; > + > + rc = recv(fd->fd, msg->tail, msg->data_len, 0); > + if (rc <= 0) { > + close(fd->fd); > + osmo_fd_unregister(fd); > + fd->fd = -1; > + goto err; > + } > + > + msgb_put(msg, rc); > + > + if (test_recv_msg(msg) < 0) { > + LOGP(DL1C, LOGL_NOTICE, "Failed: Malformed receive message"); ^---------^ ^^^^^^ Use LOGL_ERROR. > + goto err; > + } > + > + mo = &bts->mo; > + msg->trx = mo->bts->c0; > + > + return abis_oml_sendmsg(msg); > + > +err: > + msgb_free(msg); > + return -1; > +} > + > +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) > +{ > + int sfd = fd->fd, cl; > + struct osmo_fd *read_fd = (struct osmo_fd *)fd->data; > + > + if (read_fd->fd > -1) { > + close(read_fd->fd); > + osmo_fd_unregister(read_fd); > + read_fd->fd = -1; > + } > + > + cl = accept(sfd, NULL, NULL); > + if (cl < 0) > + return -1; > + > + read_fd->fd = cl; > + if (osmo_fd_register(read_fd) != 0) { > + close(cl); > + return -1; > + } > + > + return 0; > +} > +#endif > + > +static int sbts2050_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) > +{ > +#ifdef BUILD_SBTS2050 > + int rc; > + > + accept->cb = accept_unix_sock; > + read->cb = read_sock; > + read->when = BSC_FD_READ; > + read->fd = -1; > + accept->data = read; > + > + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, > + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); > + return rc; > +#else > + return 0; > +#endif > +} > + > int main(int argc, char **argv) > { > struct stat st; > @@ -295,6 +437,7 @@ int main(int argc, char **argv) > struct gsm_bts_role_bts *btsb; > struct e1inp_line *line; > void *tall_msgb_ctx; > + struct osmo_fd accept_fd, read_fd; > int rc; > > tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); > @@ -371,6 +514,12 @@ int main(int argc, char **argv) > exit(1); > } > > + rc = sbts2050_sock_unix_init(&accept_fd, &read_fd); > + if (rc < 0) { > + perror("Error creating socket domain creation"); > + exit(3); > + } > + > if (daemonize) { > rc = osmo_daemonize(); > if (rc < 0) { > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > index 6c64d0f..7a50bdc 100644 > --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > @@ -36,6 +36,7 @@ > #include > #include > #include > +#include > #include > #include > > @@ -45,9 +46,16 @@ > #include "misc/sysmobts_nl.h" > #include "misc/sysmobts_par.h" > > +enum { > + SYSMO_MGR_DISCONNECTED = 0, > + SYSMO_MGR_CONNECTED, > +}; > + > static int no_eeprom_write = 0; > static int daemonize = 0; > +static int fd_unix = -1; > void *tall_mgr_ctx; > +static struct sbts2050_config_info confinfo; > > /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ > #define TEMP_TIMER_SECS (6 * 3600) > @@ -55,7 +63,61 @@ void *tall_mgr_ctx; > /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ > #define HOURS_TIMER_SECS (1 * 3600) > > +/* every 5 minutes try to reconnect if we have a problem in the communication*/ > +#define CONNECT_TIMER_SECS 300 > + > +/* unix domain socket file descriptor */ > +#define SOCKET_PATH "/var/run/bts_oml" > + > #ifdef BUILD_SBTS2050 > +static int trx_nr = -1; > +static int state_connection = 0; > + > +static struct osmo_timer_list connect_timer; > +static void socket_connect_cb(void *data) > +{ > + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, > + OSMO_SOCK_F_CONNECT); > + if (fd_unix < 0) { > + osmo_timer_schedule(&connect_timer, > + CONNECT_TIMER_SECS, 0); This two lines above fit in one line. > + return; > + } > + > + state_connection = SYSMO_MGR_CONNECTED; > +} > + > +static void check_temperature(struct uc *ucontrol0, int downlimit, int uplimit, > + int current_temp, > + enum sbts2050_temp_sensor sensor, > + enum sbts2050_alert_lvl alert) > +{ > + int rc; > + > + if (downlimit >= current_temp || uplimit <= current_temp) { > + switch (alert) { > + case SBTS2050_WARN_ALERT: > + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, > + &confinfo, trx_nr); > + break; > + case SBTS2050_SEVER_ALERT: > + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, > + &confinfo, trx_nr); > + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, > + confinfo.slave_power_act, > + confinfo.pa_power_act); > + break; > + } > + } > + > + state_connection = rc; > + > + if (state_connection == SYSMO_MGR_DISCONNECTED) { > + close(fd_unix); > + socket_connect_cb(NULL); > + } > +} > + > static struct osmo_timer_list temp_uc_timer; > static void check_uctemp_timer_cb(void *data) > { > @@ -64,6 +126,26 @@ static void check_uctemp_timer_cb(void *data) > > sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); > > + confinfo.temp_pa_cur = temp_pa; > + confinfo.temp_board_cur = temp_board; > + > + check_temperature(ucontrol0, confinfo.temp_min_pa_warn_limit, > + confinfo.temp_max_pa_warn_limit, > + temp_pa, SBTS2050_TEMP_PA, SBTS2050_WARN_ALERT); > + > + check_temperature(ucontrol0, confinfo.temp_min_pa_sever_limit, > + confinfo.temp_max_pa_sever_limit, > + temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVER_ALERT); > + > + check_temperature(ucontrol0, confinfo.temp_min_board_warn_limit, > + confinfo.temp_max_board_warn_limit, > + temp_board, SBTS2050_TEMP_BOARD, SBTS2050_WARN_ALERT); > + > + check_temperature(ucontrol0, confinfo.temp_min_board_sever_limit, > + confinfo.temp_min_board_sever_limit, > + temp_board, SBTS2050_TEMP_BOARD, > + SBTS2050_SEVER_ALERT); > + > osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); > } > #endif > @@ -93,6 +175,7 @@ static void initialize_sbts2050(void) > if (val != 0) > return; > } > + trx_nr = val; > > ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); > if (ucontrol0.fd < 0) { > @@ -101,6 +184,10 @@ static void initialize_sbts2050(void) > return; > } > > + /* start handle for reconnect the socket in case of error */ > + connect_timer.cb = socket_connect_cb; > + socket_connect_cb(NULL); > + > temp_uc_timer.cb = check_uctemp_timer_cb; > temp_uc_timer.data = &ucontrol0; > check_uctemp_timer_cb(&ucontrol0); > @@ -169,6 +256,7 @@ static void signal_handler(int signal) > case SIGINT: > sysmobts_check_temp(no_eeprom_write); > sysmobts_update_hours(no_eeprom_write); > + close(fd_unix); > exit(0); > break; > case SIGABRT: > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c > index 9ea26c2..8f708b6 100644 > --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c > +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c > @@ -29,13 +29,17 @@ > #include > #include > #include > +#include > > #include > #include > #include > +#include > #include > #include > #include > +#include > +#include > > #include "btsconfig.h" > #include "sysmobts_misc.h" > @@ -49,10 +53,147 @@ > #define SERIAL_ALLOC_SIZE 300 > #define SIZE_HEADER_RSP 5 > #define SIZE_HEADER_CMD 4 > - > +#define OM_ALLOC_SIZE 1024 > +#define OM_HEADROOM_SIZE 128 > +#define IPA_OML_PROTO 0xFF > > #ifdef BUILD_SBTS2050 > /********************************************************************** > + * Function send information to OsmoBts > + *********************************************************************/ > +static void add_sw_descr(struct msgb *msg) > +{ > + char file_version[255]; > + char file_id[255]; > + > + strncpy(file_id, "sysmomgr", sizeof("sysmomgr")); > + file_id[sizeof(file_id) - 1] = '\0'; > + strncpy(file_version, PACKAGE_VERSION, sizeof(PACKAGE_VERSION)); > + file_version[sizeof(file_version) - 1] = '\0'; > + msgb_v_put(msg, NM_ATT_SW_DESCR); > + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), > + (uint8_t *)file_id); > + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), > + (uint8_t *)file_version); > +} > + > +static void add_probable_cause(struct msgb *msg) > +{ > + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); > + msgb_v_put(msg, 0); > + msgb_v_put(msg, 0); > +} > + > +static void add_ipa_header(struct msgb *msg) > +{ > + struct ipaccess_head *hh; > + > + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); > + hh->proto = IPA_OML_PROTO; > + hh->len = htons(msg->len); > +} > + > +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, > + uint8_t obj_class, uint8_t bts_nr, > + uint8_t trx_nr, uint8_t ts_nr) > +{ > + struct abis_om_fom_hdr *foh; > + struct abis_om_hdr *omh; > + > + msg->l3h = msgb_push(msg, sizeof(*foh)); > + foh = (struct abis_om_fom_hdr *) msg->l3h; > + > + foh->msg_type = msg_type; > + foh->obj_class = obj_class; > + foh->obj_inst.bts_nr = bts_nr; > + foh->obj_inst.trx_nr = trx_nr; > + foh->obj_inst.ts_nr = ts_nr; > + > + msg->l2h = msgb_push(msg, sizeof(*omh)); > + omh = (struct abis_om_hdr *) msg->l2h; > + > + omh->mdisc = ABIS_OM_MDISC_FOM; > + omh->placement = ABIS_OM_PLACEMENT_ONLY; > + omh->sequence = 0; > + omh->length = msgb_l3len(msg); > +} > + > +int sendto_osmobts(int fd_unix, struct uc *ucontrol, This is returning the state, which is an enum, right? > + enum sbts2050_alert_lvl alert, > + enum sbts2050_temp_sensor sensor, > + struct sbts2050_config_info *add_info, int trx_nr) > +{ > + int rc; > + struct msgb *msg; > + const char *buf, *nsensor; > + > + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); > + if (msg == NULL) { > + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); > + goto err; Please, review this, free(NULL) is legal, but I don't rememer if msgb_free() is doing more than just that. > + } > + > + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0); > + > + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); > + > + switch (alert) { > + case SBTS2050_WARN_ALERT: > + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); > + break; > + case SBTS2050_SEVER_ALERT: > + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); > + break; > + default: > + goto err; > + } > + > + add_probable_cause(msg); > + > + add_sw_descr(msg); > + > + switch (sensor) { > + case SBTS2050_TEMP_BOARD: > + buf = "Unusual temperature on the Board"; > + nsensor = "Board"; > + break; > + case SBTS2050_TEMP_PA: > + buf = "Unusual temperature on the PA"; > + nsensor = "PA"; > + break; > + default: > + return -1; Extremely unlikely to happen, but we have a leak here: goto err; ? I think it would be good to log this as well: "Unknown sensor type". Please, address this changes, thanks. From anayuso at sysmocom.de Thu Apr 10 13:40:38 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Thu, 10 Apr 2014 15:40:38 +0200 Subject: [osmo-bts PATCH 1/3 v7] src: Add OML support for sending failure message from manager In-Reply-To: <1397125427-28274-1-git-send-email-anayuso@sysmocom.de> References: <1397125427-28274-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397137238-12746-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso With this patch, the manager monitors the sensors and send OML Failure message from the Manager to the BTS and the BTS to BSC, for having a report system of the sensors. Signed-off-by: Alvaro Neira Ayuso --- [change in v7] * Added specific error report in all the errors case that we can find * Refactor some code using a new variable abis_om_hdr_len * Changed LOGL_NOTICE to LOGL_ERROR in all the LOGP that I have used for reporting errors * Change the function send_to for using the states variables that I have created for showing the connection state between sysmobts-mgr and sysmobts * Fixed a leak in the function send_to src/osmo-bts-sysmo/main.c | 168 +++++++++++++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 82 +++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 5 + src/osmo-bts-sysmo/misc/sysmobts_misc.c | 145 +++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 ++++++ 5 files changed, 432 insertions(+), 1 deletion(-) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..b93667d 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,8 +35,10 @@ #include #include +#include #include #include +#include #include #include @@ -45,13 +47,18 @@ #include #include #include +#include #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" +#define SOCKET_PATH "/var/run/bts_oml" + +#define IPA_OML_PROTO 0xFF #include "utils.h" #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" +#include "btsconfig.h" /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -258,6 +265,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT"); + unlink(SOCKET_PATH); break; case SIGABRT: case SIGUSR1: @@ -288,6 +296,159 @@ static int write_pid_file(char *procname) return 0; } +#ifdef BUILD_SBTS2050 +static int test_recv_msg(struct msgb *msg) +{ + struct ipaccess_head *hh; + struct abis_om_hdr *omh; + int abis_oml_hdr_len; + + if (msg->len < sizeof(struct ipaccess_head)) { + LOGP(DL1C, LOGL_ERROR, "Failed: ipa header insufficient space\n"); + return -1; + } + + hh = (struct ipaccess_head *)msg->data; + + if (hh->proto != IPA_OML_PROTO) { + LOGP(DL1C, LOGL_ERROR, "Failed: incorrect ipa header protocol\n"); + return -1; + } + + if (ntohs(hh->len) != msg->len) { + LOGP(DL1C, LOGL_ERROR, "Failed: incorrect ipa header message size\n"); + return -1; + } + + msgb_pull(msg, sizeof(struct ipaccess_head)); + + abis_oml_hdr_len = sizeof(struct abis_om_hdr); + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, "Failed: om header insufficient space\n"); + return -1; + } + + msg->l2h = msg->data; + + abis_oml_hdr_len += sizeof(struct abis_om_fom_hdr); + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, "Failed: fom header insufficient space\n"); + return -1; + } + + msg->l3h = msg->data + sizeof(struct abis_om_hdr); + + omh = (struct abis_om_hdr *) msg->l2h; + + if (omh->mdisc != ABIS_OM_MDISC_FOM) { + LOGP(DL1C, LOGL_ERROR, "Failed: incorrect om mdisc value\n"); + return -1; + } + + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) { + LOGP(DL1C, LOGL_ERROR, "Failed: incorrect om placement value\n"); + return -1; + } + + if (omh->sequence != 0) { + LOGP(DL1C, LOGL_ERROR, "Failed: incorrect om sequence value\n"); + return -1; + } + + if (omh->length != sizeof(struct abis_om_fom_hdr)) { + LOGP(DL1C, LOGL_ERROR, "Failed: incorrect om length value\n"); + return -1; + } + + return 0; +} + +static int read_sock(struct osmo_fd *fd, unsigned int what) +{ + struct msgb *msg; + struct gsm_abis_mo *mo; + int rc; + + msg = oml_msgb_alloc(); + if (msg == NULL) { + LOGP(DL1C, LOGL_ERROR, "Failed alloc oml message.\n"); + return -1; + } + + rc = recv(fd->fd, msg->tail, msg->data_len, 0); + if (rc <= 0) { + close(fd->fd); + osmo_fd_unregister(fd); + fd->fd = -1; + goto err; + } + + msgb_put(msg, rc); + + if (test_recv_msg(msg) < 0) { + LOGP(DL1C, LOGL_ERROR, "Failed: Malformed receive message\n"); + goto err; + } + + mo = &bts->mo; + msg->trx = mo->bts->c0; + + return abis_oml_sendmsg(msg); + +err: + msgb_free(msg); + return -1; +} + +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *read_fd = (struct osmo_fd *)fd->data; + + if (read_fd->fd > -1) { + close(read_fd->fd); + osmo_fd_unregister(read_fd); + read_fd->fd = -1; + } + + cl = accept(sfd, NULL, NULL); + if (cl < 0) { + LOGP(DL1C, LOGL_ERROR, "Failed to accept new connection.\n"); + return -1; + } + + read_fd->fd = cl; + if (osmo_fd_register(read_fd) != 0) { + LOGP(DL1C, LOGL_ERROR, "Failed to register the read file desc.\n"); + close(cl); + return -1; + } + + return 0; +} +#endif + +static int sbts2050_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) +{ +#ifdef BUILD_SBTS2050 + int rc; + + accept->cb = accept_unix_sock; + read->cb = read_sock; + read->when = BSC_FD_READ; + read->fd = -1; + accept->data = read; + + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + return rc; +#else + return 0; +#endif +} + int main(int argc, char **argv) { struct stat st; @@ -295,6 +456,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; + struct osmo_fd accept_fd, read_fd; int rc; tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -371,6 +533,12 @@ int main(int argc, char **argv) exit(1); } + rc = sbts2050_sock_unix_init(&accept_fd, &read_fd); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(1); + } + if (daemonize) { rc = osmo_daemonize(); if (rc < 0) { diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..51fa539 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,9 @@ static int no_eeprom_write = 0; static int daemonize = 0; +static int fd_unix = -1; void *tall_mgr_ctx; +static struct sbts2050_config_info confinfo; /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -55,7 +58,60 @@ void *tall_mgr_ctx; /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ #define HOURS_TIMER_SECS (1 * 3600) +/* every 5 minutes try to reconnect if we have a problem in the communication*/ +#define CONNECT_TIMER_SECS 300 + +/* unix domain socket file descriptor */ +#define SOCKET_PATH "/var/run/bts_oml" + #ifdef BUILD_SBTS2050 +static int trx_nr = -1; +static int state_connection = 0; + +static struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0); + return; + } + + state_connection = SYSMO_MGR_CONNECTED; +} + +static void check_temperature(struct uc *ucontrol0, int downlimit, int uplimit, + int current_temp, + enum sbts2050_temp_sensor sensor, + enum sbts2050_alert_lvl alert) +{ + int rc; + + if (downlimit >= current_temp || uplimit <= current_temp) { + switch (alert) { + case SBTS2050_WARN_ALERT: + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, + &confinfo, trx_nr); + break; + case SBTS2050_SEVER_ALERT: + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + confinfo.pa_power_act); + break; + } + } + + state_connection = rc; + + if (state_connection == SYSMO_MGR_DISCONNECTED) { + close(fd_unix); + socket_connect_cb(NULL); + } +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +120,26 @@ static void check_uctemp_timer_cb(void *data) sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); + confinfo.temp_pa_cur = temp_pa; + confinfo.temp_board_cur = temp_board; + + check_temperature(ucontrol0, confinfo.temp_min_pa_warn_limit, + confinfo.temp_max_pa_warn_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_pa_sever_limit, + confinfo.temp_max_pa_sever_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVER_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_warn_limit, + confinfo.temp_max_board_warn_limit, + temp_board, SBTS2050_TEMP_BOARD, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_sever_limit, + confinfo.temp_min_board_sever_limit, + temp_board, SBTS2050_TEMP_BOARD, + SBTS2050_SEVER_ALERT); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +169,7 @@ static void initialize_sbts2050(void) if (val != 0) return; } + trx_nr = val; ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); if (ucontrol0.fd < 0) { @@ -101,6 +178,10 @@ static void initialize_sbts2050(void) return; } + /* start handle for reconnect the socket in case of error */ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + temp_uc_timer.cb = check_uctemp_timer_cb; temp_uc_timer.data = &ucontrol0; check_uctemp_timer_cb(&ucontrol0); @@ -169,6 +250,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write); + close(fd_unix); exit(0); break; case SIGABRT: diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index ddb6774..87668e0 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -7,4 +7,9 @@ enum { DFIND, }; +enum { + SYSMO_MGR_DISCONNECTED = 0, + SYSMO_MGR_CONNECTED, +}; + #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..87e8916 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c @@ -29,13 +29,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include +#include #include "btsconfig.h" #include "sysmobts_misc.h" @@ -49,10 +53,149 @@ #define SERIAL_ALLOC_SIZE 300 #define SIZE_HEADER_RSP 5 #define SIZE_HEADER_CMD 4 - +#define OM_ALLOC_SIZE 1024 +#define OM_HEADROOM_SIZE 128 +#define IPA_OML_PROTO 0xFF #ifdef BUILD_SBTS2050 /********************************************************************** + * Function send information to OsmoBts + *********************************************************************/ +static void add_sw_descr(struct msgb *msg) +{ + char file_version[255]; + char file_id[255]; + + strncpy(file_id, "sysmomgr", sizeof("sysmomgr")); + file_id[sizeof(file_id) - 1] = '\0'; + strncpy(file_version, PACKAGE_VERSION, sizeof(PACKAGE_VERSION)); + file_version[sizeof(file_version) - 1] = '\0'; + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), + (uint8_t *)file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), + (uint8_t *)file_version); +} + +static void add_probable_cause(struct msgb *msg) +{ + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); + msgb_v_put(msg, 0); + msgb_v_put(msg, 0); +} + +static void add_ipa_header(struct msgb *msg) +{ + struct ipaccess_head *hh; + + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); + hh->proto = IPA_OML_PROTO; + hh->len = htons(msg->len); +} + +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, + uint8_t obj_class, uint8_t bts_nr, + uint8_t trx_nr, uint8_t ts_nr) +{ + struct abis_om_fom_hdr *foh; + struct abis_om_hdr *omh; + + msg->l3h = msgb_push(msg, sizeof(*foh)); + foh = (struct abis_om_fom_hdr *) msg->l3h; + + foh->msg_type = msg_type; + foh->obj_class = obj_class; + foh->obj_inst.bts_nr = bts_nr; + foh->obj_inst.trx_nr = trx_nr; + foh->obj_inst.ts_nr = ts_nr; + + msg->l2h = msgb_push(msg, sizeof(*omh)); + omh = (struct abis_om_hdr *) msg->l2h; + + omh->mdisc = ABIS_OM_MDISC_FOM; + omh->placement = ABIS_OM_PLACEMENT_ONLY; + omh->sequence = 0; + omh->length = msgb_l3len(msg); +} + +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr) +{ + int rc; + struct msgb *msg; + const char *buf, *nsensor; + + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); + if (msg == NULL) { + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); + return -1; + } + + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0); + + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); + + switch (alert) { + case SBTS2050_WARN_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); + break; + case SBTS2050_SEVER_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); + break; + default: + LOGP(DTEMP, LOGL_ERROR, "Failed: Unknown attr severity type\n"); + goto err; + } + + add_probable_cause(msg); + + add_sw_descr(msg); + + switch (sensor) { + case SBTS2050_TEMP_BOARD: + buf = "Unusual temperature on the Board"; + nsensor = "Board"; + break; + case SBTS2050_TEMP_PA: + buf = "Unusual temperature on the PA"; + nsensor = "PA"; + break; + default: + LOGP(DTEMP, LOGL_ERROR, "Failed: Unknown sensor type\n"); + goto err; + } + strncpy(add_info->name_sensor, nsensor, sizeof(add_info->name_sensor)); + add_info->name_sensor[sizeof(add_info->name_sensor) - 1] = '\0'; + + msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf); + + /* If we need to send this structure to other machine, we need to pass + * the integer inside the structure to internet format (big endian) + */ + msgb_tl16v_put(msg, NM_ATT_ADD_INFO, + sizeof(struct sbts2050_config_info), + (const uint8_t *)add_info); + + add_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0) { + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); + close(fd_unix); + msgb_free(msg); + return SYSMO_MGR_DISCONNECTED; + } + + msgb_free(msg); + return SYSMO_MGR_CONNECTED; +err: + msgb_free(msg); + return -1; +} + +/********************************************************************** * Functions read/write from serial interface *********************************************************************/ static int hand_serial_read(int fd, struct msgb *msg, int numbytes) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index 01878f2..2654348 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -32,6 +32,34 @@ struct ucinfo { int pa; }; +enum sbts2050_alert_lvl { + SBTS2050_WARN_ALERT, + SBTS2050_SEVER_ALERT +}; + +enum sbts2050_temp_sensor { + SBTS2050_TEMP_BOARD, + SBTS2050_TEMP_PA +}; + +struct sbts2050_config_info { + char name_sensor[8]; + int temp_max_pa_warn_limit; + int temp_min_pa_warn_limit; + int temp_max_pa_sever_limit; + int temp_min_pa_sever_limit; + int temp_max_board_warn_limit; + int temp_min_board_warn_limit; + int temp_max_board_sever_limit; + int temp_min_board_sever_limit; + int max_power_red; + int slave_power_act; + int master_power_act; + int pa_power_act; + int temp_pa_cur; + int temp_board_cur; +}; + int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, enum sysmobts_temp_type type); @@ -43,6 +71,11 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa); int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status); +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr); + int sysmobts_update_hours(int no_epprom_write); enum sysmobts_firmware_type { -- 1.7.10.4 From pablo at gnumonks.org Thu Apr 10 13:52:04 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Thu, 10 Apr 2014 15:52:04 +0200 Subject: [osmo-bts PATCH 1/3 v7] src: Add OML support for sending failure message from manager In-Reply-To: <1397137238-12746-1-git-send-email-anayuso@sysmocom.de> References: <1397125427-28274-1-git-send-email-anayuso@sysmocom.de> <1397137238-12746-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140410135204.GA4346@localhost> On Thu, Apr 10, 2014 at 03:40:38PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > > With this patch, the manager monitors the sensors and send > OML Failure message from the Manager to the BTS and the BTS > to BSC, for having a report system of the sensors. > > Signed-off-by: Alvaro Neira Ayuso > --- > [change in v7] > * Added specific error report in all the errors case that we can find > * Refactor some code using a new variable abis_om_hdr_len > * Changed LOGL_NOTICE to LOGL_ERROR in all the LOGP that I have used for > reporting errors > * Change the function send_to for using the states variables that I have created > for showing the connection state between sysmobts-mgr and sysmobts > * Fixed a leak in the function send_to > > src/osmo-bts-sysmo/main.c | 168 +++++++++++++++++++++++++++++++ > src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 82 +++++++++++++++ > src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 5 + > src/osmo-bts-sysmo/misc/sysmobts_misc.c | 145 +++++++++++++++++++++++++- > src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 ++++++ > 5 files changed, 432 insertions(+), 1 deletion(-) > > diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c > index 74ee47f..b93667d 100644 > --- a/src/osmo-bts-sysmo/main.c > +++ b/src/osmo-bts-sysmo/main.c > @@ -35,8 +35,10 @@ > > #include > #include > +#include > #include > #include > +#include > > #include > #include > @@ -45,13 +47,18 @@ > #include > #include > #include > +#include > > #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" > +#define SOCKET_PATH "/var/run/bts_oml" > + > +#define IPA_OML_PROTO 0xFF > > #include "utils.h" > #include "eeprom.h" > #include "l1_if.h" > #include "hw_misc.h" > +#include "btsconfig.h" > > /* FIXME: read from real hardware */ > const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; > @@ -258,6 +265,7 @@ static void signal_handler(int signal) > case SIGINT: > //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); > bts_shutdown(bts, "SIGINT"); > + unlink(SOCKET_PATH); > break; > case SIGABRT: > case SIGUSR1: > @@ -288,6 +296,159 @@ static int write_pid_file(char *procname) > return 0; > } > > +#ifdef BUILD_SBTS2050 > +static int test_recv_msg(struct msgb *msg) > +{ > + struct ipaccess_head *hh; > + struct abis_om_hdr *omh; > + int abis_oml_hdr_len; > + > + if (msg->len < sizeof(struct ipaccess_head)) { > + LOGP(DL1C, LOGL_ERROR, "Failed: ipa header insufficient space\n"); ^^^^^^^ You have to remove the "Failed:", LOGL_ERROR already includes the tag. Now this fits in one line per 80-chars: if (msg->len < sizeof(struct ipaccess_head)) { LOGP(DL1C, LOGL_ERROR, "ipa header insufficient space\n"); From anayuso at sysmocom.de Sun Apr 13 13:18:45 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Sun, 13 Apr 2014 15:18:45 +0200 Subject: [osmo-bts PATCH 1/3 v8] src: Add OML support for sending failure message from manager In-Reply-To: <1397137238-12746-1-git-send-email-anayuso@sysmocom.de> References: <1397137238-12746-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397395125-14664-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso With this patch, the manager monitors the sensors and send OML Failure message from the Manager to the BTS and the BTS to BSC, for having a report system of the sensors. Signed-off-by: Alvaro Neira Ayuso --- [changes in v8] * Changed the message in the log functions for using a incorrect message format src/osmo-bts-sysmo/main.c | 168 +++++++++++++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 82 +++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 5 + src/osmo-bts-sysmo/misc/sysmobts_misc.c | 145 +++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 33 ++++++ 5 files changed, 432 insertions(+), 1 deletion(-) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..98da626 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,8 +35,10 @@ #include #include +#include #include #include +#include #include #include @@ -45,13 +47,18 @@ #include #include #include +#include #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" +#define SOCKET_PATH "/var/run/bts_oml" + +#define IPA_OML_PROTO 0xFF #include "utils.h" #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" +#include "btsconfig.h" /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -258,6 +265,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT"); + unlink(SOCKET_PATH); break; case SIGABRT: case SIGUSR1: @@ -288,6 +296,159 @@ static int write_pid_file(char *procname) return 0; } +#ifdef BUILD_SBTS2050 +static int test_recv_msg(struct msgb *msg) +{ + struct ipaccess_head *hh; + struct abis_om_hdr *omh; + int abis_oml_hdr_len; + + if (msg->len < sizeof(struct ipaccess_head)) { + LOGP(DL1C, LOGL_ERROR, "Ipa header insufficient space\n"); + return -1; + } + + hh = (struct ipaccess_head *)msg->data; + + if (hh->proto != IPA_OML_PROTO) { + LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header protocol\n"); + return -1; + } + + if (ntohs(hh->len) != msg->len) { + LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header message size\n"); + return -1; + } + + msgb_pull(msg, sizeof(struct ipaccess_head)); + + abis_oml_hdr_len = sizeof(struct abis_om_hdr); + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, "Om header insufficient space\n"); + return -1; + } + + msg->l2h = msg->data; + + abis_oml_hdr_len += sizeof(struct abis_om_fom_hdr); + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, "Fom header insufficient space\n"); + return -1; + } + + msg->l3h = msg->data + sizeof(struct abis_om_hdr); + + omh = (struct abis_om_hdr *) msg->l2h; + + if (omh->mdisc != ABIS_OM_MDISC_FOM) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value\n"); + return -1; + } + + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value\n"); + return -1; + } + + if (omh->sequence != 0) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value\n"); + return -1; + } + + if (omh->length != sizeof(struct abis_om_fom_hdr)) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om length value\n"); + return -1; + } + + return 0; +} + +static int read_sock(struct osmo_fd *fd, unsigned int what) +{ + struct msgb *msg; + struct gsm_abis_mo *mo; + int rc; + + msg = oml_msgb_alloc(); + if (msg == NULL) { + LOGP(DL1C, LOGL_ERROR, "Failed alloc oml message.\n"); + return -1; + } + + rc = recv(fd->fd, msg->tail, msg->data_len, 0); + if (rc <= 0) { + close(fd->fd); + osmo_fd_unregister(fd); + fd->fd = -1; + goto err; + } + + msgb_put(msg, rc); + + if (test_recv_msg(msg) < 0) { + LOGP(DL1C, LOGL_ERROR, "Malformed receive message\n"); + goto err; + } + + mo = &bts->mo; + msg->trx = mo->bts->c0; + + return abis_oml_sendmsg(msg); + +err: + msgb_free(msg); + return -1; +} + +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *read_fd = (struct osmo_fd *)fd->data; + + if (read_fd->fd > -1) { + close(read_fd->fd); + osmo_fd_unregister(read_fd); + read_fd->fd = -1; + } + + cl = accept(sfd, NULL, NULL); + if (cl < 0) { + LOGP(DL1C, LOGL_ERROR, "Accept new unix domain connection.\n"); + return -1; + } + + read_fd->fd = cl; + if (osmo_fd_register(read_fd) != 0) { + LOGP(DL1C, LOGL_ERROR, "Register the read file desc.\n"); + close(cl); + return -1; + } + + return 0; +} +#endif + +static int sbts2050_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) +{ +#ifdef BUILD_SBTS2050 + int rc; + + accept->cb = accept_unix_sock; + read->cb = read_sock; + read->when = BSC_FD_READ; + read->fd = -1; + accept->data = read; + + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + return rc; +#else + return 0; +#endif +} + int main(int argc, char **argv) { struct stat st; @@ -295,6 +456,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; + struct osmo_fd accept_fd, read_fd; int rc; tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -371,6 +533,12 @@ int main(int argc, char **argv) exit(1); } + rc = sbts2050_sock_unix_init(&accept_fd, &read_fd); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(1); + } + if (daemonize) { rc = osmo_daemonize(); if (rc < 0) { diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..51fa539 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,9 @@ static int no_eeprom_write = 0; static int daemonize = 0; +static int fd_unix = -1; void *tall_mgr_ctx; +static struct sbts2050_config_info confinfo; /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -55,7 +58,60 @@ void *tall_mgr_ctx; /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ #define HOURS_TIMER_SECS (1 * 3600) +/* every 5 minutes try to reconnect if we have a problem in the communication*/ +#define CONNECT_TIMER_SECS 300 + +/* unix domain socket file descriptor */ +#define SOCKET_PATH "/var/run/bts_oml" + #ifdef BUILD_SBTS2050 +static int trx_nr = -1; +static int state_connection = 0; + +static struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0); + return; + } + + state_connection = SYSMO_MGR_CONNECTED; +} + +static void check_temperature(struct uc *ucontrol0, int downlimit, int uplimit, + int current_temp, + enum sbts2050_temp_sensor sensor, + enum sbts2050_alert_lvl alert) +{ + int rc; + + if (downlimit >= current_temp || uplimit <= current_temp) { + switch (alert) { + case SBTS2050_WARN_ALERT: + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, + &confinfo, trx_nr); + break; + case SBTS2050_SEVER_ALERT: + rc = sendto_osmobts(fd_unix, ucontrol0, alert, sensor, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + confinfo.pa_power_act); + break; + } + } + + state_connection = rc; + + if (state_connection == SYSMO_MGR_DISCONNECTED) { + close(fd_unix); + socket_connect_cb(NULL); + } +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +120,26 @@ static void check_uctemp_timer_cb(void *data) sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); + confinfo.temp_pa_cur = temp_pa; + confinfo.temp_board_cur = temp_board; + + check_temperature(ucontrol0, confinfo.temp_min_pa_warn_limit, + confinfo.temp_max_pa_warn_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_pa_sever_limit, + confinfo.temp_max_pa_sever_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVER_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_warn_limit, + confinfo.temp_max_board_warn_limit, + temp_board, SBTS2050_TEMP_BOARD, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_sever_limit, + confinfo.temp_min_board_sever_limit, + temp_board, SBTS2050_TEMP_BOARD, + SBTS2050_SEVER_ALERT); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +169,7 @@ static void initialize_sbts2050(void) if (val != 0) return; } + trx_nr = val; ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); if (ucontrol0.fd < 0) { @@ -101,6 +178,10 @@ static void initialize_sbts2050(void) return; } + /* start handle for reconnect the socket in case of error */ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + temp_uc_timer.cb = check_uctemp_timer_cb; temp_uc_timer.data = &ucontrol0; check_uctemp_timer_cb(&ucontrol0); @@ -169,6 +250,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write); + close(fd_unix); exit(0); break; case SIGABRT: diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index ddb6774..87668e0 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -7,4 +7,9 @@ enum { DFIND, }; +enum { + SYSMO_MGR_DISCONNECTED = 0, + SYSMO_MGR_CONNECTED, +}; + #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..1cd2e9c 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c @@ -29,13 +29,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include +#include #include "btsconfig.h" #include "sysmobts_misc.h" @@ -49,10 +53,149 @@ #define SERIAL_ALLOC_SIZE 300 #define SIZE_HEADER_RSP 5 #define SIZE_HEADER_CMD 4 - +#define OM_ALLOC_SIZE 1024 +#define OM_HEADROOM_SIZE 128 +#define IPA_OML_PROTO 0xFF #ifdef BUILD_SBTS2050 /********************************************************************** + * Function send information to OsmoBts + *********************************************************************/ +static void add_sw_descr(struct msgb *msg) +{ + char file_version[255]; + char file_id[255]; + + strncpy(file_id, "sysmomgr", sizeof("sysmomgr")); + file_id[sizeof(file_id) - 1] = '\0'; + strncpy(file_version, PACKAGE_VERSION, sizeof(PACKAGE_VERSION)); + file_version[sizeof(file_version) - 1] = '\0'; + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), + (uint8_t *)file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), + (uint8_t *)file_version); +} + +static void add_probable_cause(struct msgb *msg) +{ + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); + msgb_v_put(msg, 0); + msgb_v_put(msg, 0); +} + +static void add_ipa_header(struct msgb *msg) +{ + struct ipaccess_head *hh; + + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); + hh->proto = IPA_OML_PROTO; + hh->len = htons(msg->len); +} + +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, + uint8_t obj_class, uint8_t bts_nr, + uint8_t trx_nr, uint8_t ts_nr) +{ + struct abis_om_fom_hdr *foh; + struct abis_om_hdr *omh; + + msg->l3h = msgb_push(msg, sizeof(*foh)); + foh = (struct abis_om_fom_hdr *) msg->l3h; + + foh->msg_type = msg_type; + foh->obj_class = obj_class; + foh->obj_inst.bts_nr = bts_nr; + foh->obj_inst.trx_nr = trx_nr; + foh->obj_inst.ts_nr = ts_nr; + + msg->l2h = msgb_push(msg, sizeof(*omh)); + omh = (struct abis_om_hdr *) msg->l2h; + + omh->mdisc = ABIS_OM_MDISC_FOM; + omh->placement = ABIS_OM_PLACEMENT_ONLY; + omh->sequence = 0; + omh->length = msgb_l3len(msg); +} + +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr) +{ + int rc; + struct msgb *msg; + const char *buf, *nsensor; + + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); + if (msg == NULL) { + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); + return -1; + } + + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0); + + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); + + switch (alert) { + case SBTS2050_WARN_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); + break; + case SBTS2050_SEVER_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); + break; + default: + LOGP(DTEMP, LOGL_ERROR, "Unknown attr severity type\n"); + goto err; + } + + add_probable_cause(msg); + + add_sw_descr(msg); + + switch (sensor) { + case SBTS2050_TEMP_BOARD: + buf = "Unusual temperature on the Board"; + nsensor = "Board"; + break; + case SBTS2050_TEMP_PA: + buf = "Unusual temperature on the PA"; + nsensor = "PA"; + break; + default: + LOGP(DTEMP, LOGL_ERROR, "Unknown sensor type\n"); + goto err; + } + strncpy(add_info->name_sensor, nsensor, sizeof(add_info->name_sensor)); + add_info->name_sensor[sizeof(add_info->name_sensor) - 1] = '\0'; + + msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf); + + /* If we need to send this structure to other machine, we need to pass + * the integer inside the structure to internet format (big endian) + */ + msgb_tl16v_put(msg, NM_ATT_ADD_INFO, + sizeof(struct sbts2050_config_info), + (const uint8_t *)add_info); + + add_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0) { + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); + close(fd_unix); + msgb_free(msg); + return SYSMO_MGR_DISCONNECTED; + } + + msgb_free(msg); + return SYSMO_MGR_CONNECTED; +err: + msgb_free(msg); + return -1; +} + +/********************************************************************** * Functions read/write from serial interface *********************************************************************/ static int hand_serial_read(int fd, struct msgb *msg, int numbytes) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index 01878f2..2654348 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -32,6 +32,34 @@ struct ucinfo { int pa; }; +enum sbts2050_alert_lvl { + SBTS2050_WARN_ALERT, + SBTS2050_SEVER_ALERT +}; + +enum sbts2050_temp_sensor { + SBTS2050_TEMP_BOARD, + SBTS2050_TEMP_PA +}; + +struct sbts2050_config_info { + char name_sensor[8]; + int temp_max_pa_warn_limit; + int temp_min_pa_warn_limit; + int temp_max_pa_sever_limit; + int temp_min_pa_sever_limit; + int temp_max_board_warn_limit; + int temp_min_board_warn_limit; + int temp_max_board_sever_limit; + int temp_min_board_sever_limit; + int max_power_red; + int slave_power_act; + int master_power_act; + int pa_power_act; + int temp_pa_cur; + int temp_board_cur; +}; + int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, enum sysmobts_temp_type type); @@ -43,6 +71,11 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa); int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status); +int sendto_osmobts(int fd_unix, struct uc *ucontrol, + enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr); + int sysmobts_update_hours(int no_epprom_write); enum sysmobts_firmware_type { -- 1.7.10.4 From pablo at gnumonks.org Mon Apr 14 12:13:07 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Mon, 14 Apr 2014 14:13:07 +0200 Subject: [osmo-bts PATCH 1/3 v8] src: Add OML support for sending failure message from manager In-Reply-To: <1397395125-14664-1-git-send-email-anayuso@sysmocom.de> References: <1397137238-12746-1-git-send-email-anayuso@sysmocom.de> <1397395125-14664-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140414121307.GA21855@localhost> On Sun, Apr 13, 2014 at 03:18:45PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > > With this patch, the manager monitors the sensors and send > OML Failure message from the Manager to the BTS and the BTS > to BSC, for having a report system of the sensors. Unless the project leaders have any further concern, this looks good to me: Acked-by: Pablo Neira Ayuso P.S: I think we don't use the acked-by here yet. Signed-off-by is questionable since there's is not Developer's certificate of origin in the project yet, but I like the Acked-by: for traceability reasons. Just in case you consider to include this. Patchwork automagically includes it when you download the patch from it btw. From anayuso at sysmocom.de Tue Apr 15 18:11:01 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Tue, 15 Apr 2014 20:11:01 +0200 Subject: [osmo-bts PATCH 1/3 v9] src: Add OML support for sending failure message from manager In-Reply-To: <1397395125-14664-1-git-send-email-anayuso@sysmocom.de> References: <1397395125-14664-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397585461-15749-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso With this patch, the manager monitors the sensors and send OML Failure message from the Manager to the BTS and the BTS to BSC, for having a report system of the sensors. Signed-off-by: Alvaro Neira Ayuso --- [changes in v9] * Closed the file descriptor in the case that the register fail * Added LOGP more information about the error * Changed the name of the function test_recv_msg to check_oml_msg * Removed the variable IPA_OML_PROTO for using IPAC_PROTO_OML * Moved SOCKET_PATH to sysmobts_mgr.h for using the same variable in the main program and the manager. * Changed the name of the function sbts2050_sock_init to oml_sock_unix_init * Changed the variable which contains the name SEVER to SEVERE * Changed the parameters of check_temperature to lowlimit and highlimit * Changed the name of the function sendto_osmobts to send_omlfailure * Removed the parameter ucontrol in the function send_omlfailure * Removed the close when I have checked the state disconnect in the function connect * Changed the name of the function add_ipa_header to prepend_ipa_header * Fixed the ipa header len for not considering the ipa_header size in the variable * Changed the variable which contains sever to severe in the structure config * Added function descriptions src/osmo-bts-sysmo/main.c | 183 +++++++++++++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 84 ++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 7 ++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 156 +++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 32 ++++++ 5 files changed, 461 insertions(+), 1 deletion(-) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..11e1878 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,8 +35,10 @@ #include #include +#include #include #include +#include #include #include @@ -45,6 +47,9 @@ #include #include #include +#include + +#include "misc/sysmobts_mgr.h" #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" @@ -52,6 +57,7 @@ #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" +#include "btsconfig.h" /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -258,6 +264,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT"); + unlink(SOCKET_PATH); break; case SIGABRT: case SIGUSR1: @@ -288,6 +295,175 @@ static int write_pid_file(char *procname) return 0; } +/********************************************************************** + * Function for checking that the OML msg received is well-formed + *********************************************************************/ +static int check_oml_msg(struct msgb *msg) +{ + struct ipaccess_head *hh; + struct abis_om_hdr *omh; + int abis_oml_hdr_len; + + if (msg->len < sizeof(struct ipaccess_head)) { + LOGP(DL1C, LOGL_ERROR, "Ipa header insufficient space %d %d\n", + msg->len, sizeof(struct ipaccess_head)); + return -1; + } + + hh = (struct ipaccess_head *)msg->data; + + if (hh->proto != IPAC_PROTO_OML) { + LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header protocol %x %x\n", + hh->proto, IPAC_PROTO_OML); + return -1; + } + + if (ntohs(hh->len) != msg->len - sizeof(struct ipaccess_head)) { + LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header msg size %d %d\n", + ntohs(hh->len), msg->len - sizeof(struct ipaccess_head)); + return -1; + } + + msgb_pull(msg, sizeof(struct ipaccess_head)); + + abis_oml_hdr_len = sizeof(struct abis_om_hdr); + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %d\n", + msg->len, abis_oml_hdr_len); + return -1; + } + + msg->l2h = msg->data; + + abis_oml_hdr_len += sizeof(struct abis_om_fom_hdr); + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, "Fom header insufficient space %d %d\n", + msg->len, abis_oml_hdr_len); + return -1; + } + + msg->l3h = msg->data + sizeof(struct abis_om_hdr); + + omh = (struct abis_om_hdr *) msg->l2h; + + if (omh->mdisc != ABIS_OM_MDISC_FOM) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x %x\n", + omh->mdisc, ABIS_OM_MDISC_FOM); + return -1; + } + + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value %x %x\n", + omh->placement, ABIS_OM_PLACEMENT_ONLY); + return -1; + } + + if (omh->sequence != 0) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value %d\n", + omh->sequence); + return -1; + } + + if (omh->length != sizeof(struct abis_om_fom_hdr)) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om length value %d %d\n", + omh->length, sizeof(struct abis_om_fom_hdr)); + return -1; + } + + return 0; +} + +/********************************************************************** + * Function for read the incoming OML msg from the unix domain socket + *********************************************************************/ +static int read_sock(struct osmo_fd *fd, unsigned int what) +{ + struct msgb *msg; + struct gsm_abis_mo *mo; + int rc; + + msg = oml_msgb_alloc(); + if (msg == NULL) { + LOGP(DL1C, LOGL_ERROR, "Failed alloc oml message.\n"); + return -1; + } + + rc = recv(fd->fd, msg->tail, msg->data_len, 0); + if (rc <= 0) { + close(fd->fd); + osmo_fd_unregister(fd); + fd->fd = -1; + goto err; + } + + msgb_put(msg, rc); + + if (check_oml_msg(msg) < 0) { + LOGP(DL1C, LOGL_ERROR, "Malformed receive message\n"); + goto err; + } + + mo = &bts->mo; + msg->trx = mo->bts->c0; + + return abis_oml_sendmsg(msg); + +err: + msgb_free(msg); + return -1; +} + +/********************************************************************** + * Function for accept connection from the unix domain socket + *********************************************************************/ +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *read_fd = (struct osmo_fd *)fd->data; + + if (read_fd->fd > -1) { + close(read_fd->fd); + osmo_fd_unregister(read_fd); + read_fd->fd = -1; + } + + cl = accept(sfd, NULL, NULL); + if (cl < 0) { + LOGP(DL1C, LOGL_ERROR, "Accept new unix domain connection.\n"); + return -1; + } + + read_fd->fd = cl; + if (osmo_fd_register(read_fd) != 0) { + LOGP(DL1C, LOGL_ERROR, "Register the read file desc.\n"); + close(cl); + read_fd->fd = -1; + return -1; + } + + return 0; +} + +/********************************************************************** + * Function for initialize the unix domain socket + *********************************************************************/ +static int oml_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) +{ + int rc; + + accept->cb = accept_unix_sock; + read->cb = read_sock; + read->when = BSC_FD_READ; + read->fd = -1; + accept->data = read; + + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + return rc; +} + int main(int argc, char **argv) { struct stat st; @@ -295,6 +471,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; + struct osmo_fd accept_fd, read_fd; int rc; tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -371,6 +548,12 @@ int main(int argc, char **argv) exit(1); } + rc = oml_sock_unix_init(&accept_fd, &read_fd); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(1); + } + if (daemonize) { rc = osmo_daemonize(); if (rc < 0) { diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..b686c79 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,9 @@ static int no_eeprom_write = 0; static int daemonize = 0; +static int fd_unix = -1; void *tall_mgr_ctx; +static struct sbts2050_config_info confinfo; /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -55,7 +58,62 @@ void *tall_mgr_ctx; /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ #define HOURS_TIMER_SECS (1 * 3600) +/* every 5 minutes try to reconnect if we have a problem in the communication*/ +#define CONNECT_TIMER_SECS 300 + #ifdef BUILD_SBTS2050 +static int trx_nr = -1; +static int state_connection; + + +/********************************************************************** + * Function for establish the connection with unix domain server + *********************************************************************/ +static struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0); + return; + } + + state_connection = SYSMO_MGR_CONNECTED; +} + +/********************************************************************** + * Function for check if the temperature is in warning/severe limits + *********************************************************************/ +static void check_temperature(struct uc *ucontrol0, int lowlimit, int highlimit, + int current_temp, + enum sbts2050_temp_sensor sensor, + enum sbts2050_alert_lvl alert) +{ + int rc; + + if (lowlimit >= current_temp || highlimit <= current_temp) { + switch (alert) { + case SBTS2050_WARN_ALERT: + rc = send_omlfailure(fd_unix, alert, sensor, &confinfo, + trx_nr); + break; + case SBTS2050_SEVERE_ALERT: + rc = send_omlfailure(fd_unix, alert, sensor, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + confinfo.pa_power_act); + break; + } + } + + state_connection = rc; + + if (state_connection == SYSMO_MGR_DISCONNECTED) + socket_connect_cb(NULL); +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +122,26 @@ static void check_uctemp_timer_cb(void *data) sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); + confinfo.temp_pa_cur = temp_pa; + confinfo.temp_board_cur = temp_board; + + check_temperature(ucontrol0, confinfo.temp_min_pa_warn_limit, + confinfo.temp_max_pa_warn_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_pa_severe_limit, + confinfo.temp_max_pa_severe_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVERE_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_warn_limit, + confinfo.temp_max_board_warn_limit, + temp_board, SBTS2050_TEMP_BOARD, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_severe_limit, + confinfo.temp_max_board_severe_limit, + temp_board, SBTS2050_TEMP_BOARD, + SBTS2050_SEVERE_ALERT); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +171,7 @@ static void initialize_sbts2050(void) if (val != 0) return; } + trx_nr = val; ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); if (ucontrol0.fd < 0) { @@ -101,6 +180,10 @@ static void initialize_sbts2050(void) return; } + /* start handle for reconnect the socket in case of error */ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + temp_uc_timer.cb = check_uctemp_timer_cb; temp_uc_timer.data = &ucontrol0; check_uctemp_timer_cb(&ucontrol0); @@ -169,6 +252,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write); + close(fd_unix); exit(0); break; case SIGABRT: diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index ddb6774..21f30a4 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -7,4 +7,11 @@ enum { DFIND, }; +enum { + SYSMO_MGR_DISCONNECTED = 0, + SYSMO_MGR_CONNECTED, +}; + +#define SOCKET_PATH "/var/run/bts_oml" + #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..037cb6f 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c @@ -29,13 +29,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include +#include #include "btsconfig.h" #include "sysmobts_misc.h" @@ -49,10 +53,160 @@ #define SERIAL_ALLOC_SIZE 300 #define SIZE_HEADER_RSP 5 #define SIZE_HEADER_CMD 4 - +#define OM_ALLOC_SIZE 1024 +#define OM_HEADROOM_SIZE 128 #ifdef BUILD_SBTS2050 /********************************************************************** + * Function for add TLV SW_DESCR + *********************************************************************/ +static void add_sw_descr(struct msgb *msg) +{ + char file_version[255]; + char file_id[255]; + + strncpy(file_id, "sysmomgr", sizeof("sysmomgr")); + file_id[sizeof(file_id) - 1] = '\0'; + strncpy(file_version, PACKAGE_VERSION, sizeof(PACKAGE_VERSION)); + file_version[sizeof(file_version) - 1] = '\0'; + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), + (uint8_t *)file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), + (uint8_t *)file_version); +} + +/********************************************************************** + * Function for add TLV PROB_CAUSE + *********************************************************************/ +static void add_probable_cause(struct msgb *msg) +{ + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); + msgb_v_put(msg, 0); + msgb_v_put(msg, 0); +} + +/********************************************************************** + * Function for add the Ipa header + *********************************************************************/ +static void prepend_ipa_header(struct msgb *msg) +{ + struct ipaccess_head *hh; + + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); + hh->proto = IPAC_PROTO_OML; + hh->len = htons(msg->len - sizeof(struct ipaccess_head)); +} + +/********************************************************************** + * Function for add the OM and FOM OML header + *********************************************************************/ +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, + uint8_t obj_class, uint8_t bts_nr, + uint8_t trx_nr, uint8_t ts_nr) +{ + struct abis_om_fom_hdr *foh; + struct abis_om_hdr *omh; + + msg->l3h = msgb_push(msg, sizeof(*foh)); + foh = (struct abis_om_fom_hdr *) msg->l3h; + + foh->msg_type = msg_type; + foh->obj_class = obj_class; + foh->obj_inst.bts_nr = bts_nr; + foh->obj_inst.trx_nr = trx_nr; + foh->obj_inst.ts_nr = ts_nr; + + msg->l2h = msgb_push(msg, sizeof(*omh)); + omh = (struct abis_om_hdr *) msg->l2h; + + omh->mdisc = ABIS_OM_MDISC_FOM; + omh->placement = ABIS_OM_PLACEMENT_ONLY; + omh->sequence = 0; + omh->length = msgb_l3len(msg); +} + +/********************************************************************** + * Function for send the oml failure event using the unix domain socket + *********************************************************************/ +int send_omlfailure(int fd_unix, enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr) +{ + int rc; + struct msgb *msg; + const char *buf, *nsensor; + + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); + if (msg == NULL) { + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); + return -1; + } + + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0); + + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); + + switch (alert) { + case SBTS2050_WARN_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); + break; + case SBTS2050_SEVERE_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); + break; + default: + LOGP(DTEMP, LOGL_ERROR, "Unknown attr severity type %d\n", + alert); + goto err; + } + + add_probable_cause(msg); + + add_sw_descr(msg); + + switch (sensor) { + case SBTS2050_TEMP_BOARD: + buf = "Unusual temperature on the Board"; + nsensor = "Board"; + break; + case SBTS2050_TEMP_PA: + buf = "Unusual temperature on the PA"; + nsensor = "PA"; + break; + default: + LOGP(DTEMP, LOGL_ERROR, "Unknown sensor type %d\n", sensor); + goto err; + } + strncpy(add_info->name_sensor, nsensor, sizeof(add_info->name_sensor)); + add_info->name_sensor[sizeof(add_info->name_sensor) - 1] = '\0'; + + msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf); + + /* If we need to send this structure to other machine, we need to pass + * the integer inside the structure to internet format (big endian) + */ + msgb_tl16v_put(msg, NM_ATT_ADD_INFO, + sizeof(struct sbts2050_config_info), + (const uint8_t *)add_info); + + prepend_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0 || rc != msg->len) { + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); + close(fd_unix); + msgb_free(msg); + return SYSMO_MGR_DISCONNECTED; + } + + msgb_free(msg); + return SYSMO_MGR_CONNECTED; +err: + msgb_free(msg); + return -1; +} + +/********************************************************************** * Functions read/write from serial interface *********************************************************************/ static int hand_serial_read(int fd, struct msgb *msg, int numbytes) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index 01878f2..c22a54b 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -32,6 +32,34 @@ struct ucinfo { int pa; }; +enum sbts2050_alert_lvl { + SBTS2050_WARN_ALERT, + SBTS2050_SEVERE_ALERT +}; + +enum sbts2050_temp_sensor { + SBTS2050_TEMP_BOARD, + SBTS2050_TEMP_PA +}; + +struct sbts2050_config_info { + char name_sensor[8]; + int temp_max_pa_warn_limit; + int temp_min_pa_warn_limit; + int temp_max_pa_severe_limit; + int temp_min_pa_severe_limit; + int temp_max_board_warn_limit; + int temp_min_board_warn_limit; + int temp_max_board_severe_limit; + int temp_min_board_severe_limit; + int reduce_max_power; + int slave_power_act; + int master_power_act; + int pa_power_act; + int temp_pa_cur; + int temp_board_cur; +}; + int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, enum sysmobts_temp_type type); @@ -43,6 +71,10 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa); int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status); +int send_omlfailure(int fd_unix, enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr); + int sysmobts_update_hours(int no_epprom_write); enum sysmobts_firmware_type { -- 1.7.10.4 From anayuso at sysmocom.de Wed Apr 16 12:06:22 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Wed, 16 Apr 2014 14:06:22 +0200 Subject: [osmo-bts PATCH 1/3 v10] src: Add OML support for sending failure message from manager In-Reply-To: <1397585461-15749-1-git-send-email-anayuso@sysmocom.de> References: <1397585461-15749-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397649982-17674-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso With this patch, the manager monitors the sensors and send OML Failure message from the Manager to the BTS and the BTS to BSC, for having a report system of the sensors. Signed-off-by: Alvaro Neira Ayuso --- [changes in v10] * Removed useless function description in this patch src/osmo-bts-sysmo/main.c | 176 +++++++++++++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 77 ++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 7 ++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 142 ++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 32 ++++++ 5 files changed, 433 insertions(+), 1 deletion(-) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 74ee47f..aafbc50 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,8 +35,10 @@ #include #include +#include #include #include +#include #include #include @@ -45,6 +47,9 @@ #include #include #include +#include + +#include "misc/sysmobts_mgr.h" #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" @@ -52,6 +57,7 @@ #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" +#include "btsconfig.h" /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -258,6 +264,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT"); + unlink(SOCKET_PATH); break; case SIGABRT: case SIGUSR1: @@ -288,6 +295,168 @@ static int write_pid_file(char *procname) return 0; } +/* + * In succesfully case, this function set again the pointers of the l2h and l3h + * of the OML message that we have received. In other case, we don't set the + * pointers of l2h and l3h + */ +static int check_oml_msg(struct msgb *msg) +{ + struct ipaccess_head *hh; + struct abis_om_hdr *omh; + int abis_oml_hdr_len; + + if (msg->len < sizeof(struct ipaccess_head)) { + LOGP(DL1C, LOGL_ERROR, "Ipa header insufficient space %d %d\n", + msg->len, sizeof(struct ipaccess_head)); + return -1; + } + + hh = (struct ipaccess_head *)msg->data; + + if (hh->proto != IPAC_PROTO_OML) { + LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header protocol %x %x\n", + hh->proto, IPAC_PROTO_OML); + return -1; + } + + if (ntohs(hh->len) != msg->len - sizeof(struct ipaccess_head)) { + LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header msg size %d %d\n", + ntohs(hh->len), msg->len - sizeof(struct ipaccess_head)); + return -1; + } + + msgb_pull(msg, sizeof(struct ipaccess_head)); + + abis_oml_hdr_len = sizeof(struct abis_om_hdr); + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %d\n", + msg->len, abis_oml_hdr_len); + return -1; + } + + msg->l2h = msg->data; + + abis_oml_hdr_len += sizeof(struct abis_om_fom_hdr); + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, "Fom header insufficient space %d %d\n", + msg->len, abis_oml_hdr_len); + return -1; + } + + msg->l3h = msg->data + sizeof(struct abis_om_hdr); + + omh = (struct abis_om_hdr *) msg->l2h; + + if (omh->mdisc != ABIS_OM_MDISC_FOM) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x %x\n", + omh->mdisc, ABIS_OM_MDISC_FOM); + return -1; + } + + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value %x %x\n", + omh->placement, ABIS_OM_PLACEMENT_ONLY); + return -1; + } + + if (omh->sequence != 0) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value %d\n", + omh->sequence); + return -1; + } + + if (omh->length != sizeof(struct abis_om_fom_hdr)) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om length value %d %d\n", + omh->length, sizeof(struct abis_om_fom_hdr)); + return -1; + } + + return 0; +} + +static int read_sock(struct osmo_fd *fd, unsigned int what) +{ + struct msgb *msg; + struct gsm_abis_mo *mo; + int rc; + + msg = oml_msgb_alloc(); + if (msg == NULL) { + LOGP(DL1C, LOGL_ERROR, "Failed alloc oml message.\n"); + return -1; + } + + rc = recv(fd->fd, msg->tail, msg->data_len, 0); + if (rc <= 0) { + close(fd->fd); + osmo_fd_unregister(fd); + fd->fd = -1; + goto err; + } + + msgb_put(msg, rc); + + if (check_oml_msg(msg) < 0) { + LOGP(DL1C, LOGL_ERROR, "Malformed receive message\n"); + goto err; + } + + mo = &bts->mo; + msg->trx = mo->bts->c0; + + return abis_oml_sendmsg(msg); + +err: + msgb_free(msg); + return -1; +} + +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *read_fd = (struct osmo_fd *)fd->data; + + if (read_fd->fd > -1) { + close(read_fd->fd); + osmo_fd_unregister(read_fd); + read_fd->fd = -1; + } + + cl = accept(sfd, NULL, NULL); + if (cl < 0) { + LOGP(DL1C, LOGL_ERROR, "Accept new unix domain connection.\n"); + return -1; + } + + read_fd->fd = cl; + if (osmo_fd_register(read_fd) != 0) { + LOGP(DL1C, LOGL_ERROR, "Register the read file desc.\n"); + close(cl); + read_fd->fd = -1; + return -1; + } + + return 0; +} + +static int oml_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) +{ + int rc; + + accept->cb = accept_unix_sock; + read->cb = read_sock; + read->when = BSC_FD_READ; + read->fd = -1; + accept->data = read; + + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + return rc; +} + int main(int argc, char **argv) { struct stat st; @@ -295,6 +464,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; + struct osmo_fd accept_fd, read_fd; int rc; tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -371,6 +541,12 @@ int main(int argc, char **argv) exit(1); } + rc = oml_sock_unix_init(&accept_fd, &read_fd); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(1); + } + if (daemonize) { rc = osmo_daemonize(); if (rc < 0) { diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..8dd97ec 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,9 @@ static int no_eeprom_write = 0; static int daemonize = 0; +static int fd_unix = -1; void *tall_mgr_ctx; +static struct sbts2050_config_info confinfo; /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -55,7 +58,55 @@ void *tall_mgr_ctx; /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ #define HOURS_TIMER_SECS (1 * 3600) +/* every 5 minutes try to reconnect if we have a problem in the communication*/ +#define CONNECT_TIMER_SECS 300 + #ifdef BUILD_SBTS2050 +static int trx_nr = -1; +static int state_connection; + +static struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0); + return; + } + + state_connection = SYSMO_MGR_CONNECTED; +} + +static void check_temperature(struct uc *ucontrol0, int lowlimit, int highlimit, + int current_temp, + enum sbts2050_temp_sensor sensor, + enum sbts2050_alert_lvl alert) +{ + int rc; + + if (lowlimit >= current_temp || highlimit <= current_temp) { + switch (alert) { + case SBTS2050_WARN_ALERT: + rc = send_omlfailure(fd_unix, alert, sensor, &confinfo, + trx_nr); + break; + case SBTS2050_SEVERE_ALERT: + rc = send_omlfailure(fd_unix, alert, sensor, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + confinfo.pa_power_act); + break; + } + } + + state_connection = rc; + + if (state_connection == SYSMO_MGR_DISCONNECTED) + socket_connect_cb(NULL); +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +115,26 @@ static void check_uctemp_timer_cb(void *data) sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); + confinfo.temp_pa_cur = temp_pa; + confinfo.temp_board_cur = temp_board; + + check_temperature(ucontrol0, confinfo.temp_min_pa_warn_limit, + confinfo.temp_max_pa_warn_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_pa_severe_limit, + confinfo.temp_max_pa_severe_limit, + temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVERE_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_warn_limit, + confinfo.temp_max_board_warn_limit, + temp_board, SBTS2050_TEMP_BOARD, SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, confinfo.temp_min_board_severe_limit, + confinfo.temp_max_board_severe_limit, + temp_board, SBTS2050_TEMP_BOARD, + SBTS2050_SEVERE_ALERT); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +164,7 @@ static void initialize_sbts2050(void) if (val != 0) return; } + trx_nr = val; ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); if (ucontrol0.fd < 0) { @@ -101,6 +173,10 @@ static void initialize_sbts2050(void) return; } + /* start handle for reconnect the socket in case of error */ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + temp_uc_timer.cb = check_uctemp_timer_cb; temp_uc_timer.data = &ucontrol0; check_uctemp_timer_cb(&ucontrol0); @@ -169,6 +245,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write); + close(fd_unix); exit(0); break; case SIGABRT: diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index ddb6774..21f30a4 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -7,4 +7,11 @@ enum { DFIND, }; +enum { + SYSMO_MGR_DISCONNECTED = 0, + SYSMO_MGR_CONNECTED, +}; + +#define SOCKET_PATH "/var/run/bts_oml" + #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..5e43089 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c @@ -29,13 +29,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include +#include #include "btsconfig.h" #include "sysmobts_misc.h" @@ -49,9 +53,145 @@ #define SERIAL_ALLOC_SIZE 300 #define SIZE_HEADER_RSP 5 #define SIZE_HEADER_CMD 4 - +#define OM_ALLOC_SIZE 1024 +#define OM_HEADROOM_SIZE 128 #ifdef BUILD_SBTS2050 + +static void add_sw_descr(struct msgb *msg) +{ + char file_version[255]; + char file_id[255]; + + strncpy(file_id, "sysmomgr", sizeof("sysmomgr")); + file_id[sizeof(file_id) - 1] = '\0'; + strncpy(file_version, PACKAGE_VERSION, sizeof(PACKAGE_VERSION)); + file_version[sizeof(file_version) - 1] = '\0'; + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), + (uint8_t *)file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), + (uint8_t *)file_version); +} + +static void add_probable_cause(struct msgb *msg) +{ + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); + msgb_v_put(msg, 0); + msgb_v_put(msg, 0); +} + +static void prepend_ipa_header(struct msgb *msg) +{ + struct ipaccess_head *hh; + + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); + hh->proto = IPAC_PROTO_OML; + hh->len = htons(msg->len - sizeof(struct ipaccess_head)); +} + +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, + uint8_t obj_class, uint8_t bts_nr, + uint8_t trx_nr, uint8_t ts_nr) +{ + struct abis_om_fom_hdr *foh; + struct abis_om_hdr *omh; + + msg->l3h = msgb_push(msg, sizeof(*foh)); + foh = (struct abis_om_fom_hdr *) msg->l3h; + + foh->msg_type = msg_type; + foh->obj_class = obj_class; + foh->obj_inst.bts_nr = bts_nr; + foh->obj_inst.trx_nr = trx_nr; + foh->obj_inst.ts_nr = ts_nr; + + msg->l2h = msgb_push(msg, sizeof(*omh)); + omh = (struct abis_om_hdr *) msg->l2h; + + omh->mdisc = ABIS_OM_MDISC_FOM; + omh->placement = ABIS_OM_PLACEMENT_ONLY; + omh->sequence = 0; + omh->length = msgb_l3len(msg); +} + +int send_omlfailure(int fd_unix, enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr) +{ + int rc; + struct msgb *msg; + const char *buf, *nsensor; + + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); + if (msg == NULL) { + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); + return -1; + } + + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0); + + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); + + switch (alert) { + case SBTS2050_WARN_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); + break; + case SBTS2050_SEVERE_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); + break; + default: + LOGP(DTEMP, LOGL_ERROR, "Unknown attr severity type %d\n", + alert); + goto err; + } + + add_probable_cause(msg); + + add_sw_descr(msg); + + switch (sensor) { + case SBTS2050_TEMP_BOARD: + buf = "Unusual temperature on the Board"; + nsensor = "Board"; + break; + case SBTS2050_TEMP_PA: + buf = "Unusual temperature on the PA"; + nsensor = "PA"; + break; + default: + LOGP(DTEMP, LOGL_ERROR, "Unknown sensor type %d\n", sensor); + goto err; + } + strncpy(add_info->name_sensor, nsensor, sizeof(add_info->name_sensor)); + add_info->name_sensor[sizeof(add_info->name_sensor) - 1] = '\0'; + + msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf); + + /* If we need to send this structure to other machine, we need to pass + * the integer inside the structure to internet format (big endian) + */ + msgb_tl16v_put(msg, NM_ATT_ADD_INFO, + sizeof(struct sbts2050_config_info), + (const uint8_t *)add_info); + + prepend_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0 || rc != msg->len) { + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); + close(fd_unix); + msgb_free(msg); + return SYSMO_MGR_DISCONNECTED; + } + + msgb_free(msg); + return SYSMO_MGR_CONNECTED; +err: + msgb_free(msg); + return -1; +} + /********************************************************************** * Functions read/write from serial interface *********************************************************************/ diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index 01878f2..c22a54b 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -32,6 +32,34 @@ struct ucinfo { int pa; }; +enum sbts2050_alert_lvl { + SBTS2050_WARN_ALERT, + SBTS2050_SEVERE_ALERT +}; + +enum sbts2050_temp_sensor { + SBTS2050_TEMP_BOARD, + SBTS2050_TEMP_PA +}; + +struct sbts2050_config_info { + char name_sensor[8]; + int temp_max_pa_warn_limit; + int temp_min_pa_warn_limit; + int temp_max_pa_severe_limit; + int temp_min_pa_severe_limit; + int temp_max_board_warn_limit; + int temp_min_board_warn_limit; + int temp_max_board_severe_limit; + int temp_min_board_severe_limit; + int reduce_max_power; + int slave_power_act; + int master_power_act; + int pa_power_act; + int temp_pa_cur; + int temp_board_cur; +}; + int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, enum sysmobts_temp_type type); @@ -43,6 +71,10 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa); int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status); +int send_omlfailure(int fd_unix, enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr); + int sysmobts_update_hours(int no_epprom_write); enum sysmobts_firmware_type { -- 1.7.10.4 From holger at freyther.de Wed Apr 16 21:13:12 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Wed, 16 Apr 2014 23:13:12 +0200 Subject: [osmo-bts PATCH 1/3 v10] src: Add OML support for sending failure message from manager In-Reply-To: <1397649982-17674-1-git-send-email-anayuso@sysmocom.de> References: <1397585461-15749-1-git-send-email-anayuso@sysmocom.de> <1397649982-17674-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140416211312.GA6236@xiaoyu.lan> On Wed, Apr 16, 2014 at 02:06:22PM +0200, Alvaro Neira Ayuso wrote: > +/* > + * In succesfully case, this function set again the pointers of the l2h and l3h > + * of the OML message that we have received. In other case, we don't set the > + * pointers of l2h and l3h > + */ > +static int check_oml_msg(struct msgb *msg) > +{ > + msg->l2h = msg->data; ... > + if (msg->len < abis_oml_hdr_len) > + return -1; > + > + msg->l3h = msg->data + sizeof(struct abis_om_hdr); > + if (omh->mdisc != ABIS_OM_MDISC_FOM) > + return -1; Code and comment do not match. This is why I asked you to say that in the error case the behavior is undefined. The other option would be to re-set l2h/l3h to NULL to make the code match your description. In terms of structure I had thought of a documentation like this: /** * \brief Check that the data in \param msg is a proper OML message * * This function verifies that the data in \param in msg is a proper * OML message and can be handled by later functions. In the successful * case the msg->l2h will now point to the OML header and the msg->l3h * will point to the FOM header. The value of l2h/l3h is undefined in * case the verification of the \param msg is failing. * * \param msg The message to analyze. msg->len starting from msg->data * will be analyzed. * \return This function returns X on success and Y on failure. */ From anayuso at sysmocom.de Mon Apr 28 11:44:32 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Mon, 28 Apr 2014 13:44:32 +0200 Subject: [osmo-bts PATCH 3/5 v11] src: Add OML support for sending failure message from manager In-Reply-To: <1397649982-17674-1-git-send-email-anayuso@sysmocom.de> References: <1397649982-17674-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1398685472-19232-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso With this patch, the manager monitors the sensors and send OML Failure message from the Manager to the BTS and the BTS to BSC, for having a report system of the sensors. Signed-off-by: Alvaro Neira Ayuso --- [changes in v11] * Moved the function prepend_oml_ipa_header and check_oml_msg to utils for using in the future. * Added Manufacture support in the function check_oml_msg * Changed the description of the function check_oml_msg for having more information about that function. * Changed the function check_temperature for returing 1 in the case that the current_temperature is between the parameters limit that we have used. Return 0 in the other case. src/osmo-bts-sysmo/Makefile.am | 4 +- src/osmo-bts-sysmo/main.c | 93 ++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 92 ++++++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 7 ++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 143 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_misc.h | 32 +++++++ src/osmo-bts-sysmo/utils.c | 124 +++++++++++++++++++++++++++ src/osmo-bts-sysmo/utils.h | 7 ++ 8 files changed, 499 insertions(+), 3 deletions(-) diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am index 1c08af3..e9ba949 100644 --- a/src/osmo-bts-sysmo/Makefile.am +++ b/src/osmo-bts-sysmo/Makefile.am @@ -22,8 +22,8 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) sysmobts_mgr_SOURCES = \ misc/sysmobts_mgr.c misc/sysmobts_misc.c \ - misc/sysmobts_par.c misc/sysmobts_nl.c -sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) + misc/sysmobts_par.c misc/sysmobts_nl.c utils.c +sysmobts_mgr_LDADD = $(COMMON_LDADD) sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 921103e..acdf6fc 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -35,8 +35,10 @@ #include #include +#include #include #include +#include #include #include @@ -45,6 +47,9 @@ #include #include #include +#include + +#include "misc/sysmobts_mgr.h" #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" @@ -258,6 +263,7 @@ static void signal_handler(int signal) case SIGINT: //osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL); bts_shutdown(bts, "SIGINT"); + unlink(SOCKET_PATH); break; case SIGABRT: case SIGUSR1: @@ -288,6 +294,86 @@ static int write_pid_file(char *procname) return 0; } +static int read_sock(struct osmo_fd *fd, unsigned int what) +{ + struct msgb *msg; + struct gsm_abis_mo *mo; + int rc; + + msg = oml_msgb_alloc(); + if (msg == NULL) { + LOGP(DL1C, LOGL_ERROR, "Failed alloc oml message.\n"); + return -1; + } + + rc = recv(fd->fd, msg->tail, msg->data_len, 0); + if (rc <= 0) { + close(fd->fd); + osmo_fd_unregister(fd); + fd->fd = -1; + goto err; + } + + msgb_put(msg, rc); + + if (check_oml_msg(msg) < 0) { + LOGP(DL1C, LOGL_ERROR, "Malformed receive message\n"); + goto err; + } + + mo = &bts->mo; + msg->trx = mo->bts->c0; + + return abis_oml_sendmsg(msg); + +err: + msgb_free(msg); + return -1; +} + +static int accept_unix_sock(struct osmo_fd *fd, unsigned int what) +{ + int sfd = fd->fd, cl; + struct osmo_fd *read_fd = (struct osmo_fd *)fd->data; + + if (read_fd->fd > -1) { + close(read_fd->fd); + osmo_fd_unregister(read_fd); + read_fd->fd = -1; + } + + cl = accept(sfd, NULL, NULL); + if (cl < 0) { + LOGP(DL1C, LOGL_ERROR, "Accept new unix domain connection.\n"); + return -1; + } + + read_fd->fd = cl; + if (osmo_fd_register(read_fd) != 0) { + LOGP(DL1C, LOGL_ERROR, "Register the read file desc.\n"); + close(cl); + read_fd->fd = -1; + return -1; + } + + return 0; +} + +static int oml_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) +{ + int rc; + + accept->cb = accept_unix_sock; + read->cb = read_sock; + read->when = BSC_FD_READ; + read->fd = -1; + accept->data = read; + + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); + return rc; +} + int main(int argc, char **argv) { struct stat st; @@ -295,6 +381,7 @@ int main(int argc, char **argv) struct gsm_bts_role_bts *btsb; struct e1inp_line *line; void *tall_msgb_ctx; + struct osmo_fd accept_fd, read_fd; int rc; tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); @@ -371,6 +458,12 @@ int main(int argc, char **argv) exit(1); } + rc = oml_sock_unix_init(&accept_fd, &read_fd); + if (rc < 0) { + perror("Error creating socket domain creation"); + exit(1); + } + if (daemonize) { rc = osmo_daemonize(); if (rc < 0) { diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 6c64d0f..51fdd83 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,9 @@ static int no_eeprom_write = 0; static int daemonize = 0; +static int fd_unix = -1; void *tall_mgr_ctx; +static struct sbts2050_config_info confinfo; /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -55,7 +58,63 @@ void *tall_mgr_ctx; /* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */ #define HOURS_TIMER_SECS (1 * 3600) +/* every 5 minutes try to reconnect if we have a problem in the communication*/ +#define CONNECT_TIMER_SECS 300 + #ifdef BUILD_SBTS2050 +static int trx_nr = -1; +static int state_connection; + +static struct osmo_timer_list connect_timer; +static void socket_connect_cb(void *data) +{ + fd_unix = osmo_sock_unix_init(SOCK_SEQPACKET, 0, SOCKET_PATH, + OSMO_SOCK_F_CONNECT); + if (fd_unix < 0) { + osmo_timer_schedule(&connect_timer, CONNECT_TIMER_SECS, 0); + return; + } + + state_connection = SYSMO_MGR_CONNECTED; +} + +static int check_temperature(struct uc *ucontrol0, int lowlimit, int highlimit, + int current_temp, + enum sbts2050_temp_sensor sensor, + enum sbts2050_alert_lvl alert) +{ + int rc; + + if (lowlimit >= current_temp || highlimit <= current_temp) { + switch (alert) { + case SBTS2050_WARN_ALERT: + rc = send_omlfailure(fd_unix, alert, sensor, &confinfo, + trx_nr); + break; + case SBTS2050_SEVERE_ALERT: + rc = send_omlfailure(fd_unix, alert, sensor, + &confinfo, trx_nr); + sbts2050_uc_power(ucontrol0, confinfo.master_power_act, + confinfo.slave_power_act, + confinfo.pa_power_act); + break; + default: + LOGP(DFIND, LOGL_ERROR, "Unknown alert type %d\n", + alert); + return -1; + } + } else { + return 0; + } + + state_connection = rc; + + if (state_connection == SYSMO_MGR_DISCONNECTED) + socket_connect_cb(NULL); + + return 1; +} + static struct osmo_timer_list temp_uc_timer; static void check_uctemp_timer_cb(void *data) { @@ -64,6 +123,33 @@ static void check_uctemp_timer_cb(void *data) sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); + confinfo.temp_pa_cur = temp_pa; + confinfo.temp_board_cur = temp_board; + + check_temperature(ucontrol0, + confinfo.temp_min_pa_warn_limit, + confinfo.temp_max_pa_warn_limit, + temp_pa, SBTS2050_TEMP_PA, + SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, + confinfo.temp_min_pa_severe_limit, + confinfo.temp_max_pa_severe_limit, + temp_pa, SBTS2050_TEMP_PA, + SBTS2050_SEVERE_ALERT); + + check_temperature(ucontrol0, + confinfo.temp_min_board_warn_limit, + confinfo.temp_max_board_warn_limit, + temp_board, SBTS2050_TEMP_BOARD, + SBTS2050_WARN_ALERT); + + check_temperature(ucontrol0, + confinfo.temp_min_board_severe_limit, + confinfo.temp_max_board_severe_limit, + temp_board, SBTS2050_TEMP_BOARD, + SBTS2050_SEVERE_ALERT); + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif @@ -93,6 +179,7 @@ static void initialize_sbts2050(void) if (val != 0) return; } + trx_nr = val; ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200); if (ucontrol0.fd < 0) { @@ -101,6 +188,10 @@ static void initialize_sbts2050(void) return; } + /* start handle for reconnect the socket in case of error */ + connect_timer.cb = socket_connect_cb; + socket_connect_cb(NULL); + temp_uc_timer.cb = check_uctemp_timer_cb; temp_uc_timer.data = &ucontrol0; check_uctemp_timer_cb(&ucontrol0); @@ -169,6 +260,7 @@ static void signal_handler(int signal) case SIGINT: sysmobts_check_temp(no_eeprom_write); sysmobts_update_hours(no_eeprom_write); + close(fd_unix); exit(0); break; case SIGABRT: diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index ddb6774..21f30a4 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -7,4 +7,11 @@ enum { DFIND, }; +enum { + SYSMO_MGR_DISCONNECTED = 0, + SYSMO_MGR_CONNECTED, +}; + +#define SOCKET_PATH "/var/run/bts_oml" + #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index 9ea26c2..fbbd6ee 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c @@ -29,14 +29,19 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include +#include +#include "utils.h" #include "btsconfig.h" #include "sysmobts_misc.h" #include "sysmobts_par.h" @@ -49,9 +54,145 @@ #define SERIAL_ALLOC_SIZE 300 #define SIZE_HEADER_RSP 5 #define SIZE_HEADER_CMD 4 - +#define OM_ALLOC_SIZE 1024 +#define OM_HEADROOM_SIZE 128 #ifdef BUILD_SBTS2050 +static void add_sw_descr(struct msgb *msg) +{ + char file_version[255]; + char file_id[255]; + + strncpy(file_id, "sysmomgr", sizeof("sysmomgr")); + file_id[sizeof(file_id) - 1] = '\0'; + strncpy(file_version, PACKAGE_VERSION, sizeof(PACKAGE_VERSION)); + file_version[sizeof(file_version) - 1] = '\0'; + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, strlen(file_id), + (uint8_t *)file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, strlen(file_version), + (uint8_t *)file_version); +} + +static void add_probable_cause(struct msgb *msg) +{ + msgb_tv_put(msg, NM_ATT_PROB_CAUSE, NM_PCAUSE_T_MANUF); + msgb_v_put(msg, 0); + msgb_v_put(msg, 0); +} + +static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, + uint8_t obj_class, uint8_t bts_nr, + uint8_t trx_nr, uint8_t ts_nr, int is_manuf) +{ + struct abis_om_fom_hdr *foh; + struct abis_om_hdr *omh; + + msg->l3h = msgb_push(msg, sizeof(*foh)); + foh = (struct abis_om_fom_hdr *) msg->l3h; + + foh->msg_type = msg_type; + foh->obj_class = obj_class; + foh->obj_inst.bts_nr = bts_nr; + foh->obj_inst.trx_nr = trx_nr; + foh->obj_inst.ts_nr = ts_nr; + + if (is_manuf) { + /* length byte, string + 0 termination */ + uint8_t *manuf = msgb_push(msg, 1 + sizeof(osmobts_magic)); + manuf[0] = strlen(osmobts_magic)+1; + memcpy(manuf+1, osmobts_magic, strlen(osmobts_magic)); + } + + msg->l2h = msgb_push(msg, sizeof(*omh)); + omh = (struct abis_om_hdr *) msg->l2h; + + if (is_manuf) + omh->mdisc = ABIS_OM_MDISC_MANUF; + else + omh->mdisc = ABIS_OM_MDISC_FOM; + omh->placement = ABIS_OM_PLACEMENT_ONLY; + omh->sequence = 0; + omh->length = msgb_l3len(msg); +} + +int send_omlfailure(int fd_unix, enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr) +{ + int rc; + struct msgb *msg; + const char *buf, *nsensor; + + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); + if (msg == NULL) { + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); + return -1; + } + + add_oml_hdr_msg(msg, NM_MT_FAILURE_EVENT_REP, 0, 0, trx_nr, 0, 0); + + msgb_tv_put(msg, NM_ATT_EVENT_TYPE, NM_EVT_ENV_FAIL); + + switch (alert) { + case SBTS2050_WARN_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_WARNING); + break; + case SBTS2050_SEVERE_ALERT: + msgb_tv_put(msg, NM_ATT_SEVERITY, NM_SEVER_CRITICAL); + break; + default: + LOGP(DTEMP, LOGL_ERROR, "Unknown attr severity type %d\n", + alert); + goto err; + } + + add_probable_cause(msg); + + add_sw_descr(msg); + + switch (sensor) { + case SBTS2050_TEMP_BOARD: + buf = "Unusual temperature on the Board"; + nsensor = "Board"; + break; + case SBTS2050_TEMP_PA: + buf = "Unusual temperature on the PA"; + nsensor = "PA"; + break; + default: + LOGP(DTEMP, LOGL_ERROR, "Unknown sensor type %d\n", sensor); + goto err; + } + strncpy(add_info->name_sensor, nsensor, sizeof(add_info->name_sensor)); + add_info->name_sensor[sizeof(add_info->name_sensor) - 1] = '\0'; + + msgb_tl16v_put(msg, NM_ATT_ADD_TEXT, strlen(buf), (const uint8_t *)buf); + + /* If we need to send this structure to other machine, we need to pass + * the integer inside the structure to internet format (big endian) + */ + msgb_tl16v_put(msg, NM_ATT_ADD_INFO, + sizeof(struct sbts2050_config_info), + (const uint8_t *)add_info); + + prepend_oml_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0 || rc != msg->len) { + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); + close(fd_unix); + msgb_free(msg); + return SYSMO_MGR_DISCONNECTED; + } + + msgb_free(msg); + return SYSMO_MGR_CONNECTED; +err: + msgb_free(msg); + return -1; +} + /********************************************************************** * Functions read/write from serial interface *********************************************************************/ diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index 01878f2..c22a54b 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -32,6 +32,34 @@ struct ucinfo { int pa; }; +enum sbts2050_alert_lvl { + SBTS2050_WARN_ALERT, + SBTS2050_SEVERE_ALERT +}; + +enum sbts2050_temp_sensor { + SBTS2050_TEMP_BOARD, + SBTS2050_TEMP_PA +}; + +struct sbts2050_config_info { + char name_sensor[8]; + int temp_max_pa_warn_limit; + int temp_min_pa_warn_limit; + int temp_max_pa_severe_limit; + int temp_min_pa_severe_limit; + int temp_max_board_warn_limit; + int temp_min_board_warn_limit; + int temp_max_board_severe_limit; + int temp_min_board_severe_limit; + int reduce_max_power; + int slave_power_act; + int master_power_act; + int pa_power_act; + int temp_pa_cur; + int temp_board_cur; +}; + int sysmobts_temp_get(enum sysmobts_temp_sensor sensor, enum sysmobts_temp_type type); @@ -43,6 +71,10 @@ void sbts2050_uc_power(struct uc *ucontrol, int pmaster, int pslave, int ppa); int sbts2050_uc_status(struct uc *ucontrol, enum sbts2050_status_rqt status); +int send_omlfailure(int fd_unix, enum sbts2050_alert_lvl alert, + enum sbts2050_temp_sensor sensor, + struct sbts2050_config_info *add_info, int trx_nr); + int sysmobts_update_hours(int no_epprom_write); enum sysmobts_firmware_type { diff --git a/src/osmo-bts-sysmo/utils.c b/src/osmo-bts-sysmo/utils.c index af1e5d2..ecf3960 100644 --- a/src/osmo-bts-sysmo/utils.c +++ b/src/osmo-bts-sysmo/utils.c @@ -27,6 +27,9 @@ #include #include +#include +#include + #include "femtobts.h" #include "l1_if.h" @@ -147,3 +150,124 @@ int sysmobts_get_power_trx(struct gsm_bts_trx *trx) return power_transmitter; } + +void prepend_oml_ipa_header(struct msgb *msg) +{ + struct ipaccess_head *hh; + + hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh)); + hh->proto = IPAC_PROTO_OML; + hh->len = htons(msg->len - sizeof(struct ipaccess_head)); +} + +/** + * \brief Check that the data in \param msg is a proper OML message + * + * This function verifies that the data in \param in msg is a proper + * OML message and can be handled by later functions. In the successful + * case the msg->l2h will now point to the OML header and the msg->l3h + * will point to the FOM header. The value of l2h/l3h is undefined in + * case the verification of the \param msg is failing. + * + * \param msg The message to analyze. msg->len starting from msg->data + * will be analyzed. + * \return This function returns the msg with the l2h/l3h pointers in the right + * direction on success and on failure, in the case that the msg doesn't contain + * the OML header or the OML header values aren't the expect, the function + * doesn't set the l2h and l3h. In the case that the msg don't contains the FOM + * header or the FOM header values aren't the expect, the function set the l2h + * but doesn't set the l3h. + */ + +int check_oml_msg(struct msgb *msg) +{ + struct ipaccess_head *hh; + struct abis_om_hdr *omh; + int abis_oml_hdr_len; + + if (msg->len < sizeof(struct ipaccess_head)) { + LOGP(DL1C, LOGL_ERROR, "Ipa header insufficient space %d %d\n", + msg->len, sizeof(struct ipaccess_head)); + return -1; + } + + hh = (struct ipaccess_head *)msg->data; + + if (hh->proto != IPAC_PROTO_OML) { + LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header protocol %x %x\n", + hh->proto, IPAC_PROTO_OML); + return -1; + } + + if (ntohs(hh->len) != msg->len - sizeof(struct ipaccess_head)) { + LOGP(DL1C, LOGL_ERROR, "Incorrect ipa header msg size %d %d\n", + ntohs(hh->len), msg->len - sizeof(struct ipaccess_head)); + return -1; + } + + msgb_pull(msg, sizeof(struct ipaccess_head)); + + abis_oml_hdr_len = sizeof(struct abis_om_hdr); + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %d\n", + msg->len, abis_oml_hdr_len); + return -1; + } + + msg->l2h = msg->data; + + omh = (struct abis_om_hdr *) msg->l2h; + + if (omh->mdisc != ABIS_OM_MDISC_FOM && + omh->mdisc != ABIS_OM_MDISC_MANUF) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x\n", + omh->mdisc); + return -1; + } + + if (omh->placement != ABIS_OM_PLACEMENT_ONLY) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value %x %x\n", + omh->placement, ABIS_OM_PLACEMENT_ONLY); + return -1; + } + + if (omh->sequence != 0) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value %d\n", + omh->sequence); + return -1; + } + + if (omh->length != sizeof(struct abis_om_fom_hdr)) { + LOGP(DL1C, LOGL_ERROR, "Incorrect om length value %d %d\n", + omh->length, sizeof(struct abis_om_fom_hdr)); + return -1; + } + + if (omh->mdisc == ABIS_OM_MDISC_MANUF) { + abis_oml_hdr_len += sizeof(osmobts_magic) + 1; + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, + "ID manuf osmobts insufficient space%d %d\n", + msg->len, abis_oml_hdr_len); + return -1; + } + } + + abis_oml_hdr_len += sizeof(struct abis_om_fom_hdr); + + if (msg->len < abis_oml_hdr_len) { + LOGP(DL1C, LOGL_ERROR, "Fom header insufficient space %d %d\n", + msg->len, abis_oml_hdr_len); + return -1; + } + + msg->l3h = msg->data + sizeof(struct abis_om_hdr); + + if (omh->mdisc == ABIS_OM_MDISC_MANUF) + msg->l3h = msg->l3h + sizeof(osmobts_magic) + 1; + + return 0; +} + diff --git a/src/osmo-bts-sysmo/utils.h b/src/osmo-bts-sysmo/utils.h index aef774c..10782bb 100644 --- a/src/osmo-bts-sysmo/utils.h +++ b/src/osmo-bts-sysmo/utils.h @@ -13,4 +13,11 @@ int sysmobts_select_femto_band(struct gsm_bts_trx *trx, uint16_t arfcn); int sysmobts_get_nominal_power(struct gsm_bts_trx *trx); int sysmobts_get_power_trx(struct gsm_bts_trx *trx); + +struct msgb; +static const char osmobts_magic[] = "com.osmobts"; + +void prepend_oml_ipa_header(struct msgb *msg); + +int check_oml_msg(struct msgb *msg); #endif -- 1.7.10.4 From anayuso at sysmocom.de Wed Apr 2 10:01:02 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Wed, 2 Apr 2014 12:01:02 +0200 Subject: [osmo-bts PATCH] misc/sysmo-mgr: Added Vty support for configuring the manager Message-ID: <1396432862-24546-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added the vty support for configuring the parameter for using the OML report in manager when we have anomalous temperature. Signed-off-by: Alvaro Neira Ayuso --- doc/examples/osmobts-mgr.cfg | 30 ++++ src/osmo-bts-sysmo/Makefile.am | 5 +- src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 43 ++++- src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 16 ++ src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c | 250 ++++++++++++++++++++++++++++ 5 files changed, 341 insertions(+), 3 deletions(-) create mode 100644 doc/examples/osmobts-mgr.cfg create mode 100644 src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c diff --git a/doc/examples/osmobts-mgr.cfg b/doc/examples/osmobts-mgr.cfg new file mode 100644 index 0000000..3d99495 --- /dev/null +++ b/doc/examples/osmobts-mgr.cfg @@ -0,0 +1,30 @@ +! +! SysmoMgr (0.3.0.137-7576) configuration saved from vty +!! +! +log stderr + logging filter all 1 + logging color 1 + logging timestamp 0 + logging level all everything + logging level temp info + logging level fw info + logging level find info + logging level lglobal notice + logging level llapd notice + logging level linp notice + logging level lmux notice + logging level lmi notice + logging level lmib notice + logging level lsms notice +! +line vty + no login +! +config-mgr + temp-warn-board -30 50 + temp-sever-board -50 80 + temp-warn-pa -30 50 + temp-sever-pa -50 80 + pwr-action 1 1 0 + pwr-pa-transmiter 0 diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am index 1c08af3..b4b7de7 100644 --- a/src/osmo-bts-sysmo/Makefile.am +++ b/src/osmo-bts-sysmo/Makefile.am @@ -22,8 +22,9 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) sysmobts_mgr_SOURCES = \ misc/sysmobts_mgr.c misc/sysmobts_misc.c \ - misc/sysmobts_par.c misc/sysmobts_nl.c -sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) + misc/sysmobts_par.c misc/sysmobts_nl.c \ + misc/sysmobts_mgr_vty.c +sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 525e526..4a879a3 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -54,6 +54,24 @@ static int state_connection = 0; void *tall_mgr_ctx; static struct sbts2050_config_info confinfo; +static struct sysmobts_mgr_instance sysmobts_mgr_inst = { + .config_file = "osmobts-mgr.cfg", +}; + +const char *sysmomgr_copyright = + "(C) 2012 by Harald Welte \r\n" + "(C) 2014 by Holger Hans Peter Freyther\r\n" + "License AGPLv3+: GNU AGPL version 2 or later \r\n" + "This is free software: you are free to change and redistribute it.\r\n" + "There is NO WARRANTY, to the extent permitted by law.\r\n"; + +static struct vty_app_info vty_info = { + .name = "SysmoMgr", + .version = PACKAGE_VERSION, + .go_parent_cb = mgr_vty_go_parent, + .is_config_node = mgr_vty_is_config_node, +}; + /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -202,13 +220,14 @@ static void print_help(void) printf(" -s Disable color\n"); printf(" -d CAT enable debugging\n"); printf(" -D daemonize\n"); + printf(" -c Specify the filename of the config file\n"); } static int parse_options(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "nhsd:")) != -1) { + while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { switch (opt) { case 'n': no_eeprom_write = 1; @@ -225,6 +244,9 @@ static int parse_options(int argc, char **argv) case 'D': daemonize = 1; break; + case 'c': + sysmobts_mgr_inst.config_file = optarg; + break; default: return -1; } @@ -428,6 +450,25 @@ int main(int argc, char **argv) if (rc < 0) exit(2); + vty_info.copyright = sysmomgr_copyright; + vty_init(&vty_info); + logging_vty_add_cmds(&mgr_log_info); + + sysmobts_mgr_vty_init(); + + rc = sysmobts_mgr_parse_config(sysmobts_mgr_inst.config_file, + &confinfo); + if (rc < 0) { + LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); + exit(2); + } + + rc = telnet_init(tall_msgb_ctx, NULL, 4247); + if (rc < 0) { + fprintf(stderr, "Error initializing telnet\n"); + exit(1); + } + /* start temperature check timer */ temp_timer.cb = check_temp_timer_cb; check_temp_timer_cb(NULL); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index ddb6774..4048854 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -1,10 +1,26 @@ #ifndef _SYSMOBTS_MGR_H #define _SYSMOBTS_MGR_H +#include +#include + enum { DTEMP, DFW, DFIND, }; +enum mgr_vty_node { + MGR_NODE = _LAST_OSMOVTY_NODE + 1, +}; + +enum node_type mgr_vty_go_parent(struct vty *vty); +int mgr_vty_is_config_node(struct vty *vty, int node); +int sysmobts_mgr_vty_init(); +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg); + +struct sysmobts_mgr_instance { + const char *config_file; +}; #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c new file mode 100644 index 0000000..b462181 --- /dev/null +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c @@ -0,0 +1,250 @@ +/* (C) 2014 by Sysmocom + * + * All Rights Reserved + * + * Author: Alvaro Neira Ayuso + * + * 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 "sysmobts_misc.h" +#include "sysmobts_mgr.h" + +static struct sbts2050_config_info *mgr_cfg = NULL; + +enum node_type mgr_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + case MGR_NODE: + vty->node = CONFIG_NODE; + break; + default: + vty->node = CONFIG_NODE; + } + return vty->node; +} + +int mgr_vty_is_config_node(struct vty *vty, int node) +{ + switch (node) { + case MGR_NODE: + return 1; + default: + return 0; + } +} + +#define MGR_STR "Configure the sysmobts-mgr\n" + +static struct cmd_node mgr_node = { + MGR_NODE, + "%s(config-mgr)# ", + 1, +}; + +DEFUN(cfg_mgr, cfg_mgr_cmd, + "config-mgr", + MGR_STR) +{ + vty->node = MGR_NODE; + return CMD_SUCCESS; +} + +DEFUN(show_mgr, show_mgr_cmd, "show mgr", + SHOW_STR "Display information about the mgr") +{ + vty_out(vty, " temp-warn-board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_sever_limit, + mgr_cfg->temp_max_board_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-warn-pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_sever_limit, + mgr_cfg->temp_max_pa_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " pwr_action Master:%d Slave:%d PA:%d%s", + mgr_cfg->master_power_act, + mgr_cfg->slave_power_act, + mgr_cfg->pa_power_act, + VTY_NEWLINE); + + vty_out(vty, " pwr-pa-transmiter %d%s", + mgr_cfg->pa_power, + VTY_NEWLINE); + return CMD_SUCCESS; +} + +static int config_write_mgr(struct vty *vty) +{ + vty_out(vty, "config-mgr%s", VTY_NEWLINE); + + vty_out(vty, " temp-warn-board %d %d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-board %d %d%s", + mgr_cfg->temp_min_board_sever_limit, + mgr_cfg->temp_max_board_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-warn-pa %d %d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-pa %d %d%s", + mgr_cfg->temp_min_pa_sever_limit, + mgr_cfg->temp_max_pa_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " pwr-action %d %d %d%s", + mgr_cfg->master_power_act, + mgr_cfg->slave_power_act, + mgr_cfg->pa_power_act, + VTY_NEWLINE); + + vty_out(vty, " pwr-pa-transmiter %d%s", + mgr_cfg->pa_power, + VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_warn, cfg_mgr_board_temp_warn_cmd, + "temp-warn-board <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the warning limit (Min and Max)" + "in the Board\n") +{ + mgr_cfg->temp_min_board_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_sever, cfg_mgr_board_temp_sever_cmd, + "temp-sever-board <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the several limit (Min and Max)" + "in the Board\n") +{ + mgr_cfg->temp_min_board_sever_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_sever_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_warn, cfg_mgr_pa_temp_warn_cmd, + "temp-warn-pa <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the warning limit (Min and Max)" + "in the PA\n") +{ + mgr_cfg->temp_min_pa_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_sever, cfg_mgr_pa_temp_sever_cmd, + "temp-sever-pa <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the several limit (Min and Max)" + "in the PA\n") +{ + mgr_cfg->temp_min_pa_sever_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_sever_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pwr_action, cfg_mgr_pwr_action_cmd, + "pwr-action (0|1) (0|1) (0|1)", + MGR_STR "Action for switching on (1) | off (0)" + "the Master, Slave and PA\n") +{ + mgr_cfg->master_power_act = atoi(argv[0]); + mgr_cfg->slave_power_act = atoi(argv[1]); + mgr_cfg->pa_power_act = atoi(argv[2]); + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_baud_action, cfg_mgr_pa_baud_action_cmd, + "pwr-pa-transmiter <0-255>", + MGR_STR "Power baud transmition in the PA\n") +{ + mgr_cfg->pa_power = atoi(argv[0]);; + + return CMD_SUCCESS; +} + +int sysmobts_mgr_vty_init() + +{ + install_element_ve(&show_mgr_cmd); + + install_node(&mgr_node, config_write_mgr); + install_element(CONFIG_NODE, &cfg_mgr_cmd); + install_default(MGR_NODE); + + install_element(MGR_NODE, &cfg_mgr_board_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_board_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pwr_action_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_baud_action_cmd); + + return 0; +} + +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg) +{ + int rc; + + mgr_cfg = cfg; + + rc = vty_read_config_file(config_file, NULL); + if (rc < 0) { + fprintf(stderr, "Failed to parse the config file: '%s'\n", + config_file); + return rc; + } + + return 0; +} -- 1.7.10.4 From anayuso at sysmocom.de Tue Apr 8 12:35:26 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Tue, 8 Apr 2014 14:35:26 +0200 Subject: [osmo-bts PATCH 2/3 v2] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1396432862-24546-1-git-send-email-anayuso@sysmocom.de> References: <1396432862-24546-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1396960526-14064-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added the vty support for configuring the parameter for using the OML report in manager when we have anomalous temperature. Signed-off-by: Alvaro Neira Ayuso --- v2: Changed the functions for init the max_power_red value that we want to use in case of failure. doc/examples/osmobts-mgr.cfg | 30 ++++ src/osmo-bts-sysmo/Makefile.am | 5 +- src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 43 ++++- src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 16 ++ src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c | 250 ++++++++++++++++++++++++++++ 5 files changed, 341 insertions(+), 3 deletions(-) create mode 100644 doc/examples/osmobts-mgr.cfg create mode 100644 src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c diff --git a/doc/examples/osmobts-mgr.cfg b/doc/examples/osmobts-mgr.cfg new file mode 100644 index 0000000..f1c4e8e --- /dev/null +++ b/doc/examples/osmobts-mgr.cfg @@ -0,0 +1,30 @@ +! +! SysmoMgr (0.3.0.137-7576) configuration saved from vty +!! +! +log stderr + logging filter all 1 + logging color 1 + logging timestamp 0 + logging level all everything + logging level temp info + logging level fw info + logging level find info + logging level lglobal notice + logging level llapd notice + logging level linp notice + logging level lmux notice + logging level lmi notice + logging level lmib notice + logging level lsms notice +! +line vty + no login +! +config-mgr + temp-warn-board -30 50 + temp-sever-board -50 80 + temp-warn-pa -30 50 + temp-sever-pa -50 80 + pwr-action 1 1 0 + pwr-max-transmiter 32 diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am index 1c08af3..b4b7de7 100644 --- a/src/osmo-bts-sysmo/Makefile.am +++ b/src/osmo-bts-sysmo/Makefile.am @@ -22,8 +22,9 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) sysmobts_mgr_SOURCES = \ misc/sysmobts_mgr.c misc/sysmobts_misc.c \ - misc/sysmobts_par.c misc/sysmobts_nl.c -sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) + misc/sysmobts_par.c misc/sysmobts_nl.c \ + misc/sysmobts_mgr_vty.c +sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index b8813f0..0fb1221 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -57,6 +57,24 @@ static int fd_unix = -1; void *tall_mgr_ctx; static struct sbts2050_config_info confinfo; +static struct sysmobts_mgr_instance sysmobts_mgr_inst = { + .config_file = "osmobts-mgr.cfg", +}; + +const char *sysmomgr_copyright = + "(C) 2012 by Harald Welte \r\n" + "(C) 2014 by Holger Hans Peter Freyther\r\n" + "License AGPLv3+: GNU AGPL version 2 or later \r\n" + "This is free software: you are free to change and redistribute it.\r\n" + "There is NO WARRANTY, to the extent permitted by law.\r\n"; + +static struct vty_app_info vty_info = { + .name = "SysmoMgr", + .version = PACKAGE_VERSION, + .go_parent_cb = mgr_vty_go_parent, + .is_config_node = mgr_vty_is_config_node, +}; + /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -219,13 +237,14 @@ static void print_help(void) printf(" -s Disable color\n"); printf(" -d CAT enable debugging\n"); printf(" -D daemonize\n"); + printf(" -c Specify the filename of the config file\n"); } static int parse_options(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "nhsd:")) != -1) { + while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { switch (opt) { case 'n': no_eeprom_write = 1; @@ -242,6 +261,9 @@ static int parse_options(int argc, char **argv) case 'D': daemonize = 1; break; + case 'c': + sysmobts_mgr_inst.config_file = optarg; + break; default: return -1; } @@ -445,6 +467,25 @@ int main(int argc, char **argv) if (rc < 0) exit(2); + vty_info.copyright = sysmomgr_copyright; + vty_init(&vty_info); + logging_vty_add_cmds(&mgr_log_info); + + sysmobts_mgr_vty_init(); + + rc = sysmobts_mgr_parse_config(sysmobts_mgr_inst.config_file, + &confinfo); + if (rc < 0) { + LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); + exit(2); + } + + rc = telnet_init(tall_msgb_ctx, NULL, 4247); + if (rc < 0) { + fprintf(stderr, "Error initializing telnet\n"); + exit(1); + } + /* start temperature check timer */ temp_timer.cb = check_temp_timer_cb; check_temp_timer_cb(NULL); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index ddb6774..d89c46f 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -1,10 +1,26 @@ #ifndef _SYSMOBTS_MGR_H #define _SYSMOBTS_MGR_H +#include +#include + enum { DTEMP, DFW, DFIND, }; +enum mgr_vty_node { + MGR_NODE = _LAST_OSMOVTY_NODE + 1, +}; + +enum node_type mgr_vty_go_parent(struct vty *vty); +int mgr_vty_is_config_node(struct vty *vty, int node); +int sysmobts_mgr_vty_init(void); +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg); + +struct sysmobts_mgr_instance { + const char *config_file; +}; #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c new file mode 100644 index 0000000..412c2bc --- /dev/null +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c @@ -0,0 +1,250 @@ +/* (C) 2014 by Sysmocom + * + * All Rights Reserved + * + * Author: Alvaro Neira Ayuso + * + * 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 "sysmobts_misc.h" +#include "sysmobts_mgr.h" + +static struct sbts2050_config_info *mgr_cfg = NULL; + +enum node_type mgr_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + case MGR_NODE: + vty->node = CONFIG_NODE; + break; + default: + vty->node = CONFIG_NODE; + } + return vty->node; +} + +int mgr_vty_is_config_node(struct vty *vty, int node) +{ + switch (node) { + case MGR_NODE: + return 1; + default: + return 0; + } +} + +#define MGR_STR "Configure the sysmobts-mgr\n" + +static struct cmd_node mgr_node = { + MGR_NODE, + "%s(config-mgr)# ", + 1, +}; + +DEFUN(cfg_mgr, cfg_mgr_cmd, + "config-mgr", + MGR_STR) +{ + vty->node = MGR_NODE; + return CMD_SUCCESS; +} + +DEFUN(show_mgr, show_mgr_cmd, "show mgr", + SHOW_STR "Display information about the mgr") +{ + vty_out(vty, " temp-warn-board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_sever_limit, + mgr_cfg->temp_max_board_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-warn-pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_sever_limit, + mgr_cfg->temp_max_pa_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " pwr_action Master:%d Slave:%d PA:%d%s", + mgr_cfg->master_power_act, + mgr_cfg->slave_power_act, + mgr_cfg->pa_power_act, + VTY_NEWLINE); + + vty_out(vty, " pwr-max-transmiter %d%s", + mgr_cfg->max_power_red, + VTY_NEWLINE); + return CMD_SUCCESS; +} + +static int config_write_mgr(struct vty *vty) +{ + vty_out(vty, "config-mgr%s", VTY_NEWLINE); + + vty_out(vty, " temp-warn-board %d %d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-board %d %d%s", + mgr_cfg->temp_min_board_sever_limit, + mgr_cfg->temp_max_board_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-warn-pa %d %d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-pa %d %d%s", + mgr_cfg->temp_min_pa_sever_limit, + mgr_cfg->temp_max_pa_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " pwr-action %d %d %d%s", + mgr_cfg->master_power_act, + mgr_cfg->slave_power_act, + mgr_cfg->pa_power_act, + VTY_NEWLINE); + + vty_out(vty, " pwr-max-transmiter %d%s", + mgr_cfg->max_power_red, + VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_warn, cfg_mgr_board_temp_warn_cmd, + "temp-warn-board <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the warning limit (Min and Max)" + "in the Board\n") +{ + mgr_cfg->temp_min_board_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_sever, cfg_mgr_board_temp_sever_cmd, + "temp-sever-board <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the several limit (Min and Max)" + "in the Board\n") +{ + mgr_cfg->temp_min_board_sever_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_sever_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_warn, cfg_mgr_pa_temp_warn_cmd, + "temp-warn-pa <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the warning limit (Min and Max)" + "in the PA\n") +{ + mgr_cfg->temp_min_pa_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_sever, cfg_mgr_pa_temp_sever_cmd, + "temp-sever-pa <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the several limit (Min and Max)" + "in the PA\n") +{ + mgr_cfg->temp_min_pa_sever_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_sever_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pwr_action, cfg_mgr_pwr_action_cmd, + "pwr-action (0|1) (0|1) (0|1)", + MGR_STR "Action for switching on (1) | off (0)" + "the Master, Slave and PA\n") +{ + mgr_cfg->master_power_act = atoi(argv[0]); + mgr_cfg->slave_power_act = atoi(argv[1]); + mgr_cfg->pa_power_act = atoi(argv[2]); + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_baud_action, cfg_mgr_pa_baud_action_cmd, + "pwr-max-transmiter <0-255>", + MGR_STR "Power baud transmition in the PA\n") +{ + mgr_cfg->max_power_red = atoi(argv[0]); + + return CMD_SUCCESS; +} + +int sysmobts_mgr_vty_init(void) + +{ + install_element_ve(&show_mgr_cmd); + + install_node(&mgr_node, config_write_mgr); + install_element(CONFIG_NODE, &cfg_mgr_cmd); + install_default(MGR_NODE); + + install_element(MGR_NODE, &cfg_mgr_board_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_board_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pwr_action_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_baud_action_cmd); + + return 0; +} + +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg) +{ + int rc; + + mgr_cfg = cfg; + + rc = vty_read_config_file(config_file, NULL); + if (rc < 0) { + fprintf(stderr, "Failed to parse the config file: '%s'\n", + config_file); + return rc; + } + + return 0; +} -- 1.7.10.4 From pablo at gnumonks.org Wed Apr 9 08:37:10 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Wed, 9 Apr 2014 10:37:10 +0200 Subject: [osmo-bts PATCH 2/3 v2] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1396960526-14064-1-git-send-email-anayuso@sysmocom.de> References: <1396432862-24546-1-git-send-email-anayuso@sysmocom.de> <1396960526-14064-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140409083710.GB5744@localhost> On Tue, Apr 08, 2014 at 02:35:26PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > > Added the vty support for configuring the parameter for using the > OML report in manager when we have anomalous temperature. > > Signed-off-by: Alvaro Neira Ayuso > --- > v2: Changed the functions for init the max_power_red value that we want to use > in case of failure. > > doc/examples/osmobts-mgr.cfg | 30 ++++ > src/osmo-bts-sysmo/Makefile.am | 5 +- > src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 43 ++++- > src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 16 ++ > src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c | 250 ++++++++++++++++++++++++++++ > 5 files changed, 341 insertions(+), 3 deletions(-) > create mode 100644 doc/examples/osmobts-mgr.cfg > create mode 100644 src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c > > diff --git a/doc/examples/osmobts-mgr.cfg b/doc/examples/osmobts-mgr.cfg > new file mode 100644 > index 0000000..f1c4e8e > --- /dev/null > +++ b/doc/examples/osmobts-mgr.cfg > @@ -0,0 +1,30 @@ > +! > +! SysmoMgr (0.3.0.137-7576) configuration saved from vty > +!! > +! > +log stderr > + logging filter all 1 > + logging color 1 > + logging timestamp 0 > + logging level all everything > + logging level temp info > + logging level fw info > + logging level find info > + logging level lglobal notice > + logging level llapd notice > + logging level linp notice > + logging level lmux notice > + logging level lmi notice > + logging level lmib notice > + logging level lsms notice > +! > +line vty > + no login > +! > +config-mgr > + temp-warn-board -30 50 > + temp-sever-board -50 80 > + temp-warn-pa -30 50 > + temp-sever-pa -50 80 > + pwr-action 1 1 0 > + pwr-max-transmiter 32 > diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am > index 1c08af3..b4b7de7 100644 > --- a/src/osmo-bts-sysmo/Makefile.am > +++ b/src/osmo-bts-sysmo/Makefile.am > @@ -22,8 +22,9 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) > > sysmobts_mgr_SOURCES = \ > misc/sysmobts_mgr.c misc/sysmobts_misc.c \ > - misc/sysmobts_par.c misc/sysmobts_nl.c > -sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) > + misc/sysmobts_par.c misc/sysmobts_nl.c \ > + misc/sysmobts_mgr_vty.c > +sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) > > sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c > sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > index b8813f0..0fb1221 100644 > --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > @@ -57,6 +57,24 @@ static int fd_unix = -1; > void *tall_mgr_ctx; > static struct sbts2050_config_info confinfo; > > +static struct sysmobts_mgr_instance sysmobts_mgr_inst = { > + .config_file = "osmobts-mgr.cfg", > +}; > + > +const char *sysmomgr_copyright = > + "(C) 2012 by Harald Welte \r\n" > + "(C) 2014 by Holger Hans Peter Freyther\r\n" > + "License AGPLv3+: GNU AGPL version 2 or later \r\n" > + "This is free software: you are free to change and redistribute it.\r\n" > + "There is NO WARRANTY, to the extent permitted by law.\r\n"; > + > +static struct vty_app_info vty_info = { > + .name = "SysmoMgr", > + .version = PACKAGE_VERSION, > + .go_parent_cb = mgr_vty_go_parent, > + .is_config_node = mgr_vty_is_config_node, > +}; > + > /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ > #define TEMP_TIMER_SECS (6 * 3600) > > @@ -219,13 +237,14 @@ static void print_help(void) > printf(" -s Disable color\n"); > printf(" -d CAT enable debugging\n"); > printf(" -D daemonize\n"); > + printf(" -c Specify the filename of the config file\n"); > } > > static int parse_options(int argc, char **argv) > { > int opt; > > - while ((opt = getopt(argc, argv, "nhsd:")) != -1) { > + while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { > switch (opt) { > case 'n': > no_eeprom_write = 1; > @@ -242,6 +261,9 @@ static int parse_options(int argc, char **argv) > case 'D': > daemonize = 1; > break; > + case 'c': > + sysmobts_mgr_inst.config_file = optarg; > + break; > default: > return -1; > } > @@ -445,6 +467,25 @@ int main(int argc, char **argv) > if (rc < 0) > exit(2); > > + vty_info.copyright = sysmomgr_copyright; > + vty_init(&vty_info); > + logging_vty_add_cmds(&mgr_log_info); > + > + sysmobts_mgr_vty_init(); > + > + rc = sysmobts_mgr_parse_config(sysmobts_mgr_inst.config_file, > + &confinfo); > + if (rc < 0) { > + LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); > + exit(2); > + } > + > + rc = telnet_init(tall_msgb_ctx, NULL, 4247); > + if (rc < 0) { > + fprintf(stderr, "Error initializing telnet\n"); > + exit(1); > + } > + > /* start temperature check timer */ > temp_timer.cb = check_temp_timer_cb; > check_temp_timer_cb(NULL); > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h > index ddb6774..d89c46f 100644 > --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h > +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h > @@ -1,10 +1,26 @@ > #ifndef _SYSMOBTS_MGR_H > #define _SYSMOBTS_MGR_H > > +#include > +#include > + > enum { > DTEMP, > DFW, > DFIND, > }; > > +enum mgr_vty_node { > + MGR_NODE = _LAST_OSMOVTY_NODE + 1, > +}; > + > +enum node_type mgr_vty_go_parent(struct vty *vty); > +int mgr_vty_is_config_node(struct vty *vty, int node); > +int sysmobts_mgr_vty_init(void); > +int sysmobts_mgr_parse_config(const char *config_file, > + struct sbts2050_config_info *cfg); > + > +struct sysmobts_mgr_instance { > + const char *config_file; > +}; > #endif > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c > new file mode 100644 > index 0000000..412c2bc > --- /dev/null > +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c > @@ -0,0 +1,250 @@ > +/* (C) 2014 by Sysmocom by sysmocom - s.f.m.c. GmbH > + * > + * All Rights Reserved > + * > + * Author: Alvaro Neira Ayuso > + * > + * 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 "sysmobts_misc.h" > +#include "sysmobts_mgr.h" > + > +static struct sbts2050_config_info *mgr_cfg = NULL; > + > +enum node_type mgr_vty_go_parent(struct vty *vty) > +{ > + switch (vty->node) { > + case MGR_NODE: > + vty->node = CONFIG_NODE; > + break; > + default: > + vty->node = CONFIG_NODE; > + } > + return vty->node; > +} > + > +int mgr_vty_is_config_node(struct vty *vty, int node) > +{ > + switch (node) { > + case MGR_NODE: > + return 1; > + default: > + return 0; > + } > +} > + > +#define MGR_STR "Configure the sysmobts-mgr\n" > + > +static struct cmd_node mgr_node = { > + MGR_NODE, > + "%s(config-mgr)# ", > + 1, > +}; > + > +DEFUN(cfg_mgr, cfg_mgr_cmd, > + "config-mgr", > + MGR_STR) > +{ > + vty->node = MGR_NODE; > + return CMD_SUCCESS; > +} > + > +DEFUN(show_mgr, show_mgr_cmd, "show mgr", > + SHOW_STR "Display information about the mgr") > +{ > + vty_out(vty, " temp-warn-board Min:%d Max:%d%s", > + mgr_cfg->temp_min_board_warn_limit, > + mgr_cfg->temp_max_board_warn_limit, > + VTY_NEWLINE); Coding style nitpick: vty_out(vty, ... mgr_cfg->temp_min_board_warn_limit, Apart from those nitpicks, this looks good to me. From holger at freyther.de Wed Apr 9 15:17:07 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Wed, 9 Apr 2014 17:17:07 +0200 Subject: [osmo-bts PATCH 2/3 v2] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <20140409083710.GB5744@localhost> References: <1396432862-24546-1-git-send-email-anayuso@sysmocom.de> <1396960526-14064-1-git-send-email-anayuso@sysmocom.de> <20140409083710.GB5744@localhost> Message-ID: <20140409151707.GE26207@xiaoyu.lan> On Wed, Apr 09, 2014 at 10:37:10AM +0200, Pablo Neira Ayuso wrote: > > + rc = telnet_init(tall_msgb_ctx, NULL, 4247); This port number is already used by osmocomBB. Please have a look at: http://openbsc.osmocom.org/trac/wiki/PortNumbers and then claim a number from it. From anayuso at sysmocom.de Thu Apr 10 10:25:37 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Thu, 10 Apr 2014 12:25:37 +0200 Subject: [osmo-bts PATCH 2/3 v3] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1396960526-14064-1-git-send-email-anayuso@sysmocom.de> References: <1396960526-14064-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397125537-28345-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added the vty support for configuring the parameter for using the OML report in manager when we have anomalous temperature. Signed-off-by: Alvaro Neira Ayuso --- [changes in v3] * Fixed some coding style errors * Changed the port of the sysmo-mgr vty because the previous was already being used doc/examples/osmobts-mgr.cfg | 30 ++++ src/osmo-bts-sysmo/Makefile.am | 5 +- src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 43 ++++- src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 16 ++ src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c | 250 ++++++++++++++++++++++++++++ 5 files changed, 341 insertions(+), 3 deletions(-) create mode 100644 doc/examples/osmobts-mgr.cfg create mode 100644 src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c diff --git a/doc/examples/osmobts-mgr.cfg b/doc/examples/osmobts-mgr.cfg new file mode 100644 index 0000000..f1c4e8e --- /dev/null +++ b/doc/examples/osmobts-mgr.cfg @@ -0,0 +1,30 @@ +! +! SysmoMgr (0.3.0.137-7576) configuration saved from vty +!! +! +log stderr + logging filter all 1 + logging color 1 + logging timestamp 0 + logging level all everything + logging level temp info + logging level fw info + logging level find info + logging level lglobal notice + logging level llapd notice + logging level linp notice + logging level lmux notice + logging level lmi notice + logging level lmib notice + logging level lsms notice +! +line vty + no login +! +config-mgr + temp-warn-board -30 50 + temp-sever-board -50 80 + temp-warn-pa -30 50 + temp-sever-pa -50 80 + pwr-action 1 1 0 + pwr-max-transmiter 32 diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am index 1c08af3..b4b7de7 100644 --- a/src/osmo-bts-sysmo/Makefile.am +++ b/src/osmo-bts-sysmo/Makefile.am @@ -22,8 +22,9 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) sysmobts_mgr_SOURCES = \ misc/sysmobts_mgr.c misc/sysmobts_misc.c \ - misc/sysmobts_par.c misc/sysmobts_nl.c -sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) + misc/sysmobts_par.c misc/sysmobts_nl.c \ + misc/sysmobts_mgr_vty.c +sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 7a50bdc..2635c5f 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -57,6 +57,24 @@ static int fd_unix = -1; void *tall_mgr_ctx; static struct sbts2050_config_info confinfo; +static struct sysmobts_mgr_instance sysmobts_mgr_inst = { + .config_file = "osmobts-mgr.cfg", +}; + +const char *sysmomgr_copyright = + "(C) 2012 by Harald Welte \r\n" + "(C) 2014 by Holger Hans Peter Freyther\r\n" + "License AGPLv3+: GNU AGPL version 2 or later \r\n" + "This is free software: you are free to change and redistribute it.\r\n" + "There is NO WARRANTY, to the extent permitted by law.\r\n"; + +static struct vty_app_info vty_info = { + .name = "SysmoMgr", + .version = PACKAGE_VERSION, + .go_parent_cb = mgr_vty_go_parent, + .is_config_node = mgr_vty_is_config_node, +}; + /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -217,13 +235,14 @@ static void print_help(void) printf(" -s Disable color\n"); printf(" -d CAT enable debugging\n"); printf(" -D daemonize\n"); + printf(" -c Specify the filename of the config file\n"); } static int parse_options(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "nhsd:")) != -1) { + while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { switch (opt) { case 'n': no_eeprom_write = 1; @@ -240,6 +259,9 @@ static int parse_options(int argc, char **argv) case 'D': daemonize = 1; break; + case 'c': + sysmobts_mgr_inst.config_file = optarg; + break; default: return -1; } @@ -443,6 +465,25 @@ int main(int argc, char **argv) if (rc < 0) exit(2); + vty_info.copyright = sysmomgr_copyright; + vty_init(&vty_info); + logging_vty_add_cmds(&mgr_log_info); + + sysmobts_mgr_vty_init(); + + rc = sysmobts_mgr_parse_config(sysmobts_mgr_inst.config_file, + &confinfo); + if (rc < 0) { + LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); + exit(2); + } + + rc = telnet_init(tall_msgb_ctx, NULL, 4252); + if (rc < 0) { + fprintf(stderr, "Error initializing telnet\n"); + exit(1); + } + /* start temperature check timer */ temp_timer.cb = check_temp_timer_cb; check_temp_timer_cb(NULL); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index ddb6774..d89c46f 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -1,10 +1,26 @@ #ifndef _SYSMOBTS_MGR_H #define _SYSMOBTS_MGR_H +#include +#include + enum { DTEMP, DFW, DFIND, }; +enum mgr_vty_node { + MGR_NODE = _LAST_OSMOVTY_NODE + 1, +}; + +enum node_type mgr_vty_go_parent(struct vty *vty); +int mgr_vty_is_config_node(struct vty *vty, int node); +int sysmobts_mgr_vty_init(void); +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg); + +struct sysmobts_mgr_instance { + const char *config_file; +}; #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c new file mode 100644 index 0000000..33c3fe6 --- /dev/null +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c @@ -0,0 +1,250 @@ +/* (C) 2014 by sysmocom - s.f.m.c. GmbH + * + * All Rights Reserved + * + * Author: Alvaro Neira Ayuso + * + * 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 "sysmobts_misc.h" +#include "sysmobts_mgr.h" + +static struct sbts2050_config_info *mgr_cfg = NULL; + +enum node_type mgr_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + case MGR_NODE: + vty->node = CONFIG_NODE; + break; + default: + vty->node = CONFIG_NODE; + } + return vty->node; +} + +int mgr_vty_is_config_node(struct vty *vty, int node) +{ + switch (node) { + case MGR_NODE: + return 1; + default: + return 0; + } +} + +#define MGR_STR "Configure the sysmobts-mgr\n" + +static struct cmd_node mgr_node = { + MGR_NODE, + "%s(config-mgr)# ", + 1, +}; + +DEFUN(cfg_mgr, cfg_mgr_cmd, + "config-mgr", + MGR_STR) +{ + vty->node = MGR_NODE; + return CMD_SUCCESS; +} + +DEFUN(show_mgr, show_mgr_cmd, "show mgr", + SHOW_STR "Display information about the mgr") +{ + vty_out(vty, " temp-warn-board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_sever_limit, + mgr_cfg->temp_max_board_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-warn-pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_sever_limit, + mgr_cfg->temp_max_pa_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " pwr_action Master:%d Slave:%d PA:%d%s", + mgr_cfg->master_power_act, + mgr_cfg->slave_power_act, + mgr_cfg->pa_power_act, + VTY_NEWLINE); + + vty_out(vty, " pwr-max-transmiter %d%s", + mgr_cfg->max_power_red, + VTY_NEWLINE); + return CMD_SUCCESS; +} + +static int config_write_mgr(struct vty *vty) +{ + vty_out(vty, "config-mgr%s", VTY_NEWLINE); + + vty_out(vty, " temp-warn-board %d %d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-board %d %d%s", + mgr_cfg->temp_min_board_sever_limit, + mgr_cfg->temp_max_board_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-warn-pa %d %d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-pa %d %d%s", + mgr_cfg->temp_min_pa_sever_limit, + mgr_cfg->temp_max_pa_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " pwr-action %d %d %d%s", + mgr_cfg->master_power_act, + mgr_cfg->slave_power_act, + mgr_cfg->pa_power_act, + VTY_NEWLINE); + + vty_out(vty, " pwr-max-transmiter %d%s", + mgr_cfg->max_power_red, + VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_warn, cfg_mgr_board_temp_warn_cmd, + "temp-warn-board <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the warning limit (Min and Max)" + "in the Board\n") +{ + mgr_cfg->temp_min_board_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_sever, cfg_mgr_board_temp_sever_cmd, + "temp-sever-board <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the several limit (Min and Max)" + "in the Board\n") +{ + mgr_cfg->temp_min_board_sever_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_sever_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_warn, cfg_mgr_pa_temp_warn_cmd, + "temp-warn-pa <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the warning limit (Min and Max)" + "in the PA\n") +{ + mgr_cfg->temp_min_pa_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_sever, cfg_mgr_pa_temp_sever_cmd, + "temp-sever-pa <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the several limit (Min and Max)" + "in the PA\n") +{ + mgr_cfg->temp_min_pa_sever_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_sever_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pwr_action, cfg_mgr_pwr_action_cmd, + "pwr-action (0|1) (0|1) (0|1)", + MGR_STR "Action for switching on (1) | off (0)" + "the Master, Slave and PA\n") +{ + mgr_cfg->master_power_act = atoi(argv[0]); + mgr_cfg->slave_power_act = atoi(argv[1]); + mgr_cfg->pa_power_act = atoi(argv[2]); + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_baud_action, cfg_mgr_pa_baud_action_cmd, + "pwr-max-transmiter <0-255>", + MGR_STR "Power baud transmition in the PA\n") +{ + mgr_cfg->max_power_red = atoi(argv[0]); + + return CMD_SUCCESS; +} + +int sysmobts_mgr_vty_init(void) + +{ + install_element_ve(&show_mgr_cmd); + + install_node(&mgr_node, config_write_mgr); + install_element(CONFIG_NODE, &cfg_mgr_cmd); + install_default(MGR_NODE); + + install_element(MGR_NODE, &cfg_mgr_board_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_board_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pwr_action_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_baud_action_cmd); + + return 0; +} + +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg) +{ + int rc; + + mgr_cfg = cfg; + + rc = vty_read_config_file(config_file, NULL); + if (rc < 0) { + fprintf(stderr, "Failed to parse the config file: '%s'\n", + config_file); + return rc; + } + + return 0; +} -- 1.7.10.4 From pablo at gnumonks.org Thu Apr 10 11:15:36 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Thu, 10 Apr 2014 13:15:36 +0200 Subject: [osmo-bts PATCH 2/3 v3] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1397125537-28345-1-git-send-email-anayuso@sysmocom.de> References: <1396960526-14064-1-git-send-email-anayuso@sysmocom.de> <1397125537-28345-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140410111536.GB3530@localhost> On Thu, Apr 10, 2014 at 12:25:37PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > > Added the vty support for configuring the parameter for using the > OML report in manager when we have anomalous temperature. > > Signed-off-by: Alvaro Neira Ayuso > --- > [changes in v3] > * Fixed some coding style errors > * Changed the port of the sysmo-mgr vty because the previous was already being > used > > doc/examples/osmobts-mgr.cfg | 30 ++++ > src/osmo-bts-sysmo/Makefile.am | 5 +- > src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 43 ++++- > src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 16 ++ > src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c | 250 ++++++++++++++++++++++++++++ > 5 files changed, 341 insertions(+), 3 deletions(-) > create mode 100644 doc/examples/osmobts-mgr.cfg > create mode 100644 src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c > > diff --git a/doc/examples/osmobts-mgr.cfg b/doc/examples/osmobts-mgr.cfg > new file mode 100644 > index 0000000..f1c4e8e > --- /dev/null > +++ b/doc/examples/osmobts-mgr.cfg > @@ -0,0 +1,30 @@ > +! > +! SysmoMgr (0.3.0.137-7576) configuration saved from vty > +!! > +! > +log stderr > + logging filter all 1 > + logging color 1 > + logging timestamp 0 > + logging level all everything > + logging level temp info > + logging level fw info > + logging level find info > + logging level lglobal notice > + logging level llapd notice > + logging level linp notice > + logging level lmux notice > + logging level lmi notice > + logging level lmib notice > + logging level lsms notice > +! > +line vty > + no login > +! > +config-mgr > + temp-warn-board -30 50 > + temp-sever-board -50 80 > + temp-warn-pa -30 50 > + temp-sever-pa -50 80 > + pwr-action 1 1 0 > + pwr-max-transmiter 32 > diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am > index 1c08af3..b4b7de7 100644 > --- a/src/osmo-bts-sysmo/Makefile.am > +++ b/src/osmo-bts-sysmo/Makefile.am > @@ -22,8 +22,9 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) > > sysmobts_mgr_SOURCES = \ > misc/sysmobts_mgr.c misc/sysmobts_misc.c \ > - misc/sysmobts_par.c misc/sysmobts_nl.c > -sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) > + misc/sysmobts_par.c misc/sysmobts_nl.c \ > + misc/sysmobts_mgr_vty.c > +sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) > > sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c > sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > index 7a50bdc..2635c5f 100644 > --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c > @@ -57,6 +57,24 @@ static int fd_unix = -1; > void *tall_mgr_ctx; > static struct sbts2050_config_info confinfo; > > +static struct sysmobts_mgr_instance sysmobts_mgr_inst = { > + .config_file = "osmobts-mgr.cfg", > +}; > + > +const char *sysmomgr_copyright = > + "(C) 2012 by Harald Welte \r\n" > + "(C) 2014 by Holger Hans Peter Freyther\r\n" > + "License AGPLv3+: GNU AGPL version 2 or later \r\n" > + "This is free software: you are free to change and redistribute it.\r\n" > + "There is NO WARRANTY, to the extent permitted by law.\r\n"; > + > +static struct vty_app_info vty_info = { > + .name = "SysmoMgr", > + .version = PACKAGE_VERSION, > + .go_parent_cb = mgr_vty_go_parent, > + .is_config_node = mgr_vty_is_config_node, > +}; > + > /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ > #define TEMP_TIMER_SECS (6 * 3600) > > @@ -217,13 +235,14 @@ static void print_help(void) > printf(" -s Disable color\n"); > printf(" -d CAT enable debugging\n"); > printf(" -D daemonize\n"); > + printf(" -c Specify the filename of the config file\n"); > } > > static int parse_options(int argc, char **argv) > { > int opt; > > - while ((opt = getopt(argc, argv, "nhsd:")) != -1) { > + while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { > switch (opt) { > case 'n': > no_eeprom_write = 1; > @@ -240,6 +259,9 @@ static int parse_options(int argc, char **argv) > case 'D': > daemonize = 1; > break; > + case 'c': > + sysmobts_mgr_inst.config_file = optarg; > + break; > default: > return -1; > } > @@ -443,6 +465,25 @@ int main(int argc, char **argv) > if (rc < 0) > exit(2); > > + vty_info.copyright = sysmomgr_copyright; > + vty_init(&vty_info); > + logging_vty_add_cmds(&mgr_log_info); > + > + sysmobts_mgr_vty_init(); > + > + rc = sysmobts_mgr_parse_config(sysmobts_mgr_inst.config_file, > + &confinfo); > + if (rc < 0) { > + LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); > + exit(2); IIRC these error values indicate from which point we have failed. So this should be exit(3). From anayuso at sysmocom.de Thu Apr 10 13:42:33 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Thu, 10 Apr 2014 15:42:33 +0200 Subject: [osmo-bts PATCH 2/3 v4] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1397125537-28345-1-git-send-email-anayuso@sysmocom.de> References: <1397125537-28345-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397137353-12816-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added the vty support for configuring the parameter for using the OML report in manager when we have anomalous temperature. Signed-off-by: Alvaro Neira Ayuso --- [changes in v4] * Changed the exit value for having consistency with the exit values that we have used in the same failure cases but in other programs. doc/examples/osmobts-mgr.cfg | 30 ++++ src/osmo-bts-sysmo/Makefile.am | 5 +- src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 43 ++++- src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 16 ++ src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c | 250 ++++++++++++++++++++++++++++ 5 files changed, 341 insertions(+), 3 deletions(-) create mode 100644 doc/examples/osmobts-mgr.cfg create mode 100644 src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c diff --git a/doc/examples/osmobts-mgr.cfg b/doc/examples/osmobts-mgr.cfg new file mode 100644 index 0000000..f1c4e8e --- /dev/null +++ b/doc/examples/osmobts-mgr.cfg @@ -0,0 +1,30 @@ +! +! SysmoMgr (0.3.0.137-7576) configuration saved from vty +!! +! +log stderr + logging filter all 1 + logging color 1 + logging timestamp 0 + logging level all everything + logging level temp info + logging level fw info + logging level find info + logging level lglobal notice + logging level llapd notice + logging level linp notice + logging level lmux notice + logging level lmi notice + logging level lmib notice + logging level lsms notice +! +line vty + no login +! +config-mgr + temp-warn-board -30 50 + temp-sever-board -50 80 + temp-warn-pa -30 50 + temp-sever-pa -50 80 + pwr-action 1 1 0 + pwr-max-transmiter 32 diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am index 1c08af3..b4b7de7 100644 --- a/src/osmo-bts-sysmo/Makefile.am +++ b/src/osmo-bts-sysmo/Makefile.am @@ -22,8 +22,9 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) sysmobts_mgr_SOURCES = \ misc/sysmobts_mgr.c misc/sysmobts_misc.c \ - misc/sysmobts_par.c misc/sysmobts_nl.c -sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) + misc/sysmobts_par.c misc/sysmobts_nl.c \ + misc/sysmobts_mgr_vty.c +sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 51fa539..2f169e0 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -52,6 +52,24 @@ static int fd_unix = -1; void *tall_mgr_ctx; static struct sbts2050_config_info confinfo; +static struct sysmobts_mgr_instance sysmobts_mgr_inst = { + .config_file = "osmobts-mgr.cfg", +}; + +const char *sysmomgr_copyright = + "(C) 2012 by Harald Welte \r\n" + "(C) 2014 by Holger Hans Peter Freyther\r\n" + "License AGPLv3+: GNU AGPL version 2 or later \r\n" + "This is free software: you are free to change and redistribute it.\r\n" + "There is NO WARRANTY, to the extent permitted by law.\r\n"; + +static struct vty_app_info vty_info = { + .name = "SysmoMgr", + .version = PACKAGE_VERSION, + .go_parent_cb = mgr_vty_go_parent, + .is_config_node = mgr_vty_is_config_node, +}; + /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -211,13 +229,14 @@ static void print_help(void) printf(" -s Disable color\n"); printf(" -d CAT enable debugging\n"); printf(" -D daemonize\n"); + printf(" -c Specify the filename of the config file\n"); } static int parse_options(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "nhsd:")) != -1) { + while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { switch (opt) { case 'n': no_eeprom_write = 1; @@ -234,6 +253,9 @@ static int parse_options(int argc, char **argv) case 'D': daemonize = 1; break; + case 'c': + sysmobts_mgr_inst.config_file = optarg; + break; default: return -1; } @@ -437,6 +459,25 @@ int main(int argc, char **argv) if (rc < 0) exit(2); + vty_info.copyright = sysmomgr_copyright; + vty_init(&vty_info); + logging_vty_add_cmds(&mgr_log_info); + + sysmobts_mgr_vty_init(); + + rc = sysmobts_mgr_parse_config(sysmobts_mgr_inst.config_file, + &confinfo); + if (rc < 0) { + LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); + exit(1); + } + + rc = telnet_init(tall_msgb_ctx, NULL, 4252); + if (rc < 0) { + fprintf(stderr, "Error initializing telnet\n"); + exit(1); + } + /* start temperature check timer */ temp_timer.cb = check_temp_timer_cb; check_temp_timer_cb(NULL); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index 87668e0..f9e5c09 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -1,6 +1,9 @@ #ifndef _SYSMOBTS_MGR_H #define _SYSMOBTS_MGR_H +#include +#include + enum { DTEMP, DFW, @@ -12,4 +15,17 @@ enum { SYSMO_MGR_CONNECTED, }; +enum mgr_vty_node { + MGR_NODE = _LAST_OSMOVTY_NODE + 1, +}; + +enum node_type mgr_vty_go_parent(struct vty *vty); +int mgr_vty_is_config_node(struct vty *vty, int node); +int sysmobts_mgr_vty_init(void); +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg); + +struct sysmobts_mgr_instance { + const char *config_file; +}; #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c new file mode 100644 index 0000000..33c3fe6 --- /dev/null +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c @@ -0,0 +1,250 @@ +/* (C) 2014 by sysmocom - s.f.m.c. GmbH + * + * All Rights Reserved + * + * Author: Alvaro Neira Ayuso + * + * 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 "sysmobts_misc.h" +#include "sysmobts_mgr.h" + +static struct sbts2050_config_info *mgr_cfg = NULL; + +enum node_type mgr_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + case MGR_NODE: + vty->node = CONFIG_NODE; + break; + default: + vty->node = CONFIG_NODE; + } + return vty->node; +} + +int mgr_vty_is_config_node(struct vty *vty, int node) +{ + switch (node) { + case MGR_NODE: + return 1; + default: + return 0; + } +} + +#define MGR_STR "Configure the sysmobts-mgr\n" + +static struct cmd_node mgr_node = { + MGR_NODE, + "%s(config-mgr)# ", + 1, +}; + +DEFUN(cfg_mgr, cfg_mgr_cmd, + "config-mgr", + MGR_STR) +{ + vty->node = MGR_NODE; + return CMD_SUCCESS; +} + +DEFUN(show_mgr, show_mgr_cmd, "show mgr", + SHOW_STR "Display information about the mgr") +{ + vty_out(vty, " temp-warn-board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_sever_limit, + mgr_cfg->temp_max_board_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-warn-pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_sever_limit, + mgr_cfg->temp_max_pa_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " pwr_action Master:%d Slave:%d PA:%d%s", + mgr_cfg->master_power_act, + mgr_cfg->slave_power_act, + mgr_cfg->pa_power_act, + VTY_NEWLINE); + + vty_out(vty, " pwr-max-transmiter %d%s", + mgr_cfg->max_power_red, + VTY_NEWLINE); + return CMD_SUCCESS; +} + +static int config_write_mgr(struct vty *vty) +{ + vty_out(vty, "config-mgr%s", VTY_NEWLINE); + + vty_out(vty, " temp-warn-board %d %d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-board %d %d%s", + mgr_cfg->temp_min_board_sever_limit, + mgr_cfg->temp_max_board_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-warn-pa %d %d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-pa %d %d%s", + mgr_cfg->temp_min_pa_sever_limit, + mgr_cfg->temp_max_pa_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " pwr-action %d %d %d%s", + mgr_cfg->master_power_act, + mgr_cfg->slave_power_act, + mgr_cfg->pa_power_act, + VTY_NEWLINE); + + vty_out(vty, " pwr-max-transmiter %d%s", + mgr_cfg->max_power_red, + VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_warn, cfg_mgr_board_temp_warn_cmd, + "temp-warn-board <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the warning limit (Min and Max)" + "in the Board\n") +{ + mgr_cfg->temp_min_board_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_sever, cfg_mgr_board_temp_sever_cmd, + "temp-sever-board <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the several limit (Min and Max)" + "in the Board\n") +{ + mgr_cfg->temp_min_board_sever_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_sever_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_warn, cfg_mgr_pa_temp_warn_cmd, + "temp-warn-pa <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the warning limit (Min and Max)" + "in the PA\n") +{ + mgr_cfg->temp_min_pa_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_sever, cfg_mgr_pa_temp_sever_cmd, + "temp-sever-pa <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the several limit (Min and Max)" + "in the PA\n") +{ + mgr_cfg->temp_min_pa_sever_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_sever_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pwr_action, cfg_mgr_pwr_action_cmd, + "pwr-action (0|1) (0|1) (0|1)", + MGR_STR "Action for switching on (1) | off (0)" + "the Master, Slave and PA\n") +{ + mgr_cfg->master_power_act = atoi(argv[0]); + mgr_cfg->slave_power_act = atoi(argv[1]); + mgr_cfg->pa_power_act = atoi(argv[2]); + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_baud_action, cfg_mgr_pa_baud_action_cmd, + "pwr-max-transmiter <0-255>", + MGR_STR "Power baud transmition in the PA\n") +{ + mgr_cfg->max_power_red = atoi(argv[0]); + + return CMD_SUCCESS; +} + +int sysmobts_mgr_vty_init(void) + +{ + install_element_ve(&show_mgr_cmd); + + install_node(&mgr_node, config_write_mgr); + install_element(CONFIG_NODE, &cfg_mgr_cmd); + install_default(MGR_NODE); + + install_element(MGR_NODE, &cfg_mgr_board_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_board_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pwr_action_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_baud_action_cmd); + + return 0; +} + +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg) +{ + int rc; + + mgr_cfg = cfg; + + rc = vty_read_config_file(config_file, NULL); + if (rc < 0) { + fprintf(stderr, "Failed to parse the config file: '%s'\n", + config_file); + return rc; + } + + return 0; +} -- 1.7.10.4 From pablo at gnumonks.org Thu Apr 10 13:55:21 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Thu, 10 Apr 2014 15:55:21 +0200 Subject: [osmo-bts PATCH 2/3 v4] misc/sysmomgr: Added Vty support for configuring the managerg In-Reply-To: <1397137353-12816-1-git-send-email-anayuso@sysmocom.de> References: <1397125537-28345-1-git-send-email-anayuso@sysmocom.de> <1397137353-12816-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140410135521.GB4346@localhost> On Thu, Apr 10, 2014 at 03:42:33PM +0200, Alvaro Neira Ayuso wrote: > diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c > new file mode 100644 > index 0000000..33c3fe6 > --- /dev/null > +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c > @@ -0,0 +1,250 @@ > +/* (C) 2014 by sysmocom - s.f.m.c. GmbH > + * > + * All Rights Reserved > + * > + * Author: Alvaro Neira Ayuso > + * > + * 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 "sysmobts_misc.h" > +#include "sysmobts_mgr.h" > + > +static struct sbts2050_config_info *mgr_cfg = NULL; You don't need to initialize this variable, it's stored in the BSS so it's already set to zero. From anayuso at sysmocom.de Sun Apr 13 13:22:45 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Sun, 13 Apr 2014 15:22:45 +0200 Subject: [osmo-bts PATCH 2/3 v5] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1397137353-12816-1-git-send-email-anayuso@sysmocom.de> References: <1397137353-12816-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397395365-14739-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added the vty support for configuring the parameter for using the OML report in manager when we have anomalous temperature. Signed-off-by: Alvaro Neira Ayuso --- [changes in v5] * Removed a NULL initialize of a static variable doc/examples/osmobts-mgr.cfg | 30 ++++ src/osmo-bts-sysmo/Makefile.am | 5 +- src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 43 ++++- src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 16 ++ src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c | 250 ++++++++++++++++++++++++++++ 5 files changed, 341 insertions(+), 3 deletions(-) create mode 100644 doc/examples/osmobts-mgr.cfg create mode 100644 src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c diff --git a/doc/examples/osmobts-mgr.cfg b/doc/examples/osmobts-mgr.cfg new file mode 100644 index 0000000..f1c4e8e --- /dev/null +++ b/doc/examples/osmobts-mgr.cfg @@ -0,0 +1,30 @@ +! +! SysmoMgr (0.3.0.137-7576) configuration saved from vty +!! +! +log stderr + logging filter all 1 + logging color 1 + logging timestamp 0 + logging level all everything + logging level temp info + logging level fw info + logging level find info + logging level lglobal notice + logging level llapd notice + logging level linp notice + logging level lmux notice + logging level lmi notice + logging level lmib notice + logging level lsms notice +! +line vty + no login +! +config-mgr + temp-warn-board -30 50 + temp-sever-board -50 80 + temp-warn-pa -30 50 + temp-sever-pa -50 80 + pwr-action 1 1 0 + pwr-max-transmiter 32 diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am index 1c08af3..b4b7de7 100644 --- a/src/osmo-bts-sysmo/Makefile.am +++ b/src/osmo-bts-sysmo/Makefile.am @@ -22,8 +22,9 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) sysmobts_mgr_SOURCES = \ misc/sysmobts_mgr.c misc/sysmobts_misc.c \ - misc/sysmobts_par.c misc/sysmobts_nl.c -sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) + misc/sysmobts_par.c misc/sysmobts_nl.c \ + misc/sysmobts_mgr_vty.c +sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 51fa539..2f169e0 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -52,6 +52,24 @@ static int fd_unix = -1; void *tall_mgr_ctx; static struct sbts2050_config_info confinfo; +static struct sysmobts_mgr_instance sysmobts_mgr_inst = { + .config_file = "osmobts-mgr.cfg", +}; + +const char *sysmomgr_copyright = + "(C) 2012 by Harald Welte \r\n" + "(C) 2014 by Holger Hans Peter Freyther\r\n" + "License AGPLv3+: GNU AGPL version 2 or later \r\n" + "This is free software: you are free to change and redistribute it.\r\n" + "There is NO WARRANTY, to the extent permitted by law.\r\n"; + +static struct vty_app_info vty_info = { + .name = "SysmoMgr", + .version = PACKAGE_VERSION, + .go_parent_cb = mgr_vty_go_parent, + .is_config_node = mgr_vty_is_config_node, +}; + /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -211,13 +229,14 @@ static void print_help(void) printf(" -s Disable color\n"); printf(" -d CAT enable debugging\n"); printf(" -D daemonize\n"); + printf(" -c Specify the filename of the config file\n"); } static int parse_options(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "nhsd:")) != -1) { + while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { switch (opt) { case 'n': no_eeprom_write = 1; @@ -234,6 +253,9 @@ static int parse_options(int argc, char **argv) case 'D': daemonize = 1; break; + case 'c': + sysmobts_mgr_inst.config_file = optarg; + break; default: return -1; } @@ -437,6 +459,25 @@ int main(int argc, char **argv) if (rc < 0) exit(2); + vty_info.copyright = sysmomgr_copyright; + vty_init(&vty_info); + logging_vty_add_cmds(&mgr_log_info); + + sysmobts_mgr_vty_init(); + + rc = sysmobts_mgr_parse_config(sysmobts_mgr_inst.config_file, + &confinfo); + if (rc < 0) { + LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); + exit(1); + } + + rc = telnet_init(tall_msgb_ctx, NULL, 4252); + if (rc < 0) { + fprintf(stderr, "Error initializing telnet\n"); + exit(1); + } + /* start temperature check timer */ temp_timer.cb = check_temp_timer_cb; check_temp_timer_cb(NULL); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index 87668e0..f9e5c09 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -1,6 +1,9 @@ #ifndef _SYSMOBTS_MGR_H #define _SYSMOBTS_MGR_H +#include +#include + enum { DTEMP, DFW, @@ -12,4 +15,17 @@ enum { SYSMO_MGR_CONNECTED, }; +enum mgr_vty_node { + MGR_NODE = _LAST_OSMOVTY_NODE + 1, +}; + +enum node_type mgr_vty_go_parent(struct vty *vty); +int mgr_vty_is_config_node(struct vty *vty, int node); +int sysmobts_mgr_vty_init(void); +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg); + +struct sysmobts_mgr_instance { + const char *config_file; +}; #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c new file mode 100644 index 0000000..1f7a3fd --- /dev/null +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c @@ -0,0 +1,250 @@ +/* (C) 2014 by sysmocom - s.f.m.c. GmbH + * + * All Rights Reserved + * + * Author: Alvaro Neira Ayuso + * + * 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 "sysmobts_misc.h" +#include "sysmobts_mgr.h" + +static struct sbts2050_config_info *mgr_cfg; + +enum node_type mgr_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + case MGR_NODE: + vty->node = CONFIG_NODE; + break; + default: + vty->node = CONFIG_NODE; + } + return vty->node; +} + +int mgr_vty_is_config_node(struct vty *vty, int node) +{ + switch (node) { + case MGR_NODE: + return 1; + default: + return 0; + } +} + +#define MGR_STR "Configure the sysmobts-mgr\n" + +static struct cmd_node mgr_node = { + MGR_NODE, + "%s(config-mgr)# ", + 1, +}; + +DEFUN(cfg_mgr, cfg_mgr_cmd, + "config-mgr", + MGR_STR) +{ + vty->node = MGR_NODE; + return CMD_SUCCESS; +} + +DEFUN(show_mgr, show_mgr_cmd, "show mgr", + SHOW_STR "Display information about the mgr") +{ + vty_out(vty, " temp-warn-board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_sever_limit, + mgr_cfg->temp_max_board_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-warn-pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_sever_limit, + mgr_cfg->temp_max_pa_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " pwr_action Master:%d Slave:%d PA:%d%s", + mgr_cfg->master_power_act, + mgr_cfg->slave_power_act, + mgr_cfg->pa_power_act, + VTY_NEWLINE); + + vty_out(vty, " pwr-max-transmiter %d%s", + mgr_cfg->max_power_red, + VTY_NEWLINE); + return CMD_SUCCESS; +} + +static int config_write_mgr(struct vty *vty) +{ + vty_out(vty, "config-mgr%s", VTY_NEWLINE); + + vty_out(vty, " temp-warn-board %d %d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-board %d %d%s", + mgr_cfg->temp_min_board_sever_limit, + mgr_cfg->temp_max_board_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-warn-pa %d %d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temp-sever-pa %d %d%s", + mgr_cfg->temp_min_pa_sever_limit, + mgr_cfg->temp_max_pa_sever_limit, + VTY_NEWLINE); + + vty_out(vty, " pwr-action %d %d %d%s", + mgr_cfg->master_power_act, + mgr_cfg->slave_power_act, + mgr_cfg->pa_power_act, + VTY_NEWLINE); + + vty_out(vty, " pwr-max-transmiter %d%s", + mgr_cfg->max_power_red, + VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_warn, cfg_mgr_board_temp_warn_cmd, + "temp-warn-board <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the warning limit (Min and Max)" + "in the Board\n") +{ + mgr_cfg->temp_min_board_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_sever, cfg_mgr_board_temp_sever_cmd, + "temp-sever-board <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the several limit (Min and Max)" + "in the Board\n") +{ + mgr_cfg->temp_min_board_sever_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_sever_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_warn, cfg_mgr_pa_temp_warn_cmd, + "temp-warn-pa <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the warning limit (Min and Max)" + "in the PA\n") +{ + mgr_cfg->temp_min_pa_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_sever, cfg_mgr_pa_temp_sever_cmd, + "temp-sever-pa <-255-255> <-255-255>", + MGR_STR "Temperature Range Value of the several limit (Min and Max)" + "in the PA\n") +{ + mgr_cfg->temp_min_pa_sever_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_sever_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pwr_action, cfg_mgr_pwr_action_cmd, + "pwr-action (0|1) (0|1) (0|1)", + MGR_STR "Action for switching on (1) | off (0)" + "the Master, Slave and PA\n") +{ + mgr_cfg->master_power_act = atoi(argv[0]); + mgr_cfg->slave_power_act = atoi(argv[1]); + mgr_cfg->pa_power_act = atoi(argv[2]); + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_baud_action, cfg_mgr_pa_baud_action_cmd, + "pwr-max-transmiter <0-255>", + MGR_STR "Power baud transmition in the PA\n") +{ + mgr_cfg->max_power_red = atoi(argv[0]); + + return CMD_SUCCESS; +} + +int sysmobts_mgr_vty_init(void) + +{ + install_element_ve(&show_mgr_cmd); + + install_node(&mgr_node, config_write_mgr); + install_element(CONFIG_NODE, &cfg_mgr_cmd); + install_default(MGR_NODE); + + install_element(MGR_NODE, &cfg_mgr_board_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_board_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pwr_action_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_baud_action_cmd); + + return 0; +} + +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg) +{ + int rc; + + mgr_cfg = cfg; + + rc = vty_read_config_file(config_file, NULL); + if (rc < 0) { + fprintf(stderr, "Failed to parse the config file: '%s'\n", + config_file); + return rc; + } + + return 0; +} -- 1.7.10.4 From pablo at gnumonks.org Mon Apr 14 12:13:17 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Mon, 14 Apr 2014 14:13:17 +0200 Subject: [osmo-bts PATCH 2/3 v5] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1397395365-14739-1-git-send-email-anayuso@sysmocom.de> References: <1397137353-12816-1-git-send-email-anayuso@sysmocom.de> <1397395365-14739-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140414121317.GB21855@localhost> On Sun, Apr 13, 2014 at 03:22:45PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > > Added the vty support for configuring the parameter for using the > OML report in manager when we have anomalous temperature. Acked-by: Pablo Neira Ayuso From anayuso at sysmocom.de Tue Apr 15 18:17:51 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Tue, 15 Apr 2014 20:17:51 +0200 Subject: [osmo-bts PATCH 2/3 v6] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1397395365-14739-1-git-send-email-anayuso@sysmocom.de> References: <1397395365-14739-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397585872-16005-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added the vty support for configuring the parameter for using the OML report in manager when we have anomalous temperature. Signed-off-by: Alvaro Neira Ayuso --- [changes in v6] * Fixed the all the help information in the manager vty * Changed the name functions for using name more correct and with more intuitive * Changed the power-actions parameters for using ON and OFF doc/examples/osmobts-mgr.cfg | 30 +++ src/osmo-bts-sysmo/Makefile.am | 5 +- src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 43 ++++- src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 18 ++ src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c | 279 ++++++++++++++++++++++++++++ 5 files changed, 372 insertions(+), 3 deletions(-) create mode 100644 doc/examples/osmobts-mgr.cfg create mode 100644 src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c diff --git a/doc/examples/osmobts-mgr.cfg b/doc/examples/osmobts-mgr.cfg new file mode 100644 index 0000000..a1a1394 --- /dev/null +++ b/doc/examples/osmobts-mgr.cfg @@ -0,0 +1,30 @@ +! +! SysmoMgr (0.3.0.141-33e5) configuration saved from vty +!! +! +log stderr + logging filter all 1 + logging color 1 + logging timestamp 0 + logging level all everything + logging level temp info + logging level fw info + logging level find info + logging level lglobal notice + logging level llapd notice + logging level linp notice + logging level lmux notice + logging level lmi notice + logging level lmib notice + logging level lsms notice +! +line vty + no login +! +config-mgr + temperature-warning board -30 50 + temperature-severe board -50 80 + temperature-warning pa -30 50 + temperature-severe pa -50 80 + power-action ON ON OFF + power-max-transmiter 4 diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am index 1c08af3..b4b7de7 100644 --- a/src/osmo-bts-sysmo/Makefile.am +++ b/src/osmo-bts-sysmo/Makefile.am @@ -22,8 +22,9 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) sysmobts_mgr_SOURCES = \ misc/sysmobts_mgr.c misc/sysmobts_misc.c \ - misc/sysmobts_par.c misc/sysmobts_nl.c -sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) + misc/sysmobts_par.c misc/sysmobts_nl.c \ + misc/sysmobts_mgr_vty.c +sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index b686c79..efce674 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -52,6 +52,24 @@ static int fd_unix = -1; void *tall_mgr_ctx; static struct sbts2050_config_info confinfo; +static struct sysmobts_mgr_instance sysmobts_mgr_inst = { + .config_file = "osmobts-mgr.cfg", +}; + +const char *sysmomgr_copyright = + "(C) 2012 by Harald Welte \r\n" + "(C) 2014 by Holger Hans Peter Freyther\r\n" + "License AGPLv3+: GNU AGPL version 2 or later \r\n" + "This is free software: you are free to change and redistribute it.\r\n" + "There is NO WARRANTY, to the extent permitted by law.\r\n"; + +static struct vty_app_info vty_info = { + .name = "SysmoMgr", + .version = PACKAGE_VERSION, + .go_parent_cb = mgr_vty_go_parent, + .is_config_node = mgr_vty_is_config_node, +}; + /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -213,13 +231,14 @@ static void print_help(void) printf(" -s Disable color\n"); printf(" -d CAT enable debugging\n"); printf(" -D daemonize\n"); + printf(" -c Specify the filename of the config file\n"); } static int parse_options(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "nhsd:")) != -1) { + while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { switch (opt) { case 'n': no_eeprom_write = 1; @@ -236,6 +255,9 @@ static int parse_options(int argc, char **argv) case 'D': daemonize = 1; break; + case 'c': + sysmobts_mgr_inst.config_file = optarg; + break; default: return -1; } @@ -439,6 +461,25 @@ int main(int argc, char **argv) if (rc < 0) exit(2); + vty_info.copyright = sysmomgr_copyright; + vty_init(&vty_info); + logging_vty_add_cmds(&mgr_log_info); + + sysmobts_mgr_vty_init(); + + rc = sysmobts_mgr_parse_config(sysmobts_mgr_inst.config_file, + &confinfo); + if (rc < 0) { + LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); + exit(1); + } + + rc = telnet_init(tall_msgb_ctx, NULL, 4252); + if (rc < 0) { + fprintf(stderr, "Error initializing telnet\n"); + exit(1); + } + /* start temperature check timer */ temp_timer.cb = check_temp_timer_cb; check_temp_timer_cb(NULL); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index 21f30a4..5e0d4a7 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -1,6 +1,9 @@ #ifndef _SYSMOBTS_MGR_H #define _SYSMOBTS_MGR_H +#include +#include + enum { DTEMP, DFW, @@ -14,4 +17,19 @@ enum { #define SOCKET_PATH "/var/run/bts_oml" +struct sbts2050_config_info; + +enum mgr_vty_node { + MGR_NODE = _LAST_OSMOVTY_NODE + 1, +}; + +enum node_type mgr_vty_go_parent(struct vty *vty); +int mgr_vty_is_config_node(struct vty *vty, int node); +int sysmobts_mgr_vty_init(void); +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg); + +struct sysmobts_mgr_instance { + const char *config_file; +}; #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c new file mode 100644 index 0000000..c5e1a69 --- /dev/null +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c @@ -0,0 +1,279 @@ +/* (C) 2014 by sysmocom - s.f.m.c. GmbH + * + * All Rights Reserved + * + * Author: Alvaro Neira Ayuso + * + * 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 "sysmobts_misc.h" +#include "sysmobts_mgr.h" + +static struct sbts2050_config_info *mgr_cfg; + +enum node_type mgr_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + case MGR_NODE: + vty->node = CONFIG_NODE; + break; + default: + vty->node = CONFIG_NODE; + } + return vty->node; +} + +int mgr_vty_is_config_node(struct vty *vty, int node) +{ + switch (node) { + case MGR_NODE: + return 1; + default: + return 0; + } +} + +#define MGR_STR "Configure sysmobts-mgr\n" +#define MGR_TEMP_WARN_STR "Configure the temperature warning limits\n" +#define MGR_TEMP_SEVERE_STR "Configure the temperature severe limits\n" + +static struct cmd_node mgr_node = { + MGR_NODE, + "%s(config-mgr)# ", + 1, +}; + +DEFUN(cfg_mgr, cfg_mgr_cmd, + "config-mgr", + MGR_STR) +{ + vty->node = MGR_NODE; + return CMD_SUCCESS; +} + +DEFUN(show_mgr, show_mgr_cmd, "show mgr", + SHOW_STR "Display information about the mgr") +{ + vty_out(vty, " temperature-warning board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_severe_limit, + mgr_cfg->temp_max_board_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-warning pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_severe_limit, + mgr_cfg->temp_max_pa_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " power-action Master:%s Slave:%s PA:%s%s", + mgr_cfg->master_power_act ? "ON" : "OFF", + mgr_cfg->slave_power_act ? "ON" : "OFF", + mgr_cfg->pa_power_act ? "ON" : "OFF", + VTY_NEWLINE); + + vty_out(vty, " power-max-transmitter %d%s", + mgr_cfg->reduce_max_power, + VTY_NEWLINE); + return CMD_SUCCESS; +} + +static int config_write_mgr(struct vty *vty) +{ + vty_out(vty, "config-mgr%s", VTY_NEWLINE); + + vty_out(vty, " temperature-warning board %d %d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe board %d %d%s", + mgr_cfg->temp_min_board_severe_limit, + mgr_cfg->temp_max_board_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-warning pa %d %d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe pa %d %d%s", + mgr_cfg->temp_min_pa_severe_limit, + mgr_cfg->temp_max_pa_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " power-action %s %s %s%s", + mgr_cfg->master_power_act ? "ON" : "OFF", + mgr_cfg->slave_power_act ? "ON" : "OFF", + mgr_cfg->pa_power_act ? "ON" : "OFF", + VTY_NEWLINE); + + vty_out(vty, " power-max-transmitter %d%s", + mgr_cfg->reduce_max_power, + VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_warn, cfg_mgr_board_temp_warn_cmd, + "temperature-warning board <-255-255> <-255-255>", + MGR_TEMP_WARN_STR + "Set warning temperature limits on the Board\n" + "Warning temperature low limit on the Board\n" + "Warning temperature high limit on the Board\n") +{ + mgr_cfg->temp_min_board_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_sever, cfg_mgr_board_temp_sever_cmd, + "temperature-severe board <-255-255> <-255-255>", + MGR_TEMP_SEVERE_STR + "Set severe temperature limits on the Board\n" + "Severe temperature low limit on the Board\n" + "Severe Temperature high limit on the Board\n") +{ + mgr_cfg->temp_min_board_severe_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_severe_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_warn, cfg_mgr_pa_temp_warn_cmd, + "temperature-warning pa <-255-255> <-255-255>", + MGR_TEMP_WARN_STR + "Set warning temperature limits on the PA\n" + "Warning temperature low limit on the PA\n" + "Warning temperature high limit on the PA\n") +{ + mgr_cfg->temp_min_pa_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_sever, cfg_mgr_pa_temp_sever_cmd, + "temperature-severe pa <-255-255> <-255-255>", + MGR_TEMP_SEVERE_STR + "Set severe temperature limits on the Board\n" + "Severe temperature low limit on the PA\n" + "Severe temperature high limit on the PA\n") +{ + mgr_cfg->temp_min_pa_severe_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_severe_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pwr_action, cfg_mgr_pwr_action_cmd, + "power-action (ON|OFF) (ON|OFF) (ON|OFF)", + "Configure which devices we want to turn on/off in several situation\n" + "the Master\n" + "the Master\n" + "the Slave\n" + "the Slave\n" + "the PA\n" + "the PA\n") +{ + if (strcmp(argv[0], "ON") == 0) + mgr_cfg->master_power_act = 1; + else if (strcmp(argv[0], "OFF") == 0) + mgr_cfg->master_power_act = 0; + + if (strcmp(argv[1], "ON") == 0) + mgr_cfg->slave_power_act = 1; + else if (strcmp(argv[1], "OFF") == 0) + mgr_cfg->slave_power_act = 0; + + if (strcmp(argv[2], "ON") == 0) + mgr_cfg->pa_power_act = 1; + else if (strcmp(argv[2], "OFF") == 0) + mgr_cfg->pa_power_act = 0; + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_baud_action, cfg_mgr_pa_baud_action_cmd, + "power-max-transmitter <0-255>", + "Configure the power that we want to reduce in warning situation\n" + "Power baud transmition that we want to reduce in the PA\n") +{ + mgr_cfg->reduce_max_power = atoi(argv[0]); + + return CMD_SUCCESS; +} + +int sysmobts_mgr_vty_init(void) + +{ + install_element_ve(&show_mgr_cmd); + + install_node(&mgr_node, config_write_mgr); + install_element(CONFIG_NODE, &cfg_mgr_cmd); + vty_install_default(MGR_NODE); + + install_element(MGR_NODE, &cfg_mgr_board_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_board_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pwr_action_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_baud_action_cmd); + + return 0; +} + +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg) +{ + int rc; + + mgr_cfg = cfg; + + rc = vty_read_config_file(config_file, NULL); + if (rc < 0) { + fprintf(stderr, "Failed to parse the config file: '%s'\n", + config_file); + return rc; + } + + return 0; +} -- 1.7.10.4 From anayuso at sysmocom.de Wed Apr 16 12:07:34 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Wed, 16 Apr 2014 14:07:34 +0200 Subject: [osmo-bts PATCH 2/3 v7] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1397585872-16005-1-git-send-email-anayuso@sysmocom.de> References: <1397585872-16005-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397650054-17749-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added the vty support for configuring the parameter for using the OML report in manager when we have anomalous temperature. Signed-off-by: Alvaro Neira Ayuso --- [changes in v7] * Change the function power_max_transmitter for power_reduce_transmitter doc/examples/osmobts-mgr.cfg | 30 +++ src/osmo-bts-sysmo/Makefile.am | 5 +- src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 43 ++++- src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 18 ++ src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c | 279 ++++++++++++++++++++++++++++ 5 files changed, 372 insertions(+), 3 deletions(-) create mode 100644 doc/examples/osmobts-mgr.cfg create mode 100644 src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c diff --git a/doc/examples/osmobts-mgr.cfg b/doc/examples/osmobts-mgr.cfg new file mode 100644 index 0000000..c1b5465 --- /dev/null +++ b/doc/examples/osmobts-mgr.cfg @@ -0,0 +1,30 @@ +! +! SysmoMgr (0.3.0.141-33e5) configuration saved from vty +!! +! +log stderr + logging filter all 1 + logging color 1 + logging timestamp 0 + logging level all everything + logging level temp info + logging level fw info + logging level find info + logging level lglobal notice + logging level llapd notice + logging level linp notice + logging level lmux notice + logging level lmi notice + logging level lmib notice + logging level lsms notice +! +line vty + no login +! +config-mgr + temperature-warning board -30 50 + temperature-severe board -50 80 + temperature-warning pa -30 50 + temperature-severe pa -50 80 + power-action ON ON OFF + power-reduce-transmiter 4 diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am index 1c08af3..b4b7de7 100644 --- a/src/osmo-bts-sysmo/Makefile.am +++ b/src/osmo-bts-sysmo/Makefile.am @@ -22,8 +22,9 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) sysmobts_mgr_SOURCES = \ misc/sysmobts_mgr.c misc/sysmobts_misc.c \ - misc/sysmobts_par.c misc/sysmobts_nl.c -sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) + misc/sysmobts_par.c misc/sysmobts_nl.c \ + misc/sysmobts_mgr_vty.c +sysmobts_mgr_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c sysmobts_util_LDADD = $(LIBOSMOCORE_LIBS) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 8dd97ec..15199f9 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -52,6 +52,24 @@ static int fd_unix = -1; void *tall_mgr_ctx; static struct sbts2050_config_info confinfo; +static struct sysmobts_mgr_instance sysmobts_mgr_inst = { + .config_file = "osmobts-mgr.cfg", +}; + +const char *sysmomgr_copyright = + "(C) 2012 by Harald Welte \r\n" + "(C) 2014 by Holger Hans Peter Freyther\r\n" + "License AGPLv3+: GNU AGPL version 2 or later \r\n" + "This is free software: you are free to change and redistribute it.\r\n" + "There is NO WARRANTY, to the extent permitted by law.\r\n"; + +static struct vty_app_info vty_info = { + .name = "SysmoMgr", + .version = PACKAGE_VERSION, + .go_parent_cb = mgr_vty_go_parent, + .is_config_node = mgr_vty_is_config_node, +}; + /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -206,13 +224,14 @@ static void print_help(void) printf(" -s Disable color\n"); printf(" -d CAT enable debugging\n"); printf(" -D daemonize\n"); + printf(" -c Specify the filename of the config file\n"); } static int parse_options(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "nhsd:")) != -1) { + while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { switch (opt) { case 'n': no_eeprom_write = 1; @@ -229,6 +248,9 @@ static int parse_options(int argc, char **argv) case 'D': daemonize = 1; break; + case 'c': + sysmobts_mgr_inst.config_file = optarg; + break; default: return -1; } @@ -432,6 +454,25 @@ int main(int argc, char **argv) if (rc < 0) exit(2); + vty_info.copyright = sysmomgr_copyright; + vty_init(&vty_info); + logging_vty_add_cmds(&mgr_log_info); + + sysmobts_mgr_vty_init(); + + rc = sysmobts_mgr_parse_config(sysmobts_mgr_inst.config_file, + &confinfo); + if (rc < 0) { + LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); + exit(1); + } + + rc = telnet_init(tall_msgb_ctx, NULL, 4252); + if (rc < 0) { + fprintf(stderr, "Error initializing telnet\n"); + exit(1); + } + /* start temperature check timer */ temp_timer.cb = check_temp_timer_cb; check_temp_timer_cb(NULL); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index 21f30a4..5e0d4a7 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -1,6 +1,9 @@ #ifndef _SYSMOBTS_MGR_H #define _SYSMOBTS_MGR_H +#include +#include + enum { DTEMP, DFW, @@ -14,4 +17,19 @@ enum { #define SOCKET_PATH "/var/run/bts_oml" +struct sbts2050_config_info; + +enum mgr_vty_node { + MGR_NODE = _LAST_OSMOVTY_NODE + 1, +}; + +enum node_type mgr_vty_go_parent(struct vty *vty); +int mgr_vty_is_config_node(struct vty *vty, int node); +int sysmobts_mgr_vty_init(void); +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg); + +struct sysmobts_mgr_instance { + const char *config_file; +}; #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c new file mode 100644 index 0000000..fc50054 --- /dev/null +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c @@ -0,0 +1,279 @@ +/* (C) 2014 by sysmocom - s.f.m.c. GmbH + * + * All Rights Reserved + * + * Author: Alvaro Neira Ayuso + * + * 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 "sysmobts_misc.h" +#include "sysmobts_mgr.h" + +static struct sbts2050_config_info *mgr_cfg; + +enum node_type mgr_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + case MGR_NODE: + vty->node = CONFIG_NODE; + break; + default: + vty->node = CONFIG_NODE; + } + return vty->node; +} + +int mgr_vty_is_config_node(struct vty *vty, int node) +{ + switch (node) { + case MGR_NODE: + return 1; + default: + return 0; + } +} + +#define MGR_STR "Configure sysmobts-mgr\n" +#define MGR_TEMP_WARN_STR "Configure the temperature warning limits\n" +#define MGR_TEMP_SEVERE_STR "Configure the temperature severe limits\n" + +static struct cmd_node mgr_node = { + MGR_NODE, + "%s(config-mgr)# ", + 1, +}; + +DEFUN(cfg_mgr, cfg_mgr_cmd, + "config-mgr", + MGR_STR) +{ + vty->node = MGR_NODE; + return CMD_SUCCESS; +} + +DEFUN(show_mgr, show_mgr_cmd, "show mgr", + SHOW_STR "Display information about the mgr") +{ + vty_out(vty, " temperature-warning board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_severe_limit, + mgr_cfg->temp_max_board_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-warning pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_severe_limit, + mgr_cfg->temp_max_pa_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " power-action Master:%s Slave:%s PA:%s%s", + mgr_cfg->master_power_act ? "ON" : "OFF", + mgr_cfg->slave_power_act ? "ON" : "OFF", + mgr_cfg->pa_power_act ? "ON" : "OFF", + VTY_NEWLINE); + + vty_out(vty, " power-reduce-transmitter %d%s", + mgr_cfg->reduce_max_power, + VTY_NEWLINE); + return CMD_SUCCESS; +} + +static int config_write_mgr(struct vty *vty) +{ + vty_out(vty, "config-mgr%s", VTY_NEWLINE); + + vty_out(vty, " temperature-warning board %d %d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe board %d %d%s", + mgr_cfg->temp_min_board_severe_limit, + mgr_cfg->temp_max_board_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-warning pa %d %d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe pa %d %d%s", + mgr_cfg->temp_min_pa_severe_limit, + mgr_cfg->temp_max_pa_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " power-action %s %s %s%s", + mgr_cfg->master_power_act ? "ON" : "OFF", + mgr_cfg->slave_power_act ? "ON" : "OFF", + mgr_cfg->pa_power_act ? "ON" : "OFF", + VTY_NEWLINE); + + vty_out(vty, " power-reduce-transmitter %d%s", + mgr_cfg->reduce_max_power, + VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_warn, cfg_mgr_board_temp_warn_cmd, + "temperature-warning board <-255-255> <-255-255>", + MGR_TEMP_WARN_STR + "Set warning temperature limits on the Board\n" + "Warning temperature low limit on the Board\n" + "Warning temperature high limit on the Board\n") +{ + mgr_cfg->temp_min_board_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_sever, cfg_mgr_board_temp_sever_cmd, + "temperature-severe board <-255-255> <-255-255>", + MGR_TEMP_SEVERE_STR + "Set severe temperature limits on the Board\n" + "Severe temperature low limit on the Board\n" + "Severe Temperature high limit on the Board\n") +{ + mgr_cfg->temp_min_board_severe_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_severe_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_warn, cfg_mgr_pa_temp_warn_cmd, + "temperature-warning pa <-255-255> <-255-255>", + MGR_TEMP_WARN_STR + "Set warning temperature limits on the PA\n" + "Warning temperature low limit on the PA\n" + "Warning temperature high limit on the PA\n") +{ + mgr_cfg->temp_min_pa_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_sever, cfg_mgr_pa_temp_sever_cmd, + "temperature-severe pa <-255-255> <-255-255>", + MGR_TEMP_SEVERE_STR + "Set severe temperature limits on the Board\n" + "Severe temperature low limit on the PA\n" + "Severe temperature high limit on the PA\n") +{ + mgr_cfg->temp_min_pa_severe_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_severe_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pwr_action, cfg_mgr_pwr_action_cmd, + "power-action (ON|OFF) (ON|OFF) (ON|OFF)", + "Configure which devices we want to turn on/off in several situation\n" + "the Master\n" + "the Master\n" + "the Slave\n" + "the Slave\n" + "the PA\n" + "the PA\n") +{ + if (strcmp(argv[0], "ON") == 0) + mgr_cfg->master_power_act = 1; + else if (strcmp(argv[0], "OFF") == 0) + mgr_cfg->master_power_act = 0; + + if (strcmp(argv[1], "ON") == 0) + mgr_cfg->slave_power_act = 1; + else if (strcmp(argv[1], "OFF") == 0) + mgr_cfg->slave_power_act = 0; + + if (strcmp(argv[2], "ON") == 0) + mgr_cfg->pa_power_act = 1; + else if (strcmp(argv[2], "OFF") == 0) + mgr_cfg->pa_power_act = 0; + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_baud_action, cfg_mgr_pa_baud_action_cmd, + "power-reduce-transmitter <0-255>", + "Configure the power that we want to reduce in warning situation\n" + "Power baud transmition that we want to reduce in the PA\n") +{ + mgr_cfg->reduce_max_power = atoi(argv[0]); + + return CMD_SUCCESS; +} + +int sysmobts_mgr_vty_init(void) + +{ + install_element_ve(&show_mgr_cmd); + + install_node(&mgr_node, config_write_mgr); + install_element(CONFIG_NODE, &cfg_mgr_cmd); + vty_install_default(MGR_NODE); + + install_element(MGR_NODE, &cfg_mgr_board_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_board_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pwr_action_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_baud_action_cmd); + + return 0; +} + +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg) +{ + int rc; + + mgr_cfg = cfg; + + rc = vty_read_config_file(config_file, NULL); + if (rc < 0) { + fprintf(stderr, "Failed to parse the config file: '%s'\n", + config_file); + return rc; + } + + return 0; +} -- 1.7.10.4 From holger at freyther.de Wed Apr 16 21:14:26 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Wed, 16 Apr 2014 23:14:26 +0200 Subject: [osmo-bts PATCH 2/3 v7] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1397650054-17749-1-git-send-email-anayuso@sysmocom.de> References: <1397585872-16005-1-git-send-email-anayuso@sysmocom.de> <1397650054-17749-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140416211426.GB6236@xiaoyu.lan> On Wed, Apr 16, 2014 at 02:07:34PM +0200, Alvaro Neira Ayuso wrote: > +DEFUN(cfg_mgr_pwr_action, cfg_mgr_pwr_action_cmd, > + "power-action (ON|OFF) (ON|OFF) (ON|OFF)", Why do you want to use capital letters here? No need to scream at the manager? right? > + "Configure which devices we want to turn on/off in several situation\n" > + "the Master\n" > + "the Master\n" Use different descriptions for On and Off. From anayuso at sysmocom.de Mon Apr 28 11:48:42 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Mon, 28 Apr 2014 13:48:42 +0200 Subject: [osmo-bts PATCH 4/5 v8] misc/sysmomgr: Added Vty support for configuring the manager In-Reply-To: <1397650054-17749-1-git-send-email-anayuso@sysmocom.de> References: <1397650054-17749-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1398685722-19391-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added the vty support for configuring the parameter for using the OML report in manager when we have anomalous temperature. Signed-off-by: Alvaro Neira Ayuso --- [changes in v8] * Changed the capital parameter in the function power-action * Fixed a forgot value when we print our manager configuration * Added best description in the help information of the power-action parameters doc/examples/osmobts-mgr.cfg | 30 +++ src/osmo-bts-sysmo/Makefile.am | 3 +- src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 43 ++++- src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 18 ++ src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c | 279 ++++++++++++++++++++++++++++ 5 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 doc/examples/osmobts-mgr.cfg create mode 100644 src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c diff --git a/doc/examples/osmobts-mgr.cfg b/doc/examples/osmobts-mgr.cfg new file mode 100644 index 0000000..3592202 --- /dev/null +++ b/doc/examples/osmobts-mgr.cfg @@ -0,0 +1,30 @@ +! +! SysmoMgr (0.3.0.141-33e5) configuration saved from vty +!! +! +log stderr + logging filter all 1 + logging color 1 + logging timestamp 0 + logging level all everything + logging level temp info + logging level fw info + logging level find info + logging level lglobal notice + logging level llapd notice + logging level linp notice + logging level lmux notice + logging level lmi notice + logging level lmib notice + logging level lsms notice +! +line vty + no login +! +config-mgr + temperature-warning board -30 50 + temperature-severe board -50 80 + temperature-warning pa -30 50 + temperature-severe pa -50 80 + power-action on on off + power-reduce-transmitter 4 diff --git a/src/osmo-bts-sysmo/Makefile.am b/src/osmo-bts-sysmo/Makefile.am index e9ba949..de70761 100644 --- a/src/osmo-bts-sysmo/Makefile.am +++ b/src/osmo-bts-sysmo/Makefile.am @@ -22,7 +22,8 @@ l1fwd_proxy_LDADD = $(top_builddir)/src/common/libbts.a $(COMMON_LDADD) sysmobts_mgr_SOURCES = \ misc/sysmobts_mgr.c misc/sysmobts_misc.c \ - misc/sysmobts_par.c misc/sysmobts_nl.c utils.c + misc/sysmobts_par.c misc/sysmobts_nl.c utils.c \ + misc/sysmobts_mgr_vty.c sysmobts_mgr_LDADD = $(COMMON_LDADD) sysmobts_util_SOURCES = misc/sysmobts_util.c misc/sysmobts_par.c diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 51fdd83..99e95d5 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -52,6 +52,24 @@ static int fd_unix = -1; void *tall_mgr_ctx; static struct sbts2050_config_info confinfo; +static struct sysmobts_mgr_instance sysmobts_mgr_inst = { + .config_file = "osmobts-mgr.cfg", +}; + +const char *sysmomgr_copyright = + "(C) 2012 by Harald Welte \r\n" + "(C) 2014 by Holger Hans Peter Freyther\r\n" + "License AGPLv3+: GNU AGPL version 2 or later \r\n" + "This is free software: you are free to change and redistribute it.\r\n" + "There is NO WARRANTY, to the extent permitted by law.\r\n"; + +static struct vty_app_info vty_info = { + .name = "SysmoMgr", + .version = PACKAGE_VERSION, + .go_parent_cb = mgr_vty_go_parent, + .is_config_node = mgr_vty_is_config_node, +}; + /* every 6 hours means 365*4 = 1460 EEprom writes per year (max) */ #define TEMP_TIMER_SECS (6 * 3600) @@ -221,13 +239,14 @@ static void print_help(void) printf(" -s Disable color\n"); printf(" -d CAT enable debugging\n"); printf(" -D daemonize\n"); + printf(" -c Specify the filename of the config file\n"); } static int parse_options(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "nhsd:")) != -1) { + while ((opt = getopt(argc, argv, "nhsd:c:")) != -1) { switch (opt) { case 'n': no_eeprom_write = 1; @@ -244,6 +263,9 @@ static int parse_options(int argc, char **argv) case 'D': daemonize = 1; break; + case 'c': + sysmobts_mgr_inst.config_file = optarg; + break; default: return -1; } @@ -447,6 +469,25 @@ int main(int argc, char **argv) if (rc < 0) exit(2); + vty_info.copyright = sysmomgr_copyright; + vty_init(&vty_info); + logging_vty_add_cmds(&mgr_log_info); + + sysmobts_mgr_vty_init(); + + rc = sysmobts_mgr_parse_config(sysmobts_mgr_inst.config_file, + &confinfo); + if (rc < 0) { + LOGP(DFIND, LOGL_FATAL, "Cannot parse config file\n"); + exit(1); + } + + rc = telnet_init(tall_msgb_ctx, NULL, 4252); + if (rc < 0) { + fprintf(stderr, "Error initializing telnet\n"); + exit(1); + } + /* start temperature check timer */ temp_timer.cb = check_temp_timer_cb; check_temp_timer_cb(NULL); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index 21f30a4..5e0d4a7 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -1,6 +1,9 @@ #ifndef _SYSMOBTS_MGR_H #define _SYSMOBTS_MGR_H +#include +#include + enum { DTEMP, DFW, @@ -14,4 +17,19 @@ enum { #define SOCKET_PATH "/var/run/bts_oml" +struct sbts2050_config_info; + +enum mgr_vty_node { + MGR_NODE = _LAST_OSMOVTY_NODE + 1, +}; + +enum node_type mgr_vty_go_parent(struct vty *vty); +int mgr_vty_is_config_node(struct vty *vty, int node); +int sysmobts_mgr_vty_init(void); +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg); + +struct sysmobts_mgr_instance { + const char *config_file; +}; #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c new file mode 100644 index 0000000..9a77a95 --- /dev/null +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr_vty.c @@ -0,0 +1,279 @@ +/* (C) 2014 by sysmocom - s.f.m.c. GmbH + * + * All Rights Reserved + * + * Author: Alvaro Neira Ayuso + * + * 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 "sysmobts_misc.h" +#include "sysmobts_mgr.h" + +static struct sbts2050_config_info *mgr_cfg; + +enum node_type mgr_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + case MGR_NODE: + vty->node = CONFIG_NODE; + break; + default: + vty->node = CONFIG_NODE; + } + return vty->node; +} + +int mgr_vty_is_config_node(struct vty *vty, int node) +{ + switch (node) { + case MGR_NODE: + return 1; + default: + return 0; + } +} + +#define MGR_STR "Configure sysmobts-mgr\n" +#define MGR_TEMP_WARN_STR "Configure the temperature warning limits\n" +#define MGR_TEMP_SEVERE_STR "Configure the temperature severe limits\n" + +static struct cmd_node mgr_node = { + MGR_NODE, + "%s(config-mgr)# ", + 1, +}; + +DEFUN(cfg_mgr, cfg_mgr_cmd, + "config-mgr", + MGR_STR) +{ + vty->node = MGR_NODE; + return CMD_SUCCESS; +} + +DEFUN(show_mgr, show_mgr_cmd, "show mgr", + SHOW_STR "Display information about the mgr") +{ + vty_out(vty, " temperature-warning board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe board Min:%d Max:%d%s", + mgr_cfg->temp_min_board_severe_limit, + mgr_cfg->temp_max_board_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-warning pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe pa Min:%d Max:%d%s", + mgr_cfg->temp_min_pa_severe_limit, + mgr_cfg->temp_max_pa_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " power-action Master:%s Slave:%s PA:%s%s", + mgr_cfg->master_power_act ? "on" : "off", + mgr_cfg->slave_power_act ? "on" : "off", + mgr_cfg->pa_power_act ? "on" : "off", + VTY_NEWLINE); + + vty_out(vty, " power-reduce-transmitter %d%s", + mgr_cfg->reduce_max_power, + VTY_NEWLINE); + return CMD_SUCCESS; +} + +static int config_write_mgr(struct vty *vty) +{ + vty_out(vty, "config-mgr%s", VTY_NEWLINE); + + vty_out(vty, " temperature-warning board %d %d%s", + mgr_cfg->temp_min_board_warn_limit, + mgr_cfg->temp_max_board_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe board %d %d%s", + mgr_cfg->temp_min_board_severe_limit, + mgr_cfg->temp_max_board_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-warning pa %d %d%s", + mgr_cfg->temp_min_pa_warn_limit, + mgr_cfg->temp_max_pa_warn_limit, + VTY_NEWLINE); + + vty_out(vty, " temperature-severe pa %d %d%s", + mgr_cfg->temp_min_pa_severe_limit, + mgr_cfg->temp_max_pa_severe_limit, + VTY_NEWLINE); + + vty_out(vty, " power-action %s %s %s%s", + mgr_cfg->master_power_act ? "on" : "off", + mgr_cfg->slave_power_act ? "on" : "off", + mgr_cfg->pa_power_act ? "on" : "off", + VTY_NEWLINE); + + vty_out(vty, " power-reduce-transmitter %d%s", + mgr_cfg->reduce_max_power, + VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_warn, cfg_mgr_board_temp_warn_cmd, + "temperature-warning board <-255-255> <-255-255>", + MGR_TEMP_WARN_STR + "Set warning temperature limits on the Board\n" + "Warning temperature low limit on the Board\n" + "Warning temperature high limit on the Board\n") +{ + mgr_cfg->temp_min_board_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_board_temp_sever, cfg_mgr_board_temp_sever_cmd, + "temperature-severe board <-255-255> <-255-255>", + MGR_TEMP_SEVERE_STR + "Set severe temperature limits on the Board\n" + "Severe temperature low limit on the Board\n" + "Severe Temperature high limit on the Board\n") +{ + mgr_cfg->temp_min_board_severe_limit = atoi(argv[0]); + mgr_cfg->temp_max_board_severe_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_warn, cfg_mgr_pa_temp_warn_cmd, + "temperature-warning pa <-255-255> <-255-255>", + MGR_TEMP_WARN_STR + "Set warning temperature limits on the PA\n" + "Warning temperature low limit on the PA\n" + "Warning temperature high limit on the PA\n") +{ + mgr_cfg->temp_min_pa_warn_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_warn_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_temp_sever, cfg_mgr_pa_temp_sever_cmd, + "temperature-severe pa <-255-255> <-255-255>", + MGR_TEMP_SEVERE_STR + "Set severe temperature limits on the Board\n" + "Severe temperature low limit on the PA\n" + "Severe temperature high limit on the PA\n") +{ + mgr_cfg->temp_min_pa_severe_limit = atoi(argv[0]); + mgr_cfg->temp_max_pa_severe_limit = atoi(argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pwr_action, cfg_mgr_pwr_action_cmd, + "power-action (on|off) (on|off) (on|off)", + "Configure which devices we want to turn on/off in several situation\n" + "Turn on the Master\n" + "Turn off the Master\n" + "Turn on the Slave\n" + "Turn off the Slave\n" + "Turn on the PA\n" + "Turn off the PA\n") +{ + if (strcmp(argv[0], "on") == 0) + mgr_cfg->master_power_act = 1; + else if (strcmp(argv[0], "off") == 0) + mgr_cfg->master_power_act = 0; + + if (strcmp(argv[1], "on") == 0) + mgr_cfg->slave_power_act = 1; + else if (strcmp(argv[1], "off") == 0) + mgr_cfg->slave_power_act = 0; + + if (strcmp(argv[2], "on") == 0) + mgr_cfg->pa_power_act = 1; + else if (strcmp(argv[2], "off") == 0) + mgr_cfg->pa_power_act = 0; + + return CMD_SUCCESS; +} + +DEFUN(cfg_mgr_pa_baud_action, cfg_mgr_pa_baud_action_cmd, + "power-reduce-transmitter <0-255>", + "Configure the power that we want to reduce in warning situation\n" + "Power baud transmition that we want to reduce in the PA\n") +{ + mgr_cfg->reduce_max_power = atoi(argv[0]); + + return CMD_SUCCESS; +} + +int sysmobts_mgr_vty_init(void) + +{ + install_element_ve(&show_mgr_cmd); + + install_node(&mgr_node, config_write_mgr); + install_element(CONFIG_NODE, &cfg_mgr_cmd); + vty_install_default(MGR_NODE); + + install_element(MGR_NODE, &cfg_mgr_board_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_board_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_warn_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_temp_sever_cmd); + install_element(MGR_NODE, &cfg_mgr_pwr_action_cmd); + install_element(MGR_NODE, &cfg_mgr_pa_baud_action_cmd); + + return 0; +} + +int sysmobts_mgr_parse_config(const char *config_file, + struct sbts2050_config_info *cfg) +{ + int rc; + + mgr_cfg = cfg; + + rc = vty_read_config_file(config_file, NULL); + if (rc < 0) { + fprintf(stderr, "Failed to parse the config file: '%s'\n", + config_file); + return rc; + } + + return 0; +} -- 1.7.10.4 From jerlbeck at sysmocom.de Thu Apr 3 10:10:24 2014 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Thu, 3 Apr 2014 12:10:24 +0200 Subject: [PATCH] ipa: Be consistent in checking conn->cfg (Coverity) Message-ID: <1396519824-29145-1-git-send-email-jerlbeck@sysmocom.de> Coverity complains about checking connection->cfg in bsc_close_connection() at one place but not at the second. This patch fixes this by adding a check before accessing cfg when generating the 'partial message' log message. Fixes: Coverity CID 1195180 Sponsored-by: On-Waves ehf --- openbsc/src/osmo-bsc_nat/bsc_nat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index 524186a..9defbd2 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -916,7 +916,7 @@ void bsc_close_connection(struct bsc_connection *connection) if (connection->pending_msg) { LOGP(DNAT, LOGL_ERROR, "Dropping partial message on connection %d.\n", - connection->cfg->nr); + connection->cfg ? connection->cfg->nr : -1); msgb_free(connection->pending_msg); connection->pending_msg = NULL; } -- 1.7.9.5 From anayuso at sysmocom.de Tue Apr 8 12:40:35 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Tue, 8 Apr 2014 14:40:35 +0200 Subject: [osmo-bts PATCH 3/3] main: Added support for changing the max_power_red in sbts2050 Message-ID: <1396960835-14662-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added functions for changing the max_power_red in case of we receive a Failure Event report from the manager. The sbts2050 change the max_power_red to the value that we have configured in the manager and the sbts2050 restore this value to the initial value if the bts don't receive another Failure Event report in the same time that we check the temperature in the manager. Signed-off-by: Alvaro Neira Ayuso --- src/osmo-bts-sysmo/main.c | 67 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 61a5716..b492327 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -55,11 +56,14 @@ #define IPA_HEADER_SIZE 3 #define IPA_OML_PROTO 0xFF +#define TEMP_TIMER_SECS (6 * 3600) + 1 + #include "utils.h" #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" #include "btsconfig.h" +#include /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -297,6 +301,60 @@ static int write_pid_file(char *procname) return 0; } #ifdef BUILD_SBTS2050 +static int init_max_power_red; +static int new_max_power_red; +static int status_change_power_red = 0; + +enum { + SBTS2050_DISABLE_CHANGE_POWER = 0, + SBTS2050_ENABLE_CHANGE_POWER, +}; + +#define oml_tlv_parse(dec, buf, len) \ + tlv_parse(dec, &abis_nm_att_tlvdef, buf, len, 0, 0) + +/* Size of the struct plus 1 Bytes of tag and 2 Bytes for the length */ +#define tlv_add_info_len() (sizeof(struct sbts2050_config_info) + 3) + +static struct osmo_timer_list power_timer; +static void change_max_power_red_cb(void *data) +{ + struct gsm_bts *bts = data; + + if (status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) { + if (bts->c0->max_power_red != new_max_power_red) { + init_max_power_red = bts->c0->max_power_red; + bts->c0->max_power_red = new_max_power_red; + } + status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER; + osmo_timer_schedule(&power_timer, TEMP_TIMER_SECS, 0); + } else if (status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) + bts->c0->max_power_red = init_max_power_red; +} + +static int take_max_power_red(struct msgb *msg) +{ + struct sbts2050_config_info *config_info; + struct tlv_parsed tlv_out; + int rc; + + rc = oml_tlv_parse(&tlv_out, msg->tail - tlv_add_info_len(), + tlv_add_info_len()); + + if (rc < 0) + return -1; + + config_info = + (struct sbts2050_config_info *) TLVP_VAL(&tlv_out, NM_ATT_ADD_INFO); + + new_max_power_red = config_info->max_power_red; + + status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER; + change_max_power_red_cb(bts); + + return 0; +} + static int test_recv_msg(struct msgb *msg) { struct ipaccess_head *hh = (struct ipaccess_head *)msg->data; @@ -355,6 +413,11 @@ static int read_sock(struct osmo_fd *fd, unsigned int what) return -1; } + if (take_max_power_red(msg) < 0) { + LOGP(DL1C, LOGL_NOTICE, "Failed Add_info: Malformed message"); + return -1; + } + mo = &bts->mo; msg->trx = mo->bts->c0; @@ -478,6 +541,10 @@ int main(int argc, char **argv) read_fd.fd = -1; accept_fd.data = &read_fd; + init_max_power_red = bts->c0->max_power_red; + power_timer.cb = change_max_power_red_cb; + power_timer.data = bts; + rc = osmo_sock_unix_init_ofd(&accept_fd, SOCK_SEQPACKET, 0, SOCKET_PATH, OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); if (rc < 0) { -- 1.7.10.4 From pablo at gnumonks.org Wed Apr 9 08:41:26 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Wed, 9 Apr 2014 10:41:26 +0200 Subject: [osmo-bts PATCH 3/3] main: Added support for changing the max_power_red in sbts2050 In-Reply-To: <1396960835-14662-1-git-send-email-anayuso@sysmocom.de> References: <1396960835-14662-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140409084126.GC5744@localhost> On Tue, Apr 08, 2014 at 02:40:35PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > > Added functions for changing the max_power_red in case of we receive a Failure > Event report from the manager. The sbts2050 change the max_power_red to the value > that we have configured in the manager and the sbts2050 restore this value to the > initial value if the bts don't receive another Failure Event report in the same time > that we check the temperature in the manager. > > Signed-off-by: Alvaro Neira Ayuso > --- > src/osmo-bts-sysmo/main.c | 67 +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 67 insertions(+) > > diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c > index 61a5716..b492327 100644 > --- a/src/osmo-bts-sysmo/main.c > +++ b/src/osmo-bts-sysmo/main.c > @@ -39,6 +39,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -55,11 +56,14 @@ > #define IPA_HEADER_SIZE 3 > #define IPA_OML_PROTO 0xFF > > +#define TEMP_TIMER_SECS (6 * 3600) + 1 > + > #include "utils.h" > #include "eeprom.h" > #include "l1_if.h" > #include "hw_misc.h" > #include "btsconfig.h" > +#include > > /* FIXME: read from real hardware */ > const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; > @@ -297,6 +301,60 @@ static int write_pid_file(char *procname) > return 0; > } > #ifdef BUILD_SBTS2050 > +static int init_max_power_red; > +static int new_max_power_red; > +static int status_change_power_red = 0; > + > +enum { > + SBTS2050_DISABLE_CHANGE_POWER = 0, > + SBTS2050_ENABLE_CHANGE_POWER, > +}; > + > +#define oml_tlv_parse(dec, buf, len) \ > + tlv_parse(dec, &abis_nm_att_tlvdef, buf, len, 0, 0) > + > +/* Size of the struct plus 1 Bytes of tag and 2 Bytes for the length */ > +#define tlv_add_info_len() (sizeof(struct sbts2050_config_info) + 3) ^^ Better? #define TLV_INFO_LEN (sizeof(struct sbts2050_config_info) + 3) The remaning part looks good to me. Thanks Alvaro. > + > +static struct osmo_timer_list power_timer; > +static void change_max_power_red_cb(void *data) > +{ > + struct gsm_bts *bts = data; > + > + if (status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) { > + if (bts->c0->max_power_red != new_max_power_red) { > + init_max_power_red = bts->c0->max_power_red; > + bts->c0->max_power_red = new_max_power_red; > + } > + status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER; > + osmo_timer_schedule(&power_timer, TEMP_TIMER_SECS, 0); > + } else if (status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) > + bts->c0->max_power_red = init_max_power_red; > +} > + > +static int take_max_power_red(struct msgb *msg) > +{ > + struct sbts2050_config_info *config_info; > + struct tlv_parsed tlv_out; > + int rc; > + > + rc = oml_tlv_parse(&tlv_out, msg->tail - tlv_add_info_len(), > + tlv_add_info_len()); > + > + if (rc < 0) > + return -1; > + > + config_info = > + (struct sbts2050_config_info *) TLVP_VAL(&tlv_out, NM_ATT_ADD_INFO); > + > + new_max_power_red = config_info->max_power_red; > + > + status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER; > + change_max_power_red_cb(bts); > + > + return 0; > +} > + > static int test_recv_msg(struct msgb *msg) > { > struct ipaccess_head *hh = (struct ipaccess_head *)msg->data; > @@ -355,6 +413,11 @@ static int read_sock(struct osmo_fd *fd, unsigned int what) > return -1; > } > > + if (take_max_power_red(msg) < 0) { > + LOGP(DL1C, LOGL_NOTICE, "Failed Add_info: Malformed message"); > + return -1; > + } > + > mo = &bts->mo; > msg->trx = mo->bts->c0; > > @@ -478,6 +541,10 @@ int main(int argc, char **argv) > read_fd.fd = -1; > accept_fd.data = &read_fd; > > + init_max_power_red = bts->c0->max_power_red; > + power_timer.cb = change_max_power_red_cb; > + power_timer.data = bts; > + > rc = osmo_sock_unix_init_ofd(&accept_fd, SOCK_SEQPACKET, 0, SOCKET_PATH, > OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); > if (rc < 0) { > -- > 1.7.10.4 > > From anayuso at sysmocom.de Thu Apr 10 10:33:22 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Thu, 10 Apr 2014 12:33:22 +0200 Subject: [osmo-bts PATCH 3/3 v2] main: Added support for changing the max_power_red in sbts2050 In-Reply-To: <1396960835-14662-1-git-send-email-anayuso@sysmocom.de> References: <1396960835-14662-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397126002-29151-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added functions for changing the max_power_red in case of we receive a Failure Event report from the manager. The sbts2050 change the max_power_red to the value that we have configured in the manager and the sbts2050 restore this value to the initial value if the bts don't receive another Failure Event report in the same time that we check the temperature in the manager. Signed-off-by: Alvaro Neira Ayuso --- [changes in v2] * Renamed the constant variable tlv_add_info_len() to TLV_INFO_LEN src/osmo-bts-sysmo/main.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 7e332ad..9ced374 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -54,11 +55,14 @@ #define IPA_OML_PROTO 0xFF +#define TEMP_TIMER_SECS ((6 * 3600) + 1) + #include "utils.h" #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" #include "btsconfig.h" +#include /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -297,6 +301,60 @@ static int write_pid_file(char *procname) } #ifdef BUILD_SBTS2050 +static int init_max_power_red; +static int new_max_power_red; +static int status_change_power_red = 0; + +enum { + SBTS2050_DISABLE_CHANGE_POWER = 0, + SBTS2050_ENABLE_CHANGE_POWER, +}; + +#define oml_tlv_parse(dec, buf, len) \ + tlv_parse(dec, &abis_nm_att_tlvdef, buf, len, 0, 0) + +/* size of the struct plus 1 Bytes of tag and 2 Bytes for the length */ +#define TLV_ADD_INFO_LEN (sizeof(struct sbts2050_config_info) + 3) + +static struct osmo_timer_list power_timer; +static void change_max_power_red_cb(void *data) +{ + struct gsm_bts *bts = data; + + if (status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) { + if (bts->c0->max_power_red != new_max_power_red) { + init_max_power_red = bts->c0->max_power_red; + bts->c0->max_power_red = new_max_power_red; + } + status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER; + osmo_timer_schedule(&power_timer, TEMP_TIMER_SECS, 0); + } else if (status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) + bts->c0->max_power_red = init_max_power_red; +} + +static int take_max_power_red(struct msgb *msg) +{ + struct sbts2050_config_info *config_info; + struct tlv_parsed tlv_out; + int rc; + + rc = oml_tlv_parse(&tlv_out, msg->tail - TLV_ADD_INFO_LEN, + TLV_ADD_INFO_LEN); + + if (rc < 0) + return -1; + + config_info = + (struct sbts2050_config_info *) TLVP_VAL(&tlv_out, NM_ATT_ADD_INFO); + + new_max_power_red = config_info->max_power_red; + + status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER; + change_max_power_red_cb(bts); + + return 0; +} + static int test_recv_msg(struct msgb *msg) { struct ipaccess_head *hh; @@ -376,6 +434,11 @@ static int read_sock(struct osmo_fd *fd, unsigned int what) goto err; } + if (take_max_power_red(msg) < 0) { + LOGP(DL1C, LOGL_NOTICE, "Failed Add_info: Malformed message"); + goto err; + } + mo = &bts->mo; msg->trx = mo->bts->c0; @@ -422,6 +485,9 @@ static int sbts2050_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) read->fd = -1; accept->data = read; + power_timer.cb = change_max_power_red_cb; + power_timer.data = bts; + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); return rc; -- 1.7.10.4 From anayuso at sysmocom.de Thu Apr 10 13:45:21 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Thu, 10 Apr 2014 15:45:21 +0200 Subject: [osmo-bts PATCH 3/3 v3] main: Added support for changing the max_power_red in sbts2050 In-Reply-To: <1397126002-29151-1-git-send-email-anayuso@sysmocom.de> References: <1397126002-29151-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397137521-12889-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added functions for changing the max_power_red in case of we receive a Failure Event report from the manager. The sbts2050 change the max_power_red to the value that we have configured in the manager and the sbts2050 restore this value to the initial value if the bts don't receive another Failure Event report in the same time that we check the temperature in the manager. Signed-off-by: Alvaro Neira Ayuso --- [changes in v3] * Changed LOGL_NOTICE with LOGL_ERROR in error cases. src/osmo-bts-sysmo/main.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index b93667d..a4927f0 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -54,11 +55,14 @@ #define IPA_OML_PROTO 0xFF +#define TEMP_TIMER_SECS ((6 * 3600) + 1) + #include "utils.h" #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" #include "btsconfig.h" +#include /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -297,6 +301,60 @@ static int write_pid_file(char *procname) } #ifdef BUILD_SBTS2050 +static int init_max_power_red; +static int new_max_power_red; +static int status_change_power_red = 0; + +enum { + SBTS2050_DISABLE_CHANGE_POWER = 0, + SBTS2050_ENABLE_CHANGE_POWER, +}; + +#define oml_tlv_parse(dec, buf, len) \ + tlv_parse(dec, &abis_nm_att_tlvdef, buf, len, 0, 0) + +/* size of the struct plus 1 Bytes of tag and 2 Bytes for the length */ +#define TLV_ADD_INFO_LEN (sizeof(struct sbts2050_config_info) + 3) + +static struct osmo_timer_list power_timer; +static void change_max_power_red_cb(void *data) +{ + struct gsm_bts *bts = data; + + if (status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) { + if (bts->c0->max_power_red != new_max_power_red) { + init_max_power_red = bts->c0->max_power_red; + bts->c0->max_power_red = new_max_power_red; + } + status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER; + osmo_timer_schedule(&power_timer, TEMP_TIMER_SECS, 0); + } else if (status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) + bts->c0->max_power_red = init_max_power_red; +} + +static int take_max_power_red(struct msgb *msg) +{ + struct sbts2050_config_info *config_info; + struct tlv_parsed tlv_out; + int rc; + + rc = oml_tlv_parse(&tlv_out, msg->tail - TLV_ADD_INFO_LEN, + TLV_ADD_INFO_LEN); + + if (rc < 0) + return -1; + + config_info = + (struct sbts2050_config_info *) TLVP_VAL(&tlv_out, NM_ATT_ADD_INFO); + + new_max_power_red = config_info->max_power_red; + + status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER; + change_max_power_red_cb(bts); + + return 0; +} + static int test_recv_msg(struct msgb *msg) { struct ipaccess_head *hh; @@ -392,6 +450,11 @@ static int read_sock(struct osmo_fd *fd, unsigned int what) goto err; } + if (take_max_power_red(msg) < 0) { + LOGP(DL1C, LOGL_ERROR, "Failed Add_info: Malformed message\n"); + goto err; + } + mo = &bts->mo; msg->trx = mo->bts->c0; @@ -441,6 +504,9 @@ static int sbts2050_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) read->fd = -1; accept->data = read; + power_timer.cb = change_max_power_red_cb; + power_timer.data = bts; + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); return rc; -- 1.7.10.4 From anayuso at sysmocom.de Sun Apr 13 13:26:35 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Sun, 13 Apr 2014 15:26:35 +0200 Subject: [osmo-bts PATCH 3/3 v4] main: Added support for changing the max_power_red in sbts2050 In-Reply-To: <1397137521-12889-1-git-send-email-anayuso@sysmocom.de> References: <1397137521-12889-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397395595-14818-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added functions for changing the max_power_red in case of we receive a Failure Event report from the manager. The sbts2050 change the max_power_red to the value that we have configured in the manager and the sbts2050 restore this value to the initial value if the bts don't receive another Failure Event report in the same time that we check the temperature in the manager. Signed-off-by: Alvaro Neira Ayuso --- [changes in v4] * Changed the message in the log functions for using a incorrect message format src/osmo-bts-sysmo/main.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 98da626..a3be9a3 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -54,11 +55,14 @@ #define IPA_OML_PROTO 0xFF +#define TEMP_TIMER_SECS ((6 * 3600) + 1) + #include "utils.h" #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" #include "btsconfig.h" +#include /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -297,6 +301,60 @@ static int write_pid_file(char *procname) } #ifdef BUILD_SBTS2050 +static int init_max_power_red; +static int new_max_power_red; +static int status_change_power_red = 0; + +enum { + SBTS2050_DISABLE_CHANGE_POWER = 0, + SBTS2050_ENABLE_CHANGE_POWER, +}; + +#define oml_tlv_parse(dec, buf, len) \ + tlv_parse(dec, &abis_nm_att_tlvdef, buf, len, 0, 0) + +/* size of the struct plus 1 Bytes of tag and 2 Bytes for the length */ +#define TLV_ADD_INFO_LEN (sizeof(struct sbts2050_config_info) + 3) + +static struct osmo_timer_list power_timer; +static void change_max_power_red_cb(void *data) +{ + struct gsm_bts *bts = data; + + if (status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) { + if (bts->c0->max_power_red != new_max_power_red) { + init_max_power_red = bts->c0->max_power_red; + bts->c0->max_power_red = new_max_power_red; + } + status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER; + osmo_timer_schedule(&power_timer, TEMP_TIMER_SECS, 0); + } else if (status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) + bts->c0->max_power_red = init_max_power_red; +} + +static int take_max_power_red(struct msgb *msg) +{ + struct sbts2050_config_info *config_info; + struct tlv_parsed tlv_out; + int rc; + + rc = oml_tlv_parse(&tlv_out, msg->tail - TLV_ADD_INFO_LEN, + TLV_ADD_INFO_LEN); + + if (rc < 0) + return -1; + + config_info = + (struct sbts2050_config_info *) TLVP_VAL(&tlv_out, NM_ATT_ADD_INFO); + + new_max_power_red = config_info->max_power_red; + + status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER; + change_max_power_red_cb(bts); + + return 0; +} + static int test_recv_msg(struct msgb *msg) { struct ipaccess_head *hh; @@ -392,6 +450,11 @@ static int read_sock(struct osmo_fd *fd, unsigned int what) goto err; } + if (take_max_power_red(msg) < 0) { + LOGP(DL1C, LOGL_ERROR, "Add_info Malformed message\n"); + goto err; + } + mo = &bts->mo; msg->trx = mo->bts->c0; @@ -441,6 +504,9 @@ static int sbts2050_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) read->fd = -1; accept->data = read; + power_timer.cb = change_max_power_red_cb; + power_timer.data = bts; + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); return rc; -- 1.7.10.4 From pablo at gnumonks.org Mon Apr 14 12:13:26 2014 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Mon, 14 Apr 2014 14:13:26 +0200 Subject: [osmo-bts PATCH 3/3 v4] main: Added support for changing the max_power_red in sbts2050 In-Reply-To: <1397395595-14818-1-git-send-email-anayuso@sysmocom.de> References: <1397137521-12889-1-git-send-email-anayuso@sysmocom.de> <1397395595-14818-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140414121326.GC21855@localhost> On Sun, Apr 13, 2014 at 03:26:35PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > > Added functions for changing the max_power_red in case of we receive > a Failure Event report from the manager. The sbts2050 change the > max_power_red to the value that we have configured in the manager > and the sbts2050 restore this value to the initial value if the bts > don't receive another Failure Event report in the same time that we > check the temperature in the manager. Acked-by: Pablo Neira Ayuso From anayuso at sysmocom.de Tue Apr 15 18:20:03 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Tue, 15 Apr 2014 20:20:03 +0200 Subject: [osmo-bts PATCH 3/3 v5] main: Added support for changing the max_power_red in sbts2050 In-Reply-To: <1397395595-14818-1-git-send-email-anayuso@sysmocom.de> References: <1397395595-14818-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397586003-16077-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added functions for changing the max_power_red in case of we receive a Failure Event report from the manager. The sbts2050 change the max_power_red to the value that we have configured in the manager and the sbts2050 restore this value to the initial value if the bts don't receive another Failure Event report in the same time that we check the temperature in the manager. Signed-off-by: Alvaro Neira Ayuso --- [changed in v5] * Added the function for updating the power transmitter * Changed the transmitter reduce power for using a relative value and not a absolute value. src/osmo-bts-sysmo/main.c | 79 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 11e1878..3f2a20d 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -53,11 +54,14 @@ #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" +#define TEMP_TIMER_SECS ((6 * 3600) + 1) + #include "utils.h" #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" #include "btsconfig.h" +#include /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -295,6 +299,73 @@ static int write_pid_file(char *procname) return 0; } +static int reduce_max_power; +static int status_change_power_red; + +enum { + SBTS2050_DISABLE_CHANGE_POWER = 0, + SBTS2050_ENABLE_CHANGE_POWER, +}; + +#define oml_tlv_parse(dec, buf, len) \ + tlv_parse(dec, &abis_nm_att_tlvdef, buf, len, 0, 0) + +/* size of the struct plus 1 Bytes of tag and 2 Bytes for the length */ +#define TLV_ADD_INFO_LEN (sizeof(struct sbts2050_config_info) + 3) + +/********************************************************************** + * Function for change the transmitter power + *********************************************************************/ +static void update_transmiter_power(struct gsm_bts_trx *trx, int reduce_power) +{ + struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); + int power_transmitter = trx->nominal_power - trx->max_power_red; + + if (fl1h->hLayer1) + l1if_set_txpower(fl1h, power_transmitter - reduce_power); +} + +static struct osmo_timer_list power_timer; +static void change_transmitter_power_cb(void *data) +{ + struct gsm_bts *bts = data; + struct gsm_bts_trx *trx = bts->c0; + + if (status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) { + update_transmiter_power(trx, reduce_max_power); + status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER; + osmo_timer_schedule(&power_timer, TEMP_TIMER_SECS, 0); + } else if (status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) + update_transmiter_power(trx, 0); +} + +/********************************************************************** + * Function for take the power that we have configured for + * reduce the transmitter power + *********************************************************************/ +static int take_max_power_red(struct msgb *msg) +{ + struct sbts2050_config_info *config_info; + struct tlv_parsed tlv_out; + int rc; + + rc = oml_tlv_parse(&tlv_out, msg->tail - TLV_ADD_INFO_LEN, + TLV_ADD_INFO_LEN); + + if (rc < 0) + return -1; + + config_info = + (struct sbts2050_config_info *) TLVP_VAL(&tlv_out, NM_ATT_ADD_INFO); + + reduce_max_power = config_info->reduce_max_power; + + status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER; + change_transmitter_power_cb(bts); + + return 0; +} + /********************************************************************** * Function for checking that the OML msg received is well-formed *********************************************************************/ @@ -405,6 +476,11 @@ static int read_sock(struct osmo_fd *fd, unsigned int what) goto err; } + if (take_max_power_red(msg) < 0) { + LOGP(DL1C, LOGL_ERROR, "Add_info Malformed message\n"); + goto err; + } + mo = &bts->mo; msg->trx = mo->bts->c0; @@ -459,6 +535,9 @@ static int oml_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) read->fd = -1; accept->data = read; + power_timer.cb = change_transmitter_power_cb; + power_timer.data = bts; + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); return rc; -- 1.7.10.4 From anayuso at sysmocom.de Wed Apr 16 12:09:39 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Wed, 16 Apr 2014 14:09:39 +0200 Subject: [osmo-bts PATCH 3/3 v6] main: Added support for changing the max_power_red in sbts2050 In-Reply-To: <1397586003-16077-1-git-send-email-anayuso@sysmocom.de> References: <1397586003-16077-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1397650179-17828-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added functions for changing the max_power_red in case of we receive a Failure Event report from the manager. The sbts2050 change the max_power_red to the value that we have configured in the manager and the sbts2050 restore this value to the initial value if the bts don't receive another Failure Event report in the same time that we check the temperature in the manager. Signed-off-by: Alvaro Neira Ayuso --- [changes in v6] * Added the floor 0 when the reduce_power is bigger than nominal_power - max_power_red src/osmo-bts-sysmo/main.c | 80 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index aafbc50..269a64d 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -53,11 +54,14 @@ #define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock" +#define TEMP_TIMER_SECS ((6 * 3600) + 1) + #include "utils.h" #include "eeprom.h" #include "l1_if.h" #include "hw_misc.h" #include "btsconfig.h" +#include /* FIXME: read from real hardware */ const uint8_t abis_mac[6] = { 0,1,2,3,4,5 }; @@ -295,6 +299,74 @@ static int write_pid_file(char *procname) return 0; } +static int reduce_max_power; +static int status_change_power_red; +static int last_power_transmitter = -1; +enum { + SBTS2050_DISABLE_CHANGE_POWER = 0, + SBTS2050_ENABLE_CHANGE_POWER, +}; + +#define oml_tlv_parse(dec, buf, len) \ + tlv_parse(dec, &abis_nm_att_tlvdef, buf, len, 0, 0) + +/* size of the struct plus 1 Bytes of tag and 2 Bytes for the length */ +#define TLV_ADD_INFO_LEN (sizeof(struct sbts2050_config_info) + 3) + +static void update_transmiter_power(struct gsm_bts_trx *trx, int reduce_power) +{ + struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); + int power_transmitter = trx->nominal_power - trx->max_power_red; + + power_transmitter -= reduce_power; + if (power_transmitter < 0) + power_transmitter = 0; + + if (last_power_transmitter != power_transmitter) { + if (fl1h->hLayer1) { + l1if_set_txpower(fl1h, power_transmitter); + last_power_transmitter = power_transmitter; + } + } +} + +static struct osmo_timer_list power_timer; +static void change_transmitter_power_cb(void *data) +{ + struct gsm_bts *bts = data; + struct gsm_bts_trx *trx = bts->c0; + + if (status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) { + update_transmiter_power(trx, reduce_max_power); + status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER; + osmo_timer_schedule(&power_timer, TEMP_TIMER_SECS, 0); + } else if (status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) + update_transmiter_power(trx, 0); +} + +static int take_max_power_red(struct msgb *msg) +{ + struct sbts2050_config_info *config_info; + struct tlv_parsed tlv_out; + int rc; + + rc = oml_tlv_parse(&tlv_out, msg->tail - TLV_ADD_INFO_LEN, + TLV_ADD_INFO_LEN); + + if (rc < 0) + return -1; + + config_info = + (struct sbts2050_config_info *) TLVP_VAL(&tlv_out, NM_ATT_ADD_INFO); + + reduce_max_power = config_info->reduce_max_power; + + status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER; + change_transmitter_power_cb(bts); + + return 0; +} + /* * In succesfully case, this function set again the pointers of the l2h and l3h * of the OML message that we have received. In other case, we don't set the @@ -404,6 +476,11 @@ static int read_sock(struct osmo_fd *fd, unsigned int what) goto err; } + if (take_max_power_red(msg) < 0) { + LOGP(DL1C, LOGL_ERROR, "Add_info Malformed message\n"); + goto err; + } + mo = &bts->mo; msg->trx = mo->bts->c0; @@ -452,6 +529,9 @@ static int oml_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read) read->fd = -1; accept->data = read; + power_timer.cb = change_transmitter_power_cb; + power_timer.data = bts; + rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH, OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK); return rc; -- 1.7.10.4 From holger at freyther.de Wed Apr 16 21:20:07 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Wed, 16 Apr 2014 23:20:07 +0200 Subject: [osmo-bts PATCH 3/3 v6] main: Added support for changing the max_power_red in sbts2050 In-Reply-To: <1397650179-17828-1-git-send-email-anayuso@sysmocom.de> References: <1397586003-16077-1-git-send-email-anayuso@sysmocom.de> <1397650179-17828-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140416212007.GC6236@xiaoyu.lan> On Wed, Apr 16, 2014 at 02:09:39PM +0200, Alvaro Neira Ayuso wrote: > +static void update_transmiter_power(struct gsm_bts_trx *trx, int reduce_power) > +{ > + struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); > + int power_transmitter = trx->nominal_power - trx->max_power_red; > + > + power_transmitter -= reduce_power; > + if (power_transmitter < 0) > + power_transmitter = 0; This would be third place we calculate "trx->nominal_power - trx->max_power_red". The code is also fragile in regard to a sequence like this: 1.) BTS is powering up with lower power output 2.) It gets too hot already and the manager reduces the power 3.) BTS is increasing the power. With 3rd your reduction in 2nd would be undone. The right and safe way to handle it is to: * Store the manager power reduction in another variable (e.g. inside the fl1h or the trx) * Assign this variable * Have one function that works on the trx and returns you the nominal power to be used by the DSP/FPGA. This way the order of power reduction changes does not matter. > + > + if (last_power_transmitter != power_transmitter) { > + if (fl1h->hLayer1) { > + l1if_set_txpower(fl1h, power_transmitter); > + last_power_transmitter = power_transmitter; global state? Why is that needed? > +static struct osmo_timer_list power_timer; > +static void change_transmitter_power_cb(void *data) > +{ > + struct gsm_bts *bts = data; > + struct gsm_bts_trx *trx = bts->c0; > + > + if (status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) { > + update_transmiter_power(trx, reduce_max_power); > + status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER; > + osmo_timer_schedule(&power_timer, TEMP_TIMER_SECS, 0); > + } else if (status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) > + update_transmiter_power(trx, 0); > +} > + > +static int take_max_power_red(struct msgb *msg) > +{ > + struct sbts2050_config_info *config_info; > + struct tlv_parsed tlv_out; > + int rc; > + > + rc = oml_tlv_parse(&tlv_out, msg->tail - TLV_ADD_INFO_LEN, > + TLV_ADD_INFO_LEN); > + > + if (rc < 0) > + return -1; > + > + config_info = > + (struct sbts2050_config_info *) TLVP_VAL(&tlv_out, NM_ATT_ADD_INFO); > + > + reduce_max_power = config_info->reduce_max_power; > + > + status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER; > + change_transmitter_power_cb(bts); > + > + return 0; > +} Why do we need a timer in the sysmobts binary? If the switching of the power should be delayed, the manager should do this as part of the management. From anayuso at sysmocom.de Mon Apr 28 12:01:28 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Mon, 28 Apr 2014 14:01:28 +0200 Subject: [osmo-bts PATCH 5/5 v7] main: Added support for changing the power transmitter in sbts2050 In-Reply-To: <1397650179-17828-1-git-send-email-anayuso@sysmocom.de> References: <1397650179-17828-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1398686488-20113-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Added functions for changing the power transmitter in case of we receive a Failure Event report from the manager. The sbts2050 decress the power transmitter with the value that we have configured in the manager. For doing that the manager send a OML message with the power that we want to decress in warning case and too send another OML message for restoring the power transmitter. Signed-off-by: Alvaro Neira Ayuso --- [changes in v7] * Changed the reduce support. Now, We have the timer in the manager and in warning case, we will send a OML MANUF message to the BTS for saying that the BTS need to reduce the power with the value that we have configured in the manager. If everything is correct on the BTS, the BTS send a ACK to the manager for confirm that the power has been updated. In other case, the BTS send a NACK. src/osmo-bts-sysmo/main.c | 123 ++++++++++++++++++++++++++++++- src/osmo-bts-sysmo/misc/sysmobts_mgr.c | 32 +++++--- src/osmo-bts-sysmo/misc/sysmobts_mgr.h | 9 +++ src/osmo-bts-sysmo/misc/sysmobts_misc.c | 69 +++++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_misc.h | 2 + 5 files changed, 224 insertions(+), 11 deletions(-) diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index acdf6fc..695bdaa 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -294,10 +295,107 @@ static int write_pid_file(char *procname) return 0; } +#define oml_tlv_parse(dec, buf, len) \ + tlv_parse(dec, &abis_nm_att_tlvdef, buf, len, 0, 0) + +static int send_oml_fom_ack_nack(int fd_unix, struct msgb *old_msg, + uint8_t cause, int is_manuf) +{ + struct abis_om_hdr *old_om = msgb_l2(old_msg); + struct abis_om_fom_hdr *old_foh = msgb_l3(old_msg); + struct msgb *msg; + struct abis_om_fom_hdr *foh; + struct abis_om_hdr *om; + int rc; + + msg = oml_msgb_alloc(); + if (!msg) + return -ENOMEM; + + msg->l3h = msgb_push(msg, sizeof(*foh)); + foh = (struct abis_om_fom_hdr *) msg->l3h; + memcpy(foh, old_foh, sizeof(*foh)); + + if (is_manuf) { + /* length byte, string + 0 termination */ + uint8_t *manuf = msgb_push(msg, 1 + sizeof(osmobts_magic)); + manuf[0] = strlen(osmobts_magic)+1; + memcpy(manuf+1, osmobts_magic, strlen(osmobts_magic)); + } + + msg->l2h = msgb_push(msg, sizeof(*om)); + om = (struct abis_om_hdr *) msg->l2h; + memcpy(om, old_om, sizeof(*om)); + + /* alter message type */ + if (cause) { + LOGP(DOML, LOGL_ERROR, "Sending FOM NACK with cause %s.\n", + abis_nm_nack_cause_name(cause)); + foh->msg_type += 2; /* nack */ + msgb_tv_put(msg, NM_ATT_NACK_CAUSES, cause); + } else { + LOGP(DOML, LOGL_DEBUG, "Sending FOM ACK.\n"); + foh->msg_type++; /* ack */ + } + + prepend_oml_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0 || rc != msg->len) { + LOGP(DTEMP, LOGL_ERROR, "Error writting in unix socket\n"); + close(fd_unix); + msgb_free(msg); + return -1; + } + + return rc; +} + +static void update_transmiter_power(struct gsm_bts_trx *trx) +{ + struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); + + if (fl1h->hLayer1) + l1if_set_txpower(fl1h, sysmobts_get_power_trx(trx)); +} + +static int take_reduce_power(struct msgb *msg) +{ + int recv_reduce_power; + struct tlv_parsed tlv_out; + struct gsm_bts_trx *trx = bts->c0; + int rc, abis_oml_hdr_len; + + abis_oml_hdr_len = sizeof(struct abis_om_hdr); + abis_oml_hdr_len += sizeof(struct abis_om_fom_hdr); + abis_oml_hdr_len += sizeof(osmobts_magic) + 1; + + rc = oml_tlv_parse(&tlv_out, msg->data + abis_oml_hdr_len, + msg->len - abis_oml_hdr_len); + + if (rc < 0) { + msgb_free(msg); + return -1; + } + + if (TLVP_PRESENT(&tlv_out, NM_ATT_SBTS_REDUCEPOWER)) + recv_reduce_power = *TLVP_VAL(&tlv_out, + NM_ATT_SBTS_REDUCEPOWER); + else + return -1; + + trx->power_reduce = recv_reduce_power; + + update_transmiter_power(trx); + + return 0; +} + static int read_sock(struct osmo_fd *fd, unsigned int what) { struct msgb *msg; struct gsm_abis_mo *mo; + struct abis_om_fom_hdr *fom; int rc; msg = oml_msgb_alloc(); @@ -323,9 +421,32 @@ static int read_sock(struct osmo_fd *fd, unsigned int what) mo = &bts->mo; msg->trx = mo->bts->c0; + fom = (struct abis_om_fom_hdr *) msg->l3h; - return abis_oml_sendmsg(msg); + switch (fom->msg_type) { + case NM_MT_SET_RADIO_ATTR: + rc = take_reduce_power(msg); + if (rc < 0) { + rc = send_oml_fom_ack_nack(fd->fd, msg, + NM_NACK_INCORR_STRUCT, 1); + } else { + rc = send_oml_fom_ack_nack(fd->fd, msg, 0, 1); + } + msgb_free(msg); + break; + case NM_MT_FAILURE_EVENT_REP: + rc = abis_oml_sendmsg(msg); + break; + default: + LOGP(DL1C, LOGL_ERROR, "Unknown Fom message type %d\n", + fom->msg_type); + goto err; + } + if (rc < 0) + goto err; + + return rc; err: msgb_free(msg); return -1; diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c index 99e95d5..bb9bcac 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c @@ -82,6 +82,7 @@ static struct vty_app_info vty_info = { #ifdef BUILD_SBTS2050 static int trx_nr = -1; static int state_connection; +static int status_change_power_red; static struct osmo_timer_list connect_timer; static void socket_connect_cb(void *data) @@ -138,17 +139,18 @@ static void check_uctemp_timer_cb(void *data) { int temp_pa = 0, temp_board = 0; struct uc *ucontrol0 = data; + int pa_warning, board_warning; sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board); confinfo.temp_pa_cur = temp_pa; confinfo.temp_board_cur = temp_board; - check_temperature(ucontrol0, - confinfo.temp_min_pa_warn_limit, - confinfo.temp_max_pa_warn_limit, - temp_pa, SBTS2050_TEMP_PA, - SBTS2050_WARN_ALERT); + pa_warning = check_temperature(ucontrol0, + confinfo.temp_min_pa_warn_limit, + confinfo.temp_max_pa_warn_limit, + temp_pa, SBTS2050_TEMP_PA, + SBTS2050_WARN_ALERT); check_temperature(ucontrol0, confinfo.temp_min_pa_severe_limit, @@ -156,11 +158,11 @@ static void check_uctemp_timer_cb(void *data) temp_pa, SBTS2050_TEMP_PA, SBTS2050_SEVERE_ALERT); - check_temperature(ucontrol0, - confinfo.temp_min_board_warn_limit, - confinfo.temp_max_board_warn_limit, - temp_board, SBTS2050_TEMP_BOARD, - SBTS2050_WARN_ALERT); + board_warning = check_temperature(ucontrol0, + confinfo.temp_min_board_warn_limit, + confinfo.temp_max_board_warn_limit, + temp_board, SBTS2050_TEMP_BOARD, + SBTS2050_WARN_ALERT); check_temperature(ucontrol0, confinfo.temp_min_board_severe_limit, @@ -168,6 +170,16 @@ static void check_uctemp_timer_cb(void *data) temp_board, SBTS2050_TEMP_BOARD, SBTS2050_SEVERE_ALERT); + if ((pa_warning || board_warning) && + status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER) { + status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER; + send_omlreduce(fd_unix, confinfo.reduce_max_power, trx_nr); + } else if (!pa_warning && !board_warning && + status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) { + status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER; + send_omlreduce(fd_unix, 0, trx_nr); + } + osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0); } #endif diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h index 5e0d4a7..cf549fe 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.h @@ -15,8 +15,17 @@ enum { SYSMO_MGR_CONNECTED, }; +enum { + SBTS2050_DISABLE_CHANGE_POWER = 0, + SBTS2050_ENABLE_CHANGE_POWER, +}; + #define SOCKET_PATH "/var/run/bts_oml" +enum { + NM_ATT_SBTS_REDUCEPOWER = 0x1b, +}; + struct sbts2050_config_info; enum mgr_vty_node { diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.c b/src/osmo-bts-sysmo/misc/sysmobts_misc.c index fbbd6ee..4023b01 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.c @@ -58,6 +58,23 @@ #define OM_HEADROOM_SIZE 128 #ifdef BUILD_SBTS2050 + +static int check_omlreduce_nach_ack(struct msgb *msg) +{ + struct abis_om_fom_hdr *foh = msgb_l3(msg); + + if (foh->msg_type == NM_MT_SET_RADIO_ATTR + 2) { /* NACK */ + LOGP(DTEMP, LOGL_ERROR, "Reduce Power: Received a BTS NACK\n"); + return -1; + } else if (foh->msg_type != NM_MT_SET_RADIO_ATTR + 1) { /* ACK */ + LOGP(DTEMP, LOGL_ERROR, "Unknown message type %d\n", + foh->msg_type); + return -1; + } + + return 0; +} + static void add_sw_descr(struct msgb *msg) { char file_version[255]; @@ -116,6 +133,58 @@ static void add_oml_hdr_msg(struct msgb *msg, uint8_t msg_type, omh->length = msgb_l3len(msg); } +int send_omlreduce(int fd_unix, int reduce_power, int trx_nr) +{ + int rc; + struct msgb *msg; + + msg = msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); + if (msg == NULL) { + LOGP(DTEMP, LOGL_ERROR, "Error creating oml msg\n"); + return -1; + } + + add_oml_hdr_msg(msg, NM_MT_SET_RADIO_ATTR, 0, 0, trx_nr, 0, 1); + + msgb_tv_put(msg, NM_ATT_SBTS_REDUCEPOWER, reduce_power); + + prepend_oml_ipa_header(msg); + + rc = send(fd_unix, msg->data, msg->len, 0); + if (rc < 0 || rc != msg->len) { + LOGP(DTEMP, LOGL_ERROR, "Error writting to unix socket\n"); + goto err; + } + + msgb_reset(msg); + rc = recv(fd_unix, msg->tail, msg->data_len, 0); + if (rc <= 0) { + LOGP(DTEMP, LOGL_ERROR, "Error reading from unix socket\n"); + goto err; + } + msgb_put(msg, rc); + + if (check_oml_msg(msg) < 0) { + close(fd_unix); + msgb_free(msg); + return -1; + } + + if (check_omlreduce_nach_ack(msg) < 0) { + close(fd_unix); + msgb_free(msg); + return -1; + } + + msgb_free(msg); + return SYSMO_MGR_CONNECTED; + +err: + close(fd_unix); + msgb_free(msg); + return SYSMO_MGR_DISCONNECTED; +} + int send_omlfailure(int fd_unix, enum sbts2050_alert_lvl alert, enum sbts2050_temp_sensor sensor, struct sbts2050_config_info *add_info, int trx_nr) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_misc.h b/src/osmo-bts-sysmo/misc/sysmobts_misc.h index c22a54b..158e7a2 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_misc.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_misc.h @@ -75,6 +75,8 @@ int send_omlfailure(int fd_unix, enum sbts2050_alert_lvl alert, enum sbts2050_temp_sensor sensor, struct sbts2050_config_info *add_info, int trx_nr); +int send_omlreduce(int fd_unix, int reduce_power, int trx_nr); + int sysmobts_update_hours(int no_epprom_write); enum sysmobts_firmware_type { -- 1.7.10.4 From holger at freyther.de Fri Apr 25 10:57:26 2014 From: holger at freyther.de (Holger Freyther) Date: Fri, 25 Apr 2014 12:57:26 +0200 Subject: [PATCH 1/5] sms: Kill the sms->sender and use addr/ton/npi throughout the code Message-ID: <1398423450-23319-1-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther This is an incompatible database schema change. Store the type of the address in the database for both the sender and the receiver. Currently it is possible to use SMPP to store a SMS and the NPI and TON will be lost on the delivery of the SMS. The schema is changed to make the delivery always use the right NPI/TON. This patch is not ready for the master branch as there is no upgrade path for the HLR yet. --- openbsc/include/openbsc/gsm_data.h | 1 - openbsc/src/libmsc/db.c | 62 +++++++++++++++++++++++--------------- openbsc/src/libmsc/gsm_04_11.c | 9 ++---- openbsc/src/libmsc/smpp_openbsc.c | 5 ++- 4 files changed, 42 insertions(+), 35 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 8f24d4f..4338cd6 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -304,7 +304,6 @@ struct gsm_sms_addr { struct gsm_sms { unsigned long long id; - struct gsm_subscriber *sender; struct gsm_subscriber *receiver; struct gsm_sms_addr src, dst; enum gsm_sms_source_id source; diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index bfa4e75..df26b04 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -95,7 +95,6 @@ static char *create_stmts[] = { "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "sent TIMESTAMP, " - "sender_id INTEGER NOT NULL, " "receiver_id INTEGER NOT NULL, " "deliver_attempts INTEGER NOT NULL DEFAULT 0, " /* data directly copied/derived from SMS */ @@ -105,7 +104,12 @@ static char *create_stmts[] = { "protocol_id INTEGER NOT NULL, " "data_coding_scheme INTEGER NOT NULL, " "ud_hdr_ind INTEGER NOT NULL, " - "dest_addr TEXT, " + "src_addr TEXT NOT NULL, " + "src_ton INTEGER NOT NULL, " + "src_npi INTEGER NOT NULL, " + "dest_addr TEXT NOT NULL, " + "dest_ton INTEGER NOT NULL, " + "dest_npi INTEGER NOT NULL, " "user_data BLOB, " /* TP-UD */ /* additional data, interpreted from SMS */ "header BLOB, " /* UD Header */ @@ -1214,7 +1218,7 @@ int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char imei[GSM_IM int db_sms_store(struct gsm_sms *sms) { dbi_result result; - char *q_text, *q_daddr; + char *q_text, *q_daddr, *q_saddr; unsigned char *q_udata; char *validity_timestamp = "2222-2-2"; @@ -1222,25 +1226,35 @@ int db_sms_store(struct gsm_sms *sms) dbi_conn_quote_string_copy(conn, (char *)sms->text, &q_text); dbi_conn_quote_string_copy(conn, (char *)sms->dst.addr, &q_daddr); + dbi_conn_quote_string_copy(conn, (char *)sms->src.addr, &q_saddr); dbi_conn_quote_binary_copy(conn, sms->user_data, sms->user_data_len, &q_udata); + /* FIXME: correct validity period */ result = dbi_conn_queryf(conn, "INSERT INTO SMS " - "(created, sender_id, receiver_id, valid_until, " + "(created, receiver_id, valid_until, " "reply_path_req, status_rep_req, protocol_id, " - "data_coding_scheme, ud_hdr_ind, dest_addr, " - "user_data, text) VALUES " - "(datetime('now'), %llu, %llu, %u, " - "%u, %u, %u, %u, %u, %s, %s, %s)", - sms->sender->id, + "data_coding_scheme, ud_hdr_ind, " + "user_data, text, " + "dest_addr, dest_ton, dest_npi, " + "src_addr, src_ton, src_npi) VALUES " + "(datetime('now'), %llu, %u, " + "%u, %u, %u, " + "%u, %u, " + "%s, %s, " + "%s, %u, %u, " + "%s, %u, %u)", sms->receiver ? sms->receiver->id : 0, validity_timestamp, sms->reply_path_req, sms->status_rep_req, sms->protocol_id, sms->data_coding_scheme, sms->ud_hdr_ind, - q_daddr, q_udata, q_text); + q_udata, q_text, + q_daddr, sms->dst.ton, sms->dst.npi, + q_saddr, sms->src.ton, sms->src.npi); free(q_text); - free(q_daddr); free(q_udata); + free(q_daddr); + free(q_saddr); if (!result) return -EIO; @@ -1252,8 +1266,8 @@ int db_sms_store(struct gsm_sms *sms) static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result result) { struct gsm_sms *sms = sms_alloc(); - long long unsigned int sender_id, receiver_id; - const char *text, *daddr; + long long unsigned int receiver_id; + const char *text, *daddr, *saddr; const unsigned char *user_data; if (!sms) @@ -1261,18 +1275,6 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul sms->id = dbi_result_get_ulonglong(result, "id"); - sender_id = dbi_result_get_ulonglong(result, "sender_id"); - sms->sender = subscr_get_by_id(net, sender_id); - if (!sms->sender) { - LOGP(DLSMS, LOGL_ERROR, - "Failed to find sender(%llu) for id(%llu)\n", - sender_id, sms->id); - sms_free(sms); - return NULL; - } - - strncpy(sms->src.addr, sms->sender->extension, sizeof(sms->src.addr)-1); - receiver_id = dbi_result_get_ulonglong(result, "receiver_id"); sms->receiver = subscr_get_by_id(net, receiver_id); if (!sms->receiver) { @@ -1293,12 +1295,22 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul "data_coding_scheme"); /* sms->msg_ref is temporary and not stored in DB */ + sms->dst.npi = dbi_result_get_uint(result, "dest_npi"); + sms->dst.ton = dbi_result_get_uint(result, "dest_ton"); daddr = dbi_result_get_string(result, "dest_addr"); if (daddr) { strncpy(sms->dst.addr, daddr, sizeof(sms->dst.addr)); sms->dst.addr[sizeof(sms->dst.addr)-1] = '\0'; } + sms->src.npi = dbi_result_get_uint(result, "src_npi"); + sms->src.ton = dbi_result_get_uint(result, "src_ton"); + saddr = dbi_result_get_string(result, "src_addr"); + if (saddr) { + strncpy(sms->src.addr, saddr, sizeof(sms->src.addr)); + sms->src.addr[sizeof(sms->src.addr)-1] = '\0'; + } + sms->user_data_len = dbi_result_get_field_length(result, "user_data"); user_data = dbi_result_get_binary(result, "user_data"); if (sms->user_data_len > sizeof(sms->user_data)) diff --git a/openbsc/src/libmsc/gsm_04_11.c b/openbsc/src/libmsc/gsm_04_11.c index 5f10759..b2100d8 100644 --- a/openbsc/src/libmsc/gsm_04_11.c +++ b/openbsc/src/libmsc/gsm_04_11.c @@ -73,8 +73,6 @@ struct gsm_sms *sms_alloc(void) void sms_free(struct gsm_sms *sms) { /* drop references to subscriber structure */ - if (sms->sender) - subscr_put(sms->sender); if (sms->receiver) subscr_put(sms->receiver); #ifdef BUILD_SMPP @@ -97,8 +95,7 @@ struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, sms->receiver = subscr_get(receiver); strncpy(sms->text, text, sizeof(sms->text)-1); - sms->sender = subscr_get(sender); - strncpy(sms->src.addr, sms->sender->extension, sizeof(sms->src.addr)-1); + strncpy(sms->src.addr, sender->extension, sizeof(sms->src.addr)-1); sms->reply_path_req = 0; sms->status_rep_req = 0; sms->ud_hdr_ind = 0; @@ -378,12 +375,12 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m } } - gsms->sender = subscr_get(conn->subscr); + strncpy(gsms->src.addr, conn->subscr->extension, sizeof(gsms->src.addr)-1); LOGP(DLSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, " "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, " "UserDataLength: 0x%02x, UserData: \"%s\"\n", - subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref, + subscr_name(conn->subscr), sms_mti, sms_vpf, gsms->msg_ref, gsms->protocol_id, gsms->data_coding_scheme, gsms->dst.addr, gsms->user_data_len, sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text : diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c index ab558ce..ec541c2 100644 --- a/openbsc/src/libmsc/smpp_openbsc.c +++ b/openbsc/src/libmsc/smpp_openbsc.c @@ -133,7 +133,6 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net, strncpy(sms->dst.addr, dest->extension, sizeof(sms->dst.addr)-1); /* fill in the source address */ - sms->sender = subscr_get_by_id(net, 1); sms->src.ton = submit->source_addr_ton; sms->src.npi = submit->source_addr_npi; strncpy(sms->src.addr, (char *)submit->source_addr, sizeof(sms->src.addr)-1); @@ -475,13 +474,13 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms, deliver.source_addr_npi = NPI_Land_Mobile_E212; snprintf((char *)deliver.source_addr, sizeof(deliver.source_addr), "%s", - sms->sender->imsi); + conn->subscr->imsi); } else { deliver.source_addr_ton = TON_Network_Specific; deliver.source_addr_npi = NPI_ISDN_E163_E164; snprintf((char *)deliver.source_addr, sizeof(deliver.source_addr), "%s", - sms->sender->extension); + conn->subscr->extension); } deliver.dest_addr_ton = sms->dst.ton; -- 1.9.1 From holger at freyther.de Fri Apr 25 10:57:27 2014 From: holger at freyther.de (Holger Freyther) Date: Fri, 25 Apr 2014 12:57:27 +0200 Subject: [PATCH 2/5] db: Add testcase for storing/loading/comparing a sms In-Reply-To: <1398423450-23319-1-git-send-email-holger@freyther.de> References: <1398423450-23319-1-git-send-email-holger@freyther.de> Message-ID: <1398423450-23319-2-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther Use the already created subscriber, create a sms and read it back from the subscriber. --- openbsc/tests/db/db_test.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index e117b79..ee2fee7 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -59,6 +60,64 @@ static struct gsm_network dummy_net; printf("Extensions do not match in %s:%d '%s' '%s'\n", \ __FUNCTION__, __LINE__, original->extension, copy->extension); \ +/* + * Create/Store a SMS and then try to load it. + */ +static void test_sms(void) +{ + int rc; + struct gsm_sms *sms; + struct gsm_subscriber *subscr; + subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, "9993245423445"); + OSMO_ASSERT(subscr); + subscr->net = &dummy_net; + + sms = sms_alloc(); + sms->receiver = subscr_get(subscr); + + sms->src.ton = 0x23; + sms->src.npi = 0x24; + memcpy(sms->src.addr, "1234", strlen("1234") + 1); + + sms->dst.ton = 0x32; + sms->dst.npi = 0x42; + memcpy(sms->dst.addr, subscr->extension, sizeof(subscr->extension)); + + memcpy(sms->text, "Text123", strlen("Text123") + 1); + memcpy(sms->user_data, "UserData123", strlen("UserData123") + 1); + sms->user_data_len = strlen("UserData123"); + + /* random values */ + sms->reply_path_req = 1; + sms->status_rep_req = 2; + sms->ud_hdr_ind = 3; + sms->protocol_id = 4; + sms->data_coding_scheme = 5; + + rc = db_sms_store(sms); + sms_free(sms); + OSMO_ASSERT(rc == 0); + + /* now query */ + sms = db_sms_get_unsent_for_subscr(subscr); + OSMO_ASSERT(sms); + OSMO_ASSERT(sms->receiver == subscr); + OSMO_ASSERT(sms->reply_path_req == 1); + OSMO_ASSERT(sms->status_rep_req == 2); + OSMO_ASSERT(sms->ud_hdr_ind == 3); + OSMO_ASSERT(sms->protocol_id == 4); + OSMO_ASSERT(sms->data_coding_scheme == 5); + OSMO_ASSERT(sms->src.ton == 0x23); + OSMO_ASSERT(sms->src.npi == 0x24); + OSMO_ASSERT(sms->dst.ton == 0x32); + OSMO_ASSERT(sms->dst.npi == 0x42); + OSMO_ASSERT(strcmp((char *) sms->text, "Text123") == 0); + OSMO_ASSERT(sms->user_data_len == strlen("UserData123")); + OSMO_ASSERT(strcmp((char *) sms->user_data, "UserData123") == 0); + + subscr_put(subscr); +} + int main() { char scratch_str[256]; @@ -142,6 +201,8 @@ int main() SUBSCR_PUT(alice_db); SUBSCR_PUT(alice); + test_sms(); + db_fini(); printf("Done\n"); -- 1.9.1 From holger at freyther.de Fri Apr 25 10:57:28 2014 From: holger at freyther.de (Holger Freyther) Date: Fri, 25 Apr 2014 12:57:28 +0200 Subject: [PATCH 3/5] sms: Do not store received id in the SMS database. In-Reply-To: <1398423450-23319-1-git-send-email-holger@freyther.de> References: <1398423450-23319-1-git-send-email-holger@freyther.de> Message-ID: <1398423450-23319-3-git-send-email-holger@freyther.de> From: Alexander Chemeris That was a bad idea from the very beginning. A visible result of this is a wrong SMS routing when you change subscriber extensions, while having queued SMS. It's also a very wrong thing from the code layering perspective. I think the next logical step should be to remove "receiver" pointer from the gsm_sms structure into a structure, special for the internal SMS queue. --- openbsc/src/libmsc/db.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index df26b04..88bd9ad 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -95,7 +95,6 @@ static char *create_stmts[] = { "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "sent TIMESTAMP, " - "receiver_id INTEGER NOT NULL, " "deliver_attempts INTEGER NOT NULL DEFAULT 0, " /* data directly copied/derived from SMS */ "valid_until TIMESTAMP, " @@ -1233,19 +1232,19 @@ int db_sms_store(struct gsm_sms *sms) /* FIXME: correct validity period */ result = dbi_conn_queryf(conn, "INSERT INTO SMS " - "(created, receiver_id, valid_until, " + "(created, valid_until, " "reply_path_req, status_rep_req, protocol_id, " "data_coding_scheme, ud_hdr_ind, " "user_data, text, " "dest_addr, dest_ton, dest_npi, " "src_addr, src_ton, src_npi) VALUES " - "(datetime('now'), %llu, %u, " + "(datetime('now'), %u, " "%u, %u, %u, " "%u, %u, " "%s, %s, " "%s, %u, %u, " "%s, %u, %u)", - sms->receiver ? sms->receiver->id : 0, validity_timestamp, + validity_timestamp, sms->reply_path_req, sms->status_rep_req, sms->protocol_id, sms->data_coding_scheme, sms->ud_hdr_ind, q_udata, q_text, @@ -1266,7 +1265,6 @@ int db_sms_store(struct gsm_sms *sms) static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result result) { struct gsm_sms *sms = sms_alloc(); - long long unsigned int receiver_id; const char *text, *daddr, *saddr; const unsigned char *user_data; @@ -1275,16 +1273,6 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul sms->id = dbi_result_get_ulonglong(result, "id"); - receiver_id = dbi_result_get_ulonglong(result, "receiver_id"); - sms->receiver = subscr_get_by_id(net, receiver_id); - if (!sms->receiver) { - LOGP(DLSMS, LOGL_ERROR, - "Failed to find receiver(%llu) for id(%llu)\n", - receiver_id, sms->id); - sms_free(sms); - return NULL; - } - /* FIXME: validity */ /* FIXME: those should all be get_uchar, but sqlite3 is braindead */ sms->reply_path_req = dbi_result_get_uint(result, "reply_path_req"); @@ -1302,6 +1290,7 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul strncpy(sms->dst.addr, daddr, sizeof(sms->dst.addr)); sms->dst.addr[sizeof(sms->dst.addr)-1] = '\0'; } + sms->receiver = subscr_get_by_extension(net, sms->dst.addr); sms->src.npi = dbi_result_get_uint(result, "src_npi"); sms->src.ton = dbi_result_get_uint(result, "src_ton"); @@ -1356,7 +1345,7 @@ struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long mi result = dbi_conn_queryf(conn, "SELECT SMS.* " "FROM SMS JOIN Subscriber ON " - "SMS.receiver_id = Subscriber.id " + "SMS.dest_addr = Subscriber.extension " "WHERE SMS.id >= %llu AND SMS.sent IS NULL " "AND Subscriber.lac > 0 " "ORDER BY SMS.id LIMIT 1", @@ -1386,10 +1375,10 @@ struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, result = dbi_conn_queryf(conn, "SELECT SMS.* " "FROM SMS JOIN Subscriber ON " - "SMS.receiver_id = Subscriber.id " - "WHERE SMS.receiver_id >= %llu AND SMS.sent IS NULL " + "SMS.dest_addr = Subscriber.extension " + "WHERE Subscriber.id >= %llu AND SMS.sent IS NULL " "AND Subscriber.lac > 0 AND SMS.deliver_attempts < %u " - "ORDER BY SMS.receiver_id, SMS.id LIMIT 1", + "ORDER BY Subscriber.id, SMS.id LIMIT 1", min_subscr_id, failed); if (!result) return NULL; @@ -1415,8 +1404,8 @@ struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr) result = dbi_conn_queryf(conn, "SELECT SMS.* " "FROM SMS JOIN Subscriber ON " - "SMS.receiver_id = Subscriber.id " - "WHERE SMS.receiver_id = %llu AND SMS.sent IS NULL " + "SMS.dest_addr = Subscriber.extension " + "WHERE Subscriber.id = %llu AND SMS.sent IS NULL " "AND Subscriber.lac > 0 " "ORDER BY SMS.id LIMIT 1", subscr->id); -- 1.9.1 From holger at freyther.de Fri Apr 25 10:57:29 2014 From: holger at freyther.de (Holger Freyther) Date: Fri, 25 Apr 2014 12:57:29 +0200 Subject: [PATCH 4/5] sms: Add code to migrate the database to the new schema In-Reply-To: <1398423450-23319-1-git-send-email-holger@freyther.de> References: <1398423450-23319-1-git-send-email-holger@freyther.de> Message-ID: <1398423450-23319-4-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther This is mostly based on Alexander's migration code. The code adds transaction handling and some sanity checks and cleanups to the code. We made the decision to fork the sms_from_result method and freeze it to that version. This way sms_from_result can move forward without having to deal with legacy. --- openbsc/src/libbsc/gsm_subscriber_base.c | 6 + openbsc/src/libmsc/db.c | 209 ++++++++++++++++++++++++++++--- 2 files changed, 199 insertions(+), 16 deletions(-) diff --git a/openbsc/src/libbsc/gsm_subscriber_base.c b/openbsc/src/libbsc/gsm_subscriber_base.c index 5755687..5e00443 100644 --- a/openbsc/src/libbsc/gsm_subscriber_base.c +++ b/openbsc/src/libbsc/gsm_subscriber_base.c @@ -72,6 +72,12 @@ static void subscr_free(struct gsm_subscriber *subscr) talloc_free(subscr); } +void subscr_direct_free(struct gsm_subscriber *subscr) +{ + OSMO_ASSERT(subscr->use_count == 1); + subscr_free(subscr); +} + struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr) { subscr->use_count++; diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 88bd9ad..7746e44 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -38,23 +38,42 @@ #include #include +/* Semi-Private-Interface (SPI) for the subscriber code */ +void subscr_direct_free(struct gsm_subscriber *subscr); + static char *db_basename = NULL; static char *db_dirname = NULL; static dbi_conn conn; -#define SCHEMA_REVISION "3" +#define SCHEMA_REVISION "4" + +enum { + SCHEMA_META, + INSERT_META, + SCHEMA_SUBSCRIBER, + SCHEMA_AUTH, + SCHEMA_EQUIPMENT, + SCHEMA_EQUIPMENT_WATCH, + SCHEMA_SMS, + SCHEMA_VLR, + SCHEMA_APDU, + SCHEMA_COUNTERS, + SCHEMA_RATE, + SCHEMA_AUTHKEY, + SCHEMA_AUTHLAST, +}; -static char *create_stmts[] = { - "CREATE TABLE IF NOT EXISTS Meta (" +static const char *create_stmts[] = { + [SCHEMA_META] = "CREATE TABLE IF NOT EXISTS Meta (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "key TEXT UNIQUE NOT NULL, " "value TEXT NOT NULL" ")", - "INSERT OR IGNORE INTO Meta " + [INSERT_META] = "INSERT OR IGNORE INTO Meta " "(key, value) " "VALUES " "('revision', " SCHEMA_REVISION ")", - "CREATE TABLE IF NOT EXISTS Subscriber (" + [SCHEMA_SUBSCRIBER] = "CREATE TABLE IF NOT EXISTS Subscriber (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "updated TIMESTAMP NOT NULL, " @@ -66,13 +85,13 @@ static char *create_stmts[] = { "lac INTEGER NOT NULL DEFAULT 0, " "expire_lu TIMESTAMP DEFAULT NULL" ")", - "CREATE TABLE IF NOT EXISTS AuthToken (" + [SCHEMA_AUTH] = "CREATE TABLE IF NOT EXISTS AuthToken (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "subscriber_id INTEGER UNIQUE NOT NULL, " "created TIMESTAMP NOT NULL, " "token TEXT UNIQUE NOT NULL" ")", - "CREATE TABLE IF NOT EXISTS Equipment (" + [SCHEMA_EQUIPMENT] = "CREATE TABLE IF NOT EXISTS Equipment (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "updated TIMESTAMP NOT NULL, " @@ -82,7 +101,7 @@ static char *create_stmts[] = { "classmark3 BLOB, " "imei NUMERIC UNIQUE NOT NULL" ")", - "CREATE TABLE IF NOT EXISTS EquipmentWatch (" + [SCHEMA_EQUIPMENT_WATCH] = "CREATE TABLE IF NOT EXISTS EquipmentWatch (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "updated TIMESTAMP NOT NULL, " @@ -90,7 +109,7 @@ static char *create_stmts[] = { "equipment_id NUMERIC NOT NULL, " "UNIQUE (subscriber_id, equipment_id) " ")", - "CREATE TABLE IF NOT EXISTS SMS (" + [SCHEMA_SMS] = "CREATE TABLE IF NOT EXISTS SMS (" /* metadata, not part of sms */ "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " @@ -114,39 +133,39 @@ static char *create_stmts[] = { "header BLOB, " /* UD Header */ "text TEXT " /* decoded UD after UDH */ ")", - "CREATE TABLE IF NOT EXISTS VLR (" + [SCHEMA_VLR] = "CREATE TABLE IF NOT EXISTS VLR (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "updated TIMESTAMP NOT NULL, " "subscriber_id NUMERIC UNIQUE NOT NULL, " "last_bts NUMERIC NOT NULL " ")", - "CREATE TABLE IF NOT EXISTS ApduBlobs (" + [SCHEMA_APDU] = "CREATE TABLE IF NOT EXISTS ApduBlobs (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "created TIMESTAMP NOT NULL, " "apdu_id_flags INTEGER NOT NULL, " "subscriber_id INTEGER NOT NULL, " "apdu BLOB " ")", - "CREATE TABLE IF NOT EXISTS Counters (" + [SCHEMA_COUNTERS] = "CREATE TABLE IF NOT EXISTS Counters (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "timestamp TIMESTAMP NOT NULL, " "value INTEGER NOT NULL, " "name TEXT NOT NULL " ")", - "CREATE TABLE IF NOT EXISTS RateCounters (" + [SCHEMA_RATE] = "CREATE TABLE IF NOT EXISTS RateCounters (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "timestamp TIMESTAMP NOT NULL, " "value INTEGER NOT NULL, " "name TEXT NOT NULL, " "idx INTEGER NOT NULL " ")", - "CREATE TABLE IF NOT EXISTS AuthKeys (" + [SCHEMA_AUTHKEY] = "CREATE TABLE IF NOT EXISTS AuthKeys (" "subscriber_id INTEGER PRIMARY KEY, " "algorithm_id INTEGER NOT NULL, " "a3a8_ki BLOB " ")", - "CREATE TABLE IF NOT EXISTS AuthLastTuples (" + [SCHEMA_AUTHLAST] = "CREATE TABLE IF NOT EXISTS AuthLastTuples (" "subscriber_id INTEGER PRIMARY KEY, " "issued TIMESTAMP NOT NULL, " "use_count INTEGER NOT NULL DEFAULT 0, " @@ -185,12 +204,164 @@ static int update_db_revision_2(void) "WHERE key = 'revision'"); if (!result) { LOGP(DDB, LOGL_ERROR, - "Failed set new revision (upgrade vom rev 2).\n"); + "Failed to update DB schema revision (upgrade from rev 2).\n"); + return -EINVAL; + } + dbi_result_free(result); + + return 0; +} + +/** + * Copied from the normal sms_from_result_v3 to avoid having + * to make sure that the real routine will remain backward + * compatible. + */ +static struct gsm_sms *sms_from_result_v3(dbi_result result) +{ + struct gsm_sms *sms = sms_alloc(); + long long unsigned int sender_id; + struct gsm_subscriber *sender; + const char *text, *daddr; + const unsigned char *user_data; + char buf[32]; + + if (!sms) + return NULL; + + sms->id = dbi_result_get_ulonglong(result, "id"); + + sender_id = dbi_result_get_ulonglong(result, "sender_id"); + snprintf(buf, sizeof(buf), "%llu", sender_id); + sender = db_get_subscriber(GSM_SUBSCRIBER_ID, buf); + OSMO_ASSERT(sender); + strncpy(sms->src.addr, sender->extension, sizeof(sms->src.addr)-1); + subscr_direct_free(sender); + sender = NULL; + + sms->reply_path_req = dbi_result_get_uint(result, "reply_path_req"); + sms->status_rep_req = dbi_result_get_uint(result, "status_rep_req"); + sms->ud_hdr_ind = dbi_result_get_uint(result, "ud_hdr_ind"); + sms->protocol_id = dbi_result_get_uint(result, "protocol_id"); + sms->data_coding_scheme = dbi_result_get_uint(result, + "data_coding_scheme"); + + daddr = dbi_result_get_string(result, "dest_addr"); + if (daddr) { + strncpy(sms->dst.addr, daddr, sizeof(sms->dst.addr)); + sms->dst.addr[sizeof(sms->dst.addr)-1] = '\0'; + } + + sms->user_data_len = dbi_result_get_field_length(result, "user_data"); + user_data = dbi_result_get_binary(result, "user_data"); + if (sms->user_data_len > sizeof(sms->user_data)) + sms->user_data_len = (uint8_t) sizeof(sms->user_data); + memcpy(sms->user_data, user_data, sms->user_data_len); + + text = dbi_result_get_string(result, "text"); + if (text) { + strncpy(sms->text, text, sizeof(sms->text)); + sms->text[sizeof(sms->text)-1] = '\0'; + } + return sms; +} + +static int update_db_revision_3(void) +{ + dbi_result result; + struct gsm_sms *sms; + + result = dbi_conn_query(conn, "BEGIN EXCLUSIVE TRANSACTION"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to begin transaction (upgrade from rev 3)\n"); return -EINVAL; } dbi_result_free(result); + /* Rename old SMS table to be able create a new one */ + result = dbi_conn_query(conn, "ALTER TABLE SMS RENAME TO SMS_3"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to rename the old SMS table (upgrade from rev 3).\n"); + goto rollback; + } + dbi_result_free(result); + + /* Create new SMS table with all the bells and whistles! */ + result = dbi_conn_query(conn, create_stmts[SCHEMA_SMS]); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to create a new SMS table (upgrade from rev 3).\n"); + goto rollback; + } + dbi_result_free(result); + + /* Cycle through old messages and convert them to the new format */ + result = dbi_conn_queryf(conn, "SELECT * FROM SMS_3"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed fetch messages from the old SMS table (upgrade from rev 3).\n"); + goto rollback; + } + while (dbi_result_next_row(result)) { + sms = sms_from_result_v3(result); + if (db_sms_store(sms) != 0) { + LOGP(DDB, LOGL_ERROR, "Failed to store message to the new SMS table(upgrade from rev 3).\n"); + sms_free(sms); + dbi_result_free(result); + goto rollback; + } + sms_free(sms); + } + dbi_result_free(result); + + /* Remove the temporary table */ + result = dbi_conn_query(conn, "DROP TABLE SMS_3"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to drop the old SMS table (upgrade from rev 3).\n"); + goto rollback; + } + dbi_result_free(result); + + /* We're done. Bump DB Meta revision to 4 */ + result = dbi_conn_query(conn, + "UPDATE Meta " + "SET value = '4' " + "WHERE key = 'revision'"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to update DB schema revision (upgrade from rev 3).\n"); + goto rollback; + } + dbi_result_free(result); + + result = dbi_conn_query(conn, "COMMIT TRANSACTION"); + if (!result) { + LOGP(DDB, LOGL_ERROR, + "Failed to commit the transaction (upgrade from rev 3)\n"); + return -EINVAL; + } + + /* Shrink DB file size by actually wiping out SMS_3 table data */ + result = dbi_conn_query(conn, "VACUUM"); + if (!result) + LOGP(DDB, LOGL_ERROR, + "VACUUM failed. Ignoring it (upgrade from rev 3).\n"); + else + dbi_result_free(result); + return 0; + +rollback: + result = dbi_conn_query(conn, "ROLLBACK TRANSACTION"); + if (!result) + LOGP(DDB, LOGL_ERROR, + "Rollback failed (upgrade from rev 3).\n"); + else + dbi_result_free(result); + return -EINVAL; } static int check_db_revision(void) @@ -218,6 +389,12 @@ static int check_db_revision(void) dbi_result_free(result); return -EINVAL; } + } else if (!strcmp(rev_s, "3")) { + if (update_db_revision_3()) { + LOGP(DDB, LOGL_FATAL, "Failed to update database from schema revision '%s'.\n", rev_s); + dbi_result_free(result); + return -EINVAL; + } } else if (!strcmp(rev_s, SCHEMA_REVISION)) { /* everything is fine */ } else { -- 1.9.1 From holger at freyther.de Fri Apr 25 10:57:30 2014 From: holger at freyther.de (Holger Freyther) Date: Fri, 25 Apr 2014 12:57:30 +0200 Subject: [PATCH 5/5] db: Add testcase for the db migration. In-Reply-To: <1398423450-23319-1-git-send-email-holger@freyther.de> References: <1398423450-23319-1-git-send-email-holger@freyther.de> Message-ID: <1398423450-23319-5-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther --- openbsc/src/libmsc/db.c | 2 ++ openbsc/tests/db/Makefile.am | 2 +- openbsc/tests/db/db_test.c | 34 ++++++++++++++++++++++++++++++++++ openbsc/tests/db/db_test.err | 2 ++ openbsc/tests/db/hlr.sqlite3 | Bin 0 -> 29696 bytes openbsc/tests/testsuite.at | 4 +++- 6 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 openbsc/tests/db/db_test.err create mode 100644 openbsc/tests/db/hlr.sqlite3 diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 7746e44..1580acd 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -271,6 +271,8 @@ static int update_db_revision_3(void) dbi_result result; struct gsm_sms *sms; + LOGP(DDB, LOGL_NOTICE, "Going to migrate from revision 3\n"); + result = dbi_conn_query(conn, "BEGIN EXCLUSIVE TRANSACTION"); if (!result) { LOGP(DDB, LOGL_ERROR, diff --git a/openbsc/tests/db/Makefile.am b/openbsc/tests/db/Makefile.am index 26ea703..647b519 100644 --- a/openbsc/tests/db/Makefile.am +++ b/openbsc/tests/db/Makefile.am @@ -2,7 +2,7 @@ AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(LIBSMPP34_CFLAGS) $(COVERAGE_CFLAGS) AM_LDFLAGS = $(COVERAGE_LDFLAGS) -EXTRA_DIST = db_test.ok +EXTRA_DIST = db_test.ok db_test.err hlr.sqlite3 noinst_PROGRAMS = db_test diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index ee2fee7..1494e77 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -118,6 +118,39 @@ static void test_sms(void) subscr_put(subscr); } +static void test_sms_migrate(void) +{ + struct gsm_subscriber *rcv_subscr; + struct gsm_sms *sms; + static const uint8_t user_data_1[] = { + 0x41, 0xf1, 0xd8, 0x05, 0x22, 0x96, 0xcd, 0x2e, + 0x90, 0xf1, 0xfd, 0x06, 0x00 }; + static const uint8_t user_data_2[] = { + 0x41, 0xf1, 0xd8, 0x05, 0x22, 0x96, 0xcd, 0x2e, + 0xd0, 0xf1, 0xfd, 0x06, 0x00 }; + + rcv_subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, "901010000001111"); + rcv_subscr->net = &dummy_net; + + sms = db_sms_get(&dummy_net, 1); + OSMO_ASSERT(sms->id == 1); + OSMO_ASSERT(sms->receiver == rcv_subscr); + OSMO_ASSERT(strcmp(sms->text, "Abc. Def. Foo") == 0); + OSMO_ASSERT(sms->user_data_len == ARRAY_SIZE(user_data_1)); + OSMO_ASSERT(memcmp(sms->user_data, user_data_1, ARRAY_SIZE(user_data_1)) == 0); + sms_free(sms); + + sms = db_sms_get(&dummy_net, 2); + OSMO_ASSERT(sms->id == 2); + OSMO_ASSERT(sms->receiver == rcv_subscr); + OSMO_ASSERT(strcmp(sms->text, "Abc. Def. Goo") == 0); + OSMO_ASSERT(sms->user_data_len == ARRAY_SIZE(user_data_2)); + OSMO_ASSERT(memcmp(sms->user_data, user_data_2, ARRAY_SIZE(user_data_2)) == 0); + sms_free(sms); + + subscr_put(rcv_subscr); +} + int main() { char scratch_str[256]; @@ -202,6 +235,7 @@ int main() SUBSCR_PUT(alice); test_sms(); + test_sms_migrate(); db_fini(); diff --git a/openbsc/tests/db/db_test.err b/openbsc/tests/db/db_test.err new file mode 100644 index 0000000..0a0f2f3 --- /dev/null +++ b/openbsc/tests/db/db_test.err @@ -0,0 +1,2 @@ +<000d> db.c:274 Going to migrate from revision 3 + \ No newline at end of file diff --git a/openbsc/tests/db/hlr.sqlite3 b/openbsc/tests/db/hlr.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..e59dcdca361bb0bdeb097662dbf3e4e3515d6e82 GIT binary patch literal 29696 zcmeHQUufLO8P{mm`zQ7~e;jA;l5-+ML#*?9?e)gZo>Q*pB%9QY|K#j-b0H5xmd3Hp z+SOXpnz)p5b`A=qv`{F04D=q_-bNnq4$tJ^r;U$C>&hjxU?jt{YF}8 zSKifn32{lXBi7o{%r~R?e&5VU`o5pm%WuwUHWAhgvn1O>j*D;zac>9$$8po}Hw1s) z)(44*cL3k0Asv>S=EnYxd!Q8Ke^Qy3 at FV<%n+&VM@)-gQfrCU~;0Uyy?1x=nJPCUQ z6OzrzgG8LQ%@BA-5J;j3H+0w}TbiXA<=i3Y7Q&x%@L?N6fFaNY2=wBigtq`B at xQnz zzTbm?kAH?g!5`y~@ck};fT_q3cpealMezVyo?qtsc|44ktE-k`YOBQL`+D#Yx@=U- zHZiT!_zNzM at F1Eewj4PY!6GVbR<%lrl2rkU&D at V z3;~9~{}qAP`CcxUizZWXF3wF(WY3RHeNr$i6Oucs3DNRDdgNW at Nt|~^&;Nm_ zepjf^lw=4n1SkUZ{-4c%3If|00^NrIoB!QsbEYvvz(auE|Hru%4n7}qkI at 4E9{(4d z#FxDCC;I*tilqhz(avpKUeyT=O42|6@={@@SP+Ucm*xrr%@Ia4RhV5U7OoYRgd0n< z^D|4ggzJS{!pur>adrXZ=L-wPw6H<8g<|2YqOh_s`{qhPSXe9y3oCPTX<A!!mg at PPVxgEswuvefXXgvc#hLjV4QNy= zYG|2OvNQl~zOXcVxfw^QfdgY&Aa`w2rrfYb$kPHKxNex*H{sNt#XQ7?D}}2wD|1C* zA}!eTG!3>&3%abdtwHWqG?PerwLvAXL26_%*Aq=$8xFH)9YHBuPe*gn4l7O8E5&lL z4lCvAmEt=W?aZdi~HG~8r<@O{!+tiX_^V`#)VD$(`Xfc z%!qXUN6`p}M$m2aeg0kkL;Ra3n)5GsrEDUaDx3)$guYRwte-rTJ=9s1Nxw?(j at 9do zrF&D(Sn^36exg4xmi+8a$5OjN(r)o+SRNEzwyctDZe+dHBrW)PlftFB#Y+ttxmt!+ zBB85~nC)u^l&_?e^^=Ep6UkUg6w$r;AW#n5#TRpqj@CH zL#K9gacz>11eyuf5(V*Me>Alyh7HXi7!4RY034i#91sGt{80`b(G&4VoNg(RJGbZZou58`fsZF1{MBLRqBlN! z5E=f_AIJXm+2fx7&a5gK;R;#H2-gf_7VY0ucCtlNKL|E;)i9jn#aXl5 zy~V?^)W87xPLCTGoL`1_I*$b$(~$8rywMiC@>vh0r3E-viP;!As(YVJq7ZE>tW+hs zQz+XuDOGH%Z4eLQu$n5t+o+n}cy^Oi^lhmk+v}1^Hk(?2?%A?kwV<#PB2Y06+fWR> zwFVIGlqJPbwelUwQq~CsG4}>1(?V61)>VL at +#I<~3o5Z}Nmf;}7X7SRfCp{17Pwd^ zGT>J`upu_;hS9{G!V$-!yPJ+hzcIH2pW^|GLdMguXuG&fATZzu5Sn6x5VEnQRWRY+ z5QE^v{}}&|El~`C?nHp`|GLxeOlyV!MS$M_v+F+vfo%+d?n8k7HZQ`DsNzHJSNCDS zG-e2NCjzew((8YeJIV1I{15Rh^b>Rn4xDZ0+b3L#|`)N2daQ zk6 at V)WH0*unFhLlTF at -38pdh22zYqFv*g$G99WICb9h5Q0s?-MOjw~B7?Ei(2(~U16Auf*>+T?-zS at trnw!dE9-ZFN^h^1T6?wRoSc_7 zG`BzE&eh|w)Y-FWchRxK5-|L|-+gOLzZ~dJV at an@C>uz+;EyX+>K?oX%-lCEn!Rg2 zHMl`mQ|~reLJ-d$jiz232;- at Ow@k{yZgA(yF_%w&(;asewR%Z6R;?K?aU!6ppWUgN z?KsdfoC9nkt?BZeW``#XoR(aCZ$QFJ5>VeW+m{BM(X)HXQNuHt_nitT;pKL!!_zVq z^Z#|{y3e#`2)GEa=YKX57y{jk0Gt2aYkQ_SLx9fzLEt6f2l(fB8-ER-gWE(eaL;6lR)&j3@)X at PdnrkCkHh?7JQdY!c`?U*?Y9$S*E9$F9+jX}h-vRPS#(fE0O&_7M zQz3n*$tp$(Tp-Z$=;3xfu1Tx#O9Q}6QPce$G+pD`5Oq9Br7wnbL^l)(Xd!@xRmsST zLMrxnA5=(mRKX-~6U83urDtgVeQDQ<^w$C;x9b^&dS9}KsQ6d+>5#o$A(;v>HK61u z$LTrt)4{0#Kmn?wF; GiTOV&I7qty literal 0 HcmV?d00001 diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index b2c5518..4465b25 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -10,7 +10,9 @@ AT_CLEANUP AT_SETUP([db]) AT_KEYWORDS([db]) cat $abs_srcdir/db/db_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/db/db_test], [], [expout], [ignore]) +cat $abs_srcdir/db/db_test.err > experr +cat $abs_srcdir/db/hlr.sqlite3 > hlr.sqlite3 +AT_CHECK([$abs_top_builddir/tests/db/db_test], [], [expout], [experr]) AT_CLEANUP AT_SETUP([channel]) -- 1.9.1 From holger at freyther.de Fri Apr 25 11:21:51 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Fri, 25 Apr 2014 13:21:51 +0200 Subject: [PATCH 1/5] sms: Kill the sms->sender and use addr/ton/npi throughout the code In-Reply-To: <1398423450-23319-1-git-send-email-holger@freyther.de> References: <1398423450-23319-1-git-send-email-holger@freyther.de> Message-ID: <20140425112151.GC22942@xiaoyu.lan> On Fri, Apr 25, 2014 at 12:57:26PM +0200, Holger Freyther wrote: > - gsms->sender = subscr_get(conn->subscr); > + strncpy(gsms->src.addr, conn->subscr->extension, sizeof(gsms->src.addr)-1); this includes the fix Ivan made. I would really appreciate if you could send bugfixes like this to the list. holger From Ivan.Kluchnikov at fairwaves.ru Fri Apr 25 11:48:18 2014 From: Ivan.Kluchnikov at fairwaves.ru (Ivan Kluchnikov) Date: Fri, 25 Apr 2014 15:48:18 +0400 Subject: [PATCH 1/5] sms: Kill the sms->sender and use addr/ton/npi throughout the code In-Reply-To: <20140425112151.GC22942@xiaoyu.lan> References: <1398423450-23319-1-git-send-email-holger@freyther.de> <20140425112151.GC22942@xiaoyu.lan> Message-ID: Hi Holger, > I would really appreciate if you > could send bugfixes like this to the list. Ok. Also I can say, that we tested this patch set on our deployments and the code is working stable. -- Regards, Ivan Kluchnikov. http://fairwaves.ru From Jason at zx2c4.com Sat Apr 26 13:08:14 2014 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Sat, 26 Apr 2014 15:08:14 +0200 Subject: Network from Scratch on Gentoo: Official Support Message-ID: Gentoo Linux now supports Network from Scratch in 5 easy steps. We're using jolly's branches for the live ebuilds. (ETA on when we can ship master?) Network from Scratch on Gentoo ============================== 1. Add these to packages.keywords (in /etc/portage): =net-wireless/openbsc-9999 ** =net-wireless/osmobts-9999 ** =net-wireless/osmotrx-9999 ** =net-libs/libosmo-abis-9999 ** 2. Make sure your portage tree is up to date, and emerge the right packages: $ sudo emerge --sync $ sudo emerge openbsc osmobts osmotrx 3. Download configuration templates: $ mkdir ~/.osmocom $ wget -O ~/.osmocom/open-bsc.cfg http://bpaste.net/raw/236987/ $ wget -O ~/.osmocom/osmo-bts.cfg http://bpaste.net/raw/237000/ 4. Edit configuration templates to work on spectrum you have a license for: $ vim ~/.osmocom/*.cfg 5. Start these babies up, in separate shells: shell1 $ osmo-nitb -c ~/.osmocom/open-bsc.cfg -l ~/.osmocom/hlr.sqlite3 -P -C --debug=DRLL:DCC:DMM:DRR:DRSL:DNM shell2 $ osmobts-trx -c ~/.osmocom/osmo-bts.cfg shell3 $ osmo-trx From Jason at zx2c4.com Sun Apr 27 11:09:03 2014 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Sun, 27 Apr 2014 13:09:03 +0200 Subject: Network from Scratch on Gentoo: Official Support In-Reply-To: References: Message-ID: FWIW, here's a simple little start-up script to get a nice looking tmux session with everything running. #!/bin/sh config_dir="$(readlink -f "$(dirname "$0")")" openbsc_config="$config_dir/open-bsc.cfg" osmobts_config="$config_dir/osmo-bts.cfg" hlr_db="$config_dir/hlr.sqlite3" window_title="GSM" tmux new-session -s "$window_title" -n close-me -d tmux new-window -n OpenBSC -t "$window_title" tmux send-keys -t OpenBSC "osmo-nitb -c '$openbsc_config' -l '$hlr_db' \ -P -C --debug=DRLL:DCC:DMM:DRR:DRSL:DNM" Enter tmux new-window -n OsmoBTS -t "$window_title" tmux send-keys "osmobts-trx -c '$osmobts_config'" Enter tmux new-window -n OsmoTRX -t "$window_title" tmux send-keys "osmo-trx" Enter tmux new-window -n BSC-Control -t "$window_title" tmux send-keys -t BSC-Control "telnet localhost 4242" enter tmux new-window -n BTS-Control -t "$window_title" tmux send-keys -t BTS-Control "telnet localhost 4241" enter tmux set-option -t "$window_title" status on tmux kill-window -t close-me tmux select-window -t OpenBSC tmux attach -t "$window_title" From Jason at zx2c4.com Tue Apr 29 00:31:10 2014 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Tue, 29 Apr 2014 02:31:10 +0200 Subject: Network from Scratch on Gentoo: Official Support In-Reply-To: References: Message-ID: http://git.zx2c4.com/OpenBSC-Bootstrap/about/ A nice repo here. From holger at freyther.de Tue Apr 29 06:54:11 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 29 Apr 2014 08:54:11 +0200 Subject: Network from Scratch on Gentoo: Official Support In-Reply-To: References: Message-ID: <20140429065411.GB3544@xiaoyu.lan> On Tue, Apr 29, 2014 at 02:31:10AM +0200, Jason A. Donenfeld wrote: > http://git.zx2c4.com/OpenBSC-Bootstrap/about/ any reason not to participate under the Osmocom umbrella? From alexander.chemeris at gmail.com Tue Apr 29 08:03:40 2014 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 29 Apr 2014 12:03:40 +0400 Subject: Network from Scratch on Gentoo: Official Support In-Reply-To: <20140429065411.GB3544@xiaoyu.lan> References: <20140429065411.GB3544@xiaoyu.lan> Message-ID: I agree with Holger. Would be great to have this nicely documented in the official Osmocom wiki and have the code in the official repo. Please excuse typos. Written with a touchscreen keyboard. -- Regards, Alexander Chemeris CEO Fairwaves, Inc. https://fairwaves.co 29 ???. 2014 ?. 10:54 ???????????? "Holger Hans Peter Freyther" < holger at freyther.de> ???????: > On Tue, Apr 29, 2014 at 02:31:10AM +0200, Jason A. Donenfeld wrote: > > http://git.zx2c4.com/OpenBSC-Bootstrap/about/ > > any reason not to participate under the Osmocom umbrella? > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From peter at stuge.se Tue Apr 29 09:15:22 2014 From: peter at stuge.se (Peter Stuge) Date: Tue, 29 Apr 2014 11:15:22 +0200 Subject: Network from Scratch on Gentoo: Official Support In-Reply-To: References: Message-ID: <20140429091522.18838.qmail@stuge.se> Jason A. Donenfeld wrote: > Gentoo Linux now supports Network from Scratch in 5 easy steps. Looks like you're off to a good start with this. > using jolly's branches for the live ebuilds. I think the ebuilds needs to use master by default, but I think it would be lovely to be able to opt for a different branch. One easy way would be a USE flag, but that's perhaps not the best way. Ideas? > (ETA on when we can ship master?) The ETA likely depends on the reason that the branch hasn't been merged. Maybe you can help with that? > 2. Make sure your portage tree is up to date, and emerge the right packages: > > $ sudo emerge --sync > $ sudo emerge openbsc osmobts osmotrx openbsc should indeed not depend on osmobts but I think osmobts should have a USE flag to make it DEPEND & RDEPEND on osmotrx Thoughts? > 3. Download configuration templates: > > $ wget -O ~/.osmocom/open-bsc.cfg http://bpaste.net/raw/236987/ > $ wget -O ~/.osmocom/osmo-bts.cfg http://bpaste.net/raw/237000/ Please add config examples in files/ and install them into /usr/share/doc/{openbsc,osmobts}-9999/examples/ or so. > $ mkdir ~/.osmocom What do you think about hooking into emerge --config for copying the installed example configuration files to the user's home? One snag is that --config is rather for system-wide configuration. > 4. Edit configuration templates to work on spectrum you have a license for: > > $ vim ~/.osmocom/*.cfg > > 5. Start these babies up, in separate shells: > > shell1 $ osmo-nitb -c ~/.osmocom/open-bsc.cfg -l ~/.osmocom/hlr.sqlite3 -P -C --debug=DRLL:DCC:DMM:DRR:DRSL:DNM > shell2 $ osmobts-trx -c ~/.osmocom/osmo-bts.cfg > shell3 $ osmo-trx I think the tmux startup file {c,sh}ould also go into files/ along with the example configs. :) Maybe things in your git repo can go to either osmocom or gentoo repos? //Peter From anayuso at sysmocom.de Mon Apr 28 11:38:47 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Mon, 28 Apr 2014 13:38:47 +0200 Subject: [openbsc PATCH 1/5] openbsc/gsm_data_shared.h: Added the attribute reduce_power in TRX Message-ID: <1398685127-19093-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Signed-off-by: Alvaro Neira Ayuso --- openbsc/include/openbsc/gsm_data_shared.h | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index ae9e7d8..a4d3c54 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -371,6 +371,7 @@ struct gsm_bts_trx { uint16_t arfcn; int nominal_power; /* in dBm */ unsigned int max_power_red; /* in actual dB */ + int power_reduce; /* in dBm */ struct { void *l1h; -- 1.7.10.4 From holger at freyther.de Tue Apr 29 07:14:07 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 29 Apr 2014 09:14:07 +0200 Subject: [openbsc PATCH 1/5] openbsc/gsm_data_shared.h: Added the attribute reduce_power in TRX In-Reply-To: <1398685127-19093-1-git-send-email-anayuso@sysmocom.de> References: <1398685127-19093-1-git-send-email-anayuso@sysmocom.de> Message-ID: <20140429071407.GE3544@xiaoyu.lan> On Mon, Apr 28, 2014 at 01:38:47PM +0200, Alvaro Neira Ayuso wrote: > From: ?lvaro Neira Ayuso > --- a/openbsc/include/openbsc/gsm_data_shared.h > +++ b/openbsc/include/openbsc/gsm_data_shared.h > @@ -371,6 +371,7 @@ struct gsm_bts_trx { > uint16_t arfcn; > int nominal_power; /* in dBm */ > unsigned int max_power_red; /* in actual dB */ > + int power_reduce; /* in dBm */ any reason to make it use int and not unsigned int? As this is a relative value the right unit is dB (take this with a grain of salt as I am just a software guy) From anayuso at sysmocom.de Tue Apr 29 08:44:53 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Tue, 29 Apr 2014 10:44:53 +0200 Subject: [openbsc PATCH 1/5] openbsc/gsm_data_shared.h: Added the attribute reduce_power in TRX In-Reply-To: <20140429071407.GE3544@xiaoyu.lan> References: <1398685127-19093-1-git-send-email-anayuso@sysmocom.de> <20140429071407.GE3544@xiaoyu.lan> Message-ID: <20140429084453.GA4914@Ph0enix> On Tue, Apr 29, 2014 at 09:14:07AM +0200, Holger Hans Peter Freyther wrote: > On Mon, Apr 28, 2014 at 01:38:47PM +0200, Alvaro Neira Ayuso wrote: > > From: ?lvaro Neira Ayuso > > > --- a/openbsc/include/openbsc/gsm_data_shared.h > > +++ b/openbsc/include/openbsc/gsm_data_shared.h > > @@ -371,6 +371,7 @@ struct gsm_bts_trx { > > uint16_t arfcn; > > int nominal_power; /* in dBm */ > > unsigned int max_power_red; /* in actual dB */ > > + int power_reduce; /* in dBm */ > > any reason to make it use int and not unsigned int? As this > is a relative value the right unit is dB (take this with a > grain of salt as I am just a software guy) No, I don't have any reason for using int. But I have seen that that it's better to use unsigned int because it's a little bit strange accept to use negative values in a one attribute that we want to use for reducing the power transmitter. I'm going to change that and send you another version. Thanks Holger From anayuso at sysmocom.de Tue Apr 29 10:18:23 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Tue, 29 Apr 2014 12:18:23 +0200 Subject: [openbsc PATCH 1/5 v2] openbsc/gsm_data_shared.h: Added the attribute reduce_power in TRX In-Reply-To: <1398685127-19093-1-git-send-email-anayuso@sysmocom.de> References: <1398685127-19093-1-git-send-email-anayuso@sysmocom.de> Message-ID: <1398766703-7718-1-git-send-email-anayuso@sysmocom.de> Signed-off-by: Alvaro Neira Ayuso --- [changes in v2] * Changed power_reduce from int to unsigned int for not accepting negative value in a relative value. openbsc/include/openbsc/gsm_data_shared.h | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 2b405a0..ec2cae2 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -371,6 +371,7 @@ struct gsm_bts_trx { uint16_t arfcn; int nominal_power; /* in dBm */ unsigned int max_power_red; /* in actual dB */ + unsigned int power_reduce; /* in dBm */ struct { void *l1h; -- 1.7.10.4 From anayuso at sysmocom.de Mon Apr 28 11:40:24 2014 From: anayuso at sysmocom.de (Alvaro Neira Ayuso) Date: Mon, 28 Apr 2014 13:40:24 +0200 Subject: [osmo-bts PATCH 2/5] osmo-bts-sysmo/utils.c: Added a function for calculate the power transmitter Message-ID: <1398685224-19161-1-git-send-email-anayuso@sysmocom.de> From: ?lvaro Neira Ayuso Signed-off-by: Alvaro Neira Ayuso --- src/osmo-bts-sysmo/oml.c | 4 ++-- src/osmo-bts-sysmo/utils.c | 11 +++++++++++ src/osmo-bts-sysmo/utils.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c index 1543f85..4ebf664 100644 --- a/src/osmo-bts-sysmo/oml.c +++ b/src/osmo-bts-sysmo/oml.c @@ -323,7 +323,7 @@ static int trx_init(struct gsm_bts_trx *trx) dev_par->u16BcchArfcn = trx->bts->c0->arfcn; dev_par->u8NbTsc = trx->bts->bsic & 7; dev_par->fRxPowerLevel = fl1h->ul_power_target; - dev_par->fTxPowerLevel = trx->nominal_power - trx->max_power_red; + dev_par->fTxPowerLevel = sysmobts_get_power_trx(trx); LOGP(DL1C, LOGL_NOTICE, "Init TRX (ARFCN %u, TSC %u, RxPower % 2f dBm, " "TxPower % 2.2f dBm\n", dev_par->u16Arfcn, dev_par->u8NbTsc, dev_par->fRxPowerLevel, dev_par->fTxPowerLevel); @@ -1544,7 +1544,7 @@ int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, /* Did we go through MphInit yet? If yes fire and forget */ if (fl1h->hLayer1) - l1if_set_txpower(fl1h, trx->nominal_power - trx->max_power_red); + l1if_set_txpower(fl1h, sysmobts_get_power_trx(trx)); } /* FIXME: we actaully need to send a ACK or NACK for the OML message */ diff --git a/src/osmo-bts-sysmo/utils.c b/src/osmo-bts-sysmo/utils.c index f576eef..af1e5d2 100644 --- a/src/osmo-bts-sysmo/utils.c +++ b/src/osmo-bts-sysmo/utils.c @@ -136,3 +136,14 @@ int sysmobts_get_nominal_power(struct gsm_bts_trx *trx) } return -1; } + +int sysmobts_get_power_trx(struct gsm_bts_trx *trx) +{ + int power_transmitter = trx->nominal_power - trx->max_power_red; + power_transmitter -= trx->power_reduce; + + if (power_transmitter < 0) + power_transmitter = 0; + + return power_transmitter; +} diff --git a/src/osmo-bts-sysmo/utils.h b/src/osmo-bts-sysmo/utils.h index ff41437..aef774c 100644 --- a/src/osmo-bts-sysmo/utils.h +++ b/src/osmo-bts-sysmo/utils.h @@ -12,4 +12,5 @@ int sysmobts_select_femto_band(struct gsm_bts_trx *trx, uint16_t arfcn); int sysmobts_get_nominal_power(struct gsm_bts_trx *trx); +int sysmobts_get_power_trx(struct gsm_bts_trx *trx); #endif -- 1.7.10.4 From Jason at zx2c4.com Mon Apr 28 19:11:03 2014 From: Jason at zx2c4.com (Jason A. Donenfeld) Date: Mon, 28 Apr 2014 21:11:03 +0200 Subject: Uninitialized Memory Sent in SMS Message-ID: Funny bug. osmo-nitb, jolly's branches for everything. Send a blank SMS. Receiver doesn't get blank message. Instead receiver gets garbage, different everytime. Presumably this is uninitialized memory until the first null. From holger at freyther.de Tue Apr 29 06:54:57 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 29 Apr 2014 08:54:57 +0200 Subject: Uninitialized Memory Sent in SMS In-Reply-To: References: Message-ID: <20140429065457.GC3544@xiaoyu.lan> On Mon, Apr 28, 2014 at 09:11:03PM +0200, Jason A. Donenfeld wrote: > Send a blank SMS. Receiver doesn't get blank message. Instead receiver > gets garbage, different everytime. Presumably this is uninitialized > memory until the first null. How did you send the SMS? From one phone to another? Through the VTY? Through SMPP? Could you please provide a pcap file from port 3003. From tom at tsou.cc Tue Apr 29 04:12:09 2014 From: tom at tsou.cc (Thomas Tsou) Date: Tue, 29 Apr 2014 00:12:09 -0400 Subject: [PATCH 1/4] core/conv: Add optimized Viterbi decoding Message-ID: <20140429041209.GA5135@phenom.hsd1.va.comcast.net> Add a separate, faster convolution decoding implementation for rates up to N=4 and constraint lengths of K=5 and K=7, which covers the most GSM code uses. The decoding algorithm exploits the symmetric structure of the Viterbi add-compare-select (ACS) operation - commonly known as the ACS butterfly. This shift-register optimization can be found in the well-known text by Dave Forney. Forney, G.D., "The Viterbi Algorithm," Proc. of the IEEE, March 1973. Implementation is non-architecture specific and improves performance on x86 as well as ARM processors. Existing API is unchanged with optimized code being called internally for supported codes. Signed-off-by: Thomas Tsou --- src/Makefile.am | 3 +- src/conv.c | 9 + src/viterbi.c | 603 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/viterbi_gen.c | 182 ++++++++++++++++ 4 files changed, 796 insertions(+), 1 deletion(-) create mode 100644 src/viterbi.c create mode 100644 src/viterbi_gen.c diff --git a/src/Makefile.am b/src/Makefile.am index e68c29a..262a4e6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,7 +13,8 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \ logging.c logging_syslog.c rate_ctr.c \ gsmtap_util.c crc16.c panic.c backtrace.c \ conv.c application.c rbtree.c strrb.c \ - loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c + loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c \ + viterbi.c viterbi_gen.c BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c diff --git a/src/conv.c b/src/conv.c index f13deef..79b3a7c 100644 --- a/src/conv.c +++ b/src/conv.c @@ -238,6 +238,11 @@ osmo_conv_encode(const struct osmo_conv_code *code, #define MAX_AE 0x00ffffff +/* Forward declaration for accerlated decoding with certain codes */ +int +osmo_conv_decode_acc(const struct osmo_conv_code *code, + const sbit_t *input, ubit_t *output); + void osmo_conv_decode_init(struct osmo_conv_decoder *decoder, const struct osmo_conv_code *code, int len, int start_state) @@ -606,6 +611,10 @@ osmo_conv_decode(const struct osmo_conv_code *code, struct osmo_conv_decoder decoder; int rv, l; + /* Use accelerated implementation for supported codes */ + if ((code->N <= 4) && ((code->K == 5) || (code->K == 7))) + return osmo_conv_decode_acc(code, input, output); + osmo_conv_decode_init(&decoder, code, 0, 0); if (code->term == CONV_TERM_TAIL_BITING) { diff --git a/src/viterbi.c b/src/viterbi.c new file mode 100644 index 0000000..db8d5c8 --- /dev/null +++ b/src/viterbi.c @@ -0,0 +1,603 @@ +/* + * Viterbi decoder + * Copyright (C) 2013, 2014 Thomas Tsou + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +/* Forward Metric Units */ +void gen_metrics_k5_n2(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm); +void gen_metrics_k5_n3(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm); +void gen_metrics_k5_n4(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm); +void gen_metrics_k7_n2(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm); +void gen_metrics_k7_n3(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm); +void gen_metrics_k7_n4(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm); +/* Trellis State + * state - Internal lshift register value + * prev - Register values of previous 0 and 1 states + */ +struct vstate { + unsigned state; + unsigned prev[2]; +}; + +/* Trellis Object + * num_states - Number of states in the trellis + * sums - Accumulated path metrics + * outputs - Trellis ouput values + * vals - Input value that led to each state + */ +struct vtrellis { + int num_states; + int16_t *sums; + int16_t *outputs; + uint8_t *vals; +}; + +/* Viterbi Decoder + * n - Code order + * k - Constraint length + * len - Horizontal length of trellis + * recursive - Set to '1' if the code is recursive + * intrvl - Normalization interval + * trellis - Trellis object + * punc - Puncturing sequence + * paths - Trellis paths + */ +struct vdecoder { + int n; + int k; + int len; + int recursive; + int intrvl; + struct vtrellis *trellis; + int *punc; + int16_t **paths; + + void (*metric_func)(const int8_t *, const int16_t *, + int16_t *, int16_t *, int); +}; + +/* Aligned Memory Allocator + * SSE requires 16-byte memory alignment. We store relevant trellis values + * (accumulated sums, outputs, and path decisions) as 16 bit signed integers + * so the allocated memory is casted as such. + */ +#define SSE_ALIGN 16 + +static int16_t *vdec_malloc(size_t n) +{ +#ifdef HAVE_SSE3 + return (int16_t *) memalign(SSE_ALIGN, sizeof(int16_t) * n); +#else + return (int16_t *) malloc(sizeof(int16_t) * n); +#endif +} + +/* Accessor calls */ +inline int conv_code_recursive(const struct osmo_conv_code *code) +{ + return code->next_term_output ? 1 : 0; +} + +/* Left shift and mask for finding the previous state */ +static unsigned vstate_lshift(unsigned reg, int k, int val) +{ + unsigned mask; + + if (k == 5) + mask = 0x0e; + else if (k == 7) + mask = 0x3e; + else + mask = 0; + + return ((reg << 1) & mask) | val; +} + +/* Bit endian manipulators */ +inline unsigned bitswap2(unsigned v) +{ + return ((v & 0x02) >> 1) | ((v & 0x01) << 1); +} + +inline unsigned bitswap3(unsigned v) +{ + return ((v & 0x04) >> 2) | ((v & 0x02) >> 0) | + ((v & 0x01) << 2); +} + +inline unsigned bitswap4(unsigned v) +{ + return ((v & 0x08) >> 3) | ((v & 0x04) >> 1) | + ((v & 0x02) << 1) | ((v & 0x01) << 3); +} + +inline unsigned bitswap5(unsigned v) +{ + return ((v & 0x10) >> 4) | ((v & 0x08) >> 2) | ((v & 0x04) >> 0) | + ((v & 0x02) << 2) | ((v & 0x01) << 4); +} + +inline unsigned bitswap6(unsigned v) +{ + return ((v & 0x20) >> 5) | ((v & 0x10) >> 3) | ((v & 0x08) >> 1) | + ((v & 0x04) << 1) | ((v & 0x02) << 3) | ((v & 0x01) << 5); +} + +static unsigned bitswap(unsigned v, unsigned n) +{ + switch (n) { + case 1: + return v; + case 2: + return bitswap2(v); + case 3: + return bitswap3(v); + case 4: + return bitswap4(v); + case 5: + return bitswap5(v); + case 6: + return bitswap6(v); + default: + break; + } + + return 0; +} + +/* Generate non-recursive state output from generator state table + * Note that the shift register moves right (i.e. the most recent bit is + * shifted into the register at k-1 bit of the register), which is typical + * textbook representation. The API transition table expects the most recent + * bit in the low order bit, or left shift. A bitswap operation is required + * to accommodate the difference. + */ +static unsigned gen_output(struct vstate *state, int val, + const struct osmo_conv_code *code) +{ + unsigned out, prev; + + prev = bitswap(state->prev[0], code->K - 1); + out = code->next_output[prev][val]; + out = bitswap(out, code->N); + + return out; +} + +#define BIT2NRZ(REG,N) (((REG >> N) & 0x01) * 2 - 1) * -1 + +/* Populate non-recursive trellis state + * For a given state defined by the k-1 length shift register, find the + * value of the input bit that drove the trellis to that state. Also + * generate the N outputs of the generator polynomial at that state. + */ +static int gen_state_info(uint8_t *val, unsigned reg, + int16_t *output, const struct osmo_conv_code *code) +{ + int i; + unsigned out; + struct vstate state; + + /* Previous '0' state */ + state.state = reg; + state.prev[0] = vstate_lshift(reg, code->K, 0); + state.prev[1] = vstate_lshift(reg, code->K, 1); + + *val = (reg >> (code->K - 2)) & 0x01; + + /* Transition output */ + out = gen_output(&state, *val, code); + + /* Unpack to NRZ */ + for (i = 0; i < code->N; i++) + output[i] = BIT2NRZ(out, i); + + return 0; +} + +/* Generate recursive state output from generator state table */ +static unsigned gen_recursive_output(struct vstate *state, + uint8_t *val, unsigned reg, + const struct osmo_conv_code *code, int pos) +{ + int val0, val1; + unsigned out, prev; + + /* Previous '0' state */ + prev = vstate_lshift(reg, code->K, 0); + prev = bitswap(prev, code->K - 1); + + /* Input value */ + val0 = (reg >> (code->K - 2)) & 0x01; + val1 = (code->next_term_output[prev] >> pos) & 0x01; + *val = val0 == val1 ? 0 : 1; + + /* Wrapper for osmocom state access */ + prev = bitswap(state->prev[0], code->K - 1); + + /* Compute the transition output */ + out = code->next_output[prev][*val]; + out = bitswap(out, code->N); + + return out; +} + +#define NUM_STATES(K) (K == 7 ? 64 : 16) + +/* Populate recursive trellis state + * The bit position of the systematic bit is not explicitly marked by the + * API, so it must be extracted from the generator table. Otherwise, + * populate the trellis similar to the non-recursive version. + * Non-systematic recursive codes are not supported. + */ +static int gen_recursive_state_info(uint8_t *val, + unsigned reg, + int16_t *output, + const struct osmo_conv_code *code) +{ + int i, j, pos = -1; + int ns = NUM_STATES(code->K); + unsigned out; + struct vstate state; + + /* Previous '0' and '1' states */ + state.state = reg; + state.prev[0] = vstate_lshift(reg, code->K, 0); + state.prev[1] = vstate_lshift(reg, code->K, 1); + + /* Find recursive bit location */ + for (i = 0; i < code->N; i++) { + for (j = 0; j < ns; j++) { + if ((code->next_output[j][0] >> i) & 0x01) + break; + } + if (j == ns) { + pos = i; + break; + } + } + + /* Non-systematic recursive code not supported */ + if (pos < 0) + return -EPROTO; + + /* Transition output */ + out = gen_recursive_output(&state, val, reg, code, pos); + + /* Unpack to NRZ */ + for (i = 0; i < code->N; i++) + output[i] = BIT2NRZ(out, i); + + return 0; +} + +/* Release the trellis */ +static void free_trellis(struct vtrellis *trellis) +{ + if (!trellis) + return; + + free(trellis->vals); + free(trellis->outputs); + free(trellis->sums); + free(trellis); +} + +/* Allocate and initialize the trellis object + * Initialization consists of generating the outputs and output value of a + * given state. Due to trellis symmetry and anti-symmetry, only one of the + * transition paths is utilized by the butterfly operation in the forward + * recursion, so only one set of N outputs is required per state variable. + */ +static struct vtrellis *generate_trellis(const struct osmo_conv_code *code) +{ + int i, rc = -1; + struct vtrellis *trellis; + int16_t *outputs; + + int ns = NUM_STATES(code->K); + int recursive = conv_code_recursive(code); + int olen = (code->N == 2) ? 2 : 4; + + trellis = (struct vtrellis *) calloc(1, sizeof(struct vtrellis)); + trellis->num_states = ns; + trellis->sums = vdec_malloc(ns); + trellis->outputs = vdec_malloc(ns * olen); + trellis->vals = (uint8_t *) malloc(ns * sizeof(uint8_t)); + + if (!trellis->sums || !trellis->outputs) + goto fail; + + /* Populate the trellis state objects */ + for (i = 0; i < ns; i++) { + outputs = &trellis->outputs[olen * i]; + + if (recursive) + rc = gen_recursive_state_info(&trellis->vals[i], + i, outputs, code); + else + rc = gen_state_info(&trellis->vals[i], + i, outputs, code); + } + + if (rc < 0) + goto fail; + + return trellis; +fail: + free_trellis(trellis); + return NULL; +} + +/* Reset decoder + * Set accumulated path metrics to zero. For termination other than + * tail-biting, initialize the zero state as the encoder starting state. + * Intialize with the maximum accumulated sum at length equal to the + * constraint length. + */ +static void reset_decoder(struct vdecoder *dec, int term) +{ + int ns = dec->trellis->num_states; + + memset(dec->trellis->sums, 0, sizeof(int16_t) * ns); + + if (term != CONV_TERM_TAIL_BITING) + dec->trellis->sums[0] = INT8_MAX * dec->n * dec->k; +} + +static void _traceback(struct vdecoder *dec, + unsigned state, uint8_t *out, int len) +{ + int i; + unsigned path; + + for (i = len - 1; i >= 0; i--) { + path = dec->paths[i][state] + 1; + out[i] = dec->trellis->vals[state]; + state = vstate_lshift(state, dec->k, path); + } +} + +static void _traceback_rec(struct vdecoder *dec, + unsigned state, uint8_t *out, int len) +{ + int i; + unsigned path; + + for (i = len - 1; i >= 0; i--) { + path = dec->paths[i][state] + 1; + out[i] = path ^ dec->trellis->vals[state]; + state = vstate_lshift(state, dec->k, path); + } +} + +/* Traceback and generate decoded output + * Find the largest accumulated path metric at the final state except for + * the zero terminated case, where we assume the final state is always zero. + */ +static int traceback(struct vdecoder *dec, uint8_t *out, int term, int len) +{ + int i, sum, max = -1; + unsigned path, state = 0; + + if (term != CONV_TERM_FLUSH) { + for (i = 0; i < dec->trellis->num_states; i++) { + sum = dec->trellis->sums[i]; + if (sum > max) { + max = sum; + state = i; + } + } + + if (max < 0) + return -EPROTO; + } + + for (i = dec->len - 1; i >= len; i--) { + path = dec->paths[i][state] + 1; + state = vstate_lshift(state, dec->k, path); + } + + if (dec->recursive) + _traceback_rec(dec, state, out, len); + else + _traceback(dec, state, out, len); + + return 0; +} + +/* Release decoder object */ +static void free_vdec(struct vdecoder *dec) +{ + if (!dec) + return; + + free(dec->paths[0]); + free(dec->paths); + free_trellis(dec->trellis); + free(dec); +} + +/* Allocate decoder object + * Subtract the constraint length K on the normalization interval to + * accommodate the initialization path metric at state zero. + */ +static struct vdecoder *alloc_vdec(const struct osmo_conv_code *code) +{ + int i, ns; + struct vdecoder *dec; + + ns = NUM_STATES(code->K); + + dec = (struct vdecoder *) calloc(1, sizeof(struct vdecoder)); + dec->n = code->N; + dec->k = code->K; + dec->recursive = conv_code_recursive(code); + dec->intrvl = INT16_MAX / (dec->n * INT8_MAX) - dec->k; + + if (dec->k == 5) { + switch (dec->n) { + case 2: + dec->metric_func = gen_metrics_k5_n2; + break; + case 3: + dec->metric_func = gen_metrics_k5_n3; + break; + case 4: + dec->metric_func = gen_metrics_k5_n4; + break; + default: + goto fail; + } + } else if (dec->k == 7) { + switch (dec->n) { + case 2: + dec->metric_func = gen_metrics_k7_n2; + break; + case 3: + dec->metric_func = gen_metrics_k7_n3; + break; + case 4: + dec->metric_func = gen_metrics_k7_n4; + break; + default: + goto fail; + } + } else { + goto fail; + } + + if (code->term == CONV_TERM_FLUSH) + dec->len = code->len + code->K - 1; + else + dec->len = code->len; + + dec->trellis = generate_trellis(code); + if (!dec->trellis) + goto fail; + + dec->paths = (int16_t **) malloc(sizeof(int16_t *) * dec->len); + dec->paths[0] = vdec_malloc(ns * dec->len); + for (i = 1; i < dec->len; i++) + dec->paths[i] = &dec->paths[0][i * ns]; + + return dec; +fail: + free_vdec(dec); + return NULL; +} + +/* Depuncture sequence with nagative value terminated puncturing matrix */ +static int depuncture(const int8_t *in, const int *punc, int8_t *out, int len) +{ + int i, n = 0, m = 0; + + for (i = 0; i < len; i++) { + if (i == punc[n]) { + out[i] = 0; + n++; + continue; + } + + out[i] = in[m++]; + } + + return 0; +} + +/* Forward trellis recursion + * Generate branch metrics and path metrics with a combined function. Only + * accumulated path metric sums and path selections are stored. Normalize on + * the interval specified by the decoder. + */ +static void _conv_decode(struct vdecoder *dec, const int8_t *seq, int _cnt) +{ + int i, len = dec->len; + struct vtrellis *trellis = dec->trellis; + + for (i = 0; i < len; i++) { + dec->metric_func(&seq[dec->n * i], + trellis->outputs, + trellis->sums, + dec->paths[i], + !(i % dec->intrvl)); + } +} + +/* Convolutional decode with a decoder object + * Initial puncturing run if necessary followed by the forward recursion. + * For tail-biting perform a second pass before running the backward + * traceback operation. + */ +static int conv_decode(struct vdecoder *dec, const int8_t *seq, + const int *punc, uint8_t *out, int len, int term) +{ + int cnt = 0; + int8_t depunc[dec->len * dec->n]; + + reset_decoder(dec, term); + + if (punc) { + depuncture(seq, punc, depunc, dec->len * dec->n); + seq = depunc; + } + + /* Propagate through the trellis with interval normalization */ + _conv_decode(dec, seq, cnt); + + if (term == CONV_TERM_TAIL_BITING) + _conv_decode(dec, seq, cnt); + + return traceback(dec, out, term, len); +} + +/* All-in-one viterbi decoding */ +int osmo_conv_decode_acc(const struct osmo_conv_code *code, + const sbit_t *input, ubit_t *output) +{ + int rc; + struct vdecoder *vdec; + + if ((code->N < 2) || (code->N > 4) || (code->len < 1) || + ((code->K != 5) && (code->K != 7))) + return -EINVAL; + + vdec = alloc_vdec(code); + if (!vdec) + return -EFAULT; + + rc = conv_decode(vdec, input, code->puncture, + output, code->len, code->term); + + free_vdec(vdec); + + return rc; +} diff --git a/src/viterbi_gen.c b/src/viterbi_gen.c new file mode 100644 index 0000000..894d5ae --- /dev/null +++ b/src/viterbi_gen.c @@ -0,0 +1,182 @@ +/* + * Viterbi decoder + * Copyright (C) 2013, 2014 Thomas Tsou + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +/* Add-Compare-Select (ACS-Butterfly) + * Compute 4 accumulated path metrics and 4 path selections. Note that path + * selections are store as -1 and 0 rather than 0 and 1. This is to match + * the output format of the SSE packed compare instruction 'pmaxuw'. + */ +void acs_butterfly(int state, int num_states, + int16_t metric, int16_t *sum, + int16_t *new_sum, int16_t *path) +{ + int state0, state1; + int sum0, sum1, sum2, sum3; + + state0 = *(sum + (2 * state + 0)); + state1 = *(sum + (2 * state + 1)); + + sum0 = state0 + metric; + sum1 = state1 - metric; + sum2 = state0 - metric; + sum3 = state1 + metric; + + if (sum0 > sum1) { + *new_sum = sum0; + *path = -1; + } else { + *new_sum = sum1; + *path = 0; + } + + if (sum2 > sum3) { + *(new_sum + num_states / 2) = sum2; + *(path + num_states / 2) = -1; + } else { + *(new_sum + num_states / 2) = sum3; + *(path + num_states / 2) = 0; + } +} + +/* Branch metrics unit N=2 */ +void _gen_branch_metrics_n2(int num_states, const int8_t *seq, + const int16_t *out, int16_t *metrics) +{ + int i; + + for (i = 0; i < num_states / 2; i++) { + metrics[i] = seq[0] * out[2 * i + 0] + + seq[1] * out[2 * i + 1]; + } +} + +/* Branch metrics unit N=3 */ +void _gen_branch_metrics_n3(int num_states, const int8_t *seq, + const int16_t *out, int16_t *metrics) +{ + int i; + + for (i = 0; i < num_states / 2; i++) + metrics[i] = seq[0] * out[4 * i + 0] + + seq[1] * out[4 * i + 1] + + seq[2] * out[4 * i + 2]; +} + +/* Branch metrics unit N=4 */ +void _gen_branch_metrics_n4(int num_states, const int8_t *seq, + const int16_t *out, int16_t *metrics) +{ + int i; + + for (i = 0; i < num_states / 2; i++) + metrics[i] = seq[0] * out[4 * i + 0] + + seq[1] * out[4 * i + 1] + + seq[2] * out[4 * i + 2] + + seq[3] * out[4 * i + 3]; +} + +/* Path metric unit */ +void _gen_path_metrics(int num_states, int16_t *sums, + int16_t *metrics, int16_t *paths, int norm) +{ + int i; + int16_t min; + int16_t new_sums[num_states]; + + for (i = 0; i < num_states / 2; i++) { + acs_butterfly(i, num_states, metrics[i], + sums, &new_sums[i], &paths[i]); + } + + if (norm) { + min = new_sums[0]; + for (i = 1; i < num_states; i++) { + if (new_sums[i] < min) + min = new_sums[i]; + } + + for (i = 0; i < num_states; i++) + new_sums[i] -= min; + } + + memcpy(sums, new_sums, num_states * sizeof(int16_t)); +} + +/* 16-state branch-path metrics units (K=5) */ +void gen_metrics_k5_n2(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + int16_t metrics[8]; + + _gen_branch_metrics_n2(16, seq, out, metrics); + _gen_path_metrics(16, sums, metrics, paths, norm); +} + +void gen_metrics_k5_n3(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + int16_t metrics[8]; + + _gen_branch_metrics_n3(16, seq, out, metrics); + _gen_path_metrics(16, sums, metrics, paths, norm); + +} + +void gen_metrics_k5_n4(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + int16_t metrics[8]; + + _gen_branch_metrics_n4(16, seq, out, metrics); + _gen_path_metrics(16, sums, metrics, paths, norm); + +} + +/* 64-state branch-path metrics units (K=7) */ +void gen_metrics_k7_n2(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + int16_t metrics[32]; + + _gen_branch_metrics_n2(64, seq, out, metrics); + _gen_path_metrics(64, sums, metrics, paths, norm); + +} + +void gen_metrics_k7_n3(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + int16_t metrics[32]; + + _gen_branch_metrics_n3(64, seq, out, metrics); + _gen_path_metrics(64, sums, metrics, paths, norm); + +} + +void gen_metrics_k7_n4(const int8_t *seq, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + int16_t metrics[32]; + + _gen_branch_metrics_n4(64, seq, out, metrics); + _gen_path_metrics(64, sums, metrics, paths, norm); +} -- 1.9.0 From holger at freyther.de Tue Apr 29 07:08:45 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 29 Apr 2014 09:08:45 +0200 Subject: [PATCH 1/4] core/conv: Add optimized Viterbi decoding In-Reply-To: <20140429041209.GA5135@phenom.hsd1.va.comcast.net> References: <20140429041209.GA5135@phenom.hsd1.va.comcast.net> Message-ID: <20140429070845.GD3544@xiaoyu.lan> On Tue, Apr 29, 2014 at 12:12:09AM -0400, Thomas Tsou wrote: Hi, > Add a separate, faster convolution decoding implementation for rates > up to N=4 and constraint lengths of K=5 and K=7, which covers the > most GSM code uses. The decoding algorithm exploits the symmetric > structure of the Viterbi add-compare-select (ACS) operation - commonly > known as the ACS butterfly. This shift-register optimization can be > found in the well-known text by Dave Forney. I am not knowledgable enough to comment on the actual viterbi things so I will focus on the things around it. > +/* Aligned Memory Allocator > + * SSE requires 16-byte memory alignment. We store relevant trellis values > + * (accumulated sums, outputs, and path decisions) as 16 bit signed integers > + * so the allocated memory is casted as such. > + */ > +#define SSE_ALIGN 16 > + > +static int16_t *vdec_malloc(size_t n) > +{ > +#ifdef HAVE_SSE3 > + return (int16_t *) memalign(SSE_ALIGN, sizeof(int16_t) * n); > +#else > + return (int16_t *) malloc(sizeof(int16_t) * n); > +#endif > +} argh, it would be nice if you could use talloc here but then we would need to play games and align pointers ourselves. Maybe change the API to at least have a 'ctx' similar to other talloc API? > +static void free_trellis(struct vtrellis *trellis) > +{ > + if (!trellis) > + return; > + > + free(trellis->vals); > + free(trellis->outputs); > + free(trellis->sums); > + free(trellis); Can you use talloc here? > + _traceback_rec(dec, state, out, len); _ is reserved for the system. We might want to avoid using that. cheers holger From tom at tsou.cc Tue Apr 29 04:12:44 2014 From: tom at tsou.cc (Thomas Tsou) Date: Tue, 29 Apr 2014 00:12:44 -0400 Subject: [PATCH 2/4] core/conv: Add x86 SSE support for Viterbi decoding Message-ID: <20140429041244.GA5155@phenom.hsd1.va.comcast.net> Fast convolutional decoding is provided through x86 intrinsic based SSE operations. SSE3, found on virtually all modern x86 processors, is the minimal requirement with SSE4.1 used for path metric normalization if available. This feature is enabled with the compile flags HAVE_SSE3 and HAVE_SSE4_1. Signed-off-by: Thomas Tsou --- src/Makefile.am | 2 +- src/viterbi_gen.c | 4 + src/viterbi_sse.c | 581 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 586 insertions(+), 1 deletion(-) create mode 100644 src/viterbi_sse.c diff --git a/src/Makefile.am b/src/Makefile.am index 262a4e6..0ecf4b0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,7 +14,7 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \ gsmtap_util.c crc16.c panic.c backtrace.c \ conv.c application.c rbtree.c strrb.c \ loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c \ - viterbi.c viterbi_gen.c + viterbi.c viterbi_gen.c viterbi_sse.c BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c diff --git a/src/viterbi_gen.c b/src/viterbi_gen.c index 894d5ae..e3585ec 100644 --- a/src/viterbi_gen.c +++ b/src/viterbi_gen.c @@ -17,6 +17,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + +#ifndef HAVE_SSE3 #include #include @@ -180,3 +183,4 @@ void gen_metrics_k7_n4(const int8_t *seq, const int16_t *out, _gen_branch_metrics_n4(64, seq, out, metrics); _gen_path_metrics(64, sums, metrics, paths, norm); } +#endif /* !HAVE_SSE3 */ diff --git a/src/viterbi_sse.c b/src/viterbi_sse.c new file mode 100644 index 0000000..2372994 --- /dev/null +++ b/src/viterbi_sse.c @@ -0,0 +1,581 @@ +/* + * Intel SSE Viterbi decoder + * Copyright (C) 2013, 2014 Thomas Tsou + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#ifdef HAVE_SSE3 +#include +#include +#include + +#if defined(HAVE_SSE4_1) || defined(HAVE_SSE41) +#include +#endif + +#ifdef HAVE_AVX2 +#include +#endif + +/* Octo-Viterbi butterfly: + * Compute 8-wide butterfly generating 16 path decisions and 16 accumulated + * sums. Inputs all packed 16-bit integers in three 128-bit XMM registers. + * Two intermediate registers are used and results are set in the upper 4 + * registers. + * + * Input: + * M0 - Path metrics 0 (packed 16-bit integers) + * M1 - Path metrics 1 (packed 16-bit integers) + * M2 - Branch metrics (packed 16-bit integers) + * + * Output: + * M2 - Selected and accumulated path metrics 0 + * M4 - Selected and accumulated path metrics 1 + * M3 - Path selections 0 + * M1 - Path selections 1 + */ +#define SSE_BUTTERFLY(M0,M1,M2,M3,M4) \ +{ \ + M3 = _mm_adds_epi16(M0, M2); \ + M4 = _mm_subs_epi16(M1, M2); \ + M0 = _mm_subs_epi16(M0, M2); \ + M1 = _mm_adds_epi16(M1, M2); \ + M2 = _mm_max_epi16(M3, M4); \ + M3 = _mm_cmpgt_epi16(M3, M4); \ + M4 = _mm_max_epi16(M0, M1); \ + M1 = _mm_cmpgt_epi16(M0, M1); \ +} + +/* Two lane deinterleaving K = 5: + * Take 16 interleaved 16-bit integers and deinterleave to 2 packed 128-bit + * registers. The operation summarized below. Four registers are used with + * the lower 2 as input and upper 2 as output. + * + * In - 10101010 10101010 10101010 10101010 + * Out - 00000000 11111111 00000000 11111111 + * + * Input: + * M0:1 - Packed 16-bit integers + * + * Output: + * M2:3 - Deinterleaved packed 16-bit integers + */ +#define _I8_SHUFFLE_MASK 15, 14, 11, 10, 7, 6, 3, 2, 13, 12, 9, 8, 5, 4, 1, 0 + +#define SSE_DEINTERLEAVE_K5(M0,M1,M2,M3) \ +{ \ + M2 = _mm_set_epi8(_I8_SHUFFLE_MASK); \ + M0 = _mm_shuffle_epi8(M0, M2); \ + M1 = _mm_shuffle_epi8(M1, M2); \ + M2 = _mm_unpacklo_epi64(M0, M1); \ + M3 = _mm_unpackhi_epi64(M0, M1); \ +} + +/* Two lane deinterleaving K = 7: + * Take 64 interleaved 16-bit integers and deinterleave to 8 packed 128-bit + * registers. The operation summarized below. 16 registers are used with the + * lower 8 as input and upper 8 as output. + * + * In - 10101010 10101010 10101010 10101010 ... + * Out - 00000000 11111111 00000000 11111111 ... + * + * Input: + * M0:7 - Packed 16-bit integers + * + * Output: + * M8:15 - Deinterleaved packed 16-bit integers + */ +#define SSE_DEINTERLEAVE_K7(M0,M1,M2,M3,M4,M5,M6,M7, \ + M8,M9,M10,M11,M12,M13,M14,M15) \ +{ \ + M8 = _mm_set_epi8(_I8_SHUFFLE_MASK); \ + M0 = _mm_shuffle_epi8(M0, M8); \ + M1 = _mm_shuffle_epi8(M1, M8); \ + M2 = _mm_shuffle_epi8(M2, M8); \ + M3 = _mm_shuffle_epi8(M3, M8); \ + M4 = _mm_shuffle_epi8(M4, M8); \ + M5 = _mm_shuffle_epi8(M5, M8); \ + M6 = _mm_shuffle_epi8(M6, M8); \ + M7 = _mm_shuffle_epi8(M7, M8); \ + M8 = _mm_unpacklo_epi64(M0, M1); \ + M9 = _mm_unpackhi_epi64(M0, M1); \ + M10 = _mm_unpacklo_epi64(M2, M3); \ + M11 = _mm_unpackhi_epi64(M2, M3); \ + M12 = _mm_unpacklo_epi64(M4, M5); \ + M13 = _mm_unpackhi_epi64(M4, M5); \ + M14 = _mm_unpacklo_epi64(M6, M7); \ + M15 = _mm_unpackhi_epi64(M6, M7); \ +} + +/* Generate branch metrics N = 2: + * Compute 16 branch metrics from trellis outputs and input values. + * + * Input: + * M0:3 - 16 x 2 packed 16-bit trellis outputs + * M4 - Expanded and packed 16-bit input value + * + * Output: + * M6:7 - 16 computed 16-bit branch metrics + */ +#define SSE_BRANCH_METRIC_N2(M0,M1,M2,M3,M4,M6,M7) \ +{ \ + M0 = _mm_sign_epi16(M4, M0); \ + M1 = _mm_sign_epi16(M4, M1); \ + M2 = _mm_sign_epi16(M4, M2); \ + M3 = _mm_sign_epi16(M4, M3); \ + M6 = _mm_hadds_epi16(M0, M1); \ + M7 = _mm_hadds_epi16(M2, M3); \ +} + +/* Generate branch metrics N = 4: + * Compute 8 branch metrics from trellis outputs and input values. This + * macro is reused for N less than 4 where the extra soft input bits are + * padded. + * + * Input: + * M0:3 - 8 x 4 packed 16-bit trellis outputs + * M4 - Expanded and packed 16-bit input value + * + * Output: + * M5 - 8 computed 16-bit branch metrics + */ +#define SSE_BRANCH_METRIC_N4(M0,M1,M2,M3,M4,M5) \ +{ \ + M0 = _mm_sign_epi16(M4, M0); \ + M1 = _mm_sign_epi16(M4, M1); \ + M2 = _mm_sign_epi16(M4, M2); \ + M3 = _mm_sign_epi16(M4, M3); \ + M0 = _mm_hadds_epi16(M0, M1); \ + M1 = _mm_hadds_epi16(M2, M3); \ + M5 = _mm_hadds_epi16(M0, M1); \ +} + +/* Broadcast 16-bit integer + * Repeat the low 16-bit integer to all elements of the 128-bit SSE + * register. Only AVX2 has a dedicated broadcast instruction; use repeat + * unpacks for SSE only architectures. This is a destructive operation and + * the source register is overwritten. + * + * Input: + * M0 - Low 16-bit element is read + * + * Output: + * M0 - Contains broadcasted values + */ +#ifdef HAVE_AVX2 +#define SSE_BROADCAST(M0) \ +{ \ + M0 = _mm_broadcastw_epi16(M0); \ +} +#else +#define SSE_BROADCAST(M0) \ +{ \ + M0 = _mm_unpacklo_epi16(M0, M0); \ + M0 = _mm_unpacklo_epi32(M0, M0); \ + M0 = _mm_unpacklo_epi64(M0, M0); \ +} +#endif + +/* Horizontal minimum + * Compute horizontal minimum of packed unsigned 16-bit integers and place + * result in the low 16-bit element of the source register. Only SSE 4.1 + * has a dedicated minpos instruction. One internmediate register is used + * if SSE 4.1 is not available. This is a destructive operation and the + * source register is overwritten. + * + * Input: + * M0 - Packed unsigned 16-bit integers + * + * Output: + * M0 - Minimum value placed in low 16-bit element + */ +#if defined(HAVE_SSE4_1) || defined(HAVE_SSE41) +#define SSE_MINPOS(M0,M1) \ +{ \ + M0 = _mm_minpos_epu16(M0); \ +} +#else +#define SSE_MINPOS(M0,M1) \ +{ \ + M1 = _mm_shuffle_epi32(M0, _MM_SHUFFLE(0, 0, 3, 2)); \ + M0 = _mm_min_epi16(M0, M1); \ + M1 = _mm_shufflelo_epi16(M0, _MM_SHUFFLE(0, 0, 3, 2)); \ + M0 = _mm_min_epi16(M0, M1); \ + M1 = _mm_shufflelo_epi16(M0, _MM_SHUFFLE(0, 0, 0, 1)); \ + M0 = _mm_min_epi16(M0, M1); \ +} +#endif + +/* Normalize state metrics K = 5: + * Compute 16-wide normalization by subtracting the smallest value from + * all values. Inputs are 16 packed 16-bit integers across 2 XMM registers. + * Two intermediate registers are used and normalized results are placed + * in the originating locations. + * + * Input: + * M0:1 - Path metrics 0:1 (packed 16-bit integers) + * + * Output: + * M0:1 - Normalized path metrics 0:1 + */ +#define SSE_NORMALIZE_K5(M0,M1,M2,M3) \ +{ \ + M2 = _mm_min_epi16(M0, M1); \ + SSE_MINPOS(M2, M3) \ + SSE_BROADCAST(M2) \ + M0 = _mm_subs_epi16(M0, M2); \ + M1 = _mm_subs_epi16(M1, M2); \ +} + +/* Normalize state metrics K = 7: + * Compute 64-wide normalization by subtracting the smallest value from + * all values. Inputs are 8 registers of accumulated sums and 4 temporary + * registers. Normalized results are returned in the originating locations. + * + * Input: + * M0:7 - Path metricss 0:7 (packed 16-bit integers) + * + * Output: + * M0:7 - Normalized path metrics 0:7 + */ +#define SSE_NORMALIZE_K7(M0,M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11) \ +{ \ + M8 = _mm_min_epi16(M0, M1); \ + M9 = _mm_min_epi16(M2, M3); \ + M10 = _mm_min_epi16(M4, M5); \ + M11 = _mm_min_epi16(M6, M7); \ + M8 = _mm_min_epi16(M8, M9); \ + M10 = _mm_min_epi16(M10, M11); \ + M8 = _mm_min_epi16(M8, M10); \ + SSE_MINPOS(M8, M9) \ + SSE_BROADCAST(M8) \ + M0 = _mm_subs_epi16(M0, M8); \ + M1 = _mm_subs_epi16(M1, M8); \ + M2 = _mm_subs_epi16(M2, M8); \ + M3 = _mm_subs_epi16(M3, M8); \ + M4 = _mm_subs_epi16(M4, M8); \ + M5 = _mm_subs_epi16(M5, M8); \ + M6 = _mm_subs_epi16(M6, M8); \ + M7 = _mm_subs_epi16(M7, M8); \ +} + +/* Combined BMU/PMU (K=5, N=2) + * Compute branch metrics followed by path metrics for half rate 16-state + * trellis. 8 butterflies are computed. Accumulated path sums are not + * preserved and read and written into the same memory location. Normalize + * sums if requires. + */ +__always_inline void _sse_metrics_k5_n2(const int16_t *val, + const int16_t *out, + int16_t *sums, + int16_t *paths, + int norm) +{ + __m128i m0, m1, m2, m3, m4, m5, m6; + + /* (BMU) Load input sequence */ + m2 = _mm_castpd_si128(_mm_loaddup_pd((double const *) val)); + + /* (BMU) Load trellis outputs */ + m0 = _mm_load_si128((__m128i *) &out[0]); + m1 = _mm_load_si128((__m128i *) &out[8]); + + /* (BMU) Compute branch metrics */ + m0 = _mm_sign_epi16(m2, m0); + m1 = _mm_sign_epi16(m2, m1); + m2 = _mm_hadds_epi16(m0, m1); + + /* (PMU) Load accumulated path matrics */ + m0 = _mm_load_si128((__m128i *) &sums[0]); + m1 = _mm_load_si128((__m128i *) &sums[8]); + + SSE_DEINTERLEAVE_K5(m0, m1, m3, m4) + + /* (PMU) Butterflies: 0-7 */ + SSE_BUTTERFLY(m3, m4, m2, m5, m6) + + if (norm) + SSE_NORMALIZE_K5(m2, m6, m0, m1) + + _mm_store_si128((__m128i *) &sums[0], m2); + _mm_store_si128((__m128i *) &sums[8], m6); + _mm_store_si128((__m128i *) &paths[0], m5); + _mm_store_si128((__m128i *) &paths[8], m4); +} + +/* Combined BMU/PMU (K=5, N=3 and N=4) + * Compute branch metrics followed by path metrics for 16-state and rates + * to 1/4. 8 butterflies are computed. The input sequence is read four 16-bit + * values at a time, and extra values should be set to zero for rates other + * than 1/4. Normally only rates 1/3 and 1/4 are used as there is a + * dedicated implementation of rate 1/2. + */ +__always_inline void _sse_metrics_k5_n4(const int16_t *val, + const int16_t *out, + int16_t *sums, + int16_t *paths, + int norm) +{ + __m128i m0, m1, m2, m3, m4, m5, m6; + + /* (BMU) Load input sequence */ + m4 = _mm_castpd_si128(_mm_loaddup_pd((double const *) val)); + + /* (BMU) Load trellis outputs */ + m0 = _mm_load_si128((__m128i *) &out[0]); + m1 = _mm_load_si128((__m128i *) &out[8]); + m2 = _mm_load_si128((__m128i *) &out[16]); + m3 = _mm_load_si128((__m128i *) &out[24]); + + SSE_BRANCH_METRIC_N4(m0, m1, m2, m3, m4, m2) + + /* (PMU) Load accumulated path matrics */ + m0 = _mm_load_si128((__m128i *) &sums[0]); + m1 = _mm_load_si128((__m128i *) &sums[8]); + + SSE_DEINTERLEAVE_K5(m0, m1, m3, m4) + + /* (PMU) Butterflies: 0-7 */ + SSE_BUTTERFLY(m3, m4, m2, m5, m6) + + if (norm) + SSE_NORMALIZE_K5(m2, m6, m0, m1) + + _mm_store_si128((__m128i *) &sums[0], m2); + _mm_store_si128((__m128i *) &sums[8], m6); + _mm_store_si128((__m128i *) &paths[0], m5); + _mm_store_si128((__m128i *) &paths[8], m4); +} + +/* Combined BMU/PMU (K=7, N=2) + * Compute branch metrics followed by path metrics for half rate 64-state + * trellis. 32 butterfly operations are computed. Deinterleaving path + * metrics requires usage of the full SSE register file, so separate sums + * before computing branch metrics to avoid register spilling. + */ +__always_inline void _sse_metrics_k7_n2(const int16_t *val, + const const int16_t *out, + int16_t *sums, + int16_t *paths, + int norm) +{ + __m128i m0, m1, m2, m3, m4, m5, m6, m7, m8, + m9, m10, m11, m12, m13, m14, m15; + + /* (PMU) Load accumulated path matrics */ + m0 = _mm_load_si128((__m128i *) &sums[0]); + m1 = _mm_load_si128((__m128i *) &sums[8]); + m2 = _mm_load_si128((__m128i *) &sums[16]); + m3 = _mm_load_si128((__m128i *) &sums[24]); + m4 = _mm_load_si128((__m128i *) &sums[32]); + m5 = _mm_load_si128((__m128i *) &sums[40]); + m6 = _mm_load_si128((__m128i *) &sums[48]); + m7 = _mm_load_si128((__m128i *) &sums[56]); + + /* (PMU) Deinterleave to even-odd registers */ + SSE_DEINTERLEAVE_K7(m0, m1, m2, m3 ,m4 ,m5, m6, m7, + m8, m9, m10, m11, m12, m13, m14, m15) + + /* (BMU) Load input symbols */ + m7 = _mm_castpd_si128(_mm_loaddup_pd((double const *) val)); + + /* (BMU) Load trellis outputs */ + m0 = _mm_load_si128((__m128i *) &out[0]); + m1 = _mm_load_si128((__m128i *) &out[8]); + m2 = _mm_load_si128((__m128i *) &out[16]); + m3 = _mm_load_si128((__m128i *) &out[24]); + + SSE_BRANCH_METRIC_N2(m0, m1, m2, m3, m7, m4, m5) + + m0 = _mm_load_si128((__m128i *) &out[32]); + m1 = _mm_load_si128((__m128i *) &out[40]); + m2 = _mm_load_si128((__m128i *) &out[48]); + m3 = _mm_load_si128((__m128i *) &out[56]); + + SSE_BRANCH_METRIC_N2(m0, m1, m2, m3, m7, m6, m7) + + /* (PMU) Butterflies: 0-15 */ + SSE_BUTTERFLY(m8, m9, m4, m0, m1) + SSE_BUTTERFLY(m10, m11, m5, m2, m3) + + _mm_store_si128((__m128i *) &paths[0], m0); + _mm_store_si128((__m128i *) &paths[8], m2); + _mm_store_si128((__m128i *) &paths[32], m9); + _mm_store_si128((__m128i *) &paths[40], m11); + + /* (PMU) Butterflies: 17-31 */ + SSE_BUTTERFLY(m12, m13, m6, m0, m2) + SSE_BUTTERFLY(m14, m15, m7, m9, m11) + + _mm_store_si128((__m128i *) &paths[16], m0); + _mm_store_si128((__m128i *) &paths[24], m9); + _mm_store_si128((__m128i *) &paths[48], m13); + _mm_store_si128((__m128i *) &paths[56], m15); + + if (norm) + SSE_NORMALIZE_K7(m4, m1, m5, m3, m6, m2, + m7, m11, m0, m8, m9, m10) + + _mm_store_si128((__m128i *) &sums[0], m4); + _mm_store_si128((__m128i *) &sums[8], m5); + _mm_store_si128((__m128i *) &sums[16], m6); + _mm_store_si128((__m128i *) &sums[24], m7); + _mm_store_si128((__m128i *) &sums[32], m1); + _mm_store_si128((__m128i *) &sums[40], m3); + _mm_store_si128((__m128i *) &sums[48], m2); + _mm_store_si128((__m128i *) &sums[56], m11); +} + +/* Combined BMU/PMU (K=7, N=3 and N=4) + * Compute branch metrics followed by path metrics for half rate 64-state + * trellis. 32 butterfly operations are computed. Deinterleave path + * metrics before computing branch metrics as in the half rate case. + */ +__always_inline void _sse_metrics_k7_n4(const int16_t *val, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + __m128i m0, m1, m2, m3, m4, m5, m6, m7; + __m128i m8, m9, m10, m11, m12, m13, m14, m15; + + /* (PMU) Load accumulated path matrics */ + m0 = _mm_load_si128((__m128i *) &sums[0]); + m1 = _mm_load_si128((__m128i *) &sums[8]); + m2 = _mm_load_si128((__m128i *) &sums[16]); + m3 = _mm_load_si128((__m128i *) &sums[24]); + m4 = _mm_load_si128((__m128i *) &sums[32]); + m5 = _mm_load_si128((__m128i *) &sums[40]); + m6 = _mm_load_si128((__m128i *) &sums[48]); + m7 = _mm_load_si128((__m128i *) &sums[56]); + + /* (PMU) Deinterleave into even and odd packed registers */ + SSE_DEINTERLEAVE_K7(m0, m1, m2, m3 ,m4 ,m5, m6, m7, + m8, m9, m10, m11, m12, m13, m14, m15) + + /* (BMU) Load and expand 8-bit input out to 16-bits */ + m7 = _mm_castpd_si128(_mm_loaddup_pd((double const *) val)); + + /* (BMU) Load and compute branch metrics */ + m0 = _mm_load_si128((__m128i *) &out[0]); + m1 = _mm_load_si128((__m128i *) &out[8]); + m2 = _mm_load_si128((__m128i *) &out[16]); + m3 = _mm_load_si128((__m128i *) &out[24]); + + SSE_BRANCH_METRIC_N4(m0, m1, m2, m3, m7, m4) + + m0 = _mm_load_si128((__m128i *) &out[32]); + m1 = _mm_load_si128((__m128i *) &out[40]); + m2 = _mm_load_si128((__m128i *) &out[48]); + m3 = _mm_load_si128((__m128i *) &out[56]); + + SSE_BRANCH_METRIC_N4(m0, m1, m2, m3, m7, m5) + + m0 = _mm_load_si128((__m128i *) &out[64]); + m1 = _mm_load_si128((__m128i *) &out[72]); + m2 = _mm_load_si128((__m128i *) &out[80]); + m3 = _mm_load_si128((__m128i *) &out[88]); + + SSE_BRANCH_METRIC_N4(m0, m1, m2, m3, m7, m6) + + m0 = _mm_load_si128((__m128i *) &out[96]); + m1 = _mm_load_si128((__m128i *) &out[104]); + m2 = _mm_load_si128((__m128i *) &out[112]); + m3 = _mm_load_si128((__m128i *) &out[120]); + + SSE_BRANCH_METRIC_N4(m0, m1, m2, m3, m7, m7) + + /* (PMU) Butterflies: 0-15 */ + SSE_BUTTERFLY(m8, m9, m4, m0, m1) + SSE_BUTTERFLY(m10, m11, m5, m2, m3) + + _mm_store_si128((__m128i *) &paths[0], m0); + _mm_store_si128((__m128i *) &paths[8], m2); + _mm_store_si128((__m128i *) &paths[32], m9); + _mm_store_si128((__m128i *) &paths[40], m11); + + /* (PMU) Butterflies: 17-31 */ + SSE_BUTTERFLY(m12, m13, m6, m0, m2) + SSE_BUTTERFLY(m14, m15, m7, m9, m11) + + _mm_store_si128((__m128i *) &paths[16], m0); + _mm_store_si128((__m128i *) &paths[24], m9); + _mm_store_si128((__m128i *) &paths[48], m13); + _mm_store_si128((__m128i *) &paths[56], m15); + + if (norm) + SSE_NORMALIZE_K7(m4, m1, m5, m3, m6, m2, + m7, m11, m0, m8, m9, m10) + + _mm_store_si128((__m128i *) &sums[0], m4); + _mm_store_si128((__m128i *) &sums[8], m5); + _mm_store_si128((__m128i *) &sums[16], m6); + _mm_store_si128((__m128i *) &sums[24], m7); + _mm_store_si128((__m128i *) &sums[32], m1); + _mm_store_si128((__m128i *) &sums[40], m3); + _mm_store_si128((__m128i *) &sums[48], m2); + _mm_store_si128((__m128i *) &sums[56], m11); +} + +void gen_metrics_k5_n2(const int8_t *val, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + const int16_t _val[4] = { val[0], val[1], val[0], val[1] }; + + _sse_metrics_k5_n2(_val, out, sums, paths, norm); +} + +void gen_metrics_k5_n3(const int8_t *val, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + const int16_t _val[4] = { val[0], val[1], val[2], 0 }; + + _sse_metrics_k5_n4(_val, out, sums, paths, norm); +} + +void gen_metrics_k5_n4(const int8_t *val, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + const int16_t _val[4] = { val[0], val[1], val[2], val[3] }; + + _sse_metrics_k5_n4(_val, out, sums, paths, norm); +} + +void gen_metrics_k7_n2(const int8_t *val, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + const int16_t _val[4] = { val[0], val[1], val[0], val[1] }; + + _sse_metrics_k7_n2(_val, out, sums, paths, norm); +} + +void gen_metrics_k7_n3(const int8_t *val, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + const int16_t _val[4] = { val[0], val[1], val[2], 0 }; + + _sse_metrics_k7_n4(_val, out, sums, paths, norm); +} + +void gen_metrics_k7_n4(const int8_t *val, const int16_t *out, + int16_t *sums, int16_t *paths, int norm) +{ + const int16_t _val[4] = { val[0], val[1], val[2], val[3] }; + + _sse_metrics_k7_n4(_val, out, sums, paths, norm); +} + +#endif /* HAVE_SSE3 */ -- 1.9.0 From tom at tsou.cc Tue Apr 29 04:13:11 2014 From: tom at tsou.cc (Thomas Tsou) Date: Tue, 29 Apr 2014 00:13:11 -0400 Subject: [PATCH 3/4] build: Add x86 architecture type detection Message-ID: <20140429041311.GA5175@phenom.hsd1.va.comcast.net> Detect x86 SSE availability for architecture specific convolutional decoding. Use the GNU autoconf macro AX_EXT to provide built time detection and set the following definitions. http://www.gnu.org/software/autoconf-archive/ax_ext.html HAVE_SSE3 HAVE_SSE4_1 AX_EXT is generally packaged with autoconf-archive and requires the following macro files. ax_check_compile_flag.m4 ax_ext.m4 ax_gcc_x86_avx_xgetbv.m4 ax_gcc_x86_cpuid.m4 Set -march=native for automatic compile flag setting. Combined, this allows automatic detection on x86 and pass-through support for non-x86 platforms (e.g. ARM). Signed-off-by: Thomas Tsou --- configure.ac | 1 + src/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index eaaab50..4b0c572 100644 --- a/configure.ac +++ b/configure.ac @@ -179,6 +179,7 @@ then AC_DEFINE([PANIC_INFLOOP],[1],[Use infinite loop on panic rather than fprintf/abort]) fi +AX_EXT AC_OUTPUT( libosmocore.pc diff --git a/src/Makefile.am b/src/Makefile.am index 0ecf4b0..c0b78a8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,7 @@ # Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification LIBVERSION=4:0:0 -AM_CFLAGS = -Wall $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include +AM_CFLAGS = -Wall $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include -march=native lib_LTLIBRARIES = libosmocore.la -- 1.9.0 From tom at tsou.cc Tue Apr 29 04:13:32 2014 From: tom at tsou.cc (Thomas Tsou) Date: Tue, 29 Apr 2014 00:13:32 -0400 Subject: [PATCH 4/4] conv/test: Extended convolutional decoding tests Message-ID: <20140429041332.GA5194@phenom.hsd1.va.comcast.net> Add 20 additional convolutional test cases for commonly used codes. These include 16 codes for various cases of GSM TCH handing and an additional tail-biting case for LTE broadcast channels. Signed-off-by: Thomas Tsou --- tests/Makefile.am | 2 +- tests/conv/codes.c | 1034 +++++++++++++++++++++++++++++++++++++++++++++++ tests/conv/codes.h | 30 ++ tests/conv/conv_test.c | 378 +++++++---------- tests/conv/conv_test.ok | 128 ++++++ 5 files changed, 1344 insertions(+), 228 deletions(-) create mode 100644 tests/conv/codes.c create mode 100644 tests/conv/codes.h diff --git a/tests/Makefile.am b/tests/Makefile.am index c6216d5..42fea46 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -28,7 +28,7 @@ auth_milenage_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/sr bits_bitrev_test_SOURCES = bits/bitrev_test.c bits_bitrev_test_LDADD = $(top_builddir)/src/libosmocore.la -conv_conv_test_SOURCES = conv/conv_test.c +conv_conv_test_SOURCES = conv/conv_test.c conv/codes.c conv_conv_test_LDADD = $(top_builddir)/src/libosmocore.la gsm0808_gsm0808_test_SOURCES = gsm0808/gsm0808_test.c diff --git a/tests/conv/codes.c b/tests/conv/codes.c new file mode 100644 index 0000000..703946b --- /dev/null +++ b/tests/conv/codes.c @@ -0,0 +1,1034 @@ +#include +#include "codes.h" + +static const uint8_t xcch_next_output[][2] = { + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, + { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, +}; + +static const uint8_t xcch_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, +}; + +/* GSM XCCH */ +const struct osmo_conv_code gsm_conv_xcch = { + .N = 2, + .K = 5, + .len = 224, + .next_output = xcch_next_output, + .next_state = xcch_next_state, +}; + +/* GPRS CS2 */ +const struct osmo_conv_code gsm_conv_cs2 = { + .N = 2, + .K = 5, + .len = 290, + .next_output = xcch_next_output, + .next_state = xcch_next_state, +}; + +/* GPRS CS3 */ +const struct osmo_conv_code gsm_conv_cs3 = { + .N = 2, + .K = 5, + .len = 334, + .next_output = xcch_next_output, + .next_state = xcch_next_state, +}; + +/* GSM RACH */ +const struct osmo_conv_code gsm_conv_rach = { + .N = 2, + .K = 5, + .len = 14, + .next_output = xcch_next_output, + .next_state = xcch_next_state, +}; + +/* GSM SCH */ +const struct osmo_conv_code gsm_conv_sch = { + .N = 2, + .K = 5, + .len = 35, + .next_output = xcch_next_output, + .next_state = xcch_next_state, +}; + +/* GSM TCH-FR */ +const struct osmo_conv_code gsm_conv_tch_fr = { + .N = 2, + .K = 5, + .len = 185, + .next_output = xcch_next_output, + .next_state = xcch_next_state, +}; + +static const uint8_t tch_hr_next_output[][2] = { + { 0, 7 }, { 3, 4 }, { 5, 2 }, { 6, 1 }, + { 5, 2 }, { 6, 1 }, { 0, 7 }, { 3, 4 }, + { 3, 4 }, { 0, 7 }, { 6, 1 }, { 5, 2 }, + { 6, 1 }, { 5, 2 }, { 3, 4 }, { 0, 7 }, + { 4, 3 }, { 7, 0 }, { 1, 6 }, { 2, 5 }, + { 1, 6 }, { 2, 5 }, { 4, 3 }, { 7, 0 }, + { 7, 0 }, { 4, 3 }, { 2, 5 }, { 1, 6 }, + { 2, 5 }, { 1, 6 }, { 7, 0 }, { 4, 3 }, + { 7, 0 }, { 4, 3 }, { 2, 5 }, { 1, 6 }, + { 2, 5 }, { 1, 6 }, { 7, 0 }, { 4, 3 }, + { 4, 3 }, { 7, 0 }, { 1, 6 }, { 2, 5 }, + { 1, 6 }, { 2, 5 }, { 4, 3 }, { 7, 0 }, + { 3, 4 }, { 0, 7 }, { 6, 1 }, { 5, 2 }, + { 6, 1 }, { 5, 2 }, { 3, 4 }, { 0, 7 }, + { 0, 7 }, { 3, 4 }, { 5, 2 }, { 6, 1 }, + { 5, 2 }, { 6, 1 }, { 0, 7 }, { 3, 4 }, +}; + +static const uint8_t tch_hr_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, + { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, + { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, + { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, + { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, + { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, + { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, + { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, + { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, + { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, + { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, + { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, + { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, +}; + +static const int tch_hr_puncture[] = { + 1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, + 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, + 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, + 109, 112, 115, 118, 121, 124, 127, 130, 133, 136, 139, 142, + 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178, + 181, 184, 187, 190, 193, 196, 199, 202, 205, 208, 211, 214, + 217, 220, 223, 226, 229, 232, 235, 238, 241, 244, 247, 250, + 253, 256, 259, 262, 265, 268, 271, 274, 277, 280, 283, 295, + 298, 301, 304, 307, 310, 313, -1, +}; + +/* GSM TCH-HR */ +const struct osmo_conv_code gsm_conv_tch_hr = { + .N = 3, + .K = 7, + .len = 98, + .next_output = tch_hr_next_output, + .next_state = tch_hr_next_state, + .puncture = tch_hr_puncture, +}; + +/* GSM TCH-AFS12.2 */ +static const uint8_t tch_afs_12_2_next_output[][2] = { + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, +}; + +static const uint8_t tch_afs_12_2_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 9, 8 }, { 11, 10 }, { 13, 12 }, { 15, 14 }, + { 1, 0 }, { 3, 2 }, { 5, 4 }, { 7, 6 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, +}; + +static const uint8_t tch_afs_12_2_next_term_output[] = { + 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2, 0, 1, 0, 1, +}; + +static const uint8_t tch_afs_12_2_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static int tch_afs_12_2_puncture[] = { + 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 363, + 365, 369, 373, 377, 379, 381, 385, 389, 393, 395, 397, 401, + 405, 409, 411, 413, 417, 421, 425, 427, 429, 433, 437, 441, + 443, 445, 449, 453, 457, 459, 461, 465, 469, 473, 475, 477, + 481, 485, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, + -1, +}; + +/* GSM TCH-AFS12.2 */ +const struct osmo_conv_code gsm_conv_tch_afs_12_2 = { + .N = 2, + .K = 5, + .len = 250, + .next_output = tch_afs_12_2_next_output, + .next_state = tch_afs_12_2_next_state, + .next_term_output = tch_afs_12_2_next_term_output, + .next_term_state = tch_afs_12_2_next_term_state, + .puncture = tch_afs_12_2_puncture, +}; + +static const uint8_t tch_afs_10_2_next_output[][2] = { + { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 }, + { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 }, + { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 }, + { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 }, +}; + +static const uint8_t tch_afs_10_2_next_state[][2] = { + { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 }, + { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 }, + { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 }, + { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 }, +}; + +static const uint8_t tch_afs_10_2_next_term_output[] = { + 0, 5, 3, 6, 5, 0, 6, 3, 7, 2, 4, 1, 2, 7, 1, 4, +}; + +static const uint8_t tch_afs_10_2_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static int tch_afs_10_2_puncture[] = { + 1, 4, 7, 10, 16, 19, 22, 28, 31, 34, 40, 43, + 46, 52, 55, 58, 64, 67, 70, 76, 79, 82, 88, 91, + 94, 100, 103, 106, 112, 115, 118, 124, 127, 130, 136, 139, + 142, 148, 151, 154, 160, 163, 166, 172, 175, 178, 184, 187, + 190, 196, 199, 202, 208, 211, 214, 220, 223, 226, 232, 235, + 238, 244, 247, 250, 256, 259, 262, 268, 271, 274, 280, 283, + 286, 292, 295, 298, 304, 307, 310, 316, 319, 322, 325, 328, + 331, 334, 337, 340, 343, 346, 349, 352, 355, 358, 361, 364, + 367, 370, 373, 376, 379, 382, 385, 388, 391, 394, 397, 400, + 403, 406, 409, 412, 415, 418, 421, 424, 427, 430, 433, 436, + 439, 442, 445, 448, 451, 454, 457, 460, 463, 466, 469, 472, + 475, 478, 481, 484, 487, 490, 493, 496, 499, 502, 505, 508, + 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544, + 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580, + 583, 586, 589, 592, 595, 598, 601, 604, 607, 609, 610, 613, + 616, 619, 621, 622, 625, 627, 628, 631, 633, 634, 636, 637, + 639, 640, -1, +}; + +/* GSM TCH-AFS10.2 */ +const struct osmo_conv_code gsm_conv_tch_afs_10_2 = { + .N = 3, + .K = 5, + .len = 210, + .next_output = tch_afs_10_2_next_output, + .next_state = tch_afs_10_2_next_state, + .next_term_output = tch_afs_10_2_next_term_output, + .next_term_state = tch_afs_10_2_next_term_state, + .puncture = tch_afs_10_2_puncture, +}; + +static const uint8_t tch_afs_7_95_next_output[][2] = { + { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, + { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, + { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, + { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, + { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, + { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, + { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, + { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, + { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, + { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, + { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, + { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, + { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, + { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, + { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, + { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, +}; + +static const uint8_t tch_afs_7_95_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 5, 4 }, { 7, 6 }, + { 9, 8 }, { 11, 10 }, { 12, 13 }, { 14, 15 }, + { 16, 17 }, { 18, 19 }, { 21, 20 }, { 23, 22 }, + { 25, 24 }, { 27, 26 }, { 28, 29 }, { 30, 31 }, + { 33, 32 }, { 35, 34 }, { 36, 37 }, { 38, 39 }, + { 40, 41 }, { 42, 43 }, { 45, 44 }, { 47, 46 }, + { 49, 48 }, { 51, 50 }, { 52, 53 }, { 54, 55 }, + { 56, 57 }, { 58, 59 }, { 61, 60 }, { 63, 62 }, + { 1, 0 }, { 3, 2 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 13, 12 }, { 15, 14 }, + { 17, 16 }, { 19, 18 }, { 20, 21 }, { 22, 23 }, + { 24, 25 }, { 26, 27 }, { 29, 28 }, { 31, 30 }, + { 32, 33 }, { 34, 35 }, { 37, 36 }, { 39, 38 }, + { 41, 40 }, { 43, 42 }, { 44, 45 }, { 46, 47 }, + { 48, 49 }, { 50, 51 }, { 53, 52 }, { 55, 54 }, + { 57, 56 }, { 59, 58 }, { 60, 61 }, { 62, 63 }, +}; + +static const uint8_t tch_afs_7_95_next_term_output[] = { + 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5, 6, 5, 3, 0, + 4, 7, 1, 2, 1, 2, 4, 7, 7, 4, 2, 1, 2, 1, 7, 4, + 7, 4, 2, 1, 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7, + 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6, 5, 6, 0, 3, +}; + +static const uint8_t tch_afs_7_95_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, +}; + +static int tch_afs_7_95_puncture[] = { + 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310, + 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367, + 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415, + 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463, + 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505, + 506, 508, 509, 511, 512, -1, +}; + +/* GSM TCH-AFS7.95 */ +const struct osmo_conv_code gsm_conv_tch_afs_7_95 = { + .N = 3, + .K = 7, + .len = 165, + .next_output = tch_afs_7_95_next_output, + .next_state = tch_afs_7_95_next_state, + .next_term_output = tch_afs_7_95_next_term_output, + .next_term_state = tch_afs_7_95_next_term_state, + .puncture = tch_afs_7_95_puncture, +}; + +static const uint8_t tch_afs_7_4_next_output[][2] = { + { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 }, + { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 }, + { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 }, + { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 }, +}; + +static const uint8_t tch_afs_7_4_next_state[][2] = { + { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 }, + { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 }, + { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 }, + { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 }, +}; + +static const uint8_t tch_afs_7_4_next_term_output[] = { + 0, 5, 3, 6, 5, 0, 6, 3, 7, 2, 4, 1, 2, 7, 1, 4, +}; + +static const uint8_t tch_afs_7_4_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static int tch_afs_7_4_puncture[] = { + 0, 355, 361, 367, 373, 379, 385, 391, 397, 403, 409, 415, + 421, 427, 433, 439, 445, 451, 457, 460, 463, 466, 468, 469, + 471, 472, -1, +}; + +/* GSM TCH-AFS7.4 */ +const struct osmo_conv_code gsm_conv_tch_afs_7_4 = { + .N = 3, + .K = 5, + .len = 154, + .next_output = tch_afs_7_4_next_output, + .next_state = tch_afs_7_4_next_state, + .next_term_output = tch_afs_7_4_next_term_output, + .next_term_state = tch_afs_7_4_next_term_state, + .puncture = tch_afs_7_4_puncture, +}; + +static const uint8_t tch_afs_6_7_next_output[][2] = { + { 0, 15 }, { 4, 11 }, { 8, 7 }, { 12, 3 }, + { 4, 11 }, { 0, 15 }, { 12, 3 }, { 8, 7 }, + { 0, 15 }, { 4, 11 }, { 8, 7 }, { 12, 3 }, + { 4, 11 }, { 0, 15 }, { 12, 3 }, { 8, 7 }, +}; + +static const uint8_t tch_afs_6_7_next_state[][2] = { + { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 }, + { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 }, + { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 }, + { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 }, +}; + +static int tch_afs_6_7_puncture[] = { + 1, 3, 7, 11, 15, 27, 39, 55, 67, 79, 95, 107, + 119, 135, 147, 159, 175, 187, 199, 215, 227, 239, 255, 267, + 279, 287, 291, 295, 299, 303, 307, 311, 315, 319, 323, 327, + 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 369, 371, + 375, 377, 379, 383, 385, 387, 391, 393, 395, 399, 401, 403, + 407, 409, 411, 415, 417, 419, 423, 425, 427, 431, 433, 435, + 439, 441, 443, 447, 449, 451, 455, 457, 459, 463, 465, 467, + 471, 473, 475, 479, 481, 483, 487, 489, 491, 495, 497, 499, + 503, 505, 507, 511, 513, 515, 519, 521, 523, 527, 529, 531, + 535, 537, 539, 543, 545, 547, 549, 551, 553, 555, 557, 559, + 561, 563, 565, 567, 569, 571, 573, 575, + -1, +}; + +static const uint8_t tch_afs_6_7_next_term_output[] = { + 0, 11, 7, 12, 11, 0, 12, 7, 15, 4, 8, 3, 4, 15, 3, 8, +}; + +static const uint8_t tch_afs_6_7_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +/* GSM TCH-AFS6.7 */ +const struct osmo_conv_code gsm_conv_tch_afs_6_7 = { + .N = 4, + .K = 5, + .len = 140, + .next_output = tch_afs_6_7_next_output, + .next_state = tch_afs_6_7_next_state, + .next_term_output = tch_afs_6_7_next_term_output, + .next_term_state = tch_afs_6_7_next_term_state, + .puncture = tch_afs_6_7_puncture, +}; + +static const uint8_t tch_afs_5_9_next_output[][2] = { + { 0, 15 }, { 8, 7 }, { 4, 11 }, { 12, 3 }, + { 4, 11 }, { 12, 3 }, { 0, 15 }, { 8, 7 }, + { 8, 7 }, { 0, 15 }, { 12, 3 }, { 4, 11 }, + { 12, 3 }, { 4, 11 }, { 8, 7 }, { 0, 15 }, + { 8, 7 }, { 0, 15 }, { 12, 3 }, { 4, 11 }, + { 12, 3 }, { 4, 11 }, { 8, 7 }, { 0, 15 }, + { 0, 15 }, { 8, 7 }, { 4, 11 }, { 12, 3 }, + { 4, 11 }, { 12, 3 }, { 0, 15 }, { 8, 7 }, + { 0, 15 }, { 8, 7 }, { 4, 11 }, { 12, 3 }, + { 4, 11 }, { 12, 3 }, { 0, 15 }, { 8, 7 }, + { 8, 7 }, { 0, 15 }, { 12, 3 }, { 4, 11 }, + { 12, 3 }, { 4, 11 }, { 8, 7 }, { 0, 15 }, + { 8, 7 }, { 0, 15 }, { 12, 3 }, { 4, 11 }, + { 12, 3 }, { 4, 11 }, { 8, 7 }, { 0, 15 }, + { 0, 15 }, { 8, 7 }, { 4, 11 }, { 12, 3 }, + { 4, 11 }, { 12, 3 }, { 0, 15 }, { 8, 7 }, +}; + +static const uint8_t tch_afs_5_9_next_state[][2] = { + { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 }, + { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 }, + { 17, 16 }, { 18, 19 }, { 20, 21 }, { 23, 22 }, + { 24, 25 }, { 27, 26 }, { 29, 28 }, { 30, 31 }, + { 32, 33 }, { 35, 34 }, { 37, 36 }, { 38, 39 }, + { 41, 40 }, { 42, 43 }, { 44, 45 }, { 47, 46 }, + { 49, 48 }, { 50, 51 }, { 52, 53 }, { 55, 54 }, + { 56, 57 }, { 59, 58 }, { 61, 60 }, { 62, 63 }, + { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 }, + { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 }, + { 16, 17 }, { 19, 18 }, { 21, 20 }, { 22, 23 }, + { 25, 24 }, { 26, 27 }, { 28, 29 }, { 31, 30 }, + { 33, 32 }, { 34, 35 }, { 36, 37 }, { 39, 38 }, + { 40, 41 }, { 43, 42 }, { 45, 44 }, { 46, 47 }, + { 48, 49 }, { 51, 50 }, { 53, 52 }, { 54, 55 }, + { 57, 56 }, { 58, 59 }, { 60, 61 }, { 63, 62 }, +}; + +static const uint8_t tch_afs_5_9_next_term_output[] = { + 0, 7, 11, 12, 11, 12, 0, 7, 7, 0, 12, 11, 12, 11, 7, 0, + 8, 15, 3, 4, 3, 4, 8, 15, 15, 8, 4, 3, 4, 3, 15, 8, + 15, 8, 4, 3, 4, 3, 15, 8, 8, 15, 3, 4, 3, 4, 8, 15, + 7, 0, 12, 11, 12, 11, 7, 0, 0, 7, 11, 12, 11, 12, 0, 7, +}; + +static const uint8_t tch_afs_5_9_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, +}; + +static int tch_afs_5_9_puncture[] = { + 0, 1, 3, 5, 7, 11, 15, 31, 47, 63, 79, 95, + 111, 127, 143, 159, 175, 191, 207, 223, 239, 255, 271, 287, + 303, 319, 327, 331, 335, 343, 347, 351, 359, 363, 367, 375, + 379, 383, 391, 395, 399, 407, 411, 415, 423, 427, 431, 439, + 443, 447, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491, + 495, 499, 503, 507, 509, 511, 512, 513, 515, 516, 517, 519, + -1, +}; + +/* GSM TCH-AFS5.9 */ +const struct osmo_conv_code gsm_conv_tch_afs_5_9 = { + .N = 4, + .K = 7, + .len = 124, + .next_output = tch_afs_5_9_next_output, + .next_state = tch_afs_5_9_next_state, + .next_term_output = tch_afs_5_9_next_term_output, + .next_term_state = tch_afs_5_9_next_term_state, + .puncture = tch_afs_5_9_puncture, +}; + +static const uint8_t tch_afs_5_15_next_output[][2] = { + { 0, 31 }, { 4, 27 }, { 24, 7 }, { 28, 3 }, + { 4, 27 }, { 0, 31 }, { 28, 3 }, { 24, 7 }, + { 0, 31 }, { 4, 27 }, { 24, 7 }, { 28, 3 }, + { 4, 27 }, { 0, 31 }, { 28, 3 }, { 24, 7 }, +}; + +static const uint8_t tch_afs_5_15_next_state[][2] = { + { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 }, + { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 }, + { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 }, + { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 }, +}; + +static const uint8_t tch_afs_5_15_next_term_output[] = { + 0, 27, 7, 28, 27, 0, 28, 7, 31, 4, 24, 3, 4, 31, 3, 24, +}; + +static const uint8_t tch_afs_5_15_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static int tch_afs_5_15_puncture[] = { + 0, 4, 5, 9, 10, 14, 15, 20, 25, 30, 35, 40, + 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, + 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, + 290, 300, 310, 315, 320, 325, 330, 334, 335, 340, 344, 345, + 350, 354, 355, 360, 364, 365, 370, 374, 375, 380, 384, 385, + 390, 394, 395, 400, 404, 405, 410, 414, 415, 420, 424, 425, + 430, 434, 435, 440, 444, 445, 450, 454, 455, 460, 464, 465, + 470, 474, 475, 480, 484, 485, 490, 494, 495, 500, 504, 505, + 510, 514, 515, 520, 524, 525, 529, 530, 534, 535, 539, 540, + 544, 545, 549, 550, 554, 555, 559, 560, 564, -1, +}; + +/* GSM TCH-AFS5.15 */ +const struct osmo_conv_code gsm_conv_tch_afs_5_15 = { + .N = 5, + .K = 5, + .len = 109, + .next_output = tch_afs_5_15_next_output, + .next_state = tch_afs_5_15_next_state, + .next_term_output = tch_afs_5_15_next_term_output, + .next_term_state = tch_afs_5_15_next_term_state, + .puncture = tch_afs_5_15_puncture, +}; + +static const uint8_t tch_afs_4_75_next_output[][2] = { + { 0, 31 }, { 24, 7 }, { 4, 27 }, { 28, 3 }, + { 4, 27 }, { 28, 3 }, { 0, 31 }, { 24, 7 }, + { 24, 7 }, { 0, 31 }, { 28, 3 }, { 4, 27 }, + { 28, 3 }, { 4, 27 }, { 24, 7 }, { 0, 31 }, + { 24, 7 }, { 0, 31 }, { 28, 3 }, { 4, 27 }, + { 28, 3 }, { 4, 27 }, { 24, 7 }, { 0, 31 }, + { 0, 31 }, { 24, 7 }, { 4, 27 }, { 28, 3 }, + { 4, 27 }, { 28, 3 }, { 0, 31 }, { 24, 7 }, + { 0, 31 }, { 24, 7 }, { 4, 27 }, { 28, 3 }, + { 4, 27 }, { 28, 3 }, { 0, 31 }, { 24, 7 }, + { 24, 7 }, { 0, 31 }, { 28, 3 }, { 4, 27 }, + { 28, 3 }, { 4, 27 }, { 24, 7 }, { 0, 31 }, + { 24, 7 }, { 0, 31 }, { 28, 3 }, { 4, 27 }, + { 28, 3 }, { 4, 27 }, { 24, 7 }, { 0, 31 }, + { 0, 31 }, { 24, 7 }, { 4, 27 }, { 28, 3 }, + { 4, 27 }, { 28, 3 }, { 0, 31 }, { 24, 7 }, +}; + +static const uint8_t tch_afs_4_75_next_state[][2] = { + { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 }, + { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 }, + { 17, 16 }, { 18, 19 }, { 20, 21 }, { 23, 22 }, + { 24, 25 }, { 27, 26 }, { 29, 28 }, { 30, 31 }, + { 32, 33 }, { 35, 34 }, { 37, 36 }, { 38, 39 }, + { 41, 40 }, { 42, 43 }, { 44, 45 }, { 47, 46 }, + { 49, 48 }, { 50, 51 }, { 52, 53 }, { 55, 54 }, + { 56, 57 }, { 59, 58 }, { 61, 60 }, { 62, 63 }, + { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 }, + { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 }, + { 16, 17 }, { 19, 18 }, { 21, 20 }, { 22, 23 }, + { 25, 24 }, { 26, 27 }, { 28, 29 }, { 31, 30 }, + { 33, 32 }, { 34, 35 }, { 36, 37 }, { 39, 38 }, + { 40, 41 }, { 43, 42 }, { 45, 44 }, { 46, 47 }, + { 48, 49 }, { 51, 50 }, { 53, 52 }, { 54, 55 }, + { 57, 56 }, { 58, 59 }, { 60, 61 }, { 63, 62 }, +}; + +static const uint8_t tch_afs_4_75_next_term_output[] = { + 0, 7, 27, 28, 27, 28, 0, 7, 7, 0, 28, 27, 28, 27, 7, 0, + 24, 31, 3, 4, 3, 4, 24, 31, 31, 24, 4, 3, 4, 3, 31, 24, + 31, 24, 4, 3, 4, 3, 31, 24, 24, 31, 3, 4, 3, 4, 24, 31, + 7, 0, 28, 27, 28, 27, 7, 0, 0, 7, 27, 28, 27, 28, 0, 7, +}; + +static const uint8_t tch_afs_4_75_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, +}; + +static int tch_afs_4_75_puncture[] = { + 0, 1, 2, 4, 5, 7, 9, 15, 25, 35, 45, 55, + 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175, + 185, 195, 205, 215, 225, 235, 245, 255, 265, 275, 285, 295, + 305, 315, 325, 335, 345, 355, 365, 375, 385, 395, 400, 405, + 410, 415, 420, 425, 430, 435, 440, 445, 450, 455, 459, 460, + 465, 470, 475, 479, 480, 485, 490, 495, 499, 500, 505, 509, + 510, 515, 517, 519, 520, 522, 524, 525, 526, 527, 529, 530, + 531, 532, 534, -1, +}; + +/* GSM TCH-AFS4.75 */ +const struct osmo_conv_code gsm_conv_tch_afs_4_75 = { + .N = 5, + .K = 7, + .len = 101, + .next_output = tch_afs_4_75_next_output, + .next_state = tch_afs_4_75_next_state, + .next_term_output = tch_afs_4_75_next_term_output, + .next_term_state = tch_afs_4_75_next_term_state, + .puncture = tch_afs_4_75_puncture, +}; + +static const uint8_t tch_ahs_7_95_next_output[][2] = { + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, +}; + +static const uint8_t tch_ahs_7_95_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 9, 8 }, { 11, 10 }, { 13, 12 }, { 15, 14 }, + { 1, 0 }, { 3, 2 }, { 5, 4 }, { 7, 6 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, +}; + +static const uint8_t tch_ahs_7_95_next_term_output[] = { + 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2, 0, 1, 0, 1, +}; + +static const uint8_t tch_ahs_7_95_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static int tch_ahs_7_95_puncture[] = { + 1, 3, 5, 7, 11, 15, 19, 23, 27, 31, 35, 43, + 47, 51, 55, 59, 63, 67, 71, 79, 83, 87, 91, 95, + 99, 103, 107, 115, 119, 123, 127, 131, 135, 139, 143, 151, + 155, 159, 163, 167, 171, 175, 177, 179, 183, 185, 187, 191, + 193, 195, 197, 199, 203, 205, 207, 211, 213, 215, 219, 221, + 223, 227, 229, 231, 233, 235, 239, 241, 243, 247, 249, 251, + 255, 257, 259, 261, 263, 265, + -1, +}; + +/* GSM TCH-AHS7.95 */ +const struct osmo_conv_code gsm_conv_tch_ahs_7_95 = { + .N = 2, + .K = 5, + .len = 129, + .next_output = tch_ahs_7_95_next_output, + .next_state = tch_ahs_7_95_next_state, + .next_term_output = tch_ahs_7_95_next_term_output, + .next_term_state = tch_ahs_7_95_next_term_state, + .puncture = tch_ahs_7_95_puncture, +}; + +static const uint8_t tch_ahs_7_4_next_output[][2] = { + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, +}; + +static const uint8_t tch_ahs_7_4_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 9, 8 }, { 11, 10 }, { 13, 12 }, { 15, 14 }, + { 1, 0 }, { 3, 2 }, { 5, 4 }, { 7, 6 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, +}; + +static const uint8_t tch_ahs_7_4_next_term_output[] = { + 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2, 0, 1, 0, 1, +}; + +static const uint8_t tch_ahs_7_4_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static int tch_ahs_7_4_puncture[] = { + 1, 3, 7, 11, 19, 23, 27, 35, 39, 43, 51, 55, + 59, 67, 71, 75, 83, 87, 91, 99, 103, 107, 115, 119, + 123, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, + 175, 179, 183, 187, 191, 195, 199, 203, 207, 211, 215, 219, + 221, 223, 227, 229, 231, 235, 237, 239, 243, 245, 247, 251, + 253, 255, 257, 259, -1, +}; + +/* GSM TCH-AHS7.4 */ +const struct osmo_conv_code gsm_conv_tch_ahs_7_4 = { + .N = 2, + .K = 5, + .len = 126, + .next_output = tch_ahs_7_4_next_output, + .next_state = tch_ahs_7_4_next_state, + .next_term_output = tch_ahs_7_4_next_term_output, + .next_term_state = tch_ahs_7_4_next_term_state, + .puncture = tch_ahs_7_4_puncture, +}; + +static const uint8_t tch_ahs_6_7_next_output[][2] = { + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, +}; + +static const uint8_t tch_ahs_6_7_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 9, 8 }, { 11, 10 }, { 13, 12 }, { 15, 14 }, + { 1, 0 }, { 3, 2 }, { 5, 4 }, { 7, 6 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, +}; + +static const uint8_t tch_ahs_6_7_next_term_output[] = { + 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2, 0, 1, 0, 1, +}; + +static const uint8_t tch_ahs_6_7_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static int tch_ahs_6_7_puncture[] = { + 1, 3, 9, 19, 29, 39, 49, 59, 69, 79, 89, 99, + 109, 119, 129, 139, 149, 159, 167, 169, 177, 179, 187, 189, + 197, 199, 203, 207, 209, 213, 217, 219, 223, 227, 229, 231, + 233, 235, 237, 239, -1, +}; + +/* GSM TCH-AHS6.7 */ +const struct osmo_conv_code gsm_conv_tch_ahs_6_7 = { + .N = 2, + .K = 5, + .len = 116, + .next_output = tch_ahs_6_7_next_output, + .next_state = tch_ahs_6_7_next_state, + .next_term_output = tch_ahs_6_7_next_term_output, + .next_term_state = tch_ahs_6_7_next_term_state, + .puncture = tch_ahs_6_7_puncture, +}; + +static const uint8_t tch_ahs_5_9_next_output[][2] = { + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, +}; + +static const uint8_t tch_ahs_5_9_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 9, 8 }, { 11, 10 }, { 13, 12 }, { 15, 14 }, + { 1, 0 }, { 3, 2 }, { 5, 4 }, { 7, 6 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, +}; + +static const uint8_t tch_ahs_5_9_next_term_output[] = { + 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2, 0, 1, 0, 1, +}; + +static const uint8_t tch_ahs_5_9_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static int tch_ahs_5_9_puncture[] = { + 1, 15, 71, 127, 139, 151, 163, 175, 187, 195, 203, 211, + 215, 219, 221, 223, -1, +}; + +/* GSM TCH-AHS5.9 */ +const struct osmo_conv_code gsm_conv_tch_ahs_5_9 = { + .N = 2, + .K = 5, + .len = 108, + .next_output = tch_ahs_5_9_next_output, + .next_state = tch_ahs_5_9_next_state, + .next_term_output = tch_ahs_5_9_next_term_output, + .next_term_state = tch_ahs_5_9_next_term_state, + .puncture = tch_ahs_5_9_puncture, +}; + +static const uint8_t tch_ahs_5_15_next_output[][2] = { + { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 }, + { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 }, + { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 }, + { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 }, +}; + +static const uint8_t tch_ahs_5_15_next_state[][2] = { + { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 }, + { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 }, + { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 }, + { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 }, +}; + +static const uint8_t tch_ahs_5_15_next_term_output[] = { + 0, 5, 3, 6, 5, 0, 6, 3, 7, 2, 4, 1, 2, 7, 1, 4, +}; + +static const uint8_t tch_ahs_5_15_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, +}; + +static int tch_ahs_5_15_puncture[] = { + 0, 1, 3, 4, 6, 9, 12, 15, 18, 21, 27, 33, + 39, 45, 51, 54, 57, 63, 69, 75, 81, 87, 90, 93, + 99, 105, 111, 117, 123, 126, 129, 135, 141, 147, 153, 159, + 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 192, 195, + 198, 201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231, + 234, 237, 240, 243, 244, 246, 249, 252, 255, 256, 258, 261, + 264, 267, 268, 270, 273, 276, 279, 280, 282, 285, 288, 289, + 291, 294, 295, 297, 298, 300, 301, -1, +}; + +/* GSM TCH-AHS5.15 */ +const struct osmo_conv_code gsm_conv_tch_ahs_5_15 = { + .N = 3, + .K = 5, + .len = 97, + .next_output = tch_ahs_5_15_next_output, + .next_state = tch_ahs_5_15_next_state, + .next_term_output = tch_ahs_5_15_next_term_output, + .next_term_state = tch_ahs_5_15_next_term_state, + .puncture = tch_ahs_5_15_puncture, +}; + +static const uint8_t tch_ahs_4_75_next_output[][2] = { + { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, + { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, + { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, + { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, + { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, + { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, + { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, + { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, + { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, + { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, + { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, + { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, + { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, + { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, + { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, + { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, +}; + +static const uint8_t tch_ahs_4_75_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 5, 4 }, { 7, 6 }, + { 9, 8 }, { 11, 10 }, { 12, 13 }, { 14, 15 }, + { 16, 17 }, { 18, 19 }, { 21, 20 }, { 23, 22 }, + { 25, 24 }, { 27, 26 }, { 28, 29 }, { 30, 31 }, + { 33, 32 }, { 35, 34 }, { 36, 37 }, { 38, 39 }, + { 40, 41 }, { 42, 43 }, { 45, 44 }, { 47, 46 }, + { 49, 48 }, { 51, 50 }, { 52, 53 }, { 54, 55 }, + { 56, 57 }, { 58, 59 }, { 61, 60 }, { 63, 62 }, + { 1, 0 }, { 3, 2 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 13, 12 }, { 15, 14 }, + { 17, 16 }, { 19, 18 }, { 20, 21 }, { 22, 23 }, + { 24, 25 }, { 26, 27 }, { 29, 28 }, { 31, 30 }, + { 32, 33 }, { 34, 35 }, { 37, 36 }, { 39, 38 }, + { 41, 40 }, { 43, 42 }, { 44, 45 }, { 46, 47 }, + { 48, 49 }, { 50, 51 }, { 53, 52 }, { 55, 54 }, + { 57, 56 }, { 59, 58 }, { 60, 61 }, { 62, 63 }, +}; + +static const uint8_t tch_ahs_4_75_next_term_output[] = { + 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5, 6, 5, 3, 0, + 4, 7, 1, 2, 1, 2, 4, 7, 7, 4, 2, 1, 2, 1, 7, 4, + 7, 4, 2, 1, 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7, + 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6, 5, 6, 0, 3, +}; + +static const uint8_t tch_ahs_4_75_next_term_state[] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, +}; + +static int tch_ahs_4_75_puncture[] = { + 1, 2, 4, 5, 7, 8, 10, 13, 16, 22, 28, 34, + 40, 46, 52, 58, 64, 70, 76, 82, 88, 94, 100, 106, + 112, 118, 124, 130, 136, 142, 148, 151, 154, 160, 163, 166, + 172, 175, 178, 184, 187, 190, 196, 199, 202, 208, 211, 214, + 220, 223, 226, 232, 235, 238, 241, 244, 247, 250, 253, 256, + 259, 262, 265, 268, 271, 274, 275, 277, 278, 280, 281, 283, + 284, -1, +}; + +/* GSM TCH-AHS4.75 */ +const struct osmo_conv_code gsm_conv_tch_ahs_4_75 = { + .N = 3, + .K = 7, + .len = 89, + .next_output = tch_ahs_4_75_next_output, + .next_state = tch_ahs_4_75_next_state, + .next_term_output = tch_ahs_4_75_next_term_output, + .next_term_state = tch_ahs_4_75_next_term_state, + .puncture = tch_ahs_4_75_puncture, +}; + +static const uint8_t wimax_fch_next_output[][2] = { + { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 }, + { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 }, + { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 }, + { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 }, + { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 }, + { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 }, + { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 }, + { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 }, + { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 }, + { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 }, + { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 }, + { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 }, + { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 }, + { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 }, + { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 }, + { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 }, +}; + +static const uint8_t wimax_fch_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, + { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, + { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, + { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, + { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, + { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, + { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, + { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, + { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, + { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, + { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, + { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, + { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, +}; + +/* WiMax FCH */ +const struct osmo_conv_code wimax_conv_fch = { + .N = 2, + .K = 7, + .len = 48, + .term = CONV_TERM_TAIL_BITING, + .next_output = wimax_fch_next_output, + .next_state = wimax_fch_next_state, +}; + +static const uint8_t gmr1_tch3_speech_next_output[][2] = { + { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, + { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, + { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 }, + { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 }, + { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 }, + { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 }, + { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 }, + { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, + { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 }, + { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, + { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 }, + { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 }, + { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 }, + { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 }, +}; + +static const uint8_t gmr1_tch3_speech_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, + { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, + { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, + { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, + { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, + { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, + { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, + { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, + { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, + { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, + { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, + { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, + { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, +}; + +static const int gmr1_tch3_speech_puncture[] = { + 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, + 51, 55, 59, 63, 67, 71, 75, 79, 83, 87, 91, 95, + -1, +}; + +/* GMR-1 TCH3 */ +const struct osmo_conv_code gmr1_conv_tch3_speech = { + .N = 2, + .K = 7, + .len = 48, + .term = CONV_TERM_TAIL_BITING, + .next_output = gmr1_tch3_speech_next_output, + .next_state = gmr1_tch3_speech_next_state, + .puncture = gmr1_tch3_speech_puncture, +}; + +static const uint8_t lte_pbch_next_output[][2] = { + { 0, 7 }, { 3, 4 }, { 7, 0 }, { 4 , 3 }, + { 6, 1 }, { 5, 2 }, { 1, 6 }, { 2 , 5 }, + { 1, 6 }, { 2, 5 }, { 6, 1 }, { 5 , 2 }, + { 7, 0 }, { 4, 3 }, { 0, 7 }, { 3 , 4 }, + { 4, 3 }, { 7, 0 }, { 3, 4 }, { 0 , 7 }, + { 2, 5 }, { 1, 6 }, { 5, 2 }, { 6 , 1 }, + { 5, 2 }, { 6, 1 }, { 2, 5 }, { 1 , 6 }, + { 3, 4 }, { 0, 7 }, { 4, 3 }, { 7 , 0 }, + { 7, 0 }, { 4, 3 }, { 0, 7 }, { 3 , 4 }, + { 1, 6 }, { 2, 5 }, { 6, 1 }, { 5 , 2 }, + { 6, 1 }, { 5, 2 }, { 1, 6 }, { 2 , 5 }, + { 0, 7 }, { 3, 4 }, { 7, 0 }, { 4 , 3 }, + { 3, 4 }, { 0, 7 }, { 4, 3 }, { 7 , 0 }, + { 5, 2 }, { 6, 1 }, { 2, 5 }, { 1 , 6 }, + { 2, 5 }, { 1, 6 }, { 5, 2 }, { 6 , 1 }, + { 4, 3 }, { 7, 0 }, { 3, 4 }, { 0 , 7 }, +}; + +static const uint8_t lte_pbch_next_state[][2] = { + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, + { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, + { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, + { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, + { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, + { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, + { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, + { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, + { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, + { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, + { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, + { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, + { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, + { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, + { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, +}; + +/* LTE PBCH */ +const struct osmo_conv_code lte_conv_pbch = { + .N = 3, + .K = 7, + .len = 40, + .term = CONV_TERM_TAIL_BITING, + .next_output = lte_pbch_next_output, + .next_state = lte_pbch_next_state, +}; + +/* Truncated code */ +const struct osmo_conv_code conv_trunc = { + .N = 2, + .K = 5, + .len = 224, + .term = CONV_TERM_TRUNCATION, + .next_output = xcch_next_output, + .next_state = xcch_next_state, +}; diff --git a/tests/conv/codes.h b/tests/conv/codes.h new file mode 100644 index 0000000..e7c06cb --- /dev/null +++ b/tests/conv/codes.h @@ -0,0 +1,30 @@ +#ifndef TEST_CODES_H +#define TEST_CODES_H + +const struct osmo_conv_code gsm_conv_xcch; +const struct osmo_conv_code gsm_conv_cs2; +const struct osmo_conv_code gsm_conv_cs3; +const struct osmo_conv_code gsm_conv_rach; +const struct osmo_conv_code gsm_conv_sch; +const struct osmo_conv_code gsm_conv_tch_fr; +const struct osmo_conv_code gsm_conv_tch_hr; +const struct osmo_conv_code gsm_conv_tch_afs_12_2; +const struct osmo_conv_code gsm_conv_tch_afs_10_2; +const struct osmo_conv_code gsm_conv_tch_afs_7_95; +const struct osmo_conv_code gsm_conv_tch_afs_7_4; +const struct osmo_conv_code gsm_conv_tch_afs_6_7; +const struct osmo_conv_code gsm_conv_tch_afs_5_9; +const struct osmo_conv_code gsm_conv_tch_afs_5_15; +const struct osmo_conv_code gsm_conv_tch_afs_4_75; +const struct osmo_conv_code gsm_conv_tch_ahs_7_95; +const struct osmo_conv_code gsm_conv_tch_ahs_7_4; +const struct osmo_conv_code gsm_conv_tch_ahs_6_7; +const struct osmo_conv_code gsm_conv_tch_ahs_5_9; +const struct osmo_conv_code gsm_conv_tch_ahs_5_15; +const struct osmo_conv_code gsm_conv_tch_ahs_4_75; +const struct osmo_conv_code wimax_conv_fch; +const struct osmo_conv_code gmr1_conv_tch3_speech; +const struct osmo_conv_code lte_conv_pbch; +const struct osmo_conv_code conv_trunc; + +#endif /* TEST_CODES_H */ diff --git a/tests/conv/conv_test.c b/tests/conv/conv_test.c index d9440f9..89ffdb8 100644 --- a/tests/conv/conv_test.c +++ b/tests/conv/conv_test.c @@ -7,230 +7,10 @@ #include #include -#define MAX_LEN_BITS 512 -#define MAX_LEN_BYTES (512/8) - - -/* ------------------------------------------------------------------------ */ -/* Test codes */ -/* ------------------------------------------------------------------------ */ - -/* GSM xCCH -> Non-recursive code, flushed, not punctured */ -static const uint8_t conv_gsm_xcch_next_output[][2] = { - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, - { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 }, -}; - -static const uint8_t conv_gsm_xcch_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, -}; - -static const struct osmo_conv_code conv_gsm_xcch = { - .N = 2, - .K = 5, - .len = 224, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, -}; - - -/* GSM TCH/AFS 7.95 -> Recursive code, flushed, with puncturing */ -static const uint8_t conv_gsm_tch_afs_7_95_next_output[][2] = { - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 }, - { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 }, - { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 }, - { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 }, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 5, 4 }, { 7, 6 }, - { 9, 8 }, { 11, 10 }, { 12, 13 }, { 14, 15 }, - { 16, 17 }, { 18, 19 }, { 21, 20 }, { 23, 22 }, - { 25, 24 }, { 27, 26 }, { 28, 29 }, { 30, 31 }, - { 33, 32 }, { 35, 34 }, { 36, 37 }, { 38, 39 }, - { 40, 41 }, { 42, 43 }, { 45, 44 }, { 47, 46 }, - { 49, 48 }, { 51, 50 }, { 52, 53 }, { 54, 55 }, - { 56, 57 }, { 58, 59 }, { 61, 60 }, { 63, 62 }, - { 1, 0 }, { 3, 2 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 13, 12 }, { 15, 14 }, - { 17, 16 }, { 19, 18 }, { 20, 21 }, { 22, 23 }, - { 24, 25 }, { 26, 27 }, { 29, 28 }, { 31, 30 }, - { 32, 33 }, { 34, 35 }, { 37, 36 }, { 39, 38 }, - { 41, 40 }, { 43, 42 }, { 44, 45 }, { 46, 47 }, - { 48, 49 }, { 50, 51 }, { 53, 52 }, { 55, 54 }, - { 57, 56 }, { 59, 58 }, { 60, 61 }, { 62, 63 }, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_term_output[] = { - 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5, 6, 5, 3, 0, - 4, 7, 1, 2, 1, 2, 4, 7, 7, 4, 2, 1, 2, 1, 7, 4, - 7, 4, 2, 1, 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7, - 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6, 5, 6, 0, 3, -}; - -static const uint8_t conv_gsm_tch_afs_7_95_next_term_state[] = { - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, -}; - -static int conv_gsm_tch_afs_7_95_puncture[] = { - 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310, - 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367, - 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415, - 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463, - 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505, - 506, 508, 509, 511, 512, - -1, /* end */ -}; - -static const struct osmo_conv_code conv_gsm_tch_afs_7_95 = { - .N = 3, - .K = 7, - .len = 165, - .term = CONV_TERM_FLUSH, - .next_output = conv_gsm_tch_afs_7_95_next_output, - .next_state = conv_gsm_tch_afs_7_95_next_state, - .next_term_output = conv_gsm_tch_afs_7_95_next_term_output, - .next_term_state = conv_gsm_tch_afs_7_95_next_term_state, - .puncture = conv_gsm_tch_afs_7_95_puncture, -}; - - -/* GMR-1 TCH3 Speech -> Non recursive code, tail-biting, punctured */ -static const uint8_t conv_gmr1_tch3_speech_next_output[][2] = { - { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, - { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 }, - { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, - { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 }, - { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 }, - { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 }, - { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 }, - { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 }, - { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 }, - { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, - { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 }, - { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, - { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 }, - { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 }, - { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 }, - { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 }, -}; - -static const uint8_t conv_gmr1_tch3_speech_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, - { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, - { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, - { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, - { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, - { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, - { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, - { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, - { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, - { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, - { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, - { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, - { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, -}; - -static const int conv_gmr1_tch3_speech_puncture[] = { - 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, - 51, 55, 59, 63, 67, 71, 75, 79, 83, 87, 91, 95, - -1, /* end */ -}; - -static const struct osmo_conv_code conv_gmr1_tch3_speech = { - .N = 2, - .K = 7, - .len = 48, - .term = CONV_TERM_TAIL_BITING, - .next_output = conv_gmr1_tch3_speech_next_output, - .next_state = conv_gmr1_tch3_speech_next_state, - .puncture = conv_gmr1_tch3_speech_puncture, -}; - - -/* WiMax FCH -> Non recursive code, tail-biting, non-punctured */ -static const uint8_t conv_wimax_fch_next_output[][2] = { - { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 }, - { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 }, - { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 }, - { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 }, - { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 }, - { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 }, - { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 }, - { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 }, - { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 }, - { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 }, - { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 }, - { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 }, - { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 }, - { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 }, - { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 }, - { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 }, -}; - -static const uint8_t conv_wimax_fch_next_state[][2] = { - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, - { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, - { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, - { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, - { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, - { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, - { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, - { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, - { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 }, - { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 }, - { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 }, - { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 }, - { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 }, - { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 }, - { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 }, -}; - -static const struct osmo_conv_code conv_wimax_fch = { - .N = 2, - .K = 7, - .len = 48, - .term = CONV_TERM_TAIL_BITING, - .next_output = conv_wimax_fch_next_output, - .next_state = conv_wimax_fch_next_state, -}; - - -/* Random code -> Non recursive code, direct truncation, non-punctured */ -static const struct osmo_conv_code conv_trunc = { - .N = 2, - .K = 5, - .len = 224, - .term = CONV_TERM_TRUNCATION, - .next_output = conv_gsm_xcch_next_output, - .next_state = conv_gsm_xcch_next_state, -}; +#include "codes.h" +#define MAX_LEN_BITS 1024 +#define MAX_LEN_BYTES (1024/8) /* ------------------------------------------------------------------------ */ /* Test vectors */ @@ -249,7 +29,7 @@ struct conv_test_vector { static const struct conv_test_vector tests[] = { { .name = "GSM xCCH (non-recursive, flushed, not punctured)", - .code = &conv_gsm_xcch, + .code = &gsm_conv_xcch, .in_len = 224, .out_len = 456, .has_vec = 1, @@ -267,8 +47,62 @@ static const struct conv_test_vector tests[] = { 0x8f }, }, { + .name = "GPRS CS2 (non-recursive, flushed, not punctured)", + .code = &gsm_conv_cs2, + .in_len = 290, + .out_len = 588, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GPRS CS3 (non-recursive, flushed, not punctured)", + .code = &gsm_conv_cs3, + .in_len = 334, + .out_len = 676, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM RACH (non-recursive, flushed, not punctured)", + .code = &gsm_conv_rach, + .in_len = 14, + .out_len = 36, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/FR (non-recursive, flushed, not punctured)", + .code = &gsm_conv_tch_fr, + .in_len = 185, + .out_len = 378, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/AFS 12.2 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_afs_12_2, + .in_len = 250, + .out_len = 448, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/AFS 10.2 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_afs_10_2, + .in_len = 210, + .out_len = 448, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)", - .code = &conv_gsm_tch_afs_7_95, + .code = &gsm_conv_tch_afs_7_95, .in_len = 165, .out_len = 448, .has_vec = 1, @@ -284,8 +118,89 @@ static const struct conv_test_vector tests[] = { 0xa1, 0x5f, 0x45, 0x4a, 0xfb, 0xe6, 0x5a, 0x9c }, }, { + .name = "GSM TCH/AFS 7.4 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_afs_7_4, + .in_len = 154, + .out_len = 448, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/AFS 6.7 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_afs_6_7, + .in_len = 140, + .out_len = 448, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/AFS 5.9 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_afs_5_9, + .in_len = 124, + .out_len = 448, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/AHS 7.95 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_ahs_7_95, + .in_len = 129, + .out_len = 188, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/AHS 7.4 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_ahs_7_4, + .in_len = 126, + .out_len = 196, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/AHS 6.7 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_ahs_6_7, + .in_len = 116, + .out_len = 200, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/AHS 5.9 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_ahs_5_9, + .in_len = 108, + .out_len = 208, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/AHS 5.15 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_ahs_5_15, + .in_len = 97, + .out_len = 212, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { + .name = "GSM TCH/AHS 4.75 (recursive, flushed, punctured)", + .code = &gsm_conv_tch_ahs_4_75, + .in_len = 89, + .out_len = 212, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { .name = "GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)", - .code = &conv_gmr1_tch3_speech, + .code = &gmr1_conv_tch3_speech, .in_len = 48, .out_len = 72, .has_vec = 1, @@ -294,7 +209,7 @@ static const struct conv_test_vector tests[] = { }, { .name = "WiMax FCH (non-recursive, tail-biting, not punctured)", - .code = &conv_wimax_fch, + .code = &wimax_conv_fch, .in_len = 48, .out_len = 96, .has_vec = 1, @@ -303,6 +218,15 @@ static const struct conv_test_vector tests[] = { 0x8a, 0xed, 0x21, 0xed }, }, { + .name = "LTE PBCH (non-recursive, tail-biting, non-punctured)", + .code = <e_conv_pbch, + .in_len = 40, + .out_len = 120, + .has_vec = 0, + .vec_in = { }, + .vec_out = { }, + }, + { .name = "??? (non-recursive, direct truncation, not punctured)", .code = &conv_trunc, .in_len = 224, diff --git a/tests/conv/conv_test.ok b/tests/conv/conv_test.ok index 2122961..95ea671 100644 --- a/tests/conv/conv_test.ok +++ b/tests/conv/conv_test.ok @@ -9,6 +9,54 @@ [..] Encoding / Decoding cycle : OK [..] Encoding / Decoding cycle : OK +[+] Testing: GPRS CS2 (non-recursive, flushed, not punctured) +[.] Input length : ret = 290 exp = 290 -> OK +[.] Output length : ret = 588 exp = 588 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GPRS CS3 (non-recursive, flushed, not punctured) +[.] Input length : ret = 334 exp = 334 -> OK +[.] Output length : ret = 676 exp = 676 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM RACH (non-recursive, flushed, not punctured) +[.] Input length : ret = 14 exp = 14 -> OK +[.] Output length : ret = 36 exp = 36 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/FR (non-recursive, flushed, not punctured) +[.] Input length : ret = 185 exp = 185 -> OK +[.] Output length : ret = 378 exp = 378 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/AFS 12.2 (recursive, flushed, punctured) +[.] Input length : ret = 250 exp = 250 -> OK +[.] Output length : ret = 448 exp = 448 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/AFS 10.2 (recursive, flushed, punctured) +[.] Input length : ret = 210 exp = 210 -> OK +[.] Output length : ret = 448 exp = 448 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + [+] Testing: GSM TCH/AFS 7.95 (recursive, flushed, punctured) [.] Input length : ret = 165 exp = 165 -> OK [.] Output length : ret = 448 exp = 448 -> OK @@ -20,6 +68,78 @@ [..] Encoding / Decoding cycle : OK [..] Encoding / Decoding cycle : OK +[+] Testing: GSM TCH/AFS 7.4 (recursive, flushed, punctured) +[.] Input length : ret = 154 exp = 154 -> OK +[.] Output length : ret = 448 exp = 448 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/AFS 6.7 (recursive, flushed, punctured) +[.] Input length : ret = 140 exp = 140 -> OK +[.] Output length : ret = 448 exp = 448 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/AFS 5.9 (recursive, flushed, punctured) +[.] Input length : ret = 124 exp = 124 -> OK +[.] Output length : ret = 448 exp = 448 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/AHS 7.95 (recursive, flushed, punctured) +[.] Input length : ret = 129 exp = 129 -> OK +[.] Output length : ret = 188 exp = 188 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/AHS 7.4 (recursive, flushed, punctured) +[.] Input length : ret = 126 exp = 126 -> OK +[.] Output length : ret = 196 exp = 196 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/AHS 6.7 (recursive, flushed, punctured) +[.] Input length : ret = 116 exp = 116 -> OK +[.] Output length : ret = 200 exp = 200 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/AHS 5.9 (recursive, flushed, punctured) +[.] Input length : ret = 108 exp = 108 -> OK +[.] Output length : ret = 208 exp = 208 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/AHS 5.15 (recursive, flushed, punctured) +[.] Input length : ret = 97 exp = 97 -> OK +[.] Output length : ret = 212 exp = 212 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + +[+] Testing: GSM TCH/AHS 4.75 (recursive, flushed, punctured) +[.] Input length : ret = 89 exp = 89 -> OK +[.] Output length : ret = 212 exp = 212 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + [+] Testing: GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured) [.] Input length : ret = 48 exp = 48 -> OK [.] Output length : ret = 72 exp = 72 -> OK @@ -42,6 +162,14 @@ [..] Encoding / Decoding cycle : OK [..] Encoding / Decoding cycle : OK +[+] Testing: LTE PBCH (non-recursive, tail-biting, non-punctured) +[.] Input length : ret = 40 exp = 40 -> OK +[.] Output length : ret = 120 exp = 120 -> OK +[.] Random vector checks: +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK +[..] Encoding / Decoding cycle : OK + [+] Testing: ??? (non-recursive, direct truncation, not punctured) [.] Input length : ret = 224 exp = 224 -> OK [.] Output length : ret = 448 exp = 448 -> OK -- 1.9.0 From tom at tsou.cc Tue Apr 29 04:13:52 2014 From: tom at tsou.cc (Thomas Tsou) Date: Tue, 29 Apr 2014 00:13:52 -0400 Subject: [PATCH 0/4] core/conv: Fast Viterbi decoding Message-ID: <20140429041352.GA5213@phenom.hsd1.va.comcast.net> Hi all, This patch set adds to libosmocore an optimized Viterbi decodeer for architecture specific (Intel SSE) and non-specific cases. The implementation covers codes with constraint lengths of K=5 and K=7 and rates 1/4 to 3/4, which make up the majority of GSM use cases. Speedup from the current implementation is in the range of 5 to 20 depending on the processor and code type. API is unchanged. Tested on Haswell (i7-4770K) and Atom (D2550). Additional test codes from osmo-bts are included. Further tests for AWGN bit-error-rate and benchmarks can be found in the following repository. https://github.com/ttsou/osmo-conv-test Here are some examples. Bit error test for GPRS CS2 with SNR of 5 dB and 100000 bursts. $ ./conv_test -c 2 -e -r 5 -i 100000 ================================================= [+] Testing: GPRS CS2 [.] Specs: (N=2, K=5, non-recursive, flushed, not punctured) [.] Input length : ret = 290 exp = 290 -> OK [.] Output length : ret = 588 exp = 588 -> OK [.] BER tests: [..] Testing base: [..] Input BER.......................... 0.042443 [..] Output BER......................... 0.000006 [..] Output FER......................... 0.001350 (135) [..] Testing SIMD: [..] Input BER.......................... 0.042460 [..] Output BER......................... 0.000005 [..] Output FER......................... 0.001240 (124) Timed AFS benchmark with 8 threads and 100000 bursts per thread. $ ./conv_test -b -c 10 -j 8 -i 100000 ================================================= [+] Testing: GSM TCH/AFS 6.7 [.] Specs: (N=4, K=5, recursive, flushed, punctured) [.] Input length : ret = 140 exp = 140 -> OK [.] Output length : ret = 448 exp = 448 -> OK [.] Performance benchmark: [..] Encoding / Decoding 800000 bursts on 8 thread(s): [..] Testing base: [..] Elapsed time....................... 4.320001 secs [..] Rate............................... 25.925920 Mbps [..] Testing SIMD: [..] Elapsed time....................... 0.458272 secs [..] Rate............................... 244.396341 Mbps [..] Speedup............................ 9.426718 -TT From alexander.chemeris at gmail.com Tue Apr 29 06:09:44 2014 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 29 Apr 2014 10:09:44 +0400 Subject: [PATCH 0/4] core/conv: Fast Viterbi decoding In-Reply-To: <20140429041352.GA5213@phenom.hsd1.va.comcast.net> References: <20140429041352.GA5213@phenom.hsd1.va.comcast.net> Message-ID: Hi Thomas, Thank you for submitting this patch at. Finally :) It promises a very good improvement for the OsmoBTS performance. May I suggest you to check in the test cases into a test or contrib directory of libosmocore? This will help ensure that we do not loose them and that they stay in sync with the code. Ideally, we should also run validity checks on "make check" as well. 29 ???. 2014 ?. 8:13 ???????????? "Thomas Tsou" ???????: > > Hi all, > > This patch set adds to libosmocore an optimized Viterbi decodeer for > architecture specific (Intel SSE) and non-specific cases. The > implementation covers codes with constraint lengths of K=5 and K=7 and > rates 1/4 to 3/4, which make up the majority of GSM use cases. Speedup > from the current implementation is in the range of 5 to 20 depending on > the processor and code type. API is unchanged. > > Tested on Haswell (i7-4770K) and Atom (D2550). Additional test codes > from osmo-bts are included. Further tests for AWGN bit-error-rate > and benchmarks can be found in the following repository. > > https://github.com/ttsou/osmo-conv-test > > Here are some examples. > > Bit error test for GPRS CS2 with SNR of 5 dB and 100000 bursts. > > $ ./conv_test -c 2 -e -r 5 -i 100000 > > ================================================= > [+] Testing: GPRS CS2 > [.] Specs: (N=2, K=5, non-recursive, flushed, not punctured) > [.] Input length : ret = 290 exp = 290 -> OK > [.] Output length : ret = 588 exp = 588 -> OK > > [.] BER tests: > [..] Testing base: > [..] Input BER.......................... 0.042443 > [..] Output BER......................... 0.000006 > [..] Output FER......................... 0.001350 (135) > [..] Testing SIMD: > [..] Input BER.......................... 0.042460 > [..] Output BER......................... 0.000005 > [..] Output FER......................... 0.001240 (124) > > Timed AFS benchmark with 8 threads and 100000 bursts per thread. > > $ ./conv_test -b -c 10 -j 8 -i 100000 > > ================================================= > [+] Testing: GSM TCH/AFS 6.7 > [.] Specs: (N=4, K=5, recursive, flushed, punctured) > [.] Input length : ret = 140 exp = 140 -> OK > [.] Output length : ret = 448 exp = 448 -> OK > > [.] Performance benchmark: > [..] Encoding / Decoding 800000 bursts on 8 thread(s): > [..] Testing base: > [..] Elapsed time....................... 4.320001 secs > [..] Rate............................... 25.925920 Mbps > [..] Testing SIMD: > [..] Elapsed time....................... 0.458272 secs > [..] Rate............................... 244.396341 Mbps > [..] Speedup............................ 9.426718 > > -TT -------------- next part -------------- An HTML attachment was scrubbed... URL: From jerlbeck at sysmocom.de Tue Apr 29 10:40:21 2014 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 29 Apr 2014 12:40:21 +0200 Subject: [PATCH] contrib/rtp: Use payload data files directly by gen_rtp_header Message-ID: <1398768021-27350-1-git-send-email-jerlbeck@sysmocom.de> This adds a --frame-size option to read payload binary files with a fixed frame size directly. The file must not contain RTP headers. In addition '--rate' and '--duration' can be used to configure the timing. Sponsored-by: On-Waves ehf --- openbsc/contrib/rtp/gen_rtp_header.erl | 34 ++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/openbsc/contrib/rtp/gen_rtp_header.erl b/openbsc/contrib/rtp/gen_rtp_header.erl index cc4c61c..47839c1 100755 --- a/openbsc/contrib/rtp/gen_rtp_header.erl +++ b/openbsc/contrib/rtp/gen_rtp_header.erl @@ -28,6 +28,7 @@ main(Args) -> DefaultOpts = [{format, state}, {ssrc, 16#11223344}, + {rate, 8000}, {pt, 98}], {PosArgs, Opts} = getopts_checked(Args, DefaultOpts), log(debug, fun (Dev) -> @@ -144,7 +145,8 @@ show_help() -> "Options:~n" ++ " -h, --help this text~n" ++ " --version show version info~n" ++ - " -i, --file=FILE reads payload from state file~n" ++ + " -i, --file=FILE reads payload from file (state format by default)~n" ++ + " -f, --frame-size=N read payload as binary frames of size N instead~n" ++ " -p, --payload=HEX set constant payload~n" ++ " --verbose=N set verbosity~n" ++ " -v increase verbosity~n" ++ @@ -153,6 +155,8 @@ show_help() -> " --format=carray use a C array for output~n" ++ " -s, --ssrc=SSRC set the SSRC~n" ++ " -t, --type=N set the payload type~n" ++ + " -r, --rate=N set the RTP rate [8000]~n" ++ + " -D, --duration=N set the packet duration in RTP time units [160]~n" ++ " -d, --delay=FLOAT add offset to playout timestamp~n" ++ "~n" ++ "Arguments:~n" ++ @@ -165,6 +169,21 @@ getopts([ "--file=" ++ File | R], Opts) -> getopts(R, [{file, File} | Opts]); getopts([ "-i" ++ T | R], Opts) -> getopts_alias_arg("--file", T, R, Opts); +getopts([ "--frame-size=" ++ N | R], Opts) -> + Size = list_to_integer(N), + getopts(R, [{frame_size, Size}, {in_format, bin} | Opts]); +getopts([ "-f" ++ T | R], Opts) -> + getopts_alias_arg("--frame-size", T, R, Opts); +getopts([ "--duration=" ++ N | R], Opts) -> + Duration = list_to_integer(N), + getopts(R, [{duration, Duration} | Opts]); +getopts([ "-D" ++ T | R], Opts) -> + getopts_alias_arg("--duration", T, R, Opts); +getopts([ "--rate=" ++ N | R], Opts) -> + Rate = list_to_integer(N), + getopts(R, [{rate, Rate} | Opts]); +getopts([ "-r" ++ T | R], Opts) -> + getopts_alias_arg("--rate", T, R, Opts); getopts([ "--version" | _], _Opts) -> show_version(), halt(0); @@ -328,9 +347,10 @@ write_packets(Dev, DataSource, P = #rtp_packet{}, F, L, O, Opts) -> Format = proplists:get_value(format, Opts, state), Ptime = proplists:get_value(duration, Opts, 160), Delay = proplists:get_value(delay, Opts, 0), + Rate = proplists:get_value(rate, Opts, 8000), case next_payload(DataSource) of {Payload, DataSource2} -> - write_packet(Dev, 0.020 * F + Delay, + write_packet(Dev, Ptime * F / Rate + Delay, P#rtp_packet{seqno = F, timestamp = F*Ptime+O, payload = Payload}, Format), @@ -376,12 +396,18 @@ read_packets(Dev, Opts) -> read_packets(Dev, Opts, Format). read_packets(Dev, Opts, Format) -> - case read_packet(Dev, Format) of + case read_packet(Dev, Opts, Format) of eof -> []; Tuple -> [Tuple | read_packets(Dev, Opts, Format)] end. -read_packet(Dev, Format) -> +read_packet(Dev, Opts, bin) -> + Size = proplists:get_value(frame_size, Opts), + case file:read(Dev, Size) of + {ok, Data} -> {0, #rtp_packet{payload = iolist_to_binary(Data)}}; + eof -> eof + end; +read_packet(Dev, _Opts, Format) -> case read_packet_line(Dev, Format) of {Time, Bin} -> {Time, parse_rtp_packet(Bin)}; eof -> eof -- 1.7.9.5 From holger at freyther.de Tue Apr 29 12:24:06 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Tue, 29 Apr 2014 14:24:06 +0200 Subject: [PATCH] contrib/rtp: Use payload data files directly by gen_rtp_header In-Reply-To: <1398768021-27350-1-git-send-email-jerlbeck@sysmocom.de> References: <1398768021-27350-1-git-send-email-jerlbeck@sysmocom.de> Message-ID: <20140429122406.GA10912@xiaoyu.lan> On Tue, Apr 29, 2014 at 12:40:21PM +0200, Jacob Erlbeck wrote: > This adds a --frame-size option to read payload binary files with a > fixed frame size directly. The file must not contain RTP headers. > In addition '--rate' and '--duration' can be used to configure the > timing. Please push to master. You are the producer/consumer of this application. There is no possibility you interfere wuth any of us. :) > - write_packet(Dev, 0.020 * F + Delay, > + write_packet(Dev, Ptime * F / Rate + Delay, Do you need to change the default value of F? Is it (F/R)+D or F/(R+D) in erlang? From jerlbeck at sysmocom.de Tue Apr 29 13:10:46 2014 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Tue, 29 Apr 2014 15:10:46 +0200 Subject: [PATCH] contrib/rtp: Use payload data files directly by gen_rtp_header In-Reply-To: <20140429122406.GA10912@xiaoyu.lan> References: <1398768021-27350-1-git-send-email-jerlbeck@sysmocom.de> <20140429122406.GA10912@xiaoyu.lan> Message-ID: <535FA4D6.1090806@sysmocom.de> On 29.04.2014 14:24, Holger Hans Peter Freyther wrote: > On Tue, Apr 29, 2014 at 12:40:21PM +0200, Jacob Erlbeck wrote: >> This adds a --frame-size option to read payload binary files with a >> fixed frame size directly. The file must not contain RTP headers. >> In addition '--rate' and '--duration' can be used to configure the >> timing. > > Please push to master. You are the producer/consumer of this application. > There is no possibility you interfere wuth any of us. :) Yes, but perhaps somebody has comments or helpful hints on it. > >> - write_packet(Dev, 0.020 * F + Delay, >> + write_packet(Dev, Ptime * F / Rate + Delay, > > Do you need to change the default value of F? F is set to Start/First (ok, the naming could be made consistent) initially. > Is it (F/R)+D or F/(R+D) > in erlang? I'm not sure what you mean, but (F/R)+D is semantically equal to F/R+D and to D+F/R (the Erlang parser associates */ tighter than +-). R is a rate and D is a time, so (R + D) doesn't make much sense. -- - Jacob Erlbeck http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Schivelbeiner Str. 5 * 10439 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From koue at chaosophia.net Wed Apr 30 14:01:55 2014 From: koue at chaosophia.net (Nikola Kolev) Date: 30 Apr 2014 17:01:55 +0300 Subject: [PATCH] openbsc: Fix for FreeBSD Message-ID: Fix for FreeBSD. -- Nikola -------------- next part -------------- A non-text attachment was scrubbed... Name: openbsc-freebsd-patch.diff Type: application/octet-stream Size: 903 bytes Desc: openbsc-freebsd-patch.diff URL: From holger at freyther.de Wed Apr 30 15:48:01 2014 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Wed, 30 Apr 2014 17:48:01 +0200 Subject: [PATCH] openbsc: Fix for FreeBSD In-Reply-To: References: Message-ID: <20140430154801.GO3501@xiaoyu.lan> On Wed, Apr 30, 2014 at 05:01:55PM +0300, Nikola Kolev wrote: > Fix for FreeBSD. Hey! could you extend the commit message a bit? E.g. include the compile error you fixed and mention how IF_RECVIF is compatible to the bindtodevice. The support to IF_SENDIF doesn't seem to have ever been finished in FreeBSD.