diff options
author | Harald Welte <laforge@gnumonks.org> | 2009-02-09 18:13:26 +0000 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2009-02-09 18:13:26 +0000 |
commit | 1fa60c8ab04653bae5ac29d8d93ad18b44f0f354 (patch) | |
tree | 35aa1e0c66c605576bb900347c465e9120a85fc0 /include | |
parent | 0b4c34e3ca22da724de308b8154a2730b53fc388 (diff) |
* add trau_mux implementation to relay from one incoming TRAU
channel to another one (simple voice call switching)
* add a way more generic E1 input layer, abstracting out the misdn
low-level interface. This also adds infrastructure for multiple TRX
in one BTS, as well as multiple BTS on one E1 link
* add a E1 subchannel multiplexer for sending multiple 16kbit sub-channels
one one 64kBps E1 channel
* add TRAU IDLE frame generation
* terminate bsc_hack in case there is a E1 / mISDN init error
* introduce 'e1_config.c' file with static configuration of our
E1 setup (which TRX/BTS is configured for which TEI/SAPI/E1). This should
later become a config file rather than a compiled C file.
WARNING: all this compiles but is not tested yet. Expect fix-up committs over
the next hours or so
Diffstat (limited to 'include')
-rw-r--r-- | include/openbsc/abis_nm.h | 1 | ||||
-rw-r--r-- | include/openbsc/e1_input.h | 137 | ||||
-rw-r--r-- | include/openbsc/gsm_data.h | 10 | ||||
-rw-r--r-- | include/openbsc/subchan_demux.h | 57 | ||||
-rw-r--r-- | include/openbsc/trau_frame.h | 1 | ||||
-rw-r--r-- | include/openbsc/trau_mux.h | 41 |
6 files changed, 240 insertions, 7 deletions
diff --git a/include/openbsc/abis_nm.h b/include/openbsc/abis_nm.h index 2df941e6e..e75f108b2 100644 --- a/include/openbsc/abis_nm.h +++ b/include/openbsc/abis_nm.h @@ -486,5 +486,6 @@ int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname, u_int8_t win_size, int forced, gsm_cbfn *cbfn); int abis_nm_bs11_set_ext_time(struct gsm_bts *bts); int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect); +int abis_nm_bs11_restart(struct gsm_bts *bts); #endif /* _NM_H */ diff --git a/include/openbsc/e1_input.h b/include/openbsc/e1_input.h new file mode 100644 index 000000000..29c29d081 --- /dev/null +++ b/include/openbsc/e1_input.h @@ -0,0 +1,137 @@ +#ifndef _E1_INPUT_H +#define _E1_INPUT_H + +#include <stdlib.h> + +#include <openbsc/linuxlist.h> +#include <openbsc/gsm_data.h> +#include <openbsc/msgb.h> +#include <openbsc/select.h> +#include <openbsc/subchan_demux.h> + +#define NUM_E1_TS 32 + +enum e1inp_sign_type { + E1INP_SIGN_NONE, + E1INP_SIGN_OML, + E1INP_SIGN_RSL, +}; + +struct e1inp_ts; + +struct e1inp_sign_link { + /* list of signalling links */ + struct llist_head list; + + /* to which timeslot do we belong? */ + struct e1inp_ts *ts; + + enum e1inp_sign_type type; + + /* trx for msg->trx of received msgs */ + struct gsm_bts_trx *trx; + + /* msgb queue of to-be-transmitted msgs */ + struct llist_head tx_list; + + /* SAPI and TEI on the E1 TS */ + u_int8_t sapi; + u_int8_t tei; + + union { + struct { + u_int8_t channel; + } misdn; + } driver; +}; + +enum e1inp_ts_type { + E1INP_TS_TYPE_NONE, + E1INP_TS_TYPE_SIGN, + E1INP_TS_TYPE_TRAU, +}; + +/* A timeslot in the E1 interface */ +struct e1inp_ts { + enum e1inp_ts_type type; + int num; + + /* to which line do we belong ? */ + struct e1inp_line *line; + + union { + struct { + struct llist_head sign_links; + } sign; + struct { + /* subchannel demuxer for frames from E1 */ + struct subch_demux demux; + /* subchannel muxer for frames to E1 */ + struct subch_mux mux; + } trau; + }; + union { + struct { + /* mISDN driver has one fd for each ts */ + struct bsc_fd fd; + } misdn; + } driver; +}; + +struct e1inp_driver { + struct llist_head list; + const char *name; + int (*want_write)(struct e1inp_ts *ts); +}; + +struct e1inp_line { + struct llist_head list; + unsigned int num; + const char *name; + + /* array of timestlots */ + struct e1inp_ts ts[NUM_E1_TS]; + + struct e1inp_driver *driver; + void *driver_data; +}; + +/* register a driver with the E1 core */ +int e1inp_driver_register(struct e1inp_driver *drv); + +/* register a line with the E1 core */ +int e1inp_line_register(struct e1inp_line *line); + +/* find a sign_link for given TEI and SAPI in a TS */ +struct e1inp_sign_link * +e1inp_lookup_sign_link(struct e1inp_ts *ts, u_int8_t tei, + u_int8_t sapi); + +/* create a new signalling link in a E1 timeslot */ +struct e1inp_sign_link * +e1inp_sign_link_create(struct e1inp_ts *ts, enum e1inp_sign_type type, + struct gsm_bts_trx *trx, u_int8_t tei, + u_int8_t sapi); + +/* configure and initialize one e1inp_ts */ +int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line, + enum e1inp_ts_type type); + +/* Call from the Stack: configuration of this TS has changed */ +int e1inp_update_ts(struct e1inp_ts *ts); + +/* Receive a packet from the E1 driver */ +int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg, + u_int8_t tei, u_int8_t sapi); + +/* called by driver if it wants to transmit on a given TS */ +struct msgb *e1inp_tx_ts(struct e1inp_ts *e1i_ts, + struct e1inp_sign_link **sign_link); + +/* called by driver in case some kind of link state event */ +int e1inp_event(struct e1inp_ts *ts, int evt, u_int8_t tei, u_int8_t sapi); + +/* called by TRAU muxer to obtain the destination mux entity */ +struct subch_mux *e1inp_get_mux(u_int8_t e1_nr, u_int8_t ts_nr); + +#endif /* _E1_INPUT_H */ diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h index 75b3db516..b96ec402d 100644 --- a/include/openbsc/gsm_data.h +++ b/include/openbsc/gsm_data.h @@ -166,6 +166,8 @@ struct gsm_bts_trx { struct gsm_bts *bts; /* number of this TRX in the BTS */ u_int8_t nr; + /* how do we talk RSL with this TRX? */ + struct e1inp_sign_link *rsl_link; u_int16_t arfcn; struct gsm_bts_trx_ts ts[TRX_NR_TS]; @@ -215,6 +217,8 @@ struct gsm_bts { u_int8_t location_area_code; /* type of BTS */ enum gsm_bts_type type; + /* how do we talk OML with this TRX? */ + struct e1inp_sign_link *oml_link; /* Abis network management O&M handle */ struct abis_nm_h *nmh; @@ -255,10 +259,8 @@ const char *gsm_chreq_name(enum gsm_chreq_reason_t c); enum gsm_e1_event { EVT_E1_NONE, - EVT_E1_OML_UP, - EVT_E1_RSL_UP, - EVT_E1_OML_DN, - EVT_E1_RSL_DN, + EVT_E1_TEI_UP, + EVT_E1_TEI_DN, }; #endif diff --git a/include/openbsc/subchan_demux.h b/include/openbsc/subchan_demux.h index 373cf4a30..23c903204 100644 --- a/include/openbsc/subchan_demux.h +++ b/include/openbsc/subchan_demux.h @@ -1,6 +1,6 @@ #ifndef _SUBCH_DEMUX_H #define _SUBCH_DEMUX_H -/* A E1 sub-channel demultiplexer with TRAU frame sync */ +/* A E1 sub-channel (de)multiplexer with TRAU frame sync */ /* (C) 2009 by Harald Welte <laforge@gnumonks.org> * All Rights Reserved @@ -22,26 +22,77 @@ */ #include <sys/types.h> +#include <openbsc/linuxlist.h> #define NR_SUBCH 4 #define TRAU_FRAME_SIZE 40 #define TRAU_FRAME_BITS (TRAU_FRAME_SIZE*8) -struct subch { +/***********************************************************************/ +/* DEMULTIPLEXER */ +/***********************************************************************/ + +struct demux_subch { u_int8_t out_bitbuf[TRAU_FRAME_BITS]; u_int8_t out_idx; /* next bit to be written in out_bitbuf */ }; struct subch_demux { + /* bitmask of currently active subchannels */ u_int8_t chan_activ; - struct subch subch[NR_SUBCH]; + /* one demux_subch struct for every subchannel */ + struct demux_subch subch[NR_SUBCH]; + /* callback to be called once we have received a complete + * frame on a given subchannel */ int (*out_cb)(struct subch_demux *dmx, int ch, u_int8_t *data, int len, void *); + /* user-provided data, transparently passed to out_cb() */ void *data; }; +/* initialize one demultiplexer instance */ int subch_demux_init(struct subch_demux *dmx); + +/* feed 'len' number of muxed bytes into the demultiplexer */ int subch_demux_in(struct subch_demux *dmx, u_int8_t *data, int len); + +/* activate decoding/processing for one subchannel */ int subch_demux_activate(struct subch_demux *dmx, int subch); + +/* deactivate decoding/processing for one subchannel */ int subch_demux_deactivate(struct subch_demux *dmx, int subch); + +/***********************************************************************/ +/* MULTIPLEXER */ +/***********************************************************************/ + +/* one element in the tx_queue of a muxer sub-channel */ +struct subch_txq_entry { + struct llist_head list; + + unsigned int bit_len; /* total number of bits in 'bits' */ + unsigned int next_bit; /* next bit to be transmitted */ + + u_int8_t bits[0]; /* one bit per byte */ +}; + +struct mux_subch { + struct llist_head tx_queue; +}; + +/* structure representing one instance of the subchannel muxer */ +struct subch_mux { + struct mux_subch subch[NR_SUBCH]; +}; + +/* initialize a subchannel muxer instance */ +int subchan_mux_init(struct subch_mux *mx); + +/* request the output of 'len' multiplexed bytes */ +int subchan_mux_out(struct subch_mux *mx, u_int8_t *data, int len); + +/* enqueue some data into one sub-channel of the muxer */ +int subchan_mux_enqueue(struct subch_mux *mx, int s_nr, const u_int8_t *data, + int len); + #endif /* _SUBCH_DEMUX_H */ diff --git a/include/openbsc/trau_frame.h b/include/openbsc/trau_frame.h index 7f0a2e69b..5923d4ac1 100644 --- a/include/openbsc/trau_frame.h +++ b/include/openbsc/trau_frame.h @@ -59,6 +59,7 @@ struct decoded_trau_frame { int decode_trau_frame(struct decoded_trau_frame *fr, const u_int8_t *trau_bits); int encode_trau_frame(u_int8_t *trau_bits, const struct decoded_trau_frame *fr); int trau_frame_up2down(struct decoded_trau_frame *fr); +u_int8_t *trau_idle_frame(void); #endif /* _TRAU_FRAME_H */ diff --git a/include/openbsc/trau_mux.h b/include/openbsc/trau_mux.h new file mode 100644 index 000000000..43836dbc5 --- /dev/null +++ b/include/openbsc/trau_mux.h @@ -0,0 +1,41 @@ +/* Simple TRAU frame reflector to route voice calls */ + +/* (C) 2009 by Harald Welte <laforge@gnumonks.org> + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* The "TRAU mux map" defines which particular 16kbit sub-slot (in which E1 + * timeslot on which E1 interface) should be directly muxed to which other + * sub-slot. Entries in the mux map are always bi-directional. + * + * The idea of all this is to directly switch voice channels in the BSC + * from one phone to another. We do this right now since we don't support + * any external interface for voice channels, and in the future as an + * optimization to routing them externally. + */ + +/* map a TRAU mux map entry */ +int trau_mux_map(const struct gsm_e1_subslot *src, + const struct gsm_e1_subslot *dst); + +/* unmap a TRAU mux map entry */ +int trau_mux_unmap(const struct gsm_e1_subslot *ss); + +/* we get called by subchan_demux */ +int trau_mux_input(struct gsm_e1_subslot *src_e1_ss, + const u_int8_t *trau_bits, int num_bits); |