Compare commits

...

138 Commits

Author SHA1 Message Date
Holger Hans Peter Freyther
f77c0cd428 Version bump for On-Waves
* Revert RTP_PAYLOAD change as it does not work on AMR
* Change paging to not send it as a bulk...
2010-04-20 14:36:40 +08:00
Holger Hans Peter Freyther
4103a3e5b9 Revert "ipaccess: Send RTP Payload IE for CRCX & MDCX"
This is causing a regression with AMR audio. The nanoBTS
is sending a MDCX NACK with Cause 0x52. Reverting this
commit makes it work again.

This reverts commit b54dda4cef.
2010-04-20 14:08:20 +08:00
Holger Hans Peter Freyther
4aca7f621f [paging] Continuisly send paging commands.
Instead of throwing a huge pile of paging commands to the BTS
we will submit one paging command every half second. This way
we can have different messages between the paging commands.
2010-04-20 12:27:33 +08:00
Holger Hans Peter Freyther
507d536ce8 [paging] When giving credit try to send out paging requests too.
Make sure the paging timer is restarted after giving some credit
and send out paging requests.
2010-04-20 10:59:33 +08:00
Holger Hans Peter Freyther
cb618c7980 [paging] Revert the paging band aid. 2010-04-20 10:54:43 +08:00
Holger Hans Peter Freyther
3c0702d3c5 Increase the minor version as this is a band-aid.. 2010-04-19 22:30:28 +08:00
Holger Hans Peter Freyther
caf24567d1 BAND AID... Reduce the delay timer, reduce number of paging requests we send
This is a band aid and not a proper fix. Reduce the time between two
IPA commands even if it is breaking rugby sized BTSs, limit the paging
commands we send during one iteration through the event loop. This should
prevent us from killing ourselves in a RACH loop.
2010-04-19 22:30:21 +08:00
Holger Hans Peter Freyther
1d34c6ac5a bsc_msc_ip: Crash fix on MO-Call starting with a SDCCH
We do not assing a GSM Subscriber to Mobile Originated calls, when
requesting a SDCCH and then starting call control we will crash here
due trying to copy a NULL subscriber from the lchan to the other.

We do not need to know the IMSI at the BSC so it is okay to not
copy the subscriber around, we could even kill all subscriber handling
in the future.
2010-04-19 22:15:32 +08:00
Holger Hans Peter Freyther
1506f8e465 [paging] When we ran down to 0 available paging slots start a credit timer
It might be that we run down to zero available slots but the BTS
might not send us a load indication. This can happen if we think
we send paging requests and the BTS disagrees and considers them
as errors and does not count the paging message.
When we drop to zero we will start a credit timer to give us extra
credit after six seconds, if we get a CCCH load indication before
we will stop the timer.
2010-04-19 19:41:26 +08:00
Holger Hans Peter Freyther
f044c585e2 Merge remote branch 'origin/master' into on-waves/bsc-master
Conflicts:
	openbsc/include/openbsc/abis_rsl.h
	openbsc/include/openbsc/mgcp.h
	openbsc/src/abis_rsl.c
	openbsc/src/chan_alloc.c
	openbsc/src/handover_logic.c
	openbsc/src/mgcp/mgcp_network.c
	openbsc/src/vty/command.c
	openbsc/src/vty_interface.c
2010-04-19 17:17:59 +08:00
Holger Hans Peter Freyther
6d17dd1314 Increase the version. 2010-04-19 17:06:17 +08:00
Harald Welte
38e9c82114 RSL: inmplement ip.access paging load indication 'below threshold'
This is an ip.access specific 08.58 oddity.  It reports 0xffff
available paging buffers if the paging load is below the 12.21
CCCH LOAD INDICATION THRESHOLD.

We use 50, since that is what it reports if the threshold == 0.
2010-04-19 10:29:16 +02:00
Holger Hans Peter Freyther
7cb6867ea3 [vty] Count pending paging requests for the vty
Implement a method to count the number of pending paging requests
per bts and print it on the VTY. This helps to see how big the
backlog of requests is for a given BTS.
2010-04-19 16:20:28 +08:00
Holger Hans Peter Freyther
d8138c43a1 nat: Make sccp/bsc show connections more Cisco like...
Second attempt to use a syntax more comparable to 'Cisco',
I have never used such a system... let us see how this is
going.
2010-04-19 16:06:43 +08:00
Holger Hans Peter Freyther
46d9b94477 [vty] Allow to allocate TCH/H and TCH/F too for testing purposes. 2010-04-19 16:01:14 +08:00
Holger Hans Peter Freyther
4f705b9f99 [vty] Add a test command to allocate all SDCCH 2010-04-19 16:01:14 +08:00
Holger Hans Peter Freyther
c592e697ce [alloc] Assign a TCH for LU when all SDCCHs are occupied.
When the cell becomes visible we will be bombed with location
updating requests and to reduce the load on the network we should
assign as many channels for it as possible. During load peek it
is even more important than to have a spare voice channel and in
general the LU procedure is pretty fast.
2010-04-19 16:01:07 +08:00
Harald Welte
39608dc045 GPRS: Fix calculation of 'Extension Length' in GPRS Cell Options
The actual 'Extension Length' field in the 'GPRS Cell Options' IE
is coded the length - 1, not the full length.  Without this fix,
the code has an off-by-one error.
2010-04-18 22:48:46 +02:00
Harald Welte
5fda90816f GPRS: Indicate the SGSN is Release 99 as this is the first with EDGE 2010-04-18 22:48:41 +02:00
Harald Welte
1803818092 update openbsc.cfg examples for new gprs syntax 2010-04-18 21:33:00 +02:00
Harald Welte
439bb828f9 GPRS: Enable EGPRS coding schemes in Cell Attributes if 'gprs mode egprs' 2010-04-18 21:25:56 +02:00
Harald Welte
a06fea020d GPRS: actually enable indicating EDGE capability in SI13 2010-04-18 21:25:56 +02:00
Harald Welte
4511d891dd GPRS: change 'gprs enabled <0-1>' to 'gprs mode (none|gprs|egprs)'
This causes some config file breakage but sounds like a much cleaner
approach than to have two separate config variables for this.
2010-04-18 21:25:56 +02:00
Harald Welte
da0586a838 GPRS: Add Support for the GPRS Cell Option Extension Info IE
Extension Information is part of the GPRS Cell Options IE, as
specified in Chapter 12.24 of TS 04.60.  It is needed for
indicating EDGE capabilities of the BTS to the MS.

This simply adds the code to encode this IE as part of SI13,
but does not actually use the code yet.
2010-04-18 21:25:56 +02:00
Harald Welte
2c57232489 add an example config file for nanoBTS multi-trx case 2010-04-18 21:25:18 +02:00
Harald Welte
ad9f7830fb update the openbts.cfg.nanobts example 2010-04-18 21:08:26 +02:00
Harald Welte
57ba7e3093 GPRS: BVCI 0 and 1 are not permitted.
According to TS 08.18, BVCI=0 is for the SIGNALLING entity,
and BVCI=1 is for the PTM entity.  Both should not be used
by the PTP entity that we're configuring here.
2010-04-18 14:00:26 +02:00
Harald Welte
6ba3bcbbc6 BVCI 0 is not within the permitted range 2010-04-18 13:59:53 +02:00
Holger Hans Peter Freyther
ebb6b99c63 nat: Do not use 0/0 for mux/timeslot by default
0 is a valid timeslot and we should not use it... use
a negative value to be save.
2010-04-18 03:07:22 +08:00
Holger Hans Peter Freyther
e08253a3f7 nat: Clear the connection on a DLCX
We can forget about the timeslot/multiplex when getting
the DLCX. This way we make room for the next connection
that might need to reuse this address.
2010-04-18 03:05:27 +08:00
Holger Hans Peter Freyther
5e86095364 nat: Always initialize the out pointer...
Always initialize the pointer to a invalid value in case
we encounter a parsing error or such.
2010-04-18 02:41:20 +08:00
Holger Hans Peter Freyther
a7c144888d nat: Fix the test case by allocating a config.
For the statistics we do need to have an allocated config,
otherwise we will nicely crash.
2010-04-18 02:40:33 +08:00
Holger Hans Peter Freyther
7897c4446b nat: Return the SCCP Connection again...
We will reset the multiplex in a DLCX message and then
we can reset the multiplex as well...even if the MGCP
connection is staying open. or at least this is a theory.

The MSC likes to leave a connection open during CallControl
when hanging up early enough in the process.
2010-04-18 02:40:33 +08:00
Holger Hans Peter Freyther
ff9e09b2bc nat: Return the newest SCCP connection...
In case we have a stale SCCP connection with an Endpoint that
we want to reassign...use the newest (last) occurence of that
as it is most likely the one we want to handle.
2010-04-18 02:40:32 +08:00
Holger Hans Peter Freyther
ecf5cc294d bsc_msc_ip: Print a small status on active connections
This needs to be improved to print TS of the lchan, when
the connection was created, when we received the last IT.
2010-04-18 02:40:32 +08:00
Holger Hans Peter Freyther
82126763a7 nat: Increase the right counter on calls. 2010-04-18 02:40:31 +08:00
Holger Hans Peter Freyther
a380c89a9c nat: Add new connections to the end of the list
By adding them to the end the VTY interface will only append
connections and not change the order on each invocation.
2010-04-18 02:40:31 +08:00
Holger Hans Peter Freyther
bedaf5da64 bssap: Move parsing of paging into the paging section... 2010-04-18 02:40:30 +08:00
Holger Freyther
2b08aa35a6 nat: Remove the SHOW_STR from none show commands. 2010-04-18 02:40:30 +08:00
Holger Hans Peter Freyther
c24632930a bsc_msc_ip: Allow to put the MSC address into the network config 2010-04-17 09:07:24 +02:00
Holger Hans Peter Freyther
f140348eff nat: Print the LAC that was searched for and not found. 2010-04-17 08:07:19 +02:00
Holger Hans Peter Freyther
b5de1b0781 nat: Mention when we do not find a BSC for a given token.
This might help to identify what is wrong with the config
of the BSC. Also using the result of TLVP_VAL as a char
pointer looks suspicious...
2010-04-17 08:07:03 +02:00
Holger Hans Peter Freyther
b022cc3b8e nat: Print the IP address of the BSC that does not respond to the query. 2010-04-17 07:58:17 +02:00
Holger Hans Peter Freyther
e8396c9663 nat: Make the MSC configurable. 2010-04-17 07:48:45 +02:00
Holger Hans Peter Freyther
941839b300 nat: Move MSC ip address into the config..
The address can still be specified on the cli and it will
overwrite the config in the config file.
2010-04-17 07:31:08 +02:00
Holger Hans Peter Freyther
23a0e46f11 Add rf_locked to the configuration writing. 2010-04-17 07:31:08 +02:00
Holger Hans Peter Freyther
cb8fd6e99e Use osmocore tlv definition for GSM0808. 2010-04-17 07:31:03 +02:00
Holger Hans Peter Freyther
bb110f91e8 [statistics] Keep track of OML/RSL failures of the BTS. 2010-04-17 06:48:43 +02:00
Holger Hans Peter Freyther
3ba36d5b57 [statistics] Keep track of rf failures and rll release failures
Add two new counters to count the RF Failures and the RLL Release
failure and make them available via the vty interface.
2010-04-17 06:48:29 +02:00
Holger Hans Peter Freyther
bda581963d Merge branch 'on-waves/mgcp' 2010-04-17 06:46:06 +02:00
Holger Hans Peter Freyther
8d9833ef83 [mgcp] Fix vty file generation for the BSC nat and other cases
The current setting was not properly written out, this commit is
fixing it. This includes indention, empty bts ip, wrong command
for endpoints and the wrong number (+1 as zero is allocated but
unused).
2010-04-17 06:45:08 +02:00
Holger Hans Peter Freyther
2ba40afc36 Add rf_locked to the configuration writing. 2010-04-17 06:42:48 +02:00
Holger Hans Peter Freyther
e66bea8ad7 [mgcp] Fix vty file generation for the BSC nat and other cases
The current setting was not properly written out, this commit is
fixing it. This includes indention, empty bts ip, wrong command
for endpoints and the wrong number (+1 as zero is allocated but
unused).
2010-04-16 16:59:48 +02:00
Holger Hans Peter Freyther
e8a9f471ef nat: Two fixes for the write memory case...
Add new BSCs to the tail so we keep the sort order when writing
them out to the vty, fix the LAC command.
2010-04-16 16:52:20 +02:00
Holger Hans Peter Freyther
e0ec326867 [vty] Separate BSC and MSC statistics. Make it easy to print them.
Move the statistics command into the MSC part and move the
BSC statistics printing into a subroutine.
2010-04-15 11:28:14 +02:00
Holger Hans Peter Freyther
2d425059af [mgcp] Only write audio_name/payload when it is actually set. 2010-04-15 11:26:35 +02:00
Holger Hans Peter Freyther
135f797a37 [bsc_init] When the RSL/OML connection drops, free all lchans
Free all allocated channels on the TRX that failed, go through
lchan_free to signal higher layers and then force a reset of
the channel. Make the TRX and TS unusable by setting the operational
set to 0 (not really defined) which should be reset once the
RSL is coming up again.
2010-04-15 11:24:53 +02:00
Holger Hans Peter Freyther
f8eff2e4b5 [ipa] Fix the reporting of link down...
Now bsc_init.c is able to handle the link down messages.
2010-04-15 11:19:08 +02:00
Holger Hans Peter Freyther
70402a4e4d [ipa] Handle losing the RSL/OML connection..
This is addressing multiple issues regarding the loss of the
OML/RSL link to the BTS.

1.) When we lose the OML link, close down all RSL connections
on all TRXs (only tested with one TRX) and free the e1inp_line
allocated for the OML connection.
2.) When we lose the RSL link on any TRX and we know to which
lines this connection belongs, we will close down the OML connection
as we have a problem to just reactivate one RSL link.
3.) When we lose the RSL link on any TRX and we do not know
where it belongs to we will free the bfd we have allocated in the
rsl listen/accept method and we properly close the socket (i could
not test this one properly). This is made under the assumption
the BTS has not responded to the ID request.
4.) When we already have a bts->oml_link we will throw it away
and use the new link (it should not happen) and the same applies
to the rsl link.
2010-04-15 11:17:24 +02:00
Holger Hans Peter Freyther
c2d66bdf5a Increase the version 2010-04-14 11:28:55 +02:00
Holger Hans Peter Freyther
80b584bbe7 [bsc_msc_ip] Implement a simple RF lock command interface
Right now this is using unix domain sockets and it only
supports query, on and off as commands. In the future we
want to have a vty<->snmp bridge or at least more status
exposed via snmp.
2010-04-14 11:19:07 +02:00
Holger Hans Peter Freyther
15c21e8eec bsc_msc_ip.c: Create the GSM network earlier, send the reset on each connection
Create the GSM network at the end of the init, send the
GSM reset on each reconnection and close a small window
when we would send a SCCP msg before being authenticated.

For that we have introduced an authenticated into the bsc_msc
struct and will manage it inside the bsc_msc_ip.c
2010-04-14 08:49:15 +02:00
Holger Hans Peter Freyther
c0a1fff064 bsc_msc_ip.c: Set the signal handler earlier..
We should set this before starting any network operation.
2010-04-14 08:46:29 +02:00
Holger Hans Peter Freyther
77fa4d2386 bsc_msc_ip.c: Fix the source comment...
This file is the bsc_msc_ip process to communicate with a MSC
and to implement the GSM 08.08 spec.
2010-04-14 08:34:24 +02:00
Holger Hans Peter Freyther
9be8752541 [bsc_msc_ip] Fix the name of the process. 2010-04-13 11:28:13 +02:00
Holger Hans Peter Freyther
2b57b3cea4 [bsc_msc_ip] Remove the possible dangerous -P option for the BSC
We always want to handle the CRCX the way we want to without
allocating a BSC proxy process. The default value of 1 is fine
for the bsc_msc_ip and we should not allow to set it.
2010-04-13 11:27:17 +02:00
Holger Hans Peter Freyther
00c531709a nat: Add config option to filter/handle certain imsi'es. 2010-04-13 09:50:38 +02:00
Holger Hans Peter Freyther
a094108f84 [statistics] Count the times we lost the connection to the MSC. 2010-04-13 09:47:22 +02:00
Holger Hans Peter Freyther
61e73eec3f [nat] Add show statistics to the nat 2010-04-13 09:47:22 +02:00
Holger Hans Peter Freyther
1aa2798919 [statistics] Provide basic statistics for the NAT
Count number of SCCP connections, number of BSC reconnects,
number of calls. For most of them we have a per BSC and a
global count.

