blob: a0e5653fe0b5ad19c6997d89294966a161e6ba20 [file] [log] [blame]
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +02001#include <stdio.h>
Harald Welte71d87b22011-07-18 14:49:56 +02002#include <osmocom/core/talloc.h>
Pablo Neira Ayuso54b49792011-06-07 12:15:26 +02003#include <osmocom/abis/abis.h>
Pablo Neira Ayuso177094b2011-06-07 12:21:51 +02004#include <osmocom/abis/e1_input.h>
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +02005#include <osmocom/core/application.h>
6#include <osmocom/core/logging.h>
Pablo Neira Ayuso904d8f22011-07-05 18:32:12 +02007#include <osmocom/gsm/protocol/gsm_12_21.h>
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +02008
Pablo Neira Ayuso54b49792011-06-07 12:15:26 +02009static void *tall_test;
Pablo Neira Ayusoc9c4fd32011-06-30 12:19:42 +020010static struct e1inp_sign_link *oml_sign_link, *rsl_sign_link;
Pablo Neira Ayuso54b49792011-06-07 12:15:26 +020011
Pablo Neira Ayusofe8ab0a2011-07-02 18:48:45 +020012#define DBSCTEST 0
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +020013
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
Pablo Neira Ayuso2b352012011-07-02 17:45:42 +020023static 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;
Pablo Neira Ayuso1ca98b92011-07-08 15:05:42 +020027 struct e1inp_line *oml_line;
Pablo Neira Ayuso2b352012011-07-02 17:45:42 +020028
29 switch(type) {
30 case E1INP_SIGN_OML:
31 LOGP(DBSCTEST, LOGL_NOTICE, "OML link up request received.\n");
32 e1inp_ts_config_sign(&line->ts[E1INP_SIGN_OML - 1], line);
33 sign_link = oml_sign_link =
34 e1inp_sign_link_create(&line->ts[E1INP_SIGN_OML - 1],
35 E1INP_SIGN_OML, NULL, 255, 0);
36 break;
37 case E1INP_SIGN_RSL:
Pablo Neira Ayuso1ca98b92011-07-08 15:05:42 +020038 if (!oml_sign_link) {
39 LOGP(DBSCTEST, LOGL_ERROR, "OML link not yet set, "
40 "giving up\n");
41 return NULL;
42 }
Pablo Neira Ayuso2b352012011-07-02 17:45:42 +020043 LOGP(DBSCTEST, LOGL_NOTICE, "RSL link up request received.\n");
Pablo Neira Ayuso1ca98b92011-07-08 15:05:42 +020044
45 /* We have to use the same line that the OML link. */
46 oml_line = oml_sign_link->ts->line;
47 e1inp_ts_config_sign(&oml_line->ts[E1INP_SIGN_RSL - 1],
48 oml_line);
Pablo Neira Ayuso2b352012011-07-02 17:45:42 +020049 sign_link = rsl_sign_link =
Pablo Neira Ayuso1ca98b92011-07-08 15:05:42 +020050 e1inp_sign_link_create(&oml_line->ts[E1INP_SIGN_RSL - 1],
51 E1INP_SIGN_RSL, NULL, 0, 0);
Pablo Neira Ayuso2b352012011-07-02 17:45:42 +020052 break;
53 default:
54 break;
55 }
56 if (sign_link)
57 LOGP(DBSCTEST, LOGL_NOTICE, "signal link has been set up.\n");
58
59 return sign_link;
60}
61
62static void sign_link_down(struct e1inp_line *line)
63{
64 LOGP(DBSCTEST, LOGL_NOTICE, "signal link has been closed\n");
Pablo Neira Ayuso5a8cca32012-08-22 14:01:49 +020065 if (oml_sign_link) {
Pablo Neira Ayuso49bc8722011-07-08 15:23:36 +020066 e1inp_sign_link_destroy(oml_sign_link);
Pablo Neira Ayuso5a8cca32012-08-22 14:01:49 +020067 oml_sign_link = NULL;
68 }
69 if (rsl_sign_link) {
Pablo Neira Ayuso49bc8722011-07-08 15:23:36 +020070 e1inp_sign_link_destroy(rsl_sign_link);
Pablo Neira Ayuso5a8cca32012-08-22 14:01:49 +020071 rsl_sign_link = NULL;
72 }
Pablo Neira Ayuso2b352012011-07-02 17:45:42 +020073}
74
Pablo Neira Ayuso904d8f22011-07-05 18:32:12 +020075static void fill_om_hdr(struct abis_om_hdr *oh, uint8_t len)
76{
77 oh->mdisc = ABIS_OM_MDISC_FOM;
78 oh->placement = ABIS_OM_PLACEMENT_ONLY;
79 oh->sequence = 0;
80 oh->length = len;
81}
82
83static void fill_om_fom_hdr(struct abis_om_hdr *oh, uint8_t len,
84 uint8_t msg_type, uint8_t obj_class,
85 uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr)
86{
87 struct abis_om_fom_hdr *foh =
88 (struct abis_om_fom_hdr *) oh->data;
89
90 fill_om_hdr(oh, len+sizeof(*foh));
91 foh->msg_type = msg_type;
92 foh->obj_class = obj_class;
93 foh->obj_inst.bts_nr = bts_nr;
94 foh->obj_inst.trx_nr = trx_nr;
95 foh->obj_inst.ts_nr = ts_nr;
96}
97
98#define OM_ALLOC_SIZE 1024
99#define OM_HEADROOM_SIZE 128
100
101static struct msgb *nm_msgb_alloc(void)
102{
103 return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML");
104}
105
106
107static int abis_nm_sw_act_req_ack(struct e1inp_sign_link *sign_link,
108 uint8_t obj_class,
109 uint8_t i1, uint8_t i2, uint8_t i3,
110 uint8_t *attr, int att_len)
111{
112 struct abis_om_hdr *oh;
113 struct msgb *msg = nm_msgb_alloc();
114 uint8_t msgtype = NM_MT_SW_ACT_REQ_ACK;
115
116 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
117 fill_om_fom_hdr(oh, att_len, msgtype, obj_class, i1, i2, i3);
118
119 if (attr) {
120 uint8_t *ptr = msgb_put(msg, att_len);
121 memcpy(ptr, attr, att_len);
122 }
123 msg->dst = sign_link;
124 return abis_sendmsg(msg);
125}
126
127static int abis_nm_rx_sw_act_req(struct msgb *msg)
128{
129 struct abis_om_hdr *oh = msgb_l2(msg);
130 struct abis_om_fom_hdr *foh = msgb_l3(msg);
131 int ret;
132
133 ret = abis_nm_sw_act_req_ack(msg->dst,
134 foh->obj_class,
135 foh->obj_inst.bts_nr,
136 foh->obj_inst.trx_nr,
137 foh->obj_inst.ts_nr,
138 foh->data, oh->length-sizeof(*foh));
139
140 return ret;
141}
142
143static int abis_nm_rcvmsg_fom(struct msgb *msg)
144{
145 struct abis_om_fom_hdr *foh = msgb_l3(msg);
146 uint8_t mt = foh->msg_type;
147 int ret = 0;
148
149 switch (mt) {
150 case NM_MT_SW_ACT_REQ: /* Software activate request from BTS. */
151 ret = abis_nm_rx_sw_act_req(msg);
152 break;
153 default:
154 break;
155 }
156 return ret;
157}
158
159static int abis_nm_rcvmsg(struct msgb *msg)
160{
161 int ret = 0;
162 struct abis_om_hdr *oh = msgb_l2(msg);
163
164 msg->l3h = (unsigned char *)oh + sizeof(*oh);
165 switch (oh->mdisc) {
166 case ABIS_OM_MDISC_FOM:
167 ret = abis_nm_rcvmsg_fom(msg);
168 break;
169 default:
170 LOGP(DBSCTEST, LOGL_ERROR, "unknown OML message\n");
171 break;
172 }
173 return ret;
174}
175
Pablo Neira Ayusodbd82fb2011-07-05 15:29:23 +0200176static int sign_link(struct msgb *msg)
Pablo Neira Ayuso2b352012011-07-02 17:45:42 +0200177{
Pablo Neira Ayuso904d8f22011-07-05 18:32:12 +0200178 int ret = 0;
179 struct e1inp_sign_link *link = msg->dst;
180
181 switch(link->type) {
182 case E1INP_SIGN_RSL:
183 LOGP(DBSCTEST, LOGL_NOTICE, "RSL message received.\n");
184 break;
185 case E1INP_SIGN_OML:
186 LOGP(DBSCTEST, LOGL_NOTICE, "OML message received.\n");
187 ret = abis_nm_rcvmsg(msg);
188 break;
189 default:
190 LOGP(DBSCTEST, LOGL_ERROR, "Unknown signallin message.\n");
191 break;
192 }
193 return ret;
Pablo Neira Ayuso2b352012011-07-02 17:45:42 +0200194}
195
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +0200196const struct log_info bsc_test_log_info = {
197 .filter_fn = NULL,
198 .cat = bsc_test_cat,
199 .num_cat = ARRAY_SIZE(bsc_test_cat),
200};
201
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200202int main(void)
203{
204 struct e1inp_line *line;
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200205
Pablo Neira Ayuso54b49792011-06-07 12:15:26 +0200206 tall_test = talloc_named_const(NULL, 1, "e1inp_test");
207 libosmo_abis_init(tall_test);
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200208
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +0200209 osmo_init_logging(&bsc_test_log_info);
210
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200211 struct e1inp_line_ops ops = {
Pablo Neira Ayuso4e862cb2011-08-19 18:43:38 +0200212 .cfg = {
213 .ipa = {
214 .addr = "0.0.0.0",
215 .role = E1INP_LINE_R_BSC,
216 },
217 },
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200218 .sign_link_up = sign_link_up,
Pablo Neira Ayusoc9c4fd32011-06-30 12:19:42 +0200219 .sign_link_down = sign_link_down,
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200220 .sign_link = sign_link,
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200221 };
222
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200223#define LINENR 0
224
Pablo Neira Ayusof163d232011-06-25 18:42:55 +0200225 line = e1inp_line_create(LINENR, "ipa");
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200226 if (line == NULL) {
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +0200227 LOGP(DBSCTEST, LOGL_ERROR, "problem creating E1 line\n");
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200228 exit(EXIT_FAILURE);
229 }
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200230
Pablo Neira Ayusof163d232011-06-25 18:42:55 +0200231 e1inp_line_bind_ops(line, &ops);
232
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200233 /*
234 * Depending if this is a real or virtual E1 lines:
235 * - real (ISDN): create signal link for OML and RSL before line up.
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200236 * - vitual (INET): we create it in signal_link_up(...) callback.
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200237 *
238 * The signal link is created via e1inp_sign_link_create(...)
239 *
240 * See e1_reconfig_trx and e1_reconfig_bts in libbsc/e1_config.c,
241 * it explains how this is done with ISDN.
242 */
243
Pablo Neira Ayusof163d232011-06-25 18:42:55 +0200244 if (e1inp_line_update(line) < 0) {
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +0200245 LOGP(DBSCTEST, LOGL_ERROR, "problem creating E1 line\n");
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200246 exit(EXIT_FAILURE);
247 }
248
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +0200249 LOGP(DBSCTEST, LOGL_NOTICE, "entering main loop\n");
250
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200251 while (1) {
252 osmo_select_main(0);
253 }
254 return 0;
255}