summaryrefslogtreecommitdiffstats
path: root/openbsc/src/e1_config.c
blob: 898780374ad4a6ffd40357452966a10c4732af15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <string.h>
#include <errno.h>

#include <netinet/in.h>

#include <openbsc/gsm_data.h>
#include <openbsc/e1_input.h>
#include <openbsc/trau_frame.h>
#include <openbsc/trau_mux.h>
#include <openbsc/misdn.h>
#include <openbsc/talloc.h>

#define SAPI_L2ML	0
#define SAPI_OML	62
#define SAPI_RSL	0	/* 63 ? */

#define TEI_L2ML	127
#define TEI_OML		25
#define TEI_RSL		1

/* do some compiled-in configuration for our BTS/E1 setup */
int e1_config(struct gsm_bts *bts, int cardnr, int release_l2)
{
	struct e1inp_line *line;
	struct e1inp_ts *sign_ts;
	struct e1inp_sign_link *oml_link, *rsl_link;
	struct gsm_bts_trx *trx = bts->c0;
	int base_ts;

	switch (bts->nr) {
	case 0:
		/* First BTS uses E1 TS 01,02,03,04,05 */
		base_ts = HARDCODED_BTS0_TS - 1;
		break;
	case 1:
		/* Second BTS uses E1 TS 06,07,08,09,10 */
		base_ts = HARDCODED_BTS1_TS - 1;
		break;
	case 2:
		/* Third BTS uses E1 TS 11,12,13,14,15 */
		base_ts = HARDCODED_BTS2_TS - 1;
	default:
		return -EINVAL;
	}

	line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
	if (!line)
		return -ENOMEM;

	/* create E1 timeslots for signalling and TRAU frames */
	e1inp_ts_config(&line->ts[base_ts+1-1], line, E1INP_TS_TYPE_SIGN);
	e1inp_ts_config(&line->ts[base_ts+2-1], line, E1INP_TS_TYPE_TRAU);
	e1inp_ts_config(&line->ts[base_ts+3-1], line, E1INP_TS_TYPE_TRAU);

	/* create signalling links for TS1 */
	sign_ts = &line->ts[base_ts+1-1];
	oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
					  trx, TEI_OML, SAPI_OML);
	rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
					  trx, TEI_RSL, SAPI_RSL);

	/* create back-links from bts/trx */
	bts->oml_link = oml_link;
	trx->rsl_link = rsl_link;

	/* enable subchannel demuxer on TS2 */
	subch_demux_activate(&line->ts[base_ts+2-1].trau.demux, 1);
	subch_demux_activate(&line->ts[base_ts+2-1].trau.demux, 2);
	subch_demux_activate(&line->ts[base_ts+2-1].trau.demux, 3);

	/* enable subchannel demuxer on TS3 */
	subch_demux_activate(&line->ts[base_ts+3-1].trau.demux, 0);
	subch_demux_activate(&line->ts[base_ts+3-1].trau.demux, 1);
	subch_demux_activate(&line->ts[base_ts+3-1].trau.demux, 2);
	subch_demux_activate(&line->ts[base_ts+3-1].trau.demux, 3);

	trx = gsm_bts_trx_num(bts, 1);
	if (trx) {
		/* create E1 timeslots for TRAU frames of TRX1 */
		e1inp_ts_config(&line->ts[base_ts+4-1], line, E1INP_TS_TYPE_TRAU);
		e1inp_ts_config(&line->ts[base_ts+5-1], line, E1INP_TS_TYPE_TRAU);

		/* create RSL signalling link for TRX1 */
		sign_ts = &line->ts[base_ts+1-1];
		rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
					  trx, TEI_RSL+1, SAPI_RSL);
		/* create back-links from trx */
		trx->rsl_link = rsl_link;

		/* enable subchannel demuxer on TS2 */
		subch_demux_activate(&line->ts[base_ts+4-1].trau.demux, 0);
		subch_demux_activate(&line->ts[base_ts+4-1].trau.demux, 1);
		subch_demux_activate(&line->ts[base_ts+4-1].trau.demux, 2);
		subch_demux_activate(&line->ts[base_ts+4-1].trau.demux, 3);

		/* enable subchannel demuxer on TS3 */
		subch_demux_activate(&line->ts[base_ts+5-1].trau.demux, 0);
		subch_demux_activate(&line->ts[base_ts+5-1].trau.demux, 1);
		subch_demux_activate(&line->ts[base_ts+5-1].trau.demux, 2);
		subch_demux_activate(&line->ts[base_ts+5-1].trau.demux, 3);
	}

	return mi_setup(cardnr, line, release_l2);
}

/* configure pseudo E1 line in ip.access style and connect to BTS */
int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin)
{
	struct e1inp_line *line;
	struct e1inp_ts *sign_ts, *rsl_ts;
	struct e1inp_sign_link *oml_link, *rsl_link;

	line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
	if (!line)
		return -ENOMEM;

	/* create E1 timeslots for signalling and TRAU frames */
	e1inp_ts_config(&line->ts[1-1], line, E1INP_TS_TYPE_SIGN);
	e1inp_ts_config(&line->ts[2-1], line, E1INP_TS_TYPE_SIGN);

	/* create signalling links for TS1 */
	sign_ts = &line->ts[1-1];
	rsl_ts = &line->ts[2-1];
	oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
					  bts->c0, 0, 0xff);
	rsl_link = e1inp_sign_link_create(rsl_ts, E1INP_SIGN_RSL,
					  bts->c0, 0, 0);

	/* create back-links from bts/trx */
	bts->oml_link = oml_link;
	bts->c0->rsl_link = rsl_link;

	/* default port at BTS for incoming connections is 3006 */
	if (sin->sin_port == 0)
		sin->sin_port = htons(3006);

	return ipaccess_connect(line, sin);
}