Right now all structs using the counters survive until the
end of the application so we do not need to free them.
2010-04-13 09:47:22 +02:00
Holger Hans Peter Freyther
b829eac9bc [statistics] Keep track of OML/RSL failures of the BTS. 2010-04-13 09:47:22 +02:00
Holger Hans Peter Freyther
7b1719327d [statistics] Keep track of rf failures and rll release failures
Add two new counters to count the RF Failures and the RLL Release
failure and make them available via the vty interface.
2010-04-13 09:47:22 +02:00
Holger Hans Peter Freyther
493645eda9 bsc_msc_ip: Install BSC specific show statistics command. 2010-04-13 09:47:21 +02:00
Holger Hans Peter Freyther
8614cd0be7 [mgcp] Only write audio_name/payload when it is actually set. 2010-04-13 09:47:21 +02:00
Holger Hans Peter Freyther
19bd74d093 [vty] Separate BSC and MSC statistics. Make it easy to print them.
Move the statistics command into the MSC part and move the
BSC statistics printing into a subroutine.
2010-04-13 09:27:13 +02:00
Sylvain Munaut
b54dda4cef ipaccess: Send RTP Payload IE for CRCX & MDCX
For GSM V1 FR, the payload type is fixed to 3 in the RFC.
But for the other codecs, the payload type is dynamically assigned
between 96 and 127. Here, we use a static mapping internal to OpenBSC.

This patch is needed to make a rather old 139 unit (with sw version
120a002_v149b42d0) work with something else than FR codec. I also tested
this patch on a newer 139 (with sw version 120a352_v267b22d0) to make
sure it didn't add a regression. More testing with newer EDGE units
should be done by whoever has some of theses.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-04-12 19:58:57 +02:00
Sylvain Munaut
b998d7b219 abis_nm: Fix ACTIVATE SW parameters
The previous code only sent the FILE_ID tag data part,
but according to the GSM 12.21 spec, section 8.3.6, the
full SW Description 'object' must be sent so that includes
the NM_ATT_SW_DESCR tag, the whole FILE_ID and the whole
FILE_VERSION (including tags & length fields).

Note that functionnaly on a nanoBTS 139 I couldn't see any
difference ... whatever I send in there it works ...

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-04-12 19:58:57 +02:00
Holger Hans Peter Freyther
4821b5a847 [nat] Change the command strings
Put the Target/Object first... Apparently this is more what people
that know IOS expect to do.
2010-04-12 07:29:22 +02:00
Holger Hans Peter Freyther
84df56d577 Increase version.. 2010-04-11 19:41:32 +02:00
Holger Hans Peter Freyther
4e23d5f87f [bsc_init] When the RSL/OML connection drops, free all lchan
Free all allocated channels on the TRX that failed, go through
lchan_free to signal higher layers and then force a reset of
the channel. Make the TRX and TS unusable by setting the operational
set to 0 (not really defined).
2010-04-11 19:34:43 +02:00
Holger Hans Peter Freyther
4346424987 [ipa] Fix the reporting of link down...
Now bsc_init.c is able to handle the link down messages.
2010-04-11 18:54:58 +02:00
Holger Hans Peter Freyther
520656e004 [ipa] Handle losing the RSL/OML connection..
This is addressing multiple issues regarding the loss of the
OML/RSL link to the BTS.

1.) When we lose the OML link, close down all RSL connections
on all TRXs (only tested with one TRX) and free the e1inp_line
allocated for the OML connection.
2.) When we lose the RSL link on any TRX and we know to which
lines this connection belongs, we will close down the OML connection
as we have a problem to just reactivate the RSL link.
3.) When we lose the RSL link on any TRX and we do not know
where it belongs to we will free the bfd we have allocated in the
rsl listen/accept method and we properly close the socket (i could
not test this one properly).
4.) When we already have a bts->oml_link we will throw it away
and use the new link.
2010-04-11 18:49:03 +02:00
Holger Hans Peter Freyther
9dac231fe4 e1_input: Stop the timer when deleting the signalling link on the TS
Stop the tx_timer when deleting the link on top of that ts. Otherwise
bad things might happen. E.g. when scheduling a write on OML and then
the OML link vanishes...

This is a slight layering violation as there could be more than
one signalling link on the timeslow (at least in theory) so the
queue and the timer should move to the e1inp_sign_link.
2010-04-11 17:18:02 +02:00
Holger Hans Peter Freyther
2bb518a3bd [e1_input] When destroying a link clear all pending messages 2010-04-11 14:13:10 +02:00
Holger Hans Peter Freyther
476940f747 [vty] First set of fixes for the oml/rsl con dropping
The code had wrong documentation in the VTY, it crashed
when OML or RSL was not up yet. These issues are fixed
right now.
2010-04-11 12:46:45 +02:00
Holger Hans Peter Freyther
63cb447fd5 Revert "ipa: Reduce the throttling of the IPA msges"
Reducing the throttling to this value created a regression with
bringing up RSL on the nanoBTS 900. We do seem to have a bug/issue
in the bsc_init code and might send a command too early without this
longer wait period and then the state transition does not happen.

For now it is agreed that reverting is the best thing to do.

Debugged-by: Sylvain Munaut <246tnt@gmail.com>

This reverts commit f5284ae1cf.
2010-04-11 10:14:16 +02:00
Holger Hans Peter Freyther
5eec9d91d8 [rsl] Set the right state when asking for the activation.
Set the state to activation to avoid a warning about the
getting a CHAN ACK without waiting for it. We set it in
the code to make sure it is set after all error checking
to avoid inconsistent state as the state is only set back
to NONE/ACT due replies from the BTS.
2010-04-10 00:16:04 +02:00
Holger Hans Peter Freyther
63d18b51a7 [rsl] Set the release state from within the lchan class
Currently our GSM04.11 code is closing the link for SAPI=3
and this would mean that the whole channel would be scheduled
for close... where we only want to close everything when freeing
the lchan or handling an error.
2010-04-10 00:14:55 +02:00
Holger Hans Peter Freyther
74419497fc [rsl] Introduce a method to set the state of the lchan
Setting the state through a dedicated method allows us to
track the state transitions and check if they are done in
a proper way.
2010-04-10 00:13:53 +02:00
Holger Hans Peter Freyther
ccfd572647 [rsl] Remove method that is not called by anything. 2010-04-10 00:11:17 +02:00
Holger Hans Peter Freyther
07ba16fe03 [vty] Remove unused variables due them only being used in the layer3
I moved the extra code to the layer3 VTY implementation but didn't
remove the variables while doign so, silent compiler warnings.
2010-04-10 00:08:59 +02:00
Holger Hans Peter Freyther
e1ffc08f72 [vty] Forward declare the extra init function the base is calling 2010-04-10 00:08:28 +02:00
Holger Hans Peter Freyther
ef8117883b [paging] Include chan_alloc.h to silence a compiler warning
paging.c:259: warning: implicit declaration of function ‘trx_is_usable’
2010-04-10 00:06:17 +02:00
Holger Hans Peter Freyther
ae80f9291a Return anything from append_lsa_params. 2010-04-10 00:05:16 +02:00
Holger Hans Peter Freyther
1469600b0d [paging] Start with a smaller paging limit...
The value 20 is just a random number and it really depends
on the number of TRX on a bts to be a sane or insane limit.
2010-04-10 00:01:03 +02:00
Holger Hans Peter Freyther
c50b836540 [paging] Move code to use LOGP and print some more information 2010-04-10 00:00:51 +02:00
Holger Hans Peter Freyther
754e801826 [paging] Simplify the last request and treat llist as a queue
The current code was overly complex. It tried to iterate over
the list in a round robin and we had to keep track of the last
element, see if we remove that one, check if the list becomes
empty... This can all replaced by treating the double linked
list as a queue. We take the item at the front, do something
on it and then and then put it back to the list at the end.
2010-04-10 00:00:15 +02:00
Holger Hans Peter Freyther
19722d4411 paging: Avoid integer underflow on ipaccess
On the nanoBTS we do not receive any load indication for the
paging channel and we just decrement our available slots and
the unsigned int wraps to the maximum value. Together with a
not yet understood bug this makes us go amock.

For the nanoBTS and even the Siemens BS11 resetting the load
to 20 after two seconds should be just fine. For the nanoBTS
we would need to reset the 20 a lot more earlier but we need
to take a look at how often we run low.
2010-04-09 23:59:52 +02:00
Holger Hans Peter Freyther
5615b982c2 [mgcp] Improve the endpoint display on the vty..
Make sure one understands the two values for number of
incoming packets..
2010-04-09 23:53:08 +02:00
Holger Hans Peter Freyther
aff596b8e1 [mgcp] Print the IP addr of the BTS we have detected. 2010-04-09 23:53:00 +02:00
Holger Hans Peter Freyther
07d838a3bf [paging] Do not use request after it was was destroyed..
Increment the counter before we call the remove request
which is freeing the request...
2010-04-08 17:10:37 +02:00
Holger Hans Peter Freyther
d4e7888ae3 [paging] Increase the time used to send paging messages to the BTS
Send a Paging Request to the BTS every two seconds. This way it is
unlikely that a phone will try to respond to two paging requests as
it is currently happening.
2010-04-07 23:14:36 +02:00
Holger Hans Peter Freyther
6c8c0ddbe2 [ipa] When including MGCP our messages might be bigger than 300 byte
The length field of the IPA header allows to have 16bit numbers
and I just ran into the 300 byte limit with MGCP messages. Make it
three times the size and see how long this is going to be enough.
2010-04-07 23:10:38 +02:00
Holger Hans Peter Freyther
19bab73d79 [rsl] Speculative crash fix in the RSL rcv message
The theory is that the BTS is almost dead and sends out
a incomplete message and we crash with that. I have not
been able to completely verify that.
2010-04-07 23:09:21 +02:00
Holger Hans Peter Freyther
c19a65baae Merge branch 'master' into on-waves/mgcp 2010-04-07 23:03:27 +02:00
Holger Hans Peter Freyther
1ea8dbec90 [mgcp] Fix navigation in the vty hierachy (make exit work)
Make exit from the MGCP node work properly.
2010-04-07 23:01:08 +02:00
Holger Hans Peter Freyther
500ff97c21 Fix compiler warning about void return in non void method. 2010-04-07 23:00:23 +02:00
Holger Hans Peter Freyther
441273766a [mgcp] Add the logging commands for the MGCP command. 2010-04-07 22:55:17 +02:00
Holger Hans Peter Freyther
014136da47 Merge branch 'on-waves/sccp' 2010-04-07 22:54:12 +02:00
Holger Hans Peter Freyther
91b5a31a2c Merge branch 'on-waves/mgcp' 2010-04-07 22:54:07 +02:00
Holger Hans Peter Freyther
575b89585f [mgcp] Print the errno/strerror when we can not receive from our socket 2010-04-07 22:52:40 +02:00
Holger Hans Peter Freyther
408cc4ace9 [mgcp] Add an option to allow using reallocing an endpoint
For some mode of operation it can be acceptable to reallocate
an already allocated endpoint. This can be the case when we
only deal with one call agent that is keeping track of the
endpoint but slightly confused.
2010-04-07 22:52:25 +02:00
Holger Hans Peter Freyther
b4b135efbf [mgcp] Count incoming RTP packets from the BTS and remote 2010-04-07 22:51:59 +02:00
Holger Hans Peter Freyther
54fa799129 vty: Fix the byteorder... of the bound_ip
We are storing the bound_ip in host byteorder but when
using ntohl we need to convert it back to to network
byte order.
2010-04-07 22:51:37 +02:00
Holger Hans Peter Freyther
b4c7b274a1 [mgcp] Reset the the address when freeing the endp as well 2010-04-06 12:13:19 +02:00
Holger Hans Peter Freyther
7279d24232 [mgcp] Do not patch RTP payload when type is set to -1.
For the nat we might or might not want to patch it, do not
patch if we have no valid rtp payload type.
2010-04-06 12:12:52 +02:00
Holger Hans Peter Freyther
ef8253c495 [mgcp] Use a different port to more easily differentiate 2010-04-05 22:04:23 +02:00
Holger Hans Peter Freyther
6c0729fe70 [mgcp] Print the BTS IP addr of the endpoint. 2010-04-05 22:04:15 +02:00
Holger Hans Peter Freyther
e125d40f66 [mgcp] Start to look into the MGCP messages and extract the CI
we will need the call identifier for the MDCX and DLCX message
for now we were just assuming it would increment, use som python
to extract the CI from a possible response, also switch back to
a blocking read to test the BSC nat.
2010-04-05 22:04:07 +02:00
Holger Hans Peter Freyther
58df0ea9a0 [mgcp] Fix the transaction id of the AUEP request 2010-04-05 22:03:41 +02:00
Holger Hans Peter Freyther
8b120f0ef9 [mgcp] Look at the bts addr set at the endpoint
This will allow to discover the ports of a bts when we only know
the addr and have multiple bts's to handle.
2010-04-05 22:03:04 +02:00
Holger Hans Peter Freyther
f2f1591ce7 [mgcp] Export header parsing via mgcp internal
This will be used by the NAT code to implement custom protocol
handling on top of that.
2010-04-05 22:02:54 +02:00
Holger Hans Peter Freyther
f36a11a35d [mgcp] Do not operate on the ->data pointer, use ->l2h instead
This would have been broken once we attempt to parse encapsulated
MGCP messages.
2010-04-05 22:02:47 +02:00
Holger Hans Peter Freyther
c77efdf057 [mgcp] Degrade verbosity to debug 2010-04-05 22:02:38 +02:00
Holger Hans Peter Freyther
b79994c952 [mgcp] Add a new config option to set the call agent ip addr
In the case of the nat we only want to communicate with one
upstream call agent and this can now be configured.
2010-04-05 22:02:29 +02:00
Holger Hans Peter Freyther
616d222518 [mgcp] Add a helper function to convert from GSM0808 ts/mux to MGCP endpoint
Move the conversion of GSM0808 timeslot and multiplex from
the bssap.c into the mgcp.h so it can be reused by multiple
users. The weird math comes from the mapping of the MSC...
2010-04-05 22:02:16 +02:00
Holger Hans Peter Freyther
64e4e77558 [mgcp] Handle the RSIP with resetting all endpoints
We could change that the message came from a special ip
address/port to secure this service in general but we don't
do that right now.
2010-04-05 22:01:52 +02:00
Holger Hans Peter Freyther
9bdcc9ca75 [mgcp] Add some parsing for RSIP messages coming in
This will just call a callback and leave all the handling
to the application.
2010-04-05 22:01:44 +02:00
Holger Hans Peter Freyther
e7d2ae69c9 [mgcp] Remove unused method from the mgcp
This was removed when sending the RSIP was
removed from the code.
2010-04-05 22:01:36 +02:00
Holger Hans Peter Freyther
52a66aa27e [mgcp] Switch from DEBUG to LOGP in the mgcp_main.c 2010-04-05 22:01:28 +02:00
Holger Hans Peter Freyther
13d67b7ea3 [mgcp] Remove the sending of RSIP
This message is ignored by the call agent and we were
sending this on the first request which we maybe should
not ignore...
2010-04-05 22:01:20 +02:00
Holger Hans Peter Freyther
b71517f07e [sccp] Add a force_free method for connections
E.g. when the underlying connection transport medium is gone
one needs to force to close SCCP connections, add this helper.

It will remove the connection from the list of connections and
it will free the data.
2010-04-05 22:00:24 +02:00
Holger Hans Peter Freyther
95e4d34f06 [mgcp] The networking code needs a source addrs..
Make the source address mandantory and complain about
complain when it is missing. The address is mandantory
as it needs to be put into the MGCP messages...
2010-03-30 15:35:57 +02:00
Holger Hans Peter Freyther
f5b6aa60ce [mgcp] Move mgcp init into the main method... 2010-03-30 15:35:48 +02:00
Holger Hans Peter Freyther
c38b5884ff [mgcp] Fix format string usage 2010-03-30 15:35:39 +02:00
Holger Hans Peter Freyther
4079105a6c Merge remote branch 'origin/master' into on-waves/mgcp 2010-03-30 15:35:26 +02:00
Holger Hans Peter Freyther
774f0723bf [mgcp] Do not print potentially many messages... 2010-03-01 18:53:05 +01:00
Holger Hans Peter Freyther
88c6eeaa7d [mgcp] Set the right variable back to NULL 2010-03-01 18:52:04 +01:00
43 changed files with 1391 additions and 273 deletions

