blob: 292a0e3acceeae3e1a134e94807c529d63117657 [file] [log] [blame]
Pablo Neira Ayusoad1ca982011-07-08 20:31:43 +02001#include <stdio.h>
Harald Welte71d87b22011-07-18 14:49:56 +02002#include <osmocom/core/talloc.h>
Pablo Neira Ayusoad1ca982011-07-08 20:31:43 +02003#include <osmocom/abis/abis.h>
4#include <osmocom/abis/e1_input.h>
5#include <osmocom/core/application.h>
6#include <osmocom/core/logging.h>
7#include <osmocom/gsm/protocol/gsm_12_21.h>
8
9static void *tall_test;
10static struct e1inp_sign_link *oml_sign_link, *rsl_sign_link;
11
12#define DBSCTEST 0
13
14struct log_info_cat bsc_test_cat[] = {
15 [DBSCTEST] = {
16 .name = "DBSCTEST",
17 .description = "BSC-mode test",
18 .color = "\033[1;35m",
19 .enabled = 1, .loglevel = LOGL_NOTICE,
20 },
21};
22
23static struct e1inp_sign_link *
24sign_link_up(void *dev, struct e1inp_line *line, enum e1inp_sign_type type)
25{
26 struct e1inp_sign_link *sign_link = NULL;
27
28 LOGP(DBSCTEST, LOGL_NOTICE, "Signal link up request received.\n");
29 e1inp_ts_config_sign(&line->ts[E1INP_SIGN_OML - 1], line);
30 sign_link = oml_sign_link =
31 e1inp_sign_link_create(&line->ts[E1INP_SIGN_OML - 1],
32 E1INP_SIGN_OML, NULL, 255, 0);
33 if (!oml_sign_link) {
34 LOGP(DBSCTEST, LOGL_ERROR, "OML link not yet set, giving up\n");
35 return NULL;
36 }
37 e1inp_ts_config_sign(&line->ts[E1INP_SIGN_RSL - 1], line);
38 sign_link = rsl_sign_link =
39 e1inp_sign_link_create(&line->ts[E1INP_SIGN_RSL - 1],
40 E1INP_SIGN_RSL, NULL, 0, 0);
41 if (sign_link)
42 LOGP(DBSCTEST, LOGL_NOTICE, "signal link has been set up.\n");
43
44 return sign_link;
45}
46
47static void sign_link_down(struct e1inp_line *line)
48{
49 LOGP(DBSCTEST, LOGL_NOTICE, "signal link has been closed\n");
50 if (oml_sign_link)
51 e1inp_sign_link_destroy(oml_sign_link);
52 if (rsl_sign_link)
53 e1inp_sign_link_destroy(rsl_sign_link);
54}
55
56static void fill_om_hdr(struct abis_om_hdr *oh, uint8_t len)
57{
58 oh->mdisc = ABIS_OM_MDISC_FOM;
59 oh->placement = ABIS_OM_PLACEMENT_ONLY;
60 oh->sequence = 0;
61 oh->length = len;
62}
63
64static void fill_om_fom_hdr(struct abis_om_hdr *oh, uint8_t len,
65 uint8_t msg_type, uint8_t obj_class,
66 uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr)
67{
68 struct abis_om_fom_hdr *foh =
69 (struct abis_om_fom_hdr *) oh->data;
70
71 fill_om_hdr(oh, len+sizeof(*foh));
72 foh->msg_type = msg_type;
73 foh->obj_class = obj_class;
74 foh->obj_inst.bts_nr = bts_nr;
75 foh->obj_inst.trx_nr = trx_nr;
76 foh->obj_inst.ts_nr = ts_nr;
77}
78
79#define OM_ALLOC_SIZE 1024
80#define OM_HEADROOM_SIZE 128
81
82static struct msgb *nm_msgb_alloc(void)
83{
84 return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML");
85}
86
87
88static int abis_nm_sw_act_req_ack(struct e1inp_sign_link *sign_link,
89 uint8_t obj_class,
90 uint8_t i1, uint8_t i2, uint8_t i3,
91 uint8_t *attr, int att_len)
92{
93 struct abis_om_hdr *oh;
94 struct msgb *msg = nm_msgb_alloc();
95 uint8_t msgtype = NM_MT_SW_ACT_REQ_ACK;
96
97 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
98 fill_om_fom_hdr(oh, att_len, msgtype, obj_class, i1, i2, i3);
99
100 if (attr) {
101 uint8_t *ptr = msgb_put(msg, att_len);
102 memcpy(ptr, attr, att_len);
103 }
104 msg->dst = sign_link;
105 return abis_sendmsg(msg);
106}
107
108static int abis_nm_rx_sw_act_req(struct msgb *msg)
109{
110 struct abis_om_hdr *oh = msgb_l2(msg);
111 struct abis_om_fom_hdr *foh = msgb_l3(msg);
112 int ret;
113
114 ret = abis_nm_sw_act_req_ack(msg->dst,
115 foh->obj_class,
116 foh->obj_inst.bts_nr,
117 foh->obj_inst.trx_nr,
118 foh->obj_inst.ts_nr,
119 foh->data, oh->length-sizeof(*foh));
120
121 return ret;
122}
123
124static int abis_nm_rcvmsg_fom(struct msgb *msg)
125{
126 struct abis_om_fom_hdr *foh = msgb_l3(msg);
127 uint8_t mt = foh->msg_type;
128 int ret = 0;
129
130 switch (mt) {
131 case NM_MT_SW_ACT_REQ: /* Software activate request from BTS. */
132 ret = abis_nm_rx_sw_act_req(msg);
133 break;
134 default:
135 break;
136 }
137 return ret;
138}
139
140static int abis_nm_rcvmsg(struct msgb *msg)
141{
142 int ret = 0;
143 struct abis_om_hdr *oh = msgb_l2(msg);
144
145 msg->l3h = (unsigned char *)oh + sizeof(*oh);
146 switch (oh->mdisc) {
147 case ABIS_OM_MDISC_FOM:
148 ret = abis_nm_rcvmsg_fom(msg);
149 break;
150 default:
151 LOGP(DBSCTEST, LOGL_ERROR, "unknown OML message\n");
152 break;
153 }
154 return ret;
155}
156
157static int sign_link(struct msgb *msg)
158{
159 int ret = 0;
160 struct e1inp_sign_link *link = msg->dst;
161
162 switch(link->type) {
163 case E1INP_SIGN_RSL:
164 LOGP(DBSCTEST, LOGL_NOTICE, "RSL message received.\n");
165 break;
166 case E1INP_SIGN_OML:
167 LOGP(DBSCTEST, LOGL_NOTICE, "OML message received.\n");
168 ret = abis_nm_rcvmsg(msg);
169 break;
170 default:
171 LOGP(DBSCTEST, LOGL_ERROR, "Unknown signallin message.\n");
172 break;
173 }
174 return ret;
175}
176
177const struct log_info bsc_test_log_info = {
178 .filter_fn = NULL,
179 .cat = bsc_test_cat,
180 .num_cat = ARRAY_SIZE(bsc_test_cat),
181};
182
183int main(void)
184{
185 struct e1inp_line *line;
186
187 tall_test = talloc_named_const(NULL, 1, "e1inp_test");
188 libosmo_abis_init(tall_test);
189
190 osmo_init_logging(&bsc_test_log_info);
191
192 struct e1inp_line_ops ops = {
193 .addr = "0.0.0.0",
194 .role = E1INP_LINE_R_BSC,
195 .sign_link_up = sign_link_up,
196 .sign_link_down = sign_link_down,
197 .sign_link = sign_link,
198 };
199
200#define LINENR 0
201
202 line = e1inp_line_create(LINENR, "hsl");
203 if (line == NULL) {
204 LOGP(DBSCTEST, LOGL_ERROR, "problem creating E1 line\n");
205 exit(EXIT_FAILURE);
206 }
207
208 e1inp_line_bind_ops(line, &ops);
209
210 /*
211 * Depending if this is a real or virtual E1 lines:
212 * - real (ISDN): create signal link for OML and RSL before line up.
213 * - vitual (INET): we create it in signal_link_up(...) callback.
214 *
215 * The signal link is created via e1inp_sign_link_create(...)
216 *
217 * See e1_reconfig_trx and e1_reconfig_bts in libbsc/e1_config.c,
218 * it explains how this is done with ISDN.
219 */
220
221 if (e1inp_line_update(line) < 0) {
222 LOGP(DBSCTEST, LOGL_ERROR, "problem creating E1 line\n");
223 exit(EXIT_FAILURE);
224 }
225
226 LOGP(DBSCTEST, LOGL_NOTICE, "entering main loop\n");
227
228 while (1) {
229 osmo_select_main(0);
230 }
231 return 0;
232}