Compare commits

..

403 Commits

Author SHA1 Message Date
Holger Hans Peter Freyther
955c3d1894 misc: Fix the make distcheck of the sources. 2011-02-28 20:49:47 +01:00
Holger Hans Peter Freyther
afb883956d mgcp: Fix make distcheck due a copy 'n pasted Makefile.am 2011-02-28 20:45:55 +01:00
Holger Hans Peter Freyther
6990687f4c mgcp: Only allow transcoding on the virtual trunk 2011-02-28 19:40:54 +01:00
Holger Hans Peter Freyther
44016fee14 mgcp: Fix the static allocation of E1 trunks for the BTS/NET side 2011-02-28 19:40:54 +01:00
Holger Hans Peter Freyther
1f0c5b4742 mgcp: Allocate the endpoints for the E1 trunks as well. 2011-02-28 19:40:53 +01:00
Holger Hans Peter Freyther
74e61110e5 mgcp: Look up the E1 trunks through the trunk configuration 2011-02-28 19:40:53 +01:00
Holger Hans Peter Freyther
6ea7e777f5 mgcp: Implement find_trunk to find the E1 trunks as well. 2011-02-28 19:40:53 +01:00
Holger Hans Peter Freyther
cdba04978d mgcp: Make show mgcp print the new trunks we have. 2011-02-28 19:40:53 +01:00
Holger Hans Peter Freyther
0e939fec42 mgcp: Introduce a trunk config for multiple trunks.
A trunk will always have 32 endpoints to be used and we allow
a sparse allocation of endpoints.
2011-02-28 19:40:53 +01:00
Holger Hans Peter Freyther
ab3bb9d444 mgcp: Update the commands to work on more than the virtual trunk 2011-02-28 19:40:53 +01:00
Holger Hans Peter Freyther
d011c91512 mgcp: Prepare the show mgcp command to work on multiple trunks 2011-02-28 19:40:53 +01:00
Holger Hans Peter Freyther
88ad7723b4 mgcp: Introduce a mgcp_trunk_config enum for endpoint configs
We want to support real trunks in the MGCP code and we need to
have some better book keeping for those. Move the code around.
2011-02-28 19:40:53 +01:00
Holger Hans Peter Freyther
dfdf8d929a nat: For debugging make it possible to set the last used endpoint
This will influence the allocator from where to search for the
next free endpoint. This can be used to force it to allocate a
specific endpoint next.
2011-02-28 19:40:46 +01:00
Holger Hans Peter Freyther
9212d9d636 nat: Fix some corruption in the test case 2011-02-27 11:18:41 +01:00
Holger Hans Peter Freyther
9ec030d32d nat: Change number of multiplexes to the max-endpoints 2011-02-27 11:05:18 +01:00
Holger Hans Peter Freyther
a9e9331285 nat: Allocate endpoints from multiple multiplexes.
This code allocates endpoints from multiple multiplexes but
will always leave 0x0 and 0x1f unassigned in the multiplex.
2011-02-26 11:38:00 +01:00
Holger Hans Peter Freyther
7b07b2dcff nat: Start making the number of multiplexes configurable
Introduce a VTY setting that right now needs to be set to
one. To make updating this setting possible we will now store
the number of endpoints in the bsc connection as well.
2011-02-26 10:42:01 +01:00
Holger Hans Peter Freyther
86c1db6338 nat: Verify that we are not assigning 0x1f as endpoint.
On a classic BSC we have 32 channels but one is reserved for
signalling. Make sure that we are not assigning 0x1f as we
assume that this is the signalling channel. This means that
from 32 possible voice channels we are only going to use 30
as we are already not using the 0x0.
2011-02-26 10:38:52 +01:00
Holger Hans Peter Freyther
ed500e3877 nat: Allocate the endpoint status dynamically
Allocate the status for an endpoint dynamically. We will support
BSCs with different amount of multiplexes and need to have this
flexibility in the future. Add the proper null checks to the
current users of this code.
2011-02-26 10:35:33 +01:00
Holger Hans Peter Freyther
7e0cc50e44 nat: Update the tests to make them going again
We now need to have access to a mgcp_cfg and the change to the
setup number patching needs new data. We now set the number to
international type.
2011-02-25 17:30:48 +01:00
Holger Hans Peter Freyther
867d69bbcb configure: Require a new libosmovty due to the syslog/logging changes 2011-02-25 17:30:48 +01:00
Harald Welte
ec1921dfa3 Use shorter vty_app_info->name for all apps
... as this is now used as SYSLOG ident
2011-02-24 23:57:06 +01:00
Nico Golde
b62b12398b sms: introduce new command to trigger the sending process for specific subscribers only 2011-02-24 14:48:57 +01:00
Holger Hans Peter Freyther
11762459e8 rf: Delay execution of commands
Delay executing RF commands up to a second. If many commands
arrive within a second then just execute the last command.
2011-02-24 14:40:23 +01:00
Holger Hans Peter Freyther
00c805f213 rf: Verify that the requested mode is entered and drop OML in error
Verify that the BTS is following our orders, if we think there was
an error we will drop the OML connection.
2011-02-24 14:40:11 +01:00
Holger Hans Peter Freyther
37ac420254 rf: Remember the last command requested on the RF CMD interface 2011-02-24 14:37:36 +01:00
Dieter Spaar
6a458eac2c oml: Parse probable cause and additional text in failure reports 2011-02-24 14:37:10 +01:00
Holger Hans Peter Freyther
6c79a68103 misc: Compile fixes due 4d54d0b883 2011-02-24 14:34:03 +01:00
Holger Hans Peter Freyther
ca8f3b59c1 debian: Correct the path for the binaries. 2011-02-20 11:56:12 +01:00
Harald Welte
21bbda242e BSC: Fix empty neighbor list in case of manual SI/SI5 mode 2011-02-19 20:43:37 +01:00
Harald Welte
4d54d0b883 Fix various compiler warnings all over the code 2011-02-19 16:48:17 +01:00
Harald Welte
5ec26fe983 Install programs into $(prefix)/bin, not /sbin
At least in many configurations, there is no need to run any
of our programs as root.  Thus, we shouldn't install them in sbin.
2011-02-19 16:19:19 +09:00
Holger Hans Peter Freyther
f358964fb2 bsc: Use msg->data and msg->len for the hexdump, pick a better name
Rename the method as we send everything to the MSC and not just
SCCP. Put alink into the function name. Also use msg->data and
msg->len in hexdump as this is what we are sending to the server.
2011-02-18 23:44:49 +01:00
Holger Hans Peter Freyther
91fa850791 nat: If the number starts with 00 turn it into a international number
Switch the type to international and skip the '00' of the phone
number. This should fix some issues with gateway MSCs.
2011-02-18 23:44:49 +01:00
Holger Hans Peter Freyther
4446b3bf34 nat: Add extra size check for the number and fail if it does not fit
If the replaced number is too long for the phone number we will
have to stop processing here.
2011-02-18 23:44:49 +01:00
Holger Hans Peter Freyther
6e1a676e21 bsc: core-mobile-country-code and core-mobile-network-code range is too small
Make both VTY commands have the same range as the normal MCC and
NCC command in the config file.
2011-02-18 23:44:49 +01:00
Harald Welte
8dcebd3e7f LOGGING: make sure to make the 'logging filter' compatible with vty log cfg
Recent libosmocore introdues a way how log targets can be configured from
the VTY.

This commit makes the 'log filter (imsi|nsvc|bvc)' compatible with it.
2011-02-18 21:10:05 +01:00
Harald Welte
64c07d213c Allow configuration of SI5 neighbor list != SI2 neighbor list
This introducecs the new VTY command "neighbor-list mode manual-si5"
in combination with "si5 neighbor-list (add|del) arfcn <0-1024>",
which allows you to (optionally) have neighbor channel lists that
differ in SI5 and in SI2.
2011-02-15 11:43:27 +01:00
Harald Welte
b01bf33ad4 add example openbsc.cfg for RBS2308 with 4TRX 2011-02-14 16:45:06 +01:00
Harald Welte
e925205c28 DAHDI: Automatically switch signalling slots to HDLC + FCS mode
This will now make signalling slots work anywhere, even if
/etc/dahdi/system.conf states the timeslot is a bchan.
2011-02-14 16:43:35 +01:00
Harald Welte
da87154093 OM2000: Make sure the IS and CON lists are kept in order 2011-02-14 16:32:44 +01:00
Harald Welte
ebec58e8ba DAHDI: usse lower-case name to parse correctly by vty code 2011-02-14 16:31:53 +01:00
Harald Welte
59eee42b05 OM2000/RBS2000: Make IS+CON configuration persistent in config file
This uses the new bts_model->config_write_bts() callbacks
2011-02-14 16:17:49 +01:00
Harald Welte
face7edc62 VTY: Allow for per-BTS-model specific config file write functions
This way a BTS module can append config data to the TS, TRX and BTS
sections.
2011-02-14 16:15:21 +01:00
Harald Welte
a0fe72de6f LAPD: keep sent/receive sequence numbers per SAPI, not just per TEI
If there are multiple SAPIs active on the same TEI, we need to keep
one set of sequence numbers for each SAPI, not just for the TEI.
2011-02-14 15:51:57 +01:00
Harald Welte
fdb71949db OM2000: Handle various ACKs better, implement CON CONF REQ 2011-02-14 15:31:43 +01:00
Harald Welte
d88a3878cc OM2000: Route outgoing NM message depending on MO
Depending on the MO we adress, select the proper OML link
2011-02-14 15:26:13 +01:00
Harald Welte
9c0958bf4c OM2000: Complete the VTY help message for OM2000 MO commands 2011-02-13 22:51:03 +01:00
Harald Welte
a02085dab0 OM2000: Allow configuration of CON from VTY
However, we have no code that generates the OM2K CON List attribute.
2011-02-13 22:45:02 +01:00
Harald Welte
a8e6a652ca OM2000: Allow VTY based configuration of IS connection groups 2011-02-13 22:13:28 +01:00
Harald Welte
b7eebf8699 OM2000: Don't send START REQ in response to FAULT REP 2011-02-13 20:09:24 +01:00
Harald Welte
c4989a8e5e INPUT: Disable the per-TRX OML Link for now
We need a way for the caller to specify which OML link (BTS or TRX) he wants.
2011-02-13 20:06:58 +01:00
Harald Welte
9f0866c2a3 RBS2000: Differentiate between BTS OML and TRX OML
We don't want to restart the CF on TRX OML link establishment...
2011-02-13 19:44:47 +01:00
Harald Welte
bd3137c2dd INPUT: Include TEI + SAPI in E1 INPUT SIGNAL 2011-02-13 19:44:21 +01:00
Harald Welte
15ccc77f62 INPUT: Allow for a per-TRX OML link
So far, all BTS we have interfaced had one OML link per BTS, independent of the
number of TRX.  In Ericsson RBS 2000, there is an OML link for the DXU/IXU,
and one additional OML link for each TRX/TRU.
2011-02-13 19:36:18 +01:00
Harald Welte
82b03a1f2b RBS2000: fix compiler warning about unhandled enum in switch() 2011-02-13 19:35:39 +01:00
Harald Welte
cca849a825 Merge branch 'rbs2000' 2011-02-13 15:50:43 +01:00
Harald Welte
0896b50197 OM2000: Configure the IS to route both TRX0 and TRX1 2011-02-13 15:49:27 +01:00
Harald Welte
909212fc87 LAPD: Make sure we don't re-start SABM timer for INACTIVE SAPs 2011-02-13 15:49:27 +01:00
Harald Welte
c834b70d04 RBS2000: Generate per-TRX OML link 2011-02-13 15:49:27 +01:00
Harald Welte
174a51a761 DAHDI: Deliver ALARM/NOALARM as input signal to RBS2000 driver
... and re-start LAPD SABM as required
2011-02-13 15:49:27 +01:00
Harald Welte
b3d70fd0bd OM2000: Make sure we ACK an ENABLE RESULT 2011-02-13 15:49:26 +01:00
Harald Welte
dcf42e6cd2 RBS2000: Move SABM re-transmit logic into LAPD code
This means we now can support multiple LAPD links
2011-02-13 15:49:26 +01:00
Harald Welte
334c5ab2e6 RBS2000: Make sure we transmit SABM at 0.3 second intervals
This is apparently the right timing to increase the chance that the RBS detects
it quickly. (10..15 seconds)
2011-02-13 15:49:26 +01:00
Harald Welte
b0ec9e3dae OM2000: Use om2k in VTY prompt 2011-02-13 15:49:26 +01:00
Harald Welte
8bcb1a0a99 OM2000: Add IS Conf Req 2011-02-13 15:49:26 +01:00
Harald Welte
0741ffe69f OM2000: Add enable/disable commands 2011-02-13 15:49:26 +01:00
Harald Welte
56ee6b8075 OM2000: Fix Negotiation parsing 2011-02-13 15:49:26 +01:00
Harald Welte
563d316106 OM2000: Implement proper parsing and response for Negotiation 2011-02-13 15:49:26 +01:00
Harald Welte
8024d8ff58 OM2000: Add support for sending the TEST REQUEST message 2011-02-13 15:49:25 +01:00
Harald Welte
8d4a472cc4 OML2000: Make sure we can properly exit the VTY node 2011-02-13 15:49:25 +01:00
Harald Welte
810e32394d OM2000: Make sure we can properly exit tye VTY node 2011-02-13 15:49:25 +01:00
Harald Welte
6fec79da18 OM2000: Add VTY commands for connect/disconnect and op_info 2011-02-13 15:49:25 +01:00
Harald Welte
51c8238024 OM2000: Add missing file from previous commit 2011-02-13 15:49:25 +01:00
Harald Welte
e1d5eca916 OM2000: Introduce VTY commands to initiate OM2000 procedures 2011-02-13 15:49:25 +01:00
Harald Welte
7354107946 OM2000: Negotiation Resposne, send START on OML-up event 2011-02-13 15:49:25 +01:00
Harald Welte
bc867d9a17 OM2000: Fix computation of length field in header, direct transmit of msgs 2011-02-13 15:49:24 +01:00
Harald Welte
9a311ec25e [RBS2000] Add initial code for Ericsson OM2000 O&M protocol
... and link it from the RBS2000 BTS support
2011-02-13 15:49:24 +01:00
Harald Welte
b80e14e567 [RBS2000] Add FIXMEs in code that is a crude hack 2011-02-13 15:49:24 +01:00
Harald Welte
03cc8a810b [RBS2000] Actually activate the RBS2000 support
The previous patch introduces new code for the RBS2000 but didn't
actually activate/call it yet.

After this patch, you can see LAPD being established and OM2000 messages
will fall into abis_nm.c (which of course has no clue about them).
2011-02-13 15:49:24 +01:00
Harald Welte
db44f6012d [RBS2000] Initial attempt at Ericsson RBS2000 support 2011-02-13 15:49:24 +01:00
Harald Welte
09cefee4db [OML] Allow each BTS model to specify the OML callback
This allows us to add BTS models that do not use the standard TS 12.21 OML
2011-02-13 15:49:09 +01:00
Harald Welte
a4898a868b DAHDI: print debug hexdump of every signalling msg we send 2011-02-13 15:47:26 +01:00
Harald Welte
1a00d823b3 [LAPD] Add minimal support for TE-side LAPD 2011-02-13 15:46:48 +01:00
Harald Welte
00ee4b78db DAHDI: Register every FD in the select() exceptfd-set
This helps us to receive events even if we don't receive or transmit
anything on the line.
2011-02-13 15:46:08 +01:00
Harald Welte
44f04da379 DAHDI: Handle exceptions 2011-02-13 15:44:53 +01:00
Harald Welte
95aa5c4ae3 E1 INPUT: Fix PCAP file generation for non-mISDN case 2011-02-13 15:44:22 +01:00
Harald Welte
f27d043032 E1 Input: Add new S_INP_LINE_INIT signal
This allows other code to listen ot a signal about a new line that
was just configured.
2011-02-11 16:49:41 +01:00
Harald Welte
f338a03b0c [BSC] Move the BTS-type specific code from bcs_init.c to bts_*.c
bsc_init.c was a big mess even only for two supported BTS models,
so before adding more BTS types, this needs a cleanup.

All the BTS specific code from bsc_init.c has now moved into
bts_{siemens_bs11,ipaccess_nanobts}.c

This has required that input_event() and nm_state_event() get both
converted to proper libosmocore signals instead of referencing external
symbols.
2011-02-11 16:26:31 +01:00
Harald Welte
f3956cbb20 [gb_proxy] vty: display the BVC BLOCKED status in 'show gbproxy' 2011-02-06 17:44:14 +01:00
Harald Welte
fb9e06f310 [gb_proxy] make sure bssgp cell id is copied correctly
When we copy a msgb, we need to make sure the msgb_cb->bssgp_cell_id
pointer points to data in the new message, not in the old message.

Thanks to Dieter Spaar for spotting this.
2011-02-06 17:17:05 +01:00
Harald Welte
c471d3d8a2 [gb proxy] treat BVCI=1 consistently like signalling
1 is reserved for point-to-multipoint data, i.e. not a point-to-point BVCI.
2011-02-06 17:13:12 +01:00
Harald Welte
5e106d7765 [gb_proxy] Convert a NS-BLOCK from BSS into BVC-RESET to SGSN
As we only have one NS-VC between gb_proxy and SGSN, we cannot
forward a NS-BLOCK from the BSS to the SGSN, as it would affect
all other BSS's, too.

Thus, we check if we have an unblocked PTP-BVC in the NSVC to the BSS,
and then issue a BVC-BLOCK towards the SGSN.

This should prevent any further PDU's from the SGSN to be sent to
this BSS.
2011-02-06 16:33:29 +01:00
Harald Welte
36f98d9c53 [gb_proxy] Track the state of blocked/unblocked BVC in the proxy
This allows us to reject any additional messages sent by the SGSN
after the BVC was blocked (+ acknowledged to be blocked)
2011-02-06 13:09:29 +01:00
Harald Welte
b63c3639eb remove dead code 2011-02-05 22:17:24 +01:00
Harald Welte
62d460301b [DAHDI] cosmetic fixes 2011-02-05 20:26:27 +01:00
Harald Welte
4ee2eaf3c4 [DAHDI] make sure LAPD transmits with correct SAPI 2011-02-05 20:26:27 +01:00
Harald Welte
8fc66a0c4d [LAPD] fix bug in TEI manager rendering LAPD unusable 2011-02-05 20:26:27 +01:00
Harald Welte
1458ec6571 [DAHDI] remove unused variable 2011-02-05 20:26:27 +01:00
Harald Welte
d38f10593a [LAPD] Support multiple instances of LAPD
We cannot afford static/global state, as we may have multiple E1
lines, each having its own LAPD instance.  Furthermore, we might
even have multiple LAPD instances on the same E1 line (think of
a multi-drop setup).

This also implements dynamic TEI allocation, i.e. no hardcoded
TEI list anymore.
2011-02-05 20:26:27 +01:00
Harald Welte
0ae575536a [LAPD] remove a number of unneeded assert() calls 2011-02-05 20:26:27 +01:00
Harald Welte
716d2a47b2 [LAPD] further code cleanup 2011-02-05 20:26:27 +01:00
Harald Welte
0abc11a0d0 [LAPD] use LOGP/DEBUGP instead of custom logging function 2011-02-05 20:26:26 +01:00
Harald Welte
50d369e1a9 [DAHDI] update to latest e1_input changes 2011-02-05 20:26:26 +01:00
Harald Welte
ca17ef88f5 [DAHDI] build dahdi driver only if dahdi header is present 2011-02-05 20:26:26 +01:00
Harald Welte
1dd68c3d0f [DAHDI] integrate DAHDI driver into E1 Input layer 2011-02-05 20:26:26 +01:00
Harald Welte
ba0db5b7f3 [dahdi] remove lots of dead code and references to mISDN 2011-02-05 20:26:26 +01:00
Harald Welte
d273529a8d [dahdi] don't export private functions from lapd.c 2011-02-05 20:26:26 +01:00
Harald Welte
e1de69af7e [dahdi] support multiple-include of lapd.h 2011-02-05 20:26:25 +01:00
Harald Welte
7e859bc17c [dahdi] Fix LAPD code comments (C-style) 2011-02-05 20:26:25 +01:00
Harald Welte
30fe64165b [dahdi] Fix lapd.c coding style 2011-02-05 20:26:25 +01:00
creslin287
cd8b86f124 Working audio data version 2011-02-05 20:26:25 +01:00
Matthew Fredrickson
69245a0496 Current LAPD with fixes for frames with P/F bit set 2011-02-05 20:26:25 +01:00
Matthew Fredrickson
cc2bc35f2c Current version of mostly working dahdi driver 2011-02-05 20:26:25 +01:00
Xavier Carcelle
17289eda65 first commit 2011-02-05 20:26:25 +01:00
Matthew Fredrickson
b1cb8eb7a6 Latest version of driver from other machine. 2011-02-05 20:26:25 +01:00
Matthew Fredrickson
d105e2048a Add addtional copyright notices for changes 2011-02-05 20:26:24 +01:00
Matthew Fredrickson
bc6649e942 Add lapd.c and lapd.h 2011-02-05 20:26:24 +01:00
Matthew Fredrickson
b5ddc184ff Add dahdi.c 2011-02-05 20:26:24 +01:00
Harald Welte
f933de97ba [E1] fix typo resulting in NM message being logged as RSL 2011-02-05 20:23:44 +01:00
Harald Welte
98c98547d0 [E1 INPUT] update E1 / BS-11 config files
Add the new 'e1_input' config section that is required
2011-02-05 15:58:03 +01:00
Harald Welte
07bb0daaff [E1 input] make sure config file with new E1 input config saves correctly 2011-02-05 15:57:42 +01:00
Harald Welte
889f16eac3 [E1 input] proper config error reporting 2011-02-05 15:43:15 +01:00
Harald Welte
fefb52361a [E1 INPUT] remove debug printf's 2011-02-05 15:31:40 +01:00
Harald Welte
3016d9f299 [E1 INPUT] explicitly configure the E1 input driver for each line
This introduces a new 'e1_input' config node with a command to be
used like:
  e1_line 0 driver misdn

This allows us to have different input drivers in the future
2011-02-05 15:31:34 +01:00
Harald Welte
5455243306 [input] make mi_e1_line_update() a driver specific callback
This helps us to further disentangle the misdn driver and e1_input
in preparation of DAHDI support.
2011-02-05 15:31:31 +01:00
Holger Hans Peter Freyther
a61c709ef0 mncc: Fix a crash in the call release code
When the remote subscriber has not responded yet we could
end up with a crash in the MNCC code. It was enough to dial
the number, then hang up and bsc_hack would end up with a
segfault due the list poisining of linux_list.
2011-01-27 15:05:45 +01:00
Holger Hans Peter Freyther
6e94d6d10d mgcp: Be able to parse RQNT messages and reply to them
We do not implement the request for notification at all but
we will tell the server that we have received something.
2011-01-25 23:33:54 +01:00
Holger Hans Peter Freyther
3fbd244187 bsc: Initialize the subscr to NULL in the default case
The paging response should always have a TMSI or IMSI
and we should be able to find the subscriber using that. If
no IMSI/TMSI is present and we would still accept the LU
we would access the uninitialized memory.
2011-01-16 20:31:59 +01:00
Holger Hans Peter Freyther
b549ddfb04 mncc: Fix crash when memory allocation is failing 2011-01-16 20:31:59 +01:00
Holger Hans Peter Freyther
05bbec7227 bsc: Fix possible crash when the lchan->conn alloc failed
Another null pointer dereference found by clang.
2011-01-16 20:31:59 +01:00
Holger Hans Peter Freyther
91f587ed98 misc: Make clang --analyze happy with the source code
The compiler concludes that if (ts->type == type && ts->line && line
can be false as line is NULL and then we unconditionally access
it, make it happy by adding an extra NULL check.
2011-01-16 20:31:59 +01:00
Harald Welte
1761d02ddb [wireshark] Update HSL wireshark dissector
now it correctly names some of the IEs like DSP/FPGA version,
and also automatically marks the UDP streams as RTP depending on
what it has seen in the RSL CONNECT TRAU message.
2011-01-15 18:09:25 +01:00
Harald Welte
934676e158 [wireshark] some more HSL RSL decoding 2011-01-15 13:09:01 +01:00
Harald Welte
7bbaefb349 update gitignore 2011-01-14 14:38:42 +01:00
Harald Welte
64bb754b40 [RSL] Move RF CHAN REL ACK into its own function
... rather than handling it in the main switch() statement
2011-01-14 14:25:57 +01:00
Harald Welte
da0a99ab0d [wireshark] add some lines to the README about the HSL patches 2011-01-14 10:01:17 +01:00
Harald Welte
95932e7bd0 [wiresehark] Update the HSL patch for wireshark RSL dissector
now it correctly parses BSSGP and displays some more HSL specific IEs
2011-01-13 23:23:13 +01:00
Harald Welte
aace9fc9b9 [SI] Make sure we set BS_AG_BLKS_RES !=0
This parameter indicates how many of the PCH+AGCH blocks are reserved
for the AGCH and thus not used for the PCH.  If we set it to 0,
we basically tell the BTS there is no AGCH - and thus it would be
impossible to send any IMMEDIATE ASSIGNMENTs.

Luckily the BS-11 and the nanoBTS don't seem to care.
2011-01-13 23:20:45 +01:00
Harald Welte
7a69cf0a98 [RSL] add missing hunk from commit 18b590de4a 2011-01-13 23:16:03 +01:00
Harald Welte
4bf40c090d [wireshark] some initial hackish patches to support HSLs Abis/IP 2011-01-13 11:03:51 +01:00
Harald Welte
18b590de4a RSL: add code to generate SACCH INFO MODIFY command
SACCH INFO MODIFY is intended to modify the SACCH content for a single
logical channel (as opposed to the default SACCH FILLING)
2011-01-13 00:08:17 +01:00
Harald Welte
32c0962b10 [BSC] Allow manual override of neighbor cell list
So far, OpenBSC simply assumed that all BTS's configured in openbsc.cfg are
neighbors of each other.  While this is true for small site installations,
it is definitely not true in most real world cases.  We now have the
following new commands at the 'configure bts' level:

'neighbor-list mode (auto|manual)' for selecting the mode

'neighbor-list (add|del) arfcn <0-1024>'
	for adding/deleting ARFCN in manual mode
2011-01-11 23:48:52 +01:00
Holger Hans Peter Freyther
9b5f1d7b43 wireshark: rebase the patches, rename and add a README
Add a short README mentioning the svn version they apply
to, how to rebase them in the future, and what they do.

The renaming is done to add a hint on in which order to
apply them. The abis_oml patch has been updated to some
value_string changes in epan, all patches now add the new
files to the CMakeLists.txt of epan as well.
2011-01-11 16:33:52 +01:00
Holger Hans Peter Freyther
3b0fd2b0b9 wireshark: Remove patches applied in upstream wireshark
These patches were applied to upstream wireshark as of
svn revision r35475.
2011-01-11 15:22:29 +01:00
Holger Hans Peter Freyther
8e3f0e7185 silent sms: Fix the silent SMS feature once again
It got broken in the refactoring of 20474ad029.
2011-01-10 17:04:06 +01:00
Holger Hans Peter Freyther
cdfcbee53b sms: Allow to specify the DCS for the SMS. 2011-01-10 15:34:09 +01:00
Holger Hans Peter Freyther
c464491b0b sms: Move the sms_from_text to gsm_04_11
Move the SMS from text code from the VTY interface into the
gsm_04_11.c code next to the sms_alloc and sms_free.
2011-01-10 15:21:34 +01:00
Holger Hans Peter Freyther
368a0a73d4 ipa: Only use one IPA number for Osmo extensions
Instead of using more numbers from the proto range we will
use the 0xee and then have a mini header with our new proto
id in there. For a start rename the use types to _OLD.
2011-01-07 16:54:46 +01:00
Holger Hans Peter Freyther
45c2184c7e mgcp: Return with NULL if we fail the size check. 2011-01-07 11:36:54 +01:00
Holger Hans Peter Freyther
f43f2fce82 mgcp: We want to count trunks starting from one. 2011-01-07 11:34:50 +01:00
Holger Hans Peter Freyther
9f239a2a0f mgcp: Parse a Digital Trunk endpoint name. 2011-01-06 19:35:10 +01:00
Holger Hans Peter Freyther
6adac17a10 mgcp: Include a MGCP Response String in the response
Switch to a \r\n at the end of the query. Both \n and \r\n
are valid according to the spec but this makes us match
responses of other equipment.
2011-01-06 19:35:10 +01:00
Holger Hans Peter Freyther
49b3ed2226 subscr: Stop stopping paging requests behind the back of subscr
The transaction layer was stopping paging requests that might or
might not have been owned by the transaction. This makes the subscr
code get stuck delivering requests. This code is mostly a band aid
and just makes sure that we will kick the queue if it is needed.
2011-01-06 14:52:53 +01:00
Holger Hans Peter Freyther
182c81f04e subscr: Remember if we need to call subscr_put_channel at the end.
Remember if this channel got opened due a paging response and in
that case when we close it down we will call subscr_put_channel
that will try to page the subscriber again. This highlights the
lack of a good subscriber management in the MSC code.
2011-01-06 14:52:53 +01:00
Holger Hans Peter Freyther
90c0aff174 paging: Handle the possible OOM message as well. 2011-01-06 14:52:53 +01:00
Holger Hans Peter Freyther
52ffb922c4 sms: Improve the logging of the paging callback. 2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
451eb29e37 subscr: Add a vty option to kick the queue. 2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
763b42a92a subscr: Dump the pending requests to help with debugging state. 2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
68c3bf6de8 subscr: Store the state of a subscr request for inspection. 2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
c02b12086c subscr: Fix subscr leaks in the KI code. 2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
fc857414ae subscr: Make it possible to clear pending requests for a subscriber 2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
ebdd3cbd89 subscr: Show the number of pending requests on this subscriber. 2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
ffccb77df0 subscr: Stop all paging requests if one is failing.
If one paging request is timing out the others will timeout soon
as well. With the current code the next timeout would expire the
next request in the queue. We will now stop all paging requests
and then issue a next paging request. So for both paging success
and failure we will now stop all the other requests.

This is mostly a workaround, one should count on how many
BTSes we are paging and wait for all failures before we remove
the item from the queue.
2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
f72b3d51fc subscr: Kick the queue in case of a paging timeout
Kick the queue in case the paging was timing out. No one is going
to call subscr_put_channel for us so we will do it on the subscriber.

There is also another problem with multiple BTS in the LAC and paging
timeout. We will need to remember how many BTSes we have paged.
2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
c29043ea24 msc: Attempt to fix a bug with 'stuck' SMS due RF failure on auth
If we have a RF failure between the paging response and the auth
success we will not inform the subscriber layer of the failed paging
and instead just 'drop' the SMS. In case we have not completed the
auth and close the channel we will now send an auth failure.
2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
701076e9d3 sms: Add new SMS requests to the end of the list. 2011-01-06 14:52:52 +01:00
Holger Hans Peter Freyther
96e9f08101 sms: Argh... reset the pending after we have cleared the queue. 2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
79eff7eeff sms: Fix crash by saving the gsm_network
The conn might be released during the loop and then conn->bts
is a null pointer and we end up crashing. Store the gsm_network
in a local variable and access this one.
2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
583e9aef33 sms: Show the amount of failures and the SMS we want to send.
Improve the debugging possibilities and print the failed attempts
and the sms that was attempted to be delivered. this should help
with debugging the code.
2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
dc53af6721 sms: Fix the log message and end with a new newline. 2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
725966d9b4 subscr: Make the subscr_put_channel work with the subscr
The active channel might or might not be gone when the transaction
has been released. Instead of passing an invalid subscriber conn
we will pass the subscr that is ref-counted and guranteed to be
valid at this point. subscr_put_channel could search the connections
for an active connection if that is ever needed.
2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
8e3eb584a8 mncc: Do not print the BTS at all as it might not be present
In contrast to the previous believe we may not have a conn here
as we are still paging for the sub. Instead of printing the BTS
print the lac where we think the subscriber is located.
2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
b56a6bbc55 mncc: bts can be NULL, attempt to find the bts from the transaction
Follow trans->conn->lchan to the BTS instead of using the BTS that
is guranteed to be NULL in the codepath we have entered here. The
trans->conn should still be there, and the lchan should be valid as
well as we have reordered the clear statements.
2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
50c5ff7b94 mncc: Do not use bts->nr as it might be NULL. 2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
ebd50a6fd2 bsc: Clear the hand-over in case the new_lchan is failing
When the new_lchan for handover is failing we should stop the
handover operation. This is fixing a crash that we get a timeout
on the lchan and have no conn set to it. Introduce a flag to
the bsc_clear_handover to not free the lchan. In case the ho_lchan
is failing we do not want to call lchan_release as it would
reset the state.
2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
f1ba09b2e6 misc: Remove unused variable from the function. 2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
1cc7184bc9 misc: Fix compiler warning about incompatible pointers 2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
02d45c00f5 misc: Fix warning about the cast. 2011-01-06 14:52:51 +01:00
Holger Hans Peter Freyther
f4152d1025 misc: Remove unused variable from the db. 2011-01-06 14:52:50 +01:00
Holger Hans Peter Freyther
54146271b6 misc: Forward declare the struct gsm_bts_trx_ts to avoid warning. 2011-01-06 14:52:50 +01:00
Holger Hans Peter Freyther
913bc032b9 mncc: Move the cc_tx_to_mncc code into the libbsc.a
The trau_mux likes to call cc_tx_to_mncc for each received
frame from the E1 link. Using a signal for each audio frame
is messy as well. The best thing I could think of is to put
this into the BSC to deref the pointer. The other option would
be to include the gsm_data.h in the mncc.h header and have
the method as inline.
2011-01-06 14:52:50 +01:00
Holger Hans Peter Freyther
59234a3eb2 mncc: Switch the header file from u_int to uint
Include stdint.h to have the C99 data types.
2011-01-06 14:52:50 +01:00
Holger Hans Peter Freyther
6c4d2443b4 rtp: Move the RTP Proxy code out of RSL into the BSC/MSC domain
Instead of creating the sockets in the RSL code we will do this
in the CRCX_ACK, MDCX_ACK, DLCX_IND signal handler of gsm_04_08.
Introduce a handover signal so we can repatch the RTP sockets in
the gsm_04_08 as well.
2011-01-06 14:31:16 +01:00
Harald Welte
04d362f79d fix spelling mistake in log message 2011-01-01 17:28:55 +01:00
Harald Welte
6349b7f15e re-order the sequence of events in bsc_api:handle_release()
This should make sure conn->lchan is valid throughout the release
cause, especially make trau_mux_unmap() happy that conn->lchan
still exists.
2011-01-01 17:28:49 +01:00
Harald Welte
624e89d3f7 [db] Fix double-quoting in libdbi backend 2011-01-01 17:28:43 +01:00
Harald Welte
b854b29e32 MNCC: avoid segfault in DEBUGP due to non-existing conn->lchan 2011-01-01 17:28:38 +01:00
Harald Welte
f0901f0067 [SGSN] Fix processing of RA Update Request regarding TLLI
In case we get a RA UPD REQ on a new cell (both served by the same
SGSN), the LLC stack should not allocate a ne LLE/LLME, as the latter
would reset the V(u)sent / V(u)recv to zero and make the MS discard
our responses.

Instead, whenever the LLC stack sees a foreign TLLI, it should always
convert it to the local TLLI before doing any lookup for a LLE/LLME.
2011-01-01 17:28:29 +01:00
Harald Welte
91c59c8cb5 MNCC: fix copy+paste mistake in log message and change it to DEBUG 2011-01-01 17:23:43 +01:00
Harald Welte
eb76c7a93f mncc_sock: Fix potential segfault in case MNCC app dies
We create a loop by not setting trans->callref = 0 before calling
trans_free(), as the latter would again send a MNCC_REL_IND up
the stack.

Also: Fix memory leak in case we try to read from mncc_sock
but socket is just gone.
2011-01-01 17:23:43 +01:00
Harald Welte
0d6f930785 mncc_sock: Use proper logging directives and levels, don't printf. 2011-01-01 17:23:43 +01:00
Harald Welte
02d9966053 MNCC: Introduce bsc_hack argument '-m' for enabling MNCC socket 2011-01-01 17:23:42 +01:00
Harald Welte
ea057d9350 mncc_sock: Add new 'mncc handler' function
This adds mncc_sock_from_cc() as a handler function for CC messages
to be passed to the MNCC interface.  If there is no MNCC socket
registered, we immediately release any CC related messages.

Together with flushing all established CC transaction at MNCC socket
close time, this ensures that all resources are released and no
new resources can be established until the MNCC applicaiton has
re-attached.
2011-01-01 17:23:42 +01:00
Harald Welte
29b64e9708 MNCC: pass the actual 'struct msgb' down the mncc_recv() callback
this is required as we no longer have a dequeue-handler that can take
care of free()ing the message after passing it to the MNCC handler.
2011-01-01 17:23:42 +01:00
Harald Welte
04dc88fb9d GSM 04.08 / MNCC interface: verbuse logging of incoming MNCC primitives 2011-01-01 17:23:42 +01:00
Harald Welte
371efe5955 mncc_sock: Clear all calls if MNCC application (LCR) disconnects 2011-01-01 17:23:42 +01:00
Harald Welte
49a2ddeec0 mncc_sock: Add an assert() in case our queue peek trick goes wrong 2011-01-01 17:23:42 +01:00
Harald Welte
e8e432dd59 MNCC: remove 'upqueue'
The MNCC messages now again get directly handled by the net->mncc_recv()
callback.  If the callee wants to put them in a queue, it' his business
to do that.
2011-01-01 17:23:42 +01:00
Harald Welte
fea236e27c MNCC: move cc_tx_to_mncc() from gsm_data.h into mncc.c 2011-01-01 17:23:41 +01:00
Harald Welte
31bbbf4e52 MNCC socket: Export MNCC interface via unix domain socket
Using this code we will soon be able to use LCR or other MNCC
applications via a unix domain socket.

The code is not actually used yet after this patch.
2011-01-01 17:23:41 +01:00
Harald Welte
76556376c3 MNCC: rename mncc_send() to mncc_tx_to_cc()
This name clearly indicates: MNCC api transmits to Call Control,
i.e. down from the L4/application into the L3 04.08 code.
2011-01-01 17:23:41 +01:00
Harald Welte
3e6376d20d MNCC: split into generic mncc.c and mncc_builtin.c
The built-in code to handle call switching inside OpenBSC is
now in mncc_builtin.c, whereas some core/utility functions remain
in mncc.c
2011-01-01 17:23:41 +01:00
Harald Welte
081e14d071 MNCC: make get_call_ref() function static 2011-01-01 17:23:41 +01:00
Harald Welte
e6da14fde4 MNCC: clarify naming / rename mncc_recv() to int_mncc_recv()
the int_ perfix (internal) symbolizes that this is the internal
MNCC handler code, receiving messages from the MNCC interface point.
2011-01-01 17:23:41 +01:00
Harald Welte
54209c2dce MNCC: rename mncc_upq_enqueue() to cc_tx_to_mncc()
The new function name clearly indicates: The Call Control
(TS 04.08, msc-side in OpenBSC) wants to transmit something to the
MNCC interface.
2011-01-01 17:23:41 +01:00
Harald Welte
9af6ddfcec License change: We are now AGPLv3+ instead of GPLv2+
The reason for this is quite simple: We want to make sure anyone
running a customized version of OpenBSC to operate a network will
have to release all custom modifiations to the source code.
2011-01-01 15:39:34 +01:00
Holger Hans Peter Freyther
08eebd59b7 lchan: Every SS_LCHAN signal now sends a struct lchan_sig_data
The SS_LCHAN signals now always include the lchan_sig_data. For
the measurement report it will optionally include the measurement
report as well. Attempt to update all handlers of this signal as well
2010-12-27 13:32:20 +01:00
Holger Hans Peter Freyther
9ae7b29e3a bsc: Some S_LCHAN signals don't provide an lchan
Check the signal and only continue if it is any of the
signals we want to handle. In the case of measurement
reports we would cast some random code to a lchan.
2010-12-27 12:30:12 +01:00
Holger Hans Peter Freyther
59f787a4c1 auth: Release the security operation after we sent out a message
The release might release the lchan we want to send the response
on. Reorder the code to first send the message and then give up
the security operation which might release the lchan.
2010-12-27 10:58:55 +01:00
Holger Hans Peter Freyther
8ce8d3a00d bsc: Avoid crashing when no lchan is present in the subscriber connection
If someone wants to send a message but we have no lchan anymore
we will now complain, delete the message and return.
2010-12-27 10:58:55 +01:00
Sylvain Munaut
cfcf7e84bd gsm_04_08_utils: Fix Channel Request mode for e0/e0 and neci=1
According to the specs (GSM 04.08 Table 9.9), the only possibility
if neci=1 and this cause is used is "Originating call and TCH/F is
needed"

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-27 00:59:23 +01:00
Holger Hans Peter Freyther
f64a20f2e8 db: Quote the IMEI string before passing it into the database. 2010-12-26 21:19:29 +01:00
Holger Hans Peter Freyther
9d3e2ec698 ho: Access the network after we are known to have an entry. 2010-12-26 21:19:29 +01:00
Holger Hans Peter Freyther
c839667324 ho: Set the conn to NULL before calling lchan_release
In case we fail to activate the lchan set the connection to
NULL before calling the lchan release function.
2010-12-26 21:19:28 +01:00
Harald Welte
019d0167b6 [db] Properly quote name and extension for SQL access 2010-12-26 19:20:15 +01:00
Harald Welte
c728eeaf9b SGSN: Avoid duplicate MM contexts in case MS and SGSN disagree on P-TMSI 2010-12-26 19:20:07 +01:00
Harald Welte
a9b473a3c2 SGSN: Implement network-initiated PDP CTX DEACT when GGSN restarts
If the GGSN restarts, its restart counter will increase.  We can
detect that and accordingly release/delete all PDP contexts for
that GGSN.
2010-12-26 19:20:03 +01:00
Harald Welte
3357add225 SGSN: some more comments 2010-12-26 19:19:56 +01:00
Holger Hans Peter Freyther
c407ba5ed2 Merge branch 'zecke/sms-queue' 2010-12-26 09:42:19 +01:00
Holger Hans Peter Freyther
5479fc80d5 sms: Make sure that this loop is broken from time to time. 2010-12-26 09:40:49 +01:00
Holger Hans Peter Freyther
203845730f sms: Rewrite the queue to find SMS harder.
With the old code it was possible that we first saw SMS that
we have already in the queue. In that case we had free slots
available but have not filled them. With his new loop we try
harder to find SMS we can send, it attempts (and should work)
to detect a loop to break the loop before finding SMS to deliver.
2010-12-26 09:40:48 +01:00
Holger Hans Peter Freyther
f7e2389eb6 sms: Move the finding of the next SMS to handle to a new method
Prepare changing the loop to fill all the available slots. Set
the last subscriber based on the SMS query.
2010-12-26 09:40:48 +01:00
Holger Hans Peter Freyther
a37e3bc39a sms: Change the default values for the sms_queue
Increase the number of SMS we will try to send at a time and
decrease the failures we handle before going to the next item. With
the default timeout we will attempt to page the subscriber for 60
seconds and we can increase the queue speed by going to the next
item faster.
2010-12-26 09:40:48 +01:00
Holger Hans Peter Freyther
a3a659ba5c sms: Workaround a bug in the db layer and update the data
The sync with the database might fail. Reread the updated
subscriber after we have written it. The source of this
failure is unknown.
2010-12-26 09:40:48 +01:00
Holger Hans Peter Freyther
445e615d03 sms: Always go through the database and the smsqueue to send messages
This is also fixing a memory and subscriber leak. Make sure to
always release the gsm_sms structure.
2010-12-26 09:40:48 +01:00
Holger Hans Peter Freyther
994dcbb201 sms: Allow setting amount of failures through the vty. 2010-12-26 09:40:30 +01:00
Holger Hans Peter Freyther
7e59c83d66 sms: Make the amount of failures configurable as well. 2010-12-26 09:40:03 +01:00
Holger Hans Peter Freyther
4dcc5e5f8a sms: Add vty command to clear the pending message 2010-12-26 09:40:03 +01:00
Holger Hans Peter Freyther
3c6f6c25a6 sms: Make the max_pending tunable via a vty runtime setting
Make it possible to change the max pending via the vty. This
can be useful to play with the performance of the queue.
2010-12-26 09:40:03 +01:00
Holger Hans Peter Freyther
7a0e166fb0 sms: Add vty command to trigger running the queue.
Allow to manually trigger running the queue. This can be useful
if SMS were manually added to the database or such.
2010-12-26 09:40:03 +01:00
Holger Hans Peter Freyther
81c0e2582f sms: Provide some simple vty command for the state of the SMS queue 2010-12-26 09:40:03 +01:00
Holger Hans Peter Freyther
17164061a6 sms: Begin sending SMS messages, handle failures
The sms queue will attempt to send one SMS per subscriber
to fill all the available slots. It will handle the case
where paging has not started, timed out or if there was
any kind of other failure. It is also retransmitting SMS
in case of failures.
2010-12-26 09:40:03 +01:00
Holger Hans Peter Freyther
11b28f9c26 sms: Introduce a SMS queue that will be responsible for delivery
The SMSqueue will be responsible of sending to the user. It will
do so in a loop and will also try not to overload the BTS. This
means the throughput of SMS will be limited.
2010-12-26 09:40:03 +01:00
Holger Hans Peter Freyther
04144c1905 sms: Create signal data for SMS with more information
This is providing access to the paging result, the sms,
the transaction. This will allow the SMS queue to do
decisions based on the source of the failure.
2010-12-26 09:40:02 +01:00
Holger Hans Peter Freyther
0eb7666efa sms: Dispatch a failed signal in many of the MT-sms points
This attempts to dispatch a signal whenever a MT-sms is failing. In
some cases, e.g. with freeing the transaction, this will also happen
for MO-sms.
2010-12-26 09:40:02 +01:00
Holger Hans Peter Freyther
41c5aaf62c sms: Use the SMS in the signals where it makes sense.
The signal_data was inconsistent. Sometimes we passed the transaction
and sometimes we passed the sms. Change it to always pass the sms. The
S_SMS_SMMA is a bit special as it does not involve any SMS.
2010-12-26 09:40:02 +01:00
Holger Hans Peter Freyther
69ac83dd54 sms: Add a simple SystemTap probe to see SQL queries
This will proble all queries done in the system. This can
help to identify some issues with libdbi's performance.
2010-12-26 09:40:02 +01:00
Holger Hans Peter Freyther
9d277d3b33 sms: Add a script to query for unsent SMS
This is generating the query statement. It can be used to
play with database indexes and such.
2010-12-26 09:40:02 +01:00
Holger Hans Peter Freyther
e3018c7ad6 sms: Add dummy script to create subscribers and SMS
This is creating 1000 subscribers and 30 SMS each. The SMS
itself is badly formatted (not a valid 7bit encoding) but
it should be enough for a stress test.
2010-12-26 09:40:02 +01:00
Holger Hans Peter Freyther
dd715bd2ee sms: Fix a small typo. 2010-12-25 21:39:04 +01:00
Holger Hans Peter Freyther
73b878a85a db: Introduce a limit in delivery attempts for the SMS search
We do not want to attempt submitting SMS that has failed for
too many times. The failure could be due RF failure or due
a bug in the message handling.
2010-12-25 21:39:04 +01:00
Holger Hans Peter Freyther
812dad0ff7 db: Add method to load a SMS by id. 2010-12-25 21:39:04 +01:00
Holger Hans Peter Freyther
e25445b864 subscr: Sync the database before sending the attached signal
If a signal handler accesses the database he will still see
the old lac. Make sure he is seeing the new one. Update the
subscriber from the database in case the query failed or other
things have changed.
2010-12-25 21:39:04 +01:00
Holger Hans Peter Freyther
3d76e44968 subscr: Print the lac of the subscriber. 2010-12-25 21:39:04 +01:00
Holger Hans Peter Freyther
d3baf415b1 paging: Introduce a GSM_PAGING_BUSY event for a special timeout
Start counting the attempts of each paging request and call
the callback with the PAGING_BUSY type when the paging request
timed out but the subscriber was not paged at all. This can
only happen with a huge paging backlog.
In case the system has so many pending paging
2010-12-25 21:39:04 +01:00
Holger Hans Peter Freyther
ee139e7253 Merge branch 'zecke/subscr' 2010-12-24 21:43:14 +01:00
Holger Hans Peter Freyther
abd0cac0c5 subscr: Add a VTY command to update the subscriber from the database. 2010-12-24 21:40:48 +01:00
Holger Hans Peter Freyther
c577ca1822 subscr: Add VTY command to purge subscribers that are held in memory
Call the subscr_purge_inactive function and mention how many
subscribers were removed from the RAM.
2010-12-24 21:40:48 +01:00
Holger Hans Peter Freyther
ae9006aeed subscr: Introduce VTY option to keep subscribers in ram. 2010-12-24 21:40:48 +01:00
Holger Hans Peter Freyther
f694d5f47a subscr: Introduce subscr_purge_inactive to free unused subscribers
Introduce a method that will remove all subscribers that have a
zero use count. This is useful if someone wants to purge subscribers
from memory or wants to disable the everything in RAM feature.
2010-12-24 21:40:47 +01:00
Holger Hans Peter Freyther
daee5ca7c1 subscr: Make it possible to keep subscribers in RAM.
This is implemented by not freeing the subscriber when the
reference count becomes smaller than zero. We hope that this
will save many database accesses during the congres.
2010-12-24 21:40:47 +01:00
Harald Welte
a29e43a26f BSC Call Control: Actually implement call statistics
The existing call realated statistics counters apparently were
never used.  This introduces a new set of counters, two for the
MO and MT case.
2010-12-24 16:07:40 +01:00
Harald Welte
75e2defc7f BSC VTY: Print some more of the already-generated statistics 2010-12-24 16:07:35 +01:00
Harald Welte
eafe22ca72 SGSN / GMM: Only allow non-roaming IMSIs
As we do not yet use the HLR from the SGSN, we allow all MS to
attach to our GPRS network.  However, if this is running in a public
environment, it could cause service interruption to users of commercial
GPRS networks.

Thus, we now check if the first 5 digits of the IMSI match the MCC/MNC
of the cell that they want to register to.  Thus, any subscribers with
SIM cards from real operators will no longer be accepted.
2010-12-24 15:42:26 +01:00
Harald Welte
2cafc4b309 BSC API: Make 'Got data in non active state' message as LOGL_INFO
LOGL_ERROR will make this message shpw up in everey default log
config.  However, as it seems, this is commonly observed in case
a MS still sends a MS STATUS (in respons to the MM INFO) at the
end of a location area update.

It might be best to actually change the channel release procedure
to make sure we can still pass such 'late' data to the MSC until
the time the Layer2 has been completely released.
2010-12-24 15:42:22 +01:00
Harald Welte
3a3c277b70 RSL: Make "waiting for SAPI=%d to be released" LOGL_DEBUG 2010-12-24 15:42:17 +01:00
Harald Welte
b29cea1d9c Fix some stupid typos resulting in compile errors. 2010-12-24 12:26:13 +01:00
Harald Welte
712ddbcd72 BSC VTY: Fix off-by-one / segfault in 'show bts NR' 2010-12-24 12:24:03 +01:00
Harald Welte
85bded8b50 BTS VTY: Order bts-trx-ts-lchan in 'show lchan' 2010-12-24 12:22:34 +01:00
Harald Welte
cd103a9a5d BSC VTY: Print the current mode of a dynamic TCH/F / PDCH 2010-12-24 12:14:52 +01:00
Harald Welte
026b4cab36 BSC VTY: Change order of elements in 'show timeslot' command
It's not logical to first show TS, then TRX, then BTS.  It should
always be ordered from big to small (BTS, TRX, TS)
2010-12-24 12:12:10 +01:00
Harald Welte
127af34eea BSC VTY: Remove extraneous 'else' from write_ts_single()
This caused the E1 parameters not to be displayed in case the channel
was using frequency hopping.
2010-12-24 12:07:07 +01:00
Harald Welte
274d015cbb BSC VTY: Fix 'show timeslot' command if BTS and/or TRX are specified 2010-12-24 12:05:03 +01:00
Harald Welte
f6bd340df6 GPRS/GMM: Correctly look up MM Context in RA Update
If a MS changes RA, the RA will arrive in the new cell using the old
TLLI (masked as foreign TLLI).  So we need to look-up the TLLI
in a special way, using the old RA as indicated in the 04.08 GMM
message.

There is still another bug remaining: As we somehow create a new LLC,
the sequence numbers of our responses start from 0 again, which is not
what the MS expects.  This needs to be fixed in a follow-up patch.
2010-12-23 23:38:02 +01:00
Harald Welte
985263e55f GPRS: enhance msgb headroom/tailroom for SGSN (GMM)
In the GPRS NS protocol stack, the amount of NS/BSSGP headers like MS RADIO
CAPA INFO can be quite long.  In order to fit the full user message and
those headers, we have to enlarge the head/tailroom of the msgb allocations.
2010-12-23 23:37:55 +01:00
Harald Welte
082b01f18e More verbose logging of authentication internals 2010-12-23 23:37:49 +01:00
Harald Welte
c9f499f7d3 IMM ASS REJ: Actually add t3122 parsing to vty code 2010-12-23 23:37:45 +01:00
Harald Welte
86dda08762 Authentication: use ENUM instead of magic numbers
This improves readability of the code...
2010-12-23 18:09:51 +01:00
Harald Welte
2862dcac58 Use 04.08 IMM ASS REJECT in case we run out of channels
If the user has a non-zero 'timer t3122' in the config file, we will
send an IMM ASS REJECT in case we run out of resources.
2010-12-23 14:41:50 +01:00
Harald Welte
d0d2b0b605 Dynamic PDC: Add VTY comand 'bts N trx M timeslot O pdch [de]activate'
On a nanoBTS, this command can be used to manually switch a given 'dynamic
pdch/tch' timeslot from one mode into the other.

There are no safeguards that the timeslot is not in use at the given time.
2010-12-23 14:41:44 +01:00
Harald Welte
53cd7ac44c Dynamic PDCH: rsl_ipacc_pdch_activate() operates on a timeslot
... not on the lchan.
2010-12-23 14:41:40 +01:00
Holger Hans Peter Freyther
d4e6872d6c gsm48: Release the LU procedure only after the TMSI REALL_COMPL
We send a LU Accept with the TMSI as the MI. According to the
spec the phone should store this new TMSI and send a TMSI
REALLOCATION COMPLETE to us. We will release the LU then and this
should trigger the release procedure.
2010-12-22 20:25:38 +01:00
Harald Welte
434bb3f39f MNCC: introduce mncc_upq_enqueue() wrapper around msgb_enqueue()
This wrapper will allow us to add queue related code at one single
location in the code as opposed to three locations.
2010-12-22 19:03:40 +01:00
Harald Welte
7ce5e259c9 mnccc.c: Add 2 line header describing what this file is all about 2010-12-22 19:03:40 +01:00
Holger Hans Peter Freyther
f93e8fabd8 gsm48: Use NULL instead of 0 for pointers in C. 2010-12-22 18:26:36 +01:00
Holger Hans Peter Freyther
6003d6b928 rsl: Remove unimplemented/unused rsl_paging_cmd_subscr
RSL should not know the details of a GSM Subscriber anyway.
2010-12-22 18:26:36 +01:00
Holger Hans Peter Freyther
28dcbc5ee5 misc: Remove gsm_subscriber.h from the db.h file
Reduce the dependencies on the header files.
2010-12-22 18:26:36 +01:00
Holger Hans Peter Freyther
c5faf66b82 misc: Reorder includes, move osmocore to the end 2010-12-22 18:26:36 +01:00
Holger Hans Peter Freyther
3547045c73 misc: Remove gsm_subscriber.h include to reduce dependencies. 2010-12-22 18:26:36 +01:00
Holger Hans Peter Freyther
e2fee354cf misc: Include abis_rsl.h to remove some compiler warnings
This was introduced by a recent change to gsm_data.h to include
less header files. We really need to access the RSL information
here so it is fine to include the file.
2010-12-22 18:26:36 +01:00
Harald Welte
c7782dec4a gsm48_tx_release_compl(): Don't use transaction after trans_free()
In commit 39e2eadc99 a bug was introduced
that used the 'trans' after trans_free() had already been called.

This became visible now when the openbsc+lcr combination was calling
an unknown/invalid telephone number in a MO call, resulting in
a segfault.
2010-12-21 19:33:19 +01:00
Holger Hans Peter Freyther
ceeddf87f5 Merge branch 'zecke/e1_speed' 2010-12-21 13:54:45 +01:00
Holger Hans Peter Freyther
d49fc5ae24 ts: Reduce the delay to 0 for OML and RSL
This is possible after not sending more than one OML command that
requires an extra ACK. For the RSL line we do not need any speed
limitation.
2010-12-21 13:53:42 +01:00
Holger Hans Peter Freyther
d85642a1a7 ts Make the e1inp_ts delay configurable
Currently the nanoBTS bootstrap code requires a high delay
otherwise we are not bringing the device up properly. Changing
the init code turns out harder than it seems like. So this is
a workaround for that to allow a high speed RSL/OML connection
after the bringup.

The line driver can have a default TS delay. It is set to the
current default for the nanoBTS and the BS11. For the ipaccess
case we will set the delay lower for the RSL connection and
inside the ipaccess-config we can set it low right away to
have fast firmware flashing and such.
2010-12-21 13:53:41 +01:00
Holger Hans Peter Freyther
6f615551a4 abis_nm: Band aid on OML initialisation by queuing messages
Instead of sending many messages we will queue the OML
messages and wait for the ACK/NACK before sending the
next message from the queue. We tag the msgb to remember
if we need to wait for an ack or not.

We keep the order of all messages, on ACKs and similiar
occassions we will drown the queue until we reach a message
that needs to be acked and then wait for that ack again.

Possible breakage can appear when we send an OML (e.g.
BS11 specific message) msg which does not need to be acked
through the abis_nm_sendmsg call. The fix will be to use
the _direct version of this method.

Re-Enable as it might have fixed something... who knows.

Conflicts:

	openbsc/include/openbsc/abis_nm.h
	openbsc/include/openbsc/gsm_data.h
	openbsc/src/abis_nm.c
	openbsc/src/gsm_data.c
2010-12-21 13:53:41 +01:00
Holger Hans Peter Freyther
39e6ba09c2 oml: In case we get a NACK, drop the OML connection and hope for the best
Assume that a NACK is a onetime failure and that on the next
attempt it will work better. If that is not the case we might
even send a reboot to the BTS.
2010-12-21 13:53:41 +01:00
Holger Hans Peter Freyther
c7a1a1fd2e oml: Another band aid for reliable BTS init...
Sometimes the operative change for the NSE is getting nacked,
this might be due that we send it before we get the OPSTART ACK
for this object class. Send it from the CELL availability as
a workaround. This init code needs to be changed to make these
dependencies work more reliable.
2010-12-21 13:53:41 +01:00
Holger Hans Peter Freyther
d9cdd056ff test: Make it compile but it is segfaulting on start now 2010-12-21 13:43:52 +01:00
Holger Hans Peter Freyther
2391b4c474 ho: On ho failure clear the subscriber connection
Forget about the ho_lchan inside the gsm_subscriber_connection
in case of a handover failure, also clear the gsm_subscriber_connection
pointer before the lchan is passed to the lchan_free routine.
2010-12-21 13:41:33 +01:00
Holger Hans Peter Freyther
90cdd28e6f ho: Make this allocation a child of the BSC talloc context
Do not use the NULL context for this allocation. It should hang
off the gsm_subscriber_connection but for now at least make it
the child of the BSC so it is showing up in the talloc report.
2010-12-21 13:41:33 +01:00
Harald Welte
63dbfc6a2b bsc_vty: Fix unknown 'use-dtx' config parser error
commit 5a3a61d88f introduces a DTX attribute
which is parsed as dtx-used, but written as use-dtx (and thus causes a parser
error).
2010-12-15 15:34:23 +01:00
Harald Welte
f604bba026 osmo-bsc: Make it compile against paging_request_stop() api change
The additional msgb argument was introduced by Sylvain in
c7ff2572a7
2010-12-15 15:33:08 +01:00
Harald Welte
ec073e9f5b bs11_config: more verbose output of ACK/NACK responses 2010-12-14 13:34:35 +01:00
Harald Welte
230cd6a720 bs11_config: fix help message about multi-drop (not 'port') 2010-12-14 13:28:43 +01:00
Harald Welte
5f5189e658 bs11_config: update copyright statement 2010-12-14 13:14:32 +01:00
Harald Welte
f751a10018 bs11_config: show the BPORT0 / BPORT1 configuration in 'query'
This introduces abis_nm_bs11_get_bport_line_cfg() and a parser for the result.
2010-12-14 12:52:16 +01:00
Harald Welte
7e72fa0250 bs11_config: Add option to set BPORT1 in multi-drop mode 2010-12-14 12:35:59 +01:00
Dieter Spaar
df30d40b98 Add mandatory routeing area IE to SUSPEND-NACK 2010-12-12 15:46:00 +01:00
Sylvain Munaut
98b53cba06 include: Add proper predeclaration for struct in mncc.h
We use them, so declare them. (avoid including all gsm_data.h)

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 23:04:27 +01:00
Sylvain Munaut
81a8bf1039 include: Small fixes to gsm_data.h
We don't really need openbsc/gsm_04_08.h or abis_rsl.h
But we do need some definition from libosmocore

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 23:04:27 +01:00
Sylvain Munaut
12e373c218 include: Add proper predeclaration for struct in system_information.h
We use them, so declare them. (avoid including all gsm_data.h)

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 23:04:26 +01:00
Sylvain Munaut
3f16da2032 include: Add proper predeclaration for struct in abis_rsl.h
We use them, so declare them. (avoid including all gsm_data.h)

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 23:04:26 +01:00
Sylvain Munaut
8a31a3fcee paging: Dispatch the SS_PAGING signals at the MSC code level
This way the channel is fully ready for use.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 23:04:26 +01:00
Sylvain Munaut
5a86e06eb3 auth/ciph: Enable securing of channel directly after paging response
This protects MT services

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 23:04:26 +01:00
Sylvain Munaut
0fbfd1bb52 gsm_04_08: Make gsm48_secure_channel available globally
Can't declare it in gsm_04_08.h tough ... gsm_cbfn is defined in
gsm_data.h and trying to include that in gsm_04_08 just creates a
huge mess.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 22:39:40 +01:00
Sylvain Munaut
567c8dc7c9 gsm_04_08: Use subscr_get_channel instead of directly paging_request
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 22:39:40 +01:00
Sylvain Munaut
c7ff2572a7 paging: Give the msgb that caused paging_stop up to the paging callback
The handler might need to know some info of the paging response

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 22:39:40 +01:00
Sylvain Munaut
1e24550d3d gsm_subscriber: Move the get_channel/put_channel logic in MSC part
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 22:39:40 +01:00
Sylvain Munaut
67706df7c2 gsm_04_08: Don't set ciphering manually but call gsm0808_cipher_mode
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 20:36:34 +01:00
Sylvain Munaut
e0b06b0293 bsc: Allow to configure Optional Cell Selection params from vty
The default values are those where the parameters are encoded
as '0' and they're not output in the config file if that case

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-12-01 20:23:34 +01:00
Harald Welte
6d42dbe35c wireshark: port abis_oml.patch to more recent version of wireshark
Some internals of the value_string_extended have changed
2010-12-01 00:04:09 +01:00
Harald Welte
db2c28aef6 wireshark: update HSL patch to add preferences on where to show HSL debug 2010-12-01 00:02:58 +01:00
Harald Welte
318105d58d wireshark: add patch to make IPA ports configurable preferences 2010-12-01 00:02:42 +01:00
Harald Welte
a36f0ede25 wireshark: More work on Ericsson OML (OM2000) dissector
We now decode virtually everything in a RBS startup.
2010-11-29 22:05:34 +01:00
Harald Welte
0326cd5ac9 wireshark: Add initial patch for adding Ericsson OML-in-HDLC-in-L2TP support
This also hooks up the RSL dissector with the Ericsson HLDC
2010-11-29 16:32:47 +01:00
Harald Welte
3b71247cd0 wireshakrk: add patch to display HSL debug messages in log 2010-11-29 15:58:58 +01:00
Holger Hans Peter Freyther
fbceea4f0f bsc: Add a command to set the ussd_welcome_text
Make the USSD welcome text configurable.
2010-11-26 00:12:24 +01:00
Holger Hans Peter Freyther
414bc4a1f4 mid-call: Do not lose the first word of the message 2010-11-26 00:06:58 +01:00
Holger Hans Peter Freyther
cf6f71aa7f mid-call: Make the mid-call behavior the default for switching things off
When switching the RF off we will always go through the grace
period, add a direct off mode to switch it off directly. Make
the query return a 'g' if we are in the process of switching
things over.
2010-11-26 00:06:15 +01:00
Holger Hans Peter Freyther
70c232f75a mid-call: Implement a timer to go from grace to off.
Start the timer... switch it off when we do the final
tranistion by a command.
2010-11-26 00:06:01 +01:00
Holger Hans Peter Freyther
bb62b3f053 mid-call: Rename ussd-grace to mid-call 2010-11-26 00:03:32 +01:00
Holger Hans Peter Freyther
625b6e4dab mid-call: Introduce a timeout to switch from grace to rf off. 2010-11-26 00:02:12 +01:00
Holger Hans Peter Freyther
d283db496f vty: For ipaccess we will dump if the OML connection is present 2010-11-26 00:00:22 +01:00
Holger Hans Peter Freyther
e17c030b76 test: Add shell script to drop the OML in fixed intervals 2010-11-26 00:00:21 +01:00
Holger Hans Peter Freyther
dab8e27755 ipaccess: Fix dropping the OML/RSL connection.
Use the ipaccess_drop_oml and ipaccess_drop_rsl functions
instead of closing the socket and hoping this is picked up
somehow. This just leads to some weird hangs. And gdb was
not really helpful to say where it was coming from.
2010-11-15 20:30:38 +01:00
Holger Hans Peter Freyther
e19d6fc1ee Merge branch 'zecke/osmo-bsc' 2010-11-15 20:07:10 +01:00
Holger Hans Peter Freyther
09a925b117 bsc: Add script to hang up the MSC connection every 58s 2010-11-15 20:06:50 +01:00
Holger Hans Peter Freyther
e9f7a0d3b9 bsc: Add wild scripts to do dial testing with a Motorola A1200 2010-11-15 20:06:50 +01:00
Holger Hans Peter Freyther
b4e72f881c bsc: Implement queuing of messages to the MSC before the con is established 2010-11-15 20:06:50 +01:00
Holger Hans Peter Freyther
16e958dc68 bsc: Use the BSC Filter to stop a paging_request 2010-11-15 20:06:50 +01:00
Holger Hans Peter Freyther
9c838ae069 bsc: Implement paging by creating a dummy subscr for the paging
In the future we should avoid using a gsm_subscriber at all
and pass the imsi/tmsi to the paging function directly. For
now we can use the old model for paging and go through the
gsm_subscriber. This has the benefit of load balancing on
the BTS and such.
2010-11-15 20:06:50 +01:00
Holger Hans Peter Freyther
b79c3c97a2 bsc: The ip.access rtp-payload has no useful meaning
Sending this as the RTP_PAYLOAD2 will produce a MDCX NACK
as we send the RTP_PAYLOAD in the CRCX. It does not seem to
be necessary to send anything != 0 for the RTP_PAYLOAD2.
2010-11-15 20:06:50 +01:00
Holger Hans Peter Freyther
620c2e678a bsc: Add thr audio module to send the MDCX message to the BTS 2010-11-15 20:06:50 +01:00
Holger Hans Peter Freyther
dbc698aef0 bsc: Implement DTAP coming from the MSC and forward to the BSC API 2010-11-15 20:06:50 +01:00
Holger Hans Peter Freyther
50c579b8c5 bsc: Implement the assignment command to the point of calling into the BSC API 2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
fae3c65938 bsc: Parse the cipher mode command and pass it to the BSC api. 2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
f1f57a84c1 bsc: Parse the CLEAR COMMAND and close the lchan and ack that 2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
863a55d44d bsc: Make bsc_queue_for_msc work on the osmo_bsc_sccp_con
The gsm_subscriber_connection can die before the SCCP connection
so we should work on the osmo_bsc_sccp_con.
2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
890dfc58ed bsc: Work on paging and parsing other messages
The paging is not implemented due bad/missing API in the
BSC API, the rest are simple stubs to be merged from the
on-waves/bsc-master.
2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
3485feb49b bsc: Add module for handling BSSAP input
The current implementation is a stub. The code from
bssap.c of on-waves/bsc-master will be migrated into
this new structure
2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
cf256d678f bsc: Implement sending a SCCP CR with the complete layer3 data 2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
933daaa016 bsc: Implement SCCP connection confirmed handling. 2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
af4b5fb13e bsc: Implement clearing the SCCP connection 2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
57d304871e bsc: Implement writing out UDT messages to a MSC Connection 2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
00f4cc22c8 bsc: Implement closing the connections when the MSC goes missing
Refactor the closing code of the CC timeout to a new function,
also make sure that the SCCP Connection is forced closed before
we destruct the connection for real.
2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
ca5c022a32 bsc: Implement sending a message toward the MSC. 2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
c97d9b4df1 bsc: Implement a CC timeout and the IT timeout, prepare the timers 2010-11-15 20:06:49 +01:00
Holger Hans Peter Freyther
7e9010892d bsc: Make open/close work on the sccp data 2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
b8781d2cd5 bsc: Start to open a SCCP connection and prepare timers and such. 2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
9b17c769b9 bsc: Work a bit on opening the SCCP connection to the MSC.
Most of the code is still stubs but the structure is a lot
cleaner than the one in the on-waves/bsc-master branch.
2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
2a8675e49a bsc: Add a mobile country code setting for the backbone. 2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
52d42abdb7 bsc: Implement scanning and changing messages from the MSC
This will change the LAI of a LU accept message to the LAI
used for the on-air network. It will also detect when to
send a welcome ussd to the subscriber.
2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
a54732d19d bsc: Add a method to scan messages coming from the MSC. 2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
d65305f5b4 bsc: Look for location updating requests in messages
Introduce the SCCP connection data and remember that
we were seeing a location updating request from a
different LAC.
2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
5bb874d2f5 bsc: Add a hook where we can scan for LU and other messages. 2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
cc48fb8083 bsc: Call into the SCCP layer to create a new connection. 2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
46c5ab3624 bsc: Reduce duplication with a macro. 2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
e46f1d6cc4 bsc: Implement sending an assignment failure 2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
c2b3270e93 bsc: Send a Clear Reques on RF Failures to the MSC. 2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
c8166f3a91 bsc: Implement sending a SAPI n Reject.
It is not clear that the link_id is setup correctly here.
2010-11-15 20:06:48 +01:00
Holger Hans Peter Freyther
58f2cf6494 bsc: Implement the DTAP callback and forward the data to the MSC 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
da488ae343 bsc: Implement sending the assignment complete to the network 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
2d2c910f2c bsc: Implement sending a Cipher Mode Complete message 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
4582586e24 bsc: Add a method that will queue the message on a MSC connection. 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
7225fd18e0 bsc: Add some basic checks to see if a SCCP connection is established 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
1999cf11b9 bsc: Complain about unimplemented stuff. 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
77cd95d5b5 bsc_api: Implement the assignment command for the BSC. 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
f05750ca24 bsc_api: Rework the signal handler to be extendable 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
abf962b096 bsc_api: Clear lchan->conn on lchan_release
Set conn to NULL before starting the release procedure, remove
code to check for a lchan->conn as it can not happen. If there
are any memleaks we will notice them.
Detach the lchan->conn from the channel before detaching.
2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
8d216c7756 bsc_api: Clear the conn->lchan before calling subscr_con_free 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
a2e5cb8601 bsc_api: Clear the conn of the failed lchan to avoid a runtime warning 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
a2828fa4bc bsc_api: Set the lchan->conn to NULL in all of the cases 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
088dde8173 bsc_api: Send a channel modify when we already have a TCH. 2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
7e50c8140b bsc_api: Plug a theoretical window for the RLL callbacks
The timedout could come between lchan_release and the
S_CHALLOC_FREED signal. In the future we might want to
use the gsm0808_clear to stop the RLL timeouts and such.
2010-11-15 20:06:47 +01:00
Holger Hans Peter Freyther
8d380dcadd bsc_api: Change submit dtap to allow to automatically use the SACH
For SAPI=3 on a TCH it might be nice to use the SACH to submit
the message. The api allows to automatically use the SACH if
a message like this is submitted.
2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
2603c1f545 bsc_api: Clarify the parameters of the assignment command 2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
4be7d41a50 bsc_api: Implement sending the cipher mode method
This will set the encryption algorithm, key and then
send the RR Cipher Mode message to the MS. The method
is also verifying the input.
2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
2f169d64dd bsc_api: Make the cipher_mode take the 'include imei sv' argument
The cipher mode command should enable encryption and send the
right RR message to the other side.
2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
45b575fd94 bsc_api: The rr_cause is optional, pass it as a pointer 2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
66dcd925c6 bsc_api: Nuke the clear complete from the API.
There is no place where it can be called. Whoever is calling
the gsm0808_clear method should generate the clear complete
as the result.
2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
46caa3048d bsc_api: Provide the link_id in the dtap callback. 2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
b094171c9f bsc_api: Add needed parameters to the assignment complete callback
Provide the chosen channel and more information in the assignment
complete method.
2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
e1996f013c bsc_api: The cipher mode is not a message on the air interface
The cipher mode reject will be send in case the BSC is not
able to support the requested cipher. So this reject can be
handled by however attempts to enable ciphering.
2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
6c199e7d99 bsc_api: Look into the msg and call the right API functions
For certain messages we will need to call other GSM0808 functions. To
keep the bsc_hack working we will try to send this through the normal
messages first and then fallback to dtap if no handler is registered.

The gsm_04_08.c code is not forced to handle the IPA activation
and channel modify ack anymore. This is done transparently by the
BSC API now.
2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
fce9307553 bsc_api: Change the cause to a uint8_t for now
The RR Cause can only be one byte. Change from uint16_t to uint8_t for that.
2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
05c68841a8 bsc_api: Fix a use after free error in the Clear Request path
The implementation of bsc_hack would call subscr_con_free before
the BSC API has had the chance to call gsm0808_clear to try to
release other channels. Fix that by adding a return value.
2010-11-15 20:06:46 +01:00
Holger Hans Peter Freyther
85334f1309 paging: Move the paging data into the paging.h 2010-11-15 20:06:45 +01:00
Holger Hans Peter Freyther
8dfd241bc6 subscr: Add method to find an active subscriber
This is used by the paging code of the osmo_bsc. When we get
a paging response there should be an active subscriber with
the TMSI or IMSI and we can stop paging. There is no need to
allocate a new subscriber.
2010-11-15 20:06:45 +01:00
Holger Hans Peter Freyther
d740b688dc subscr: Add the subscr_get_or_create from the on-waves/bsc-master branch
Create a subscriber based on a known IMSI, search the list of
active subscribers if there is already someone like this.
2010-11-15 20:06:45 +01:00
Holger Hans Peter Freyther
928ca743db subscr: Move the TMSI reserved into the gsm_data
Put it into the gsm_data.h to avoid requiring MSC code
in the BSC code paths.
2010-11-15 20:06:45 +01:00
Holger Hans Peter Freyther
8cc59036e6 rsl: Allow to hardcode the RTP Payload
In case of a inflexible network it is better to hardcode
the rtp payload to a given type. E.g. when using AMR5.9 on
a TCH/F and TCH/H having the same payload is helpful. For
now this will be only used by the osmo-bsc.
2010-11-15 20:06:45 +01:00
Holger Hans Peter Freyther
ecd94a4b45 misc: Introduce a --enable-coverage mode to build with gprof coverage
This adds a test coverage build. One can use gcov and lcov on the
resulting data afterwards to see which code paths were executed and
which were not.
2010-11-15 20:06:45 +01:00
Holger Hans Peter Freyther
0b369c582b e1_input: Fix compiler warning by using offsetof
Use the offsetof/__builtin_offsetof to determine the
offset of a variable inside a structure instead of going
via a NULL pointer and taking the address.

This fixes:
warning: variably modified ‘dummyhalen_offset’ at file scope
2010-11-09 23:11:29 +01:00
Andreas Eversberg
5652cfc0e8 mark andreas@eversberg.eu as 'extern' for lcr 2010-11-09 13:39:43 +01:00
Holger Hans Peter Freyther
1406977e7e nat: Verify that the endpoint from the assignment command exists
Make sure that the MSC endpoint exists on the NAT, otherwise
we end up trying to free this endpoint when the SCCP connection
is taken down and will corrupt our memory. This issue started
to pop up as we have reduced the number of endpoints to 60
to allow transcoding on them.
2010-11-04 17:14:41 +01:00
Holger Hans Peter Freyther
f3d1ae7072 bsc: Add simple SCCP binding code. 2010-11-03 16:40:03 +01:00
Holger Hans Peter Freyther
0425c38feb bsc: Fix crash when making a MSC connection.
Use the right types that are passed as void..
2010-11-03 14:46:56 +01:00
Holger Hans Peter Freyther
7bf66c5a6e bsc: Add the audio codec list command to list preferred codecs 2010-11-03 13:56:27 +01:00
Holger Hans Peter Freyther
fe16622bf5 bsc: Add the rtp-base command to osmo-bsc 2010-11-03 13:56:26 +01:00
Holger Hans Peter Freyther
45f9e69ac5 bsc: Add the ip.access rtp-payload command known from bsc_msc_ip 2010-11-03 13:56:26 +01:00
Holger Hans Peter Freyther
4de1116356 bsc: Readd the core network code setting
This will instruct the BSC to patch messages and replace
the old network code with the new one.
2010-11-03 13:56:26 +01:00
Holger Hans Peter Freyther
5b848f37cf bsc: Fix the name of the local vty variable. 2010-11-03 13:11:14 +01:00
200 changed files with 15258 additions and 3419 deletions

0
README Normal file
View File

2
openbsc/.gitignore vendored
View File

@@ -9,6 +9,7 @@ openbsc.pc
bsc_hack
bsc_msc_ip
bsc_mgcp
src/bsc/osmo-bsc
*.*~
*.sw?
@@ -49,3 +50,4 @@ tests/sccp/sccp_test
tests/sms/sms_test
tests/timer/timer_test
src/openbsc.cfg*

View File

@@ -1,285 +1,624 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
TERMS AND CONDITIONS
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
0. Definitions.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
"This License" refers to version 3 of the GNU Affero General Public License.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
A "covered work" means either the unmodified Program or a work based
on the Program.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
1. Source Code.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
The Corresponding Source for a work in source code form is that
same work.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
2. Basic Permissions.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
13. Remote Network Interaction; Use with the GNU General Public License.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
14. Revised Versions of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
NO WARRANTY
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
15. Disclaimer of Warranty.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
END OF TERMS AND CONDITIONS
16. Limitation of Liability.
How to Apply These Terms to Your New Programs
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -287,53 +626,36 @@ free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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
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.
GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<http://www.gnu.org/licenses/>.

View File

@@ -44,10 +44,12 @@ AC_ARG_ENABLE([osmo-bsc], [AS_HELP_STRING([--enable-osmo-bsc], [Build the Osmo B
AM_CONDITIONAL(BUILD_BSC, test "x$osmo_ac_build_bsc" = "xyes")
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.27)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.1.19)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.1.28)
dnl checks for header files
AC_HEADER_STDC
AC_CHECK_HEADERS(dahdi/user.h,,AC_MSG_WARN(DAHDI input driver will not be built))
dnl Checks for typedefs, structures and compiler characteristics
@@ -62,6 +64,20 @@ AC_COMPILE_IFELSE([char foo;],
CFLAGS="$saved_CFLAGS"
AC_SUBST(SYMBOL_VISIBILITY)
# Coverage build taken from WebKit's configure.in
AC_MSG_CHECKING([whether to enable code coverage support])
AC_ARG_ENABLE(coverage,
AC_HELP_STRING([--enable-coverage],
[enable code coverage support [default=no]]),
[],[enable_coverage="no"])
AC_MSG_RESULT([$enable_coverage])
if test "$enable_coverage" = "yes"; then
COVERAGE_CFLAGS="-ftest-coverage -fprofile-arcs"
COVERAGE_LDFLAGS="-ftest-coverage -fprofile-arcs"
AC_SUBST([COVERAGE_CFLAGS])
AC_SUBST([COVERAGE_LDFLAGS])
fi
dnl Generate the output
AM_CONFIG_HEADER(bscconfig.h)
@@ -81,4 +97,5 @@ AC_OUTPUT(
tests/db/Makefile
tests/channel/Makefile
tests/bsc-nat/Makefile
tests/mgcp/Makefile
Makefile)

View File

@@ -0,0 +1 @@
Some crazy scripts call testing... and MSC link failure simulation

View File

@@ -0,0 +1,8 @@
ABORT BUSY
ABORT 'NO CARRIER'
ABORT 'OK'
'' AT
SAY "Dialing a number\n"
'OK' ATD05660066;

View File

@@ -0,0 +1,11 @@
#!/bin/sh
# Evil dial script..
while true;
do
chat -v -f all_dial < /dev/ttyACM0 > /dev/ttyACM0
sleep 5s
chat -v -f hangup < /dev/ttyACM0 > /dev/ttyACM0
sleep 2s
done

View File

@@ -0,0 +1,6 @@
#!/bin/sh
sleep 3
echo "enable"
sleep 1
echo "drop bts connection 0 oml"
sleep 1

View File

@@ -0,0 +1,8 @@
#!/bin/sh
while true;
do
echo "Going to drop the OML connection"
./drop-oml.sh | telnet 127.0.0.1 4242
sleep 58m
done

View File

@@ -0,0 +1,4 @@
TIMEOUT 10
'' ^Z
SAY "Waiting for hangup confirm\n"
'' ATH;

View File

@@ -0,0 +1,8 @@
#!/bin/sh
while true;
do
echo "Kill the osmo-bsc"
/usr/bin/kill -s SIGUSR2 `pidof osmo-bsc`
sleep 58s
done

View File

@@ -0,0 +1,66 @@
"I create output for some simple SQL statements for the HLR db"
Eval [
"Create tables if they don't exist"
Transcript show: 'CREATE TABLE SMS (
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,
valid_until TIMESTAMP,
reply_path_req INTEGER NOT NULL,
status_rep_req INTEGER NOT NULL,
protocol_id INTEGER NOT NULL,
data_coding_scheme INTEGER NOT NULL,
ud_hdr_ind INTEGER NOT NULL,
dest_addr TEXT,
user_data BLOB,
header BLOB,
text TEXT);'; nl;
show: 'CREATE TABLE Subscriber (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created TIMESTAMP NOT NULL,
updated TIMESTAMP NOT NULL,
imsi NUMERIC UNIQUE NOT NULL,
name TEXT,
extension TEXT UNIQUE,
authorized INTEGER NOT NULL DEFAULT 0,
tmsi TEXT UNIQUE,
lac INTEGER NOT NULL DEFAULT 0);'; nl.
"Create some dummy subscribers"
num_sub := 1000.
num_sms := 30.
lac := 1.
Transcript show: 'BEGIN;'; nl.
1 to: num_sub do: [:each |
Transcript show: 'INSERT INTO Subscriber
(imsi, created, updated, authorized, lac, extension)
VALUES
(%1, datetime(''now''), datetime(''now''), 1, %2, %3);' %
{(274090000000000 + each). lac. each}; nl.
].
1 to: num_sms do: [:sms |
1 to: num_sub do: [:sub |
Transcript show: 'INSERT INTO SMS
(created, sender_id, receiver_id, valid_until,
reply_path_req, status_rep_req, protocol_id,
data_coding_scheme, ud_hdr_ind, dest_addr,
text) VALUES
(datetime(''now''), 1, %1, ''2222-2-2'',
0, 0, 0,
0, 0, ''123456'',
''abc'');' % {sub}; nl.
]
].
Transcript show: 'COMMIT;'; nl.
]

View File

@@ -0,0 +1,10 @@
"Query for one SMS"
Eval [
1 to: 100 do: [:each |
Transcript show: 'SELECT SMS.* FROM SMS
JOIN Subscriber ON SMS.receiver_id = Subscriber.id
WHERE SMS.id >= 1 AND SMS.sent IS NULL AND Subscriber.lac > 0
ORDER BY SMS.id LIMIT 1;'; nl.
].
]

View File

@@ -0,0 +1,5 @@
probe process("/usr/lib/libsqlite3.so.0.8.6").function("sqlite3_get_table")
{
a = user_string($zSql);
printf("sqlite3_get_table called '%s'\n", a);
}

View File

@@ -1,2 +1,2 @@
/usr/sbin/bs11_config
/usr/sbin/isdnsync
/usr/bin/bs11_config
/usr/bin/isdnsync

View File

@@ -1,2 +1,2 @@
/usr/sbin/bsc_mgcp
/usr/bin/bsc_mgcp
/usr/bin/osmo-bsc

View File

@@ -1 +1 @@
/usr/sbin/osmo-gbproxy
/usr/bin/osmo-gbproxy

View File

@@ -1,3 +1,3 @@
/usr/sbin/ipaccess-config
/usr/sbin/ipaccess-find
/usr/sbin/ipaccess-proxy
/usr/bin/ipaccess-config
/usr/bin/ipaccess-find
/usr/bin/ipaccess-proxy

View File

@@ -1 +1 @@
/usr/sbin/bsc_hack
/usr/bin/bsc_hack

View File

@@ -1 +1 @@
/usr/sbin/osmo-sgsn
/usr/bin/osmo-sgsn

View File

@@ -11,7 +11,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \
gb_proxy.h gprs_sgsn.h gsm_04_08_gprs.h sgsn.h \
gprs_ns_frgre.h auth.h osmo_msc.h bsc_msc.h bsc_nat.h \
osmo_bsc_rf.h osmo_bsc.h network_listen.h bsc_nat_sccp.h \
osmo_msc_data.h osmo_bsc_grace.h
osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h
openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
openbscdir = $(includedir)/openbsc

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -138,6 +137,7 @@ int abis_nm_bs11_get_state(struct gsm_bts *bts);
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_get_bport_line_cfg(struct gsm_bts *bts, u_int8_t bport);
int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, u_int8_t bport, enum abis_bs11_line_cfg line_cfg);
int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect);
int abis_nm_bs11_restart(struct gsm_bts *bts);
@@ -160,18 +160,13 @@ int ipac_parse_bcch_info(struct ipac_bcch_info *binf, u_int8_t *buf);
const char *ipacc_testres_name(u_int8_t res);
/* Functions calling into other code parts */
enum nm_evt {
EVT_STATECHG_OPER,
EVT_STATECHG_ADM,
};
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_inst);
const char *nm_opstate_name(u_int8_t os);
const char *nm_avail_name(u_int8_t avail);
int nm_is_running(struct gsm_nm_state *s);
int abis_nm_vty_init(void);
void abis_nm_clear_queue(struct gsm_bts *bts);
#endif /* _NM_H */

View File

@@ -0,0 +1,62 @@
#ifndef OPENBSC_ABIS_OM2K_H
#define OPENBSC_ABIS_OM2K_H
/* Ericsson RBS 2xxx GSM O&M (OM2000) messages on the A-bis interface
* implemented based on protocol trace analysis, no formal documentation */
/* (C) 2010-2011 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 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 <http://www.gnu.org/licenses/>.
*
*/
struct abis_om2k_mo {
uint8_t class;
uint8_t bts;
uint8_t assoc_so;
uint8_t inst;
} __attribute__ ((packed));
struct om2k_is_conn_grp {
uint16_t icp1;
uint16_t icp2;
uint8_t cont_idx;
} __attribute__ ((packed));
extern const struct value_string om2k_mo_class_short_vals[];
int abis_om2k_rcvmsg(struct msgb *msg);
extern const struct abis_om2k_mo om2k_mo_cf;
int abis_om2k_tx_reset_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
int abis_om2k_tx_start_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
int abis_om2k_tx_status_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
int abis_om2k_tx_connect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
int abis_om2k_tx_disconnect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
int abis_om2k_tx_enable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
int abis_om2k_tx_disable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
int abis_om2k_tx_test_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
uint8_t operational);
int abis_om2k_tx_is_conf_req(struct gsm_bts *bts, struct om2k_is_conn_grp *cg,
unsigned int num_cg);
int abis_om2k_vty_init(void);
struct vty;
void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts);
#endif /* OPENBCS_ABIS_OM2K_H */

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -27,6 +26,12 @@
#include <osmocore/msgb.h>
struct gsm_bts;
struct gsm_lchan;
struct gsm_subscriber;
struct gsm_bts_trx_ts;
int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
const u_int8_t *data, int len);
int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
@@ -43,8 +48,6 @@ int rsl_chan_mode_modify_req(struct gsm_lchan *ts);
int rsl_encryption_cmd(struct msgb *msg);
int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
u_int8_t *ms_ident, u_int8_t chan_needed);
int rsl_paging_cmd_subscr(struct gsm_bts *bts, u_int8_t chan_needed,
struct gsm_subscriber *subscr);
int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val);
int rsl_data_request(struct msgb *msg, u_int8_t link_id);
@@ -59,7 +62,7 @@ int rsl_ipacc_crcx(struct gsm_lchan *lchan);
int rsl_ipacc_mdcx(struct gsm_lchan *lchan, u_int32_t ip,
u_int16_t port, u_int8_t rtp_payload2);
int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan);
int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act);
int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act);
int abis_rsl_rcvmsg(struct msgb *msg);
@@ -82,6 +85,9 @@ int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf);
int rsl_number_of_paging_subchannels(struct gsm_bts *bts);
int rsl_sacch_info_modify(struct gsm_lchan *lchan, u_int8_t type,
const u_int8_t *data, int len);
int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db);
int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm);

View File

@@ -4,6 +4,13 @@
struct gsm_auth_tuple;
struct gsm_subscriber;
enum auth_action {
AUTH_NOT_AVAIL = 0, /* No auth tuple available */
AUTH_DO_AUTH_THAN_CIPH = 1, /* Firsth authenticate, then cipher */
AUTH_DO_CIPH = 2, /* Only ciphering */
AUTH_DO_AUTH = 3, /* Only authentication, no ciphering */
};
int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
struct gsm_subscriber *subscr, int key_seq);

View File

@@ -12,25 +12,24 @@ struct bsc_api {
void (*sapi_n_reject)(struct gsm_subscriber_connection *conn, int dlci);
void (*cipher_mode_compl)(struct gsm_subscriber_connection *conn,
struct msgb *msg, uint8_t chosen_encr);
void (*cipher_mode_reject)(struct gsm_subscriber_connection *conn,
struct msgb *msg, uint16_t reason);
int (*compl_l3)(struct gsm_subscriber_connection *conn,
struct msgb *msg, uint16_t chosen_channel);
void (*dtap)(struct gsm_subscriber_connection *conn, struct msgb *msg);
void (*dtap)(struct gsm_subscriber_connection *conn, uint8_t link_id,
struct msgb *msg);
void (*assign_compl)(struct gsm_subscriber_connection *conn,
uint16_t rr_cause);
uint8_t rr_cause, uint8_t chosen_channel,
uint8_t encr_alg_id, uint8_t speech_mode);
void (*assign_fail)(struct gsm_subscriber_connection *conn,
uint16_t rr_cause);
void (*clear_request)(struct gsm_subscriber_connection *conn,
uint8_t cause, uint8_t *rr_cause);
int (*clear_request)(struct gsm_subscriber_connection *conn,
uint32_t cause);
void (*clear_compl)(struct gsm_subscriber_connection *conn);
};
int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id);
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_type, int audio);
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id, int allow_sach);
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate);
int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
uint8_t *key, int len);
const uint8_t *key, int len, int include_imeisv);
int gsm0808_page(struct gsm_bts *bts, unsigned int page_group,
unsigned int mi_len, uint8_t *mi, int chan_type);
int gsm0808_clear(struct gsm_subscriber_connection *conn);

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -4,18 +4,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -79,7 +78,9 @@ struct bsc_connection {
struct timer_list pong_timeout;
/* mgcp related code */
int endpoint_status[32];
char *_endpoint_status;
int number_multiplexes;
int max_endpoints;
int last_endpoint;
/* a back pointer */
@@ -125,6 +126,9 @@ struct bsc_config {
int forbid_paging;
/* audio handling */
int max_endpoints;
/* backpointer */
struct bsc_nat *nat;
@@ -257,6 +261,7 @@ struct bsc_nat {
/* create and init the structures */
struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token);
struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
void bsc_config_free(struct bsc_config *);
void bsc_config_add_lac(struct bsc_config *cfg, int lac);
void bsc_config_del_lac(struct bsc_config *cfg, int lac);
int bsc_config_handles_lac(struct bsc_config *cfg, int lac);
@@ -303,6 +308,7 @@ struct sccp_connections *bsc_nat_find_con_by_bsc(struct bsc_nat *, struct sccp_s
/**
* MGCP/Audio handling
*/
int bsc_mgcp_nr_multiplexes(int max_endpoints);
int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length);
int bsc_mgcp_assign_patch(struct sccp_connections *, struct msgb *msg);
void bsc_mgcp_init(struct sccp_connections *);

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -4,24 +4,23 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _CHAN_ALLOC_H
#define _CHAN_ALLOC_H
#include "gsm_subscriber.h"
#include "gsm_data.h"
struct gsm_subscriber_connection;

View File

@@ -3,18 +3,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -23,7 +22,14 @@
#include <sys/types.h>
#include <openbsc/gsm_subscriber.h>
struct gsm_equipment;
struct gsm_network;
struct gsm_auth_info;
struct gsm_auth_tuple;
struct gsm_sms;
struct gsm_subscriber;
enum gsm_subscriber_field;
/* one time initialisation */
int db_init(const char *name);
@@ -42,6 +48,7 @@ int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber);
int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, u_int32_t* token);
int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char *imei);
int db_sync_equipment(struct gsm_equipment *equip);
int db_subscriber_update(struct gsm_subscriber *subscriber);
/* auth info */
int db_get_authinfo_for_subscr(struct gsm_auth_info *ainfo,
@@ -55,8 +62,9 @@ int db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
/* SMS store-and-forward */
int db_sms_store(struct gsm_sms *sms);
struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id);
struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id);
struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id);
struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id, unsigned int failed);
struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr);
int db_sms_mark_sent(struct gsm_sms *sms);
int db_sms_inc_deliver_attempts(struct gsm_sms *sms);

View File

@@ -66,6 +66,8 @@ struct e1inp_ts {
struct {
/* list of all signalling links on this TS */
struct llist_head sign_links;
/* delay for the queue */
int delay;
/* timer when to dequeue next frame */
struct timer_list tx_timer;
} sign;
@@ -85,7 +87,11 @@ struct e1inp_ts {
/* ip.access driver has one fd for each ts */
struct bsc_fd fd;
} ipaccess;
struct {
/* DAHDI driver has one fd for each ts */
struct bsc_fd fd;
struct lapd_instance *lapd;
} dahdi;
} driver;
};
@@ -93,6 +99,8 @@ struct e1inp_driver {
struct llist_head list;
const char *name;
int (*want_write)(struct e1inp_ts *ts);
int (*line_update)(struct e1inp_line *line);
int default_delay;
};
struct e1inp_line {
@@ -110,11 +118,17 @@ struct e1inp_line {
/* register a driver with the E1 core */
int e1inp_driver_register(struct e1inp_driver *drv);
/* fine a previously registered driver */
struct e1inp_driver *e1inp_driver_find(const char *name);
/* register a line with the E1 core */
int e1inp_line_register(struct e1inp_line *line);
/* ensure a certain line exists, return pointer to it */
struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr);
/* get a line by its ID */
struct e1inp_line *e1inp_line_get(u_int8_t e1_nr);
/* create a line in the E1 input core */
struct e1inp_line *e1inp_line_create(u_int8_t e1_nr, const char *driver_name);
/* find a sign_link for given TEI and SAPI in a TS */
struct e1inp_sign_link *
@@ -165,4 +179,9 @@ int ipaccess_setup(struct gsm_network *gsmnet);
extern struct llist_head e1inp_driver_list;
extern struct llist_head e1inp_line_list;
int e1inp_vty_init(void);
void e1inp_init(void);
int _abis_nm_sendmsg(struct msgb *msg, int to_trx_oml);
#endif /* _E1_INPUT_H */

View File

@@ -4,6 +4,7 @@
#include <osmocore/msgb.h>
#include <openbsc/gprs_sgsn.h>
int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause);
int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
uint8_t cause, uint8_t pco_len, uint8_t *pco_v);
int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp);

View File

@@ -119,12 +119,17 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
/* Allocate a new SGSN MM context */
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli,
const struct gprs_ra_id *raid);
void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm);
enum pdp_ctx_state {
PDP_STATE_NONE,
PDP_STATE_CR_REQ,
PDP_STATE_CR_CONF,
/* 04.08 / Figure 6.2 / 6.1.2.2 */
PDP_STATE_INACT_PEND,
PDP_STATE_INACTIVE = PDP_STATE_NONE,
};
enum pdp_type {
@@ -162,6 +167,10 @@ struct sgsn_pdp_ctx {
uint32_t rx_gtp_snu;
//uint32_t charging_id;
int reordering_reqd;
struct timer_list timer;
unsigned int T; /* Txxxx number */
unsigned int num_T_exp; /* number of consecutive T expirations */
};
@@ -182,10 +191,12 @@ struct sgsn_ggsn_ctx {
uint32_t id;
unsigned int gtp_version;
struct in_addr remote_addr;
int remote_restart_ctr;
struct gsn_t *gsn;
};
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id);
struct apn_ctx {
@@ -202,4 +213,8 @@ extern struct llist_head sgsn_pdp_ctxts;
uint32_t sgsn_alloc_ptmsi(void);
/* High-level function to be called in case a GGSN has disappeared or
* ottherwise lost state (recovery procedure) */
int drop_all_pdp_for_ggsn(struct sgsn_ggsn_ctx *ggsn);
#endif /* _GPRS_SGSN_H */

View File

@@ -13,8 +13,8 @@ struct gsm_network;
struct gsm_trans;
struct gsm_subscriber_connection;
#define GSM48_ALLOC_SIZE 1024
#define GSM48_ALLOC_HEADROOM 128
#define GSM48_ALLOC_SIZE 2048
#define GSM48_ALLOC_HEADROOM 256
static inline struct msgb *gsm48_msgb_alloc(void)
{
@@ -25,6 +25,7 @@ static inline struct msgb *gsm48_msgb_alloc(void)
/* config options controlling the behaviour of the lower leves */
void gsm0408_allow_everyone(int allow);
void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause);
void gsm0408_clear_all_trans(struct gsm_network *net, int protocol);
int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg);
int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id);
@@ -44,9 +45,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan,
int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,
u_int8_t power_command, u_int8_t ho_ref);
int bsc_upqueue(struct gsm_network *net);
int mncc_send(struct gsm_network *net, int msg_type, void *arg);
int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg);
/* convert a ASCII phone number to call-control BCD */
int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,

View File

@@ -29,9 +29,12 @@ int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, struct msgb *msg);
struct gsm_sms *sms_alloc(void);
void sms_free(struct gsm_sms *sms);
struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, int dcs, const char *text);
void _gsm411_sms_trans_free(struct gsm_trans *trans);
int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
struct gsm_sms *sms);
int gsm411_send_sms(struct gsm_subscriber_connection *conn,
struct gsm_sms *sms);
void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn);
#endif

View File

@@ -5,6 +5,7 @@
struct osmo_msc_data;
struct osmo_bsc_sccp_con;
struct gsm_sms_queue;
enum gsm_phys_chan_config {
GSM_PCHAN_NONE,
@@ -44,9 +45,8 @@ enum gsm_chreq_reason_t {
};
#include <osmocore/timer.h>
#include <openbsc/gsm_04_08.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/system_information.h>
#include <openbsc/rest_octets.h>
#include <openbsc/mncc.h>
#include <osmocore/tlv.h>
@@ -56,6 +56,9 @@ enum gsm_chreq_reason_t {
#include <osmocore/utils.h>
#include <osmocore/rxlev_stat.h>
#include <osmocore/protocol/gsm_08_58.h>
#define TRX_NR_TS 8
#define TS_MAX_LCHAN 8
@@ -68,6 +71,9 @@ enum gsm_chreq_reason_t {
#define HARDCODED_BTS1_TS 6
#define HARDCODED_BTS2_TS 11
/* reserved according to GSM 03.03 § 2.4 */
#define GSM_RESERVED_TMSI 0xFFFFFFFF
enum gsm_hooks {
GSM_HOOK_NM_SWLOAD,
GSM_HOOK_RR_PAGING,
@@ -78,6 +84,7 @@ enum gsm_paging_event {
GSM_PAGING_SUCCEEDED,
GSM_PAGING_EXPIRED,
GSM_PAGING_OOM,
GSM_PAGING_BUSY,
};
enum bts_gprs_mode {
@@ -86,6 +93,8 @@ enum bts_gprs_mode {
BTS_GPRS_EGPRS = 2,
};
#define OBSC_NM_W_ACK_CB(__msgb) (__msgb)->cb[3]
/* the data structure stored in msgb->cb for openbsc apps */
struct openbsc_msgb_cb {
unsigned char *bssgph;
@@ -243,6 +252,7 @@ struct gsm_subscriber_connection {
/* Are we part of a special "silent" call */
int silent_call;
int put_channel;
/* bsc structures */
struct osmo_bsc_sccp_con *sccp_con;
@@ -252,6 +262,11 @@ struct gsm_subscriber_connection {
struct gsm_lchan *lchan;
struct gsm_lchan *ho_lchan;
struct gsm_bts *bts;
/* for assignment handling */
struct timer_list T10;
struct gsm_lchan *secondary_lchan;
};
struct gsm_lchan {
@@ -371,6 +386,8 @@ struct gsm_bts_trx {
struct gsm_e1_subslot rsl_e1_link;
u_int8_t rsl_tei;
struct e1inp_sign_link *rsl_link;
/* Some BTS (specifically Ericsson RBS) have a per-TRX OML Link */
struct e1inp_sign_link *oml_link;
struct gsm_nm_state nm_state;
struct tlv_parsed nm_attr;
@@ -406,14 +423,23 @@ enum gsm_bts_type {
GSM_BTS_TYPE_UNKNOWN,
GSM_BTS_TYPE_BS11,
GSM_BTS_TYPE_NANOBTS,
GSM_BTS_TYPE_RBS2000,
};
struct vty;
struct gsm_bts_model {
struct llist_head list;
enum gsm_bts_type type;
const char *name;
int (*oml_rcvmsg)(struct msgb *msg);
void (*config_write_bts)(struct vty *vty, struct gsm_bts *bts);
void (*config_write_trx)(struct vty *vty, struct gsm_bts_trx *trx);
void (*config_write_ts)(struct vty *vty, struct gsm_bts_trx_ts *ts);
struct tlv_definition nm_att_tlvdef;
struct bitvec features;
@@ -428,28 +454,6 @@ enum gsm_bts_features {
BTS_FEAT_HOPPING,
};
/**
* A pending paging request
*/
struct gsm_paging_request {
/* list_head for list of all paging requests */
struct llist_head entry;
/* the subscriber which we're paging. Later gsm_paging_request
* should probably become a part of the gsm_subscriber struct? */
struct gsm_subscriber *subscr;
/* back-pointer to the BTS on which we are paging */
struct gsm_bts *bts;
/* what kind of channel type do we ask the MS to establish */
int chan_type;
/* Timer 3113: how long do we try to page? */
struct timer_list T3113;
/* callback to be called in case paging completes */
gsm_cbfn *cbfn;
void *cbfn_param;
};
/*
* This keeps track of the paging status of one BTS. It
* includes a number of pending requests, a back pointer
@@ -487,6 +491,12 @@ struct gsm_bts_gprs_nsvc {
struct gsm_nm_state nm_state;
};
enum neigh_list_manual_mode {
NL_MODE_AUTOMATIC = 0,
NL_MODE_MANUAL = 1,
NL_MODE_MANUAL_SI5SEP = 2, /* SI2 and SI5 have separate neighbor lists */
};
/* One BTS */
struct gsm_bts {
/* list header in net->bts_list */
@@ -538,19 +548,24 @@ struct gsm_bts {
struct gsm_nm_state nm_state;
} site_mgr;
enum neigh_list_manual_mode neigh_list_manual_mode;
/* parameters from which we build SYSTEM INFORMATION */
struct {
struct gsm48_rach_control rach_control;
u_int8_t ncc_permitted;
struct gsm48_cell_sel_par cell_sel_par;
struct gsm48_si_selection_params cell_ro_sel_par; /* rest octet */
struct gsm48_cell_options cell_options;
struct gsm48_control_channel_descr chan_desc;
struct bitvec neigh_list;
struct bitvec cell_alloc;
struct bitvec si5_neigh_list;
struct {
/* bitmask large enough for all possible ARFCN's */
u_int8_t neigh_list[1024/8];
u_int8_t cell_alloc[1024/8];
/* If the user wants a different neighbor list in SI5 than in SI2 */
u_int8_t si5_neigh_list[1024/8];
} data;
} si_common;
@@ -577,6 +592,14 @@ struct gsm_bts {
} rack;
struct gsm_envabtse envabtse[4];
} bs11;
struct {
struct {
struct llist_head conn_groups;
} is;
struct {
struct llist_head conn_groups;
} con;
} rbs2000;
};
/* Not entirely sure how ip.access specific this is */
@@ -603,6 +626,10 @@ struct gsm_bts {
/* transceivers */
int num_trx;
struct llist_head trx_list;
/* Abis NM queue */
struct llist_head abis_queue;
int abis_nm_pend;
};
/* Some statistics of our network */
@@ -642,9 +669,10 @@ struct gsmnet_stats {
struct counter *rp_err_other;
} sms;
struct {
struct counter *dialled; /* total number of dialled calls */
struct counter *alerted; /* we alerted the other end */
struct counter *connected;/* how many calls were accepted */
struct counter *mo_setup;
struct counter *mo_connect_ack;
struct counter *mt_setup;
struct counter *mt_connect;
} call;
struct {
struct counter *rf_fail;
@@ -696,7 +724,7 @@ struct gsm_network {
struct gsmnet_stats stats;
/* layer 4 */
int (*mncc_recv) (struct gsm_network *net, int msg_type, void *arg);
int (*mncc_recv) (struct gsm_network *net, struct msgb *msg);
struct llist_head upqueue;
struct llist_head trans_list;
struct bsc_api *bsc_api;
@@ -715,6 +743,7 @@ struct gsm_network {
int T3115;
int T3117;
int T3119;
int T3122;
int T3141;
/* Radio Resource Location Protocol (TS 04.31) */
@@ -732,6 +761,11 @@ struct gsm_network {
/* MSC data in case we are a true BSC */
struct osmo_msc_data *msc_data;
int hardcoded_rtp_payload;
/* subscriber related features */
int keep_subscr;
struct gsm_sms_queue *sms_queue;
};
#define SMS_HDR_SIZE 128
@@ -758,7 +792,7 @@ struct gsm_sms {
struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_code,
int (*mncc_recv)(struct gsm_network *, int, void *));
int (*mncc_recv)(struct gsm_network *, struct msgb *));
struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
u_int8_t tsc, u_int8_t bsic);
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
@@ -781,12 +815,6 @@ char *gsm_ts_name(struct gsm_bts_trx_ts *ts);
char *gsm_lchan_name(struct gsm_lchan *lchan);
const char *gsm_lchans_name(enum gsm_lchan_state s);
enum gsm_e1_event {
EVT_E1_NONE,
EVT_E1_TEI_UP,
EVT_E1_TEI_DN,
};
void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr,
u_int8_t e1_ts, u_int8_t e1_ts_ss);
enum gsm_bts_type parse_btstype(const char *arg);

View File

@@ -13,13 +13,11 @@
#define GSM_MIN_EXTEN 20000
#define GSM_MAX_EXTEN 49999
/* reserved according to GSM 03.03 § 2.4 */
#define GSM_RESERVED_TMSI 0xFFFFFFFF
#define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001
#define tmsi_from_string(str) strtoul(str, NULL, 10)
struct vty;
struct gsm_equipment {
long long unsigned int id;
char imei[GSM_IMEI_LENGTH];
@@ -81,13 +79,27 @@ struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net,
const char *ext);
struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net,
unsigned long long id);
struct gsm_subscriber *subscr_get_or_create(struct gsm_network *net,
const char *imsi);
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason);
void subscr_put_channel(struct gsm_subscriber_connection *conn);
void subscr_put_channel(struct gsm_subscriber *subscr);
void subscr_get_channel(struct gsm_subscriber *subscr,
int type, gsm_cbfn *cbfn, void *param);
struct gsm_subscriber *subscr_active_by_tmsi(struct gsm_network *net,
uint32_t tmsi);
struct gsm_subscriber *subscr_active_by_imsi(struct gsm_network *net,
const char *imsi);
int subscr_pending_requests(struct gsm_subscriber *subscr);
int subscr_pending_clear(struct gsm_subscriber *subscr);
int subscr_pending_dump(struct gsm_subscriber *subscr, struct vty *vty);
int subscr_pending_kick(struct gsm_subscriber *subscr);
char *subscr_name(struct gsm_subscriber *subscr);
int subscr_purge_inactive(struct gsm_network *net);
void subscr_update_from_db(struct gsm_subscriber *subscr);
/* internal */
struct gsm_subscriber *subscr_alloc(void);
extern struct llist_head active_subscribers;

View File

@@ -9,6 +9,6 @@ struct gsm_subscriber_connection;
int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts);
/* clear any operation for this connection */
void bsc_clear_handover(struct gsm_subscriber_connection *conn);
void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan);
#endif /* _HANDOVER_H */

View File

@@ -14,14 +14,21 @@ struct ipaccess_head {
u_int8_t data[0];
} __attribute__ ((packed));
struct ipaccess_head_ext {
uint8_t proto;
uint8_t data[0];
} __attribute__ ((packed));
enum ipaccess_proto {
IPAC_PROTO_RSL = 0x00,
IPAC_PROTO_IPACCESS = 0xfe,
IPAC_PROTO_SCCP = 0xfd,
IPAC_PROTO_OML = 0xff,
/* OpenBSC extensions */
IPAC_PROTO_MGCP = 0xfc,
IPAC_PROTO_OSMO = 0xee,
IPAC_PROTO_MGCP_OLD = 0xfc,
};
enum ipaccess_msgtype {
@@ -32,7 +39,7 @@ enum ipaccess_msgtype {
IPAC_MSGT_ID_ACK = 0x06,
/* OpenBSC extension */
IPAC_MSGT_SCCP_STATE = 0xff,
IPAC_MSGT_SCCP_OLD = 0xff,
};
enum ipaccess_id_tags {

View File

@@ -1,23 +1,22 @@
/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
/*
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by On-Waves
* (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2011 by On-Waves
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -64,6 +63,7 @@ static inline int rtp_calculate_port(int multiplex, int base)
*/
struct mgcp_endpoint;
struct mgcp_config;
struct mgcp_trunk_config;
#define MGCP_ENDP_CRCX 1
#define MGCP_ENDP_DLCX 2
@@ -79,9 +79,9 @@ struct mgcp_config;
#define MGCP_POLICY_REJECT 5
#define MGCP_POLICY_DEFER 6
typedef int (*mgcp_realloc)(struct mgcp_config *cfg, int endpoint);
typedef int (*mgcp_change)(struct mgcp_config *cfg, int endpoint, int state);
typedef int (*mgcp_policy)(struct mgcp_config *cfg, int endpoint, int state, const char *transactio_id);
typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
typedef int (*mgcp_reset)(struct mgcp_config *cfg);
#define PORT_ALLOC_STATIC 0
@@ -102,18 +102,33 @@ struct mgcp_port_range {
int last_port;
};
struct mgcp_trunk_config {
struct llist_head entry;
struct mgcp_config *cfg;
int trunk_nr;
int trunk_type;
char *audio_name;
int audio_payload;
int audio_loop;
/* spec handling */
int force_realloc;
unsigned int number_endpoints;
struct mgcp_endpoint *endpoints;
};
struct mgcp_config {
int source_port;
char *local_ip;
char *source_addr;
unsigned int number_endpoints;
char *bts_ip;
char *call_agent_addr;
struct in_addr bts_in;
char *audio_name;
int audio_payload;
int audio_loop;
/* transcoder handling */
char *transcoder_ip;
@@ -127,24 +142,28 @@ struct mgcp_config {
struct mgcp_port_range transcoder_ports;
int endp_dscp;
/* spec handling */
int force_realloc;
mgcp_change change_cb;
mgcp_policy policy_cb;
mgcp_reset reset_cb;
mgcp_realloc realloc_cb;
void *data;
struct mgcp_endpoint *endpoints;
uint32_t last_call_id;
/* trunk handling */
struct mgcp_trunk_config trunk;
struct llist_head trunks;
/* only used for start with a static configuration */
int last_net_port;
int last_bts_port;
};
/* config management */
struct mgcp_config *mgcp_config_alloc(void);
int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg);
int mgcp_vty_init(void);
int mgcp_endpoints_allocate(struct mgcp_config *cfg);
int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
void mgcp_free_endp(struct mgcp_endpoint *endp);
int mgcp_reset_transcoder(struct mgcp_config *cfg);
@@ -152,7 +171,7 @@ int mgcp_reset_transcoder(struct mgcp_config *cfg);
* format helper functions
*/
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
struct msgb *mgcp_create_response_with_data(int code, const char *msg, const char *trans, const char *data);
struct msgb *mgcp_create_response_with_data(int code, const char *txt, const char *msg, const char *trans, const char *data);
/* adc helper */
static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)

View File

@@ -1,23 +1,22 @@
/* MGCP Private Data */
/*
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by On-Waves
* (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2011 by On-Waves
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -36,6 +35,11 @@ enum mgcp_connection_mode {
MGCP_CONN_LOOPBACK = 4,
};
enum mgcp_trunk_type {
MGCP_TRUNK_VIRTUAL,
MGCP_TRUNK_E1,
};
struct mgcp_rtp_state {
int initialized;
int patch;
@@ -94,6 +98,7 @@ struct mgcp_endpoint {
/* backpointer */
struct mgcp_config *cfg;
struct mgcp_trunk_config *tcfg;
/* port status for bts/net */
struct mgcp_rtp_end bts_end;
@@ -119,7 +124,7 @@ struct mgcp_endpoint {
struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
};
#define ENDPOINT_NUMBER(endp) abs(endp - endp->cfg->endpoints)
#define ENDPOINT_NUMBER(endp) abs(endp - endp->tcfg->endpoints)
struct mgcp_msg_ptr {
unsigned int start;
@@ -142,5 +147,8 @@ static inline int endp_back_channel(int endpoint)
return endpoint + 60;
}
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
#endif

View File

@@ -2,18 +2,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -23,7 +22,6 @@
#include "e1_input.h"
int mi_setup(int cardnr, struct e1inp_line *line, int release_l2);
int _abis_nm_sendmsg(struct msgb *msg);
int mi_e1_line_update(struct e1inp_line *line);
#endif

View File

@@ -7,18 +7,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -28,6 +27,12 @@
#include <osmocore/linuxlist.h>
#include <osmocore/mncc.h>
#include <stdint.h>
struct gsm_network;
struct msgb;
/* One end of a call */
struct gsm_call {
struct llist_head entry;
@@ -36,9 +41,9 @@ struct gsm_call {
void *net;
/* the 'local' transaction */
u_int32_t callref;
uint32_t callref;
/* the 'remote' transaction */
u_int32_t remote_ref;
uint32_t remote_ref;
};
#define MNCC_SETUP_REQ 0x0101
@@ -112,11 +117,11 @@ struct gsm_call {
struct gsm_mncc {
/* context based information */
u_int32_t msg_type;
u_int32_t callref;
uint32_t msg_type;
uint32_t callref;
/* which fields are present */
u_int32_t fields;
uint32_t fields;
/* data derived informations (MNCC_F_ based) */
struct gsm_mncc_bearer_cap bearer_cap;
@@ -147,13 +152,21 @@ struct gsm_mncc {
};
struct gsm_data_frame {
u_int32_t msg_type;
u_int32_t callref;
uint32_t msg_type;
uint32_t callref;
unsigned char data[0];
};
char *get_mncc_name(int value);
int mncc_recv(struct gsm_network *net, int msg_type, void *arg);
void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
/* input from CC code into mncc_builtin */
int int_mncc_recv(struct gsm_network *net, struct msgb *msg);
/* input from CC code into mncc_sock */
int mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg);
int mncc_sock_init(struct gsm_network *gsmnet);
#endif

View File

@@ -4,18 +4,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -5,6 +5,39 @@
#include "bsc_api.h"
struct sccp_connection;
struct osmo_bsc_sccp_con {
struct llist_head entry;
int ciphering_handled;
int rtp_port;
/* SCCP connection realted */
struct sccp_connection *sccp;
struct bsc_msc_connection *msc_con;
struct timer_list sccp_it_timeout;
struct timer_list sccp_cc_timeout;
struct llist_head sccp_queue;
unsigned int sccp_queue_size;
struct gsm_subscriber_connection *conn;
uint8_t new_subscriber;
};
struct bsc_api *osmo_bsc_api();
int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
int bsc_open_connection(struct osmo_bsc_sccp_con *sccp, struct msgb *msg);
int bsc_create_new_connection(struct gsm_subscriber_connection *conn);
int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp);
int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
int bsc_handle_udt(struct gsm_network *net, struct bsc_msc_connection *conn, struct msgb *msg, unsigned int length);
int bsc_handle_dt1(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int len);
#endif

View File

@@ -4,18 +4,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -2,6 +2,7 @@
#define OSMO_BSC_RF
#include <osmocore/write_queue.h>
#include <osmocore/timer.h>
struct gsm_network;
@@ -10,6 +11,18 @@ struct osmo_bsc_rf {
int policy;
struct bsc_fd listen;
struct gsm_network *gsm_network;
const char *last_state_command;
/* delay the command */
char last_request;
struct timer_list delay_cmd;
/* verify that RF is up as it should be */
struct timer_list rf_check;
/* some handling for the automatic grace switch */
struct timer_list grace_timeout;
};
struct osmo_bsc_rf_conn {

View File

@@ -6,18 +6,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -29,6 +28,12 @@
#include <osmocore/timer.h>
struct osmo_bsc_rf;
struct gsm_network;
struct gsm_audio_support {
uint8_t hr : 1,
ver : 7;
};
struct osmo_msc_data {
/* Connection data */
@@ -41,16 +46,31 @@ struct osmo_msc_data {
struct timer_list ping_timer;
struct timer_list pong_timer;
struct bsc_msc_connection *msc_con;
int core_ncc;
int core_mcc;
int rtp_base;
/* audio codecs */
struct gsm_audio_support **audio_support;
int audio_length;
/* mgcp agent */
struct write_queue mgcp_agent;
/* rf ctl related bits */
char *ussd_grace_txt;
char *mid_call_txt;
int mid_call_timeout;
struct osmo_bsc_rf *rf_ctl;
/* ussd welcome text */
char *ussd_welcome_txt;
};
int osmo_bsc_msc_init(struct gsm_network *network);
int osmo_bsc_sccp_init(struct gsm_network *gsmnet);
int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto);
int osmo_bsc_audio_init(struct gsm_network *network);
#endif

View File

@@ -3,18 +3,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -29,6 +28,31 @@
#include "gsm_subscriber.h"
#include <osmocore/timer.h>
/**
* A pending paging request
*/
struct gsm_paging_request {
/* list_head for list of all paging requests */
struct llist_head entry;
/* the subscriber which we're paging. Later gsm_paging_request
* should probably become a part of the gsm_subscriber struct? */
struct gsm_subscriber *subscr;
/* back-pointer to the BTS on which we are paging */
struct gsm_bts *bts;
/* what kind of channel type do we ask the MS to establish */
int chan_type;
/* Timer 3113: how long do we try to page? */
struct timer_list T3113;
/* How often did we ask the BTS to page? */
int attempts;
/* callback to be called in case paging completes */
gsm_cbfn *cbfn;
void *cbfn_param;
};
/* call once for every gsm_bts... */
void paging_init(struct gsm_bts *bts);
@@ -38,7 +62,8 @@ int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
/* stop paging requests */
void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr,
struct gsm_subscriber_connection *conn);
struct gsm_subscriber_connection *conn,
struct msgb *msg);
/* update paging load */
void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t);

View File

@@ -7,18 +7,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -47,6 +46,8 @@ enum signal_subsystems {
SS_IPAC_NWL,
SS_RF,
SS_MSC,
SS_HO,
SS_INPUT,
};
/* SS_PAGING signals */
@@ -61,6 +62,7 @@ enum signal_sms {
S_SMS_DELIVERED, /* A SMS has been successfully delivered to a MS */
S_SMS_SMMA, /* A MS tells us it has more space available */
S_SMS_MEM_EXCEEDED, /* A MS tells us it has no more space available */
S_SMS_UNKNOWN_ERROR, /* A MS tells us it has an error */
};
/* SS_ABISIP signals */
@@ -80,6 +82,8 @@ enum signal_nm {
S_NM_IPACC_RESTART_ACK, /* nanoBTS has send a restart ack */
S_NM_IPACC_RESTART_NACK,/* nanoBTS has send a restart ack */
S_NM_TEST_REP, /* GSM 12.21 Test Report */
S_NM_STATECHG_OPER, /* Operational State changed*/
S_NM_STATECHG_ADM, /* Administrative State changed */
};
/* SS_LCHAN signals */
@@ -125,6 +129,7 @@ enum signal_ipaccess {
enum signal_global {
S_GLOBAL_SHUTDOWN,
S_GLOBAL_BTS_CLOSE_OM,
};
/* SS_RF signals */
@@ -134,12 +139,24 @@ enum signal_rf {
S_RF_GRACE,
};
/* SS_INPUT signals */
enum signal_input {
S_INP_NONE,
S_INP_TEI_UP,
S_INP_TEI_DN,
S_INP_LINE_INIT,
S_INP_LINE_ALARM,
S_INP_LINE_NOALARM,
};
struct gsm_subscriber;
struct paging_signal_data {
struct gsm_subscriber *subscr;
struct gsm_bts *bts;
int paging_result;
/* NULL in case the paging didn't work */
struct gsm_subscriber_connection *conn;
};
@@ -155,6 +172,14 @@ struct ipacc_ack_signal_data {
u_int8_t msg_type;
};
struct nm_statechg_signal_data {
u_int8_t obj_class;
void *obj;
struct gsm_nm_state *old_state;
struct gsm_nm_state *new_state;
struct abis_om_obj_inst *obj_inst;
};
struct nm_nack_signal_data {
struct msgb *msg;
uint8_t mt;
@@ -170,6 +195,22 @@ struct rf_signal_data {
struct gsm_network *net;
};
struct sms_signal_data {
/* The transaction where this occured */
struct gsm_trans *trans;
/* Can be NULL for SMMA */
struct gsm_sms *sms;
/* int paging result. Only the ones with > 0 */
int paging_result;
};
struct lchan_signal_data {
/* The lchan the signal happened on */
struct gsm_lchan *lchan;
/* Measurement reports on this lchan */
struct gsm_meas_rep *mr;
};
enum signal_ns {
S_NS_RESET,
S_NS_BLOCK,
@@ -193,5 +234,22 @@ struct msc_signal_data {
struct osmo_msc_data *data;
};
/* handover */
enum signal_ho {
S_HANDOVER_ACK,
};
struct ho_signal_data {
struct gsm_lchan *old_lchan;
struct gsm_lchan *new_lchan;
};
struct input_signal_data {
int link_type;
uint8_t tei;
uint8_t sapi;
struct gsm_bts_trx *trx;
struct e1inp_line *line;
};
#endif

View File

@@ -0,0 +1,17 @@
#ifndef SMS_QUEUE_H
#define SMS_QUEUE_H
struct gsm_network;
struct gsm_sms_queue;
struct vty;
int sms_queue_start(struct gsm_network *, int in_flight);
int sms_queue_trigger(struct gsm_sms_queue *);
/* vty helper functions */
int sms_queue_stats(struct gsm_sms_queue *, struct vty* vty);
int sms_queue_set_max_pending(struct gsm_sms_queue *, int max);
int sms_queue_set_max_failure(struct gsm_sms_queue *, int fail);
int sms_queue_clear(struct gsm_sms_queue *);
#endif

View File

@@ -6,18 +6,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -5,6 +5,9 @@
#define GSM_MACBLOCK_LEN 23
struct gsm_bts;
enum osmo_sysinfo_type {
SYSINFO_TYPE_NONE,
SYSINFO_TYPE_1,
@@ -34,7 +37,7 @@ enum osmo_sysinfo_type {
typedef u_int8_t sysinfo_buf_t[GSM_MACBLOCK_LEN];
const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE];
extern const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE];
uint8_t gsm_sitype2rsl(enum osmo_sysinfo_type si_type);
const char *gsm_sitype_name(enum osmo_sysinfo_type si_type);
int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type);

View File

@@ -29,6 +29,9 @@ struct gsm_trans {
/* if traffic channel receive was requested */
int tch_recv;
/* is thats one paging? */
struct gsm_network **paging_request;
union {
struct {

View File

@@ -6,18 +6,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -4,18 +4,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -29,12 +29,18 @@ enum bsc_vty_node {
NS_NODE,
BSSGP_NODE,
OML_NODE,
E1INP_NODE,
NAT_NODE,
NAT_BSC_NODE,
MSC_NODE,
OM2K_NODE,
TRUNK_NODE,
};
extern int bsc_vty_is_config_node(struct vty *vty, int node);
extern void bsc_replace_string(void *ctx, char **dst, const char *newstr);
int bsc_vty_init(void);
int bsc_vty_init_extra(void);
#endif

View File

@@ -1,6 +1,6 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS)
AM_LDFLAGS = $(LIBOSMOCORE_LIBS)
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
# build current directory before building gprs
SUBDIRS = . ipaccess gprs
@@ -13,29 +13,31 @@ if BUILD_BSC
SUBDIRS += bsc
endif
sbin_PROGRAMS = bsc_hack bs11_config isdnsync bsc_mgcp
bin_PROGRAMS = bsc_hack bs11_config isdnsync bsc_mgcp
noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libmgcp.a
libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \
chan_alloc.c debug.c socket.c abis_nm_vty.c \
libbsc_a_SOURCES = abis_rsl.c abis_nm.c abis_om2000.c gsm_data.c gsm_04_08_utils.c \
chan_alloc.c debug.c socket.c abis_nm_vty.c abis_om2000_vty.c \
gsm_subscriber_base.c subchan_demux.c bsc_rll.c transaction.c \
trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c \
input/misdn.c input/ipaccess.c handover_logic.c \
talloc_ctx.c system_information.c rest_octets.c \
rtp_proxy.c bts_siemens_bs11.c bts_ipaccess_nanobts.c \
trau_frame.c trau_mux.c paging.c \
e1_config.c e1_input.c e1_input_vty.c \
input/misdn.c input/ipaccess.c input/dahdi.c input/lapd.c \
handover_logic.c talloc_ctx.c system_information.c rest_octets.c \
bts_siemens_bs11.c bts_ipaccess_nanobts.c bts_ericsson_rbs2000.c mncc_upqueue.c \
bts_unknown.c bsc_version.c bsc_api.c bsc_vty.c meas_rep.c gsm_04_80.c
libmsc_a_SOURCES = gsm_subscriber.c db.c \
mncc.c gsm_04_08.c gsm_04_11.c transaction.c \
mncc.c mncc_builtin.c mncc_sock.c \
gsm_04_08.c gsm_04_11.c transaction.c \
token_auth.c rrlp.c ussd.c silent_call.c \
handover_decision.c auth.c \
osmo_msc.c
osmo_msc.c rtp_proxy.c
libvty_a_SOURCES = common_vty.c
libmgcp_a_SOURCES = mgcp/mgcp_protocol.c mgcp/mgcp_network.c mgcp/mgcp_vty.c
bsc_hack_SOURCES = bsc_hack.c bsc_init.c bsc_vty.c vty_interface_layer3.c
bsc_hack_SOURCES = bsc_hack.c bsc_init.c bsc_vty.c vty_interface_layer3.c sms_queue.c
bsc_hack_LDADD = libmsc.a libbsc.a libvty.a libmsc.a \
-ldl -ldbi $(LIBCRYPT) $(LIBOSMOVTY_LIBS)
@@ -46,3 +48,5 @@ isdnsync_SOURCES = isdnsync.c
bsc_mgcp_SOURCES = mgcp/mgcp_main.c debug.c
bsc_mgcp_LDADD = libvty.a libmgcp.a $(LIBOSMOVTY_LIBS)
EXTRA_DIST = input/lapd.h

269
openbsc/src/a3a8.c Normal file
View File

@@ -0,0 +1,269 @@
/* An implementation of the GSM A3A8 algorithm. (Specifically, COMP128.)
*/
/* Copyright 1998, Marc Briceno, Ian Goldberg, and David Wagner.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the authors nor the names of the contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Coded in C merely because C is a much more precise, concise form of
* expression for these purposes. See Judge Patel if you have any problems
* with this...
* Of course, it's only authentication, so it should be exportable for the
* usual boring reasons.
*/
typedef unsigned char Byte;
#include <stdio.h>
/* #define TEST */
/*
* rand[0..15]: the challenge from the base station
* key[0..15]: the SIM's A3/A8 long-term key Ki
* simoutput[0..11]: what you'd get back if you fed rand and key to a real
* SIM.
*
* The GSM spec states that simoutput[0..3] is SRES,
* and simoutput[4..11] is Kc (the A5 session key).
* (See GSM 11.11, Section 8.16. See also the leaked document
* referenced below.)
* Note that Kc is bits 74..127 of the COMP128 output, followed by 10
* zeros.
* In other words, A5 is keyed with only 54 bits of entropy. This
* represents a deliberate weakening of the key used for voice privacy
* by a factor of over 1000.
*
* Verified with a Pacific Bell Schlumberger SIM. Your mileage may vary.
*
* Marc Briceno <marc@scard.org>, Ian Goldberg <iang@cs.berkeley.edu>,
* and David Wagner <daw@cs.berkeley.edu>
*/
void A3A8(/* in */ Byte rand[16], /* in */ Byte key[16],
/* out */ Byte simoutput[12]);
/* The compression tables. */
static const Byte table_0[512] = {
102,177,186,162, 2,156,112, 75, 55, 25, 8, 12,251,193,246,188,
109,213,151, 53, 42, 79,191,115,233,242,164,223,209,148,108,161,
252, 37,244, 47, 64,211, 6,237,185,160,139,113, 76,138, 59, 70,
67, 26, 13,157, 63,179,221, 30,214, 36,166, 69,152,124,207,116,
247,194, 41, 84, 71, 1, 49, 14, 95, 35,169, 21, 96, 78,215,225,
182,243, 28, 92,201,118, 4, 74,248,128, 17, 11,146,132,245, 48,
149, 90,120, 39, 87,230,106,232,175, 19,126,190,202,141,137,176,
250, 27,101, 40,219,227, 58, 20, 51,178, 98,216,140, 22, 32,121,
61,103,203, 72, 29,110, 85,212,180,204,150,183, 15, 66,172,196,
56,197,158, 0,100, 45,153, 7,144,222,163,167, 60,135,210,231,
174,165, 38,249,224, 34,220,229,217,208,241, 68,206,189,125,255,
239, 54,168, 89,123,122, 73,145,117,234,143, 99,129,200,192, 82,
104,170,136,235, 93, 81,205,173,236, 94,105, 52, 46,228,198, 5,
57,254, 97,155,142,133,199,171,187, 50, 65,181,127,107,147,226,
184,218,131, 33, 77, 86, 31, 44, 88, 62,238, 18, 24, 43,154, 23,
80,159,134,111, 9,114, 3, 91, 16,130, 83, 10,195,240,253,119,
177,102,162,186,156, 2, 75,112, 25, 55, 12, 8,193,251,188,246,
213,109, 53,151, 79, 42,115,191,242,233,223,164,148,209,161,108,
37,252, 47,244,211, 64,237, 6,160,185,113,139,138, 76, 70, 59,
26, 67,157, 13,179, 63, 30,221, 36,214, 69,166,124,152,116,207,
194,247, 84, 41, 1, 71, 14, 49, 35, 95, 21,169, 78, 96,225,215,
243,182, 92, 28,118,201, 74, 4,128,248, 11, 17,132,146, 48,245,
90,149, 39,120,230, 87,232,106, 19,175,190,126,141,202,176,137,
27,250, 40,101,227,219, 20, 58,178, 51,216, 98, 22,140,121, 32,
103, 61, 72,203,110, 29,212, 85,204,180,183,150, 66, 15,196,172,
197, 56, 0,158, 45,100, 7,153,222,144,167,163,135, 60,231,210,
165,174,249, 38, 34,224,229,220,208,217, 68,241,189,206,255,125,
54,239, 89,168,122,123,145, 73,234,117, 99,143,200,129, 82,192,
170,104,235,136, 81, 93,173,205, 94,236, 52,105,228, 46, 5,198,
254, 57,155, 97,133,142,171,199, 50,187,181, 65,107,127,226,147,
218,184, 33,131, 86, 77, 44, 31, 62, 88, 18,238, 43, 24, 23,154,
159, 80,111,134,114, 9, 91, 3,130, 16, 10, 83,240,195,119,253
}, table_1[256] = {
19, 11, 80,114, 43, 1, 69, 94, 39, 18,127,117, 97, 3, 85, 43,
27,124, 70, 83, 47, 71, 63, 10, 47, 89, 79, 4, 14, 59, 11, 5,
35,107,103, 68, 21, 86, 36, 91, 85,126, 32, 50,109, 94,120, 6,
53, 79, 28, 45, 99, 95, 41, 34, 88, 68, 93, 55,110,125,105, 20,
90, 80, 76, 96, 23, 60, 89, 64,121, 56, 14, 74,101, 8, 19, 78,
76, 66,104, 46,111, 50, 32, 3, 39, 0, 58, 25, 92, 22, 18, 51,
57, 65,119,116, 22,109, 7, 86, 59, 93, 62,110, 78, 99, 77, 67,
12,113, 87, 98,102, 5, 88, 33, 38, 56, 23, 8, 75, 45, 13, 75,
95, 63, 28, 49,123,120, 20,112, 44, 30, 15, 98,106, 2,103, 29,
82,107, 42,124, 24, 30, 41, 16,108,100,117, 40, 73, 40, 7,114,
82,115, 36,112, 12,102,100, 84, 92, 48, 72, 97, 9, 54, 55, 74,
113,123, 17, 26, 53, 58, 4, 9, 69,122, 21,118, 42, 60, 27, 73,
118,125, 34, 15, 65,115, 84, 64, 62, 81, 70, 1, 24,111,121, 83,
104, 81, 49,127, 48,105, 31, 10, 6, 91, 87, 37, 16, 54,116,126,
31, 38, 13, 0, 72,106, 77, 61, 26, 67, 46, 29, 96, 37, 61, 52,
101, 17, 44,108, 71, 52, 66, 57, 33, 51, 25, 90, 2,119,122, 35
}, table_2[128] = {
52, 50, 44, 6, 21, 49, 41, 59, 39, 51, 25, 32, 51, 47, 52, 43,
37, 4, 40, 34, 61, 12, 28, 4, 58, 23, 8, 15, 12, 22, 9, 18,
55, 10, 33, 35, 50, 1, 43, 3, 57, 13, 62, 14, 7, 42, 44, 59,
62, 57, 27, 6, 8, 31, 26, 54, 41, 22, 45, 20, 39, 3, 16, 56,
48, 2, 21, 28, 36, 42, 60, 33, 34, 18, 0, 11, 24, 10, 17, 61,
29, 14, 45, 26, 55, 46, 11, 17, 54, 46, 9, 24, 30, 60, 32, 0,
20, 38, 2, 30, 58, 35, 1, 16, 56, 40, 23, 48, 13, 19, 19, 27,
31, 53, 47, 38, 63, 15, 49, 5, 37, 53, 25, 36, 63, 29, 5, 7
}, table_3[64] = {
1, 5, 29, 6, 25, 1, 18, 23, 17, 19, 0, 9, 24, 25, 6, 31,
28, 20, 24, 30, 4, 27, 3, 13, 15, 16, 14, 18, 4, 3, 8, 9,
20, 0, 12, 26, 21, 8, 28, 2, 29, 2, 15, 7, 11, 22, 14, 10,
17, 21, 12, 30, 26, 27, 16, 31, 11, 7, 13, 23, 10, 5, 22, 19
}, table_4[32] = {
15, 12, 10, 4, 1, 14, 11, 7, 5, 0, 14, 7, 1, 2, 13, 8,
10, 3, 4, 9, 6, 0, 3, 2, 5, 6, 8, 9, 11, 13, 15, 12
}, *table[5] = { table_0, table_1, table_2, table_3, table_4 };
/*
* This code derived from a leaked document from the GSM standards.
* Some missing pieces were filled in by reverse-engineering a working SIM.
* We have verified that this is the correct COMP128 algorithm.
*
* The first page of the document identifies it as
* _Technical Information: GSM System Security Study_.
* 10-1617-01, 10th June 1988.
* The bottom of the title page is marked
* Racal Research Ltd.
* Worton Drive, Worton Grange Industrial Estate,
* Reading, Berks. RG2 0SB, England.
* Telephone: Reading (0734) 868601 Telex: 847152
* The relevant bits are in Part I, Section 20 (pages 66--67). Enjoy!
*
* Note: There are three typos in the spec (discovered by
* reverse-engineering).
* First, "z = (2 * x[n] + x[n]) mod 2^(9-j)" should clearly read
* "z = (2 * x[m] + x[n]) mod 2^(9-j)".
* Second, the "k" loop in the "Form bits from bytes" section is severely
* botched: the k index should run only from 0 to 3, and clearly the range
* on "the (8-k)th bit of byte j" is also off (should be 0..7, not 1..8,
* to be consistent with the subsequent section).
* Third, SRES is taken from the first 8 nibbles of x[], not the last 8 as
* claimed in the document. (And the document doesn't specify how Kc is
* derived, but that was also easily discovered with reverse engineering.)
* All of these typos have been corrected in the following code.
*/
void A3A8(/* in */ Byte rand[16], /* in */ Byte key[16],
/* out */ Byte simoutput[12])
{
Byte x[32], bit[128];
int i, j, k, l, m, n, y, z, next_bit;
/* ( Load RAND into last 16 bytes of input ) */
for (i=16; i<32; i++)
x[i] = rand[i-16];
/* ( Loop eight times ) */
for (i=1; i<9; i++) {
/* ( Load key into first 16 bytes of input ) */
for (j=0; j<16; j++)
x[j] = key[j];
/* ( Perform substitutions ) */
for (j=0; j<5; j++)
for (k=0; k<(1<<j); k++)
for (l=0; l<(1<<(4-j)); l++) {
m = l + k*(1<<(5-j));
n = m + (1<<(4-j));
y = (x[m]+2*x[n]) % (1<<(9-j));
z = (2*x[m]+x[n]) % (1<<(9-j));
x[m] = table[j][y];
x[n] = table[j][z];
}
/* ( Form bits from bytes ) */
for (j=0; j<32; j++)
for (k=0; k<4; k++)
bit[4*j+k] = (x[j]>>(3-k)) & 1;
/* ( Permutation but not on the last loop ) */
if (i < 8)
for (j=0; j<16; j++) {
x[j+16] = 0;
for (k=0; k<8; k++) {
next_bit = ((8*j + k)*17) % 128;
x[j+16] |= bit[next_bit] << (7-k);
}
}
}
/*
* ( At this stage the vector x[] consists of 32 nibbles.
* The first 8 of these are taken as the output SRES. )
*/
/* The remainder of the code is not given explicitly in the
* standard, but was derived by reverse-engineering.
*/
for (i=0; i<4; i++)
simoutput[i] = (x[2*i]<<4) | x[2*i+1];
for (i=0; i<6; i++)
simoutput[4+i] = (x[2*i+18]<<6) | (x[2*i+18+1]<<2)
| (x[2*i+18+2]>>2);
simoutput[4+6] = (x[2*6+18]<<6) | (x[2*6+18+1]<<2);
simoutput[4+7] = 0;
}
#ifdef TEST
int hextoint(char x)
{
x = toupper(x);
if (x >= 'A' && x <= 'F')
return x-'A'+10;
else if (x >= '0' && x <= '9')
return x-'0';
fprintf(stderr, "bad input.\n");
exit(1);
}
int main(int argc, char **argv)
{
Byte key[16], rand[16], simoutput[12];
int i;
if (argc != 3 || strlen(argv[1]) != 34 || strlen(argv[2]) != 34
|| strncmp(argv[1], "0x", 2) != 0
|| strncmp(argv[2], "0x", 2) != 0) {
fprintf(stderr, "Usage: %s 0x<key> 0x<rand>\n", argv[0]);
exit(1);
}
for (i=0; i<16; i++)
key[i] = (hextoint(argv[1][2*i+2])<<4)
| hextoint(argv[1][2*i+3]);
for (i=0; i<16; i++)
rand[i] = (hextoint(argv[2][2*i+2])<<4)
| hextoint(argv[2][2*i+3]);
A3A8(rand, key, simoutput);
printf("simoutput: ");
for (i=0; i<12; i++)
printf("%02X", simoutput[i]);
printf("\n");
return 0;
}
#endif

View File

@@ -6,18 +6,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -410,11 +409,31 @@ static struct msgb *nm_msgb_alloc(void)
}
/* Send a OML NM Message from BSC to BTS */
int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg)
static int abis_nm_queue_msg(struct gsm_bts *bts, struct msgb *msg)
{
msg->trx = bts->c0;
return _abis_nm_sendmsg(msg);
/* queue OML messages */
if (llist_empty(&bts->abis_queue) && !bts->abis_nm_pend) {
bts->abis_nm_pend = OBSC_NM_W_ACK_CB(msg);
return _abis_nm_sendmsg(msg, 0);
} else {
msgb_enqueue(&bts->abis_queue, msg);
return 0;
}
}
int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg)
{
OBSC_NM_W_ACK_CB(msg) = 1;
return abis_nm_queue_msg(bts, msg);
}
static int abis_nm_sendmsg_direct(struct gsm_bts *bts, struct msgb *msg)
{
OBSC_NM_W_ACK_CB(msg) = 0;
return abis_nm_queue_msg(bts, msg);
}
static int abis_nm_rcvmsg_sw(struct msgb *mb);
@@ -664,11 +683,10 @@ static int update_admstate(struct gsm_bts *bts, u_int8_t obj_class,
struct abis_om_obj_inst *obj_inst, u_int8_t adm_state)
{
struct gsm_nm_state *nm_state, new_state;
void *obj;
int rc;
struct nm_statechg_signal_data nsd;
obj = objclass2obj(bts, obj_class, obj_inst);
if (!obj)
nsd.obj = objclass2obj(bts, obj_class, obj_inst);
if (!nsd.obj)
return -EINVAL;
nm_state = objclass2nmstate(bts, obj_class, obj_inst);
if (!nm_state)
@@ -677,11 +695,15 @@ static int update_admstate(struct gsm_bts *bts, u_int8_t obj_class,
new_state = *nm_state;
new_state.administrative = adm_state;
rc = nm_state_event(EVT_STATECHG_ADM, obj_class, obj, nm_state, &new_state, obj_inst);
nsd.obj_class = obj_class;
nsd.old_state = nm_state;
nsd.new_state = &new_state;
nsd.obj_inst = obj_inst;
dispatch_signal(SS_NM, S_NM_STATECHG_ADM, &nsd);
nm_state->administrative = adm_state;
return rc;
return 0;
}
static int abis_nm_rx_statechg_rep(struct msgb *mb)
@@ -691,7 +713,6 @@ static int abis_nm_rx_statechg_rep(struct msgb *mb)
struct gsm_bts *bts = mb->trx->bts;
struct tlv_parsed tp;
struct gsm_nm_state *nm_state, new_state;
int rc;
DEBUGPC(DNM, "STATE CHG: ");
@@ -730,8 +751,13 @@ static int abis_nm_rx_statechg_rep(struct msgb *mb)
new_state.availability != nm_state->availability) {
/* Update the operational state of a given object in our in-memory data
* structures and send an event to the higher layer */
void *obj = objclass2obj(bts, foh->obj_class, &foh->obj_inst);
rc = nm_state_event(EVT_STATECHG_OPER, foh->obj_class, obj, nm_state, &new_state, &foh->obj_inst);
struct nm_statechg_signal_data nsd;
nsd.obj = objclass2obj(bts, foh->obj_class, &foh->obj_inst);
nsd.obj_class = foh->obj_class;
nsd.old_state = nm_state;
nsd.new_state = &new_state;
nsd.obj_inst = &foh->obj_inst;
dispatch_signal(SS_NM, S_NM_STATECHG_OPER, &nsd);
nm_state->operational = new_state.operational;
nm_state->availability = new_state.availability;
if (nm_state->administrative == 0)
@@ -754,6 +780,8 @@ static int rx_fail_evt_rep(struct msgb *mb)
struct abis_om_hdr *oh = msgb_l2(mb);
struct abis_om_fom_hdr *foh = msgb_l3(mb);
struct tlv_parsed tp;
const uint8_t *p_val;
char *p_text;
DEBUGPC(DNM, "Failure Event Report ");
@@ -763,6 +791,18 @@ static int rx_fail_evt_rep(struct msgb *mb)
DEBUGPC(DNM, "Type=%s ", event_type_name(*TLVP_VAL(&tp, NM_ATT_EVENT_TYPE)));
if (TLVP_PRESENT(&tp, NM_ATT_SEVERITY))
DEBUGPC(DNM, "Severity=%s ", severity_name(*TLVP_VAL(&tp, NM_ATT_SEVERITY)));
if (TLVP_PRESENT(&tp, NM_ATT_PROB_CAUSE)) {
p_val = TLVP_VAL(&tp, NM_ATT_PROB_CAUSE);
DEBUGPC(DNM, "Probable cause= %02X %02X %02X ", p_val[0], p_val[1], p_val[2]);
}
if (TLVP_PRESENT(&tp, NM_ATT_ADD_TEXT)) {
p_val = TLVP_VAL(&tp, NM_ATT_ADD_TEXT);
p_text = talloc_strndup(tall_bsc_ctx, (const char *) p_val, TLVP_LEN(&tp, NM_ATT_ADD_TEXT));
if (p_text) {
DEBUGPC(DNM, "Additional Text=%s ", p_text);
talloc_free(p_text);
}
}
DEBUGPC(DNM, "\n");
@@ -951,12 +991,30 @@ static int abis_nm_rx_lmt_event(struct msgb *mb)
return 0;
}
static void abis_nm_queue_send_next(struct gsm_bts *bts)
{
int wait = 0;
struct msgb *msg;
/* the queue is empty */
while (!llist_empty(&bts->abis_queue)) {
msg = msgb_dequeue(&bts->abis_queue);
wait = OBSC_NM_W_ACK_CB(msg);
_abis_nm_sendmsg(msg, 0);
if (wait)
break;
}
bts->abis_nm_pend = wait;
}
/* Receive a OML NM Message from BTS */
static int abis_nm_rcvmsg_fom(struct msgb *mb)
{
struct abis_om_hdr *oh = msgb_l2(mb);
struct abis_om_fom_hdr *foh = msgb_l3(mb);
u_int8_t mt = foh->msg_type;
int ret = 0;
/* check for unsolicited message */
if (is_report(mt))
@@ -983,6 +1041,7 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
nack_data.msg = mb;
nack_data.mt = mt;
dispatch_signal(SS_NM, S_NM_NACK, &nack_data);
abis_nm_queue_send_next(mb->trx->bts);
return 0;
}
#if 0
@@ -1004,13 +1063,13 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
switch (mt) {
case NM_MT_CHG_ADM_STATE_ACK:
return abis_nm_rx_chg_adm_state_ack(mb);
ret = abis_nm_rx_chg_adm_state_ack(mb);
break;
case NM_MT_SW_ACT_REQ:
return abis_nm_rx_sw_act_req(mb);
ret = abis_nm_rx_sw_act_req(mb);
break;
case NM_MT_BS11_LMT_SESSION:
return abis_nm_rx_lmt_event(mb);
ret = abis_nm_rx_lmt_event(mb);
break;
case NM_MT_CONN_MDROP_LINK_ACK:
DEBUGP(DNM, "CONN MDROP LINK ACK\n");
@@ -1023,7 +1082,8 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
break;
}
return 0;
abis_nm_queue_send_next(mb->trx->bts);
return ret;
}
static int abis_nm_rx_ipacc(struct msgb *mb);
@@ -1036,6 +1096,7 @@ static int abis_nm_rcvmsg_manuf(struct msgb *mb)
switch (bts_type) {
case GSM_BTS_TYPE_NANOBTS:
rc = abis_nm_rx_ipacc(mb);
abis_nm_queue_send_next(mb->trx->bts);
break;
default:
LOGP(DNM, LOGL_ERROR, "don't know how to parse OML for this "
@@ -1280,7 +1341,7 @@ static int sw_load_segment(struct abis_nm_sw *sw)
sw->obj_instance[0], sw->obj_instance[1],
sw->obj_instance[2]);
return abis_nm_sendmsg(sw->bts, msg);
return abis_nm_sendmsg_direct(sw->bts, msg);
}
/* 6.2.4 / 8.3.4 Load Data End */
@@ -1473,6 +1534,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
sw->cb_data, NULL);
rc = sw_fill_window(sw);
sw->state = SW_STATE_WAIT_SEGACK;
abis_nm_queue_send_next(mb->trx->bts);
break;
case NM_MT_LOAD_INIT_NACK:
if (sw->forced) {
@@ -1493,6 +1555,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
sw->cb_data, NULL);
sw->state = SW_STATE_ERROR;
}
abis_nm_queue_send_next(mb->trx->bts);
break;
}
break;
@@ -1513,6 +1576,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
sw->state = SW_STATE_WAIT_ENDACK;
rc = sw_load_end(sw);
}
abis_nm_queue_send_next(mb->trx->bts);
break;
case NM_MT_LOAD_ABORT:
if (sw->cbfn)
@@ -1534,6 +1598,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
NM_MT_LOAD_END_ACK, mb,
sw->cb_data, NULL);
rc = 0;
abis_nm_queue_send_next(mb->trx->bts);
break;
case NM_MT_LOAD_END_NACK:
if (sw->forced) {
@@ -1553,6 +1618,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
NM_MT_LOAD_END_NACK, mb,
sw->cb_data, NULL);
}
abis_nm_queue_send_next(mb->trx->bts);
break;
}
case SW_STATE_WAIT_ACTACK:
@@ -1566,6 +1632,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
sw->cbfn(GSM_HOOK_NM_SWLOAD,
NM_MT_ACTIVATE_SW_ACK, mb,
sw->cb_data, NULL);
abis_nm_queue_send_next(mb->trx->bts);
break;
case NM_MT_ACTIVATE_SW_NACK:
DEBUGP(DNM, "Activate Software NACK\n");
@@ -1575,6 +1642,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
sw->cbfn(GSM_HOOK_NM_SWLOAD,
NM_MT_ACTIVATE_SW_NACK, mb,
sw->cb_data, NULL);
abis_nm_queue_send_next(mb->trx->bts);
break;
}
case SW_STATE_NONE:
@@ -1959,7 +2027,6 @@ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb)
{
struct gsm_bts *bts = ts->trx->bts;
struct abis_om_hdr *oh;
u_int16_t arfcn = htons(ts->trx->arfcn);
u_int8_t zero = 0x00;
struct msgb *msg = nm_msgb_alloc();
u_int8_t len = 2 + 2;
@@ -2032,7 +2099,7 @@ int abis_nm_sw_act_req_ack(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i1,
if (nack)
msgb_tv_put(msg, NM_ATT_NACK_CAUSES, NM_NACK_OBJCLASS_NOTSUPP);
return abis_nm_sendmsg(bts, msg);
return abis_nm_sendmsg_direct(bts, msg);
}
int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *rawmsg)
@@ -2125,7 +2192,7 @@ int abis_nm_perform_test(struct gsm_bts *bts, u_int8_t obj_class,
{
struct abis_om_hdr *oh;
DEBUGP(DNM, "PEFORM TEST\n");
DEBUGP(DNM, "PEFORM TEST %s\n", get_value_string(test_names, test_nr));
if (!msg)
msg = nm_msgb_alloc();
@@ -2681,6 +2748,20 @@ int abis_nm_bs11_set_ext_time(struct gsm_bts *bts)
return abis_nm_sendmsg(bts, msg);
}
int abis_nm_bs11_get_bport_line_cfg(struct gsm_bts *bts, u_int8_t bport)
{
struct abis_om_hdr *oh;
struct msgb *msg = nm_msgb_alloc();
u_int8_t attr = NM_ATT_BS11_LINE_CFG;
oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
fill_om_fom_hdr(oh, 2+sizeof(attr), NM_MT_GET_ATTR,
NM_OC_BS11_BPORT, bport, 0xff, 0x02);
msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(attr), &attr);
return abis_nm_sendmsg(bts, msg);
}
int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, u_int8_t bport, enum abis_bs11_line_cfg line_cfg)
{
struct abis_om_hdr *oh;
@@ -3031,3 +3112,15 @@ int ipac_parse_bcch_info(struct ipac_bcch_info *binf, u_int8_t *buf)
return 0;
}
void abis_nm_clear_queue(struct gsm_bts *bts)
{
struct msgb *msg;
while (!llist_empty(&bts->abis_queue)) {
msg = msgb_dequeue(&bts->abis_queue);
msgb_free(msg);
}
bts->abis_nm_pend = 0;
}

View File

@@ -0,0 +1,87 @@
/* GSM Network Management (OML) messages on the A-bis interface
* Extensions for the ip.access A-bis over IP protocol*/
/* (C) 2008-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 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 <http://www.gnu.org/licenses/>.
*
*/
/* A list of all the 'embedded' attributes of ip.access */
enum ipa_embedded_att {
IPA_ATT_ARFCN_WHITELIST = 0x01,
IPA_ATT_ARFCN_BLACKLIST = 0x02,
IPA_ATT_FREQ_ERR_LIST = 0x03,
IPA_ATT_CHAN_USAGE_LIST = 0x04,
IPA_ATT_BCCH_INF_TYPE = 0x05,
IPA_ATT_BCCH_INF = 0x06,
IPA_ATT_CONFIG = 0x07,
IPA_ATT_RESULT_DETAILS = 0x08,
IPA_ATT_RXLEV_THRESH = 0x09,
IPA_ATT_FREQ_SYNC_OPT = 0x0a,
IPA_ATT_MAC_ADDR = 0x0b,
IPA_ATT_HW_SW_COMPAT_NR = 0x0c,
IPA_ATT_MANUF_SER_NR = 0x0d,
IPA_ATT_OEM_ID = 0x0e,
IPA_ATT_DATETIME_MANUF = 0x0f,
IPA_ATT_DATETIME_CALIB = 0x10,
IPA_ATT_BEACON_INF = 0x11,
IPA_ATT_FREQ_ERR = 0x12,
IPA_ATT_SNMP_COMM_STRING = 0x13,
IPA_ATT_SNMP_TRAP_ADDR = 0x14,
IPA_ATT_SNMP_TRAP_PORT = 0x15,
IPA_ATT_SNMP_MAN_ADDR = 0x16,
IPA_ATT_SNMP_SYS_CONTACT = 0x17,
IPA_ATT_FACTORY_ID = 0x18,
IPA_ATT_FACTORY_SERIAL = 0x19,
IPA_ATT_LOGGED_EVT_IND = 0x1a,
IPA_ATT_LOCAL_ADD_TEXT = 0x1b,
IPA_ATT_FREQ_BANDS = 0x1c,
IPA_ATT_MAX_TA = 0x1d,
IPA_ATT_CIPH_ALG = 0x1e,
IPA_ATT_CHAN_TYPES = 0x1f,
IPA_ATT_CHAN_MODES = 0x20,
IPA_ATT_GPRS_CODING_SCHEMES = 0x21,
IPA_ATT_RTP_FEATURES = 0x22,
IPA_ATT_RSL_FEATURES = 0x23,
IPA_ATT_BTS_HW_CLASS = 0x24,
IPA_ATT_BTS_ID = 0x25,
IPA_ATT_BCAST_L2_MSG = 0x26,
};
/* append an ip.access channel list to the given msgb */
static int ipa_chan_list_append(struct msgb *msg, u_int8_t ie,
u_int16_t *arfcns, int arfcn_count)
{
int i;
u_int8_t *u8;
u_int16_t *u16;
/* tag */
u8 = msgb_push(msg, 1);
*u8 = ie;
/* length in octets */
u16 = msgb_push(msg, 2);
*u16 = htons(arfcn_count * 2);
for (i = 0; i < arfcn_count; i++) {
u16 = msgb_push(msg, 2);
*u16 = htons(arfcns[i]);
}
return 0;
}

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

878
openbsc/src/abis_om2000.c Normal file
View File

@@ -0,0 +1,878 @@
/* Ericsson RBS 2xxx GSM O&M (OM2000) messages on the A-bis interface
* implemented based on protocol trace analysis, no formal documentation */
/* (C) 2010-2011 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 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 <http://www.gnu.org/licenses/>.
*
*/
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <osmocore/msgb.h>
#include <osmocore/tlv.h>
#include <osmocore/talloc.h>
#include <osmocore/utils.h>
#include <openbsc/gsm_data.h>
#include <openbsc/debug.h>
#include <openbsc/abis_nm.h>
#include <openbsc/abis_om2000.h>
#include <openbsc/signal.h>
#include <openbsc/e1_input.h>
#define OM_ALLOC_SIZE 1024
#define OM_HEADROOM_SIZE 128
/* use following functions from abis_nm.c:
* om2k_msgb_alloc()
* abis_om2k_sendmsg()
*/
struct abis_om2k_hdr {
struct abis_om_hdr om;
uint16_t msg_type;
struct abis_om2k_mo mo;
uint8_t data[0];
} __attribute__ ((packed));
enum abis_om2k_msgtype {
OM2K_MSGT_ABORT_SP_CMD = 0x0000,
OM2K_MSGT_ABORT_SP_COMPL = 0x0002,
OM2K_MSGT_ALARM_REP_ACK = 0x0004,
OM2K_MSGT_ALARM_REP_NACK = 0x0005,
OM2K_MSGT_ALARM_REP = 0x0006,
OM2K_MSGT_ALARM_STATUS_REQ = 0x0008,
OM2K_MSGT_ALARM_STATUS_REQ_ACK = 0x000a,
OM2K_MSGT_ALARM_STATUS_REQ_REJ = 0x000b,
OM2K_MSGT_ALARM_STATUS_RES_ACK = 0x000c,
OM2K_MSGT_ALARM_STATUS_RES_NACK = 0x000d,
OM2K_MSGT_ALARM_STATUS_RES = 0x000e,
OM2K_MSGT_CAL_TIME_RESP = 0x0010,
OM2K_MSGT_CAL_TIME_REJ = 0x0011,
OM2K_MSGT_CAL_TIME_REQ = 0x0012,
OM2K_MSGT_CON_CONF_REQ = 0x0014,
OM2K_MSGT_CON_CONF_REQ_ACK = 0x0016,
OM2K_MSGT_CON_CONF_REQ_REJ = 0x0017,
OM2K_MSGT_CON_CONF_RES_ACK = 0x0018,
OM2K_MSGT_CON_CONF_RES_NACK = 0x0019,
OM2K_MSGT_CON_CONF_RES = 0x001a,
OM2K_MSGT_CONNECT_CMD = 0x001c,
OM2K_MSGT_CONNECT_COMPL = 0x001e,
OM2K_MSGT_CONNECT_REJ = 0x001f,
OM2K_MSGT_DISABLE_REQ = 0x0028,
OM2K_MSGT_DISABLE_REQ_ACK = 0x002a,
OM2K_MSGT_DISABLE_REQ_REJ = 0x002b,
OM2K_MSGT_DISABLE_RES_ACK = 0x002c,
OM2K_MSGT_DISABLE_RES_NACK = 0x002d,
OM2K_MSGT_DISABLE_RES = 0x002e,
OM2K_MSGT_DISCONNECT_CMD = 0x0030,
OM2K_MSGT_DISCONNECT_COMPL = 0x0032,
OM2K_MSGT_DISCONNECT_REJ = 0x0033,
OM2K_MSGT_ENABLE_REQ = 0x0034,
OM2K_MSGT_ENABLE_REQ_ACK = 0x0036,
OM2K_MSGT_ENABLE_REQ_REJ = 0x0037,
OM2K_MSGT_ENABLE_RES_ACK = 0x0038,
OM2K_MSGT_ENABLE_RES_NACK = 0x0039,
OM2K_MSGT_ENABLE_RES = 0x003a,
OM2K_MSGT_FAULT_REP_ACK = 0x0040,
OM2K_MSGT_FAULT_REP_NACK = 0x0041,
OM2K_MSGT_FAULT_REP = 0x0042,
OM2K_MSGT_IS_CONF_REQ = 0x0060,
OM2K_MSGT_IS_CONF_REQ_ACK = 0x0062,
OM2K_MSGT_IS_CONF_REQ_REJ = 0x0063,
OM2K_MSGT_IS_CONF_RES_ACK = 0x0064,
OM2K_MSGT_IS_CONF_RES_NACK = 0x0065,
OM2K_MSGT_IS_CONF_RES = 0x0066,
OM2K_MSGT_OP_INFO = 0x0074,
OM2K_MSGT_OP_INFO_ACK = 0x0076,
OM2K_MSGT_OP_INFO_REJ = 0x0077,
OM2K_MSGT_RESET_CMD = 0x0078,
OM2K_MSGT_RESET_COMPL = 0x007a,
OM2K_MSGT_RESET_REJ = 0x007b,
OM2K_MSGT_START_REQ = 0x0084,
OM2K_MSGT_START_REQ_ACK = 0x0086,
OM2K_MSGT_START_REQ_REJ = 0x0087,
OM2K_MSGT_START_RES_ACK = 0x0088,
OM2K_MSGT_START_RES_NACK = 0x0089,
OM2K_MSGT_START_RES = 0x008a,
OM2K_MSGT_STATUS_REQ = 0x008c,
OM2K_MSGT_STATUS_RESP = 0x008e,
OM2K_MSGT_STATUS_REJ = 0x008f,
OM2K_MSGT_TEST_REQ = 0x0094,
OM2K_MSGT_TEST_REQ_ACK = 0x0096,
OM2K_MSGT_TEST_REQ_REJ = 0x0097,
OM2K_MSGT_TEST_RES_ACK = 0x0098,
OM2K_MSGT_TEST_RES_NACK = 0x0099,
OM2K_MSGT_TEST_RES = 0x009a,
OM2K_MSGT_NEGOT_REQ_ACK = 0x0104,
OM2K_MSGT_NEGOT_REQ_NACK = 0x0105,
OM2K_MSGT_NEGOT_REQ = 0x0106,
};
enum abis_om2k_dei {
OM2K_DEI_CAL_TIME = 0x0d,
OM2K_DEI_CON_CONN_LIST = 0x10,
OM2K_DEI_END_LIST_NR = 0x13,
OM2K_DEI_IS_CONN_LIST = 0x27,
OM2K_DEI_LIST_NR = 0x28,
OM2K_DEI_OP_INFO = 0x2e,
OM2K_DEI_NEGOT_REC1 = 0x90,
OM2K_DEI_NEGOT_REC2 = 0x91,
};
enum abis_om2k_mo_cls {
OM2K_MO_CLS_TRXC = 0x01,
OM2K_MO_CLS_TS = 0x03,
OM2K_MO_CLS_TF = 0x04,
OM2K_MO_CLS_IS = 0x05,
OM2K_MO_CLS_CON = 0x06,
OM2K_MO_CLS_DP = 0x07,
OM2K_MO_CLS_CF = 0x0a,
OM2K_MO_CLS_TX = 0x0b,
OM2K_MO_CLS_RX = 0x0c,
};
static const struct value_string om2k_msgcode_vals[] = {
{ 0x0000, "Abort SP Command" },
{ 0x0002, "Abort SP Complete" },
{ 0x0004, "Alarm Report ACK" },
{ 0x0005, "Alarm Report NACK" },
{ 0x0006, "Alarm Report" },
{ 0x0008, "Alarm Status Request" },
{ 0x000a, "Alarm Status Request Accept" },
{ 0x000b, "Alarm Status Request Reject" },
{ 0x000c, "Alarm Status Result ACK" },
{ 0x000d, "Alarm Status Result NACK" },
{ 0x000e, "Alarm Status Result" },
{ 0x0010, "Calendar Time Response" },
{ 0x0011, "Calendar Time Reject" },
{ 0x0012, "Calendar Time Request" },
{ 0x0014, "CON Configuration Request" },
{ 0x0016, "CON Configuration Request Accept" },
{ 0x0017, "CON Configuration Request Reject" },
{ 0x0018, "CON Configuration Result ACK" },
{ 0x0019, "CON Configuration Result NACK" },
{ 0x001a, "CON Configuration Result" },
{ 0x001c, "Connect Command" },
{ 0x001e, "Connect Complete" },
{ 0x001f, "Connect Rejecte" },
{ 0x0028, "Disable Request" },
{ 0x002a, "Disable Request Accept" },
{ 0x002b, "Disable Request Reject" },
{ 0x002c, "Disable Result ACK" },
{ 0x002d, "Disable Result NACK" },
{ 0x002e, "Disable Result" },
{ 0x0030, "Disconnect Command" },
{ 0x0032, "Disconnect Complete" },
{ 0x0033, "Disconnect Reject" },
{ 0x0034, "Enable Request" },
{ 0x0036, "Enable Request Accept" },
{ 0x0037, "Enable Request Reject" },
{ 0x0038, "Enable Result ACK" },
{ 0x0039, "Enable Result NACK" },
{ 0x003a, "Enable Result" },
{ 0x003c, "Escape Downlink Normal" },
{ 0x003d, "Escape Downlink NACK" },
{ 0x003e, "Escape Uplink Normal" },
{ 0x003f, "Escape Uplink NACK" },
{ 0x0040, "Fault Report ACK" },
{ 0x0041, "Fault Report NACK" },
{ 0x0042, "Fault Report" },
{ 0x0044, "File Package End Command" },
{ 0x0046, "File Package End Result" },
{ 0x0047, "File Package End Reject" },
{ 0x0048, "File Relation Request" },
{ 0x004a, "File Relation Response" },
{ 0x004b, "File Relation Request Reject" },
{ 0x004c, "File Segment Transfer" },
{ 0x004e, "File Segment Transfer Complete" },
{ 0x004f, "File Segment Transfer Reject" },
{ 0x0050, "HW Information Request" },
{ 0x0052, "HW Information Request Accept" },
{ 0x0053, "HW Information Request Reject" },
{ 0x0054, "HW Information Result ACK" },
{ 0x0055, "HW Information Result NACK" },
{ 0x0056, "HW Information Result" },
{ 0x0060, "IS Configuration Request" },
{ 0x0062, "IS Configuration Request Accept" },
{ 0x0063, "IS Configuration Request Reject" },
{ 0x0064, "IS Configuration Result ACK" },
{ 0x0065, "IS Configuration Result NACK" },
{ 0x0066, "IS Configuration Result" },
{ 0x0068, "Load Data End" },
{ 0x006a, "Load Data End Result" },
{ 0x006b, "Load Data End Reject" },
{ 0x006c, "Load Data Init" },
{ 0x006e, "Load Data Init Accept" },
{ 0x006f, "Load Data Init Reject" },
{ 0x0070, "Loop Control Command" },
{ 0x0072, "Loop Control Complete" },
{ 0x0073, "Loop Control Reject" },
{ 0x0074, "Operational Information" },
{ 0x0076, "Operational Information Accept" },
{ 0x0077, "Operational Information Reject" },
{ 0x0078, "Reset Command" },
{ 0x007a, "Reset Complete" },
{ 0x007b, "Reset Reject" },
{ 0x007c, "RX Configuration Request" },
{ 0x007e, "RX Configuration Request Accept" },
{ 0x007f, "RX Configuration Request Reject" },
{ 0x0080, "RX Configuration Result ACK" },
{ 0x0081, "RX Configuration Result NACK" },
{ 0x0082, "RX Configuration Result" },
{ 0x0084, "Start Request" },
{ 0x0086, "Start Request Accept" },
{ 0x0087, "Start Request Reject" },
{ 0x0088, "Start Result ACK" },
{ 0x0089, "Start Result NACK" },
{ 0x008a, "Start Result" },
{ 0x008c, "Status Request" },
{ 0x008e, "Status Response" },
{ 0x008f, "Status Reject" },
{ 0x0094, "Test Request" },
{ 0x0096, "Test Request Accept" },
{ 0x0097, "Test Request Reject" },
{ 0x0098, "Test Result ACK" },
{ 0x0099, "Test Result NACK" },
{ 0x009a, "Test Result" },
{ 0x00a0, "TF Configuration Request" },
{ 0x00a2, "TF Configuration Request Accept" },
{ 0x00a3, "TF Configuration Request Reject" },
{ 0x00a4, "TF Configuration Result ACK" },
{ 0x00a5, "TF Configuration Result NACK" },
{ 0x00a6, "TF Configuration Result" },
{ 0x00a8, "TS Configuration Request" },
{ 0x00aa, "TS Configuration Request Accept" },
{ 0x00ab, "TS Configuration Request Reject" },
{ 0x00ac, "TS Configuration Result ACK" },
{ 0x00ad, "TS Configuration Result NACK" },
{ 0x00ae, "TS Configuration Result" },
{ 0x00b0, "TX Configuration Request" },
{ 0x00b2, "TX Configuration Request Accept" },
{ 0x00b3, "TX Configuration Request Reject" },
{ 0x00b4, "TX Configuration Result ACK" },
{ 0x00b5, "TX Configuration Result NACK" },
{ 0x00b6, "TX Configuration Result" },
{ 0x00bc, "DIP Alarm Report ACK" },
{ 0x00bd, "DIP Alarm Report NACK" },
{ 0x00be, "DIP Alarm Report" },
{ 0x00c0, "DIP Alarm Status Request" },
{ 0x00c2, "DIP Alarm Status Response" },
{ 0x00c3, "DIP Alarm Status Reject" },
{ 0x00c4, "DIP Quality Report I ACK" },
{ 0x00c5, "DIP Quality Report I NACK" },
{ 0x00c6, "DIP Quality Report I" },
{ 0x00c8, "DIP Quality Report II ACK" },
{ 0x00c9, "DIP Quality Report II NACK" },
{ 0x00ca, "DIP Quality Report II" },
{ 0x00dc, "DP Configuration Request" },
{ 0x00de, "DP Configuration Request Accept" },
{ 0x00df, "DP Configuration Request Reject" },
{ 0x00e0, "DP Configuration Result ACK" },
{ 0x00e1, "DP Configuration Result NACK" },
{ 0x00e2, "DP Configuration Result" },
{ 0x00e4, "Capabilities HW Info Report ACK" },
{ 0x00e5, "Capabilities HW Info Report NACK" },
{ 0x00e6, "Capabilities HW Info Report" },
{ 0x00e8, "Capabilities Request" },
{ 0x00ea, "Capabilities Request Accept" },
{ 0x00eb, "Capabilities Request Reject" },
{ 0x00ec, "Capabilities Result ACK" },
{ 0x00ed, "Capabilities Result NACK" },
{ 0x00ee, "Capabilities Result" },
{ 0x00f0, "FM Configuration Request" },
{ 0x00f2, "FM Configuration Request Accept" },
{ 0x00f3, "FM Configuration Request Reject" },
{ 0x00f4, "FM Configuration Result ACK" },
{ 0x00f5, "FM Configuration Result NACK" },
{ 0x00f6, "FM Configuration Result" },
{ 0x00f8, "FM Report Request" },
{ 0x00fa, "FM Report Response" },
{ 0x00fb, "FM Report Reject" },
{ 0x00fc, "FM Start Command" },
{ 0x00fe, "FM Start Complete" },
{ 0x00ff, "FM Start Reject" },
{ 0x0100, "FM Stop Command" },
{ 0x0102, "FM Stop Complete" },
{ 0x0103, "FM Stop Reject" },
{ 0x0104, "Negotiation Request ACK" },
{ 0x0105, "Negotiation Request NACK" },
{ 0x0106, "Negotiation Request" },
{ 0x0108, "BTS Initiated Request ACK" },
{ 0x0109, "BTS Initiated Request NACK" },
{ 0x010a, "BTS Initiated Request" },
{ 0x010c, "Radio Channels Release Command" },
{ 0x010e, "Radio Channels Release Complete" },
{ 0x010f, "Radio Channels Release Reject" },
{ 0x0118, "Feature Control Command" },
{ 0x011a, "Feature Control Complete" },
{ 0x011b, "Feature Control Reject" },
{ 0, NULL }
};
/* TS 12.21 Section 9.4: Attributes */
static const struct value_string om2k_attr_vals[] = {
{ 0x00, "Accordance indication" },
{ 0x01, "Alarm Id" },
{ 0x02, "Alarm Data" },
{ 0x03, "Alarm Severity" },
{ 0x04, "Alarm Status" },
{ 0x05, "Alarm Status Type" },
{ 0x06, "BCC" },
{ 0x07, "BS_AG_BKS_RES" },
{ 0x09, "BSIC" },
{ 0x0a, "BA_PA_MFRMS" },
{ 0x0b, "CBCH Indicator" },
{ 0x0c, "CCCH Options" },
{ 0x0d, "Calendar Time" },
{ 0x0f, "Channel Combination" },
{ 0x10, "CON Connection List" },
{ 0x11, "Data End Indication" },
{ 0x12, "DRX_DEV_MAX" },
{ 0x13, "End List Number" },
{ 0x14, "External Condition Map Class 1" },
{ 0x15, "External Condition Map Class 2" },
{ 0x16, "File Relation Indication" },
{ 0x17, "File Revision" },
{ 0x18, "File Segment Data" },
{ 0x19, "File Segment Length" },
{ 0x1a, "File Segment Sequence Number" },
{ 0x1b, "File Size" },
{ 0x1c, "Filling Marker" },
{ 0x1d, "FN Offset" },
{ 0x1e, "Frequency List" },
{ 0x1f, "Frequency Specifier RX" },
{ 0x20, "Frequency Specifier TX" },
{ 0x21, "HSN" },
{ 0x22, "ICM Indicator" },
{ 0x23, "Internal Fault Map Class 1A" },
{ 0x24, "Internal Fault Map Class 1B" },
{ 0x25, "Internal Fault Map Class 2A" },
{ 0x26, "Internal Fault Map Class 2A Extension" },
{ 0x27, "IS Connection List" },
{ 0x28, "List Number" },
{ 0x29, "File Package State Indication" },
{ 0x2a, "Local Access State" },
{ 0x2b, "MAIO" },
{ 0x2c, "MO State" },
{ 0x2d, "Ny1" },
{ 0x2e, "Operational Information" },
{ 0x2f, "Power" },
{ 0x30, "RU Position Data" },
{ 0x31, "Protocol Error" },
{ 0x32, "Reason Code" },
{ 0x33, "Receiver Diversity" },
{ 0x34, "Replacement Unit Map" },
{ 0x35, "Result Code" },
{ 0x36, "RU Revision Data" },
{ 0x38, "T3105" },
{ 0x39, "Test Loop Setting" },
{ 0x3a, "TF Mode" },
{ 0x3b, "TF Compensation Value" },
{ 0x3c, "Time Slot Number" },
{ 0x3d, "TSC" },
{ 0x3e, "RU Logical Id" },
{ 0x3f, "RU Serial Number Data" },
{ 0x40, "BTS Version" },
{ 0x41, "OML IWD Version" },
{ 0x42, "RWL IWD Version" },
{ 0x43, "OML Function Map 1" },
{ 0x44, "OML Function Map 2" },
{ 0x45, "RSL Function Map 1" },
{ 0x46, "RSL Function Map 2" },
{ 0x47, "Extended Range Indicator" },
{ 0x48, "Request Indicators" },
{ 0x49, "DIP Alarm Condition Map" },
{ 0x4a, "ES Incoming" },
{ 0x4b, "ES Outgoing" },
{ 0x4e, "SES Incoming" },
{ 0x4f, "SES Outgoing" },
{ 0x50, "Replacement Unit Map Extension" },
{ 0x52, "UAS Incoming" },
{ 0x53, "UAS Outgoing" },
{ 0x58, "DF Incoming" },
{ 0x5a, "DF Outgoing" },
{ 0x5c, "SF" },
{ 0x60, "S Bits Setting" },
{ 0x61, "CRC-4 Use Option" },
{ 0x62, "T Parameter" },
{ 0x63, "N Parameter" },
{ 0x64, "N1 Parameter" },
{ 0x65, "N3 Parameter" },
{ 0x66, "N4 Parameter" },
{ 0x67, "P Parameter" },
{ 0x68, "Q Parameter" },
{ 0x69, "BI_Q1" },
{ 0x6a, "BI_Q2" },
{ 0x74, "ICM Boundary Parameters" },
{ 0x77, "AFT" },
{ 0x78, "AFT RAI" },
{ 0x79, "Link Supervision Control" },
{ 0x7a, "Link Supervision Filtering Time" },
{ 0x7b, "Call Supervision Time" },
{ 0x7c, "Interval Length UAS Incoming" },
{ 0x7d, "Interval Length UAS Outgoing" },
{ 0x7e, "ICM Channel Rate" },
{ 0x7f, "Attribute Identifier" },
{ 0x80, "FM Frequency List" },
{ 0x81, "FM Frequency Report" },
{ 0x82, "FM Percentile" },
{ 0x83, "FM Clear Indication" },
{ 0x84, "HW Info Signature" },
{ 0x85, "MO Record" },
{ 0x86, "TF Synchronisation Source" },
{ 0x87, "TTA" },
{ 0x88, "End Segment Number" },
{ 0x89, "Segment Number" },
{ 0x8a, "Capabilities Signature" },
{ 0x8c, "File Relation List" },
{ 0x90, "Negotiation Record I" },
{ 0x91, "Negotiation Record II" },
{ 0x92, "Encryption Algorithm" },
{ 0x94, "Interference Rejection Combining" },
{ 0x95, "Dedication Information" },
{ 0x97, "Feature Code" },
{ 0x98, "FS Offset" },
{ 0x99, "ESB Timeslot" },
{ 0x9a, "Master TG Instance" },
{ 0x9b, "Master TX Chain Delay" },
{ 0x9c, "External Condition Class 2 Extension" },
{ 0x9d, "TSs MO State" },
{ 0, NULL }
};
const struct value_string om2k_mo_class_short_vals[] = {
{ 0x01, "TRXC" },
{ 0x03, "TS" },
{ 0x04, "TF" },
{ 0x05, "IS" },
{ 0x06, "CON" },
{ 0x07, "DP" },
{ 0x0a, "CF" },
{ 0x0b, "TX" },
{ 0x0c, "RX" },
{ 0, NULL }
};
static struct msgb *om2k_msgb_alloc(void)
{
return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE,
"OM2000");
}
static char *om2k_mo_name(const struct abis_om2k_mo *mo)
{
static char mo_buf[64];
memset(mo_buf, 0, sizeof(mo_buf));
snprintf(mo_buf, sizeof(mo_buf), "%s/%02x/%02x/%02x",
get_value_string(om2k_mo_class_short_vals, mo->class),
mo->bts, mo->assoc_so, mo->inst);
return mo_buf;
}
static int abis_om2k_sendmsg(struct gsm_bts *bts, struct msgb *msg)
{
struct abis_om2k_hdr *o2h;
int to_trx_oml;
msg->l2h = msg->data;
o2h = (struct abis_om2k_hdr *) msg->l2h;
switch (o2h->mo.class) {
case OM2K_MO_CLS_TRXC:
case OM2K_MO_CLS_TX:
case OM2K_MO_CLS_RX:
case OM2K_MO_CLS_TS:
/* Route through per-TRX OML Link to the appropriate TRX */
to_trx_oml = 1;
msg->trx = gsm_bts_trx_by_nr(bts, o2h->mo.inst);
if (!msg->trx) {
LOGP(DNM, LOGL_ERROR, "MO=%s Tx Dropping msg to "
"non-existing TRX\n", om2k_mo_name(&o2h->mo));
return -ENODEV;
}
break;
default:
/* Route through the IXU/DXU OML Link */
msg->trx = bts->c0;
to_trx_oml = 0;
break;
}
return _abis_nm_sendmsg(msg, to_trx_oml);
}
static void fill_om2k_hdr(struct abis_om2k_hdr *o2h, const struct abis_om2k_mo *mo,
uint16_t msg_type, uint8_t attr_len)
{
o2h->om.mdisc = ABIS_OM_MDISC_FOM;
o2h->om.placement = ABIS_OM_PLACEMENT_ONLY;
o2h->om.sequence = 0;
o2h->om.length = 6 + attr_len;
o2h->msg_type = htons(msg_type);
memcpy(&o2h->mo, mo, sizeof(o2h->mo));
}
const struct abis_om2k_mo om2k_mo_cf = { OM2K_MO_CLS_CF, 0, 0xFF, 0 };
const struct abis_om2k_mo om2k_mo_is = { OM2K_MO_CLS_IS, 0, 0xFF, 0 };
const struct abis_om2k_mo om2k_mo_con = { OM2K_MO_CLS_CON, 0, 0xFF, 0 };
static int abis_om2k_cal_time_resp(struct gsm_bts *bts)
{
struct msgb *msg = om2k_msgb_alloc();
struct abis_om2k_hdr *o2k;
time_t tm_t;
struct tm *tm;
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
fill_om2k_hdr(o2k, &om2k_mo_cf, OM2K_MSGT_CAL_TIME_RESP, 7);
tm_t = time(NULL);
tm = localtime(&tm_t);
msgb_put_u8(msg, OM2K_DEI_CAL_TIME);
msgb_put_u8(msg, tm->tm_year % 100);
msgb_put_u8(msg, tm->tm_mon + 1);
msgb_put_u8(msg, tm->tm_mday);
msgb_put_u8(msg, tm->tm_hour);
msgb_put_u8(msg, tm->tm_min);
msgb_put_u8(msg, tm->tm_sec);
return abis_om2k_sendmsg(bts, msg);
}
static int abis_om2k_tx_simple(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
uint8_t msg_type)
{
struct msgb *msg = om2k_msgb_alloc();
struct abis_om2k_hdr *o2k;
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
fill_om2k_hdr(o2k, mo, msg_type, 0);
DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo),
get_value_string(om2k_msgcode_vals, msg_type));
return abis_om2k_sendmsg(bts, msg);
}
int abis_om2k_tx_reset_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
{
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_RESET_CMD);
}
int abis_om2k_tx_start_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
{
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_START_REQ);
}
int abis_om2k_tx_status_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
{
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_STATUS_REQ);
}
int abis_om2k_tx_connect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
{
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_CONNECT_CMD);
}
int abis_om2k_tx_disconnect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
{
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_DISCONNECT_CMD);
}
int abis_om2k_tx_test_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
{
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_TEST_REQ);
}
int abis_om2k_tx_enable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
{
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_ENABLE_REQ);
}
int abis_om2k_tx_disable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
{
return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_DISABLE_REQ);
}
int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
uint8_t operational)
{
struct msgb *msg = om2k_msgb_alloc();
struct abis_om2k_hdr *o2k;
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
fill_om2k_hdr(o2k, mo, OM2K_MSGT_OP_INFO, 2);
msgb_tv_put(msg, OM2K_DEI_OP_INFO, operational);
DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo),
get_value_string(om2k_msgcode_vals, OM2K_MSGT_OP_INFO));
return abis_om2k_sendmsg(bts, msg);
}
int abis_om2k_tx_is_conf_req(struct gsm_bts *bts, struct om2k_is_conn_grp *cg,
unsigned int num_cg )
{
struct msgb *msg = om2k_msgb_alloc();
struct abis_om2k_hdr *o2k;
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
fill_om2k_hdr(o2k, &om2k_mo_is, OM2K_MSGT_IS_CONF_REQ,
2 + 2 + TLV_GROSS_LEN(num_cg * sizeof(*cg)));
msgb_tv_put(msg, OM2K_DEI_LIST_NR, 1);
msgb_tv_put(msg, OM2K_DEI_END_LIST_NR, 1);
msgb_tlv_put(msg, OM2K_DEI_IS_CONN_LIST,
num_cg * sizeof(*cg), (uint8_t *)cg);
return abis_om2k_sendmsg(bts, msg);
}
int abis_om2k_tx_con_conf_req(struct gsm_bts *bts, uint8_t *data,
unsigned int len)
{
struct msgb *msg = om2k_msgb_alloc();
struct abis_om2k_hdr *o2k;
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
fill_om2k_hdr(o2k, &om2k_mo_con, OM2K_MSGT_CON_CONF_REQ,
2 + 2 + TLV_GROSS_LEN(len));
msgb_tv_put(msg, OM2K_DEI_LIST_NR, 1);
msgb_tv_put(msg, OM2K_DEI_END_LIST_NR, 1);
msgb_tlv_put(msg, OM2K_DEI_CON_CONN_LIST, len, data);
return abis_om2k_sendmsg(bts, msg);
}
static int abis_om2k_tx_negot_req_ack(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
uint8_t *data, unsigned int len)
{
struct msgb *msg = om2k_msgb_alloc();
struct abis_om2k_hdr *o2k;
o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
fill_om2k_hdr(o2k, mo, OM2K_MSGT_NEGOT_REQ_ACK, 2+len);
msgb_tlv_put(msg, OM2K_DEI_NEGOT_REC2, len, data);
DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo),
get_value_string(om2k_msgcode_vals, OM2K_MSGT_NEGOT_REQ_ACK));
return abis_om2k_sendmsg(bts, msg);
}
struct iwd_version {
uint8_t gen_char[3+1];
uint8_t rev_char[3+1];
};
struct iwd_type {
uint8_t num_vers;
struct iwd_version v[8];
};
static int om2k_rx_negot_req(struct msgb *msg)
{
struct abis_om2k_hdr *o2h = msgb_l2(msg);
struct iwd_type iwd_types[16];
uint8_t num_iwd_types = o2h->data[2];
uint8_t *cur = o2h->data+3;
unsigned int i, v;
uint8_t out_buf[1024];
uint8_t *out_cur = out_buf+1;
uint8_t out_num_types = 0;
memset(iwd_types, 0, sizeof(iwd_types));
/* Parse the RBS-supported IWD versions into iwd_types array */
for (i = 0; i < num_iwd_types; i++) {
uint8_t num_versions = *cur++;
uint8_t iwd_type = *cur++;
iwd_types[iwd_type].num_vers = num_versions;
for (v = 0; v < num_versions; v++) {
struct iwd_version *iwd_v = &iwd_types[iwd_type].v[v];
memcpy(iwd_v->gen_char, cur, 3);
cur += 3;
memcpy(iwd_v->rev_char, cur, 3);
cur += 3;
DEBUGP(DNM, "\tIWD Type %u Gen %s Rev %s\n", iwd_type,
iwd_v->gen_char, iwd_v->rev_char);
}
}
/* Select the last version for each IWD type */
for (i = 0; i < ARRAY_SIZE(iwd_types); i++) {
struct iwd_type *type = &iwd_types[i];
struct iwd_version *last_v;
if (type->num_vers == 0)
continue;
out_num_types++;
last_v = &type->v[type->num_vers-1];
*out_cur++ = i;
memcpy(out_cur, last_v->gen_char, 3);
out_cur += 3;
memcpy(out_cur, last_v->rev_char, 3);
out_cur += 3;
}
out_buf[0] = out_num_types;
return abis_om2k_tx_negot_req_ack(msg->trx->bts, &o2h->mo, out_buf, out_cur - out_buf);
}
static int om2k_rx_start_res(struct msgb *msg)
{
struct abis_om2k_hdr *o2h = msgb_l2(msg);
int rc;
rc = abis_om2k_tx_simple(msg->trx->bts, &o2h->mo, OM2K_MSGT_START_RES_ACK);
rc = abis_om2k_tx_op_info(msg->trx->bts, &o2h->mo, 1);
return rc;
}
static int om2k_rx_op_info_ack(struct msgb *msg)
{
struct abis_om2k_hdr *o2h = msgb_l2(msg);
/* FIXME: update Operational state in our structures */
return 0;
}
int abis_om2k_rcvmsg(struct msgb *msg)
{
struct gsm_bts *bts = msg->trx->bts;
struct abis_om2k_hdr *o2h = msgb_l2(msg);
struct abis_om_hdr *oh = &o2h->om;
uint16_t msg_type = ntohs(o2h->msg_type);
int rc = 0;
/* Various consistency checks */
if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
oh->placement);
if (oh->placement != ABIS_OM_PLACEMENT_FIRST)
return -EINVAL;
}
if (oh->sequence != 0) {
LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
oh->sequence);
return -EINVAL;
}
msg->l3h = (unsigned char *)o2h + sizeof(*o2h);
if (oh->mdisc != ABIS_OM_MDISC_FOM) {
LOGP(DNM, LOGL_ERROR, "unknown ABIS OM2000 message discriminator 0x%x\n",
oh->mdisc);
return -EINVAL;
}
DEBUGP(DNM, "Rx MO=%s %s (%s)\n", om2k_mo_name(&o2h->mo),
get_value_string(om2k_msgcode_vals, msg_type),
hexdump(msg->l2h, msgb_l2len(msg)));
switch (msg_type) {
case OM2K_MSGT_CAL_TIME_REQ:
rc = abis_om2k_cal_time_resp(bts);
break;
case OM2K_MSGT_FAULT_REP:
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_FAULT_REP_ACK);
break;
case OM2K_MSGT_NEGOT_REQ:
rc = om2k_rx_negot_req(msg);
break;
case OM2K_MSGT_START_RES:
rc = om2k_rx_start_res(msg);
break;
case OM2K_MSGT_OP_INFO_ACK:
rc = om2k_rx_op_info_ack(msg);
break;
case OM2K_MSGT_IS_CONF_RES:
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_IS_CONF_RES_ACK);
break;
case OM2K_MSGT_CON_CONF_RES:
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_CON_CONF_RES_ACK);
break;
case OM2K_MSGT_CONNECT_COMPL:
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_RESET_CMD);
break;
case OM2K_MSGT_RESET_COMPL:
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_START_REQ);
break;
case OM2K_MSGT_ENABLE_RES:
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_ENABLE_RES_ACK);
break;
case OM2K_MSGT_DISABLE_RES:
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_DISABLE_RES_ACK);
break;
case OM2K_MSGT_TEST_RES:
rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TEST_RES_ACK);
break;
case OM2K_MSGT_STATUS_RESP:
break;
case OM2K_MSGT_START_REQ_ACK:
case OM2K_MSGT_CON_CONF_REQ_ACK:
case OM2K_MSGT_IS_CONF_REQ_ACK:
case OM2K_MSGT_ENABLE_REQ_ACK:
case OM2K_MSGT_ALARM_STATUS_REQ_ACK:
case OM2K_MSGT_DISABLE_REQ_ACK:
break;
default:
LOGP(DNM, LOGL_NOTICE, "Rx unhandled OM2000 msg %s\n",
get_value_string(om2k_msgcode_vals, msg_type));
}
msgb_free(msg);
return rc;
}

View File

@@ -0,0 +1,456 @@
/* VTY interface for A-bis OM2000 */
/* (C) 2010-2011 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 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 <http://www.gnu.org/licenses/>.
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <openbsc/gsm_data.h>
#include <osmocore/msgb.h>
#include <osmocore/tlv.h>
#include <osmocore/talloc.h>
#include <openbsc/debug.h>
#include <openbsc/signal.h>
#include <openbsc/abis_om2000.h>
#include <openbsc/vty.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/telnet_interface.h>
extern struct gsm_network *bsc_gsmnet;
static struct cmd_node om2k_node = {
OM2K_NODE,
"%s(om2k)# ",
1,
};
struct oml_node_state {
struct gsm_bts *bts;
struct abis_om2k_mo mo;
};
static int dummy_config_write(struct vty *v)
{
return CMD_SUCCESS;
}
/* FIXME: auto-generate those strings from the value_string lists */
#define OM2K_OBJCLASS_VTY "(trxc|ts|tf|is|con|dp|cf|tx|rx)"
#define OM2K_OBJCLASS_VTY_HELP "TRX Controller\n" \
"Timeslot\n" \
"Timing Function\n" \
"Interface Switch\n" \
"Abis Concentrator\n" \
"Digital Path\n" \
"Central Function\n" \
"Transmitter\n" \
"Receiver\n"
DEFUN(om2k_class_inst, om2k_class_inst_cmd,
"bts <0-255> om2000 class " OM2K_OBJCLASS_VTY
" <0-255> <0-255> <0-255>",
"BTS related commands\n" "BTS Number\n"
"Manipulate the OM2000 managed objects\n"
"Object Class\n" OM2K_OBJCLASS_VTY_HELP
"BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
{
struct gsm_bts *bts;
struct oml_node_state *oms;
int bts_nr = atoi(argv[0]);
bts = gsm_bts_num(bsc_gsmnet, bts_nr);
if (!bts) {
vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
if (bts->type != GSM_BTS_TYPE_RBS2000) {
vty_out(vty, "%% BTS %d not an Ericsson RBS%s",
bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
if (!oms)
return CMD_WARNING;
oms->bts = bts;
oms->mo.class = get_string_value(om2k_mo_class_short_vals, argv[1]);
oms->mo.bts = atoi(argv[2]);
oms->mo.assoc_so = atoi(argv[3]);
oms->mo.inst = atoi(argv[4]);
vty->index = oms;
vty->node = OM2K_NODE;
return CMD_SUCCESS;
}
DEFUN(om2k_classnum_inst, om2k_classnum_inst_cmd,
"bts <0-255> om2000 class <0-255> <0-255> <0-255> <0-255>",
"BTS related commands\n" "BTS Number\n"
"Manipulate the OML managed objects\n"
"Object Class\n" "Object Class\n"
"BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
{
struct gsm_bts *bts;
struct oml_node_state *oms;
int bts_nr = atoi(argv[0]);
bts = gsm_bts_num(bsc_gsmnet, bts_nr);
if (!bts) {
vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
if (!oms)
return CMD_WARNING;
oms->bts = bts;
oms->mo.class = atoi(argv[1]);
oms->mo.bts = atoi(argv[2]);
oms->mo.assoc_so = atoi(argv[3]);
oms->mo.inst = atoi(argv[4]);
vty->index = oms;
vty->node = OM2K_NODE;
return CMD_SUCCESS;
}
DEFUN(om2k_reset, om2k_reset_cmd,
"reset-command",
"Reset the MO\n")
{
struct oml_node_state *oms = vty->index;
abis_om2k_tx_reset_cmd(oms->bts, &oms->mo);
return CMD_SUCCESS;
}
DEFUN(om2k_start, om2k_start_cmd,
"start-request",
"Start the MO\n")
{
struct oml_node_state *oms = vty->index;
abis_om2k_tx_start_req(oms->bts, &oms->mo);
return CMD_SUCCESS;
}
DEFUN(om2k_status, om2k_status_cmd,
"status-request",
"Get the MO Status\n")
{
struct oml_node_state *oms = vty->index;
abis_om2k_tx_status_req(oms->bts, &oms->mo);
return CMD_SUCCESS;
}
DEFUN(om2k_connect, om2k_connect_cmd,
"connect-command",
"Connect the MO\n")
{
struct oml_node_state *oms = vty->index;
abis_om2k_tx_connect_cmd(oms->bts, &oms->mo);
return CMD_SUCCESS;
}
DEFUN(om2k_disconnect, om2k_disconnect_cmd,
"disconnect-command",
"Disconnect the MO\n")
{
struct oml_node_state *oms = vty->index;
abis_om2k_tx_disconnect_cmd(oms->bts, &oms->mo);
return CMD_SUCCESS;
}
DEFUN(om2k_enable, om2k_enable_cmd,
"enable-request",
"Enable the MO\n")
{
struct oml_node_state *oms = vty->index;
abis_om2k_tx_enable_req(oms->bts, &oms->mo);
return CMD_SUCCESS;
}
DEFUN(om2k_disable, om2k_disable_cmd,
"disable-request",
"Disable the MO\n")
{
struct oml_node_state *oms = vty->index;
abis_om2k_tx_disable_req(oms->bts, &oms->mo);
return CMD_SUCCESS;
}
DEFUN(om2k_op_info, om2k_op_info_cmd,
"operational-info <0-1>",
"Set operational information\n")
{
struct oml_node_state *oms = vty->index;
int oper = atoi(argv[0]);
abis_om2k_tx_op_info(oms->bts, &oms->mo, oper);
return CMD_SUCCESS;
}
DEFUN(om2k_test, om2k_test_cmd,
"test-request",
"Test the MO\n")
{
struct oml_node_state *oms = vty->index;
abis_om2k_tx_test_req(oms->bts, &oms->mo);
return CMD_SUCCESS;
}
struct con_conn_group {
struct llist_head list;
uint8_t cg;
uint16_t ccp;
uint8_t tag;
uint8_t tei;
};
static void add_con_list(struct gsm_bts *bts, uint8_t cg, uint16_t ccp,
uint8_t tag, uint8_t tei)
{
struct con_conn_group *ent = talloc_zero(bts, struct con_conn_group);
ent->cg = cg;
ent->ccp = ccp;
ent->tag = tag;
ent->tei = tei;
llist_add_tail(&ent->list, &bts->rbs2000.con.conn_groups);
}
static int del_con_list(struct gsm_bts *bts, uint8_t cg, uint16_t ccp,
uint8_t tag, uint8_t tei)
{
struct con_conn_group *grp, *grp2;
llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.con.conn_groups, list) {
if (grp->cg == cg && grp->ccp == ccp && grp->tag == tag
&& grp->tei == tei) {
llist_del(&grp->list);
talloc_free(grp);
return 0;
}
}
return -ENOENT;
}
#define CON_LIST_HELP "CON connetiton list\n" \
"Add entry to CON list\n" \
"Delete entry from CON list\n" \
"Connection Group Number\n" \
"CON Connection Point\n" \
DEFUN(om2k_con_list_dec, om2k_con_list_dec_cmd,
"con-connection-list (add|del) <1-255> <0-1023> deconcentrated",
CON_LIST_HELP "De-concentrated in/outlet\n")
{
struct oml_node_state *oms = vty->index;
struct gsm_bts *bts = oms->bts;
uint8_t cg = atoi(argv[1]);
uint16_t ccp = atoi(argv[2]);
if (!strcmp(argv[0], "add"))
add_con_list(bts, cg, ccp, 0, 0xff);
else {
if (del_con_list(bts, cg, ccp, 0, 0xff) < 0) {
vty_out(vty, "%% No matching CON list entry%s",
VTY_NEWLINE);
return CMD_WARNING;
}
}
return CMD_SUCCESS;
}
DEFUN(om2k_con_list_tei, om2k_con_list_tei_cmd,
"con-connection-list (add|del) <1-255> <0-1023> tei <0-63>",
CON_LIST_HELP "Concentrated in/outlet with TEI\n" "TEI Number\n")
{
struct oml_node_state *oms = vty->index;
struct gsm_bts *bts = oms->bts;
uint8_t cg = atoi(argv[1]);
uint16_t ccp = atoi(argv[2]);
uint8_t tei = atoi(argv[3]);
if (!strcmp(argv[0], "add"))
add_con_list(bts, cg, ccp, cg, tei);
else {
if (del_con_list(bts, cg, ccp, cg, tei) < 0) {
vty_out(vty, "%% No matching CON list entry%s",
VTY_NEWLINE);
return CMD_WARNING;
}
}
return CMD_SUCCESS;
}
static void om2k_fill_is_conn_grp(struct om2k_is_conn_grp *grp, uint16_t icp1,
uint16_t icp2, uint8_t cont_idx)
{
grp->icp1 = htons(icp1);
grp->icp2 = htons(icp2);
grp->cont_idx = cont_idx;
}
struct is_conn_group {
struct llist_head list;
uint16_t icp1;
uint16_t icp2;
uint8_t ci;
};
DEFUN(cfg_bts_is_conn_list, cfg_bts_is_conn_list_cmd,
"is-connection-list (add|del) <0-2047> <0-2047> <0-255>",
"Interface Switch Connnection List\n"
"Add to IS list\n" "Delete from IS list\n"
"ICP1\n" "ICP2\n" "Contiguity Index\n")
{
struct gsm_bts *bts = vty->index;
uint16_t icp1 = atoi(argv[1]);
uint16_t icp2 = atoi(argv[2]);
uint8_t ci = atoi(argv[3]);
struct is_conn_group *grp, *grp2;
if (!strcmp(argv[0], "add")) {
grp = talloc_zero(bts, struct is_conn_group);
grp->icp1 = icp1;
grp->icp2 = icp2;
grp->ci = ci;
llist_add_tail(&grp->list, &bts->rbs2000.is.conn_groups);
} else {
llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.is.conn_groups, list) {
if (grp->icp1 == icp1 && grp->icp2 == icp2
&& grp->ci == ci) {
llist_del(&grp->list);
talloc_free(grp);
return CMD_SUCCESS;
}
}
vty_out(vty, "%% No matching IS Conn Group found!%s",
VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(om2k_is_conf_req, om2k_is_conf_req_cmd,
"is-conf-req",
"Send IS Configuration Request\n")
{
struct oml_node_state *oms = vty->index;
struct gsm_bts *bts = oms->bts;
struct is_conn_group *grp;
unsigned int num_grps = 0, i = 0;
struct om2k_is_conn_grp *o2grps;
/* count number of groups in linked list */
llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list)
num_grps++;
if (!num_grps) {
vty_out(vty, "%% No IS connection groups configured!%s",
VTY_NEWLINE);
return CMD_WARNING;
}
/* allocate buffer for oml group array */
o2grps = talloc_zero_array(bts, struct om2k_is_conn_grp, num_grps);
/* fill array with data from linked list */
llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list)
om2k_fill_is_conn_grp(&o2grps[i++], grp->icp1, grp->icp2, grp->ci);
/* send the actual OML request */
abis_om2k_tx_is_conf_req(oms->bts, o2grps, num_grps);
talloc_free(o2grps);
return CMD_SUCCESS;
}
void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts)
{
struct is_conn_group *igrp;
struct con_conn_group *cgrp;
llist_for_each_entry(igrp, &bts->rbs2000.is.conn_groups, list)
vty_out(vty, " is-connection-list add %u %u %u%s",
igrp->icp1, igrp->icp2, igrp->ci, VTY_NEWLINE);
llist_for_each_entry(cgrp, &bts->rbs2000.con.conn_groups, list) {
vty_out(vty, " con-connection-list add %u %u ",
cgrp->cg, cgrp->ccp);
if (cgrp->tei == 0xff)
vty_out(vty, "deconcentrated%s", VTY_NEWLINE);
else
vty_out(vty, "tei %u%s", cgrp->tei, VTY_NEWLINE);
}
}
int abis_om2k_vty_init(void)
{
install_element(ENABLE_NODE, &om2k_class_inst_cmd);
install_element(ENABLE_NODE, &om2k_classnum_inst_cmd);
install_node(&om2k_node, dummy_config_write);
install_default(OM2K_NODE);
install_element(OM2K_NODE, &ournode_exit_cmd);
install_element(OM2K_NODE, &om2k_reset_cmd);
install_element(OM2K_NODE, &om2k_start_cmd);
install_element(OM2K_NODE, &om2k_status_cmd);
install_element(OM2K_NODE, &om2k_connect_cmd);
install_element(OM2K_NODE, &om2k_disconnect_cmd);
install_element(OM2K_NODE, &om2k_enable_cmd);
install_element(OM2K_NODE, &om2k_disable_cmd);
install_element(OM2K_NODE, &om2k_op_info_cmd);
install_element(OM2K_NODE, &om2k_test_cmd);
install_element(OM2K_NODE, &om2k_is_conf_req_cmd);
install_element(OM2K_NODE, &om2k_con_list_dec_cmd);
install_element(OM2K_NODE, &om2k_con_list_tei_cmd);
install_element(BTS_NODE, &cfg_bts_is_conn_list_cmd);
return 0;
}

View File

@@ -6,18 +6,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -51,6 +50,15 @@
static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
struct gsm_meas_rep *resp)
{
struct lchan_signal_data sig;
sig.lchan = lchan;
sig.mr = resp;
dispatch_signal(SS_LCHAN, sig_no, &sig);
}
static u_int8_t mdisc_by_msgtype(u_int8_t msg_type)
{
/* mask off the transparent bit ? */
@@ -130,9 +138,8 @@ struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
}
/* See Table 10.5.25 of GSM04.08 */
u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan)
static u_int8_t ts2chan_nr(const struct gsm_bts_trx_ts *ts, uint8_t lchan_nr)
{
struct gsm_bts_trx_ts *ts = lchan->ts;
u_int8_t cbits, chan_nr;
switch (ts->pchan) {
@@ -143,15 +150,15 @@ u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan)
break;
case GSM_PCHAN_TCH_H:
cbits = 0x02;
cbits += lchan->nr;
cbits += lchan_nr;
break;
case GSM_PCHAN_CCCH_SDCCH4:
cbits = 0x04;
cbits += lchan->nr;
cbits += lchan_nr;
break;
case GSM_PCHAN_SDCCH8_SACCH8C:
cbits = 0x08;
cbits += lchan->nr;
cbits += lchan_nr;
break;
default:
case GSM_PCHAN_CCCH:
@@ -164,6 +171,11 @@ u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan)
return chan_nr;
}
u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan)
{
return ts2chan_nr(lchan->ts, lchan->nr);
}
/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
u_int64_t str_to_imsi(const char *imsi_str)
{
@@ -268,6 +280,25 @@ int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
return abis_rsl_sendmsg(msg);
}
int rsl_sacch_info_modify(struct gsm_lchan *lchan, u_int8_t type,
const u_int8_t *data, int len)
{
struct abis_rsl_dchan_hdr *dh;
struct msgb *msg = rsl_msgb_alloc();
u_int8_t chan_nr = lchan2chan_nr(lchan);
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
init_dchan_hdr(dh, RSL_MT_SACCH_INFO_MODIFY);
dh->chan_nr = chan_nr;
msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
msg->trx = lchan->ts->trx;
return abis_rsl_sendmsg(msg);
}
int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
{
struct abis_rsl_dchan_hdr *dh;
@@ -644,6 +675,24 @@ static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
return abis_rsl_sendmsg(msg);
}
static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
{
DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
gsm_lchan_name(lchan),
gsm_lchans_name(lchan->state));
bsc_del_timer(&lchan->T3111);
/* we have an error timer pending to release that */
if (lchan->state != LCHAN_S_REL_ERR)
rsl_lchan_set_state(lchan, LCHAN_S_NONE);
lchan_free(lchan);
return 0;
}
int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
u_int8_t *ms_ident, u_int8_t chan_needed)
{
@@ -663,18 +712,6 @@ int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
return abis_rsl_sendmsg(msg);
}
int rsl_paging_cmd_subscr(struct gsm_bts *bts, u_int8_t chan_need,
struct gsm_subscriber *subscr)
{
#if 0
u_int8_t mi[128];
unsigned int mi_len;
u_int8_t paging_group;
#endif
return -1;
}
int imsi_str2bcd(u_int8_t *bcd_out, const char *str_in)
{
int i, len = strlen(str_in);
@@ -821,7 +858,7 @@ static int rsl_rx_chan_act_ack(struct msgb *msg)
msg->lchan->rqd_ta = 0;
}
dispatch_signal(SS_LCHAN, S_LCHAN_ACTIVATE_ACK, msg->lchan);
send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
return 0;
}
@@ -851,7 +888,7 @@ static int rsl_rx_chan_act_nack(struct msgb *msg)
LOGPC(DRSL, LOGL_ERROR, "\n");
dispatch_signal(SS_LCHAN, S_LCHAN_ACTIVATE_NACK, msg->lchan);
send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
lchan_free(msg->lchan);
return 0;
@@ -994,7 +1031,7 @@ static int rsl_rx_meas_res(struct msgb *msg)
print_meas_rep(mr);
dispatch_signal(SS_LCHAN, S_LCHAN_MEAS_REP, mr);
send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
return 0;
}
@@ -1015,7 +1052,7 @@ static int rsl_rx_hando_det(struct msgb *msg)
else
DEBUGPC(DRSL, "\n");
dispatch_signal(SS_LCHAN, S_LCHAN_HANDOVER_DETECT, msg->lchan);
send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
return 0;
}
@@ -1047,16 +1084,7 @@ static int abis_rsl_rx_dchan(struct msgb *msg)
rc = rsl_rx_hando_det(msg);
break;
case RSL_MT_RF_CHAN_REL_ACK:
DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", ts_name);
if (msg->lchan->state != LCHAN_S_REL_REQ && msg->lchan->state != LCHAN_S_REL_ERR)
LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
gsm_lchan_name(msg->lchan),
gsm_lchans_name(msg->lchan->state));
bsc_del_timer(&msg->lchan->T3111);
/* we have an error timer pending to release that */
if (msg->lchan->state != LCHAN_S_REL_ERR)
rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
lchan_free(msg->lchan);
rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
break;
case RSL_MT_MODE_MODIFY_ACK:
DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
@@ -1160,6 +1188,45 @@ static void t3111_expired(void *data)
#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
unsigned int num_req_refs,
struct gsm48_req_ref *rqd_refs,
uint8_t wait_ind)
{
uint8_t buf[GSM_MACBLOCK_LEN];
struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
/* create IMMEDIATE ASSIGN REJECT 04.08 message */
memset(iar, 0, sizeof(*iar));
iar->proto_discr = GSM48_PDISC_RR;
iar->msg_type = GSM48_MT_RR_IMM_ASS;
iar->page_mode = GSM48_PM_SAME;
memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
iar->wait_ind1 = wait_ind;
if (num_req_refs >= 2)
memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
else
memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
iar->wait_ind2 = wait_ind;
if (num_req_refs >= 3)
memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
else
memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
iar->wait_ind3 = wait_ind;
if (num_req_refs >= 4)
memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
else
memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
iar->wait_ind4 = wait_ind;
return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
}
/* MS has requested a channel on the RACH */
static int rsl_rx_chan_rqd(struct msgb *msg)
{
@@ -1205,7 +1272,9 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
counter_inc(bts->network->stats.chreq.no_channel);
/* FIXME: send some kind of reject ?!? */
/* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
if (bts->network->T3122)
rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
return -ENOMEM;
}
@@ -1376,7 +1445,7 @@ static void rsl_handle_release(struct gsm_lchan *lchan)
for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
continue;
LOGP(DRSL, LOGL_NOTICE, "%s waiting for SAPI=%d to be released.\n",
LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
gsm_lchan_name(lchan), sapi);
return;
}
@@ -1505,6 +1574,12 @@ static u_int8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
static u_int8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
{
struct gsm_network *net = lchan->ts->trx->bts->network;
/* allow to hardcode the rtp payload */
if (net->hardcoded_rtp_payload != 0)
return net->hardcoded_rtp_payload;
switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_V1:
switch (lchan->type) {
@@ -1677,7 +1752,7 @@ int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
return rc;
}
int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act)
int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
{
struct msgb *msg = rsl_msgb_alloc();
struct abis_rsl_dchan_hdr *dh;
@@ -1691,12 +1766,12 @@ int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act)
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
init_dchan_hdr(dh, msg_type);
dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
dh->chan_nr = lchan2chan_nr(lchan);
dh->chan_nr = ts2chan_nr(ts, 0);
DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_lchan_name(lchan),
DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
act ? "" : "DE");
msg->trx = lchan->ts->trx;
msg->trx = ts->trx;
return abis_rsl_sendmsg(msg);
}
@@ -1721,32 +1796,9 @@ static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
ipac_parse_rtp(lchan, &tv);
/* in case we don't use direct BTS-to-BTS RTP */
if (!ipacc_rtp_direct) {
int rc;
/* the BTS has successfully bound a TCH to a local ip/port,
* which means we can connect our UDP socket to it */
if (lchan->abis_ip.rtp_socket) {
rtp_socket_free(lchan->abis_ip.rtp_socket);
lchan->abis_ip.rtp_socket = NULL;
}
lchan->abis_ip.rtp_socket = rtp_socket_create();
if (!lchan->abis_ip.rtp_socket)
goto out_err;
rc = rtp_socket_connect(lchan->abis_ip.rtp_socket,
lchan->abis_ip.bound_ip,
lchan->abis_ip.bound_port);
if (rc < 0)
goto out_err;
}
dispatch_signal(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
return 0;
out_err:
return -EIO;
}
static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
@@ -1770,7 +1822,6 @@ static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
{
struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
struct tlv_parsed tv;
struct gsm_lchan *lchan = msg->lchan;
rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
@@ -1778,12 +1829,6 @@ static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
TLVP_LEN(&tv, RSL_IE_CAUSE));
/* the BTS tells us a RTP stream has been disconnected */
if (lchan->abis_ip.rtp_socket) {
rtp_socket_free(lchan->abis_ip.rtp_socket);
lchan->abis_ip.rtp_socket = NULL;
}
dispatch_signal(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
return 0;

View File

@@ -0,0 +1,194 @@
/* C-Implementation of the Algorithm described in Appendix J of GSM TS 44.018,
* (C) 2009 by Dirk Hakkesteegt <dirk@hakkesteegt.org>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
/* Annex J.3 indicates that at least in one BA list, we can never have more
* than 29 frequencies within the 16byte limit */
#define MAX_ARRFCNS 29
/*****************************************************************************
* NAME : smod
* DESCRIPTION : n smod m indicates the offset remainder of the euclidian
* division of n by m
* INPUT : n, m
* OUTPUT : n smod m
* RETURNS :
* Errorcodes :
******************************************************************************/
static int smod(int n, int m)
{
int result = n % m;
if (result < 0)
result += m;
if (result == 0)
result = m;
return result;
}
/*****************************************************************************
* NAME : mod
* DESCRIPTION : n mod m indicates the remainder of the euclidian division of
* n by m
* INPUT : n, m
* OUTPUT : n mod m
* RETURNS :
* Errorcodes :
******************************************************************************/
static int mod(int n, int m)
{
int result = n % m;
if (result < 0)
result += m;
return result;
}
/*****************************************************************************
* NAME : greatest_power_of_2_le_to
* DESCRIPTION : Calculates the greatest power of 2 that is lesser or equal
* to the input value;
* INPUT :
* OUTPUT :
* RETURNS :
* Errorcodes :
******************************************************************************/
static int greatest_power_of_2_le_to(int input)
{
int check_val = 1;
while (check_val <= input)
check_val *= 2;
return check_val / 2;
}
/*****************************************************************************
* NAME : ENCODE_SUBTREE
* DESCRIPTION : Recursive encoding routine based on 3GPP TS44.018 Annex J.4
* INPUT : index: current position in the W list
* set: the array to be encoded
* range: the current range
* set_size: number of elements in set
* OUTPUT : W: the array of results
* RETURNS :
* Errorcodes :
******************************************************************************/
static void encode_subtree(int index, int *set, int range, int set_size, int *W)
{
int index_in_set = 0;
int N, J, I, x;
int subset[18];
int subset_index, origin_value;
/* Check if this is a leaf */
if (set_size == 0) {
W[index] = 0;
return;
} else {
if (set_size == 1) {
W[index] = 1 + set[1];
return;
}
}
for (I = 1; I <= set_size; I++) {
N = 0;
for (J = 1; J <= set_size; J++) {
x = set[J] - set[I];
x = mod(x, range);
if (x <= (range-1)/2)
N++;
}
if (N-1 == (set_size-1) / 2) {
index_in_set = I;
break;
}
}
W[index] = set[index_in_set] + 1;
/* Left subset */
subset[0] = 0;
origin_value = mod((set[index_in_set] + (range-1) / 2 + 1), range);
subset_index = 1;
for (I = 1; I <= set_size; I++) {
if (mod((set[I]-origin_value), range) < range/2) {
subset[subset_index] = mod((set[I] - origin_value), range);
subset_index++;
subset[subset_index] = 0;
}
}
encode_subtree(index + greatest_power_of_2_le_to(index),
subset, range / 2, subset_index-1, W);
/* Right subset */
subset[0] = 0;
origin_value = mod((set[index_in_set] + 1), range);
subset_index=1;
for (I = 1; I<= set_size; I++) {
if (mod((set[I]-origin_value), range) < range/2) {
subset[subset_index] = mod((set[I] - origin_value), range);
subset_index++;
subset[subset_index] = 0;
}
}
encode_subtree(index + 2*greatest_power_of_2_le_to(index),
subset, (range-1)/2, subset_index-1, W);
}
/*****************************************************************************
* NAME : CalcARFCN
* DESCRIPTION : Calculate the ARFCN list
* INPUT : F: the list of input frequencies. MUST BE SORTED!
* count: the number of elements in the F list
* range: the encoding range (default: range 512)
* OUTPUT : W: the list of W values
* RETURNS :
* Errorcodes :
******************************************************************************/
static void CalcARFCN(const unsigned int *F, int *W, unsigned int count, unsigned int range)
{
int i;
int Fd[MAX_ARFCNS+1];
W[0] = F[0];
for (i = 1; i < count; i++) {
Fd[i] = F[i] - F[0] - 1;
}
encode_subtree(1, Fd, range-1, count-1, W);
}
int bitvec2arfcn_list_range(uint8_t *range, struct bitvec *bv, uint16_t range)
{
unsigned int i, idx = 0;
int F[MAX_ARFCNS+1];
int W[MAX_ARFCNS+1];
/* build an array of integers from the bitmask */
for (i = 0; i < bv->data_len*8; i++) {
if (bitvec_get_bit_pos(bv, i))
F[idx++] = i;
}
/* Perform the actual algorithm to calculate the 'W' values */
CalcARFCN(F, W, idx, range);
/* FIXME: Encode the 'W' values into the actual format as used in 04.08 */
return -EIO;
}

View File

@@ -6,23 +6,23 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <openbsc/db.h>
#include <openbsc/debug.h>
#include <openbsc/auth.h>
#include <openbsc/gsm_data.h>
#include <osmocore/comp128.h>
@@ -36,7 +36,7 @@ _use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
int i, l = ainfo->a3a8_ki_len;
if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) {
DEBUGP(DMM, "Invalid XOR key (len=%d) %s",
LOGP(DMM, LOGL_ERROR, "Invalid XOR key (len=%d) %s\n",
ainfo->a3a8_ki_len,
hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
return -1;
@@ -54,7 +54,7 @@ static int
_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
{
if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
DEBUGP(DMM, "Invalid COMP128v1 key (len=%d) %s",
LOGP(DMM, LOGL_ERROR, "Invalid COMP128v1 key (len=%d) %s\n",
ainfo->a3a8_ki_len,
hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
return -1;
@@ -80,8 +80,9 @@ int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
/* Get subscriber info (if any) */
rc = db_get_authinfo_for_subscr(&ainfo, subscr);
if (rc < 0) {
DEBUGP(DMM, "No retrievable Ki for subscriber, skipping auth");
return rc == -ENOENT ? 0 : -1;
LOGP(DMM, LOGL_NOTICE,
"No retrievable Ki for subscriber, skipping auth\n");
return rc == -ENOENT ? AUTH_NOT_AVAIL : -1;
}
/* If possible, re-use the last tuple and skip auth */
@@ -92,7 +93,8 @@ int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
{
atuple->use_count++;
db_sync_lastauthtuple_for_subscr(atuple, subscr);
return 2;
DEBUGP(DMM, "Auth tuple use < 3, just doing ciphering\n");
return AUTH_DO_CIPH;
}
/* Generate a new one */
@@ -102,27 +104,29 @@ int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
atuple->rand[i] = random() & 0xff;
switch (ainfo.auth_algo) {
case AUTH_ALGO_NONE:
case AUTH_ALGO_NONE:
DEBUGP(DMM, "No authentication for subscriber\n");
return 0;
case AUTH_ALGO_XOR:
if (_use_xor(&ainfo, atuple))
return 0;
break;
case AUTH_ALGO_XOR:
if (_use_xor(&ainfo, atuple))
return 0;
break;
case AUTH_ALGO_COMP128v1:
if (_use_comp128_v1(&ainfo, atuple))
return 0;
break;
default:
DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
ainfo.auth_algo);
case AUTH_ALGO_COMP128v1:
if (_use_comp128_v1(&ainfo, atuple))
return 0;
break;
default:
DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
ainfo.auth_algo);
return 0;
}
db_sync_lastauthtuple_for_subscr(atuple, subscr);
return 1;
DEBUGP(DMM, "Need to do authentication and ciphering\n");
return AUTH_DO_AUTH_THAN_CIPH;
}

View File

@@ -1,24 +1,23 @@
/* Siemens BS-11 microBTS configuration tool */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
* All Rights Reserved
*
* This software is based on ideas (but not code) of BS11Config
* (C) 2009 by Dieter Spaar <spaar@mirider.augusta.de>
*
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -331,6 +330,18 @@ static const char *cclk_acc_name(u_int8_t acc)
}
}
static const char *bport_lcfg_name(u_int8_t lcfg)
{
switch (lcfg) {
case BS11_LINE_CFG_STAR:
return "Star";
case BS11_LINE_CFG_MULTIDROP:
return "Multi-Drop";
default:
return "unknown";
}
}
static const char *obj_name(struct abis_om_fom_hdr *foh)
{
static char retbuf[256];
@@ -356,6 +367,10 @@ static const char *obj_name(struct abis_om_fom_hdr *foh)
case NM_OC_SITE_MANAGER:
strcat(retbuf, "SITE MANAGER ");
break;
case NM_OC_BS11_BPORT:
sprintf(retbuf+strlen(retbuf), "BPORT%u ",
foh->obj_inst.bts_nr);
break;
}
return retbuf;
}
@@ -441,6 +456,13 @@ static int print_attr(struct tlv_parsed *tp)
const u_int8_t *acc = TLVP_VAL(tp, NM_ATT_BS11_CCLK_TYPE);
printf("\tCCLK Type=%d\n", *acc);
}
if (TLVP_PRESENT(tp, NM_ATT_BS11_LINE_CFG) &&
TLVP_LEN(tp, NM_ATT_BS11_LINE_CFG) >= 1) {
const u_int8_t *lcfg = TLVP_VAL(tp, NM_ATT_BS11_LINE_CFG);
printf("\tLine Configuration: %s (%d)\n",
bport_lcfg_name(*lcfg), *lcfg);
}
return 0;
@@ -459,6 +481,8 @@ static void cmd_query(void)
trx = gsm_bts_trx_num(g_bts, 1);
if (trx)
abis_nm_bs11_get_trx_power(trx);
abis_nm_bs11_get_bport_line_cfg(g_bts, 0);
abis_nm_bs11_get_bport_line_cfg(g_bts, 1);
sleep(1);
abis_nm_bs11_factory_logon(g_bts, 0);
command = NULL;
@@ -585,7 +609,13 @@ static int handle_state_resp(enum abis_bs11_phase state)
sleep(1);
abis_nm_bs11_factory_logon(g_bts, 0);
command = NULL;
} else if (!strcmp(command, "bport1-multidrop")) {
abis_nm_bs11_set_bport_line_cfg(g_bts, 1, BS11_LINE_CFG_MULTIDROP);
sleep(1);
abis_nm_bs11_factory_logon(g_bts, 0);
command = NULL;
}
}
break;
case BS11_STATE_NORMAL:
@@ -672,6 +702,21 @@ int handle_serial_msg(struct msgb *rx_msg)
foh->obj_class, foh->obj_inst.bts_nr,
foh->obj_inst.trx_nr, foh->obj_inst.ts_nr);
break;
case NM_MT_GET_ATTR_NACK:
printf("\n%sGET ATTR NACK\n", obj_name(foh));
break;
case NM_MT_BS11_CREATE_OBJ_ACK:
printf("\n%sCREATE OBJECT ACK\n", obj_name(foh));
break;
case NM_MT_BS11_CREATE_OBJ_NACK:
printf("\n%sCREATE OBJECT NACK\n", obj_name(foh));
break;
case NM_MT_BS11_DELETE_OBJ_ACK:
printf("\n%sDELETE OBJECT ACK\n", obj_name(foh));
break;
case NM_MT_BS11_DELETE_OBJ_NACK:
printf("\n%sDELETE OBJECT NACK\n", obj_name(foh));
break;
default:
rc = abis_nm_rcvmsg(rx_msg);
}
@@ -696,13 +741,6 @@ int handle_serial_msg(struct msgb *rx_msg)
return rc;
}
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_ins)
{
return 0;
}
void status_timer_cb(void *data)
{
abis_nm_bs11_get_state(g_bts);
@@ -710,7 +748,7 @@ void status_timer_cb(void *data)
static void print_banner(void)
{
printf("bs11_config (C) 2009 by Harald Welte and Dieter Spaar\n");
printf("bs11_config (C) 2009-2010 by Harald Welte and Dieter Spaar\n");
printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
}
@@ -740,7 +778,8 @@ static void print_help(void)
printf("\tpll-workvalue <value>\tSet the PLL work value\n");
printf("\toml-tei\t\t\tSet OML E1 TS and TEI\n");
printf("\tbport0-star\t\tSet BPORT0 line config to star\n");
printf("\tbport0-multiport\tSet BPORT0 line config to multiport\n");
printf("\tbport0-multidrop\tSet BPORT0 line config to multidrop\n");
printf("\tbport1-multidrop\tSet BPORT1 line config to multidrop\n");
printf("\tcreate-bport1\t\tCreate BPORT1 object\n");
printf("\tdelete-bport1\t\tDelete BPORT1 object\n");
}

View File

@@ -1,12 +1,13 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS)
AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS)
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
bin_PROGRAMS = osmo-bsc
osmo_bsc_SOURCES = osmo_bsc_main.c osmo_bsc_rf.c osmo_bsc_vty.c osmo_bsc_api.c \
osmo_bsc_grace.c osmo_bsc_msc.c \
osmo_bsc_grace.c osmo_bsc_msc.c osmo_bsc_sccp.c \
osmo_bsc_filter.c osmo_bsc_bssap.c osmo_bsc_audio.c \
$(top_srcdir)/src/debug.c $(top_srcdir)/src/bsc_msc.c \
$(top_srcdir)/src/bsc_init.c
osmo_bsc_LDADD = $(top_builddir)/src/libvty.a \

View File

@@ -3,73 +3,169 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <openbsc/osmo_bsc.h>
#include <openbsc/osmo_msc_data.h>
#include <openbsc/debug.h>
#include <osmocore/protocol/gsm_08_08.h>
#include <osmocore/gsm0808.h>
#define return_when_not_connected(conn) \
if (!conn->sccp_con) {\
LOGP(DMSC, LOGL_ERROR, "MSC Connection not present.\n"); \
return; \
}
#define return_when_not_connected_val(conn, ret) \
if (!conn->sccp_con) {\
LOGP(DMSC, LOGL_ERROR, "MSC Connection not present.\n"); \
return ret; \
}
#define queue_msg_or_return(resp) \
if (!resp) { \
LOGP(DMSC, LOGL_ERROR, "Failed to allocate response.\n"); \
return; \
} \
bsc_queue_for_msc(conn->sccp_con, resp);
static uint16_t get_network_code_for_msc(struct gsm_network *net)
{
if (net->msc_data->core_ncc != -1)
return net->msc_data->core_ncc;
return net->network_code;
}
static uint16_t get_country_code_for_msc(struct gsm_network *net)
{
if (net->msc_data->core_mcc != -1)
return net->msc_data->core_mcc;
return net->country_code;
}
static void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
{
struct msgb *resp;
return_when_not_connected(conn);
resp = gsm0808_create_sapi_reject(dlci);
queue_msg_or_return(resp);
}
static void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
struct msgb *msg, uint8_t chosen_encr)
{
struct msgb *resp;
return_when_not_connected(conn);
LOGP(DMSC, LOGL_DEBUG, "CIPHER MODE COMPLETE from MS, forwarding to MSC\n");
resp = gsm0808_create_cipher_complete(msg, chosen_encr);
queue_msg_or_return(resp);
}
static void bsc_cipher_mode_reject(struct gsm_subscriber_connection *conn,
struct msgb *msg, uint16_t reason)
{
}
/*
* Instruct to reserve data for a new connectiom, create the complete
* layer three message, send it to open the connection.
*/
static int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg,
uint16_t chosen_channel)
{
return BSC_API_CONN_POL_REJECT;
struct msgb *resp;
uint16_t network_code = get_network_code_for_msc(conn->bts->network);
uint16_t country_code = get_country_code_for_msc(conn->bts->network);
/* allocate resource for a new connection */
if (bsc_create_new_connection(conn) != 0)
return BSC_API_CONN_POL_REJECT;
bsc_scan_bts_msg(conn, msg);
resp = gsm0808_create_layer3(msg, network_code, country_code,
conn->bts->location_area_code,
conn->bts->cell_identity);
if (!resp) {
LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
bsc_delete_connection(conn->sccp_con);
return BSC_API_CONN_POL_REJECT;
}
if (bsc_open_connection(conn->sccp_con, resp) != 0) {
bsc_delete_connection(conn->sccp_con);
msgb_free(resp);
return BSC_API_CONN_POL_REJECT;
}
return BSC_API_CONN_POL_ACCEPT;
}
static void bsc_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg)
static void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
{
struct msgb *resp;
return_when_not_connected(conn);
bsc_scan_bts_msg(conn, msg);
resp = gsm0808_create_dtap(msg, link_id);
queue_msg_or_return(resp);
}
static void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint16_t rr_cause)
static void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_cause,
uint8_t chosen_channel, uint8_t encr_alg_id,
uint8_t speech_model)
{
struct msgb *resp;
return_when_not_connected(conn);
resp = gsm0808_create_assignment_completed(rr_cause, chosen_channel,
encr_alg_id, speech_model);
queue_msg_or_return(resp);
}
static void bsc_assign_fail(struct gsm_subscriber_connection *conn, uint32_t cause)
static void bsc_assign_fail(struct gsm_subscriber_connection *conn,
uint8_t cause, uint8_t *rr_cause)
{
struct msgb *resp;
return_when_not_connected(conn);
resp = gsm0808_create_assignment_failure(cause, rr_cause);
queue_msg_or_return(resp);
}
static void bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
{
}
struct msgb *resp;
return_when_not_connected_val(conn, 1);
static void bsc_clear_compl(struct gsm_subscriber_connection *conn)
{
resp = gsm0808_create_clear_rqst(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE);
if (!resp) {
LOGP(DMSC, LOGL_ERROR, "Failed to allocate response.\n");
return 0;
}
bsc_queue_for_msc(conn->sccp_con, resp);
return 0;
}
static struct bsc_api bsc_handler = {
.sapi_n_reject = bsc_sapi_n_reject,
.cipher_mode_compl = bsc_cipher_mode_compl,
.cipher_mode_reject = bsc_cipher_mode_reject,
.compl_l3 = bsc_compl_l3,
.dtap = bsc_dtap,
.assign_compl = bsc_assign_compl,
.assign_fail = bsc_assign_fail,
.clear_request = bsc_clear_request,
.clear_compl = bsc_clear_compl,
};
struct bsc_api *osmo_bsc_api()

View File

@@ -0,0 +1,70 @@
/*
* ipaccess audio handling
*
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by On-Waves
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include <openbsc/osmo_msc_data.h>
#include <openbsc/osmo_bsc.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/gsm_data.h>
#include <openbsc/debug.h>
#include <openbsc/signal.h>
#include <arpa/inet.h>
static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct gsm_subscriber_connection *con;
struct gsm_lchan *lchan = signal_data;
int rc;
if (subsys != SS_ABISIP)
return 0;
con = lchan->conn;
if (!con || !con->sccp_con)
return 0;
switch (signal) {
case S_ABISIP_CRCX_ACK:
/* we can ask it to connect now */
LOGP(DMSC, LOGL_DEBUG, "Connecting BTS to port: %d conn: %d\n",
con->sccp_con->rtp_port, lchan->abis_ip.conn_id);
rc = rsl_ipacc_mdcx(lchan, ntohl(INADDR_ANY),
con->sccp_con->rtp_port,
lchan->abis_ip.rtp_payload2);
if (rc < 0) {
LOGP(DMSC, LOGL_ERROR, "Failed to send MDCX: %d\n", rc);
return rc;
}
break;
}
return 0;
}
int osmo_bsc_audio_init(struct gsm_network *net)
{
net->hardcoded_rtp_payload = 98;
register_signal_handler(SS_ABISIP, handle_abisip_signal, net);
return 0;
}

View File

@@ -0,0 +1,548 @@
/* GSM 08.08 BSSMAP handling */
/* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by On-Waves
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include <openbsc/osmo_bsc.h>
#include <openbsc/osmo_bsc_grace.h>
#include <openbsc/osmo_msc_data.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_subscriber.h>
#include <openbsc/mgcp.h>
#include <openbsc/paging.h>
#include <osmocore/gsm0808.h>
#include <osmocore/protocol/gsm_08_08.h>
#include <arpa/inet.h>
static uint16_t read_data16(const uint8_t *data)
{
uint16_t res;
memcpy(&res, data, sizeof(res));
return res;
}
/*
* helpers for the assignment command
*/
enum gsm0808_permitted_speech audio_support_to_gsm88(struct gsm_audio_support *audio)
{
if (audio->hr) {
switch (audio->ver) {
case 1:
return GSM0808_PERM_HR1;
break;
case 2:
return GSM0808_PERM_HR2;
break;
case 3:
return GSM0808_PERM_HR3;
break;
default:
LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n", audio->ver);
return GSM0808_PERM_FR1;
}
} else {
switch (audio->ver) {
case 1:
return GSM0808_PERM_FR1;
break;
case 2:
return GSM0808_PERM_FR2;
break;
case 3:
return GSM0808_PERM_FR3;
break;
default:
LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n", audio->ver);
return GSM0808_PERM_HR1;
}
}
}
enum gsm48_chan_mode gsm88_to_chan_mode(enum gsm0808_permitted_speech speech)
{
switch (speech) {
case GSM0808_PERM_HR1:
case GSM0808_PERM_FR1:
return GSM48_CMODE_SPEECH_V1;
break;
case GSM0808_PERM_HR2:
case GSM0808_PERM_FR2:
return GSM48_CMODE_SPEECH_EFR;
break;
case GSM0808_PERM_HR3:
case GSM0808_PERM_FR3:
return GSM48_CMODE_SPEECH_AMR;
break;
}
LOGP(DMSC, LOGL_FATAL, "Should not be reached.\n");
return GSM48_CMODE_SPEECH_AMR;
}
static int bssmap_handle_reset_ack(struct gsm_network *net,
struct msgb *msg, unsigned int length)
{
LOGP(DMSC, LOGL_NOTICE, "Reset ACK from MSC\n");
return 0;
}
/* GSM 08.08 § 3.2.1.19 */
static int bssmap_handle_paging(struct gsm_network *net,
struct msgb *msg, unsigned int payload_length)
{
struct gsm_subscriber *subscr;
struct tlv_parsed tp;
char mi_string[GSM48_MI_SIZE];
uint32_t tmsi = GSM_RESERVED_TMSI;
unsigned int lac = GSM_LAC_RESERVED_ALL_BTS;
uint8_t data_length;
const uint8_t *data;
uint8_t chan_needed = RSL_CHANNEED_ANY;
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
if (!TLVP_PRESENT(&tp, GSM0808_IE_IMSI)) {
LOGP(DMSC, LOGL_ERROR, "Mandantory IMSI not present.\n");
return -1;
} else if ((TLVP_VAL(&tp, GSM0808_IE_IMSI)[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI) {
LOGP(DMSC, LOGL_ERROR, "Wrong content in the IMSI\n");
return -1;
}
if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) {
LOGP(DMSC, LOGL_ERROR, "Mandantory CELL IDENTIFIER LIST not present.\n");
return -1;
}
if (TLVP_PRESENT(&tp, GSM0808_IE_TMSI)) {
gsm48_mi_to_string(mi_string, sizeof(mi_string),
TLVP_VAL(&tp, GSM0808_IE_TMSI), TLVP_LEN(&tp, GSM0808_IE_TMSI));
tmsi = strtoul(mi_string, NULL, 10);
}
/*
* parse the IMSI
*/
gsm48_mi_to_string(mi_string, sizeof(mi_string),
TLVP_VAL(&tp, GSM0808_IE_IMSI), TLVP_LEN(&tp, GSM0808_IE_IMSI));
/*
* parse the cell identifier list
*/
data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
/*
* Support paging to all network or one BTS at one LAC
*/
if (data_length == 3 && data[0] == CELL_IDENT_LAC) {
lac = ntohs(read_data16(&data[1]));
} else if (data_length > 1 || (data[0] & 0x0f) != CELL_IDENT_BSS) {
LOGP(DMSC, LOGL_ERROR, "Unsupported Cell Identifier List: %s\n", hexdump(data, data_length));
return -1;
}
if (TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_NEEDED) && TLVP_LEN(&tp, GSM0808_IE_CHANNEL_NEEDED) == 1)
chan_needed = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_NEEDED)[0] & 0x03;
if (TLVP_PRESENT(&tp, GSM0808_IE_EMLPP_PRIORITY)) {
LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n");
}
subscr = subscr_get_or_create(net, mi_string);
if (!subscr) {
LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string);
return -1;
}
subscr->lac = lac;
subscr->tmsi = tmsi;
LOGP(DMSC, LOGL_DEBUG, "Paging request from MSC IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n", mi_string, tmsi, tmsi, lac);
paging_request(net, subscr, chan_needed, NULL, NULL);
return 0;
}
/*
* GSM 08.08 § 3.1.9.1 and 3.2.1.21...
* release our gsm_subscriber_connection and send message
*/
static int bssmap_handle_clear_command(struct osmo_bsc_sccp_con *conn,
struct msgb *msg, unsigned int payload_length)
{
struct msgb *resp;
/* TODO: handle the cause of this package */
if (conn->conn) {
LOGP(DMSC, LOGL_DEBUG, "Releasing all transactions on %p\n", conn);
gsm0808_clear(conn->conn);
subscr_con_free(conn->conn);
conn->conn = NULL;
}
/* send the clear complete message */
resp = gsm0808_create_clear_complete();
if (!resp) {
LOGP(DMSC, LOGL_ERROR, "Sending clear complete failed.\n");
return -1;
}
bsc_queue_for_msc(conn, resp);
return 0;
}
/*
* GSM 08.08 § 3.4.7 cipher mode handling. We will have to pick
* the cipher to be used for this. In case we are already using
* a cipher we will have to send cipher mode reject to the MSC,
* otherwise we will have to pick something that we and the MS
* is supporting. Currently we are doing it in a rather static
* way by picking one ecnryption or no encrytpion.
*/
static int bssmap_handle_cipher_mode(struct osmo_bsc_sccp_con *conn,
struct msgb *msg, unsigned int payload_length)
{
uint16_t len;
struct gsm_network *network = NULL;
const uint8_t *data;
struct tlv_parsed tp;
struct msgb *resp;
int reject_cause = -1;
int include_imeisv = 1;
if (!conn->conn) {
LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
goto reject;
}
if (conn->ciphering_handled) {
LOGP(DMSC, LOGL_ERROR, "Already seen ciphering command. Protocol Error.\n");
goto reject;
}
conn->ciphering_handled = 1;
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
if (!TLVP_PRESENT(&tp, GSM0808_IE_ENCRYPTION_INFORMATION)) {
LOGP(DMSC, LOGL_ERROR, "IE Encryption Information missing.\n");
goto reject;
}
/*
* check if our global setting is allowed
* - Currently we check for A5/0 and A5/1
* - Copy the key if that is necessary
* - Otherwise reject
*/
len = TLVP_LEN(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
if (len < 1) {
LOGP(DMSC, LOGL_ERROR, "IE Encryption Information is too short.\n");
goto reject;
}
network = conn->conn->bts->network;
data = TLVP_VAL(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
if (TLVP_PRESENT(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE))
include_imeisv = TLVP_VAL(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE)[0] & 0x1;
if (network->a5_encryption == 0 && (data[0] & 0x1) == 0x1) {
gsm0808_cipher_mode(conn->conn, 0, NULL, 0, include_imeisv);
} else if (network->a5_encryption != 0 && (data[0] & 0x2) == 0x2) {
gsm0808_cipher_mode(conn->conn, 1, &data[1], len - 1, include_imeisv);
} else {
LOGP(DMSC, LOGL_ERROR, "Can not select encryption...\n");
goto reject;
}
reject:
resp = gsm0808_create_cipher_reject(reject_cause);
if (!resp) {
LOGP(DMSC, LOGL_ERROR, "Sending the cipher reject failed.\n");
return -1;
}
bsc_queue_for_msc(conn, resp);
return -1;
}
/*
* Handle the assignment request message.
*
* See §3.2.1.1 for the message type
*/
static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn,
struct msgb *msg, unsigned int length)
{
struct msgb *resp;
struct gsm_network *network;
struct tlv_parsed tp;
uint8_t *data;
uint16_t cic;
uint8_t timeslot;
uint8_t multiplex;
enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN;
int i, supported, port, full_rate = -1;
if (!conn->conn) {
LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
return -1;
}
network = conn->conn->bts->network;
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0);
if (!TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_TYPE)) {
LOGP(DMSC, LOGL_ERROR, "Mandantory channel type not present.\n");
goto reject;
}
if (!TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
LOGP(DMSC, LOGL_ERROR, "Identity code missing. Audio routing will not work.\n");
goto reject;
}
cic = ntohs(read_data16(TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)));
timeslot = cic & 0x1f;
multiplex = (cic & ~0x1f) >> 5;
/*
* Currently we only support a limited subset of all
* possible channel types. The limitation ends by not using
* multi-slot, limiting the channel coding, speech...
*/
if (TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE) < 3) {
LOGP(DMSC, LOGL_ERROR, "ChannelType len !=3 not supported: %d\n",
TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE));
goto reject;
}
/*
* Try to figure out if we support the proposed speech codecs. For
* now we will always pick the full rate codecs.
*/
data = (uint8_t *) TLVP_VAL(&tp, GSM0808_IE_CHANNEL_TYPE);
if ((data[0] & 0xf) != 0x1) {
LOGP(DMSC, LOGL_ERROR, "ChannelType != speech: %d\n", data[0]);
goto reject;
}
if (data[1] != GSM0808_SPEECH_FULL_PREF && data[1] != GSM0808_SPEECH_HALF_PREF) {
LOGP(DMSC, LOGL_ERROR, "ChannelType full not allowed: %d\n", data[1]);
goto reject;
}
/*
* go through the list of preferred codecs of our gsm network
* and try to find it among the permitted codecs. If we found
* it we will send chan_mode to the right mode and break the
* inner loop. The outer loop will exit due chan_mode having
* the correct value.
*/
full_rate = 0;
for (supported = 0;
chan_mode == GSM48_CMODE_SIGN && supported < network->msc_data->audio_length;
++supported) {
int perm_val = audio_support_to_gsm88(network->msc_data->audio_support[supported]);
for (i = 2; i < TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE); ++i) {
if ((data[i] & 0x7f) == perm_val) {
chan_mode = gsm88_to_chan_mode(perm_val);
full_rate = (data[i] & 0x4) == 0;
break;
} else if ((data[i] & 0x80) == 0x00) {
break;
}
}
}
if (chan_mode == GSM48_CMODE_SIGN) {
LOGP(DMSC, LOGL_ERROR, "No supported audio type found.\n");
goto reject;
}
/* map it to a MGCP Endpoint and a RTP port */
port = mgcp_timeslot_to_endpoint(multiplex, timeslot);
conn->rtp_port = rtp_calculate_port(port,
network->msc_data->rtp_base);
return gsm0808_assign_req(conn->conn, chan_mode, full_rate);
reject:
resp = gsm0808_create_assignment_failure(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
if (!resp) {
LOGP(DMSC, LOGL_ERROR, "Channel allocation failure.\n");
return -1;
}
bsc_queue_for_msc(conn, resp);
return -1;
}
static int bssmap_rcvmsg_udt(struct gsm_network *net,
struct msgb *msg, unsigned int length)
{
int ret = 0;
if (length < 1) {
LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
return -1;
}
switch (msg->l4h[0]) {
case BSS_MAP_MSG_RESET_ACKNOWLEDGE:
ret = bssmap_handle_reset_ack(net, msg, length);
break;
case BSS_MAP_MSG_PAGING:
if (bsc_grace_allow_new_connection(net))
ret = bssmap_handle_paging(net, msg, length);
break;
}
return ret;
}
static int bssmap_rcvmsg_dt1(struct osmo_bsc_sccp_con *conn,
struct msgb *msg, unsigned int length)
{
int ret = 0;
if (length < 1) {
LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
return -1;
}
switch (msg->l4h[0]) {
case BSS_MAP_MSG_CLEAR_CMD:
ret = bssmap_handle_clear_command(conn, msg, length);
break;
case BSS_MAP_MSG_CIPHER_MODE_CMD:
ret = bssmap_handle_cipher_mode(conn, msg, length);
break;
case BSS_MAP_MSG_ASSIGMENT_RQST:
ret = bssmap_handle_assignm_req(conn, msg, length);
break;
default:
LOGP(DMSC, LOGL_DEBUG, "Unimplemented msg type: %d\n", msg->l4h[0]);
break;
}
return ret;
}
static int dtap_rcvmsg(struct osmo_bsc_sccp_con *conn,
struct msgb *msg, unsigned int length)
{
struct dtap_header *header;
struct msgb *gsm48;
uint8_t *data;
if (!conn->conn) {
LOGP(DMSC, LOGL_ERROR, "No subscriber connection available\n");
return -1;
}
header = (struct dtap_header *) msg->l3h;
if (sizeof(*header) >= length) {
LOGP(DMSC, LOGL_ERROR, "The DTAP header does not fit. Wanted: %u got: %u\n", sizeof(*header), length);
LOGP(DMSC, LOGL_ERROR, "hex: %s\n", hexdump(msg->l3h, length));
return -1;
}
if (header->length > length - sizeof(*header)) {
LOGP(DMSC, LOGL_ERROR, "The DTAP l4 information does not fit: header: %u length: %u\n", header->length, length);
LOGP(DMSC, LOGL_ERROR, "hex: %s\n", hexdump(msg->l3h, length));
return -1;
}
LOGP(DMSC, LOGL_DEBUG, "DTAP message: SAPI: %u CHAN: %u\n", header->link_id & 0x07, header->link_id & 0xC0);
/* forward the data */
gsm48 = gsm48_msgb_alloc();
if (!gsm48) {
LOGP(DMSC, LOGL_ERROR, "Allocation of the message failed.\n");
return -1;
}
gsm48->l3h = gsm48->data;
data = msgb_put(gsm48, length - sizeof(*header));
memcpy(data, msg->l3h + sizeof(*header), length - sizeof(*header));
/* pass it to the filter for extra actions */
bsc_scan_msc_msg(conn->conn, gsm48);
return gsm0808_submit_dtap(conn->conn, gsm48, header->link_id, 1);
}
int bsc_handle_udt(struct gsm_network *network,
struct bsc_msc_connection *conn,
struct msgb *msgb, unsigned int length)
{
struct bssmap_header *bs;
LOGP(DMSC, LOGL_DEBUG, "Incoming SCCP message ftom MSC: %s\n",
hexdump(msgb->l3h, length));
if (length < sizeof(*bs)) {
LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
return -1;
}
bs = (struct bssmap_header *) msgb->l3h;
if (bs->length < length - sizeof(*bs))
return -1;
switch (bs->type) {
case BSSAP_MSG_BSS_MANAGEMENT:
msgb->l4h = &msgb->l3h[sizeof(*bs)];
bssmap_rcvmsg_udt(network, msgb, length - sizeof(*bs));
break;
default:
LOGP(DMSC, LOGL_ERROR, "Unimplemented msg type: %d\n", bs->type);
}
return 0;
}
int bsc_handle_dt1(struct osmo_bsc_sccp_con *conn,
struct msgb *msg, unsigned int len)
{
if (len < sizeof(struct bssmap_header)) {
LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
}
switch (msg->l3h[0]) {
case BSSAP_MSG_BSS_MANAGEMENT:
msg->l4h = &msg->l3h[sizeof(struct bssmap_header)];
bssmap_rcvmsg_dt1(conn, msg, len - sizeof(struct bssmap_header));
break;
case BSSAP_MSG_DTAP:
dtap_rcvmsg(conn, msg, len);
break;
default:
LOGP(DMSC, LOGL_DEBUG, "Unimplemented msg type: %d\n", msg->l3h[0]);
}
return -1;
}

View File

@@ -0,0 +1,170 @@
/* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by On-Waves
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include <openbsc/osmo_bsc.h>
#include <openbsc/osmo_msc_data.h>
#include <openbsc/gsm_04_80.h>
#include <openbsc/gsm_subscriber.h>
#include <openbsc/debug.h>
#include <openbsc/paging.h>
#include <stdlib.h>
static void handle_lu_request(struct gsm_subscriber_connection *conn,
struct msgb *msg)
{
struct gsm48_hdr *gh;
struct gsm48_loc_upd_req *lu;
struct gsm48_loc_area_id lai;
struct gsm_network *net;
if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu)) {
LOGP(DMSC, LOGL_ERROR, "LU too small to look at: %u\n", msgb_l3len(msg));
return;
}
net = conn->bts->network;
gh = msgb_l3(msg);
lu = (struct gsm48_loc_upd_req *) gh->data;
gsm48_generate_lai(&lai, net->country_code, net->network_code,
conn->bts->location_area_code);
if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) {
LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n");
conn->sccp_con->new_subscriber = 1;
}
}
/* we will need to stop the paging request */
static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
uint8_t mi_type;
char mi_string[GSM48_MI_SIZE];
struct gsm48_hdr *gh;
struct gsm48_pag_resp *resp;
struct gsm_subscriber *subscr;
if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*resp)) {
LOGP(DMSC, LOGL_ERROR, "PagingResponse too small: %u\n", msgb_l3len(msg));
return -1;
}
gh = msgb_l3(msg);
resp = (struct gsm48_pag_resp *) &gh->data[0];
gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
mi_string, &mi_type);
DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
mi_type, mi_string);
switch (mi_type) {
case GSM_MI_TYPE_TMSI:
subscr = subscr_active_by_tmsi(conn->bts->network,
tmsi_from_string(mi_string));
break;
case GSM_MI_TYPE_IMSI:
subscr = subscr_active_by_imsi(conn->bts->network, mi_string);
break;
default:
subscr = NULL;
break;
}
if (!subscr) {
LOGP(DMSC, LOGL_ERROR, "Non active subscriber got paged.\n");
return -1;
}
paging_request_stop(conn->bts, subscr, conn, msg);
subscr_put(subscr);
return 0;
}
/**
* This is used to scan a message for extra functionality of the BSC. This
* includes scanning for location updating requests/acceptd and then send
* a welcome USSD message to the subscriber.
*/
int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
uint8_t pdisc = gh->proto_discr & 0x0f;
uint8_t mtype = gh->msg_type & 0xbf;
if (pdisc == GSM48_PDISC_MM) {
if (mtype == GSM48_MT_MM_LOC_UPD_REQUEST)
handle_lu_request(conn, msg);
} else if (pdisc == GSM48_PDISC_RR) {
if (mtype == GSM48_MT_RR_PAG_RESP)
handle_page_resp(conn, msg);
}
return 0;
}
static void send_welcome_ussd(struct gsm_subscriber_connection *conn)
{
struct gsm_network *net;
net = conn->bts->network;
if (!net->msc_data->ussd_welcome_txt)
return;
gsm0480_send_ussdNotify(conn, 1, net->msc_data->ussd_welcome_txt);
gsm0480_send_releaseComplete(conn);
}
/**
* Messages coming back from the MSC.
*/
int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
struct gsm_network *net;
struct gsm48_loc_area_id *lai;
struct gsm48_hdr *gh;
uint8_t mtype;
if (msgb_l3len(msg) < sizeof(*gh)) {
LOGP(DMSC, LOGL_ERROR, "GSM48 header does not fit.\n");
return -1;
}
gh = (struct gsm48_hdr *) msgb_l3(msg);
mtype = gh->msg_type & 0xbf;
net = conn->bts->network;
if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) {
if (net->msc_data->core_ncc != -1 ||
net->msc_data->core_mcc != -1) {
if (msgb_l3len(msg) >= sizeof(*gh) + sizeof(*lai)) {
lai = (struct gsm48_loc_area_id *) &gh->data[0];
gsm48_generate_lai(lai, net->country_code,
net->network_code,
conn->bts->location_area_code);
}
}
if (conn->sccp_con->new_subscriber)
send_welcome_ussd(conn);
}
return 0;
}

View File

@@ -4,18 +4,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -69,7 +68,7 @@ static int handle_grace(struct gsm_network *network)
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
if (!network->msc_data->ussd_grace_txt)
if (!network->msc_data->mid_call_txt)
return 0;
llist_for_each_entry(bts, &network->bts_list, list) {
@@ -78,7 +77,7 @@ static int handle_grace(struct gsm_network *network)
struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN; ++lchan_nr) {
handle_sub(&ts->lchan[lchan_nr],
network->msc_data->ussd_grace_txt);
network->msc_data->mid_call_txt);
}
}
}

View File

@@ -4,18 +4,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -51,8 +50,7 @@ static const char *rf_ctl = NULL;
extern const char *openbsc_copyright;
static int daemonize = 0;
extern void bsc_vty_init(void);
extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, int, void *), const char *cfg_file);
extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, struct msgb *), const char *cfg_file);
static void print_usage()
{
@@ -140,7 +138,7 @@ extern int bts_model_nanobts_init(void);
extern enum node_type bsc_vty_go_parent(struct vty *vty);
static struct vty_app_info vty_info = {
.name = "OpenBSC Osmo BSC",
.name = "OsmoBSC",
.version = PACKAGE_VERSION,
.go_parent_cb = bsc_vty_go_parent,
.is_config_node = bsc_vty_is_config_node,
@@ -231,6 +229,16 @@ int main(int argc, char **argv)
exit(1);
}
if (osmo_bsc_sccp_init(bsc_gsmnet) != 0) {
LOGP(DNM, LOGL_ERROR, "Failed to register SCCP.\n");
exit(1);
}
if (osmo_bsc_audio_init(bsc_gsmnet) != 0) {
LOGP(DMSC, LOGL_ERROR, "Failed to register audio support.\n");
exit(1);
}
signal(SIGINT, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);

View File

@@ -6,18 +6,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -68,7 +67,7 @@ static int mgcp_do_read(struct bsc_fd *fd)
}
mgcp->l2h = msgb_put(mgcp, ret);
msc_queue_write(data->msc_con, mgcp, IPAC_PROTO_MGCP);
msc_queue_write(data->msc_con, mgcp, IPAC_PROTO_MGCP_OLD);
return 0;
}
@@ -175,12 +174,12 @@ int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto
return 0;
}
static int msc_sccp_do_write(struct bsc_fd *fd, struct msgb *msg)
static int msc_alink_do_write(struct bsc_fd *fd, struct msgb *msg)
{
int ret;
LOGP(DMSC, LOGL_DEBUG, "Sending SCCP to MSC: %u\n", msgb_l2len(msg));
LOGP(DMI, LOGL_DEBUG, "MSC TX %s\n", hexdump(msg->l2h, msgb_l2len(msg)));
LOGP(DMI, LOGL_DEBUG, "MSC TX %s\n", hexdump(msg->data, msg->len));
ret = write(fd->fd, msg->data, msg->len);
if (ret < msg->len)
@@ -194,8 +193,7 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
int error;
struct msgb *msg = ipaccess_read_msg(bfd, &error);
struct ipaccess_head *hh;
struct gsm_network *net = (struct gsm_network *) bfd->data;
struct osmo_msc_data *data = net->msc_data;
struct osmo_msc_data *data = (struct osmo_msc_data *) bfd->data;
if (!msg) {
if (error == 0) {
@@ -225,7 +223,7 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
}
} else if (hh->proto == IPAC_PROTO_SCCP) {
sccp_system_incoming(msg);
} else if (hh->proto == IPAC_PROTO_MGCP) {
} else if (hh->proto == IPAC_PROTO_MGCP_OLD) {
mgcp_forward(data, msg);
}
@@ -283,7 +281,7 @@ static void msc_connection_connected(struct bsc_msc_connection *con)
LOGP(DMSC, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
data = (struct osmo_msc_data *) con->write_queue.bfd.data;
msc_ping_timeout_cb(con);
msc_ping_timeout_cb(data);
sig.data = data;
dispatch_signal(SS_MSC, S_MSC_CONNECTED, &sig);
@@ -363,7 +361,7 @@ int osmo_bsc_msc_init(struct gsm_network *network)
data->msc_con->connection_loss = msc_connection_was_lost;
data->msc_con->connected = msc_connection_connected;
data->msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
data->msc_con->write_queue.write_cb = msc_sccp_do_write;
data->msc_con->write_queue.write_cb = msc_alink_do_write;
bsc_msc_connect(data->msc_con);
return 0;

View File

@@ -6,18 +6,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -25,6 +24,7 @@
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/signal.h>
#include <openbsc/osmo_msc_data.h>
#include <osmocore/talloc.h>
#include <osmocore/protocol/gsm_12_21.h>
@@ -38,7 +38,8 @@
#define RF_CMD_QUERY '?'
#define RF_CMD_OFF '0'
#define RF_CMD_ON '1'
#define RF_CMD_GRACE 'g'
#define RF_CMD_D_OFF 'd'
#define RF_CMD_ON_G 'g'
static int lock_each_trx(struct gsm_network *net, int lock)
{
@@ -54,25 +55,9 @@ static int lock_each_trx(struct gsm_network *net, int lock)
return 0;
}
/*
* Send a '1' when one TRX is online, otherwise send 0
*/
static void handle_query(struct osmo_bsc_rf_conn *conn)
static void send_resp(struct osmo_bsc_rf_conn *conn, char send)
{
struct msgb *msg;
struct gsm_bts *bts;
char send = RF_CMD_OFF;
llist_for_each_entry(bts, &conn->rf->gsm_network->bts_list, list) {
struct gsm_bts_trx *trx;
llist_for_each_entry(trx, &bts->trx_list, list) {
if (trx->nm_state.availability == NM_AVSTATE_OK &&
trx->nm_state.operational != NM_STATE_LOCKED) {
send = RF_CMD_ON;
break;
}
}
}
msg = msgb_alloc(10, "RF Query");
if (!msg) {
@@ -92,15 +77,122 @@ static void handle_query(struct osmo_bsc_rf_conn *conn)
return;
}
static void send_signal(struct osmo_bsc_rf_conn *conn, int val)
/*
* Send a
* 'g' when we are in grace mode
* '1' when one TRX is online,
* '0' otherwise
*/
static void handle_query(struct osmo_bsc_rf_conn *conn)
{
struct gsm_bts *bts;
char send = RF_CMD_OFF;
if (conn->rf->policy == S_RF_GRACE)
return send_resp(conn, RF_CMD_ON_G);
llist_for_each_entry(bts, &conn->rf->gsm_network->bts_list, list) {
struct gsm_bts_trx *trx;
llist_for_each_entry(trx, &bts->trx_list, list) {
if (trx->nm_state.availability == NM_AVSTATE_OK &&
trx->nm_state.operational != NM_STATE_LOCKED) {
send = RF_CMD_ON;
break;
}
}
}
send_resp(conn, send);
}
static void rf_check_cb(void *_data)
{
struct gsm_bts *bts;
struct osmo_bsc_rf *rf = _data;
llist_for_each_entry(bts, &rf->gsm_network->bts_list, list) {
struct gsm_bts_trx *trx;
/* don't bother to check a booting or missing BTS */
if (!bts->oml_link || !is_ipaccess_bts(bts))
continue;
llist_for_each_entry(trx, &bts->trx_list, list) {
if (trx->nm_state.availability != NM_AVSTATE_OK ||
trx->nm_state.operational != NM_OPSTATE_ENABLED ||
trx->nm_state.administrative != NM_STATE_UNLOCKED) {
LOGP(DNM, LOGL_ERROR, "RF activation failed. Starting again.\n");
ipaccess_drop_oml(bts);
break;
}
}
}
}
static void send_signal(struct osmo_bsc_rf *rf, int val)
{
struct rf_signal_data sig;
sig.net = conn->rf->gsm_network;
sig.net = rf->gsm_network;
conn->rf->policy = val;
rf->policy = val;
dispatch_signal(SS_RF, val, &sig);
}
static int switch_rf_off(struct osmo_bsc_rf *rf)
{
lock_each_trx(rf->gsm_network, 1);
send_signal(rf, S_RF_OFF);
return 0;
}
static void grace_timeout(void *_data)
{
struct osmo_bsc_rf *rf = (struct osmo_bsc_rf *) _data;
LOGP(DINP, LOGL_NOTICE, "Grace timeout. Disabling the TRX.\n");
switch_rf_off(rf);
}
static int enter_grace(struct osmo_bsc_rf *rf)
{
rf->grace_timeout.cb = grace_timeout;
rf->grace_timeout.data = rf;
bsc_schedule_timer(&rf->grace_timeout, rf->gsm_network->msc_data->mid_call_timeout, 0);
LOGP(DINP, LOGL_NOTICE, "Going to switch RF off in %d seconds.\n",
rf->gsm_network->msc_data->mid_call_timeout);
send_signal(rf, S_RF_GRACE);
return 0;
}
static void rf_delay_cmd_cb(void *data)
{
struct osmo_bsc_rf *rf = data;
switch (rf->last_request) {
case RF_CMD_D_OFF:
rf->last_state_command = "RF Direct Off";
bsc_del_timer(&rf->rf_check);
bsc_del_timer(&rf->grace_timeout);
switch_rf_off(rf);
break;
case RF_CMD_ON:
rf->last_state_command = "RF Direct On";
bsc_del_timer(&rf->grace_timeout);
lock_each_trx(rf->gsm_network, 0);
send_signal(rf, S_RF_ON);
bsc_schedule_timer(&rf->rf_check, 3, 0);
break;
case RF_CMD_OFF:
rf->last_state_command = "RF Scheduled Off";
bsc_del_timer(&rf->rf_check);
enter_grace(rf);
break;
}
}
static int rf_read_cmd(struct bsc_fd *fd)
{
struct osmo_bsc_rf_conn *conn = fd->data;
@@ -121,18 +213,15 @@ static int rf_read_cmd(struct bsc_fd *fd)
case RF_CMD_QUERY:
handle_query(conn);
break;
case RF_CMD_OFF:
lock_each_trx(conn->rf->gsm_network, 1);
send_signal(conn, S_RF_OFF);
break;
case RF_CMD_D_OFF:
case RF_CMD_ON:
lock_each_trx(conn->rf->gsm_network, 0);
send_signal(conn, S_RF_ON);
break;
case RF_CMD_GRACE:
send_signal(conn, S_RF_GRACE);
case RF_CMD_OFF:
conn->rf->last_request = buf[0];
if (!bsc_timer_pending(&conn->rf->delay_cmd))
bsc_schedule_timer(&conn->rf->delay_cmd, 1, 0);
break;
default:
conn->rf->last_state_command = "Unknown command";
LOGP(DINP, LOGL_ERROR, "Unknown command %d\n", buf[0]);
break;
}
@@ -260,6 +349,15 @@ struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net
rf->gsm_network = net;
rf->policy = S_RF_ON;
rf->last_state_command = "";
/* check the rf state */
rf->rf_check.data = rf;
rf->rf_check.cb = rf_check_cb;
/* delay cmd handling */
rf->delay_cmd.data = rf;
rf->delay_cmd.cb = rf_delay_cmd_cb;
return rf;
}

View File

@@ -0,0 +1,288 @@
/* Interaction with the SCCP subsystem */
/*
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by On-Waves
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include <openbsc/gsm_data.h>
#include <openbsc/osmo_bsc.h>
#include <openbsc/osmo_bsc_grace.h>
#include <openbsc/osmo_msc_data.h>
#include <openbsc/debug.h>
#include <openbsc/ipaccess.h>
#include <openbsc/signal.h>
#include <osmocore/gsm0808.h>
#include <osmocore/talloc.h>
#include <osmocore/protocol/gsm_08_08.h>
#include <osmocom/sccp/sccp.h>
/* SCCP helper */
#define SCCP_IT_TIMER 60
static LLIST_HEAD(active_connections);
static void free_queued(struct osmo_bsc_sccp_con *conn)
{
struct msgb *msg;
while (!llist_empty(&conn->sccp_queue)) {
/* this is not allowed to fail */
msg = msgb_dequeue(&conn->sccp_queue);
msgb_free(msg);
}
conn->sccp_queue_size = 0;
}
static void send_queued(struct osmo_bsc_sccp_con *conn)
{
struct msgb *msg;
while (!llist_empty(&conn->sccp_queue)) {
/* this is not allowed to fail */
msg = msgb_dequeue(&conn->sccp_queue);
sccp_connection_write(conn->sccp, msg);
msgb_free(msg);
conn->sccp_queue_size -= 1;
}
}
static void msc_outgoing_sccp_data(struct sccp_connection *conn,
struct msgb *msg, unsigned int len)
{
struct osmo_bsc_sccp_con *bsc_con =
(struct osmo_bsc_sccp_con *) conn->data_ctx;
bsc_handle_dt1(bsc_con, msg, len);
}
static void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state)
{
struct osmo_bsc_sccp_con *con_data;
if (conn->connection_state >= SCCP_CONNECTION_STATE_RELEASE_COMPLETE) {
con_data = (struct osmo_bsc_sccp_con *) conn->data_ctx;
if(con_data->conn) {
LOGP(DMSC, LOGL_ERROR,
"ERROR: The lchan is still associated\n.");
gsm0808_clear(con_data->conn);
subscr_con_free(con_data->conn);
con_data->conn = NULL;
}
con_data->sccp = NULL;
free_queued(con_data);
sccp_connection_free(conn);
bsc_delete_connection(con_data);
} else if (conn->connection_state == SCCP_CONNECTION_STATE_ESTABLISHED) {
LOGP(DMSC, LOGL_DEBUG, "Connection established: %p\n", conn);
con_data = (struct osmo_bsc_sccp_con *) conn->data_ctx;
bsc_del_timer(&con_data->sccp_cc_timeout);
bsc_schedule_timer(&con_data->sccp_it_timeout, SCCP_IT_TIMER, 0);
send_queued(con_data);
}
}
static void bsc_sccp_force_free(struct osmo_bsc_sccp_con *data)
{
if (data->conn) {
gsm0808_clear(data->conn);
subscr_con_free(data->conn);
data->conn = NULL;
}
free_queued(data);
sccp_connection_force_free(data->sccp);
data->sccp = NULL;
bsc_delete_connection(data);
}
static void sccp_it_timeout(void *_data)
{
struct osmo_bsc_sccp_con *data =
(struct osmo_bsc_sccp_con *) _data;
sccp_connection_send_it(data->sccp);
bsc_schedule_timer(&data->sccp_it_timeout, SCCP_IT_TIMER, 0);
}
static void sccp_cc_timeout(void *_data)
{
struct osmo_bsc_sccp_con *data =
(struct osmo_bsc_sccp_con *) _data;
if (data->sccp->connection_state >= SCCP_CONNECTION_STATE_ESTABLISHED)
return;
LOGP(DMSC, LOGL_ERROR, "The connection was never established.\n");
bsc_sccp_force_free(data);
}
static void msc_sccp_write_ipa(struct sccp_connection *conn, struct msgb *msg, void *data)
{
struct gsm_network *net = (struct gsm_network *) data;
msc_queue_write(net->msc_data->msc_con, msg, IPAC_PROTO_SCCP);
}
static int msc_sccp_accept(struct sccp_connection *connection, void *data)
{
LOGP(DMSC, LOGL_DEBUG, "Rejecting incoming SCCP connection.\n");
return -1;
}
static int msc_sccp_read(struct msgb *msgb, unsigned int length, void *data)
{
struct gsm_network *net = (struct gsm_network *) data;
return bsc_handle_udt(net, net->msc_data->msc_con, msgb, length);
}
int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
{
struct sccp_connection *sccp = conn->sccp;
if (sccp->connection_state > SCCP_CONNECTION_STATE_ESTABLISHED) {
LOGP(DMSC, LOGL_ERROR, "Connection closing, dropping packet on: %p\n", sccp);
msgb_free(msg);
} else if (sccp->connection_state == SCCP_CONNECTION_STATE_ESTABLISHED
&& conn->sccp_queue_size == 0) {
sccp_connection_write(sccp, msg);
msgb_free(msg);
} else if (conn->sccp_queue_size > 10) {
LOGP(DMSC, LOGL_ERROR, "Connection closing, dropping packet on: %p\n", sccp);
msgb_free(msg);
} else {
LOGP(DMSC, LOGL_DEBUG, "Queueing packet on %p. Queue size: %d\n", sccp, conn->sccp_queue_size);
conn->sccp_queue_size += 1;
msgb_enqueue(&conn->sccp_queue, msg);
}
return 0;
}
int bsc_create_new_connection(struct gsm_subscriber_connection *conn)
{
struct gsm_network *net;
struct osmo_bsc_sccp_con *bsc_con;
struct sccp_connection *sccp;
net = conn->bts->network;
if (!net->msc_data->msc_con->is_authenticated) {
LOGP(DMSC, LOGL_ERROR, "Not connected to a MSC. Not forwarding data.\n");
return -1;
}
if (!bsc_grace_allow_new_connection(net)) {
LOGP(DMSC, LOGL_NOTICE, "BSC in grace period. No new connections.\n");
return -1;
}
sccp = sccp_connection_socket();
if (!sccp) {
LOGP(DMSC, LOGL_ERROR, "Failed to allocate memory.\n");
return -ENOMEM;
}
bsc_con = talloc_zero(conn->bts, struct osmo_bsc_sccp_con);
if (!bsc_con) {
LOGP(DMSC, LOGL_ERROR, "Failed to allocate.\n");
sccp_connection_free(sccp);
return -1;
}
/* callbacks */
sccp->state_cb = msc_outgoing_sccp_state;
sccp->data_cb = msc_outgoing_sccp_data;
sccp->data_ctx = bsc_con;
/* prepare the timers */
bsc_con->sccp_it_timeout.cb = sccp_it_timeout;
bsc_con->sccp_it_timeout.data = bsc_con;
bsc_con->sccp_cc_timeout.cb = sccp_cc_timeout;
bsc_con->sccp_cc_timeout.data = bsc_con;
INIT_LLIST_HEAD(&bsc_con->sccp_queue);
bsc_con->sccp = sccp;
bsc_con->msc_con = net->msc_data->msc_con;
bsc_con->conn = conn;
llist_add(&bsc_con->entry, &active_connections);
conn->sccp_con = bsc_con;
return 0;
}
int bsc_open_connection(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
{
bsc_schedule_timer(&conn->sccp_cc_timeout, 10, 0);
sccp_connection_connect(conn->sccp, &sccp_ssn_bssap, msg);
msgb_free(msg);
return 0;
}
int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp)
{
if (!sccp)
return 0;
if (sccp->conn)
LOGP(DMSC, LOGL_ERROR, "Should have been cleared.\n");
llist_del(&sccp->entry);
bsc_del_timer(&sccp->sccp_it_timeout);
bsc_del_timer(&sccp->sccp_cc_timeout);
talloc_free(sccp);
return 0;
}
static void bsc_close_connections(struct bsc_msc_connection *msc_con)
{
struct osmo_bsc_sccp_con *con, *tmp;
llist_for_each_entry_safe(con, tmp, &active_connections, entry)
bsc_sccp_force_free(con);
}
static int handle_msc_signal(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct osmo_msc_data *data;
if (subsys != SS_MSC)
return 0;
data = (struct osmo_msc_data *) signal_data;
if (signal == S_MSC_LOST)
bsc_close_connections(data->msc_con);
return 0;
}
int osmo_bsc_sccp_init(struct gsm_network *gsmnet)
{
sccp_set_log_area(DSCCP);
sccp_system_init(msc_sccp_write_ipa, gsmnet);
sccp_connection_set_incoming(&sccp_ssn_bssap, msc_sccp_accept, NULL);
sccp_set_read(&sccp_ssn_bssap, msc_sccp_read, gsmnet);
register_signal_handler(SS_MSC, handle_msc_signal, gsmnet);
return 0;
}

View File

@@ -4,18 +4,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -25,6 +24,9 @@
#include <osmocore/talloc.h>
#define IPA_STR "IP.ACCESS specific\n"
extern struct gsm_network *bsc_gsmnet;
static struct osmo_msc_data *osmo_msc_data(struct vty *vty)
@@ -54,18 +56,45 @@ static int config_write_msc(struct vty *vty)
vty_out(vty, " msc%s", VTY_NEWLINE);
if (data->bsc_token)
vty_out(vty, " token %s%s", data->bsc_token, VTY_NEWLINE);
if (data->core_ncc != -1)
vty_out(vty, " core-mobile-network-code %d%s",
data->core_ncc, VTY_NEWLINE);
if (data->core_mcc != -1)
vty_out(vty, " core-mobile-country-code %d%s",
data->core_mcc, VTY_NEWLINE);
vty_out(vty, " ip.access rtp-base %d%s", data->rtp_base, VTY_NEWLINE);
vty_out(vty, " ip %s%s", data->msc_ip, VTY_NEWLINE);
vty_out(vty, " port %d%s", data->msc_port, VTY_NEWLINE);
vty_out(vty, " ip-dscp %d%s", data->msc_ip_dscp, VTY_NEWLINE);
vty_out(vty, " timeout-ping %d%s", data->ping_timeout, VTY_NEWLINE);
vty_out(vty, " timeout-pong %d%s", data->pong_timeout, VTY_NEWLINE);
if (data->ussd_grace_txt)
vty_out(vty, "bsc-grace-text %s%s", data->ussd_grace_txt, VTY_NEWLINE);
if (data->mid_call_txt)
vty_out(vty, "mid-call-text %s%s", data->mid_call_txt, VTY_NEWLINE);
vty_out(vty, " mid-call-timeout %d%s", data->mid_call_timeout, VTY_NEWLINE);
if (data->ussd_welcome_txt)
vty_out(vty, " bsc-welcome-text %s%s", data->ussd_welcome_txt, VTY_NEWLINE);
if (data->audio_length != 0) {
int i;
vty_out(vty, " codec_list ");
for (i = 0; i < data->audio_length; ++i) {
if (i != 0)
vty_out(vty, ", ");
if (data->audio_support[i]->hr)
vty_out(vty, "hr%.1u", data->audio_support[i]->ver);
else
vty_out(vty, "fr%.1u", data->audio_support[i]->ver);
}
vty_out(vty, "%s", VTY_NEWLINE);
}
return CMD_SUCCESS;
}
DEFUN(cfg_net_msc_token,
DEFUN(cfg_net_bsc_token,
cfg_net_bsc_token_cmd,
"token TOKEN",
"A token for the BSC to be sent to the MSC")
@@ -76,6 +105,98 @@ DEFUN(cfg_net_msc_token,
return CMD_SUCCESS;
}
DEFUN(cfg_net_bsc_ncc,
cfg_net_bsc_ncc_cmd,
"core-mobile-network-code <1-999>",
"Use this network code for the backbone\n" "NCC value\n")
{
struct osmo_msc_data *data = osmo_msc_data(vty);
data->core_ncc = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_net_bsc_mcc,
cfg_net_bsc_mcc_cmd,
"core-mobile-country-code <1-999>",
"Use this country code for the backbone\n" "MCC value\n")
{
struct osmo_msc_data *data = osmo_msc_data(vty);
data->core_mcc = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_net_bsc_rtp_base,
cfg_net_bsc_rtp_base_cmd,
"ip.access rtp-base <1-65000>",
IPA_STR
"Set the rtp-base port for the RTP stream\n"
"Port number\n")
{
struct osmo_msc_data *data = osmo_msc_data(vty);
data->rtp_base = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_net_bsc_codec_list,
cfg_net_bsc_codec_list_cmd,
"codec-list .LIST",
"Set the allowed audio codecs\n"
"List of audio codecs\n")
{
struct osmo_msc_data *data = osmo_msc_data(vty);
int saw_fr, saw_hr;
int i;
saw_fr = saw_hr = 0;
/* free the old list... if it exists */
if (data->audio_support) {
talloc_free(data->audio_support);
data->audio_support = NULL;
data->audio_length = 0;
}
/* create a new array */
data->audio_support =
talloc_zero_array(data, struct gsm_audio_support *, argc);
data->audio_length = argc;
for (i = 0; i < argc; ++i) {
/* check for hrX or frX */
if (strlen(argv[i]) != 3
|| argv[i][1] != 'r'
|| (argv[i][0] != 'h' && argv[i][0] != 'f')
|| argv[i][2] < 0x30
|| argv[i][2] > 0x39)
goto error;
data->audio_support[i] = talloc_zero(data->audio_support,
struct gsm_audio_support);
data->audio_support[i]->ver = atoi(argv[i] + 2);
if (strncmp("hr", argv[i], 2) == 0) {
data->audio_support[i]->hr = 1;
saw_hr = 1;
} else if (strncmp("fr", argv[i], 2) == 0) {
data->audio_support[i]->hr = 0;
saw_fr = 1;
}
if (saw_hr && saw_fr) {
vty_out(vty, "Can not have full-rate and half-rate codec.%s",
VTY_NEWLINE);
return CMD_ERR_INCOMPLETE;
}
}
return CMD_SUCCESS;
error:
vty_out(vty, "Codec name must be hrX or frX. Was '%s'%s",
argv[i], VTY_NEWLINE);
return CMD_ERR_INCOMPLETE;
}
DEFUN(cfg_net_msc_ip,
cfg_net_msc_ip_cmd,
"ip A.B.C.D", "Set the MSC/MUX IP address.")
@@ -127,33 +248,64 @@ DEFUN(cfg_net_msc_pong_time,
return CMD_SUCCESS;
}
DEFUN(cfg_net_msc_grace_ussd,
cfg_net_msc_grace_ussd_cmd,
"bsc-grace-text .TEXT",
DEFUN(cfg_net_msc_mid_call_text,
cfg_net_msc_mid_call_text_cmd,
"mid-call-text .TEXT",
"Set the USSD notifcation to be send.\n" "Text to be sent\n")
{
struct osmo_msc_data *data = osmo_msc_data(vty);
char *txt = argv_concat(argv, argc, 1);
char *txt = argv_concat(argv, argc, 0);
if (!txt)
return CMD_WARNING;
bsc_replace_string(data, &data->ussd_grace_txt, txt);
bsc_replace_string(data, &data->mid_call_txt, txt);
talloc_free(txt);
return CMD_SUCCESS;
}
DEFUN(cfg_net_msc_mid_call_timeout,
cfg_net_msc_mid_call_timeout_cmd,
"mid-call-timeout NR",
"Switch from Grace to Off in NR seconds.\n" "Timeout in seconds\n")
{
struct osmo_msc_data *data = osmo_msc_data(vty);
data->mid_call_timeout = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_net_msc_welcome_ussd,
cfg_net_msc_welcome_ussd_cmd,
"bsc-welcome-text .TEXT",
"Set the USSD notification to be sent.\n" "Text to be sent\n")
{
struct osmo_msc_data *data = osmo_msc_data(vty);
char *str = argv_concat(argv, argc, 0);
if (!str)
return CMD_WARNING;
bsc_replace_string(data, &data->ussd_welcome_txt, str);
talloc_free(str);
return CMD_SUCCESS;
}
int bsc_vty_init_extra(void)
{
install_element(GSMNET_NODE, &cfg_net_msc_cmd);
install_node(&msc_node, config_write_msc);
install_default(MSC_NODE);
install_element(MSC_NODE, &cfg_net_bsc_token_cmd);
install_element(MSC_NODE, &cfg_net_bsc_ncc_cmd);
install_element(MSC_NODE, &cfg_net_bsc_mcc_cmd);
install_element(MSC_NODE, &cfg_net_bsc_rtp_base_cmd);
install_element(MSC_NODE, &cfg_net_bsc_codec_list_cmd);
install_element(MSC_NODE, &cfg_net_msc_ip_cmd);
install_element(MSC_NODE, &cfg_net_msc_port_cmd);
install_element(MSC_NODE, &cfg_net_msc_prio_cmd);
install_element(MSC_NODE, &cfg_net_msc_ping_time_cmd);
install_element(MSC_NODE, &cfg_net_msc_pong_time_cmd);
install_element(MSC_NODE, &cfg_net_msc_grace_ussd_cmd);
install_element(MSC_NODE, &cfg_net_msc_mid_call_text_cmd);
install_element(MSC_NODE, &cfg_net_msc_mid_call_timeout_cmd);
install_element(MSC_NODE, &cfg_net_msc_welcome_ussd_cmd);
return 0;
}

View File

@@ -7,36 +7,202 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <openbsc/bsc_api.h>
#include <openbsc/bsc_rll.h>
#include <openbsc/gsm_data.h>
#include <openbsc/gsm_subscriber.h>
#include <openbsc/signal.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/chan_alloc.h>
#include <openbsc/handover.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_04_08.h>
#include <osmocore/protocol/gsm_08_08.h>
#include <osmocore/talloc.h>
#define GSM0808_T10_VALUE 6, 0
static LLIST_HEAD(sub_connections);
static void rll_ind_cb(struct gsm_lchan *, uint8_t, void *, enum bsc_rllr_ind);
static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id);
static void handle_release(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan);
static void handle_chan_ack(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan);
static void handle_chan_nack(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct gsm_lchan *lchan);
/* GSM 08.08 3.2.2.33 */
static u_int8_t lchan_to_chosen_channel(struct gsm_lchan *lchan)
{
u_int8_t channel_mode = 0, channel = 0;
switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_V1:
case GSM48_CMODE_SPEECH_EFR:
case GSM48_CMODE_SPEECH_AMR:
channel_mode = 0x9;
break;
case GSM48_CMODE_SIGN:
channel_mode = 0x8;
break;
case GSM48_CMODE_DATA_14k5:
channel_mode = 0xe;
break;
case GSM48_CMODE_DATA_12k0:
channel_mode = 0xb;
break;
case GSM48_CMODE_DATA_6k0:
channel_mode = 0xc;
break;
case GSM48_CMODE_DATA_3k6:
channel_mode = 0xd;
break;
}
switch (lchan->type) {
case GSM_LCHAN_NONE:
channel = 0x0;
break;
case GSM_LCHAN_SDCCH:
channel = 0x1;
break;
case GSM_LCHAN_TCH_F:
channel = 0x8;
break;
case GSM_LCHAN_TCH_H:
channel = 0x9;
break;
case GSM_LCHAN_UNKNOWN:
LOGP(DMSC, LOGL_ERROR, "Unknown lchan type: %p\n", lchan);
break;
}
return channel_mode << 4 | channel;
}
static u_int8_t chan_mode_to_speech(struct gsm_lchan *lchan)
{
int mode = 0;
switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_V1:
mode = 1;
break;
case GSM48_CMODE_SPEECH_EFR:
mode = 0x11;
break;
case GSM48_CMODE_SPEECH_AMR:
mode = 0x21;
break;
case GSM48_CMODE_SIGN:
case GSM48_CMODE_DATA_14k5:
case GSM48_CMODE_DATA_12k0:
case GSM48_CMODE_DATA_6k0:
case GSM48_CMODE_DATA_3k6:
default:
LOGP(DMSC, LOGL_ERROR, "Using non speech mode: %d\n", mode);
return 0;
break;
}
/* assume to always do AMR HR on any TCH type */
if (lchan->type == GSM_LCHAN_TCH_H ||
lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
mode |= 0x4;
return mode;
}
static void assignment_t10_timeout(void *_conn)
{
struct bsc_api *api;
struct gsm_subscriber_connection *conn =
(struct gsm_subscriber_connection *) _conn;
LOGP(DMSC, LOGL_ERROR, "Assigment T10 timeout on %p\n", conn);
/* normal release on the secondary channel */
lchan_release(conn->secondary_lchan, 0, 1);
conn->secondary_lchan = NULL;
/* inform them about the failure */
api = conn->bts->network->bsc_api;
api->assign_fail(conn, GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
}
/*
* Start a new assignment and make sure that it is completed within T10 either
* positively, negatively or by the timeout.
*
* 1.) allocate a new lchan
* 2.) copy the encryption key and other data from the
* old to the new channel.
* 3.) RSL Channel Activate this channel and wait
*
* -> Signal handler for the LCHAN
* 4.) Send GSM 04.08 assignment command to the MS
*
* -> Assignment Complete/Assignment Failure
* 5.) Release the SDCCH, continue signalling on the new link
*/
static int handle_new_assignment(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate)
{
struct gsm_lchan *new_lchan;
int chan_type;
chan_type = full_rate ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H;
new_lchan = lchan_alloc(conn->bts, chan_type, 0);
if (!new_lchan) {
LOGP(DMSC, LOGL_NOTICE, "No free channel.\n");
return -1;
}
/* copy old data to the new channel */
memcpy(&new_lchan->encr, &conn->lchan->encr, sizeof(new_lchan->encr));
new_lchan->ms_power = conn->lchan->ms_power;
new_lchan->bs_power = conn->lchan->bs_power;
/* copy new data to it */
new_lchan->tch_mode = chan_mode;
new_lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
/* handle AMR correctly */
if (chan_mode == GSM48_CMODE_SPEECH_AMR) {
new_lchan->mr_conf.ver = 1;
new_lchan->mr_conf.icmi = 1;
new_lchan->mr_conf.m5_90 = 1;
}
if (rsl_chan_activate_lchan(new_lchan, 0x1, 0, 0) < 0) {
LOGP(DHO, LOGL_ERROR, "could not activate channel\n");
lchan_free(new_lchan);
return -1;
}
/* remember that we have the channel */
conn->secondary_lchan = new_lchan;
new_lchan->conn = conn;
rsl_lchan_set_state(new_lchan, LCHAN_S_ACT_REQ);
return 0;
}
struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan)
{
@@ -57,9 +223,6 @@ struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan)
/* TODO: move subscriber put here... */
void subscr_con_free(struct gsm_subscriber_connection *conn)
{
struct gsm_lchan *lchan;
if (!conn)
return;
@@ -70,16 +233,23 @@ void subscr_con_free(struct gsm_subscriber_connection *conn)
}
if (conn->ho_lchan)
if (conn->ho_lchan) {
LOGP(DNM, LOGL_ERROR, "The ho_lchan should have been cleared.\n");
conn->ho_lchan->conn = NULL;
}
if (conn->lchan) {
LOGP(DNM, LOGL_ERROR, "The lchan should have been cleared.\n");
conn->lchan->conn = NULL;
}
if (conn->secondary_lchan) {
LOGP(DNM, LOGL_ERROR, "The secondary_lchan should have been cleared.\n");
conn->secondary_lchan->conn = NULL;
}
llist_del(&conn->entry);
lchan = conn->lchan;
talloc_free(conn);
if (lchan)
lchan->conn = NULL;
}
int bsc_api_init(struct gsm_network *network, struct bsc_api *api)
@@ -89,12 +259,28 @@ int bsc_api_init(struct gsm_network *network, struct bsc_api *api)
}
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn,
struct msgb *msg, int link_id)
struct msgb *msg, int link_id, int allow_sach)
{
uint8_t sapi = link_id & 0x7;
uint8_t sapi;
if (!conn->lchan) {
LOGP(DMSC, LOGL_ERROR,
"Called submit dtap without an lchan.\n");
msgb_free(msg);
return -1;
}
sapi = link_id & 0x7;
msg->lchan = conn->lchan;
msg->trx = msg->lchan->ts->trx;
/* If we are on a TCH and need to submit a SMS (on SAPI=3) we need to use the SACH */
if (allow_sach && sapi != 0) {
if (conn->lchan->type == GSM_LCHAN_TCH_F || conn->lchan->type == GSM_LCHAN_TCH_H)
link_id |= 0x40;
}
msg->l3h = msg->data;
if (conn->lchan->sapis[sapi] == LCHAN_SAPI_UNUSED) {
OBSC_LINKID_CB(msg) = link_id;
@@ -111,15 +297,40 @@ int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn,
/**
* Send a GSM08.08 Assignment Request. Right now this does not contain the
* audio codec type or the allowed rates for the config.
* audio codec type or the allowed rates for the config. It is assumed that
* this is for audio handling and that when we have a TCH it is capable of
* handling the audio codec. On top of that it is assumed that we are using
* AMR 5.9 when assigning a TCH/H.
*/
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_type, int audio)
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate)
{
struct bsc_api *api;
api = conn->bts->network->bsc_api;
api->assign_fail(conn, 0);
if (conn->lchan->type == GSM_LCHAN_SDCCH) {
if (handle_new_assignment(conn, chan_mode, full_rate) != 0)
goto error;
} else {
LOGP(DMSC, LOGL_NOTICE,
"Sending ChanModify for speech %d %d\n", chan_mode, full_rate);
if (chan_mode == GSM48_CMODE_SPEECH_AMR) {
conn->lchan->mr_conf.ver = 1;
conn->lchan->mr_conf.icmi = 1;
conn->lchan->mr_conf.m5_90 = 1;
}
gsm48_lchan_modify(conn->lchan, chan_mode);
}
/* we will now start the timer to complete the assignment */
conn->T10.cb = assignment_t10_timeout;
conn->T10.data = conn;
bsc_schedule_timer(&conn->T10, GSM0808_T10_VALUE);
return 0;
error:
api->assign_fail(conn, 0, NULL);
return -1;
}
int gsm0808_page(struct gsm_bts *bts, unsigned int page_group, unsigned int mi_len,
@@ -128,23 +339,124 @@ int gsm0808_page(struct gsm_bts *bts, unsigned int page_group, unsigned int mi_l
return rsl_paging_cmd(bts, page_group, mi_len, mi, chan_type);
}
/* dequeue messages to layer 4 */
int bsc_upqueue(struct gsm_network *net)
static void handle_ass_compl(struct gsm_subscriber_connection *conn,
struct msgb *msg)
{
struct gsm_mncc *mncc;
struct msgb *msg;
int work = 0;
struct gsm48_hdr *gh;
struct bsc_api *api = conn->bts->network->bsc_api;
if (net)
while ((msg = msgb_dequeue(&net->upqueue))) {
mncc = (struct gsm_mncc *)msg->data;
if (net->mncc_recv)
net->mncc_recv(net, mncc->msg_type, mncc);
work = 1; /* work done */
talloc_free(msg);
if (conn->secondary_lchan != msg->lchan) {
LOGP(DMSC, LOGL_ERROR, "Assignment Compl should occur on second lchan.\n");
return;
}
gh = msgb_l3(msg);
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
LOGP(DMSC, LOGL_ERROR, "Assignment Compl invalid: %lu\n",
msgb_l3len(msg) - sizeof(*gh));
return;
}
/* swap channels */
bsc_del_timer(&conn->T10);
lchan_release(conn->lchan, 0, 1);
conn->lchan = conn->secondary_lchan;
conn->secondary_lchan = NULL;
if (is_ipaccess_bts(conn->bts) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)
rsl_ipacc_crcx(conn->lchan);
api->assign_compl(conn, gh->data[0],
lchan_to_chosen_channel(conn->lchan),
conn->lchan->encr.alg_id,
chan_mode_to_speech(conn->lchan));
}
static void handle_ass_fail(struct gsm_subscriber_connection *conn,
struct msgb *msg)
{
struct bsc_api *api = conn->bts->network->bsc_api;
uint8_t *rr_failure;
struct gsm48_hdr *gh;
if (conn->lchan != msg->lchan) {
LOGP(DMSC, LOGL_ERROR, "Assignment failure should occur on primary lchan.\n");
return;
}
/* stop the timer and release it */
bsc_del_timer(&conn->T10);
lchan_release(conn->secondary_lchan, 0, 1);
conn->secondary_lchan = NULL;
gh = msgb_l3(msg);
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
LOGP(DMSC, LOGL_ERROR, "assignemnt failure unhandled: %lu\n",
msgb_l3len(msg) - sizeof(*gh));
rr_failure = NULL;
} else {
rr_failure = &gh->data[0];
}
api->assign_fail(conn,
GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE,
rr_failure);
}
static void dispatch_dtap(struct gsm_subscriber_connection *conn,
uint8_t link_id, struct msgb *msg)
{
struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api;
struct gsm48_hdr *gh;
uint8_t pdisc;
int rc;
if (msgb_l3len(msg) < sizeof(*gh)) {
LOGP(DMSC, LOGL_ERROR, "Message too short for a GSM48 header.\n");
return;
}
gh = msgb_l3(msg);
pdisc = gh->proto_discr & 0x0f;
switch (pdisc) {
case GSM48_PDISC_RR:
switch (gh->msg_type) {
case GSM48_MT_RR_CIPH_M_COMPL:
if (api->cipher_mode_compl)
return api->cipher_mode_compl(conn, msg,
conn->lchan->encr.alg_id);
break;
case GSM48_MT_RR_ASS_COMPL:
handle_ass_compl(conn, msg);
break;
case GSM48_MT_RR_ASS_FAIL:
handle_ass_fail(conn, msg);
break;
case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
bsc_del_timer(&conn->T10);
rc = gsm48_rx_rr_modif_ack(msg);
if (rc < 0 && api->assign_fail) {
api->assign_fail(conn,
GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE,
NULL);
} else if (rc >= 0 && api->assign_compl)
api->assign_compl(conn, 0,
lchan_to_chosen_channel(conn->lchan),
conn->lchan->encr.alg_id,
chan_mode_to_speech(conn->lchan));
return;
break;
}
break;
case GSM48_PDISC_MM:
break;
}
return work;
/* default case */
if (api->dtap)
api->dtap(conn, link_id, msg);
}
int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
@@ -155,21 +467,26 @@ int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
lchan = msg->lchan;
if (lchan->state != LCHAN_S_ACTIVE) {
LOGP(DRSL, LOGL_ERROR, "Got data in non active state. discarding.\n");
LOGP(DRSL, LOGL_INFO, "Got data in non active state(%s), "
"discarding.\n", gsm_lchans_name(lchan->state));
return -1;
}
if (lchan->conn) {
api->dtap(lchan->conn, msg);
dispatch_dtap(lchan->conn, link_id, msg);
} else {
rc = BSC_API_CONN_POL_REJECT;
lchan->conn = subscr_con_allocate(msg->lchan);
if (!lchan->conn) {
lchan_release(lchan, 0, 0);
return -1;
}
if (lchan->conn)
rc = api->compl_l3(lchan->conn, msg, 0);
rc = api->compl_l3(lchan->conn, msg, 0);
if (rc != BSC_API_CONN_POL_ACCEPT) {
lchan->conn->lchan = NULL;
subscr_con_free(lchan->conn);
lchan_release(lchan, 0, 0);
}
@@ -179,9 +496,25 @@ int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
}
int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
uint8_t *key, int len)
const uint8_t *key, int len, int include_imeisv)
{
return -1;
if (cipher > 0 && key == NULL) {
LOGP(DRSL, LOGL_ERROR, "Need to have an encrytpion key.\n");
return -1;
}
if (len > MAX_A5_KEY_LEN) {
LOGP(DRSL, LOGL_ERROR, "The key is too long: %d\n", len);
return -1;
}
conn->lchan->encr.alg_id = RSL_ENC_ALG_A5(cipher);
if (key) {
conn->lchan->encr.key_len = len;
memcpy(conn->lchan->encr.key, key, len);
}
return gsm48_send_rr_ciph_mode(conn->lchan, include_imeisv);
}
/*
@@ -190,17 +523,21 @@ int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
int gsm0808_clear(struct gsm_subscriber_connection *conn)
{
if (conn->ho_lchan)
bsc_clear_handover(conn);
bsc_clear_handover(conn, 1);
if (conn->lchan) {
if (conn->secondary_lchan)
lchan_release(conn->secondary_lchan, 0, 1);
if (conn->lchan)
lchan_release(conn->lchan, 1, 0);
conn->lchan->conn = NULL;
}
conn->lchan = NULL;
conn->secondary_lchan = NULL;
conn->ho_lchan = NULL;
conn->bts = NULL;
bsc_del_timer(&conn->T10);
return 0;
}
@@ -222,6 +559,14 @@ static void rll_ind_cb(struct gsm_lchan *lchan, uint8_t link_id, void *_data, en
{
struct msgb *msg = _data;
/*
* There seems to be a small window that the RLL timer can
* fire after a lchan_release call and before the S_CHALLOC_FREED
* is called. Check if a conn is set before proceeding.
*/
if (!lchan->conn)
return;
switch (rllr_ind) {
case BSC_RLLR_IND_EST_CONF:
rsl_data_request(msg, OBSC_LINKID_CB(msg));
@@ -240,31 +585,88 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
{
struct bsc_api *bsc;
struct gsm_lchan *lchan;
struct gsm_subscriber_connection *conn;
struct lchan_signal_data *lchan_data;
if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
if (subsys != SS_LCHAN)
return 0;
lchan = (struct gsm_lchan *)signal_data;
if (!lchan || !lchan->conn)
lchan_data = signal_data;
if (!lchan_data->lchan || !lchan_data->lchan->conn)
return 0;
lchan = lchan_data->lchan;
bsc = lchan->ts->trx->bts->network->bsc_api;
if (!bsc)
return 0;
conn = lchan->conn;
switch (signal) {
case S_LCHAN_UNEXPECTED_RELEASE:
handle_release(lchan->conn, bsc, lchan);
break;
case S_LCHAN_ACTIVATE_ACK:
handle_chan_ack(lchan->conn, bsc, lchan);
break;
case S_LCHAN_ACTIVATE_NACK:
handle_chan_nack(lchan->conn, bsc, lchan);
break;
}
return 0;
}
static void handle_release(struct gsm_subscriber_connection *conn,
struct bsc_api *bsc, struct gsm_lchan *lchan)
{
int destruct = 1;
if (conn->secondary_lchan == lchan) {
bsc_del_timer(&conn->T10);
conn->secondary_lchan = NULL;
bsc->assign_fail(conn,
GSM0808_CAUSE_RADIO_INTERFACE_FAILURE,
NULL);
}
/* clear the connection now */
if (bsc->clear_request)
bsc->clear_request(conn, 0);
destruct = bsc->clear_request(conn, 0);
/* now give up all channels */
if (conn->lchan == lchan)
conn->lchan = NULL;
if (conn->ho_lchan == lchan)
if (conn->ho_lchan == lchan) {
bsc_clear_handover(conn, 0);
conn->ho_lchan = NULL;
}
lchan->conn = NULL;
gsm0808_clear(conn);
return 0;
if (destruct)
subscr_con_free(conn);
}
static void handle_chan_ack(struct gsm_subscriber_connection *conn,
struct bsc_api *api, struct gsm_lchan *lchan)
{
if (conn->secondary_lchan != lchan)
return;
LOGP(DMSC, LOGL_NOTICE, "Sending assignment on chan: %p\n", lchan);
gsm48_send_rr_ass_cmd(conn->lchan, lchan, 0x3);
}
static void handle_chan_nack(struct gsm_subscriber_connection *conn,
struct bsc_api *api, struct gsm_lchan *lchan)
{
if (conn->secondary_lchan != lchan)
return;
LOGP(DMSC, LOGL_ERROR, "Channel activation failed. Waiting for timeout now\n");
conn->secondary_lchan->conn = NULL;
conn->secondary_lchan = NULL;
}
static __attribute__((constructor)) void on_dso_load_bsc(void)

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -38,6 +37,7 @@
#include <osmocore/talloc.h>
#include <openbsc/signal.h>
#include <openbsc/osmo_msc.h>
#include <openbsc/sms_queue.h>
#include <openbsc/vty.h>
#include "../bscconfig.h"
@@ -49,12 +49,13 @@ static const char *database_name = "hlr.sqlite3";
static const char *config_file = "openbsc.cfg";
extern const char *openbsc_copyright;
static int daemonize = 0;
static int use_mncc_sock = 0;
/* timer to store statistics */
#define DB_SYNC_INTERVAL 60, 0
static struct timer_list db_sync_timer;
extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *),
extern int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, struct msgb *),
const char *cfg_file);
extern int bsc_shutdown_net(struct gsm_network *net);
@@ -91,6 +92,7 @@ static void print_help()
printf(" -V --version. Print the version of OpenBSC.\n");
printf(" -P --rtp-proxy Enable the RTP Proxy code inside OpenBSC\n");
printf(" -e --log-level number. Set a global loglevel.\n");
printf(" -m --mncc-sock Disable built-in MNCC handler and offer socket\n");
}
static void handle_options(int argc, char **argv)
@@ -110,10 +112,11 @@ static void handle_options(int argc, char **argv)
{"version", 0, 0, 'V' },
{"rtp-proxy", 0, 0, 'P'},
{"log-level", 1, 0, 'e'},
{"mncc-sock", 0, 0, 'm'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hd:Dsl:ar:p:TPVc:e:",
c = getopt_long(argc, argv, "hd:Dsl:ar:p:TPVc:e:m",
long_options, &option_index);
if (c == -1)
break;
@@ -150,6 +153,9 @@ static void handle_options(int argc, char **argv)
case 'e':
log_set_log_level(stderr_target, atoi(optarg));
break;
case 'm':
use_mncc_sock = 1;
break;
case 'V':
print_version(1);
exit(0);
@@ -204,6 +210,8 @@ static void db_sync_timer_cb(void *data)
extern int bts_model_unknown_init(void);
extern int bts_model_bs11_init(void);
extern int bts_model_nanobts_init(void);
extern int bts_model_rbs2k_init(void);
void talloc_ctx_init(void);
extern enum node_type bsc_vty_go_parent(struct vty *vty);
@@ -232,6 +240,9 @@ int main(int argc, char **argv)
bts_model_unknown_init();
bts_model_bs11_init();
bts_model_nanobts_init();
bts_model_rbs2k_init();
e1inp_init();
/* enable filters */
log_set_all_filter(stderr_target, 1);
@@ -243,10 +254,17 @@ int main(int argc, char **argv)
/* parse options */
handle_options(argc, argv);
rc = bsc_bootstrap_network(mncc_recv, config_file);
/* internal MNCC handler or MNCC socket? */
if (use_mncc_sock) {
rc = bsc_bootstrap_network(mncc_sock_from_cc, config_file);
if (rc >= 0)
mncc_sock_init(bsc_gsmnet);
} else
rc = bsc_bootstrap_network(int_mncc_recv, config_file);
if (rc < 0)
exit(1);
bsc_api_init(bsc_gsmnet, msc_bsc_api());
mncc_sock_init(bsc_gsmnet);
/* seed the PRNG */
srand(time(NULL));
@@ -274,6 +292,10 @@ int main(int argc, char **argv)
signal(SIGUSR2, &signal_handler);
signal(SIGPIPE, SIG_IGN);
/* start the SMS queue */
if (sms_queue_start(bsc_gsmnet, 20) != 0)
return -1;
if (daemonize) {
rc = osmo_daemonize();
if (rc < 0) {
@@ -283,7 +305,6 @@ int main(int argc, char **argv)
}
while (1) {
bsc_upqueue(bsc_gsmnet);
log_reset_context();
bsc_select_main(0);
}

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -33,542 +32,30 @@
#include <openbsc/signal.h>
#include <openbsc/chan_alloc.h>
#include <osmocore/talloc.h>
#include <openbsc/ipaccess.h>
/* global pointer to the gsm network data structure */
extern struct gsm_network *bsc_gsmnet;
static void patch_nm_tables(struct gsm_bts *bts);
/* The following definitions are for OM and NM packets that we cannot yet
* generate by code but we just pass on */
// BTS Site Manager, SET ATTRIBUTES
/*
Object Class: BTS Site Manager
Instance 1: FF
Instance 2: FF
Instance 3: FF
SET ATTRIBUTES
sAbisExternalTime: 2007/09/08 14:36:11
omLAPDRelTimer: 30sec
shortLAPDIntTimer: 5sec
emergencyTimer1: 10 minutes
emergencyTimer2: 0 minutes
*/
unsigned char msg_1[] =
{
NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER, 0xFF, 0xFF, 0xFF,
NM_ATT_BS11_ABIS_EXT_TIME, 0x07,
0xD7, 0x09, 0x08, 0x0E, 0x24, 0x0B, 0xCE,
0x02,
0x00, 0x1E,
NM_ATT_BS11_SH_LAPD_INT_TIMER,
0x01, 0x05,
0x42, 0x02, 0x00, 0x0A,
0x44, 0x02, 0x00, 0x00
};
// BTS, SET BTS ATTRIBUTES
/*
Object Class: BTS
BTS relat. Number: 0
Instance 2: FF
Instance 3: FF
SET BTS ATTRIBUTES
bsIdentityCode / BSIC:
PLMN_colour_code: 7h
BS_colour_code: 7h
BTS Air Timer T3105: 4 ,unit 10 ms
btsIsHopping: FALSE
periodCCCHLoadIndication: 1sec
thresholdCCCHLoadIndication: 0%
cellAllocationNumber: 00h = GSM 900
enableInterferenceClass: 00h = Disabled
fACCHQual: 6 (FACCH stealing flags minus 1)
intaveParameter: 31 SACCH multiframes
interferenceLevelBoundaries:
Interference Boundary 1: 0Ah
Interference Boundary 2: 0Fh
Interference Boundary 3: 14h
Interference Boundary 4: 19h
Interference Boundary 5: 1Eh
mSTxPwrMax: 11
GSM range: 2=39dBm, 15=13dBm, stepsize 2 dBm
DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
30=33dBm, 31=32dBm
ny1:
Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20
powerOutputThresholds:
Out Power Fault Threshold: -10 dB
Red Out Power Threshold: - 6 dB
Excessive Out Power Threshold: 5 dB
rACHBusyThreshold: -127 dBm
rACHLoadAveragingSlots: 250 ,number of RACH burst periods
rfResourceIndicationPeriod: 125 SACCH multiframes
T200:
SDCCH: 044 in 5 ms
FACCH/Full rate: 031 in 5 ms
FACCH/Half rate: 041 in 5 ms
SACCH with TCH SAPI0: 090 in 10 ms
SACCH with SDCCH: 090 in 10 ms
SDCCH with SAPI3: 090 in 5 ms
SACCH with TCH SAPI3: 135 in 10 ms
tSync: 9000 units of 10 msec
tTrau: 9000 units of 10 msec
enableUmLoopTest: 00h = disabled
enableExcessiveDistance: 00h = Disabled
excessiveDistance: 64km
hoppingMode: 00h = baseband hopping
cellType: 00h = Standard Cell
BCCH ARFCN / bCCHFrequency: 1
*/
static unsigned char bs11_attr_bts[] =
{
NM_ATT_BSIC, HARDCODED_BSIC,
NM_ATT_BTS_AIR_TIMER, 0x04,
NM_ATT_BS11_BTSLS_HOPPING, 0x00,
NM_ATT_CCCH_L_I_P, 0x01,
NM_ATT_CCCH_L_T, 0x00,
NM_ATT_BS11_CELL_ALLOC_NR, NM_BS11_CANR_GSM,
NM_ATT_BS11_ENA_INTERF_CLASS, 0x01,
NM_ATT_BS11_FACCH_QUAL, 0x06,
/* interference avg. period in numbers of SACCH multifr */
NM_ATT_INTAVE_PARAM, 0x1F,
NM_ATT_INTERF_BOUND, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B,
NM_ATT_CCCH_L_T, 0x23,
NM_ATT_GSM_TIME, 0x28, 0x00,
NM_ATT_ADM_STATE, 0x03,
NM_ATT_RACH_B_THRESH, 0x7F,
NM_ATT_LDAVG_SLOTS, 0x00, 0xFA,
NM_ATT_BS11_RF_RES_IND_PER, 0x7D,
NM_ATT_T200, 0x2C, 0x1F, 0x29, 0x5A, 0x5A, 0x5A, 0x87,
NM_ATT_BS11_TSYNC, 0x23, 0x28,
NM_ATT_BS11_TTRAU, 0x23, 0x28,
NM_ATT_TEST_DUR, 0x01, 0x00,
NM_ATT_OUTST_ALARM, 0x01, 0x00,
NM_ATT_BS11_EXCESSIVE_DISTANCE, 0x01, 0x40,
NM_ATT_BS11_HOPPING_MODE, 0x01, 0x00,
NM_ATT_BS11_PLL, 0x01, 0x00,
NM_ATT_BCCH_ARFCN, 0x00, HARDCODED_ARFCN/*0x01*/,
};
// Handover Recognition, SET ATTRIBUTES
/*
Illegal Contents GSM Formatted O&M Msg
Object Class: Handover Recognition
BTS relat. Number: 0
Instance 2: FF
Instance 3: FF
SET ATTRIBUTES
enableDelayPowerBudgetHO: 00h = Disabled
enableDistanceHO: 00h = Disabled
enableInternalInterCellHandover: 00h = Disabled
enableInternalIntraCellHandover: 00h = Disabled
enablePowerBudgetHO: 00h = Disabled
enableRXLEVHO: 00h = Disabled
enableRXQUALHO: 00h = Disabled
hoAveragingDistance: 8 SACCH multiframes
hoAveragingLev:
A_LEV_HO: 8 SACCH multiframes
W_LEV_HO: 1 SACCH multiframes
hoAveragingPowerBudget: 16 SACCH multiframes
hoAveragingQual:
A_QUAL_HO: 8 SACCH multiframes
W_QUAL_HO: 2 SACCH multiframes
hoLowerThresholdLevDL: (10 - 110) dBm
hoLowerThresholdLevUL: (5 - 110) dBm
hoLowerThresholdQualDL: 06h = 6.4% < BER < 12.8%
hoLowerThresholdQualUL: 06h = 6.4% < BER < 12.8%
hoThresholdLevDLintra : (20 - 110) dBm
hoThresholdLevULintra: (20 - 110) dBm
hoThresholdMsRangeMax: 20 km
nCell: 06h
timerHORequest: 3 ,unit 2 SACCH multiframes
*/
unsigned char msg_3[] =
{
NM_MT_BS11_SET_ATTR, NM_OC_BS11_HANDOVER, 0x00, 0xFF, 0xFF,
0xD0, 0x00, /* enableDelayPowerBudgetHO */
0x64, 0x00, /* enableDistanceHO */
0x67, 0x00, /* enableInternalInterCellHandover */
0x68, 0x00, /* enableInternalInterCellHandover */
0x6A, 0x00, /* enablePowerBudgetHO */
0x6C, 0x00, /* enableRXLEVHO */
0x6D, 0x00, /* enableRXQUALHO */
0x6F, 0x08, /* hoAveragingDistance */
0x70, 0x08, 0x01, /* hoAveragingLev */
0x71, 0x10, 0x10, 0x10,
0x72, 0x08, 0x02, /* hoAveragingQual */
0x73, 0x0A, /* hoLowerThresholdLevDL */
0x74, 0x05, /* hoLowerThresholdLevUL */
0x75, 0x06, /* hoLowerThresholdQualDL */
0x76, 0x06, /* hoLowerThresholdQualUL */
0x78, 0x14, /* hoThresholdLevDLintra */
0x79, 0x14, /* hoThresholdLevULintra */
0x7A, 0x14, /* hoThresholdMsRangeMax */
0x7D, 0x06, /* nCell */
NM_ATT_BS11_TIMER_HO_REQUEST, 0x03,
0x20, 0x01, 0x00,
0x45, 0x01, 0x00,
0x48, 0x01, 0x00,
0x5A, 0x01, 0x00,
0x5B, 0x01, 0x05,
0x5E, 0x01, 0x1A,
0x5F, 0x01, 0x20,
0x9D, 0x01, 0x00,
0x47, 0x01, 0x00,
0x5C, 0x01, 0x64,
0x5D, 0x01, 0x1E,
0x97, 0x01, 0x20,
0xF7, 0x01, 0x3C,
};
// Power Control, SET ATTRIBUTES
/*
Object Class: Power Control
BTS relat. Number: 0
Instance 2: FF
Instance 3: FF
SET ATTRIBUTES
enableMsPowerControl: 00h = Disabled
enablePowerControlRLFW: 00h = Disabled
pcAveragingLev:
A_LEV_PC: 4 SACCH multiframes
W_LEV_PC: 1 SACCH multiframes
pcAveragingQual:
A_QUAL_PC: 4 SACCH multiframes
W_QUAL_PC: 2 SACCH multiframes
pcLowerThresholdLevDL: 0Fh
pcLowerThresholdLevUL: 0Ah
pcLowerThresholdQualDL: 05h = 3.2% < BER < 6.4%
pcLowerThresholdQualUL: 05h = 3.2% < BER < 6.4%
pcRLFThreshold: 0Ch
pcUpperThresholdLevDL: 14h
pcUpperThresholdLevUL: 0Fh
pcUpperThresholdQualDL: 04h = 1.6% < BER < 3.2%
pcUpperThresholdQualUL: 04h = 1.6% < BER < 3.2%
powerConfirm: 2 ,unit 2 SACCH multiframes
powerControlInterval: 2 ,unit 2 SACCH multiframes
powerIncrStepSize: 02h = 4 dB
powerRedStepSize: 01h = 2 dB
radioLinkTimeoutBs: 64 SACCH multiframes
enableBSPowerControl: 00h = disabled
*/
unsigned char msg_4[] =
{
NM_MT_BS11_SET_ATTR, NM_OC_BS11_PWR_CTRL, 0x00, 0xFF, 0xFF,
NM_ATT_BS11_ENA_MS_PWR_CTRL, 0x00,
NM_ATT_BS11_ENA_PWR_CTRL_RLFW, 0x00,
0x7E, 0x04, 0x01, /* pcAveragingLev */
0x7F, 0x04, 0x02, /* pcAveragingQual */
0x80, 0x0F, /* pcLowerThresholdLevDL */
0x81, 0x0A, /* pcLowerThresholdLevUL */
0x82, 0x05, /* pcLowerThresholdQualDL */
0x83, 0x05, /* pcLowerThresholdQualUL */
0x84, 0x0C, /* pcRLFThreshold */
0x85, 0x14, /* pcUpperThresholdLevDL */
0x86, 0x0F, /* pcUpperThresholdLevUL */
0x87, 0x04, /* pcUpperThresholdQualDL */
0x88, 0x04, /* pcUpperThresholdQualUL */
0x89, 0x02, /* powerConfirm */
0x8A, 0x02, /* powerConfirmInterval */
0x8B, 0x02, /* powerIncrStepSize */
0x8C, 0x01, /* powerRedStepSize */
0x8D, 0x40, /* radioLinkTimeoutBs */
0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl
};
// Transceiver, SET TRX ATTRIBUTES (TRX 0)
/*
Object Class: Transceiver
BTS relat. Number: 0
Tranceiver number: 0
Instance 3: FF
SET TRX ATTRIBUTES
aRFCNList (HEX): 0001
txPwrMaxReduction: 00h = 30dB
radioMeasGran: 254 SACCH multiframes
radioMeasRep: 01h = enabled
memberOfEmergencyConfig: 01h = TRUE
trxArea: 00h = TRX doesn't belong to a concentric cell
*/
static unsigned char bs11_attr_radio[] =
{
NM_ATT_ARFCN_LIST, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/,
NM_ATT_RF_MAXPOWR_R, 0x00,
NM_ATT_BS11_RADIO_MEAS_GRAN, 0x01, 0x05,
NM_ATT_BS11_RADIO_MEAS_REP, 0x01, 0x01,
NM_ATT_BS11_EMRG_CFG_MEMBER, 0x01, 0x01,
NM_ATT_BS11_TRX_AREA, 0x01, 0x00,
};
static unsigned char nanobts_attr_bts[] = {
NM_ATT_INTERF_BOUND, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x73,
/* interference avg. period in numbers of SACCH multifr */
NM_ATT_INTAVE_PARAM, 0x06,
/* conn fail based on SACCH error rate */
NM_ATT_CONN_FAIL_CRIT, 0x00, 0x02, 0x01, 0x10,
NM_ATT_T200, 0x1e, 0x24, 0x24, 0xa8, 0x34, 0x21, 0xa8,
NM_ATT_MAX_TA, 0x3f,
NM_ATT_OVERL_PERIOD, 0x00, 0x01, 10, /* seconds */
NM_ATT_CCCH_L_T, 10, /* percent */
NM_ATT_CCCH_L_I_P, 1, /* seconds */
NM_ATT_RACH_B_THRESH, 10, /* busy threshold in - dBm */
NM_ATT_LDAVG_SLOTS, 0x03, 0xe8, /* rach load averaging 1000 slots */
NM_ATT_BTS_AIR_TIMER, 128, /* miliseconds */
NM_ATT_NY1, 10, /* 10 retransmissions of physical config */
NM_ATT_BCCH_ARFCN, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
NM_ATT_BSIC, HARDCODED_BSIC,
NM_ATT_IPACC_CGI, 0, 7, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x00,
};
static unsigned char nanobts_attr_radio[] = {
NM_ATT_RF_MAXPOWR_R, 0x0c, /* number of -2dB reduction steps / Pn */
NM_ATT_ARFCN_LIST, 0x00, 0x02, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
};
static unsigned char nanobts_attr_nse[] = {
NM_ATT_IPACC_NSEI, 0, 2, 0x03, 0x9d, /* NSEI 925 */
NM_ATT_IPACC_NS_CFG, 0, 7, 3, /* (un)blocking timer (Tns-block) */
3, /* (un)blocking retries */
3, /* reset timer (Tns-reset) */
3, /* reset retries */
30, /* test timer (Tns-test) */
3, /* alive timer (Tns-alive) */
10, /* alive retrires */
NM_ATT_IPACC_BSSGP_CFG, 0, 11,
3, /* blockimg timer (T1) */
3, /* blocking retries */
3, /* unblocking retries */
3, /* reset timer */
3, /* reset retries */
10, /* suspend timer (T3) in 100ms */
3, /* suspend retries */
10, /* resume timer (T4) in 100ms */
3, /* resume retries */
10, /* capability update timer (T5) */
3, /* capability update retries */
};
static unsigned char nanobts_attr_cell[] = {
NM_ATT_IPACC_RAC, 0, 1, 1, /* routing area code */
NM_ATT_IPACC_GPRS_PAGING_CFG, 0, 2,
5, /* repeat time (50ms) */
3, /* repeat count */
NM_ATT_IPACC_BVCI, 0, 2, 0x03, 0x9d, /* BVCI 925 */
NM_ATT_IPACC_RLC_CFG, 0, 9,
20, /* T3142 */
5, /* T3169 */
5, /* T3191 */
200, /* T3193 */
5, /* T3195 */
10, /* N3101 */
4, /* N3103 */
8, /* N3105 */
15, /* RLC CV countdown */
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */
NM_ATT_IPACC_RLC_CFG_2, 0, 5,
0x00, 250, /* T downlink TBF extension (0..500) */
0x00, 250, /* T uplink TBF extension (0..500) */
2, /* CS2 */
#if 0
/* EDGE model only, breaks older models.
* Should inquire the BTS capabilities */
NM_ATT_IPACC_RLC_CFG_3, 0, 1,
2, /* MCS2 */
#endif
};
static unsigned char nanobts_attr_nsvc0[] = {
NM_ATT_IPACC_NSVCI, 0, 2, 0x03, 0x9d, /* 925 */
NM_ATT_IPACC_NS_LINK_CFG, 0, 8,
0x59, 0xd8, /* remote udp port (23000) */
192, 168, 100, 11, /* remote ip address */
0x59, 0xd8, /* local udp port (23000) */
};
/* Callback function to be called whenever we get a GSM 12.21 state change event */
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_inst)
{
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
struct gsm_bts_trx_ts *ts;
struct gsm_bts_gprs_nsvc *nsvc;
/* This event-driven BTS setup is currently only required on nanoBTS */
/* EVT_STATECHG_ADM is called after we call chg_adm_state() and would create
* endless loop */
if (evt != EVT_STATECHG_OPER)
return 0;
switch (obj_class) {
case NM_OC_SITE_MANAGER:
bts = container_of(obj, struct gsm_bts, site_mgr);
if ((new_state->operational == NM_OPSTATE_ENABLED &&
new_state->availability == NM_AVSTATE_OK) ||
(new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_OFF_LINE))
abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff);
break;
case NM_OC_BTS:
bts = obj;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
patch_nm_tables(bts);
abis_nm_set_bts_attr(bts, nanobts_attr_bts,
sizeof(nanobts_attr_bts));
abis_nm_chg_adm_state(bts, obj_class,
bts->bts_nr, 0xff, 0xff,
NM_STATE_UNLOCKED);
abis_nm_opstart(bts, obj_class,
bts->bts_nr, 0xff, 0xff);
}
break;
case NM_OC_CHANNEL:
ts = obj;
trx = ts->trx;
if (new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_DEPENDENCY) {
patch_nm_tables(trx->bts);
enum abis_nm_chan_comb ccomb =
abis_nm_chcomb4pchan(ts->pchan);
abis_nm_set_channel_attr(ts, ccomb);
abis_nm_chg_adm_state(trx->bts, obj_class,
trx->bts->bts_nr, trx->nr, ts->nr,
NM_STATE_UNLOCKED);
abis_nm_opstart(trx->bts, obj_class,
trx->bts->bts_nr, trx->nr, ts->nr);
}
break;
case NM_OC_RADIO_CARRIER:
trx = obj;
if (new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_OK)
abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
trx->nr, 0xff);
break;
case NM_OC_GPRS_NSE:
bts = container_of(obj, struct gsm_bts, gprs.nse);
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
0xff, 0xff, nanobts_attr_nse,
sizeof(nanobts_attr_nse));
abis_nm_opstart(bts, obj_class, bts->bts_nr,
0xff, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
0xff, 0xff, NM_STATE_UNLOCKED);
}
break;
case NM_OC_GPRS_CELL:
bts = container_of(obj, struct gsm_bts, gprs.cell);
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
0, 0xff, nanobts_attr_cell,
sizeof(nanobts_attr_cell));
abis_nm_opstart(bts, obj_class, bts->bts_nr,
0, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
0, 0xff, NM_STATE_UNLOCKED);
}
break;
case NM_OC_GPRS_NSVC:
nsvc = obj;
bts = nsvc->bts;
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
/* We skip NSVC1 since we only use NSVC0 */
if (nsvc->id == 1)
break;
if (new_state->availability == NM_AVSTATE_OFF_LINE) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff,
nanobts_attr_nsvc0,
sizeof(nanobts_attr_nsvc0));
abis_nm_opstart(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff,
NM_STATE_UNLOCKED);
}
default:
break;
}
return 0;
}
/* Callback function to be called every time we receive a 12.21 SW activated report */
static int sw_activ_rep(struct msgb *mb)
{
struct abis_om_fom_hdr *foh = msgb_l3(mb);
struct gsm_bts *bts = mb->trx->bts;
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
if (!trx)
return -EINVAL;
switch (foh->obj_class) {
case NM_OC_BASEB_TRANSC:
abis_nm_chg_adm_state(trx->bts, foh->obj_class,
trx->bts->bts_nr, trx->nr, 0xff,
NM_STATE_UNLOCKED);
abis_nm_opstart(trx->bts, foh->obj_class,
trx->bts->bts_nr, trx->nr, 0xff);
/* TRX software is active, tell it to initiate RSL Link */
abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei);
break;
case NM_OC_RADIO_CARRIER: {
/*
* Locking the radio carrier will make it go
* offline again and we would come here. The
* framework should determine that there was
* no change and avoid recursion.
*
* This code is here to make sure that on start
* a TRX remains locked.
*/
int rc_state = trx->nm_state.administrative;
/* Patch ARFCN into radio attribute */
nanobts_attr_radio[5] &= 0xf0;
nanobts_attr_radio[5] |= trx->arfcn >> 8;
nanobts_attr_radio[6] = trx->arfcn & 0xff;
abis_nm_set_radio_attr(trx, nanobts_attr_radio,
sizeof(nanobts_attr_radio));
abis_nm_chg_adm_state(trx->bts, foh->obj_class,
trx->bts->bts_nr, trx->nr, 0xff,
rc_state);
abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
trx->nr, 0xff);
break;
}
}
return 0;
}
/* Callback function for NACK on the OML NM */
static int oml_msg_nack(struct nm_nack_signal_data *nack)
{
int i;
if (nack->mt == NM_MT_SET_BTS_ATTR_NACK) {
LOGP(DNM, LOGL_FATAL, "Failed to set BTS attributes. That is fatal. "
"Was the bts type and frequency properly specified?\n");
exit(-1);
} else {
LOGP(DNM, LOGL_ERROR, "Got a NACK going to drop the OML links.\n");
for (i = 0; i < bsc_gsmnet->num_bts; ++i) {
struct gsm_bts *bts = gsm_bts_num(bsc_gsmnet, i);
if (is_ipaccess_bts(bts))
ipaccess_drop_oml(bts);
}
}
return 0;
@@ -579,11 +66,8 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct nm_nack_signal_data *nack;
u_int8_t *msg_type;
switch (signal) {
case S_NM_SW_ACTIV_REP:
return sw_activ_rep(signal_data);
case S_NM_NACK:
nack = signal_data;
return oml_msg_nack(nack);
@@ -593,190 +77,13 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal,
return 0;
}
static void bootstrap_om_nanobts(struct gsm_bts *bts)
{
/* We don't do callback based bootstrapping, but event driven (see above) */
}
static void nm_reconfig_ts(struct gsm_bts_trx_ts *ts)
{
enum abis_nm_chan_comb ccomb = abis_nm_chcomb4pchan(ts->pchan);
struct gsm_e1_subslot *e1l = &ts->e1_link;
abis_nm_set_channel_attr(ts, ccomb);
if (is_ipaccess_bts(ts->trx->bts))
return;
switch (ts->pchan) {
case GSM_PCHAN_TCH_F:
case GSM_PCHAN_TCH_H:
abis_nm_conn_terr_traf(ts, e1l->e1_nr, e1l->e1_ts,
e1l->e1_ts_ss);
break;
default:
break;
}
}
static void nm_reconfig_trx(struct gsm_bts_trx *trx)
{
struct gsm_e1_subslot *e1l = &trx->rsl_e1_link;
int i;
patch_nm_tables(trx->bts);
switch (trx->bts->type) {
case GSM_BTS_TYPE_BS11:
/* FIXME: discover this by fetching an attribute */
#if 0
trx->nominal_power = 15; /* 15dBm == 30mW PA configuration */
#else
trx->nominal_power = 24; /* 24dBm == 250mW PA configuration */
#endif
abis_nm_conn_terr_sign(trx, e1l->e1_nr, e1l->e1_ts,
e1l->e1_ts_ss);
abis_nm_establish_tei(trx->bts, trx->nr, e1l->e1_nr,
e1l->e1_ts, e1l->e1_ts_ss, trx->rsl_tei);
/* Set Radio Attributes */
if (trx == trx->bts->c0)
abis_nm_set_radio_attr(trx, bs11_attr_radio,
sizeof(bs11_attr_radio));
else {
u_int8_t trx1_attr_radio[sizeof(bs11_attr_radio)];
u_int8_t arfcn_low = trx->arfcn & 0xff;
u_int8_t arfcn_high = (trx->arfcn >> 8) & 0x0f;
memcpy(trx1_attr_radio, bs11_attr_radio,
sizeof(trx1_attr_radio));
/* patch ARFCN into TRX Attributes */
trx1_attr_radio[2] &= 0xf0;
trx1_attr_radio[2] |= arfcn_high;
trx1_attr_radio[3] = arfcn_low;
abis_nm_set_radio_attr(trx, trx1_attr_radio,
sizeof(trx1_attr_radio));
}
break;
case GSM_BTS_TYPE_NANOBTS:
switch (trx->bts->band) {
case GSM_BAND_850:
case GSM_BAND_900:
trx->nominal_power = 20;
break;
case GSM_BAND_1800:
case GSM_BAND_1900:
trx->nominal_power = 23;
break;
default:
LOGP(DNM, LOGL_ERROR, "Unsupported nanoBTS GSM band %s\n",
gsm_band_name(trx->bts->band));
break;
}
break;
default:
break;
}
for (i = 0; i < TRX_NR_TS; i++)
nm_reconfig_ts(&trx->ts[i]);
}
static void nm_reconfig_bts(struct gsm_bts *bts)
{
struct gsm_bts_trx *trx;
switch (bts->type) {
case GSM_BTS_TYPE_BS11:
patch_nm_tables(bts);
abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
abis_nm_set_bts_attr(bts, bs11_attr_bts, sizeof(bs11_attr_bts));
abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */
break;
default:
break;
}
llist_for_each_entry(trx, &bts->trx_list, list)
nm_reconfig_trx(trx);
}
static void bootstrap_om_bs11(struct gsm_bts *bts)
{
/* stop sending event reports */
abis_nm_event_reports(bts, 0);
/* begin DB transmission */
abis_nm_bs11_db_transmission(bts, 1);
/* end DB transmission */
abis_nm_bs11_db_transmission(bts, 0);
/* Reset BTS Site manager resource */
abis_nm_bs11_reset_resource(bts);
/* begin DB transmission */
abis_nm_bs11_db_transmission(bts, 1);
/* reconfigure BTS with all TRX and all TS */
nm_reconfig_bts(bts);
/* end DB transmission */
abis_nm_bs11_db_transmission(bts, 0);
/* Reset BTS Site manager resource */
abis_nm_bs11_reset_resource(bts);
/* restart sending event reports */
abis_nm_event_reports(bts, 1);
}
static void bootstrap_om(struct gsm_bts *bts)
{
LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
switch (bts->type) {
case GSM_BTS_TYPE_BS11:
bootstrap_om_bs11(bts);
break;
case GSM_BTS_TYPE_NANOBTS:
bootstrap_om_nanobts(bts);
break;
default:
LOGP(DNM, LOGL_ERROR, "Unable to bootstrap OML: Unknown BTS type %d\n", bts->type);
}
}
static int shutdown_om(struct gsm_bts *bts)
{
LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr);
/* stop sending event reports */
abis_nm_event_reports(bts, 0);
/* begin DB transmission */
abis_nm_bs11_db_transmission(bts, 1);
/* end DB transmission */
abis_nm_bs11_db_transmission(bts, 0);
/* Reset BTS Site manager resource */
abis_nm_bs11_reset_resource(bts);
return 0;
}
int bsc_shutdown_net(struct gsm_network *net)
{
struct gsm_bts *bts;
llist_for_each_entry(bts, &net->bts_list, list) {
int rc;
rc = shutdown_om(bts);
if (rc < 0)
return rc;
LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr);
dispatch_signal(SS_GLOBAL, S_GLOBAL_BTS_CLOSE_OM, bts);
}
return 0;
@@ -858,98 +165,6 @@ err_out:
return rc;
}
static void patch_16(uint8_t *data, const uint16_t val)
{
memcpy(data, &val, sizeof(val));
}
static void patch_32(uint8_t *data, const uint32_t val)
{
memcpy(data, &val, sizeof(val));
}
/*
* Patch the various SYSTEM INFORMATION tables to update
* the LAI
*/
static void patch_nm_tables(struct gsm_bts *bts)
{
u_int8_t arfcn_low = bts->c0->arfcn & 0xff;
u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
/* patch ARFCN into BTS Attributes */
bs11_attr_bts[69] &= 0xf0;
bs11_attr_bts[69] |= arfcn_high;
bs11_attr_bts[70] = arfcn_low;
nanobts_attr_bts[42] &= 0xf0;
nanobts_attr_bts[42] |= arfcn_high;
nanobts_attr_bts[43] = arfcn_low;
/* patch ARFCN into TRX Attributes */
bs11_attr_radio[2] &= 0xf0;
bs11_attr_radio[2] |= arfcn_high;
bs11_attr_radio[3] = arfcn_low;
/* patch the RACH attributes */
if (bts->rach_b_thresh != -1) {
nanobts_attr_bts[33] = bts->rach_b_thresh & 0xff;
bs11_attr_bts[33] = bts->rach_b_thresh & 0xff;
}
if (bts->rach_ldavg_slots != -1) {
u_int8_t avg_high = bts->rach_ldavg_slots & 0xff;
u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
nanobts_attr_bts[35] = avg_high;
nanobts_attr_bts[36] = avg_low;
bs11_attr_bts[35] = avg_high;
bs11_attr_bts[36] = avg_low;
}
/* patch BSIC */
bs11_attr_bts[1] = bts->bsic;
nanobts_attr_bts[sizeof(nanobts_attr_bts)-11] = bts->bsic;
/* patch CGI */
abis_nm_ipaccess_cgi(nanobts_attr_bts+sizeof(nanobts_attr_bts)-7, bts);
/* patch the power reduction */
bs11_attr_radio[5] = bts->c0->max_power_red / 2;
nanobts_attr_radio[1] = bts->c0->max_power_red / 2;
/* patch NSEI */
nanobts_attr_nse[3] = bts->gprs.nse.nsei >> 8;
nanobts_attr_nse[4] = bts->gprs.nse.nsei & 0xff;
memcpy(nanobts_attr_nse+8, bts->gprs.nse.timer,
ARRAY_SIZE(bts->gprs.nse.timer));
memcpy(nanobts_attr_nse+18, bts->gprs.cell.timer,
ARRAY_SIZE(bts->gprs.cell.timer));
/* patch NSVCI */
nanobts_attr_nsvc0[3] = bts->gprs.nsvc[0].nsvci >> 8;
nanobts_attr_nsvc0[4] = bts->gprs.nsvc[0].nsvci & 0xff;
/* patch IP address as SGSN IP */
patch_16(nanobts_attr_nsvc0 + 8,
htons(bts->gprs.nsvc[0].remote_port));
patch_32(nanobts_attr_nsvc0 + 10,
htonl(bts->gprs.nsvc[0].remote_ip));
patch_16(nanobts_attr_nsvc0 + 14,
htons(bts->gprs.nsvc[0].local_port));
/* patch BVCI */
nanobts_attr_cell[12] = bts->gprs.cell.bvci >> 8;
nanobts_attr_cell[13] = bts->gprs.cell.bvci & 0xff;
/* patch RAC */
nanobts_attr_cell[3] = bts->gprs.rac;
if (bts->gprs.mode == BTS_GPRS_EGPRS) {
/* patch EGPRS coding schemes MCS 1..9 */
nanobts_attr_cell[29] = 0x8f;
nanobts_attr_cell[30] = 0xff;
}
}
/* Produce a MA as specified in 10.5.2.21 */
static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts)
{
@@ -1023,29 +238,28 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx)
generate_ma_for_ts(&trx->ts[i]);
}
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
/* Callback function to be called every time we receive a signal from INPUT */
static int inp_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct input_signal_data *isd = signal_data;
struct gsm_bts_trx *trx = isd->trx;
int ts_no, lchan_no;
switch (event) {
case EVT_E1_TEI_UP:
switch (type) {
case E1INP_SIGN_OML:
bootstrap_om(trx->bts);
break;
case E1INP_SIGN_RSL:
bootstrap_rsl(trx);
break;
default:
break;
}
break;
case EVT_E1_TEI_DN:
LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", type, trx);
if (subsys != SS_INPUT)
return -EINVAL;
if (type == E1INP_SIGN_OML)
switch (signal) {
case S_INP_TEI_UP:
if (isd->link_type == E1INP_SIGN_RSL)
bootstrap_rsl(trx);
break;
case S_INP_TEI_DN:
LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", isd->link_type, trx);
if (isd->link_type == E1INP_SIGN_OML)
counter_inc(trx->bts->network->stats.bts.oml_fail);
else if (type == E1INP_SIGN_RSL)
else if (isd->link_type == E1INP_SIGN_RSL)
counter_inc(trx->bts->network->stats.bts.rsl_fail);
/*
@@ -1070,10 +284,14 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
trx->nm_state.availability = 0;
trx->bb_transc.nm_state.operational = 0;
trx->bb_transc.nm_state.availability = 0;
abis_nm_clear_queue(trx->bts);
break;
default:
break;
}
return 0;
}
static int bootstrap_bts(struct gsm_bts *bts)
@@ -1125,6 +343,8 @@ static int bootstrap_bts(struct gsm_bts *bts)
/* Control Channel Description */
bts->si_common.chan_desc.att = 1;
bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5;
bts->si_common.chan_desc.bs_ag_blks_res = 1;
/* T3212 is set from vty/config */
/* Set ccch config by looking at ts config */
@@ -1172,7 +392,7 @@ static int bootstrap_bts(struct gsm_bts *bts)
return 0;
}
int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, int, void *),
int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, struct msgb *),
const char *config_file)
{
struct telnet_connection dummy_conn;
@@ -1200,14 +420,17 @@ int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, int, void *),
return rc;
register_signal_handler(SS_NM, nm_sig_cb, NULL);
register_signal_handler(SS_INPUT, inp_sig_cb, NULL);
llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) {
bootstrap_bts(bts);
if (!is_ipaccess_bts(bts))
rc = e1_reconfig_bts(bts);
if (rc < 0)
if (rc < 0) {
fprintf(stderr, "Error in E1 input driver setup\n");
exit (1);
}
}
/* initialize nanoBTS support omce */

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -6,18 +6,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -3,18 +3,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -22,9 +21,9 @@
const char *openbsc_copyright =
"Copyright (C) 2008-2010 Harald Welte, Holger Freyther\r\n"
"Contributions by Daniel Willmann, Jan Lübbe,Stefan Schmidt\r\n"
"Dieter Spaar, Andreas Eversberg\r\n\r\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\r\n"
"Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\r\n"
"Dieter Spaar, Andreas Eversberg, Sylvain Munaut\r\n\r\n"
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\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";

View File

@@ -3,18 +3,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -34,6 +33,7 @@
#include <openbsc/gsm_data.h>
#include <openbsc/e1_input.h>
#include <openbsc/abis_nm.h>
#include <openbsc/abis_om2000.h>
#include <osmocore/utils.h>
#include <osmocore/gsm_utils.h>
#include <openbsc/chan_alloc.h>
@@ -44,6 +44,11 @@
#include <openbsc/gprs_ns.h>
#include <openbsc/system_information.h>
#include <openbsc/debug.h>
#include <openbsc/paging.h>
#include <openbsc/ipaccess.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/osmo_msc_data.h>
#include <openbsc/osmo_bsc_rf.h>
#include "../bscconfig.h"
@@ -74,6 +79,13 @@ static const struct value_string gprs_bssgp_cfg_strs[] = {
{ 0, NULL }
};
static const struct value_string bts_neigh_mode_strs[] = {
{ NL_MODE_AUTOMATIC, "automatic" },
{ NL_MODE_MANUAL, "manual" },
{ NL_MODE_MANUAL_SI5SEP, "manual-si5" },
{ 0, NULL }
};
struct cmd_node net_node = {
GSMNET_NODE,
"%s(network)#",
@@ -175,6 +187,12 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net)
network_chan_load(&pl, net);
vty_out(vty, " Current Channel Load:%s", VTY_NEWLINE);
dump_pchan_load_vty(vty, " ", &pl);
/* show rf */
if (net->msc_data)
vty_out(vty, " Last RF Command: %s%s",
net->msc_data->rf_ctl->last_state_command,
VTY_NEWLINE);
}
DEFUN(show_net, show_net_cmd, "show network",
@@ -241,11 +259,15 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
net_dump_nmstate(vty, &bts->site_mgr.nm_state);
vty_out(vty, " Paging: FIXME pending requests, %u free slots%s",
bts->paging.available_slots, VTY_NEWLINE);
if (!is_ipaccess_bts(bts)) {
if (is_ipaccess_bts(bts)) {
vty_out(vty, " OML Link state: %s.%s",
bts->oml_link ? "connected" : "disconnected", VTY_NEWLINE);
} else {
vty_out(vty, " E1 Signalling Link:%s", VTY_NEWLINE);
e1isl_dump_vty(vty, bts->oml_link);
}
/* FIXME: oml_link, chan_desc */
/* FIXME: chan_desc */
memset(&pl, 0, sizeof(pl));
bts_chan_load(&pl, bts);
vty_out(vty, " Current Channel Load:%s", VTY_NEWLINE);
@@ -262,7 +284,7 @@ DEFUN(show_bts, show_bts_cmd, "show bts [number]",
if (argc != 0) {
/* use the BTS number that the user has specified */
bts_nr = atoi(argv[0]);
if (bts_nr > net->num_bts) {
if (bts_nr >= net->num_bts) {
vty_out(vty, "%% can't find BTS '%s'%s", argv[0],
VTY_NEWLINE);
return CMD_WARNING;
@@ -325,8 +347,11 @@ static void config_write_ts_single(struct vty *vty, struct gsm_bts_trx_ts *ts)
vty_out(vty, " hopping arfcn add %u%s",
i, VTY_NEWLINE);
}
} else
}
config_write_e1_link(vty, &ts->e1_link, " ");
if (ts->trx->bts->model->config_write_ts)
ts->trx->bts->model->config_write_ts(vty, ts);
}
static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
@@ -346,6 +371,9 @@ static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
config_write_e1_link(vty, &trx->rsl_e1_link, " rsl ");
vty_out(vty, " rsl e1 tei %u%s", trx->rsl_tei, VTY_NEWLINE);
if (trx->bts->model->config_write_trx)
trx->bts->model->config_write_trx(vty, trx);
for (i = 0; i < TRX_NR_TS; i++)
config_write_ts_single(vty, &trx->ts[i]);
}
@@ -409,6 +437,34 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE);
vty_out(vty, " rxlev access min %u%s",
bts->si_common.cell_sel_par.rxlev_acc_min, VTY_NEWLINE);
if (bts->si_common.cell_ro_sel_par.present) {
struct gsm48_si_selection_params *sp;
sp = &bts->si_common.cell_ro_sel_par;
if (sp->cbq)
vty_out(vty, " cell bar qualify %u%s",
sp->cbq, VTY_NEWLINE);
if (sp->cell_resel_off)
vty_out(vty, " cell reselection offset %u%s",
sp->cell_resel_off*2, VTY_NEWLINE);
if (sp->temp_offs == 7)
vty_out(vty, " temporary offset infinite%s",
VTY_NEWLINE);
else if (sp->temp_offs)
vty_out(vty, " temporary offset %u%s",
sp->temp_offs*10, VTY_NEWLINE);
if (sp->penalty_time == 31)
vty_out(vty, " penalty time reserved%s",
VTY_NEWLINE);
else if (sp->penalty_time)
vty_out(vty, " penalty time %u%s",
(sp->penalty_time*20)+20, VTY_NEWLINE);
}
if (bts->si_common.chan_desc.t3212)
vty_out(vty, " periodic location update %u%s",
bts->si_common.chan_desc.t3212 * 6, VTY_NEWLINE);
@@ -454,8 +510,28 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
if (bts->paging.free_chans_need >= 0)
vty_out(vty, " paging free %d%s", bts->paging.free_chans_need, VTY_NEWLINE);
vty_out(vty, " neighbor-list mode %s%s",
get_value_string(bts_neigh_mode_strs, bts->neigh_list_manual_mode), VTY_NEWLINE);
if (bts->neigh_list_manual_mode != NL_MODE_AUTOMATIC) {
for (i = 0; i < 1024; i++) {
if (bitvec_get_bit_pos(&bts->si_common.neigh_list, i))
vty_out(vty, " neighbor-list add arfcn %u%s",
i, VTY_NEWLINE);
}
}
if (bts->neigh_list_manual_mode == NL_MODE_MANUAL_SI5SEP) {
for (i = 0; i < 1024; i++) {
if (bitvec_get_bit_pos(&bts->si_common.si5_neigh_list, i))
vty_out(vty, " si5 neighbor-list add arfcn %u%s",
i, VTY_NEWLINE);
}
}
config_write_bts_gprs(vty, bts);
if (bts->model->config_write_bts)
bts->model->config_write_bts(vty, bts);
llist_for_each_entry(trx, &bts->trx_list, list)
config_write_trx_single(vty, trx);
}
@@ -512,8 +588,11 @@ static int config_write_net(struct vty *vty)
vty_out(vty, " timer t3115 %u%s", gsmnet->T3115, VTY_NEWLINE);
vty_out(vty, " timer t3117 %u%s", gsmnet->T3117, VTY_NEWLINE);
vty_out(vty, " timer t3119 %u%s", gsmnet->T3119, VTY_NEWLINE);
vty_out(vty, " timer t3122 %u%s", gsmnet->T3122, VTY_NEWLINE);
vty_out(vty, " timer t3141 %u%s", gsmnet->T3141, VTY_NEWLINE);
vty_out(vty, " use-dtx %u%s", gsmnet->dtx_enabled, VTY_NEWLINE);
vty_out(vty, " dtx-used %u%s", gsmnet->dtx_enabled, VTY_NEWLINE);
vty_out(vty, " subscriber-keep-in-ram %d%s",
gsmnet->keep_subscr, VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -597,9 +676,13 @@ DEFUN(show_trx,
static void ts_dump_vty(struct vty *vty, struct gsm_bts_trx_ts *ts)
{
vty_out(vty, "Timeslot %u of TRX %u in BTS %u, phys cfg %s%s",
ts->nr, ts->trx->nr, ts->trx->bts->nr,
gsm_pchan_name(ts->pchan), VTY_NEWLINE);
vty_out(vty, "BTS %u, TRX %u, Timeslot %u, phys cfg %s",
ts->trx->bts->nr, ts->trx->nr, ts->nr,
gsm_pchan_name(ts->pchan));
if (ts->pchan == GSM_PCHAN_TCH_F_PDCH)
vty_out(vty, " (%s mode)",
ts->flags & TS_F_PDCH_MODE ? "PDCH" : "TCH/F");
vty_out(vty, "%s", VTY_NEWLINE);
vty_out(vty, " NM State: ");
net_dump_nmstate(vty, &ts->nm_state);
if (!is_ipaccess_bts(ts->trx->bts))
@@ -615,9 +698,9 @@ DEFUN(show_ts,
"BTS Number\n" "TRX Number\n" "Timeslot Number\n")
{
struct gsm_network *net = gsmnet_from_vty(vty);
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
struct gsm_bts_trx_ts *ts;
struct gsm_bts *bts = NULL;
struct gsm_bts_trx *trx = NULL;
struct gsm_bts_trx_ts *ts = NULL;
int bts_nr, trx_nr, ts_nr;
if (argc >= 1) {
@@ -646,12 +729,20 @@ DEFUN(show_ts,
VTY_NEWLINE);
return CMD_WARNING;
}
/* Fully Specified: print and exit */
ts = &trx->ts[ts_nr];
ts_dump_vty(vty, ts);
return CMD_SUCCESS;
}
for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
bts = gsm_bts_num(net, bts_nr);
if (bts && trx) {
/* Iterate over all TS in this TRX */
for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
ts = &trx->ts[ts_nr];
ts_dump_vty(vty, ts);
}
} else if (bts) {
/* Iterate over all TRX in this BTS, TS in each TRX */
for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
trx = gsm_bts_trx_num(bts, trx_nr);
for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
@@ -659,6 +750,18 @@ DEFUN(show_ts,
ts_dump_vty(vty, ts);
}
}
} else {
/* Iterate over all BTS, TRX in each BTS, TS in each TRX */
for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
bts = gsm_bts_num(net, bts_nr);
for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
trx = gsm_bts_trx_num(bts, trx_nr);
for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
ts = &trx->ts[ts_nr];
ts_dump_vty(vty, ts);
}
}
}
}
return CMD_SUCCESS;
@@ -720,10 +823,9 @@ static void lchan_dump_full_vty(struct vty *vty, struct gsm_lchan *lchan)
{
int idx;
vty_out(vty, "Lchan %u in Timeslot %u of TRX %u in BTS %u, Type %s%s",
lchan->nr, lchan->ts->nr, lchan->ts->trx->nr,
lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type),
VTY_NEWLINE);
vty_out(vty, "BTS %u, TRX %u, Timeslot %u, Lchan %u: Type %s%s",
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
lchan->nr, gsm_lchant_name(lchan->type), VTY_NEWLINE);
vty_out(vty, " Connection: %u, State: %s%s",
lchan->conn ? 1: 0,
gsm_lchans_name(lchan->state), VTY_NEWLINE);
@@ -762,11 +864,10 @@ static void lchan_dump_short_vty(struct vty *vty, struct gsm_lchan *lchan)
lchan->meas_rep_idx, 1);
mr = &lchan->meas_rep[idx];
vty_out(vty, "Lchan: %u Timeslot: %u TRX: %u BTS: %u Type: %s - L1 MS Power: %u dBm "
"RXL-FULL-dl: %4d dBm RXL-FULL-ul: %4d dBm%s",
lchan->nr, lchan->ts->nr, lchan->ts->trx->nr,
lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type),
mr->ms_l1.pwr,
vty_out(vty, "BTS %u, TRX %u, Timeslot %u, Lchan %u, Type %s - "
"L1 MS Power: %u dBm RXL-FULL-dl: %4d dBm RXL-FULL-ul: %4d dBm%s",
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
lchan->nr, gsm_lchant_name(lchan->type), mr->ms_l1.pwr,
rxlev2dbm(mr->dl.full.rx_lev),
rxlev2dbm(mr->ul.full.rx_lev),
VTY_NEWLINE);
@@ -1288,6 +1389,7 @@ DECLARE_TIMER(3113, "Set the time to try paging a subscriber.")
DECLARE_TIMER(3115, "Currently not used.")
DECLARE_TIMER(3117, "Currently not used.")
DECLARE_TIMER(3119, "Currently not used.")
DECLARE_TIMER(3122, "Waiting time (seconds) after IMM ASS REJECT")
DECLARE_TIMER(3141, "Currently not used.")
DEFUN(cfg_net_dtx,
@@ -1301,6 +1403,17 @@ DEFUN(cfg_net_dtx,
return CMD_SUCCESS;
}
DEFUN(cfg_net_subscr_keep,
cfg_net_subscr_keep_cmd,
"subscriber-keep-in-ram (0|1)",
"Keep unused subscribers in RAM.\n"
"Delete unused subscribers\n" "Keep unused subscribers\n")
{
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
gsmnet->keep_subscr = atoi(argv[0]);
return CMD_SUCCESS;
}
/* per-BTS configuration */
DEFUN(cfg_bts,
cfg_bts_cmd,
@@ -1644,6 +1757,80 @@ DEFUN(cfg_bts_rxlev_acc_min, cfg_bts_rxlev_acc_min_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_cell_bar_qualify, cfg_bts_cell_bar_qualify_cmd,
"cell bar qualify (0|1)",
"Cell Bar Qualify")
{
struct gsm_bts *bts = vty->index;
bts->si_common.cell_ro_sel_par.present = 1;
bts->si_common.cell_ro_sel_par.cbq = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_bts_cell_resel_ofs, cfg_bts_cell_resel_ofs_cmd,
"cell reselection offset <0-126>",
"Cell Re-Selection Offset in dB")
{
struct gsm_bts *bts = vty->index;
bts->si_common.cell_ro_sel_par.present = 1;
bts->si_common.cell_ro_sel_par.cell_resel_off = atoi(argv[0])/2;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_temp_ofs, cfg_bts_temp_ofs_cmd,
"temporary offset <0-60>",
"Cell selection temporary negative offset in dB")
{
struct gsm_bts *bts = vty->index;
bts->si_common.cell_ro_sel_par.present = 1;
bts->si_common.cell_ro_sel_par.temp_offs = atoi(argv[0])/10;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_temp_ofs_inf, cfg_bts_temp_ofs_inf_cmd,
"temporary offset infinite",
"Sets cell selection temporary negative offset to infinity")
{
struct gsm_bts *bts = vty->index;
bts->si_common.cell_ro_sel_par.present = 1;
bts->si_common.cell_ro_sel_par.temp_offs = 7;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_penalty_time, cfg_bts_penalty_time_cmd,
"penalty time <20-620>",
"Cell selection penalty time in seconds (by 20s increments)")
{
struct gsm_bts *bts = vty->index;
bts->si_common.cell_ro_sel_par.present = 1;
bts->si_common.cell_ro_sel_par.penalty_time = (atoi(argv[0])-20)/20;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_penalty_time_rsvd, cfg_bts_penalty_time_rsvd_cmd,
"penalty time reserved",
"Set cell selection penalty time to reserved value 31\n"
"(indicate that CELL_RESELECT_OFFSET is subtracted from C2 "
"and TEMPORARY_OFFSET is ignored)")
{
struct gsm_bts *bts = vty->index;
bts->si_common.cell_ro_sel_par.present = 1;
bts->si_common.cell_ro_sel_par.penalty_time = 31;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_per_loc_upd, cfg_bts_per_loc_upd_cmd,
"periodic location update <0-1530>",
"Periodic Location Updating Interval in Minutes")
@@ -1971,6 +2158,80 @@ DEFUN(cfg_bts_si_static, cfg_bts_si_static_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_neigh_mode, cfg_bts_neigh_mode_cmd,
"neighbor-list mode (automatic|manual|manual-si5)",
"Neighbor List\n" "Mode of Neighbor List generation\n"
"Automatically from all BTS in this OpenBSC\n" "Manual\n"
"Manual with different lists for SI2 and SI5\n")
{
struct gsm_bts *bts = vty->index;
int mode = get_string_value(bts_neigh_mode_strs, argv[0]);
switch (mode) {
case NL_MODE_MANUAL_SI5SEP:
case NL_MODE_MANUAL:
/* make sure we clear the current list when switching to
* manual mode */
if (bts->neigh_list_manual_mode == 0)
memset(&bts->si_common.data.neigh_list, 0,
sizeof(bts->si_common.data.neigh_list));
break;
default:
break;
}
bts->neigh_list_manual_mode = mode;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd,
"neighbor-list (add|del) arfcn <0-1024>",
"Neighbor List\n" "Add to manual neighbor list\n"
"Delete from manual neighbor list\n" "ARFCN of neighbor\n"
"ARFCN of neighbor\n")
{
struct gsm_bts *bts = vty->index;
struct bitvec *bv = &bts->si_common.neigh_list;
uint16_t arfcn = atoi(argv[1]);
if (!bts->neigh_list_manual_mode) {
vty_out(vty, "%% Cannot configure neighbor list in "
"automatic mode%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (!strcmp(argv[0], "add"))
bitvec_set_bit_pos(bv, arfcn, 1);
else
bitvec_set_bit_pos(bv, arfcn, 0);
return CMD_SUCCESS;
}
DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd,
"si5 neighbor-list (add|del) arfcn <0-1024>",
"SI5 Neighbor List\n" "Add to manual SI5 neighbor list\n"
"Delete from SI5 manual neighbor list\n" "ARFCN of neighbor\n"
"ARFCN of neighbor\n")
{
struct gsm_bts *bts = vty->index;
struct bitvec *bv = &bts->si_common.si5_neigh_list;
uint16_t arfcn = atoi(argv[1]);
if (!bts->neigh_list_manual_mode) {
vty_out(vty, "%% Cannot configure neighbor list in "
"automatic mode%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (!strcmp(argv[0], "add"))
bitvec_set_bit_pos(bv, arfcn, 1);
else
bitvec_set_bit_pos(bv, arfcn, 0);
return CMD_SUCCESS;
}
#define TRX_TEXT "Radio Transceiver\n"
@@ -2252,18 +2513,16 @@ DEFUN(logging_fltr_imsi,
LOGGING_STR FILTER_STR
"Filter log messages by IMSI\n" "IMSI to be used as filter\n")
{
struct telnet_connection *conn;
struct log_target *tgt = osmo_log_vty2tgt(vty);
conn = (struct telnet_connection *) vty->priv;
if (!conn->dbg) {
vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
if (!tgt)
return CMD_WARNING;
}
log_set_imsi_filter(conn->dbg, argv[0]);
log_set_imsi_filter(tgt, argv[0]);
return CMD_SUCCESS;
}
DEFUN(drop_bts,
drop_bts_cmd,
"drop bts connection <0-65535> (oml|rsl)",
@@ -2298,13 +2557,11 @@ DEFUN(drop_bts,
/* close all connections */
if (strcmp(argv[1], "oml") == 0) {
if (bts->oml_link)
close(bts->oml_link->ts->driver.ipaccess.fd.fd);
ipaccess_drop_oml(bts);
} else if (strcmp(argv[1], "rsl") == 0) {
/* close all rsl connections */
llist_for_each_entry(trx, &bts->trx_list, list) {
if (trx->rsl_link)
close(trx->rsl_link->ts->driver.ipaccess.fd.fd);
ipaccess_drop_rsl(trx);
}
} else {
vty_out(vty, "Argument must be 'oml# or 'rsl'.%s", VTY_NEWLINE);
@@ -2314,6 +2571,56 @@ DEFUN(drop_bts,
return CMD_SUCCESS;
}
DEFUN(pdch_act, pdch_act_cmd,
"bts <0-255> trx <0-255> timeslot <0-7> pdch (activate|deactivate)",
"BTS related commands\n" "BTS Number\n" "Transceiver\n" "Transceiver Number\n"
"TRX Timeslot\n" "Timeslot Number\n" "Packet Data Channel\n"
"Activate Dynamic PDCH/TCH (-> PDCH mode)\n"
"Deactivate Dynamic PDCH/TCH (-> TCH mode)\n")
{
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
struct gsm_bts_trx_ts *ts;
int bts_nr = atoi(argv[0]);
int trx_nr = atoi(argv[1]);
int ts_nr = atoi(argv[2]);
int activate;
bts = gsm_bts_num(bsc_gsmnet, bts_nr);
if (!bts) {
vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
if (!is_ipaccess_bts(bts)) {
vty_out(vty, "%% This command only works for ipaccess BTS%s",
VTY_NEWLINE);
return CMD_WARNING;
}
trx = gsm_bts_trx_num(bts, trx_nr);
if (!trx) {
vty_out(vty, "%% No such TRX (%d)%s", trx_nr, VTY_NEWLINE);
return CMD_WARNING;
}
ts = &trx->ts[ts_nr];
if (ts->pchan != GSM_PCHAN_TCH_F_PDCH) {
vty_out(vty, "%% Timeslot %u is not in dynamic TCH_F/PDCH "
"mode%s", ts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
if (!strcmp(argv[3], "activate"))
activate = 1;
else
activate = 0;
rsl_ipacc_pdch_activate(ts, activate);
return CMD_SUCCESS;
}
extern int bsc_vty_init_extra(void);
extern const char *openbsc_copyright;
@@ -2335,6 +2642,7 @@ int bsc_vty_init(void)
install_element_ve(&show_paging_cmd);
logging_vty_add_cmds();
install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
install_element(CONFIG_NODE, &cfg_net_cmd);
install_node(&net_node, config_write_net);
@@ -2368,8 +2676,10 @@ int bsc_vty_init(void)
install_element(GSMNET_NODE, &cfg_net_T3115_cmd);
install_element(GSMNET_NODE, &cfg_net_T3117_cmd);
install_element(GSMNET_NODE, &cfg_net_T3119_cmd);
install_element(GSMNET_NODE, &cfg_net_T3122_cmd);
install_element(GSMNET_NODE, &cfg_net_T3141_cmd);
install_element(GSMNET_NODE, &cfg_net_dtx_cmd);
install_element(GSMNET_NODE, &cfg_net_subscr_keep_cmd);
install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd);
install_element(GSMNET_NODE, &cfg_bts_cmd);
@@ -2400,6 +2710,12 @@ int bsc_vty_init(void)
install_element(BTS_NODE, &cfg_bts_per_loc_upd_cmd);
install_element(BTS_NODE, &cfg_bts_cell_resel_hyst_cmd);
install_element(BTS_NODE, &cfg_bts_rxlev_acc_min_cmd);
install_element(BTS_NODE, &cfg_bts_cell_bar_qualify_cmd);
install_element(BTS_NODE, &cfg_bts_cell_resel_ofs_cmd);
install_element(BTS_NODE, &cfg_bts_temp_ofs_cmd);
install_element(BTS_NODE, &cfg_bts_temp_ofs_inf_cmd);
install_element(BTS_NODE, &cfg_bts_penalty_time_cmd);
install_element(BTS_NODE, &cfg_bts_penalty_time_rsvd_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_mode_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_ns_timer_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_rac_cmd);
@@ -2413,6 +2729,9 @@ int bsc_vty_init(void)
install_element(BTS_NODE, &cfg_bts_pag_free_cmd);
install_element(BTS_NODE, &cfg_bts_si_mode_cmd);
install_element(BTS_NODE, &cfg_bts_si_static_cmd);
install_element(BTS_NODE, &cfg_bts_neigh_mode_cmd);
install_element(BTS_NODE, &cfg_bts_neigh_cmd);
install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd);
install_element(BTS_NODE, &cfg_trx_cmd);
install_node(&trx_node, dummy_config_write);
@@ -2442,8 +2761,11 @@ int bsc_vty_init(void)
install_element(TS_NODE, &cfg_ts_e1_subslot_cmd);
install_element(ENABLE_NODE, &drop_bts_cmd);
install_element(ENABLE_NODE, &pdch_act_cmd);
abis_nm_vty_init();
abis_om2k_vty_init();
e1inp_vty_init();
bsc_vty_init_extra();

View File

@@ -0,0 +1,164 @@
/* Ericsson RBS-2xxx specific code */
/* (C) 2011 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 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 <http://www.gnu.org/licenses/>.
*
*/
#include <sys/types.h>
#include <osmocore/tlv.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/abis_om2000.h>
#include <openbsc/e1_input.h>
#include <openbsc/signal.h>
#include "input/lapd.h"
static void bootstrap_om_bts(struct gsm_bts *bts)
{
LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
abis_om2k_tx_start_req(bts, &om2k_mo_cf);
/* FIXME */
}
static void bootstrap_om_trx(struct gsm_bts_trx *trx)
{
LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n",
trx->bts->nr, trx->nr);
/* FIXME */
}
static int shutdown_om(struct gsm_bts *bts)
{
/* FIXME */
return 0;
}
/* Tell LAPD to start start the SAP (send SABM requests) for all signalling
* timeslots in this line */
static void start_sabm_in_line(struct e1inp_line *line, int start)
{
struct e1inp_sign_link *link;
int i;
for (i = 0; i < ARRAY_SIZE(line->ts); i++) {
struct e1inp_ts *ts = &line->ts[i];
if (ts->type != E1INP_TS_TYPE_SIGN)
continue;
llist_for_each_entry(link, &ts->sign.sign_links, list) {
if (start)
lapd_sap_start(ts->driver.dahdi.lapd, link->tei, link->sapi);
else
lapd_sap_stop(ts->driver.dahdi.lapd, link->tei, link->sapi);
}
}
}
/* Callback function to be called every time we receive a signal from INPUT */
static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct gsm_bts *bts;
if (subsys != SS_GLOBAL)
return 0;
switch (signal) {
case S_GLOBAL_BTS_CLOSE_OM:
bts = signal_data;
if (bts->type == GSM_BTS_TYPE_RBS2000)
shutdown_om(signal_data);
break;
}
return 0;
}
/* Callback function to be called every time we receive a signal from INPUT */
static int inp_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct input_signal_data *isd = signal_data;
if (subsys != SS_INPUT)
return 0;
switch (signal) {
case S_INP_TEI_UP:
switch (isd->link_type) {
case E1INP_SIGN_OML:
if (isd->trx->bts->type != GSM_BTS_TYPE_RBS2000)
break;
if (isd->tei == isd->trx->bts->oml_tei)
bootstrap_om_bts(isd->trx->bts);
else
bootstrap_om_trx(isd->trx);
break;
}
break;
case S_INP_LINE_INIT:
/* Right now Ericsson RBS are only supported on DAHDI */
if (strcasecmp(isd->line->driver->name, "DAHDI"))
break;
start_sabm_in_line(isd->line, 1);
break;
case S_INP_LINE_ALARM:
if (strcasecmp(isd->line->driver->name, "DAHDI"))
break;
start_sabm_in_line(isd->line, 0);
break;
case S_INP_LINE_NOALARM:
if (strcasecmp(isd->line->driver->name, "DAHDI"))
break;
start_sabm_in_line(isd->line, 1);
break;
}
return 0;
}
static void config_write_bts(struct vty *vty, struct gsm_bts *bts)
{
abis_om2k_config_write_bts(vty, bts);
}
static struct gsm_bts_model model_rbs2k = {
.type = GSM_BTS_TYPE_RBS2000,
.name = "rbs2000",
.oml_rcvmsg = &abis_om2k_rcvmsg,
.config_write_bts = &config_write_bts,
};
int bts_model_rbs2k_init(void)
{
model_rbs2k.features.data = &model_rbs2k._features_data[0];
model_rbs2k.features.data_len = sizeof(model_rbs2k._features_data);
gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_HOPPING);
gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_HSCSD);
register_signal_handler(SS_INPUT, inp_sig_cb, NULL);
register_signal_handler(SS_GLOBAL, gbl_sig_cb, NULL);
return gsm_bts_model_register(&model_rbs2k);
}

View File

@@ -5,29 +5,33 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <sys/types.h>
#include <arpa/inet.h>
#include <osmocore/tlv.h>
#include <openbsc/gsm_data.h>
#include <osmocore/tlv.h>
#include <openbsc/signal.h>
#include <openbsc/abis_nm.h>
static struct gsm_bts_model model_nanobts = {
.type = GSM_BTS_TYPE_NANOBTS,
.name = "nanobts",
.oml_rcvmsg = &abis_nm_rcvmsg,
.nm_att_tlvdef = {
.def = {
/* ip.access specifics */
@@ -77,6 +81,358 @@ static struct gsm_bts_model model_nanobts = {
},
};
static unsigned char nanobts_attr_bts[] = {
NM_ATT_INTERF_BOUND, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x73,
/* interference avg. period in numbers of SACCH multifr */
NM_ATT_INTAVE_PARAM, 0x06,
/* conn fail based on SACCH error rate */
NM_ATT_CONN_FAIL_CRIT, 0x00, 0x02, 0x01, 0x10,
NM_ATT_T200, 0x1e, 0x24, 0x24, 0xa8, 0x34, 0x21, 0xa8,
NM_ATT_MAX_TA, 0x3f,
NM_ATT_OVERL_PERIOD, 0x00, 0x01, 10, /* seconds */
NM_ATT_CCCH_L_T, 10, /* percent */
NM_ATT_CCCH_L_I_P, 1, /* seconds */
NM_ATT_RACH_B_THRESH, 10, /* busy threshold in - dBm */
NM_ATT_LDAVG_SLOTS, 0x03, 0xe8, /* rach load averaging 1000 slots */
NM_ATT_BTS_AIR_TIMER, 128, /* miliseconds */
NM_ATT_NY1, 10, /* 10 retransmissions of physical config */
NM_ATT_BCCH_ARFCN, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
NM_ATT_BSIC, HARDCODED_BSIC,
NM_ATT_IPACC_CGI, 0, 7, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x00,
};
static unsigned char nanobts_attr_radio[] = {
NM_ATT_RF_MAXPOWR_R, 0x0c, /* number of -2dB reduction steps / Pn */
NM_ATT_ARFCN_LIST, 0x00, 0x02, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
};
static unsigned char nanobts_attr_nse[] = {
NM_ATT_IPACC_NSEI, 0, 2, 0x03, 0x9d, /* NSEI 925 */
NM_ATT_IPACC_NS_CFG, 0, 7, 3, /* (un)blocking timer (Tns-block) */
3, /* (un)blocking retries */
3, /* reset timer (Tns-reset) */
3, /* reset retries */
30, /* test timer (Tns-test) */
3, /* alive timer (Tns-alive) */
10, /* alive retrires */
NM_ATT_IPACC_BSSGP_CFG, 0, 11,
3, /* blockimg timer (T1) */
3, /* blocking retries */
3, /* unblocking retries */
3, /* reset timer */
3, /* reset retries */
10, /* suspend timer (T3) in 100ms */
3, /* suspend retries */
10, /* resume timer (T4) in 100ms */
3, /* resume retries */
10, /* capability update timer (T5) */
3, /* capability update retries */
};
static unsigned char nanobts_attr_cell[] = {
NM_ATT_IPACC_RAC, 0, 1, 1, /* routing area code */
NM_ATT_IPACC_GPRS_PAGING_CFG, 0, 2,
5, /* repeat time (50ms) */
3, /* repeat count */
NM_ATT_IPACC_BVCI, 0, 2, 0x03, 0x9d, /* BVCI 925 */
NM_ATT_IPACC_RLC_CFG, 0, 9,
20, /* T3142 */
5, /* T3169 */
5, /* T3191 */
200, /* T3193 */
5, /* T3195 */
10, /* N3101 */
4, /* N3103 */
8, /* N3105 */
15, /* RLC CV countdown */
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */
NM_ATT_IPACC_RLC_CFG_2, 0, 5,
0x00, 250, /* T downlink TBF extension (0..500) */
0x00, 250, /* T uplink TBF extension (0..500) */
2, /* CS2 */
#if 0
/* EDGE model only, breaks older models.
* Should inquire the BTS capabilities */
NM_ATT_IPACC_RLC_CFG_3, 0, 1,
2, /* MCS2 */
#endif
};
static unsigned char nanobts_attr_nsvc0[] = {
NM_ATT_IPACC_NSVCI, 0, 2, 0x03, 0x9d, /* 925 */
NM_ATT_IPACC_NS_LINK_CFG, 0, 8,
0x59, 0xd8, /* remote udp port (23000) */
192, 168, 100, 11, /* remote ip address */
0x59, 0xd8, /* local udp port (23000) */
};
static void patch_16(uint8_t *data, const uint16_t val)
{
memcpy(data, &val, sizeof(val));
}
static void patch_32(uint8_t *data, const uint32_t val)
{
memcpy(data, &val, sizeof(val));
}
/*
* Patch the various SYSTEM INFORMATION tables to update
* the LAI
*/
static void patch_nm_tables(struct gsm_bts *bts)
{
u_int8_t arfcn_low = bts->c0->arfcn & 0xff;
u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
/* patch ARFCN into BTS Attributes */
nanobts_attr_bts[42] &= 0xf0;
nanobts_attr_bts[42] |= arfcn_high;
nanobts_attr_bts[43] = arfcn_low;
/* patch the RACH attributes */
if (bts->rach_b_thresh != -1) {
nanobts_attr_bts[33] = bts->rach_b_thresh & 0xff;
}
if (bts->rach_ldavg_slots != -1) {
u_int8_t avg_high = bts->rach_ldavg_slots & 0xff;
u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
nanobts_attr_bts[35] = avg_high;
nanobts_attr_bts[36] = avg_low;
}
/* patch BSIC */
nanobts_attr_bts[sizeof(nanobts_attr_bts)-11] = bts->bsic;
/* patch CGI */
abis_nm_ipaccess_cgi(nanobts_attr_bts+sizeof(nanobts_attr_bts)-7, bts);
/* patch the power reduction */
nanobts_attr_radio[1] = bts->c0->max_power_red / 2;
/* patch NSEI */
nanobts_attr_nse[3] = bts->gprs.nse.nsei >> 8;
nanobts_attr_nse[4] = bts->gprs.nse.nsei & 0xff;
memcpy(nanobts_attr_nse+8, bts->gprs.nse.timer,
ARRAY_SIZE(bts->gprs.nse.timer));
memcpy(nanobts_attr_nse+18, bts->gprs.cell.timer,
ARRAY_SIZE(bts->gprs.cell.timer));
/* patch NSVCI */
nanobts_attr_nsvc0[3] = bts->gprs.nsvc[0].nsvci >> 8;
nanobts_attr_nsvc0[4] = bts->gprs.nsvc[0].nsvci & 0xff;
/* patch IP address as SGSN IP */
patch_16(nanobts_attr_nsvc0 + 8,
htons(bts->gprs.nsvc[0].remote_port));
patch_32(nanobts_attr_nsvc0 + 10,
htonl(bts->gprs.nsvc[0].remote_ip));
patch_16(nanobts_attr_nsvc0 + 14,
htons(bts->gprs.nsvc[0].local_port));
/* patch BVCI */
nanobts_attr_cell[12] = bts->gprs.cell.bvci >> 8;
nanobts_attr_cell[13] = bts->gprs.cell.bvci & 0xff;
/* patch RAC */
nanobts_attr_cell[3] = bts->gprs.rac;
if (bts->gprs.mode == BTS_GPRS_EGPRS) {
/* patch EGPRS coding schemes MCS 1..9 */
nanobts_attr_cell[29] = 0x8f;
nanobts_attr_cell[30] = 0xff;
}
}
/* Callback function to be called whenever we get a GSM 12.21 state change event */
static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
{
u_int8_t obj_class = nsd->obj_class;
void *obj = nsd->obj;
struct gsm_nm_state *new_state = nsd->new_state;
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
struct gsm_bts_trx_ts *ts;
struct gsm_bts_gprs_nsvc *nsvc;
/* This event-driven BTS setup is currently only required on nanoBTS */
/* S_NM_STATECHG_ADM is called after we call chg_adm_state() and would create
* endless loop */
if (evt != S_NM_STATECHG_OPER)
return 0;
switch (obj_class) {
case NM_OC_SITE_MANAGER:
bts = container_of(obj, struct gsm_bts, site_mgr);
if ((new_state->operational == NM_OPSTATE_ENABLED &&
new_state->availability == NM_AVSTATE_OK) ||
(new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_OFF_LINE))
abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff);
break;
case NM_OC_BTS:
bts = obj;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
patch_nm_tables(bts);
abis_nm_set_bts_attr(bts, nanobts_attr_bts,
sizeof(nanobts_attr_bts));
abis_nm_chg_adm_state(bts, obj_class,
bts->bts_nr, 0xff, 0xff,
NM_STATE_UNLOCKED);
abis_nm_opstart(bts, obj_class,
bts->bts_nr, 0xff, 0xff);
}
break;
case NM_OC_CHANNEL:
ts = obj;
trx = ts->trx;
if (new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_DEPENDENCY) {
patch_nm_tables(trx->bts);
enum abis_nm_chan_comb ccomb =
abis_nm_chcomb4pchan(ts->pchan);
abis_nm_set_channel_attr(ts, ccomb);
abis_nm_chg_adm_state(trx->bts, obj_class,
trx->bts->bts_nr, trx->nr, ts->nr,
NM_STATE_UNLOCKED);
abis_nm_opstart(trx->bts, obj_class,
trx->bts->bts_nr, trx->nr, ts->nr);
}
break;
case NM_OC_RADIO_CARRIER:
trx = obj;
if (new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_OK)
abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
trx->nr, 0xff);
break;
case NM_OC_GPRS_NSE:
bts = container_of(obj, struct gsm_bts, gprs.nse);
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
0xff, 0xff, nanobts_attr_nse,
sizeof(nanobts_attr_nse));
abis_nm_opstart(bts, obj_class, bts->bts_nr,
0xff, 0xff);
}
break;
case NM_OC_GPRS_CELL:
bts = container_of(obj, struct gsm_bts, gprs.cell);
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
0, 0xff, nanobts_attr_cell,
sizeof(nanobts_attr_cell));
abis_nm_opstart(bts, obj_class, bts->bts_nr,
0, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
0, 0xff, NM_STATE_UNLOCKED);
abis_nm_chg_adm_state(bts, NM_OC_GPRS_NSE, bts->bts_nr,
0xff, 0xff, NM_STATE_UNLOCKED);
}
break;
case NM_OC_GPRS_NSVC:
nsvc = obj;
bts = nsvc->bts;
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
/* We skip NSVC1 since we only use NSVC0 */
if (nsvc->id == 1)
break;
if (new_state->availability == NM_AVSTATE_OFF_LINE) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff,
nanobts_attr_nsvc0,
sizeof(nanobts_attr_nsvc0));
abis_nm_opstart(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff,
NM_STATE_UNLOCKED);
}
default:
break;
}
return 0;
}
/* Callback function to be called every time we receive a 12.21 SW activated report */
static int sw_activ_rep(struct msgb *mb)
{
struct abis_om_fom_hdr *foh = msgb_l3(mb);
struct gsm_bts *bts = mb->trx->bts;
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
if (!trx)
return -EINVAL;
if (trx->bts->type != GSM_BTS_TYPE_NANOBTS)
return 0;
switch (foh->obj_class) {
case NM_OC_BASEB_TRANSC:
abis_nm_chg_adm_state(trx->bts, foh->obj_class,
trx->bts->bts_nr, trx->nr, 0xff,
NM_STATE_UNLOCKED);
abis_nm_opstart(trx->bts, foh->obj_class,
trx->bts->bts_nr, trx->nr, 0xff);
/* TRX software is active, tell it to initiate RSL Link */
abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei);
break;
case NM_OC_RADIO_CARRIER: {
/*
* Locking the radio carrier will make it go
* offline again and we would come here. The
* framework should determine that there was
* no change and avoid recursion.
*
* This code is here to make sure that on start
* a TRX remains locked.
*/
int rc_state = trx->nm_state.administrative;
/* Patch ARFCN into radio attribute */
nanobts_attr_radio[5] &= 0xf0;
nanobts_attr_radio[5] |= trx->arfcn >> 8;
nanobts_attr_radio[6] = trx->arfcn & 0xff;
abis_nm_set_radio_attr(trx, nanobts_attr_radio,
sizeof(nanobts_attr_radio));
abis_nm_chg_adm_state(trx->bts, foh->obj_class,
trx->bts->bts_nr, trx->nr, 0xff,
rc_state);
abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
trx->nr, 0xff);
break;
}
}
return 0;
}
/* Callback function to be called every time we receive a signal from NM */
static int nm_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
if (subsys != SS_NM)
return 0;
switch (signal) {
case S_NM_SW_ACTIV_REP:
return sw_activ_rep(signal_data);
case S_NM_STATECHG_OPER:
case S_NM_STATECHG_ADM:
return nm_statechg_event(signal, signal_data);
default:
break;
}
return 0;
}
int bts_model_nanobts_init(void)
{
model_nanobts.features.data = &model_nanobts._features_data[0];
@@ -85,5 +441,7 @@ int bts_model_nanobts_init(void)
gsm_btsmodel_set_feature(&model_nanobts, BTS_FEAT_GPRS);
gsm_btsmodel_set_feature(&model_nanobts, BTS_FEAT_EGPRS);
register_signal_handler(SS_NM, nm_sig_cb, NULL);
return gsm_bts_model_register(&model_nanobts);
}

View File

@@ -5,29 +5,34 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <sys/types.h>
#include <openbsc/gsm_data.h>
#include <osmocore/tlv.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/abis_nm.h>
#include <openbsc/e1_input.h>
#include <openbsc/signal.h>
static struct gsm_bts_model model_bs11 = {
.type = GSM_BTS_TYPE_BS11,
.name = "bs11",
.oml_rcvmsg = &abis_nm_rcvmsg,
.nm_att_tlvdef = {
.def = {
[NM_ATT_AVAIL_STATUS] = { TLV_TYPE_TLV },
@@ -60,6 +65,517 @@ static struct gsm_bts_model model_bs11 = {
},
};
/* The following definitions are for OM and NM packets that we cannot yet
* generate by code but we just pass on */
// BTS Site Manager, SET ATTRIBUTES
/*
Object Class: BTS Site Manager
Instance 1: FF
Instance 2: FF
Instance 3: FF
SET ATTRIBUTES
sAbisExternalTime: 2007/09/08 14:36:11
omLAPDRelTimer: 30sec
shortLAPDIntTimer: 5sec
emergencyTimer1: 10 minutes
emergencyTimer2: 0 minutes
*/
unsigned char msg_1[] =
{
NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER, 0xFF, 0xFF, 0xFF,
NM_ATT_BS11_ABIS_EXT_TIME, 0x07,
0xD7, 0x09, 0x08, 0x0E, 0x24, 0x0B, 0xCE,
0x02,
0x00, 0x1E,
NM_ATT_BS11_SH_LAPD_INT_TIMER,
0x01, 0x05,
0x42, 0x02, 0x00, 0x0A,
0x44, 0x02, 0x00, 0x00
};
// BTS, SET BTS ATTRIBUTES
/*
Object Class: BTS
BTS relat. Number: 0
Instance 2: FF
Instance 3: FF
SET BTS ATTRIBUTES
bsIdentityCode / BSIC:
PLMN_colour_code: 7h
BS_colour_code: 7h
BTS Air Timer T3105: 4 ,unit 10 ms
btsIsHopping: FALSE
periodCCCHLoadIndication: 1sec
thresholdCCCHLoadIndication: 0%
cellAllocationNumber: 00h = GSM 900
enableInterferenceClass: 00h = Disabled
fACCHQual: 6 (FACCH stealing flags minus 1)
intaveParameter: 31 SACCH multiframes
interferenceLevelBoundaries:
Interference Boundary 1: 0Ah
Interference Boundary 2: 0Fh
Interference Boundary 3: 14h
Interference Boundary 4: 19h
Interference Boundary 5: 1Eh
mSTxPwrMax: 11
GSM range: 2=39dBm, 15=13dBm, stepsize 2 dBm
DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
30=33dBm, 31=32dBm
ny1:
Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20
powerOutputThresholds:
Out Power Fault Threshold: -10 dB
Red Out Power Threshold: - 6 dB
Excessive Out Power Threshold: 5 dB
rACHBusyThreshold: -127 dBm
rACHLoadAveragingSlots: 250 ,number of RACH burst periods
rfResourceIndicationPeriod: 125 SACCH multiframes
T200:
SDCCH: 044 in 5 ms
FACCH/Full rate: 031 in 5 ms
FACCH/Half rate: 041 in 5 ms
SACCH with TCH SAPI0: 090 in 10 ms
SACCH with SDCCH: 090 in 10 ms
SDCCH with SAPI3: 090 in 5 ms
SACCH with TCH SAPI3: 135 in 10 ms
tSync: 9000 units of 10 msec
tTrau: 9000 units of 10 msec
enableUmLoopTest: 00h = disabled
enableExcessiveDistance: 00h = Disabled
excessiveDistance: 64km
hoppingMode: 00h = baseband hopping
cellType: 00h = Standard Cell
BCCH ARFCN / bCCHFrequency: 1
*/
static unsigned char bs11_attr_bts[] =
{
NM_ATT_BSIC, HARDCODED_BSIC,
NM_ATT_BTS_AIR_TIMER, 0x04,
NM_ATT_BS11_BTSLS_HOPPING, 0x00,
NM_ATT_CCCH_L_I_P, 0x01,
NM_ATT_CCCH_L_T, 0x00,
NM_ATT_BS11_CELL_ALLOC_NR, NM_BS11_CANR_GSM,
NM_ATT_BS11_ENA_INTERF_CLASS, 0x01,
NM_ATT_BS11_FACCH_QUAL, 0x06,
/* interference avg. period in numbers of SACCH multifr */
NM_ATT_INTAVE_PARAM, 0x1F,
NM_ATT_INTERF_BOUND, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B,
NM_ATT_CCCH_L_T, 0x23,
NM_ATT_GSM_TIME, 0x28, 0x00,
NM_ATT_ADM_STATE, 0x03,
NM_ATT_RACH_B_THRESH, 0x7F,
NM_ATT_LDAVG_SLOTS, 0x00, 0xFA,
NM_ATT_BS11_RF_RES_IND_PER, 0x7D,
NM_ATT_T200, 0x2C, 0x1F, 0x29, 0x5A, 0x5A, 0x5A, 0x87,
NM_ATT_BS11_TSYNC, 0x23, 0x28,
NM_ATT_BS11_TTRAU, 0x23, 0x28,
NM_ATT_TEST_DUR, 0x01, 0x00,
NM_ATT_OUTST_ALARM, 0x01, 0x00,
NM_ATT_BS11_EXCESSIVE_DISTANCE, 0x01, 0x40,
NM_ATT_BS11_HOPPING_MODE, 0x01, 0x00,
NM_ATT_BS11_PLL, 0x01, 0x00,
NM_ATT_BCCH_ARFCN, 0x00, HARDCODED_ARFCN/*0x01*/,
};
// Handover Recognition, SET ATTRIBUTES
/*
Illegal Contents GSM Formatted O&M Msg
Object Class: Handover Recognition
BTS relat. Number: 0
Instance 2: FF
Instance 3: FF
SET ATTRIBUTES
enableDelayPowerBudgetHO: 00h = Disabled
enableDistanceHO: 00h = Disabled
enableInternalInterCellHandover: 00h = Disabled
enableInternalIntraCellHandover: 00h = Disabled
enablePowerBudgetHO: 00h = Disabled
enableRXLEVHO: 00h = Disabled
enableRXQUALHO: 00h = Disabled
hoAveragingDistance: 8 SACCH multiframes
hoAveragingLev:
A_LEV_HO: 8 SACCH multiframes
W_LEV_HO: 1 SACCH multiframes
hoAveragingPowerBudget: 16 SACCH multiframes
hoAveragingQual:
A_QUAL_HO: 8 SACCH multiframes
W_QUAL_HO: 2 SACCH multiframes
hoLowerThresholdLevDL: (10 - 110) dBm
hoLowerThresholdLevUL: (5 - 110) dBm
hoLowerThresholdQualDL: 06h = 6.4% < BER < 12.8%
hoLowerThresholdQualUL: 06h = 6.4% < BER < 12.8%
hoThresholdLevDLintra : (20 - 110) dBm
hoThresholdLevULintra: (20 - 110) dBm
hoThresholdMsRangeMax: 20 km
nCell: 06h
timerHORequest: 3 ,unit 2 SACCH multiframes
*/
unsigned char msg_3[] =
{
NM_MT_BS11_SET_ATTR, NM_OC_BS11_HANDOVER, 0x00, 0xFF, 0xFF,
0xD0, 0x00, /* enableDelayPowerBudgetHO */
0x64, 0x00, /* enableDistanceHO */
0x67, 0x00, /* enableInternalInterCellHandover */
0x68, 0x00, /* enableInternalInterCellHandover */
0x6A, 0x00, /* enablePowerBudgetHO */
0x6C, 0x00, /* enableRXLEVHO */
0x6D, 0x00, /* enableRXQUALHO */
0x6F, 0x08, /* hoAveragingDistance */
0x70, 0x08, 0x01, /* hoAveragingLev */
0x71, 0x10, 0x10, 0x10,
0x72, 0x08, 0x02, /* hoAveragingQual */
0x73, 0x0A, /* hoLowerThresholdLevDL */
0x74, 0x05, /* hoLowerThresholdLevUL */
0x75, 0x06, /* hoLowerThresholdQualDL */
0x76, 0x06, /* hoLowerThresholdQualUL */
0x78, 0x14, /* hoThresholdLevDLintra */
0x79, 0x14, /* hoThresholdLevULintra */
0x7A, 0x14, /* hoThresholdMsRangeMax */
0x7D, 0x06, /* nCell */
NM_ATT_BS11_TIMER_HO_REQUEST, 0x03,
0x20, 0x01, 0x00,
0x45, 0x01, 0x00,
0x48, 0x01, 0x00,
0x5A, 0x01, 0x00,
0x5B, 0x01, 0x05,
0x5E, 0x01, 0x1A,
0x5F, 0x01, 0x20,
0x9D, 0x01, 0x00,
0x47, 0x01, 0x00,
0x5C, 0x01, 0x64,
0x5D, 0x01, 0x1E,
0x97, 0x01, 0x20,
0xF7, 0x01, 0x3C,
};
// Power Control, SET ATTRIBUTES
/*
Object Class: Power Control
BTS relat. Number: 0
Instance 2: FF
Instance 3: FF
SET ATTRIBUTES
enableMsPowerControl: 00h = Disabled
enablePowerControlRLFW: 00h = Disabled
pcAveragingLev:
A_LEV_PC: 4 SACCH multiframes
W_LEV_PC: 1 SACCH multiframes
pcAveragingQual:
A_QUAL_PC: 4 SACCH multiframes
W_QUAL_PC: 2 SACCH multiframes
pcLowerThresholdLevDL: 0Fh
pcLowerThresholdLevUL: 0Ah
pcLowerThresholdQualDL: 05h = 3.2% < BER < 6.4%
pcLowerThresholdQualUL: 05h = 3.2% < BER < 6.4%
pcRLFThreshold: 0Ch
pcUpperThresholdLevDL: 14h
pcUpperThresholdLevUL: 0Fh
pcUpperThresholdQualDL: 04h = 1.6% < BER < 3.2%
pcUpperThresholdQualUL: 04h = 1.6% < BER < 3.2%
powerConfirm: 2 ,unit 2 SACCH multiframes
powerControlInterval: 2 ,unit 2 SACCH multiframes
powerIncrStepSize: 02h = 4 dB
powerRedStepSize: 01h = 2 dB
radioLinkTimeoutBs: 64 SACCH multiframes
enableBSPowerControl: 00h = disabled
*/
unsigned char msg_4[] =
{
NM_MT_BS11_SET_ATTR, NM_OC_BS11_PWR_CTRL, 0x00, 0xFF, 0xFF,
NM_ATT_BS11_ENA_MS_PWR_CTRL, 0x00,
NM_ATT_BS11_ENA_PWR_CTRL_RLFW, 0x00,
0x7E, 0x04, 0x01, /* pcAveragingLev */
0x7F, 0x04, 0x02, /* pcAveragingQual */
0x80, 0x0F, /* pcLowerThresholdLevDL */
0x81, 0x0A, /* pcLowerThresholdLevUL */
0x82, 0x05, /* pcLowerThresholdQualDL */
0x83, 0x05, /* pcLowerThresholdQualUL */
0x84, 0x0C, /* pcRLFThreshold */
0x85, 0x14, /* pcUpperThresholdLevDL */
0x86, 0x0F, /* pcUpperThresholdLevUL */
0x87, 0x04, /* pcUpperThresholdQualDL */
0x88, 0x04, /* pcUpperThresholdQualUL */
0x89, 0x02, /* powerConfirm */
0x8A, 0x02, /* powerConfirmInterval */
0x8B, 0x02, /* powerIncrStepSize */
0x8C, 0x01, /* powerRedStepSize */
0x8D, 0x40, /* radioLinkTimeoutBs */
0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl
};
// Transceiver, SET TRX ATTRIBUTES (TRX 0)
/*
Object Class: Transceiver
BTS relat. Number: 0
Tranceiver number: 0
Instance 3: FF
SET TRX ATTRIBUTES
aRFCNList (HEX): 0001
txPwrMaxReduction: 00h = 30dB
radioMeasGran: 254 SACCH multiframes
radioMeasRep: 01h = enabled
memberOfEmergencyConfig: 01h = TRUE
trxArea: 00h = TRX doesn't belong to a concentric cell
*/
static unsigned char bs11_attr_radio[] =
{
NM_ATT_ARFCN_LIST, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/,
NM_ATT_RF_MAXPOWR_R, 0x00,
NM_ATT_BS11_RADIO_MEAS_GRAN, 0x01, 0x05,
NM_ATT_BS11_RADIO_MEAS_REP, 0x01, 0x01,
NM_ATT_BS11_EMRG_CFG_MEMBER, 0x01, 0x01,
NM_ATT_BS11_TRX_AREA, 0x01, 0x00,
};
/*
* Patch the various SYSTEM INFORMATION tables to update
* the LAI
*/
static void patch_nm_tables(struct gsm_bts *bts)
{
u_int8_t arfcn_low = bts->c0->arfcn & 0xff;
u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
/* patch ARFCN into BTS Attributes */
bs11_attr_bts[69] &= 0xf0;
bs11_attr_bts[69] |= arfcn_high;
bs11_attr_bts[70] = arfcn_low;
/* patch ARFCN into TRX Attributes */
bs11_attr_radio[2] &= 0xf0;
bs11_attr_radio[2] |= arfcn_high;
bs11_attr_radio[3] = arfcn_low;
/* patch the RACH attributes */
if (bts->rach_b_thresh != -1)
bs11_attr_bts[33] = bts->rach_b_thresh & 0xff;
if (bts->rach_ldavg_slots != -1) {
u_int8_t avg_high = bts->rach_ldavg_slots & 0xff;
u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
bs11_attr_bts[35] = avg_high;
bs11_attr_bts[36] = avg_low;
}
/* patch BSIC */
bs11_attr_bts[1] = bts->bsic;
/* patch the power reduction */
bs11_attr_radio[5] = bts->c0->max_power_red / 2;
}
static void nm_reconfig_ts(struct gsm_bts_trx_ts *ts)
{
enum abis_nm_chan_comb ccomb = abis_nm_chcomb4pchan(ts->pchan);
struct gsm_e1_subslot *e1l = &ts->e1_link;
abis_nm_set_channel_attr(ts, ccomb);
if (is_ipaccess_bts(ts->trx->bts))
return;
switch (ts->pchan) {
case GSM_PCHAN_TCH_F:
case GSM_PCHAN_TCH_H:
abis_nm_conn_terr_traf(ts, e1l->e1_nr, e1l->e1_ts,
e1l->e1_ts_ss);
break;
default:
break;
}
}
static void nm_reconfig_trx(struct gsm_bts_trx *trx)
{
struct gsm_e1_subslot *e1l = &trx->rsl_e1_link;
int i;
patch_nm_tables(trx->bts);
switch (trx->bts->type) {
case GSM_BTS_TYPE_BS11:
/* FIXME: discover this by fetching an attribute */
#if 0
trx->nominal_power = 15; /* 15dBm == 30mW PA configuration */
#else
trx->nominal_power = 24; /* 24dBm == 250mW PA configuration */
#endif
abis_nm_conn_terr_sign(trx, e1l->e1_nr, e1l->e1_ts,
e1l->e1_ts_ss);
abis_nm_establish_tei(trx->bts, trx->nr, e1l->e1_nr,
e1l->e1_ts, e1l->e1_ts_ss, trx->rsl_tei);
/* Set Radio Attributes */
if (trx == trx->bts->c0)
abis_nm_set_radio_attr(trx, bs11_attr_radio,
sizeof(bs11_attr_radio));
else {
u_int8_t trx1_attr_radio[sizeof(bs11_attr_radio)];
u_int8_t arfcn_low = trx->arfcn & 0xff;
u_int8_t arfcn_high = (trx->arfcn >> 8) & 0x0f;
memcpy(trx1_attr_radio, bs11_attr_radio,
sizeof(trx1_attr_radio));
/* patch ARFCN into TRX Attributes */
trx1_attr_radio[2] &= 0xf0;
trx1_attr_radio[2] |= arfcn_high;
trx1_attr_radio[3] = arfcn_low;
abis_nm_set_radio_attr(trx, trx1_attr_radio,
sizeof(trx1_attr_radio));
}
break;
case GSM_BTS_TYPE_NANOBTS:
switch (trx->bts->band) {
case GSM_BAND_850:
case GSM_BAND_900:
trx->nominal_power = 20;
break;
case GSM_BAND_1800:
case GSM_BAND_1900:
trx->nominal_power = 23;
break;
default:
LOGP(DNM, LOGL_ERROR, "Unsupported nanoBTS GSM band %s\n",
gsm_band_name(trx->bts->band));
break;
}
break;
default:
break;
}
for (i = 0; i < TRX_NR_TS; i++)
nm_reconfig_ts(&trx->ts[i]);
}
static void nm_reconfig_bts(struct gsm_bts *bts)
{
struct gsm_bts_trx *trx;
switch (bts->type) {
case GSM_BTS_TYPE_BS11:
patch_nm_tables(bts);
abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
abis_nm_set_bts_attr(bts, bs11_attr_bts, sizeof(bs11_attr_bts));
abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */
break;
default:
break;
}
llist_for_each_entry(trx, &bts->trx_list, list)
nm_reconfig_trx(trx);
}
static void bootstrap_om_bs11(struct gsm_bts *bts)
{
LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
/* stop sending event reports */
abis_nm_event_reports(bts, 0);
/* begin DB transmission */
abis_nm_bs11_db_transmission(bts, 1);
/* end DB transmission */
abis_nm_bs11_db_transmission(bts, 0);
/* Reset BTS Site manager resource */
abis_nm_bs11_reset_resource(bts);
/* begin DB transmission */
abis_nm_bs11_db_transmission(bts, 1);
/* reconfigure BTS with all TRX and all TS */
nm_reconfig_bts(bts);
/* end DB transmission */
abis_nm_bs11_db_transmission(bts, 0);
/* Reset BTS Site manager resource */
abis_nm_bs11_reset_resource(bts);
/* restart sending event reports */
abis_nm_event_reports(bts, 1);
}
static int shutdown_om(struct gsm_bts *bts)
{
/* stop sending event reports */
abis_nm_event_reports(bts, 0);
/* begin DB transmission */
abis_nm_bs11_db_transmission(bts, 1);
/* end DB transmission */
abis_nm_bs11_db_transmission(bts, 0);
/* Reset BTS Site manager resource */
abis_nm_bs11_reset_resource(bts);
return 0;
}
/* Callback function to be called every time we receive a signal from INPUT */
static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct gsm_bts *bts;
if (subsys != SS_GLOBAL)
return 0;
switch (signal) {
case S_GLOBAL_BTS_CLOSE_OM:
bts = signal_data;
if (bts->type == GSM_BTS_TYPE_BS11)
shutdown_om(signal_data);
break;
}
return 0;
}
/* Callback function to be called every time we receive a signal from INPUT */
static int inp_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct input_signal_data *isd = signal_data;
if (subsys != SS_INPUT)
return 0;
switch (signal) {
case S_INP_TEI_UP:
switch (isd->link_type) {
case E1INP_SIGN_OML:
if (isd->trx->bts->type == GSM_BTS_TYPE_BS11)
bootstrap_om_bs11(isd->trx->bts);
break;
}
}
return 0;
}
int bts_model_bs11_init(void)
{
model_bs11.features.data = &model_bs11._features_data[0];
@@ -68,5 +584,8 @@ int bts_model_bs11_init(void)
gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_HOPPING);
gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_HSCSD);
register_signal_handler(SS_INPUT, inp_sig_cb, NULL);
register_signal_handler(SS_GLOBAL, gbl_sig_cb, NULL);
return gsm_bts_model_register(&model_bs11);
}

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -28,6 +27,8 @@
static struct gsm_bts_model model_unknown = {
.type = GSM_BTS_TYPE_UNKNOWN,
.name = "unknown",
.oml_rcvmsg = &abis_nm_rcvmsg,
.nm_att_tlvdef = {
.def = {
},

View File

@@ -6,18 +6,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -26,7 +25,7 @@
#include <string.h>
#include <errno.h>
#include <openbsc/gsm_data.h>
#include <openbsc/gsm_subscriber.h>
#include <openbsc/chan_alloc.h>
#include <openbsc/abis_nm.h>
#include <openbsc/abis_rsl.h>
@@ -281,13 +280,6 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type,
/* clear multi rate config */
memset(&lchan->mr_conf, 0, sizeof(lchan->mr_conf));
/* clear per MSC/BSC data */
if (lchan->conn) {
LOGP(DRLL, LOGL_ERROR, "lchan->conn should be NULL.\n");
subscr_con_free(lchan->conn);
lchan->conn = NULL;
}
} else {
struct challoc_signal_data sig;
sig.bts = bts;
@@ -309,8 +301,12 @@ void lchan_free(struct gsm_lchan *lchan)
if (lchan->conn) {
struct lchan_signal_data sig;
/* We might kill an active channel... */
dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan);
sig.lchan = lchan;
sig.mr = NULL;
dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, &sig);
}
@@ -338,7 +334,6 @@ void lchan_free(struct gsm_lchan *lchan)
if (lchan->conn) {
LOGP(DRLL, LOGL_ERROR, "the subscriber connection should be gone.\n");
subscr_con_free(lchan->conn);
lchan->conn = NULL;
}
@@ -422,6 +417,7 @@ int lchan_release(struct gsm_lchan *lchan, int sach_deact, int reason)
DEBUGP(DRLL, "%s starting release sequence\n", gsm_lchan_name(lchan));
rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ);
lchan->conn = NULL;
lchan->release_reason = reason;
lchan->sach_deact = sach_deact;
_lchan_handle_release(lchan);

View File

@@ -4,18 +4,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -68,6 +67,7 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
}
break;
case OML_NODE:
case OM2K_NODE:
vty->node = ENABLE_NODE;
talloc_free(vty->index);
vty->index = NULL;
@@ -86,6 +86,9 @@ enum node_type bsc_vty_go_parent(struct vty *vty)
case MSC_NODE:
vty->node = GSMNET_NODE;
break;
case TRUNK_NODE:
vty->node = MGCP_NODE;
break;
default:
vty->node = CONFIG_NODE;
}
@@ -146,6 +149,7 @@ gDEFUN(ournode_exit,
vty->index = NULL;
break;
case OML_NODE:
case OM2K_NODE:
vty->node = ENABLE_NODE;
talloc_free(vty->index);
vty->index = NULL;
@@ -153,6 +157,10 @@ gDEFUN(ournode_exit,
case MSC_NODE:
vty->node = GSMNET_NODE;
break;
case TRUNK_NODE:
vty->node = MGCP_NODE;
vty->index = NULL;
break;
default:
break;
}
@@ -174,6 +182,7 @@ gDEFUN(ournode_end,
case TRX_NODE:
case TS_NODE:
case MGCP_NODE:
case TRUNK_NODE:
case GBPROXY_NODE:
case SGSN_NODE:
case NS_NODE:
@@ -197,6 +206,7 @@ int bsc_vty_is_config_node(struct vty *vty, int node)
switch (node) {
/* add items that are not config */
case OML_NODE:
case OM2K_NODE:
case SUBSCR_NODE:
case CONFIG_NODE:
return 0;

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -30,10 +29,12 @@
#include <dbi/dbi.h>
#include <openbsc/gsm_data.h>
#include <openbsc/gsm_subscriber.h>
#include <openbsc/gsm_04_11.h>
#include <openbsc/db.h>
#include <osmocore/talloc.h>
#include <openbsc/debug.h>
#include <osmocore/talloc.h>
#include <osmocore/statistics.h>
#include <osmocore/rate_ctr.h>
@@ -556,13 +557,35 @@ int db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
return 0;
}
static void db_set_from_query(struct gsm_subscriber *subscr, dbi_conn result)
{
const char *string;
string = dbi_result_get_string(result, "imsi");
if (string)
strncpy(subscr->imsi, string, GSM_IMSI_LENGTH);
string = dbi_result_get_string(result, "tmsi");
if (string)
subscr->tmsi = tmsi_from_string(string);
string = dbi_result_get_string(result, "name");
if (string)
strncpy(subscr->name, string, GSM_NAME_LENGTH);
string = dbi_result_get_string(result, "extension");
if (string)
strncpy(subscr->extension, string, GSM_EXTENSION_LENGTH);
subscr->lac = dbi_result_get_uint(result, "lac");
subscr->authorized = dbi_result_get_uint(result, "authorized");
}
#define BASE_QUERY "SELECT * FROM Subscriber "
struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
enum gsm_subscriber_field field,
const char *id)
{
dbi_result result;
const char *string;
char *quoted;
struct gsm_subscriber *subscr;
@@ -619,24 +642,8 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
subscr = subscr_alloc();
subscr->net = net;
subscr->id = dbi_result_get_ulonglong(result, "id");
string = dbi_result_get_string(result, "imsi");
if (string)
strncpy(subscr->imsi, string, GSM_IMSI_LENGTH);
string = dbi_result_get_string(result, "tmsi");
if (string)
subscr->tmsi = tmsi_from_string(string);
string = dbi_result_get_string(result, "name");
if (string)
strncpy(subscr->name, string, GSM_NAME_LENGTH);
string = dbi_result_get_string(result, "extension");
if (string)
strncpy(subscr->extension, string, GSM_EXTENSION_LENGTH);
subscr->lac = dbi_result_get_uint(result, "lac");
subscr->authorized = dbi_result_get_uint(result, "authorized");
db_set_from_query(subscr, result);
DEBUGP(DDB, "Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %u, EXTEN '%s', LAC %hu, AUTH %u\n",
subscr->id, subscr->imsi, subscr->name, subscr->tmsi, subscr->extension,
subscr->lac, subscr->authorized);
@@ -647,12 +654,46 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
return subscr;
}
int db_subscriber_update(struct gsm_subscriber *subscr)
{
char buf[32];
dbi_result result;
/* Copy the id to a string as queryf with %llu is failing */
sprintf(buf, "%llu", subscr->id);
result = dbi_conn_queryf(conn,
BASE_QUERY
"WHERE id = %s", buf);
if (!result) {
LOGP(DDB, LOGL_ERROR, "Failed to query Subscriber: %llu\n", subscr->id);
return -EIO;
}
if (!dbi_result_next_row(result)) {
DEBUGP(DDB, "Failed to find the Subscriber. %llu\n",
subscr->id);
dbi_result_free(result);
return -EIO;
}
db_set_from_query(subscr, result);
dbi_result_free(result);
get_equipment_by_subscr(subscr);
return 0;
}
int db_sync_subscriber(struct gsm_subscriber *subscriber)
{
dbi_result result;
char tmsi[14];
char *q_tmsi;
char *q_tmsi, *q_name, *q_extension;
dbi_conn_quote_string_copy(conn,
subscriber->name, &q_name);
dbi_conn_quote_string_copy(conn,
subscriber->extension, &q_extension);
if (subscriber->tmsi != GSM_RESERVED_TMSI) {
sprintf(tmsi, "%u", subscriber->tmsi);
dbi_conn_quote_string_copy(conn,
@@ -664,20 +705,22 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber)
result = dbi_conn_queryf(conn,
"UPDATE Subscriber "
"SET updated = datetime('now'), "
"name = '%s', "
"extension = '%s', "
"name = %s, "
"extension = %s, "
"authorized = %i, "
"tmsi = %s, "
"lac = %i "
"WHERE imsi = %s ",
subscriber->name,
subscriber->extension,
q_name,
q_extension,
subscriber->authorized,
q_tmsi,
subscriber->lac,
subscriber->imsi);
free(q_tmsi);
free(q_name);
free(q_extension);
if (!result) {
LOGP(DDB, LOGL_ERROR, "Failed to update Subscriber (by IMSI).\n");
@@ -693,6 +736,7 @@ int db_sync_equipment(struct gsm_equipment *equip)
{
dbi_result result;
unsigned char *cm2, *cm3;
char *q_imei;
u_int8_t classmark1;
memcpy(&classmark1, &equip->classmark1, sizeof(classmark1));
@@ -710,6 +754,7 @@ int db_sync_equipment(struct gsm_equipment *equip)
equip->classmark2_len, &cm2);
dbi_conn_quote_binary_copy(conn, equip->classmark3,
equip->classmark3_len, &cm3);
dbi_conn_quote_string_copy(conn, equip->imei, &q_imei);
result = dbi_conn_queryf(conn,
"UPDATE Equipment SET "
@@ -717,11 +762,12 @@ int db_sync_equipment(struct gsm_equipment *equip)
"classmark1 = %u, "
"classmark2 = %s, "
"classmark3 = %s "
"WHERE imei = '%s' ",
classmark1, cm2, cm3, equip->imei);
"WHERE imei = %s ",
classmark1, cm2, cm3, q_imei);
free(cm2);
free(cm3);
free(q_imei);
if (!result) {
LOGP(DDB, LOGL_ERROR, "Failed to update Equipment\n");
@@ -1025,6 +1071,28 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul
return sms;
}
struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id)
{
dbi_result result;
struct gsm_sms *sms;
result = dbi_conn_queryf(conn,
"SELECT * FROM SMS WHERE SMS.id = %llu", id);
if (!result)
return NULL;
if (!dbi_result_next_row(result)) {
dbi_result_free(result);
return NULL;
}
sms = sms_from_result(net, result);
dbi_result_free(result);
return sms;
}
/* retrieve the next unsent SMS with ID >= min_id */
struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id)
{
@@ -1054,7 +1122,9 @@ struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long mi
return sms;
}
struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id)
struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net,
unsigned long long min_subscr_id,
unsigned int failed)
{
dbi_result result;
struct gsm_sms *sms;
@@ -1064,9 +1134,9 @@ struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned lo
"FROM SMS JOIN Subscriber ON "
"SMS.receiver_id = Subscriber.id "
"WHERE SMS.receiver_id >= %llu AND SMS.sent IS NULL "
"AND Subscriber.lac > 0 "
"AND Subscriber.lac > 0 AND SMS.deliver_attempts < %u "
"ORDER BY SMS.receiver_id, SMS.id LIMIT 1",
min_subscr_id);
min_subscr_id, failed);
if (!result)
return NULL;

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

View File

@@ -1,3 +1,23 @@
/* OpenBSC E1 Input code */
/* (C) 2008-2010 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 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 <http://www.gnu.org/licenses/>.
*
*/
#include <string.h>
#include <errno.h>
@@ -28,12 +48,19 @@ int e1_reconfig_ts(struct gsm_bts_trx_ts *ts)
DEBUGP(DMI, "e1_reconfig_ts(%u,%u,%u)\n", ts->trx->bts->nr, ts->trx->nr, ts->nr);
if (!e1_link->e1_ts)
if (!e1_link->e1_ts) {
LOGP(DINP, LOGL_ERROR, "TS (%u/%u/%u) without E1 timeslot?\n",
ts->nr, ts->trx->nr, ts->trx->bts->nr);
return 0;
}
line = e1inp_line_get_create(e1_link->e1_nr);
if (!line)
line = e1inp_line_get(e1_link->e1_nr);
if (!line) {
LOGP(DINP, LOGL_ERROR, "TS (%u/%u/%u) referring to "
"non-existing E1 line %u\n", ts->nr, ts->trx->nr,
ts->trx->bts->nr, e1_link->e1_nr);
return -ENOMEM;
}
switch (ts->pchan) {
case GSM_PCHAN_TCH_F:
@@ -57,19 +84,43 @@ int e1_reconfig_trx(struct gsm_bts_trx *trx)
struct e1inp_sign_link *rsl_link;
int i;
if (!e1_link->e1_ts)
if (!e1_link->e1_ts) {
LOGP(DINP, LOGL_ERROR, "TRX (%u/%u) RSL link without "
"timeslot?\n", trx->bts->nr, trx->nr);
return -EINVAL;
}
/* RSL Link */
line = e1inp_line_get_create(e1_link->e1_nr);
if (!line)
line = e1inp_line_get(e1_link->e1_nr);
if (!line) {
LOGP(DINP, LOGL_ERROR, "TRX (%u/%u) RSL link referring "
"to non-existing E1 line %u\n", trx->bts->nr,
trx->nr, e1_link->e1_nr);
return -ENOMEM;
}
sign_ts = &line->ts[e1_link->e1_ts-1];
e1inp_ts_config(sign_ts, line, E1INP_TS_TYPE_SIGN);
/* Ericsson RBS have a per-TRX OML link in parallel to RSL */
if (trx->bts->type == GSM_BTS_TYPE_RBS2000) {
struct e1inp_sign_link *oml_link;
oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML, trx,
trx->rsl_tei, SAPI_OML);
if (!oml_link) {
LOGP(DINP, LOGL_ERROR, "TRX (%u/%u) OML link creation "
"failed\n", trx->bts->nr, trx->nr);
return -ENOMEM;
}
if (trx->oml_link)
e1inp_sign_link_destroy(trx->oml_link);
trx->oml_link = oml_link;
}
rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
trx, trx->rsl_tei, SAPI_RSL);
if (!rsl_link)
if (!rsl_link) {
LOGP(DINP, LOGL_ERROR, "TRX (%u/%u) RSL link creation "
"failed\n", trx->bts->nr, trx->nr);
return -ENOMEM;
}
if (trx->rsl_link)
e1inp_sign_link_destroy(trx->rsl_link);
trx->rsl_link = rsl_link;
@@ -90,19 +141,28 @@ int e1_reconfig_bts(struct gsm_bts *bts)
DEBUGP(DMI, "e1_reconfig_bts(%u)\n", bts->nr);
if (!e1_link->e1_ts)
if (!e1_link->e1_ts) {
LOGP(DINP, LOGL_ERROR, "BTS %u OML link without timeslot?\n",
bts->nr);
return -EINVAL;
}
/* OML link */
line = e1inp_line_get_create(e1_link->e1_nr);
if (!line)
line = e1inp_line_get(e1_link->e1_nr);
if (!line) {
LOGP(DINP, LOGL_ERROR, "BTS %u OML link referring to "
"non-existing E1 line %u\n", bts->nr, e1_link->e1_nr);
return -ENOMEM;
}
sign_ts = &line->ts[e1_link->e1_ts-1];
e1inp_ts_config(sign_ts, line, E1INP_TS_TYPE_SIGN);
oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
bts->c0, bts->oml_tei, SAPI_OML);
if (!oml_link)
if (!oml_link) {
LOGP(DINP, LOGL_ERROR, "BTS %u OML link creation failed\n",
bts->nr);
return -ENOMEM;
}
if (bts->oml_link)
e1inp_sign_link_destroy(bts->oml_link);
bts->oml_link = oml_link;

View File

@@ -5,18 +5,17 @@
* 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
* 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.
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -55,6 +54,8 @@
#include <openbsc/signal.h>
#include <openbsc/misdn.h>
#include "../bscconfig.h"
#define NUM_E1_TS 32
/* list of all E1 drivers */
@@ -65,9 +66,6 @@ LLIST_HEAD(e1inp_line_list);
static void *tall_sigl_ctx;
/* to be implemented, e.g. by bsc_hack.c */
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx);
/*
* pcap writing of the misdn load
* pcap format is from http://wiki.wireshark.org/Development/LibpcapFileFormat
@@ -110,11 +108,11 @@ struct lapd_header {
u_int8_t control_foo; /* fake UM's ... */
} __attribute__((packed));
static_assert((int)&((struct fake_linux_lapd_header*)NULL)->hatype == 2, hatype_offset);
static_assert((int)&((struct fake_linux_lapd_header*)NULL)->halen == 4, halen_offset);
static_assert((int)&((struct fake_linux_lapd_header*)NULL)->addr == 6, addr_offset);
static_assert((int)&((struct fake_linux_lapd_header*)NULL)->protocol == 14, proto_offset);
static_assert(sizeof(struct fake_linux_lapd_header) == 16, lapd_header_size);
static_assert(offsetof(struct fake_linux_lapd_header, hatype) == 2, hatype_offset);
static_assert(offsetof(struct fake_linux_lapd_header, halen) == 4, halen_offset);
static_assert(offsetof(struct fake_linux_lapd_header, addr) == 6, addr_offset);
static_assert(offsetof(struct fake_linux_lapd_header, protocol) == 14, proto_offset);
static_assert(sizeof(struct fake_linux_lapd_header) == 16, lapd_header_size);
static int pcap_fd = -1;
@@ -145,7 +143,6 @@ static void write_pcap_packet(int direction, int sapi, int tei,
int ret;
time_t cur_time;
struct tm *tm;
int mi_head = (direction==PCAP_INPUT) ? MISDN_HEADER_LEN : 0;
struct fake_linux_lapd_header header = {
.pkttype = 4,
@@ -167,12 +164,10 @@ static void write_pcap_packet(int direction, int sapi, int tei,
struct pcaprec_hdr payload_header = {
.ts_sec = 0,
.ts_usec = 0,
.incl_len = msg->len + sizeof(struct fake_linux_lapd_header)
+ sizeof(struct lapd_header)
- mi_head,
.orig_len = msg->len + sizeof(struct fake_linux_lapd_header)
+ sizeof(struct lapd_header)
- mi_head,
.incl_len = msgb_l2len(msg) + sizeof(struct fake_linux_lapd_header)
+ sizeof(struct lapd_header),
.orig_len = msgb_l2len(msg) + sizeof(struct fake_linux_lapd_header)
+ sizeof(struct lapd_header),
};
@@ -183,8 +178,7 @@ static void write_pcap_packet(int direction, int sapi, int tei,
ret = write(pcap_fd, &payload_header, sizeof(payload_header));
ret = write(pcap_fd, &header, sizeof(header));
ret = write(pcap_fd, &lapd_header, sizeof(lapd_header));
ret = write(pcap_fd, msg->data + mi_head,
msg->len - mi_head);
ret = write(pcap_fd, msg->l2h, msgb_l2len(msg));
}
static const char *sign_types[] = {
@@ -261,7 +255,7 @@ int abis_rsl_sendmsg(struct msgb *msg)
return 0;
}
int _abis_nm_sendmsg(struct msgb *msg)
int _abis_nm_sendmsg(struct msgb *msg, int to_trx_oml)
{
struct e1inp_sign_link *sign_link;
struct e1inp_driver *e1inp_driver;
@@ -270,11 +264,18 @@ int _abis_nm_sendmsg(struct msgb *msg)
msg->l2h = msg->data;
if (!msg->trx || !msg->trx->bts || !msg->trx->bts->oml_link) {
LOGP(DRSL, LOGL_ERROR, "nm_sendmsg: msg->trx == NULL\n");
LOGP(DNM, LOGL_ERROR, "nm_sendmsg: msg->trx == NULL\n");
return -EINVAL;
}
sign_link = msg->trx->bts->oml_link;
/* Check for TRX-specific OML link first */
if (to_trx_oml) {
if (!msg->trx->oml_link)
return -ENODEV;
sign_link = msg->trx->oml_link;
} else
sign_link = msg->trx->bts->oml_link;
e1i_ts = sign_link->ts;
if (!bsc_timer_pending(&e1i_ts->sign.tx_timer)) {
/* notify the driver we have something to write */
@@ -303,6 +304,10 @@ int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line,
switch (type) {
case E1INP_TS_TYPE_SIGN:
if (line && line->driver)
ts->sign.delay = line->driver->default_delay;
else
ts->sign.delay = 100000;
INIT_LLIST_HEAD(&ts->sign.sign_links);
break;
case E1INP_TS_TYPE_TRAU:
@@ -319,7 +324,7 @@ int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line,
return 0;
}
static struct e1inp_line *e1inp_line_get(u_int8_t e1_nr)
struct e1inp_line *e1inp_line_get(u_int8_t e1_nr)
{
struct e1inp_line *e1i_line;
@@ -331,6 +336,43 @@ static struct e1inp_line *e1inp_line_get(u_int8_t e1_nr)
return NULL;
}
struct e1inp_line *e1inp_line_create(u_int8_t e1_nr, const char *driver_name)
{
struct e1inp_driver *driver;
struct e1inp_line *line;
int i;
line = e1inp_line_get(e1_nr);
if (line) {
LOGP(DINP, LOGL_ERROR, "E1 Line %u already exists\n",
e1_nr);
return NULL;
}
driver = e1inp_driver_find(driver_name);
if (!driver) {
LOGP(DINP, LOGL_ERROR, "No such E1 driver '%s'\n",
driver_name);
return NULL;
}
line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
if (!line)
return NULL;
line->driver = driver;
line->num = e1_nr;
for (i = 0; i < NUM_E1_TS; i++) {
line->ts[i].num = i+1;
line->ts[i].line = line;
}
llist_add_tail(&line->list, &e1inp_line_list);
return line;
}
#if 0
struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr)
{
struct e1inp_line *line;
@@ -353,6 +395,7 @@ struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr)
return line;
}
#endif
static struct e1inp_ts *e1inp_ts_get(u_int8_t e1_nr, u_int8_t ts_nr)
{
@@ -439,6 +482,7 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
u_int8_t tei, u_int8_t sapi)
{
struct e1inp_sign_link *link;
struct gsm_bts *bts;
int ret;
switch (ts->type) {
@@ -456,7 +500,8 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
switch (link->type) {
case E1INP_SIGN_OML:
msg->trx = link->trx;
ret = abis_nm_rcvmsg(msg);
bts = msg->trx->bts;
ret = bts->model->oml_rcvmsg(msg);
break;
case E1INP_SIGN_RSL:
msg->trx = link->trx;
@@ -520,13 +565,19 @@ struct msgb *e1inp_tx_ts(struct e1inp_ts *e1i_ts,
int e1inp_event(struct e1inp_ts *ts, int evt, u_int8_t tei, u_int8_t sapi)
{
struct e1inp_sign_link *link;
struct input_signal_data isd;
link = e1inp_lookup_sign_link(ts, tei, sapi);
if (!link)
return -EINVAL;
/* FIXME: report further upwards */
input_event(evt, link->type, link->trx);
isd.link_type = link->type;
isd.trx = link->trx;
isd.tei = tei;
isd.sapi = sapi;
/* report further upwards */
dispatch_signal(SS_INPUT, evt, &isd);
return 0;
}
@@ -537,9 +588,34 @@ int e1inp_driver_register(struct e1inp_driver *drv)
return 0;
}
struct e1inp_driver *e1inp_driver_find(const char *name)
{
struct e1inp_driver *drv;
llist_for_each_entry(drv, &e1inp_driver_list, list) {
if (!strcasecmp(name, drv->name))
return drv;
}
return NULL;
}
int e1inp_line_update(struct e1inp_line *line)
{
return mi_e1_line_update(line);
struct input_signal_data isd;
int rc;
if (line->driver && line->driver->line_update)
rc = line->driver->line_update(line);
else
rc = 0;
/* Send a signal to anyone who is interested in new lines being
* configured */
memset(&isd, 0, sizeof(isd));
isd.line = line;
dispatch_signal(SS_INPUT, S_INP_LINE_INIT, &isd);
return rc;
}
static int e1i_sig_cb(unsigned int subsys, unsigned int signal,
@@ -557,9 +633,17 @@ static int e1i_sig_cb(unsigned int subsys, unsigned int signal,
return 0;
}
static __attribute__((constructor)) void on_dso_load_e1_inp(void)
void e1inp_misdn_init(void);
void e1inp_dahdi_init(void);
void e1inp_init(void)
{
tall_sigl_ctx = talloc_named_const(tall_bsc_ctx, 1,
"e1inp_sign_link");
register_signal_handler(SS_GLOBAL, e1i_sig_cb, NULL);
e1inp_misdn_init();
#ifdef HAVE_DAHDI_USER_H
e1inp_dahdi_init();
#endif
}

102
openbsc/src/e1_input_vty.c Normal file
View File

@@ -0,0 +1,102 @@
/* OpenBSC E1 vty interface */
/* (C) 2011 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 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 <http://www.gnu.org/licenses/>.
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/buffer.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocore/linuxlist.h>
#include <openbsc/gsm_data.h>
#include <openbsc/e1_input.h>
#include <osmocore/utils.h>
#include <osmocore/gsm_utils.h>
#include <osmocore/talloc.h>
#include <openbsc/vty.h>
#include <openbsc/debug.h>
#include "../bscconfig.h"
#define E1_DRIVER_NAMES "(misdn|dahdi)"
#define E1_DRIVER_HELP "mISDN supported E1 Card\n" \
"DAHDI supported E1/T1/J1 Card\n"
DEFUN(cfg_e1line_driver, cfg_e1_line_driver_cmd,
"e1_line <0-255> driver " E1_DRIVER_NAMES,
"Configure E1/T1/J1 Line\n" "Line Number\n" "Set driver for this line\n"
E1_DRIVER_HELP)
{
struct e1inp_line *line;
int e1_nr = atoi(argv[0]);
line = e1inp_line_get(e1_nr);
if (line) {
vty_out(vty, "%% Line %d already exists%s", e1_nr, VTY_NEWLINE);
return CMD_WARNING;
}
line = e1inp_line_create(e1_nr, argv[1]);
if (!line) {
vty_out(vty, "%% Error creating line %d%s", e1_nr, VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(cfg_e1inp, cfg_e1inp_cmd,
"e1_input",
"Configure E1/T1/J1 TDM input\n")
{
vty->node = E1INP_NODE;
return CMD_SUCCESS;
}
static int e1inp_config_write(struct vty *vty)
{
struct e1inp_line *line;
vty_out(vty, "e1_input%s", VTY_NEWLINE);
llist_for_each_entry(line, &e1inp_line_list, list) {
vty_out(vty, " e1_line %u driver %s%s", line->num,
line->driver->name, VTY_NEWLINE);
}
return CMD_SUCCESS;
}
struct cmd_node e1inp_node = {
E1INP_NODE,
"%s(e1_input)#",
1,
};
int e1inp_vty_init(void)
{
install_element(CONFIG_NODE, &cfg_e1inp_cmd);
install_node(&e1inp_node, e1inp_config_write);
install_element(E1INP_NODE, &cfg_e1_line_driver_cmd);
return 0;
}

2
openbsc/src/gprs/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
gsn_restart
osmo_*.cfg*

Some files were not shown because too many files have changed in this diff Show More