View File

@@ -1,7 +1,7 @@
dnl Process this file with autoconf to produce a configure script
AC_INIT
AM_INIT_AUTOMAKE(openbsc, 0.3.95onwaves)
AM_INIT_AUTOMAKE(openbsc, 0.3.98.2onwaves)
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])

View File

@@ -6,7 +6,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \
bsc_rll.h mncc.h transaction.h ussd.h gsm_04_80.h \
silent_call.h mgcp.h meas_rep.h rest_octets.h \
system_information.h handover.h mgcp_internal.h \
vty.h bssap.h bsc_msc.h bsc_nat.h
vty.h bssap.h bsc_msc.h bsc_nat.h bsc_msc_rf.h
openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
openbscdir = $(includedir)/openbsc

View File

@@ -72,6 +72,8 @@ int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t rele
int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
/* to be provided by external code */
int abis_rsl_sendmsg(struct msgb *msg);
int rsl_deact_sacch(struct gsm_lchan *lchan);

View File

@@ -29,6 +29,7 @@
struct bsc_msc_connection {
struct write_queue write_queue;
int is_connected;
int is_authenticated;
const char *ip;
int port;

View File

@@ -0,0 +1,20 @@
#ifndef BSC_MSC_RF
#define BSC_MSC_RF
#include <osmocore/write_queue.h>
struct gsm_network;
struct bsc_msc_rf {
struct bsc_fd listen;
struct gsm_network *gsm_network;
};
struct bsc_msc_rf_conn {
struct write_queue queue;
struct gsm_network *gsm_network;
};
struct bsc_msc_rf *bsc_msc_rf_create(const char *path, struct gsm_network *net);
#endif

View File

@@ -31,6 +31,9 @@
#include <osmocore/msgb.h>
#include <osmocore/timer.h>
#include <osmocore/write_queue.h>
#include <osmocore/statistics.h>
#include <regex.h>
#define DIR_BSC 1
#define DIR_MSC 2
@@ -113,6 +116,20 @@ struct sccp_connections {
int bsc_timeslot;
};
/**
* Stats per BSC
*/
struct bsc_config_stats {
struct {
struct counter *conn;
struct counter *calls;
} sccp;
struct {
struct counter *reconn;
} net;
};
/**
* One BSC entry in the config
*/
@@ -123,7 +140,16 @@ struct bsc_config {
unsigned int lac;
int nr;
/* imsi white and blacklist */
char *imsi_allow;
regex_t imsi_allow_re;
char *imsi_deny;
regex_t imsi_deny_re;
/* backpointer */
struct bsc_nat *nat;
struct bsc_config_stats stats;
};
/**
@@ -138,6 +164,25 @@ struct bsc_endpoint {
int pending_delete;
};
/**
* Statistic for the nat.
*/
struct bsc_nat_statistics {
struct {
struct counter *conn;
struct counter *calls;
} sccp;
struct {
struct counter *reconn;
struct counter *auth_fail;
} bsc;
struct {
struct counter *reconn;
} msc;
};
/**
* the structure of the "nat" network
*/
@@ -159,9 +204,20 @@ struct bsc_nat {
int mgcp_length;
/* msc things */
char *msc_ip;
int msc_port;
int first_contact;
struct bsc_endpoint *bsc_endpoints;
/* filter */
char *imsi_allow;
regex_t imsi_allow_re;
char *imsi_deny;
regex_t imsi_deny_re;
/* statistics */
struct bsc_nat_statistics stats;
};
/* create and init the structures */
@@ -169,6 +225,7 @@ struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsi
struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
struct bsc_nat *bsc_nat_alloc(void);
struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat);
void bsc_nat_set_msc_ip(struct bsc_nat *bsc, const char *ip);
void sccp_connection_destroy(struct sccp_connections *);
@@ -182,7 +239,7 @@ struct bsc_nat_parsed *bsc_nat_parse(struct msgb *msg);
*/
int bsc_nat_filter_ipa(int direction, struct msgb *msg, struct bsc_nat_parsed *parsed);
int bsc_nat_vty_init(struct bsc_nat *nat);
struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg);
struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *_lac);
/**
* SCCP patching and handling
@@ -203,7 +260,7 @@ void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int);
void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
int bsc_mgcp_init(struct bsc_nat *nat);
struct bsc_connection *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
struct sccp_connections *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
struct msgb *bsc_mgcp_rewrite(char *input, int length, const char *ip, int port);
void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg);

View File

@@ -330,6 +330,4 @@ void bts_send_queued(struct bss_sccp_connection_data*);
void bts_free_queued(struct bss_sccp_connection_data*);
void bts_unblock_queue(struct bss_sccp_connection_data*);
const struct tlv_definition *gsm0808_att_tlvdef();
#endif

View File

@@ -63,10 +63,11 @@ struct gsm_lchan *lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr)
struct gsm_lchan *lchan_for_subscr(struct gsm_subscriber *subscr);
/* Allocate a logical channel (SDCCH, TCH, ...) */
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type);
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type, int allow_bigger);
/* Free a logical channel (SDCCH, TCH, ...) */
void lchan_free(struct gsm_lchan *lchan);
void lchan_reset(struct gsm_lchan *lchan);
/* internal.. do not use */
int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason);

View File

