blob: 3885dc975cd0a1c7af50376d3d4737c8e0d4f05d [file] [log] [blame]
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +02001#include <stdio.h>
Pablo Neira Ayuso54b49792011-06-07 12:15:26 +02002#include <talloc.h>
3#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");
65 e1inp_sign_link_destroy(oml_sign_link);
66 e1inp_sign_link_destroy(rsl_sign_link);
67}
68
Pablo Neira Ayuso904d8f22011-07-05 18:32:12 +020069static void fill_om_hdr(struct abis_om_hdr *oh, uint8_t len)
70{
71 oh->mdisc = ABIS_OM_MDISC_FOM;
72 oh->placement = ABIS_OM_PLACEMENT_ONLY;
73 oh->sequence = 0;
74 oh->length = len;
75}
76
77static void fill_om_fom_hdr(struct abis_om_hdr *oh, uint8_t len,
78 uint8_t msg_type, uint8_t obj_class,
79 uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr)
80{
81 struct abis_om_fom_hdr *foh =
82 (struct abis_om_fom_hdr *) oh->data;
83
84 fill_om_hdr(oh, len+sizeof(*foh));
85 foh->msg_type = msg_type;
86 foh->obj_class = obj_class;
87 foh->obj_inst.bts_nr = bts_nr;
88 foh->obj_inst.trx_nr = trx_nr;
89 foh->obj_inst.ts_nr = ts_nr;
90}
91
92#define OM_ALLOC_SIZE 1024
93#define OM_HEADROOM_SIZE 128
94
95static struct msgb *nm_msgb_alloc(void)
96{
97 return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML");
98}
99
100
101static int abis_nm_sw_act_req_ack(struct e1inp_sign_link *sign_link,
102 uint8_t obj_class,
103 uint8_t i1, uint8_t i2, uint8_t i3,
104 uint8_t *attr, int att_len)
105{
106 struct abis_om_hdr *oh;
107 struct msgb *msg = nm_msgb_alloc();
108 uint8_t msgtype = NM_MT_SW_ACT_REQ_ACK;
109
110 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
111 fill_om_fom_hdr(oh, att_len, msgtype, obj_class, i1, i2, i3);
112
113 if (attr) {
114 uint8_t *ptr = msgb_put(msg, att_len);
115 memcpy(ptr, attr, att_len);
116 }
117 msg->dst = sign_link;
118 return abis_sendmsg(msg);
119}
120
121static int abis_nm_rx_sw_act_req(struct msgb *msg)
122{
123 struct abis_om_hdr *oh = msgb_l2(msg);
124 struct abis_om_fom_hdr *foh = msgb_l3(msg);
125 int ret;
126
127 ret = abis_nm_sw_act_req_ack(msg->dst,
128 foh->obj_class,
129 foh->obj_inst.bts_nr,
130 foh->obj_inst.trx_nr,
131 foh->obj_inst.ts_nr,
132 foh->data, oh->length-sizeof(*foh));
133
134 return ret;
135}
136
137static int abis_nm_rcvmsg_fom(struct msgb *msg)
138{
139 struct abis_om_fom_hdr *foh = msgb_l3(msg);
140 uint8_t mt = foh->msg_type;
141 int ret = 0;
142
143 switch (mt) {
144 case NM_MT_SW_ACT_REQ: /* Software activate request from BTS. */
145 ret = abis_nm_rx_sw_act_req(msg);
146 break;
147 default:
148 break;
149 }
150 return ret;
151}
152
153static int abis_nm_rcvmsg(struct msgb *msg)
154{
155 int ret = 0;
156 struct abis_om_hdr *oh = msgb_l2(msg);
157
158 msg->l3h = (unsigned char *)oh + sizeof(*oh);
159 switch (oh->mdisc) {
160 case ABIS_OM_MDISC_FOM:
161 ret = abis_nm_rcvmsg_fom(msg);
162 break;
163 default:
164 LOGP(DBSCTEST, LOGL_ERROR, "unknown OML message\n");
165 break;
166 }
167 return ret;
168}
169
Pablo Neira Ayusodbd82fb2011-07-05 15:29:23 +0200170static int sign_link(struct msgb *msg)
Pablo Neira Ayuso2b352012011-07-02 17:45:42 +0200171{
Pablo Neira Ayuso904d8f22011-07-05 18:32:12 +0200172 int ret = 0;
173 struct e1inp_sign_link *link = msg->dst;
174
175 switch(link->type) {
176 case E1INP_SIGN_RSL:
177 LOGP(DBSCTEST, LOGL_NOTICE, "RSL message received.\n");
178 break;
179 case E1INP_SIGN_OML:
180 LOGP(DBSCTEST, LOGL_NOTICE, "OML message received.\n");
181 ret = abis_nm_rcvmsg(msg);
182 break;
183 default:
184 LOGP(DBSCTEST, LOGL_ERROR, "Unknown signallin message.\n");
185 break;
186 }
187 return ret;
Pablo Neira Ayuso2b352012011-07-02 17:45:42 +0200188}
189
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +0200190const struct log_info bsc_test_log_info = {
191 .filter_fn = NULL,
192 .cat = bsc_test_cat,
193 .num_cat = ARRAY_SIZE(bsc_test_cat),
194};
195
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200196int main(void)
197{
198 struct e1inp_line *line;
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200199
Pablo Neira Ayuso54b49792011-06-07 12:15:26 +0200200 tall_test = talloc_named_const(NULL, 1, "e1inp_test");
201 libosmo_abis_init(tall_test);
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200202
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +0200203 osmo_init_logging(&bsc_test_log_info);
204
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200205 struct e1inp_line_ops ops = {
Pablo Neira Ayusof163d232011-06-25 18:42:55 +0200206 .addr = "0.0.0.0",
207 .role = E1INP_LINE_R_BSC,
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200208 .sign_link_up = sign_link_up,
Pablo Neira Ayusoc9c4fd32011-06-30 12:19:42 +0200209 .sign_link_down = sign_link_down,
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200210 .sign_link = sign_link,
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200211 };
212
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200213#define LINENR 0
214
Pablo Neira Ayusof163d232011-06-25 18:42:55 +0200215 line = e1inp_line_create(LINENR, "ipa");
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200216 if (line == NULL) {
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +0200217 LOGP(DBSCTEST, LOGL_ERROR, "problem creating E1 line\n");
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200218 exit(EXIT_FAILURE);
219 }
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200220
Pablo Neira Ayusof163d232011-06-25 18:42:55 +0200221 e1inp_line_bind_ops(line, &ops);
222
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200223 /*
224 * Depending if this is a real or virtual E1 lines:
225 * - real (ISDN): create signal link for OML and RSL before line up.
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200226 * - vitual (INET): we create it in signal_link_up(...) callback.
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200227 *
228 * The signal link is created via e1inp_sign_link_create(...)
229 *
230 * See e1_reconfig_trx and e1_reconfig_bts in libbsc/e1_config.c,
231 * it explains how this is done with ISDN.
232 */
233
Pablo Neira Ayusof163d232011-06-25 18:42:55 +0200234 if (e1inp_line_update(line) < 0) {
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +0200235 LOGP(DBSCTEST, LOGL_ERROR, "problem creating E1 line\n");
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200236 exit(EXIT_FAILURE);
237 }
238
Pablo Neira Ayusoe19c70a2011-06-12 15:15:30 +0200239 LOGP(DBSCTEST, LOGL_NOTICE, "entering main loop\n");
240
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200241 while (1) {
242 osmo_select_main(0);
243 }
244 return 0;
245}