@@ -73,6 +73,12 @@ enum gsm_paging_event {
GSM_PAGING_OOM,
};
enum bts_gprs_mode {
BTS_GPRS_NONE = 0,
BTS_GPRS_GPRS = 1,
BTS_GPRS_EGPRS = 2,
};
struct msgb;
typedef int gsm_cbfn(unsigned int hooknum,
unsigned int event,
@@ -399,6 +405,7 @@ struct gsm_bts_paging_state {
struct gsm_bts *bts;
struct timer_list work_timer;
struct timer_list credit_timer;
/* load */
u_int16_t available_slots;
@@ -503,7 +510,7 @@ struct gsm_bts {
/* Not entirely sure how ip.access specific this is */
struct {
int enabled;
enum bts_gprs_mode mode;
struct {
struct gsm_nm_state nm_state;
u_int16_t nsei;
@@ -562,6 +569,14 @@ struct gsmnet_stats {
struct counter *alerted; /* we alerted the other end */
struct counter *connected;/* how many calls were accepted */
} call;
struct {
struct counter *rf_fail;
struct counter *rll_err;
} chan;
struct {
struct counter *oml_fail;
struct counter *rsl_fail;
} bts;
};
enum gsm_auth_policy {
@@ -653,6 +668,8 @@ struct gsm_network {
/* a simple token for this network... */
char *bsc_token;
char *msc_ip;
int msc_port;
};
#define SMS_HDR_SIZE 128
@@ -749,6 +766,9 @@ const char *gsm_auth_policy_name(enum gsm_auth_policy policy);
enum rrlp_mode rrlp_mode_parse(const char *arg);
const char *rrlp_mode_name(enum rrlp_mode mode);
enum bts_gprs_mode bts_gprs_mode_parse(const char *arg);
const char *bts_gprs_mode_name(enum bts_gprs_mode mode);
void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
/* A parsed GPRS routing area */

View File

@@ -53,6 +53,8 @@ int ipaccess_send_id_req(int fd);
int ipaccess_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len);
int ipaccess_drop_oml(struct gsm_bts *bts);
int ipaccess_drop_rsl(struct gsm_bts_trx *trx);
/*
* Firmware specific header

View File

@@ -43,4 +43,7 @@ void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr,
/* update paging load */
void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t);
/* pending paging requests */
unsigned int paging_pending_requests_nr(struct gsm_bts *bts);
#endif

View File

@@ -71,6 +71,7 @@ enum gprs_nmo {
GPRS_NMO_III = 2, /* no paging coordination */
};
/* TS 04.60 12.24 */
struct gprs_cell_options {
enum gprs_nmo nmo;
/* T3168: wait for packet uplink assignment message */
@@ -79,6 +80,16 @@ struct gprs_cell_options {
u_int32_t t3192; /* in milliseconds */
u_int32_t drx_timer_max;/* in seconds */
u_int32_t bs_cv_max;
u_int8_t ext_info_present;
struct {
u_int8_t egprs_supported;
u_int8_t use_egprs_p_ch_req;
u_int8_t bep_period;
u_int8_t pfc_supported;
u_int8_t dtm_supported;
u_int8_t bss_paging_coordination;
} ext_info;
};
/* TS 04.60 Table 12.9.2 */

View File

@@ -1,6 +1,10 @@
#ifndef OPENBSC_VTY_H
#define OPENBSC_VTY_H
struct gsm_network;
struct vty;
void openbsc_vty_add_cmds(void);
void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
#endif

View File

@@ -35,7 +35,7 @@ bsc_hack_LDADD = libmsc.a libbsc.a libmsc.a libvty.a -ldl -ldbi $(LIBCRYPT)
bs11_config_SOURCES = bs11_config.c abis_nm.c gsm_data.c debug.c \
rs232.c bts_siemens_bs11.c
bsc_msc_ip_SOURCES = bssap.c bsc_msc_ip.c bsc_init.c vty_interface.c vty_interface_bsc.c \
bsc_msc.c
bsc_msc.c bsc_msc_rf.c
bsc_msc_ip_LDADD = libbsc.a libvty.a libsccp.a

View File

@@ -822,15 +822,56 @@ static int ipacc_sw_activate(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i
return abis_nm_sendmsg(bts, msg);
}
static int abis_nm_parse_sw_descr(const u_int8_t *sw_descr, int sw_descr_len)
{
static const struct tlv_definition sw_descr_def = {
.def = {
[NM_ATT_FILE_ID] = { TLV_TYPE_TL16V, },
[NM_ATT_FILE_VERSION] = { TLV_TYPE_TL16V, },
},
};
u_int8_t tag;
u_int16_t tag_len;
const u_int8_t *val;
int ofs = 0, len;
/* Classic TLV parsing doesn't work well with SW_DESCR because of it's
* nested nature and the fact you have to assume it contains only two sub
* tags NM_ATT_FILE_VERSION & NM_ATT_FILE_ID to parse it */
if (sw_descr[0] != NM_ATT_SW_DESCR) {
DEBUGP(DNM, "SW_DESCR attribute identifier not found!\n");
return -1;
}
ofs += 1;
len = tlv_parse_one(&tag, &tag_len, &val,
&sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
if (len < 0 || (tag != NM_ATT_FILE_ID)) {
DEBUGP(DNM, "FILE_ID attribute identifier not found!\n");
return -2;
}
ofs += len;
len = tlv_parse_one(&tag, &tag_len, &val,
&sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
if (len < 0 || (tag != NM_ATT_FILE_VERSION)) {
DEBUGP(DNM, "FILE_VERSION attribute identifier not found!\n");
return -3;
}
ofs += len;
return ofs;
}
static int abis_nm_rx_sw_act_req(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 u_int8_t *sw_config;
int sw_config_len;
int file_id_len;
int ret;
int ret, sw_config_len, sw_descr_len;
debugp_foh(foh);
@@ -854,20 +895,16 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
DEBUGP(DNM, "Found SW config: %s\n", hexdump(sw_config, sw_config_len));
}
if (sw_config[0] != NM_ATT_SW_DESCR)
DEBUGP(DNM, "SW_DESCR attribute identifier not found!\n");
if (sw_config[1] != NM_ATT_FILE_ID)
DEBUGP(DNM, "FILE_ID attribute identifier not found!\n");
file_id_len = sw_config[2] * 256 + sw_config[3];
/* Use the first SW_DESCR present in SW config */
sw_descr_len = abis_nm_parse_sw_descr(sw_config, sw_config_len);
if (sw_descr_len < 0)
return -EINVAL;
/* Assumes first SW file in list is the one to be activated */
/* sw_config + 4 to skip over 2 attribute ID bytes and 16-bit length field */
return ipacc_sw_activate(mb->trx->bts, foh->obj_class,
foh->obj_inst.bts_nr,
foh->obj_inst.trx_nr,
foh->obj_inst.ts_nr,
sw_config + 4,
file_id_len);
sw_config, sw_descr_len);
}
/* Receive a CHANGE_ADM_STATE_ACK, parse the TLV and update local state */

View File

@@ -845,6 +845,7 @@ static int rsl_rx_conn_fail(struct msgb *msg)
LOGPC(DRSL, LOGL_NOTICE, "\n");
/* FIXME: only free it after channel release ACK */
counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
return rsl_rf_chan_release(msg->lchan, 1);
}
@@ -1139,6 +1140,7 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
struct gsm_lchan *lchan;
u_int8_t rqd_ta;
int ret;
int is_lu;
u_int16_t arfcn;
u_int8_t ts_number, subch;
@@ -1161,8 +1163,14 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
counter_inc(bts->network->stats.chreq.total);
/*
* We want LOCATION UPDATES to succeed and will assign a TCH
* if we have no SDCCH available.
*/
is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
/* check availability / allocate channel */
lchan = lchan_alloc(bts, lctype);
lchan = lchan_alloc(bts, lctype, is_lu);
if (!lchan) {
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);
@@ -1232,6 +1240,10 @@ static int rsl_rx_ccch_load(struct msgb *msg)
switch (rslh->data[0]) {
case RSL_IE_PAGING_LOAD:
pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
if (is_ipaccess_bts(msg->trx->bts) && pg_buf_space == 0xffff) {
/* paging load below configured threshold, use 50 as default */
pg_buf_space = 50;
}
paging_update_buffer_space(msg->trx->bts, pg_buf_space);
break;
case RSL_IE_RACH_LOAD:
@@ -1291,8 +1303,10 @@ static int rsl_rx_rll_err_ind(struct msgb *msg)
rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED)
if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
return rsl_rf_chan_release(msg->lchan, 1);
}
return 0;
}

View File

@@ -7,6 +7,7 @@ line vty
no login
!
nat
msc ip 10.0.0.23
bsc 0
token zecke
location_area_code 3

View File

@@ -31,6 +31,7 @@
#include <openbsc/system_information.h>
#include <openbsc/paging.h>
#include <openbsc/signal.h>
#include <openbsc/chan_alloc.h>
#include <osmocore/talloc.h>
/* global pointer to the gsm network data structure */
@@ -377,11 +378,11 @@ static unsigned char nanobts_attr_cell[] = {
4, /* N3103 */
8, /* N3105 */
15, /* RLC CV countdown */
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00,
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */
NM_ATT_IPACC_RLC_CFG_2, 0, 5,
0x00, 250,
0x00, 250,
2, /* MCS2 */
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 */
@@ -463,7 +464,7 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
break;
case NM_OC_GPRS_NSE:
bts = container_of(obj, struct gsm_bts, gprs.nse);
if (!bts->gprs.enabled)
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == 5) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
@@ -477,7 +478,7 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
break;
case NM_OC_GPRS_CELL:
bts = container_of(obj, struct gsm_bts, gprs.cell);
if (!bts->gprs.enabled)
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == 5) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
@@ -492,7 +493,7 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
case NM_OC_GPRS_NSVC:
nsvc = obj;
bts = nsvc->bts;
if (!bts->gprs.enabled)
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
/* We skip NSVC1 since we only use NSVC0 */
if (nsvc->id == 1)
@@ -800,7 +801,7 @@ static int set_system_infos(struct gsm_bts_trx *trx)
DEBUGP(DRR, "SI%2u: %s\n", i, hexdump(si_tmp, rc));
rsl_bcch_info(trx, i, si_tmp, sizeof(si_tmp));
}
if (bts->gprs.enabled) {
if (bts->gprs.mode != BTS_GPRS_NONE) {
i = 13;
rc = gsm_generate_si(si_tmp, trx->bts, RSL_SYSTEM_INFO_13);
if (rc < 0)
@@ -887,6 +888,11 @@ static void patch_nm_tables(struct gsm_bts *bts)
/* 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;
}
}
static void bootstrap_rsl(struct gsm_bts_trx *trx)
@@ -901,6 +907,8 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx)
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
{
int ts_no, lchan_no;
switch (event) {
case EVT_E1_TEI_UP:
switch (type) {
@@ -915,8 +923,35 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
}
break;
case EVT_E1_TEI_DN:
LOGP(DMI, LOGL_NOTICE, "Lost some E1 TEI link\n");
/* FIXME: deal with TEI or L1 link loss */
LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", type, trx);
if (type == E1INP_SIGN_OML)
counter_inc(trx->bts->network->stats.bts.oml_fail);
else if (type == E1INP_SIGN_RSL)
counter_inc(trx->bts->network->stats.bts.rsl_fail);
/*
* free all allocated channels. change the nm_state so the
* trx and trx_ts becomes unusable and chan_alloc.c can not
* allocate from it.
*/
for (ts_no = 0; ts_no < ARRAY_SIZE(trx->ts); ++ts_no) {
struct gsm_bts_trx_ts *ts = &trx->ts[ts_no];
for (lchan_no = 0; lchan_no < ARRAY_SIZE(ts->lchan); ++lchan_no) {
if (ts->lchan[lchan_no].state != GSM_LCHAN_NONE)
lchan_free(&ts->lchan[lchan_no]);
lchan_reset(&ts->lchan[lchan_no]);
}
ts->nm_state.operational = 0;
ts->nm_state.availability = 0;
}
trx->nm_state.operational = 0;
trx->nm_state.availability = 0;
trx->bb_transc.nm_state.operational = 0;
trx->bb_transc.nm_state.availability = 0;
break;
default:
break;

View File

@@ -1,4 +1,4 @@
/* A hackish minimal BSC (+MSC +HLR) implementation */
/* The BSC Process to handle GSM08.08 (A-Interface) */
/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
@@ -44,6 +44,7 @@
#include <openbsc/chan_alloc.h>
#include <openbsc/bsc_msc.h>
#include <openbsc/bsc_nat.h>
#include <openbsc/bsc_msc_rf.h>
#include <osmocore/select.h>
#include <osmocore/talloc.h>
@@ -58,16 +59,23 @@
static struct log_target *stderr_target;
struct gsm_network *bsc_gsmnet = 0;
static const char *config_file = "openbsc.cfg";
static char *msc_address = "127.0.0.1";
static char *msc_address = NULL;
static struct bsc_msc_connection *msc_con;
static struct in_addr local_addr;
static LLIST_HEAD(active_connections);
static struct write_queue mgcp_agent;
static const char *rf_ctl = NULL;
extern int ipacc_rtp_direct;
extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, int, void *), const char *cfg_file);
extern int bsc_shutdown_net(struct gsm_network *net);
struct llist_head *bsc_sccp_connections()
{
return &active_connections;
}
struct bss_sccp_connection_data *bss_sccp_create_data()
{
struct bss_sccp_connection_data *data;
@@ -217,7 +225,7 @@ static int open_sccp_connection(struct msgb *layer3)
struct msgb *data;
/* When not connected to a MSC. We will simply close things down. */
if (!msc_con->is_connected) {
if (!msc_con->is_authenticated) {
LOGP(DMSC, LOGL_ERROR, "Not connected to a MSC. Not forwarding data.\n");
use_subscr_con(&layer3->lchan->conn);
put_subscr_con(&layer3->lchan->conn, 0);
@@ -364,7 +372,8 @@ static int handle_ass_compl(struct msgb *msg)
old_chan->msc_data = NULL;
/* give up the old channel to not do a SACCH deactivate */
subscr_put(old_chan->conn.subscr);
if (old_chan->conn.subscr)
subscr_put(old_chan->conn.subscr);
old_chan->conn.subscr = NULL;
put_subscr_con(&old_chan->conn, 1);
@@ -568,7 +577,7 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
static void print_usage()
{
printf("Usage: bsc_hack\n");
printf("Usage: bsc_msc_ip\n");
}
/*
@@ -762,18 +771,10 @@ static int msc_sccp_read(struct msgb *msgb, unsigned int length, void *data)
*/
static void initialize_if_needed(void)
{
if (!bsc_gsmnet) {
int rc;
struct msgb *msg;
fprintf(stderr, "Bootstraping the network. Sending GSM08.08 reset.\n");
rc = bsc_bootstrap_network(NULL, config_file);
if (rc < 0) {
fprintf(stderr, "Bootstrapping the network failed. exiting.\n");
exit(1);
}
struct msgb *msg;
if (!msc_con->is_authenticated) {
/* send a gsm 08.08 reset message from here */
msg = bssmap_create_reset();
if (!msg) {
@@ -783,6 +784,7 @@ static void initialize_if_needed(void)
sccp_write(msg, &sccp_ssn_bssap, &sccp_ssn_bssap, 0);
msgb_free(msg);
msc_con->is_authenticated = 1;
}
}
@@ -839,6 +841,7 @@ static void msc_connection_was_lost(struct bsc_msc_connection *msc)
bss_sccp_free_data(bss);
}
msc->is_authenticated = 0;
bsc_msc_schedule_connect(msc);
}
@@ -896,6 +899,7 @@ static void print_help()
printf(" -m --msc=IP. The address of the MSC.\n");
printf(" -l --local=IP. The local address of the MGCP.\n");
printf(" -e --log-level number. Set a global loglevel.\n");
printf(" -r --rf-ctl NAME. A unix domain socket to listen for cmds.\n");
}
static void handle_options(int argc, char** argv)
@@ -908,14 +912,14 @@ static void handle_options(int argc, char** argv)
{"config-file", 1, 0, 'c'},
{"disable-color", 0, 0, 's'},
{"timestamp", 0, 0, 'T'},
{"rtp-proxy", 0, 0, 'P'},
{"msc", 1, 0, 'm'},
{"local", 1, 0, 'l'},
{"log-level", 1, 0, 'e'},
{"rf-ctl", 1, 0, 'r'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hd:sTPc:m:l:e:",
c = getopt_long(argc, argv, "hd:sTc:m:l:e:r:",
long_options, &option_index);
if (c == -1)
break;
@@ -941,7 +945,7 @@ static void handle_options(int argc, char** argv)
ipacc_rtp_direct = 0;
break;
case 'm':
msc_address = strdup(optarg);
msc_address = optarg;
break;
case 'l':
inet_aton(optarg, &local_addr);
@@ -949,6 +953,9 @@ static void handle_options(int argc, char** argv)
case 'e':
log_set_log_level(stderr_target, atoi(optarg));
break;
case 'r':
rf_ctl = optarg;
break;
default:
/* ignore */
break;
@@ -975,7 +982,7 @@ static void signal_handler(int signal)
talloc_report_full(tall_bsc_ctx, stderr);
break;
case SIGUSR2:
if (!msc_con->is_connected)
if (!msc_con || !msc_con->is_connected)
return;
bsc_msc_lost(msc_con);
break;
@@ -1030,6 +1037,9 @@ extern int bts_model_nanobts_init(void);
int main(int argc, char **argv)
{
char *msc;
int rc;
log_init(&log_info);
tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
stderr_target = log_target_create_stderr();
@@ -1048,6 +1058,12 @@ int main(int argc, char **argv)
/* seed the PRNG */
srand(time(NULL));
signal(SIGINT, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGUSR2, &signal_handler);
signal(SIGPIPE, SIG_IGN);
/* attempt to register the local mgcp forward */
if (mgcp_create_port() != 0) {
fprintf(stderr, "Failed to bind local MGCP port\n");
@@ -1062,9 +1078,28 @@ int main(int argc, char **argv)
/* initialize ipaccess handling */
register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
fprintf(stderr, "Bootstraping the network. Sending GSM08.08 reset.\n");
rc = bsc_bootstrap_network(NULL, config_file);
if (rc < 0) {
fprintf(stderr, "Bootstrapping the network failed. exiting.\n");
exit(1);
}
if (rf_ctl) {
struct bsc_msc_rf *rf;
rf = bsc_msc_rf_create(rf_ctl, bsc_gsmnet);
if (!rf) {
fprintf(stderr, "Failed to create the RF service.\n");
exit(1);
}
}
/* setup MSC Connection handling */
msc_con = bsc_msc_create(msc_address, 5000);
msc = bsc_gsmnet->msc_ip;
if (msc_address)
msc = msc_address;
msc_con = bsc_msc_create(msc, bsc_gsmnet->msc_port);
if (!msc_con) {
fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
exit(1);
@@ -1076,11 +1111,6 @@ int main(int argc, char **argv)
bsc_msc_connect(msc_con);
signal(SIGINT, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGUSR2, &signal_handler);
signal(SIGPIPE, SIG_IGN);
while (1) {
bsc_select_main(0);

249
openbsc/src/bsc_msc_rf.c Normal file
View File

@@ -0,0 +1,249 @@
/* RF Ctl handling socket */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 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 General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <openbsc/bsc_msc_rf.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <osmocore/talloc.h>
#include <osmocore/protocol/gsm_12_21.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <unistd.h>
#define RF_CMD_QUERY '?'
#define RF_CMD_OFF '0'
#define RF_CMD_ON '1'
static int lock_each_trx(struct gsm_network *net, int lock)
{
struct gsm_bts *bts;
llist_for_each_entry(bts, &net->bts_list, list) {
struct gsm_bts_trx *trx;
llist_for_each_entry(trx, &bts->trx_list, list) {
gsm_trx_lock_rf(trx, lock);
}
}
return 0;
}
/*
* Send a '1' when one TRX is online, otherwise send 0
*/
static void handle_query(struct bsc_msc_rf_conn *conn)
{
struct msgb *msg;
struct gsm_bts *bts;
char send = '0';
llist_for_each_entry(bts, &conn->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 = '1';
break;
}
}
}
msg = msgb_alloc(10, "RF Query");
if (!msg) {
LOGP(DINP, LOGL_ERROR, "Failed to allocate response msg.\n");
return;
}
msg->l2h = msgb_put(msg, 1);
msg->l2h[0] = send;
if (write_queue_enqueue(&conn->queue, msg) != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to enqueue the answer.\n");
msgb_free(msg);
return;
}
return;
}
static int rf_read_cmd(struct bsc_fd *fd)
{
struct bsc_msc_rf_conn *conn = fd->data;
char buf[1];
int rc;
rc = read(fd->fd, buf, sizeof(buf));
if (rc != sizeof(buf)) {
LOGP(DINP, LOGL_ERROR, "Short read %d/%s\n", errno, strerror(errno));
bsc_unregister_fd(fd);
close(fd->fd);
write_queue_clear(&conn->queue);
talloc_free(conn);
return -1;
}
switch (buf[0]) {
case RF_CMD_QUERY:
handle_query(conn);
break;
case RF_CMD_OFF:
lock_each_trx(conn->gsm_network, 1);
break;
case RF_CMD_ON:
lock_each_trx(conn->gsm_network, 0);
break;
default:
LOGP(DINP, LOGL_ERROR, "Unknown command %d\n", buf[0]);
break;
}
return 0;
}
static int rf_write_cmd(struct bsc_fd *fd, struct msgb *msg)
{
int rc;
rc = write(fd->fd, msg->data, msg->len);
if (rc != msg->len) {
LOGP(DINP, LOGL_ERROR, "Short write %d/%s\n", errno, strerror(errno));
return -1;
}
return 0;
}
static int rf_ctl_accept(struct bsc_fd *bfd, unsigned int what)
{
struct bsc_msc_rf_conn *conn;
struct bsc_msc_rf *rf = bfd->data;
struct sockaddr_un addr;
socklen_t len = sizeof(addr);
int fd;
fd = accept(bfd->fd, (struct sockaddr *) &addr, &len);
if (fd < 0) {
LOGP(DINP, LOGL_ERROR, "Failed to accept. errno: %d/%s\n",
errno, strerror(errno));
return -1;
}
conn = talloc_zero(rf, struct bsc_msc_rf_conn);
if (!conn) {
LOGP(DINP, LOGL_ERROR, "Failed to allocate mem.\n");
close(fd);
return -1;
}
write_queue_init(&conn->queue, 10);
conn->queue.bfd.data = conn;
conn->queue.bfd.fd = fd;
conn->queue.bfd.when = BSC_FD_READ | BSC_FD_WRITE;
conn->queue.read_cb = rf_read_cmd;
conn->queue.write_cb = rf_write_cmd;
conn->gsm_network = rf->gsm_network;
if (bsc_register_fd(&conn->queue.bfd) != 0) {
close(fd);
talloc_free(conn);
return -1;
}
return 0;
}
struct bsc_msc_rf *bsc_msc_rf_create(const char *path, struct gsm_network *net)
{
unsigned int namelen;
struct sockaddr_un local;
struct bsc_fd *bfd;
struct bsc_msc_rf *rf;
int rc;
rf = talloc_zero(NULL, struct bsc_msc_rf);
if (!rf) {
LOGP(DINP, LOGL_ERROR, "Failed to create bsc_msc_rf.\n");
return NULL;
}
bfd = &rf->listen;
bfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (bfd->fd < 0) {
LOGP(DINP, LOGL_ERROR, "Can not create socket. %d/%s\n",
errno, strerror(errno));
return NULL;
}
local.sun_family = AF_UNIX;
strncpy(local.sun_path, path, sizeof(local.sun_path));
local.sun_path[sizeof(local.sun_path) - 1] = '\0';
unlink(local.sun_path);
/* we use the same magic that X11 uses in Xtranssock.c for
* calculating the proper length of the sockaddr */
#if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
local.sun_len = strlen(local.sun_path);
#endif
#if defined(BSD44SOCKETS) || defined(SUN_LEN)
namelen = SUN_LEN(&local);
#else
namelen = strlen(local.sun_path) +
offsetof(struct sockaddr_un, sun_path);
#endif
rc = bind(bfd->fd, (struct sockaddr *) &local, namelen);
if (rc != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to bind '%s' errno: %d/%s\n",
local.sun_path, errno, strerror(errno));
close(bfd->fd);
talloc_free(rf);
return NULL;
}
if (listen(bfd->fd, 0) != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to listen: %d/%s\n", errno, strerror(errno));
close(bfd->fd);
talloc_free(rf);
return NULL;
}
bfd->when = BSC_FD_READ;
bfd->cb = rf_ctl_accept;
bfd->data = rf;
if (bsc_register_fd(bfd) != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to register bfd.\n");
close(bfd->fd);
talloc_free(rf);
return NULL;
}
rf->gsm_network = net;
return rf;
}

View File

@@ -29,7 +29,7 @@
#include <openbsc/paging.h>
#include <openbsc/chan_alloc.h>
#include <osmocore/tlv.h>
#include <osmocore/gsm0808.h>
#include <sccp/sccp.h>
@@ -44,34 +44,6 @@ static void bts_queue_send(struct msgb *msg, int link_id);
static void bssmap_free_secondary(struct bss_sccp_connection_data *data);
static const struct tlv_definition bss_att_tlvdef = {
.def = {
[GSM0808_IE_IMSI] = { TLV_TYPE_TLV },
[GSM0808_IE_TMSI] = { TLV_TYPE_TLV },
[GSM0808_IE_CELL_IDENTIFIER_LIST] = { TLV_TYPE_TLV },
[GSM0808_IE_CHANNEL_NEEDED] = { TLV_TYPE_TV },
[GSM0808_IE_EMLPP_PRIORITY] = { TLV_TYPE_TV },
[GSM0808_IE_CHANNEL_TYPE] = { TLV_TYPE_TLV },
[GSM0808_IE_PRIORITY] = { TLV_TYPE_TLV },
[GSM0808_IE_CIRCUIT_IDENTITY_CODE] = { TLV_TYPE_TV },
[GSM0808_IE_DOWNLINK_DTX_FLAG] = { TLV_TYPE_TV },
[GSM0808_IE_INTERFERENCE_BAND_TO_USE] = { TLV_TYPE_TV },
[GSM0808_IE_CLASSMARK_INFORMATION_T2] = { TLV_TYPE_TLV },
[GSM0808_IE_GROUP_CALL_REFERENCE] = { TLV_TYPE_TLV },
[GSM0808_IE_TALKER_FLAG] = { TLV_TYPE_T },
[GSM0808_IE_CONFIG_EVO_INDI] = { TLV_TYPE_TV },
[GSM0808_IE_LSA_ACCESS_CTRL_SUPPR] = { TLV_TYPE_TV },
[GSM0808_IE_SERVICE_HANDOVER] = { TLV_TYPE_TV},
[GSM0808_IE_ENCRYPTION_INFORMATION] = { TLV_TYPE_TLV },
[GSM0808_IE_CIPHER_RESPONSE_MODE] = { TLV_TYPE_TV },
},
};
const struct tlv_definition *gsm0808_att_tlvdef()
{
return &bss_att_tlvdef;
}
static u_int16_t get_network_code_for_msc(struct gsm_network *net)
{
if (net->core_network_code > 0)
@@ -88,7 +60,7 @@ static u_int16_t get_country_code_for_msc(struct gsm_network *net)
static int bssmap_paging_cb(unsigned int hooknum, unsigned int event, struct msgb *msg, void *data, void *param)
{
LOGP(DMSC, LOGL_DEBUG, "Paging is complete.\n");
LOGP(DPAG, LOGL_DEBUG, "Paging is complete.\n");
return 0;
}
@@ -112,7 +84,7 @@ static int bssmap_handle_paging(struct gsm_network *net, struct msgb *msg, unsig
u_int8_t chan_needed = RSL_CHANNEED_ANY;
int paged;
tlv_parse(&tp, &bss_att_tlvdef, msg->l4h + 1, payload_length - 1, 0, 0);
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");
@@ -173,7 +145,7 @@ static int bssmap_handle_paging(struct gsm_network *net, struct msgb *msg, unsig
subscr->tmsi = tmsi;
subscr->lac = lac;
paged = paging_request(net, subscr, chan_needed, bssmap_paging_cb, subscr);
LOGP(DMSC, LOGL_DEBUG, "Paged IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x on #bts: %d\n", mi_string, tmsi, tmsi, lac, paged);
LOGP(DPAG, LOGL_DEBUG, "Paged IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x on #bts: %d\n", mi_string, tmsi, tmsi, lac, paged);
subscr_put(subscr);
return -1;
@@ -242,7 +214,7 @@ static int bssmap_handle_cipher_mode(struct sccp_connection *conn,
msg->lchan->msc_data->ciphering_handled = 1;
msg->lchan->msc_data->block_gsm = 1;
tlv_parse(&tp, &bss_att_tlvdef, msg->l4h + 1, payload_length - 1, 0, 0);
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;
@@ -317,7 +289,8 @@ static void bssmap_free_secondary(struct bss_sccp_connection_data *data)
lchan->msc_data = NULL;
/* give up the new channel to not do a SACCH deactivate */
subscr_put(lchan->conn.subscr);
if (lchan->conn.subscr)
subscr_put(lchan->conn.subscr);
lchan->conn.subscr = NULL;
put_subscr_con(&lchan->conn, 1);
}
@@ -431,7 +404,7 @@ static int handle_new_assignment(struct msgb *msg, int full_rate, int chan_mode)
bts = msg->lchan->ts->trx->bts;
chan_type = full_rate ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H;
new_lchan = lchan_alloc(bts, chan_type);
new_lchan = lchan_alloc(bts, chan_type, 0);
if (!new_lchan) {
LOGP(DMSC, LOGL_NOTICE, "No free channel.\n");
@@ -442,7 +415,8 @@ static int handle_new_assignment(struct msgb *msg, int full_rate, int chan_mode)
memcpy(&new_lchan->encr, &msg->lchan->encr, sizeof(new_lchan->encr));
new_lchan->ms_power = msg->lchan->ms_power;
new_lchan->bs_power = msg->lchan->bs_power;
new_lchan->conn.subscr = subscr_get(msg->lchan->conn.subscr);
if (msg->lchan->conn.subscr)
new_lchan->conn.subscr = subscr_get(msg->lchan->conn.subscr);
/* copy new data to it */
use_subscr_con(&new_lchan->conn);
@@ -515,7 +489,7 @@ static int bssmap_handle_assignm_req(struct sccp_connection *conn,
msc_data = msg->lchan->msc_data;
network = msg->lchan->ts->trx->bts->network;
tlv_parse(&tp, &bss_att_tlvdef, msg->l4h + 1, length - 1, 0, 0);
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");

View File

@@ -223,7 +223,8 @@ _lc_find_bts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan)
}
/* Allocate a logical channel */
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type,
int allow_bigger)
{
struct gsm_lchan *lchan = NULL;
enum gsm_phys_chan_config first, second;
@@ -241,6 +242,19 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
lchan = _lc_find_bts(bts, first);
if (lchan == NULL)
lchan = _lc_find_bts(bts, second);
/* allow to assign bigger channels */
if (allow_bigger) {
if (lchan == NULL) {
lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_H);
type = GSM_LCHAN_TCH_H;
}
if (lchan == NULL) {
lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
type = GSM_LCHAN_TCH_F;
}
}
break;
case GSM_LCHAN_TCH_F:
lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
@@ -322,6 +336,21 @@ void lchan_free(struct gsm_lchan *lchan)
* channel using it */
}
/*
* There was an error with the TRX and we need to forget
* any state so that a lchan can be allocated again after
* the trx is fully usable.
*/
void lchan_reset(struct gsm_lchan *lchan)
{
bsc_del_timer(&lchan->T3101);
bsc_del_timer(&lchan->T3111);
bsc_del_timer(&lchan->error_timer);
lchan->type = GSM_LCHAN_NONE;
lchan->state = LCHAN_S_NONE;
}
static int _lchan_release_next_sapi(struct gsm_lchan *lchan)
{
int sapi;
@@ -360,6 +389,7 @@ static void _lchan_handle_release(struct gsm_lchan *lchan)
lchan->conn.use_count);
rsl_release_request(lchan, 0, lchan->release_reason);
rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ);
}
/* called from abis rsl */

View File

@@ -420,7 +420,17 @@ e1inp_sign_link_create(struct e1inp_ts *ts, enum e1inp_sign_type type,
void e1inp_sign_link_destroy(struct e1inp_sign_link *link)
{
struct msgb *msg;
llist_del(&link->list);
while (!llist_empty(&link->tx_list)) {
msg = msgb_dequeue(&link->tx_list);
msgb_free(msg);
}
if (link->ts->type == E1INP_TS_TYPE_SIGN)
bsc_del_timer(&link->ts->sign.tx_timer);
talloc_free(link);
}

View File

@@ -281,6 +281,10 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c
net->stats.call.dialled = counter_alloc("net.call.dialled");
net->stats.call.alerted = counter_alloc("net.call.alerted");
net->stats.call.connected = counter_alloc("net.call.connected");
net->stats.chan.rf_fail = counter_alloc("net.chan.rf_fail");
net->stats.chan.rll_err = counter_alloc("net.chan.rll_err");
net->stats.bts.oml_fail = counter_alloc("net.bts.oml_fail");
net->stats.bts.rsl_fail = counter_alloc("net.bts.rsl_fail");
net->mncc_recv = mncc_recv;
@@ -290,6 +294,9 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c
net->core_network_code = -1;
net->rtp_base_port = 4000;
net->msc_ip = talloc_strdup(net, "127.0.0.1");
net->msc_port = 5000;
return net;
}
@@ -505,6 +512,23 @@ const char *rrlp_mode_name(enum rrlp_mode mode)
return get_value_string(rrlp_mode_names, mode);
}
static const struct value_string bts_gprs_mode_names[] = {
{ BTS_GPRS_NONE, "none" },
{ BTS_GPRS_GPRS, "gprs" },
{ BTS_GPRS_EGPRS, "egprs" },
{ 0, NULL }
};
enum bts_gprs_mode bts_gprs_mode_parse(const char *arg)
{
return get_string_value(bts_gprs_mode_names, arg);
}
const char *bts_gprs_mode_name(enum bts_gprs_mode mode)
{
return get_value_string(bts_gprs_mode_names, mode);
}
struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
{
struct gsm_meas_rep *meas_rep;

View File

@@ -99,7 +99,7 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts)
counter_inc(bts->network->stats.handover.attempted);
new_lchan = lchan_alloc(bts, old_lchan->type);
new_lchan = lchan_alloc(bts, old_lchan->type, 0);
if (!new_lchan) {
LOGP(DHO, LOGL_NOTICE, "No free channel\n");
counter_inc(bts->network->stats.handover.no_channel);
@@ -230,7 +230,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
/* update lchan pointer of transaction */
trans_lchan_change(&ho->old_lchan->conn, &new_lchan->conn);
ho->old_lchan->state = LCHAN_S_INACTIVE;
rsl_lchan_set_state(ho->old_lchan, LCHAN_S_INACTIVE);
/* do something to re-route the actual speech frames ! */

View File

@@ -1,6 +1,8 @@
/* OpenBSC Abis input driver for ip.access */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by Holger Hans Peter Freyther
* (C) 2010 by On-Waves
*
* All Rights Reserved
*
@@ -234,6 +236,8 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
}
DEBUGP(DINP, "Identified BTS %u/%u/%u\n", site_id, bts_id, trx_id);
if (bfd->priv_nr == PRIV_OML) {
/* drop any old oml connection */
ipaccess_drop_oml(bts);
bts->oml_link = e1inp_sign_link_create(&line->ts[PRIV_OML - 1],
E1INP_SIGN_OML, bts->c0,
bts->oml_tei, 0);
@@ -241,7 +245,18 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
struct e1inp_ts *e1i_ts;
struct bsc_fd *newbfd;
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, trx_id);
/* drop any old rsl connection */
ipaccess_drop_rsl(trx);
if (!bts->oml_link) {
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
talloc_free(bfd);
return 0;
}
bfd->data = line = bts->oml_link->ts->line;
e1i_ts = &line->ts[PRIV_RSL + trx_id - 1];
newbfd = &e1i_ts->driver.ipaccess.fd;
@@ -251,19 +266,13 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
E1INP_SIGN_RSL, trx,
trx->rsl_tei, 0);
if (newbfd->fd >= 0) {
LOGP(DINP, LOGL_ERROR, "BTS is still registered. Closing old connection.\n");
bsc_unregister_fd(newbfd);
close(newbfd->fd);
newbfd->fd = -1;
}
/* get rid of our old temporary bfd */
memcpy(newbfd, bfd, sizeof(*newbfd));
newbfd->priv_nr = PRIV_RSL + trx_id;
bsc_unregister_fd(bfd);
bsc_register_fd(newbfd);
bfd->fd = -1;
talloc_free(bfd);
bsc_register_fd(newbfd);
}
break;
}
@@ -328,6 +337,103 @@ struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
return msg;
}
int ipaccess_drop_oml(struct gsm_bts *bts)
{
struct gsm_bts_trx *trx;
struct e1inp_ts *ts;
struct e1inp_line *line;
struct bsc_fd *bfd;
if (!bts || !bts->oml_link)
return -1;
/* send OML down */
ts = bts->oml_link->ts;
line = ts->line;
e1inp_event(ts, EVT_E1_TEI_DN, bts->oml_link->tei, bts->oml_link->sapi);
bfd = &ts->driver.ipaccess.fd;
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
/* clean up OML and RSL */
e1inp_sign_link_destroy(bts->oml_link);
bts->oml_link = NULL;
bts->ip_access.flags = 0;
/* drop all RSL connections too */
llist_for_each_entry(trx, &bts->trx_list, list)
ipaccess_drop_rsl(trx);
/* kill the E1 line now... as we have no one left to use it */
talloc_free(line);
return -1;
}
static int ipaccess_drop(struct e1inp_ts *ts, struct bsc_fd *bfd)
{
struct e1inp_sign_link *link;
int bts_nr;
if (!ts) {
/*
* If we don't have a TS this means that this is a RSL
* connection but we are not past the authentication
* handling yet. So we can safely delete this bfd and
* wait for a reconnect.
*/
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
talloc_free(bfd);
return -1;
}
/* attempt to find a signalling link */
if (ts->type == E1INP_TS_TYPE_SIGN) {
llist_for_each_entry(link, &ts->sign.sign_links, list) {
bts_nr = link->trx->bts->bts_nr;
/* we have issues just reconnecting RLS so we drop OML */
ipaccess_drop_oml(link->trx->bts);
return bts_nr;
}
}
/* error case */
LOGP(DINP, LOGL_ERROR, "Failed to find a signalling link for ts: %p\n", ts);
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
return -1;
}
int ipaccess_drop_rsl(struct gsm_bts_trx *trx)
{
struct bsc_fd *bfd;
struct e1inp_ts *ts;
if (!trx || !trx->rsl_link)
return -1;
/* send RSL down */
ts = trx->rsl_link->ts;
e1inp_event(ts, EVT_E1_TEI_DN, trx->rsl_link->tei, trx->rsl_link->sapi);
/* close the socket */
bfd = &ts->driver.ipaccess.fd;
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
/* destroy */
e1inp_sign_link_destroy(trx->rsl_link);
trx->rsl_link = NULL;
return -1;
}
static int handle_ts1_read(struct bsc_fd *bfd)
{
struct e1inp_line *line = bfd->data;
@@ -341,18 +447,12 @@ static int handle_ts1_read(struct bsc_fd *bfd)
msg = ipaccess_read_msg(bfd, &error);
if (!msg) {
if (error == 0) {
link = e1inp_lookup_sign_link(e1i_ts, IPAC_PROTO_OML, 0);
if (link) {
link->trx->bts->ip_access.flags = 0;
int ret = ipaccess_drop(e1i_ts, bfd);
if (ret >= 0)
LOGP(DINP, LOGL_NOTICE, "BTS %u disappeared, dead socket\n",
link->trx->bts->nr);
} else
ret);
else
LOGP(DINP, LOGL_NOTICE, "unknown BTS disappeared, dead socket\n");
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_RSL);
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_OML);
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
}
return error;
}
@@ -362,13 +462,8 @@ static int handle_ts1_read(struct bsc_fd *bfd)
hh = (struct ipaccess_head *) msg->data;
if (hh->proto == IPAC_PROTO_IPACCESS) {
ret = ipaccess_rcvmsg(line, msg, bfd);
if (ret < 0) {
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_RSL);
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_OML);
bsc_unregister_fd(bfd);
close(bfd->fd);
bfd->fd = -1;
}
if (ret < 0)
ipaccess_drop(e1i_ts, bfd);
msgb_free(msg);
return ret;
}
@@ -477,7 +572,8 @@ static int handle_ts1_write(struct bsc_fd *bfd)
e1i_ts->sign.tx_timer.data = e1i_ts;
/* Reducing this might break the nanoBTS 900 init. */
bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, 100000);
/* BAND AID for paging problem */
bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, 100);
return ret;
}

View File

@@ -33,6 +33,8 @@
#include <vty/command.h>
#include <vty/vty.h>
#include <string.h>
static struct mgcp_config *g_cfg = NULL;
/*
@@ -48,23 +50,25 @@ static int config_write_mgcp(struct vty *vty)
{
vty_out(vty, "mgcp%s", VTY_NEWLINE);
if (g_cfg->local_ip)
vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
if (g_cfg->bts_ip)
vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
if (g_cfg->bts_ip && strlen(g_cfg->bts_ip) != 0)
vty_out(vty, " bts ip %s%s", g_cfg->bts_ip, VTY_NEWLINE);
vty_out(vty, " bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
vty_out(vty, " bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
vty_out(vty, " bind early %u%s", !!g_cfg->early_bind, VTY_NEWLINE);
vty_out(vty, " rtp base %u%s", g_cfg->rtp_base_port, VTY_NEWLINE);
vty_out(vty, " sdp audio payload number %u%s", g_cfg->audio_payload, VTY_NEWLINE);
vty_out(vty, " sdp audio payload name %s%s", g_cfg->audio_name, VTY_NEWLINE);
if (g_cfg->audio_payload != -1)
vty_out(vty, " sdp audio payload number %d%s", g_cfg->audio_payload, VTY_NEWLINE);
if (g_cfg->audio_name)
vty_out(vty, " sdp audio payload name %s%s", g_cfg->audio_name, VTY_NEWLINE);
vty_out(vty, " loop %u%s", !!g_cfg->audio_loop, VTY_NEWLINE);
vty_out(vty, " endpoints %u%s", g_cfg->number_endpoints, VTY_NEWLINE);
vty_out(vty, " number endpoints %u%s", g_cfg->number_endpoints - 1, VTY_NEWLINE);
if (g_cfg->forward_ip)
vty_out(vty, " forward audio ip %s%s", g_cfg->forward_ip, VTY_NEWLINE);
vty_out(vty, " forward audio ip %s%s", g_cfg->forward_ip, VTY_NEWLINE);
if (g_cfg->forward_port != 0)
vty_out(vty, " forward audio port %d%s", g_cfg->forward_port, VTY_NEWLINE);
vty_out(vty, " forward audio port %d%s", g_cfg->forward_port, VTY_NEWLINE);
if (g_cfg->call_agent_addr)
vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
return CMD_SUCCESS;
}

View File

@@ -27,6 +27,7 @@
#include <openbsc/mgcp_internal.h>
#include <osmocore/talloc.h>
#include <osmocore/gsm0808.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -91,8 +92,9 @@ void bsc_mgcp_free_endpoints(struct bsc_nat *nat)
bsc_mgcp_free_endpoint(nat, i);
}
struct bsc_connection *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
struct sccp_connections *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
{
struct sccp_connections *con = NULL;
struct sccp_connections *sccp;
llist_for_each_entry(sccp, &nat->sccp_connections, list_entry) {
@@ -101,9 +103,12 @@ struct bsc_connection *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
if (mgcp_timeslot_to_endpoint(0, sccp->msc_timeslot) != endpoint)
continue;
return sccp->bsc;
con = sccp;
}
if (con)
return con;
LOGP(DMGCP, LOGL_ERROR, "Failed to find the connection.\n");
return NULL;
}
@@ -112,7 +117,7 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
{
struct bsc_nat *nat;
struct bsc_endpoint *bsc_endp;
struct bsc_connection *bsc_con;
struct sccp_connections *sccp;
struct mgcp_endpoint *mgcp_endp;
struct msgb *bsc_msg;
@@ -120,9 +125,9 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
bsc_endp = &nat->bsc_endpoints[endpoint];
mgcp_endp = &nat->mgcp_cfg->endpoints[endpoint];
bsc_con = bsc_mgcp_find_con(nat, endpoint);
sccp = bsc_mgcp_find_con(nat, endpoint);
if (!bsc_con) {
if (!sccp) {
LOGP(DMGCP, LOGL_ERROR, "Did not find BSC for a new connection on 0x%x for %d\n", endpoint, state);
switch (state) {
@@ -158,14 +163,14 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
bsc_endp->transaction_id = talloc_strdup(nat, transaction_id);
bsc_endp->bsc = bsc_con;
bsc_endp->bsc = sccp->bsc;
bsc_endp->pending_delete = 0;
/* we need to update some bits */
if (state == MGCP_ENDP_CRCX) {
struct sockaddr_in sock;
socklen_t len = sizeof(sock);
if (getpeername(bsc_con->write_queue.bfd.fd, (struct sockaddr *) &sock, &len) != 0) {
if (getpeername(sccp->bsc->write_queue.bfd.fd, (struct sockaddr *) &sock, &len) != 0) {
LOGP(DMGCP, LOGL_ERROR, "Can not get the peername...%d/%s\n",
errno, strerror(errno));
} else {
@@ -173,11 +178,12 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
}
} else if (state == MGCP_ENDP_DLCX) {
/* we will free the endpoint now in case the BSS does not respond */
bsc_mgcp_clear(sccp);
bsc_endp->pending_delete = 1;
mgcp_free_endp(mgcp_endp);
}
bsc_write(bsc_con, bsc_msg, NAT_IPAC_PROTO_MGCP);
bsc_write(sccp->bsc, bsc_msg, NAT_IPAC_PROTO_MGCP);
return MGCP_POLICY_DEFER;
}

View File

@@ -51,10 +51,10 @@
struct log_target *stderr_target;
static const char *config_file = "bsc-nat.cfg";
static char *msc_address = "127.0.0.1";
static struct in_addr local_addr;
static struct bsc_msc_connection *msc_con;
static struct bsc_fd bsc_listen;
static const char *msc_ip = NULL;
static struct bsc_nat *nat;
@@ -258,7 +258,10 @@ static int forward_sccp_to_bts(struct msgb *msg)
case SCCP_MSG_TYPE_IT:
con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
if (parsed->gsm_type == BSS_MAP_MSG_ASSIGMENT_RQST) {
counter_inc(nat->stats.sccp.calls);
if (con) {
counter_inc(con->bsc->cfg->stats.sccp.calls);
if (bsc_mgcp_assign(con, msg) != 0)
LOGP(DNAT, LOGL_ERROR, "Failed to assign...\n");
} else
@@ -306,11 +309,13 @@ send_to_all:
* message and then send it to the authenticated messages...
*/
if (parsed->ipa_proto == IPAC_PROTO_SCCP && parsed->gsm_type == BSS_MAP_MSG_PAGING) {
bsc = bsc_nat_find_bsc(nat, msg);
int lac;
bsc = bsc_nat_find_bsc(nat, msg, &lac);
if (bsc)
bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
else
LOGP(DNAT, LOGL_ERROR, "Could not determine BSC for paging.\n");
LOGP(DNAT, LOGL_ERROR, "Could not determine BSC for paging on lac: %d/0x%x\n",
lac, lac);
goto exit;
}
@@ -331,6 +336,8 @@ static void msc_connection_was_lost(struct bsc_msc_connection *con)
{
struct bsc_connection *bsc, *tmp;
counter_inc(nat->stats.msc.reconn);
LOGP(DMSC, LOGL_ERROR, "Closing all connections downstream.\n");
llist_for_each_entry_safe(bsc, tmp, &nat->bsc_connections, list_entry)
remove_bsc_connection(bsc);
@@ -453,9 +460,14 @@ static void remove_bsc_connection(struct bsc_connection *connection)
static void ipaccess_close_bsc(void *data)
{
struct sockaddr_in sock;
socklen_t len = sizeof(sock);
struct bsc_connection *conn = data;
LOGP(DNAT, LOGL_ERROR, "BSC didn't respond to identity request. Closing.\n");
getpeername(conn->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
LOGP(DNAT, LOGL_ERROR, "BSC on %s didn't respond to identity request. Closing.\n",
inet_ntoa(sock.sin_addr));
remove_bsc_connection(conn);
}
@@ -466,13 +478,16 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc
llist_for_each_entry(conf, &bsc->nat->bsc_configs, entry) {
if (strcmp(conf->token, token) == 0) {
counter_inc(conf->stats.net.reconn);
bsc->authenticated = 1;
bsc->cfg = conf;
bsc_del_timer(&bsc->id_timeout);
LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d lac: %d\n", conf->nr, conf->lac);
break;
return;
}
}
LOGP(DNAT, LOGL_ERROR, "No bsc found for token %s.\n", token);
}
static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
@@ -632,6 +647,9 @@ static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
return ret;
}
/* count the reconnect */
counter_inc(nat->stats.bsc.reconn);
/*
* if we are not connected to a msc... just close the socket
*/
@@ -773,7 +791,7 @@ static void handle_options(int argc, char** argv)
log_set_print_timestamp(stderr_target, 1);
break;
case 'm':
msc_address = strdup(optarg);
msc_ip = optarg;
break;
case 'l':
inet_aton(optarg, &local_addr);
@@ -806,10 +824,6 @@ int main(int argc, char** argv)
log_add_target(stderr_target);
log_set_all_filter(stderr_target, 1);
/* parse options */
local_addr.s_addr = INADDR_ANY;
handle_options(argc, argv);
nat = bsc_nat_alloc();
if (!nat) {
fprintf(stderr, "Failed to allocate the BSC nat.\n");
@@ -817,6 +831,14 @@ int main(int argc, char** argv)
}
nat->mgcp_cfg = talloc_zero(nat, struct mgcp_config);
if (!nat->mgcp_cfg) {
fprintf(stderr, "Failed to allocate MGCP cfg.\n");
return -5;
}
/* parse options */
local_addr.s_addr = INADDR_ANY;
handle_options(argc, argv);
/* init vty and parse */
bsc_nat_vty_init(nat);
@@ -826,6 +848,10 @@ int main(int argc, char** argv)
return -3;
}
/* over rule the VTY config */
if (msc_ip)
bsc_nat_set_msc_ip(nat, msc_ip);
/* seed the PRNG */
srand(time(NULL));
@@ -836,7 +862,7 @@ int main(int argc, char** argv)
return -4;
/* connect to the MSC */
msc_con = bsc_msc_create(msc_address, 5000);
msc_con = bsc_msc_create(nat->msc_ip, nat->msc_port);
if (!msc_con) {
fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
exit(1);

View File

@@ -30,6 +30,7 @@
#include <osmocore/linuxlist.h>
#include <osmocore/talloc.h>
#include <osmocore/gsm0808.h>
#include <sccp/sccp.h>
@@ -45,9 +46,23 @@ struct bsc_nat *bsc_nat_alloc(void)
INIT_LLIST_HEAD(&nat->sccp_connections);
INIT_LLIST_HEAD(&nat->bsc_connections);
INIT_LLIST_HEAD(&nat->bsc_configs);
nat->stats.sccp.conn = counter_alloc("nat.sccp.conn");
nat->stats.sccp.calls = counter_alloc("nat.sccp.calls");
nat->stats.bsc.reconn = counter_alloc("nat.bsc.conn");
nat->stats.bsc.auth_fail = counter_alloc("nat.bsc.auth_fail");
nat->stats.msc.reconn = counter_alloc("nat.msc.conn");
nat->msc_ip = talloc_strdup(nat, "127.0.0.1");
nat->msc_port = 5000;
return nat;
}
void bsc_nat_set_msc_ip(struct bsc_nat *nat, const char *ip)
{
if (nat->msc_ip)
talloc_free(nat->msc_ip);
nat->msc_ip = talloc_strdup(nat, ip);
}
struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat)
{
struct bsc_connection *con = talloc_zero(nat, struct bsc_connection);
@@ -69,9 +84,13 @@ struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsi
conf->nr = nat->num_bsc;
conf->nat = nat;
llist_add(&conf->entry, &nat->bsc_configs);
llist_add_tail(&conf->entry, &nat->bsc_configs);
++nat->num_bsc;
conf->stats.sccp.conn = counter_alloc("nat.bsc.sccp.conn");
conf->stats.sccp.calls = counter_alloc("nat.bsc.sccp.calls");
conf->stats.net.reconn = counter_alloc("nat.bsc.net.reconnects");
return conf;
}
@@ -85,7 +104,7 @@ void sccp_connection_destroy(struct sccp_connections *conn)
talloc_free(conn);
}
struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg)
struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *lac_out)
{
struct bsc_connection *bsc;
int data_length;
@@ -93,6 +112,8 @@ struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg)
struct tlv_parsed tp;
int i = 0;
*lac_out = -1;
if (!msg->l3h || msgb_l3len(msg) < 3) {
LOGP(DNAT, LOGL_ERROR, "Paging message is too short.\n");
return NULL;
@@ -114,6 +135,7 @@ struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg)
/* Currently we only handle one BSC */
for (i = 1; i < data_length - 1; i += 2) {
unsigned int _lac = ntohs(*(unsigned int *) &data[i]);
*lac_out = _lac;
llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
if (!bsc->cfg)
continue;

View File

@@ -51,6 +51,12 @@ static struct cmd_node bsc_node = {
static int config_write_nat(struct vty *vty)
{
vty_out(vty, "nat%s", VTY_NEWLINE);
if (_nat->imsi_allow)
vty_out(vty, " imsi allow %s%s", _nat->imsi_allow, VTY_NEWLINE);
if (_nat->imsi_deny)
vty_out(vty, " insi deny %s%s", _nat->imsi_deny, VTY_NEWLINE);
vty_out(vty, " msc ip %s%s", _nat->msc_ip, VTY_NEWLINE);
vty_out(vty, " msc port %d%s", _nat->msc_port, VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -58,7 +64,11 @@ static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
{
vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
vty_out(vty, " token %s%s", bsc->token, VTY_NEWLINE);
vty_out(vty, " lac %u%s", bsc->lac, VTY_NEWLINE);
vty_out(vty, " location_area_code %u%s", bsc->lac, VTY_NEWLINE);
if (bsc->imsi_allow)
vty_out(vty, " imsi allow %s%s", bsc->imsi_allow, VTY_NEWLINE);
if (bsc->imsi_deny)
vty_out(vty, " imsi deny %s%s", bsc->imsi_deny, VTY_NEWLINE);
}
static int config_write_bsc(struct vty *vty)
@@ -71,7 +81,7 @@ static int config_write_bsc(struct vty *vty)
}
DEFUN(show_sccp, show_sccp_cmd, "show connections sccp",
DEFUN(show_sccp, show_sccp_cmd, "show sccp connections",
SHOW_STR "Display information about current SCCP connections")
{
struct sccp_connections *con;
@@ -88,7 +98,7 @@ DEFUN(show_sccp, show_sccp_cmd, "show connections sccp",
return CMD_SUCCESS;
}
DEFUN(show_bsc, show_bsc_cmd, "show connections bsc",
DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
SHOW_STR "Display information about current BSCs")
{
struct bsc_connection *con;
@@ -107,18 +117,51 @@ DEFUN(show_bsc, show_bsc_cmd, "show connections bsc",
return CMD_SUCCESS;
}
DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "show bsc config",
SHOW_STR "Display information about known BSC configs")
DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "bsc config show",
"Display information about known BSC configs")
{
struct bsc_config *conf;
llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
vty_out(vty, "BSC token: '%s' lac: %u nr: %u%s",
conf->token, conf->lac, conf->nr, VTY_NEWLINE);
vty_out(vty, " imsi_allow: '%s' imsi_deny: '%s'%s",
conf->imsi_allow ? conf->imsi_allow: "any",
conf->imsi_deny ? conf->imsi_deny : "none",
VTY_NEWLINE);
}
return CMD_SUCCESS;
}
DEFUN(show_stats,
show_stats_cmd,
"show statistics",
SHOW_STR "Display network statistics\n")
{
struct bsc_config *conf;
vty_out(vty, "NAT statistics%s", VTY_NEWLINE);
vty_out(vty, " SCCP Connections %lu total, %lu calls%s",
counter_get(_nat->stats.sccp.conn),
counter_get(_nat->stats.sccp.calls), VTY_NEWLINE);
vty_out(vty, " MSC Connections %lu%s",
counter_get(_nat->stats.msc.reconn), VTY_NEWLINE);
vty_out(vty, " BSC Connections %lu total, %lu auth failed.%s",
counter_get(_nat->stats.bsc.reconn),
counter_get(_nat->stats.bsc.auth_fail), VTY_NEWLINE);
llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
vty_out(vty, " BSC lac: %d nr: %d%s",
conf->lac, conf->nr, VTY_NEWLINE);
vty_out(vty, " SCCP Connnections %lu total, %lu calls%s",
counter_get(conf->stats.sccp.conn),
counter_get(conf->stats.sccp.calls), VTY_NEWLINE);
vty_out(vty, " BSC Connections %lu total%s",
counter_get(conf->stats.net.reconn), VTY_NEWLINE);
}
return CMD_SUCCESS;
}
DEFUN(cfg_nat, cfg_nat_cmd, "nat", "Configute the NAT")
{
@@ -128,6 +171,58 @@ DEFUN(cfg_nat, cfg_nat_cmd, "nat", "Configute the NAT")
return CMD_SUCCESS;
}
static void parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv)
{
if (*imsi) {
talloc_free(*imsi);
*imsi = NULL;
}
regfree(reg);
if (argc > 0) {
*imsi = talloc_strdup(ctx, argv[0]);
regcomp(reg, argv[0], 0);
}
}
DEFUN(cfg_nat_imsi_allow,
cfg_nat_imsi_allow_cmd,
"imsi allow [REGEXP]",
"Allow matching IMSIs to talk to the MSC. "
"The defualt is to allow everyone.")
{
parse_reg(_nat, &_nat->imsi_allow_re, &_nat->imsi_allow, argc, argv);
return CMD_SUCCESS;
}
DEFUN(cfg_nat_imsi_deny,
cfg_nat_imsi_deny_cmd,
"imsi deny [REGEXP]",
"Deny matching IMSIs to talk to the MSC. "
"The defualt is to not deny.")
{
parse_reg(_nat, &_nat->imsi_deny_re, &_nat->imsi_deny, argc, argv);
return CMD_SUCCESS;
}
DEFUN(cfg_nat_msc_ip,
cfg_nat_msc_ip_cmd,
"msc ip IP",
"Set the IP address of the MSC.")
{
bsc_nat_set_msc_ip(_nat, argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_nat_msc_port,
cfg_nat_msc_port_cmd,
"msc port <1-65500>",
"Set the port of the MSC.")
{
_nat->msc_port = atoi(argv[0]);
return CMD_SUCCESS;
}
/* per BSC configuration */
DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure\n")
{
@@ -196,6 +291,30 @@ DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
return CMD_SUCCESS;
}
DEFUN(cfg_bsc_imsi_allow,
cfg_bsc_imsi_allow_cmd,
"imsi allow [REGEXP]",
"Allow IMSIs with the following network to talk to the MSC."
"The default is to allow everyone)")
{
struct bsc_config *conf = vty->index;
parse_reg(conf, &conf->imsi_allow_re, &conf->imsi_allow, argc, argv);
return CMD_SUCCESS;
}
DEFUN(cfg_bsc_imsi_deny,
cfg_bsc_imsi_deny_cmd,
"imsi deny [REGEXP]",
"Deny IMSIs with the following network to talk to the MSC."
"The default is to not deny anyone.)")
{
struct bsc_config *conf = vty->index;
parse_reg(conf, &conf->imsi_deny_re, &conf->imsi_deny, argc, argv);
return CMD_SUCCESS;
}
int bsc_nat_vty_init(struct bsc_nat *nat)
{
_nat = nat;
@@ -207,6 +326,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(VIEW_NODE, &show_sccp_cmd);
install_element(VIEW_NODE, &show_bsc_cmd);
install_element(VIEW_NODE, &show_bsc_cfg_cmd);
install_element(VIEW_NODE, &show_stats_cmd);
openbsc_vty_add_cmds();
@@ -214,6 +334,10 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(CONFIG_NODE, &cfg_nat_cmd);
install_node(&nat_node, config_write_nat);
install_default(NAT_NODE);
install_element(NAT_NODE, &cfg_nat_imsi_allow_cmd);
install_element(NAT_NODE, &cfg_nat_imsi_deny_cmd);
install_element(NAT_NODE, &cfg_nat_msc_ip_cmd);
install_element(NAT_NODE, &cfg_nat_msc_port_cmd);
/* BSC subgroups */
install_element(NAT_NODE, &cfg_bsc_cmd);
@@ -221,6 +345,8 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_default(BSC_NODE);
install_element(BSC_NODE, &cfg_bsc_token_cmd);
install_element(BSC_NODE, &cfg_bsc_lac_cmd);
install_element(BSC_NODE, &cfg_bsc_imsi_allow_cmd);
install_element(BSC_NODE, &cfg_bsc_imsi_deny_cmd);
mgcp_vty_init();

View File

@@ -99,7 +99,10 @@ int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc
return -1;
}
llist_add(&conn->list_entry, &bsc->nat->sccp_connections);
bsc_mgcp_clear(conn);
llist_add_tail(&conn->list_entry, &bsc->nat->sccp_connections);
counter_inc(bsc->cfg->stats.sccp.conn);
counter_inc(bsc->cfg->nat->stats.sccp.conn);
LOGP(DNAT, LOGL_DEBUG, "Created 0x%x <-> 0x%x mapping for con %p\n",
sccp_src_ref_to_int(&conn->real_ref),

View File

@@ -1,6 +1,6 @@
!
! OpenBSC configuration saved from vty
!
! !
password foo
!
line vty
@@ -11,17 +11,52 @@ network
mobile network code 1
short name OpenBSC
long name OpenBSC
auth policy closed
location updating reject cause 13
encryption a5 0
neci 0
rrlp mode none
mm info 1
handover 0
handover window rxlev averaging 10
handover window rxqual averaging 1
handover window rxlev neighbor averaging 10
handover power budget interval 6
handover power budget hysteresis 3
handover maximum distance 9999
timer t3101 10
timer t3103 0
timer t3105 0
timer t3107 0
timer t3109 0
timer t3111 0
timer t3113 60
timer t3115 0
timer t3117 0
timer t3119 0
timer t3141 0
bts 0
type nanobts
ip.access unit_id 1801 0
band GSM1800
band DCS1800
cell_identity 0
location_area_code 1
training_sequence_code 7
base_station_id_code 63
ms max power 15
cell reselection hysteresis 4
rxlev access min 0
channel allocator ascending
rach tx integer 9
rach max transmission 7
ip.access unit_id 1801 0
oml ip.access stream_id 255
gprs mode none
trx 0
rf_locked 0
arfcn 514
nominal power 23
max_power_red 20
rsl e1 tei 0
timeslot 0
phys_chan_config CCCH+SDCCH4
timeslot 1

View File

@@ -0,0 +1,97 @@
!
! OpenBSC configuration saved from vty
! !
password foo
!
line vty
no login
!
network
network country code 1
mobile network code 1
short name OpenBSC
long name OpenBSC
auth policy closed
location updating reject cause 13
encryption a5 0
neci 0
rrlp mode none
mm info 0
handover 0
handover window rxlev averaging 10
handover window rxqual averaging 1
handover window rxlev neighbor averaging 10
handover power budget interval 6
handover power budget hysteresis 3
handover maximum distance 9999
timer t3101 10
timer t3103 0
timer t3105 0
timer t3107 0
timer t3109 0
timer t3111 0
timer t3113 60
timer t3115 0
timer t3117 0
timer t3119 0
timer t3141 0
bts 0
type nanobts
band DCS1800
cell_identity 0
location_area_code 1
training_sequence_code 7
base_station_id_code 63
ms max power 15
cell reselection hysteresis 4
rxlev access min 0
channel allocator ascending
rach tx integer 9
rach max transmission 7
ip.access unit_id 1800 0
oml ip.access stream_id 255
gprs mode none
trx 0
rf_locked 0
arfcn 871
nominal power 23
max_power_red 0
rsl e1 tei 0
timeslot 0
phys_chan_config CCCH+SDCCH4
timeslot 1
phys_chan_config SDCCH8
timeslot 2
phys_chan_config TCH/F
timeslot 3
phys_chan_config TCH/F
timeslot 4
phys_chan_config TCH/F
timeslot 5
phys_chan_config TCH/F
timeslot 6
phys_chan_config TCH/F
timeslot 7
phys_chan_config TCH/F
trx 1
rf_locked 0
arfcn 873
nominal power 23
max_power_red 0
rsl e1 tei 0
timeslot 0
phys_chan_config CCCH+SDCCH4
timeslot 1
phys_chan_config SDCCH8
timeslot 2
phys_chan_config TCH/F
timeslot 3
phys_chan_config TCH/F
timeslot 4
phys_chan_config TCH/F
timeslot 5
phys_chan_config TCH/F
timeslot 6
phys_chan_config TCH/F
timeslot 7
phys_chan_config TCH/F

View File

@@ -45,9 +45,12 @@
#include <openbsc/signal.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/gsm_data.h>
#include <openbsc/chan_alloc.h>
void *tall_paging_ctx;
#define PAGING_TIMER 0, 500000
static unsigned int calculate_group(struct gsm_bts *bts, struct gsm_subscriber *subscr)
{
int ccch_conf;
@@ -95,6 +98,26 @@ static void page_ms(struct gsm_paging_request *request)
request->chan_type);
}
static void paging_schedule_if_needed(struct gsm_bts_paging_state *paging_bts)
{
if (llist_empty(&paging_bts->pending_requests))
return;
if (!bsc_timer_pending(&paging_bts->work_timer))
bsc_schedule_timer(&paging_bts->work_timer, PAGING_TIMER);
}
static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_bts);
static void paging_give_credit(void *data)
{
struct gsm_bts_paging_state *paging_bts = data;
LOGP(DPAG, LOGL_NOTICE, "No slots available on bts nr %d\n", paging_bts->bts->nr);
paging_bts->available_slots = 20;
paging_handle_pending_requests(paging_bts);
}
/*
* This is kicked by the periodic PAGING LOAD Indicator
* coming from abis_rsl.c
@@ -104,8 +127,7 @@ static void page_ms(struct gsm_paging_request *request)
*/
static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_bts)
{
struct gsm_paging_request *initial_request = NULL;
struct gsm_paging_request *current_request = NULL;
struct gsm_paging_request *request = NULL;
/*
* Determine if the pending_requests list is empty and
@@ -117,39 +139,30 @@ static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_b
}
/*
* In case the BTS does not provide us with load indication just fill
* up our slots for this round. We should be able to page 20 subscribers
* every two seconds. So we will just give the BTS some extra credit.
* We will have to see how often we run out of this credit, so we might
* need a low watermark and then add credit or give 20 every run when
* the bts sets an option for that.
* In case the BTS does not provide us with load indication and we
* ran out of slots, call an autofill routine. It might be that the
* BTS did not like our paging messages and then we have counted down
* to zero and we do not get any messages.
*/
if (paging_bts->available_slots == 0) {
LOGP(DPAG, LOGL_NOTICE, "No slots available on bts nr %d\n",
paging_bts->bts->nr);
paging_bts->available_slots = 20;
paging_bts->credit_timer.cb = paging_give_credit;
paging_bts->credit_timer.data = paging_bts;
bsc_schedule_timer(&paging_bts->credit_timer, 5, 0);
return;
}
initial_request = llist_entry(paging_bts->pending_requests.next,
struct gsm_paging_request, entry);
current_request = initial_request;
request = llist_entry(paging_bts->pending_requests.next,
struct gsm_paging_request, entry);
do {
/* handle the paging request now */
page_ms(current_request);
paging_bts->available_slots--;
/* handle the paging request now */
page_ms(request);
paging_bts->available_slots--;
/* take the current and add it to the back */
llist_del(&current_request->entry);
llist_add_tail(&current_request->entry, &paging_bts->pending_requests);
/* take the current and add it to the back */
llist_del(&request->entry);
llist_add_tail(&request->entry, &paging_bts->pending_requests);
/* take the next request */
current_request = llist_entry(paging_bts->pending_requests.next,
struct gsm_paging_request, entry);
} while (paging_bts->available_slots > 0
&& initial_request != current_request);
bsc_schedule_timer(&paging_bts->work_timer, 2, 0);
bsc_schedule_timer(&paging_bts->work_timer, PAGING_TIMER);
}
static void paging_worker(void *data)
@@ -232,9 +245,7 @@ static int _paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr,
req->T3113.data = req;
bsc_schedule_timer(&req->T3113, bts->network->T3113, 0);
llist_add_tail(&req->entry, &bts_entry->pending_requests);
if (!bsc_timer_pending(&bts_entry->work_timer))
bsc_schedule_timer(&bts_entry->work_timer, 2, 0);
paging_schedule_if_needed(bts_entry);
return 0;
}
@@ -324,5 +335,19 @@ void paging_request_stop(struct gsm_bts *_bts, struct gsm_subscriber *subscr,
void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t free_slots)
{
bsc_del_timer(&bts->paging.credit_timer);
bts->paging.available_slots = free_slots;
paging_schedule_if_needed(&bts->paging);
}
unsigned int paging_pending_requests_nr(struct gsm_bts *bts)
{
unsigned int requests = 0;
struct gsm_paging_request *req;
llist_for_each_entry(req, &bts->paging.pending_requests, entry)
++requests;
return requests;
}

View File

@@ -133,6 +133,7 @@ static int append_lsa_params(struct bitvec *bv,
const struct gsm48_lsa_params *lsa_params)
{
/* FIXME */
return -1;
}
/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
@@ -318,8 +319,31 @@ static int append_gprs_cell_opt(struct bitvec *bv,
/* hard-code no PAN_{DEC,INC,MAX} */
bitvec_set_bit(bv, 0);
/* no extension information (EDGE) */
bitvec_set_bit(bv, 0);
if (!gco->ext_info_present) {
/* no extension information */
bitvec_set_bit(bv, 0);
} else {
/* extension information */
bitvec_set_bit(bv, 1);
if (!gco->ext_info.egprs_supported) {
/* 6bit length of extension */
bitvec_set_uint(bv, (1 + 3)-1, 6);
/* EGPRS supported in the cell */
bitvec_set_bit(bv, 0);
} else {
/* 6bit length of extension */
bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
/* EGPRS supported in the cell */
bitvec_set_bit(bv, 1);
/* 1bit EGPRS PACKET CHANNEL REQUEST */
bitvec_set_bit(bv, gco->ext_info.use_egprs_p_ch_req);
/* 4bit BEP PERIOD */
bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
}
bitvec_set_bit(bv, gco->ext_info.pfc_supported);
bitvec_set_bit(bv, gco->ext_info.dtm_supported);
bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
}
return 0;
}
@@ -334,7 +358,7 @@ static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
bitvec_set_uint(bv, pcp->n_avg_i, 4);
}
/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13)
{
struct bitvec bv;
@@ -390,6 +414,11 @@ int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13)
break;
}
}
/* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
bitvec_set_bit(&bv, H); /* added Release 99 */
/* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
* was only added in this Release */
bitvec_set_bit(&bv, 1);
}
bitvec_spare_padding(&bv, (bv.data_len*8)-1);
return bv.data_len;

View File

@@ -402,6 +402,16 @@ static struct gsm48_si13_info si13_default = {
.t3192 = 500,
.drx_timer_max = 3,
.bs_cv_max = 15,
.ext_info_present = 0,
.ext_info = {
/* The values below are just guesses ! */
.egprs_supported = 0,
.use_egprs_p_ch_req = 1,
.bep_period = 4,
.pfc_supported = 0,
.dtm_supported = 0,
.bss_paging_coordination = 0,
},
},
.pwr_ctrl_pars = {
.alpha = 10, /* a = 1.0 */
@@ -448,7 +458,18 @@ static int generate_si13(u_int8_t *output, struct gsm_bts *bts)
int gsm_generate_si(u_int8_t *output, struct gsm_bts *bts, int type)
{
si_info.gprs_ind.present = bts->gprs.enabled;
switch (bts->gprs.mode) {
case BTS_GPRS_EGPRS:
si13_default.cell_opts.ext_info_present = 1;
si13_default.cell_opts.ext_info.egprs_supported = 1;
/* fallthrough */
case BTS_GPRS_GPRS:
si_info.gprs_ind.present = 1;
break;
case BTS_GPRS_NONE:
si_info.gprs_ind.present = 0;
break;
}
switch (type) {
case RSL_SYSTEM_INFO_1:

View File

@@ -39,6 +39,8 @@
#include <osmocore/talloc.h>
#include <openbsc/telnet_interface.h>
#include <openbsc/vty.h>
#include <openbsc/ipaccess.h>
#include <openbsc/paging.h>
static struct gsm_network *gsmnet;
@@ -195,7 +197,8 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
net_dump_nmstate(vty, &bts->nm_state);
vty_out(vty, " Site Mgr NM State: ");
net_dump_nmstate(vty, &bts->site_mgr.nm_state);
vty_out(vty, " Paging: FIXME pending requests, %u free slots%s",
vty_out(vty, " Paging: %u pending requests, %u free slots%s",
paging_pending_requests_nr(bts),
bts->paging.available_slots, VTY_NEWLINE);
if (!is_ipaccess_bts(bts)) {
vty_out(vty, " E1 Signalling Link:%s", VTY_NEWLINE);
@@ -233,6 +236,36 @@ DEFUN(show_bts, show_bts_cmd, "show bts [number]",
return CMD_SUCCESS;
}
DEFUN(test_bts_lchan_alloc, test_bts_lchan_alloc_cmd, "test bts alloc (sdcch|tch_h|tch_f)",
"Test command to allocate all channels. You will need to restart. To free these channels.\n")
{
struct gsm_network *net = gsmnet;
int bts_nr;
enum gsm_chan_t type = GSM_LCHAN_NONE;
if (strcmp("sdcch", argv[0]) == 0)
type = GSM_LCHAN_SDCCH;
else if (strcmp("tch_h", argv[0]) == 0)
type = GSM_LCHAN_TCH_H;
else if (strcmp("tch_f", argv[0]) == 0)
type = GSM_LCHAN_TCH_F;
else {
vty_out(vty, "Unknown mode for allocation.%s", VTY_NEWLINE);
}
for (bts_nr = 0; bts_nr < net->num_bts; ++bts_nr) {
struct gsm_bts *bts = gsm_bts_num(net, bts_nr);
struct gsm_lchan *lchan;
/* alloc the channel */
while ((lchan = lchan_alloc(bts, type, 0)) != NULL)
rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
}
return CMD_SUCCESS;
}
/* utility functions */
static void parse_e1_link(struct gsm_e1_subslot *e1_link, const char *line,
const char *ts, const char *ss)
@@ -275,6 +308,9 @@ static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
int i;
vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE);
vty_out(vty, " rf_locked %u%s",
trx->nm_state.administrative == NM_STATE_LOCKED ? 1 : 0,
VTY_NEWLINE);
vty_out(vty, " arfcn %u%s", trx->arfcn, VTY_NEWLINE);
vty_out(vty, " nominal power %u%s", trx->nominal_power, VTY_NEWLINE);
vty_out(vty, " max_power_red %u%s", trx->max_power_red, VTY_NEWLINE);
@@ -324,8 +360,9 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
config_write_e1_link(vty, &bts->oml_e1_link, " oml ");
vty_out(vty, " oml e1 tei %u%s", bts->oml_tei, VTY_NEWLINE);
}
vty_out(vty, " gprs enabled %u%s", bts->gprs.enabled, VTY_NEWLINE);
if (bts->gprs.enabled) {
vty_out(vty, " gprs mode %s%s", bts_gprs_mode_name(bts->gprs.mode),
VTY_NEWLINE);
if (bts->gprs.mode != BTS_GPRS_NONE) {
vty_out(vty, " gprs routing area %u%s", bts->gprs.rac,
VTY_NEWLINE);
vty_out(vty, " gprs cell bvci %u%s", bts->gprs.cell.bvci,
@@ -429,6 +466,8 @@ static int config_write_net(struct vty *vty)
if (gsmnet->bsc_token)
vty_out(vty, " bsc_token %s%s", gsmnet->bsc_token, VTY_NEWLINE);
vty_out(vty, " msc ip %s%s", gsmnet->msc_ip, VTY_NEWLINE);
vty_out(vty, " msc port %d%s", gsmnet->msc_port, VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -576,10 +615,6 @@ DEFUN(show_ts,
static void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr)
{
int rc;
struct gsm_auth_info ainfo;
struct gsm_auth_tuple atuple;
vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
subscr->authorized, VTY_NEWLINE);
if (subscr->name)
@@ -915,50 +950,10 @@ DEFUN(show_paging,
return CMD_SUCCESS;
}
DEFUN(show_stats,
show_stats_cmd,
"show statistics",
SHOW_STR "Display network statistics\n")
{
struct gsm_network *net = gsmnet;
vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
counter_get(net->stats.chreq.total),
counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
vty_out(vty, "Location Update : %lu attach, %lu normal, %lu periodic%s",
counter_get(net->stats.loc_upd_type.attach),
counter_get(net->stats.loc_upd_type.normal),
counter_get(net->stats.loc_upd_type.periodic), VTY_NEWLINE);
vty_out(vty, "IMSI Detach Indications : %lu%s",
counter_get(net->stats.loc_upd_type.detach), VTY_NEWLINE);
vty_out(vty, "Location Update Response: %lu accept, %lu reject%s",
counter_get(net->stats.loc_upd_resp.accept),
counter_get(net->stats.loc_upd_resp.reject), VTY_NEWLINE);
vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
counter_get(net->stats.paging.attempted),
counter_get(net->stats.paging.completed),
counter_get(net->stats.paging.expired), VTY_NEWLINE);
vty_out(vty, "Handover : %lu attempted, %lu no_channel, %lu timeout, "
"%lu completed, %lu failed%s",
counter_get(net->stats.handover.attempted),
counter_get(net->stats.handover.no_channel),
counter_get(net->stats.handover.timeout),
counter_get(net->stats.handover.completed),
counter_get(net->stats.handover.failed), VTY_NEWLINE);
vty_out(vty, "SMS MO : %lu submitted, %lu no receiver%s",
counter_get(net->stats.sms.submitted),
counter_get(net->stats.sms.no_receiver), VTY_NEWLINE);
vty_out(vty, "SMS MT : %lu delivered, %lu no memory, %lu other error%s",
counter_get(net->stats.sms.delivered),
counter_get(net->stats.sms.rp_err_mem),
counter_get(net->stats.sms.rp_err_other), VTY_NEWLINE);
return CMD_SUCCESS;
}
DEFUN(drop_bts,
drop_bts_cmd,
"drop bts connection [nr] (oml|rsl)",
SHOW_STR "Debug/Simulation command to drop ipaccess BTS\n")
"drop bts connection <0-65535> (oml|rsl)",
"Debug/Simulation command to drop ipaccess BTS\n")
{
struct gsm_bts_trx *trx;
struct gsm_bts *bts;
@@ -984,15 +979,15 @@ DEFUN(drop_bts,
/* close all connections */
if (strcmp(argv[1], "oml") == 0) {
close(bts->oml_link->ts->driver.ipaccess.fd.fd);
} else if (strcmp(argv[1], "rsl") == 0) {
if (strcmp(argv[1], "oml") == 0)
ipaccess_drop_oml(bts);
else if (strcmp(argv[1], "rsl") == 0) {
/* close all rsl connections */
llist_for_each_entry(trx, &bts->trx_list, list) {
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);
vty_out(vty, "Argument must be 'oml' or 'rsl'.%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1308,6 +1303,27 @@ DEFUN(cfg_net_pag_any_tch,
return CMD_SUCCESS;
}
DEFUN(cfg_net_msc_ip,
cfg_net_msc_ip_cmd,
"msc ip IP",
"Set the MSC/MUX IP address.")
{
if (gsmnet->msc_ip)
talloc_free(gsmnet->msc_ip);
gsmnet->msc_ip = talloc_strdup(gsmnet, argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_net_msc_port,
cfg_net_msc_port_cmd,
"msc port <1-65000>",
"Set the MSC/MUX port.")
{
gsmnet->msc_port = atoi(argv[0]);
return CMD_SUCCESS;
}
#define DECLARE_TIMER(number, doc) \
DEFUN(cfg_net_T##number, \
cfg_net_T##number##_cmd, \
@@ -1639,12 +1655,12 @@ DEFUN(cfg_bts_per_loc_upd, cfg_bts_per_loc_upd_cmd,
}
DEFUN(cfg_bts_prs_bvci, cfg_bts_gprs_bvci_cmd,
"gprs cell bvci <0-65535>",
"gprs cell bvci <2-65535>",
"GPRS BSSGP VC Identifier")
{
struct gsm_bts *bts = vty->index;
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1660,7 +1676,7 @@ DEFUN(cfg_bts_gprs_nsei, cfg_bts_gprs_nsei_cmd,
{
struct gsm_bts *bts = vty->index;
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1678,7 +1694,7 @@ DEFUN(cfg_bts_gprs_nsvci, cfg_bts_gprs_nsvci_cmd,
struct gsm_bts *bts = vty->index;
int idx = atoi(argv[0]);
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1695,7 +1711,7 @@ DEFUN(cfg_bts_gprs_nsvc_lport, cfg_bts_gprs_nsvc_lport_cmd,
struct gsm_bts *bts = vty->index;
int idx = atoi(argv[0]);
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1712,7 +1728,7 @@ DEFUN(cfg_bts_gprs_nsvc_rport, cfg_bts_gprs_nsvc_rport_cmd,
struct gsm_bts *bts = vty->index;
int idx = atoi(argv[0]);
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1730,7 +1746,7 @@ DEFUN(cfg_bts_gprs_nsvc_rip, cfg_bts_gprs_nsvc_rip_cmd,
int idx = atoi(argv[0]);
struct in_addr ia;
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1747,7 +1763,7 @@ DEFUN(cfg_bts_gprs_rac, cfg_bts_gprs_rac_cmd,
{
struct gsm_bts *bts = vty->index;
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1757,13 +1773,13 @@ DEFUN(cfg_bts_gprs_rac, cfg_bts_gprs_rac_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_gprs_enabled, cfg_bts_gprs_enabled_cmd,
"gprs enabled <0-1>",
"GPRS Enabled on this BTS")
DEFUN(cfg_bts_gprs_mode, cfg_bts_gprs_mode_cmd,
"gprs mode (none|gprs|egprs)",
"GPRS Mode for this BTS")
{
struct gsm_bts *bts = vty->index;
bts->gprs.enabled = atoi(argv[0]);
bts->gprs.mode = bts_gprs_mode_parse(argv[0]);
return CMD_SUCCESS;
}
@@ -1946,6 +1962,8 @@ DEFUN(cfg_ts_e1_subslot,
return CMD_SUCCESS;
}
extern int bsc_vty_init_extra(struct gsm_network *net);
int bsc_vty_init(struct gsm_network *net)
{
gsmnet = net;
@@ -1964,9 +1982,9 @@ int bsc_vty_init(struct gsm_network *net)
install_element(VIEW_NODE, &show_e1ts_cmd);
install_element(VIEW_NODE, &show_paging_cmd);
install_element(VIEW_NODE, &show_stats_cmd);
install_element(VIEW_NODE, &drop_bts_cmd);
install_element(VIEW_NODE, &test_bts_lchan_alloc_cmd);
openbsc_vty_add_cmds();
@@ -2008,6 +2026,8 @@ int bsc_vty_init(struct gsm_network *net)
install_element(GSMNET_NODE, &cfg_net_T3141_cmd);
install_element(GSMNET_NODE, &cfg_net_bsc_token_cmd);
install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd);
install_element(GSMNET_NODE, &cfg_net_msc_ip_cmd);
install_element(GSMNET_NODE, &cfg_net_msc_port_cmd);
install_element(GSMNET_NODE, &cfg_bts_cmd);
install_node(&bts_node, config_write_bts);
@@ -2030,7 +2050,7 @@ int bsc_vty_init(struct gsm_network *net)
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_gprs_enabled_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_mode_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_rac_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_bvci_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_nsei_cmd);

View File

@@ -27,13 +27,39 @@
#include <vty/vty.h>
#include <openbsc/gsm_data.h>
#include <openbsc/vty.h>
static struct gsmnet *gsmnet = NULL;
#include <sccp/sccp.h>
static struct gsm_network *gsmnet = NULL;
extern struct llist_head *bsc_sccp_connections();
DEFUN(show_bsc, show_bsc_cmd, "show bsc",
SHOW_STR "Display information about the BSC\n")
{
vty_out(vty, "BSC... not implemented yet%s", VTY_NEWLINE);
struct bss_sccp_connection_data *con;
vty_out(vty, "BSC Information%s", VTY_NEWLINE);
llist_for_each_entry(con, bsc_sccp_connections(), active_connections) {
vty_out(vty, " Connection: LCHAN: %p sec LCHAN: %p SCCP src: %d dest: %d%s",
con->lchan, con->secondary_lchan,
con->sccp ? (int) sccp_src_ref_to_int(&con->sccp->source_local_reference) : -1,
con->sccp ? (int) sccp_src_ref_to_int(&con->sccp->destination_local_reference) : -1,
VTY_NEWLINE);
}
return CMD_SUCCESS;
}
DEFUN(show_stats,
show_stats_cmd,
"show statistics",
SHOW_STR "Display network statistics\n")
{
struct gsm_network *net = gsmnet;
openbsc_vty_print_statistics(vty, net);
return CMD_SUCCESS;
}
@@ -43,6 +69,7 @@ int bsc_vty_init_extra(struct gsm_network *net)
/* get runtime information */
install_element(VIEW_NODE, &show_bsc_cmd);
install_element(VIEW_NODE, &show_stats_cmd);
return 0;
}

View File

@@ -228,6 +228,23 @@ DEFUN(diable_logging,
return CMD_SUCCESS;
}
void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
{
vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
counter_get(net->stats.chreq.total),
counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
vty_out(vty, "Channel Failures : %lu rf_failures, %lu rll failures%s",
counter_get(net->stats.chan.rf_fail),
counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
counter_get(net->stats.paging.attempted),
counter_get(net->stats.paging.completed),
counter_get(net->stats.paging.expired), VTY_NEWLINE);
vty_out(vty, "BTS failures : %lu OML, %lu RSL%s",
counter_get(net->stats.bts.oml_fail),
counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
}
void openbsc_vty_add_cmds()
{
install_element(VIEW_NODE, &enable_logging_cmd);

View File

@@ -41,6 +41,7 @@
#include <osmocore/talloc.h>
#include <openbsc/signal.h>
#include <openbsc/debug.h>
#include <openbsc/vty.h>
static struct gsm_network *gsmnet;
@@ -502,6 +503,41 @@ static int scall_cbfn(unsigned int subsys, unsigned int signal,
return 0;
}
DEFUN(show_stats,
show_stats_cmd,
"show statistics",
SHOW_STR "Display network statistics\n")
{
struct gsm_network *net = gsmnet;
openbsc_vty_print_statistics(vty, net);
vty_out(vty, "Location Update : %lu attach, %lu normal, %lu periodic%s",
counter_get(net->stats.loc_upd_type.attach),
counter_get(net->stats.loc_upd_type.normal),
counter_get(net->stats.loc_upd_type.periodic), VTY_NEWLINE);
vty_out(vty, "IMSI Detach Indications : %lu%s",
counter_get(net->stats.loc_upd_type.detach), VTY_NEWLINE);
vty_out(vty, "Location Update Response: %lu accept, %lu reject%s",
counter_get(net->stats.loc_upd_resp.accept),
counter_get(net->stats.loc_upd_resp.reject), VTY_NEWLINE);
vty_out(vty, "Handover : %lu attempted, %lu no_channel, %lu timeout, "
"%lu completed, %lu failed%s",
counter_get(net->stats.handover.attempted),
counter_get(net->stats.handover.no_channel),
counter_get(net->stats.handover.timeout),
counter_get(net->stats.handover.completed),
counter_get(net->stats.handover.failed), VTY_NEWLINE);
vty_out(vty, "SMS MO : %lu submitted, %lu no receiver%s",
counter_get(net->stats.sms.submitted),
counter_get(net->stats.sms.no_receiver), VTY_NEWLINE);
vty_out(vty, "SMS MT : %lu delivered, %lu no memory, %lu other error%s",
counter_get(net->stats.sms.delivered),
counter_get(net->stats.sms.rp_err_mem),
counter_get(net->stats.sms.rp_err_other), VTY_NEWLINE);
return CMD_SUCCESS;
}
int bsc_vty_init_extra(struct gsm_network *net)
{
gsmnet = net;
@@ -517,6 +553,7 @@ int bsc_vty_init_extra(struct gsm_network *net)
install_element(VIEW_NODE, &subscriber_silent_sms_cmd);
install_element(VIEW_NODE, &subscriber_silent_call_start_cmd);
install_element(VIEW_NODE, &subscriber_silent_call_stop_cmd);
install_element(VIEW_NODE, &show_stats_cmd);
install_element(CONFIG_NODE, &cfg_subscr_cmd);
install_node(&subscr_node, dummy_config_write);

View File

@@ -242,6 +242,7 @@ static void test_contrack()
fprintf(stderr, "Testing connection tracking.\n");
nat = bsc_nat_alloc();
con = bsc_connection_alloc(nat);
con->cfg = bsc_config_alloc(nat, "foo", 23);
msg = msgb_alloc(4096, "test");
/* 1.) create a connection */
@@ -329,6 +330,7 @@ static void test_contrack()
static void test_paging(void)
{
int lac;
struct bsc_nat *nat;
struct bsc_connection *con;
struct bsc_nat_parsed *parsed;
@@ -347,7 +349,7 @@ static void test_paging(void)
/* Test completely bad input */
copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
if (bsc_nat_find_bsc(nat, msg) != 0) {
if (bsc_nat_find_bsc(nat, msg, &lac) != 0) {
fprintf(stderr, "Should have not found anything.\n");
abort();
}
@@ -355,7 +357,7 @@ static void test_paging(void)
/* Test it by not finding it */
copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
parsed = bsc_nat_parse(msg);
if (bsc_nat_find_bsc(nat, msg) != 0) {
if (bsc_nat_find_bsc(nat, msg, &lac) != 0) {
fprintf(stderr, "Should have not found aynthing.\n");
abort();
}
@@ -365,7 +367,7 @@ static void test_paging(void)
cfg.lac = 8213;
copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
parsed = bsc_nat_parse(msg);
if (bsc_nat_find_bsc(nat, msg) != con) {
if (bsc_nat_find_bsc(nat, msg, &lac) != con) {
fprintf(stderr, "Should have found it.\n");
abort();
}
@@ -431,14 +433,14 @@ static void test_mgcp_find(void)
abort();
}
if (bsc_mgcp_find_con(nat, 12) != con) {
if (bsc_mgcp_find_con(nat, 12) != sccp_con) {
fprintf(stderr, "Didn't find the connection\n");
abort();
}
sccp_con->msc_timeslot = 0;
sccp_con->bsc_timeslot = 0;
if (bsc_mgcp_find_con(nat, 1) != con) {
if (bsc_mgcp_find_con(nat, 1) != sccp_con) {
fprintf(stderr, "Didn't find the connection\n");
abort();
}

View File

@@ -38,4 +38,6 @@ int main(int argc, char** argv)
DEBUGP(DRLL, "You should see this\n");
DEBUGP(DCC, "You should see this\n");
DEBUGP(DMM, "You should not see this\n");
return 0;
}