Codebase list libosmo-netif / upstream/latest
New upstream version 0.3.0 Ruben Undheim 5 years ago
27 changed file(s) with 144 addition(s) and 1158 deletion(s). Raw diff Collapse all Expand all
3434 tests/osmux/osmux_test
3535 tests/testsuite.log
3636
37 examples/channel/abis_ipa_stream_client
38 examples/channel/abis_ipa_stream_server
3937 examples/ipa-stream-client
4038 examples/ipa-stream-server
4139 examples/lapd-over-datagram-network
8181 dnl Generate the output
8282 AM_CONFIG_HEADER(config.h)
8383
84 PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.11.0)
85 PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.11.0)
84 PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.12.0)
85 PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.12.0)
8686 dnl FIXME: We depend on libosmoabis by now until we can move LAPD code here
87 PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.5.0)
87 PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.5.1)
8888
8989 old_LIBS=$LIBS
9090 AC_SEARCH_LIBS([sctp_send], [sctp], [
117117 include/Makefile
118118 include/osmocom/Makefile
119119 include/osmocom/netif/Makefile
120 include/osmocom/netif/channel/Makefile
121120 src/Makefile
122 src/channel/Makefile
123 src/channel/abis/Makefile
124121 examples/Makefile
125 examples/channel/Makefile
126122 tests/Makefile
127123 Doxyfile
128124 Makefile)
0 libosmo-netif (0.3.0) unstable; urgency=medium
1
2 [ Pau Espin Pedrol ]
3 * tests: jibuf_test: Set some functions as static
4 * tests: jibuf_test: Add scenario to show out-of-order bug
5 * jibuf: Fix out-of-order seq queue around syncpoints
6 * osmux: change log lvl of batch full to debug
7
8 [ Harald Welte ]
9 * remove "channel" layer
10 * stream.c: Use non-blocking connect in osmo_stream_cli
11
12 -- Pau Espin Pedrol <pespin@sysmocom.de> Fri, 27 Jul 2018 18:31:42 +0200
13
014 libosmo-netif (0.2.0) unstable; urgency=medium
115
216 [ Neels Hofmeyr ]
2020 Vcs-Git: git://git.osmocom.org/libosmo-netif.git
2121 Homepage: https://projects.osmocom.org/projects/libosmo-netif
2222
23 Package: libosmonetif4
23 Package: libosmonetif6
2424 Section: libs
2525 Architecture: any
2626 Depends: ${shlibs:Depends}, ${misc:Depends}
3737 Depends: ${misc:Depends},
3838 libosmocore-dev,
3939 libosmocore,
40 libosmonetif4 (= ${binary:Version})
40 libosmonetif6 (= ${binary:Version})
4141 Multi-Arch: same
4242 Description: Development headers for Osmocom network interface
4343 The libosmo-netif library is one of the libraries needed by the
5151 Architecture: all
5252 Section: doc
5353 Depends: ${misc:Depends},
54 libosmonetif4,
54 libosmonetif6,
5555 libjs-jquery
5656 Description: Documentation for the Osmo network interface library
5757 The libosmo-netif library is one of the libraries needed by the
6464 Section: debug
6565 Architecture: any
6666 Priority: extra
67 Depends: libosmonetif4 (= ${binary:Version}), ${misc:Depends}
67 Depends: libosmonetif6 (= ${binary:Version}), ${misc:Depends}
6868 Multi-Arch: same
6969 Description: Debug symbols for Osmocom network interface library
7070 The libosmo-netif library is one of the libraries needed by the
+0
-1
debian/libosmonetif4.install less more
0 usr/lib/*/libosmonetif*.so.*
0 usr/lib/*/libosmonetif*.so.*
00 AM_CPPFLAGS = -I$(top_srcdir)/include
11 AM_CFLAGS=-Wall -g $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS)
22 AM_LDFLAGS = $(COVERAGE_LDFLAGS)
3
4 SUBDIRS = channel
53
64 noinst_PROGRAMS = ipa-stream-client \
75 ipa-stream-server \
+0
-14
examples/channel/Makefile.am less more
0 AM_CPPFLAGS = -I$(top_srcdir)/include
1 AM_CFLAGS=-Wall -g $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS)
2 AM_LDFLAGS = $(COVERAGE_LDFLAGS)
3
4 noinst_PROGRAMS = abis_ipa_stream_server \
5 abis_ipa_stream_client
6
7 abis_ipa_stream_server_SOURCES = abis_ipa_stream_server.c
8 abis_ipa_stream_server_LDADD = $(top_builddir)/src/libosmonetif.la \
9 $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
10
11 abis_ipa_stream_client_SOURCES = abis_ipa_stream_client.c
12 abis_ipa_stream_client_LDADD = $(top_builddir)/src/libosmonetif.la \
13 $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
+0
-92
examples/channel/abis_ipa_stream_client.c less more
0 #include <stdio.h>
1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4
5 #include <osmocom/core/select.h>
6 #include <osmocom/core/talloc.h>
7 #include <osmocom/core/msgb.h>
8 #include <osmocom/core/logging.h>
9 #include <osmocom/core/application.h>
10
11 #include <osmocom/netif/channel.h>
12 #include <osmocom/netif/channel/abis_ipa_client.h>
13 #include <osmocom/netif/ipa_unit.h>
14
15 static void *tall_example;
16
17 #define DEXAMPLE 0
18
19 struct log_info_cat example_cat[] = {
20 [DEXAMPLE] = {
21 .name = "DEXAMPLE",
22 .description = "example",
23 .color = "\033[1;35m",
24 .enabled = 1, .loglevel = LOGL_DEBUG,
25 },
26 };
27
28 const struct log_info example_log_info = {
29 .filter_fn = NULL,
30 .cat = example_cat,
31 .num_cat = ARRAY_SIZE(example_cat),
32 };
33
34 void sighandler(int foo)
35 {
36 LOGP(DEXAMPLE, LOGL_NOTICE, "closing test.\n");
37 exit(EXIT_SUCCESS);
38 }
39
40 static void signal_msg_cb(struct msgb *msg, int type)
41 {
42 LOGP(DEXAMPLE, LOGL_NOTICE, "received signal message\n");
43 }
44
45 static struct osmo_chan *chan;
46
47 int main(void)
48 {
49 struct osmo_ipa_unit *unit;
50
51 tall_example = talloc_named_const(NULL, 1, "example");
52 msgb_talloc_ctx_init(tall_example, 0);
53 osmo_init_logging2(tall_example, &example_log_info);
54 log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
55
56 /* initialize channel infrastructure. */
57 osmo_chan_init(tall_example);
58
59 /* create channel. */
60 chan = osmo_chan_create(OSMO_CHAN_ABIS_IPA_CLI, OSMO_SUBCHAN_STREAM);
61 if (chan == NULL) {
62 LOGP(DEXAMPLE, LOGL_ERROR, "Cannot create A-bis IPA client\n");
63 exit(EXIT_FAILURE);
64 }
65
66 /* set specific parameters (depends on channel type). */
67 osmo_abis_ipa_cli_set_oml_addr(chan, "127.0.0.1");
68 osmo_abis_ipa_cli_set_rsl_addr(chan, "127.0.0.1");
69
70 unit = osmo_ipa_unit_alloc(0);
71 if (unit == NULL) {
72 LOGP(DEXAMPLE, LOGL_ERROR, "Cannot create IPA unit\n");
73 exit(EXIT_FAILURE);
74 }
75 osmo_ipa_unit_set_site_id(unit, 1801);
76
77 osmo_abis_ipa_cli_set_unit(chan, unit);
78 osmo_abis_ipa_cli_set_cb_signalmsg(chan, signal_msg_cb);
79
80 /* open channel. */
81 if (osmo_chan_open(chan) < 0) {
82 LOGP(DEXAMPLE, LOGL_ERROR, "Cannot create A-bis IPA client\n");
83 exit(EXIT_FAILURE);
84 }
85
86 LOGP(DEXAMPLE, LOGL_NOTICE, "Entering main loop\n");
87
88 while(1) {
89 osmo_select_main(0);
90 }
91 }
+0
-79
examples/channel/abis_ipa_stream_server.c less more
0 #include <stdio.h>
1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4
5 #include <osmocom/core/select.h>
6 #include <osmocom/core/talloc.h>
7 #include <osmocom/core/msgb.h>
8 #include <osmocom/core/logging.h>
9 #include <osmocom/core/application.h>
10
11 #include <osmocom/netif/channel.h>
12 #include <osmocom/netif/channel/abis_ipa_server.h>
13
14 static void *tall_example;
15
16 #define DEXAMPLE 0
17
18 struct log_info_cat example_cat[] = {
19 [DEXAMPLE] = {
20 .name = "DEXAMPLE",
21 .description = "example",
22 .color = "\033[1;35m",
23 .enabled = 1, .loglevel = LOGL_DEBUG,
24 },
25 };
26
27 const struct log_info example_log_info = {
28 .filter_fn = NULL,
29 .cat = example_cat,
30 .num_cat = ARRAY_SIZE(example_cat),
31 };
32
33 void sighandler(int foo)
34 {
35 LOGP(DEXAMPLE, LOGL_NOTICE, "closing test.\n");
36 exit(EXIT_SUCCESS);
37 }
38
39 static void signal_msg_cb(struct msgb *msg, int type)
40 {
41 LOGP(DEXAMPLE, LOGL_NOTICE, "received signal message\n");
42 }
43
44 static struct osmo_chan *chan;
45
46 int main(void)
47 {
48 tall_example = talloc_named_const(NULL, 1, "example");
49 msgb_talloc_ctx_init(tall_example, 0);
50 osmo_init_logging2(tall_example, &example_log_info);
51 log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
52
53 /* initialize channel infrastructure. */
54 osmo_chan_init(tall_example);
55
56 /* create channel. */
57 chan = osmo_chan_create(OSMO_CHAN_ABIS_IPA_SRV, OSMO_SUBCHAN_STREAM);
58 if (chan == NULL) {
59 LOGP(DEXAMPLE, LOGL_ERROR, "Cannot create A-bis IPA server\n");
60 exit(EXIT_FAILURE);
61 }
62
63 /* set specific parameters (depends on channel type). */
64 osmo_abis_ipa_srv_set_cb_signalmsg(chan, signal_msg_cb);
65 osmo_abis_ipa_unit_add(chan, 1801, 0);
66
67 /* open channel. */
68 if (osmo_chan_open(chan) < 0) {
69 LOGP(DEXAMPLE, LOGL_ERROR, "Cannot create A-bis IPA server\n");
70 exit(EXIT_FAILURE);
71 }
72
73 LOGP(DEXAMPLE, LOGL_NOTICE, "Entering main loop\n");
74
75 while(1) {
76 osmo_select_main(0);
77 }
78 }
0 SUBDIRS = channel
1
20 osmonetif_HEADERS = amr.h \
3 channel.h \
41 datagram.h \
52 jibuf.h \
63 osmux.h \
+0
-3
include/osmocom/netif/channel/Makefile.am less more
0 osmonetif_channel_HEADERS = abis_ipa_server.h abis_ipa_client.h
1
2 osmonetif_channeldir = $(includedir)/osmocom/netif/channel
+0
-13
include/osmocom/netif/channel/abis_ipa_client.h less more
0 #ifndef _OSMO_ABIS_IPA_CLIENT_H_
1 #define _OSMO_ABIS_IPA_CLIENT_H_
2
3 struct osmo_ipa_unit;
4
5 void osmo_abis_ipa_cli_set_oml_addr(struct osmo_chan *c, const char *addr);
6 void osmo_abis_ipa_cli_set_oml_port(struct osmo_chan *c, uint16_t port);
7 void osmo_abis_ipa_cli_set_rsl_addr(struct osmo_chan *c, const char *addr);
8 void osmo_abis_ipa_cli_set_rsl_port(struct osmo_chan *c, uint16_t port);
9 void osmo_abis_ipa_cli_set_unit(struct osmo_chan *c, struct osmo_ipa_unit *unit);
10 void osmo_abis_ipa_cli_set_cb_signalmsg(struct osmo_chan *c, void (*signal_msg)(struct msgb *msg, int type));
11
12 #endif /* _OSMO_ABIS_IPA_CLIENT_H_ */
+0
-14
include/osmocom/netif/channel/abis_ipa_server.h less more
0 #ifndef _ABIS_IPA_SERVER_H_
1 #define _ABIS_IPA_SERVER_H_
2
3 void osmo_abis_ipa_srv_set_oml_addr(struct osmo_chan *c, const char *addr);
4 void osmo_abis_ipa_srv_set_oml_port(struct osmo_chan *c, uint16_t port);
5
6 void osmo_abis_ipa_srv_set_rsl_addr(struct osmo_chan *c, const char *addr);
7 void osmo_abis_ipa_srv_set_rsl_port(struct osmo_chan *c, uint16_t port);
8
9 void osmo_abis_ipa_srv_set_cb_signalmsg(struct osmo_chan *c, void (*signal_msg)(struct msgb *msg, int type));
10
11 int osmo_abis_ipa_unit_add(struct osmo_chan *c, uint16_t site_id, uint16_t bts_id);
12
13 #endif
+0
-54
include/osmocom/netif/channel.h less more
0 #ifndef _CHANNEL_H_
1 #define _CHANNEL_H_
2
3 #include <stdint.h>
4
5 /* channel types */
6 enum {
7 OSMO_CHAN_NONE,
8 OSMO_CHAN_ABIS_IPA_SRV,
9 OSMO_CHAN_ABIS_IPA_CLI,
10 OSMO_CHAN_MAX,
11 };
12
13 /* channel subtypes */
14 enum {
15 OSMO_SUBCHAN_STREAM,
16 OSMO_SUBCHAN_MAX,
17 };
18
19 struct osmo_chan;
20 struct msgb;
21
22 struct osmo_chan_type {
23 struct llist_head head;
24
25 char *name;
26 int type;
27 int subtype;
28 int datasiz;
29
30 int (*create)(struct osmo_chan *chan);
31 void (*destroy)(struct osmo_chan *chan);
32 int (*open)(struct osmo_chan *chan);
33 void (*close)(struct osmo_chan *chan);
34 int (*enqueue)(struct osmo_chan *chan, struct msgb *msg);
35 };
36
37 struct osmo_chan {
38 void *ctx;
39 struct osmo_chan_type *ops;
40 char data[0];
41 };
42
43 void osmo_chan_init(void *ctx);
44
45 struct osmo_chan *osmo_chan_create(int type, int subtype);
46 void osmo_chan_destroy(struct osmo_chan *c);
47
48 int osmo_chan_open(struct osmo_chan *c);
49 void osmo_chan_close(struct osmo_chan *c);
50
51 int osmo_chan_enqueue(struct osmo_chan *c, struct msgb *msg);
52
53 #endif /* _CHANNEL_H_ */
00 # This is _NOT_ the library release version, it's an API version.
11 # Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
2 LIBVERSION=5:0:1
2 LIBVERSION=6:0:0
33
44 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)
55 AM_CFLAGS= -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS) $(LIBSCTP_CFLAGS)
66 AM_LDFLAGS = $(COVERAGE_LDFLAGS)
77
8 SUBDIRS = channel
9
108 lib_LTLIBRARIES = libosmonetif.la
119
12 libosmonetif_la_LIBADD = channel/abis/libosmonetif-abis.la $(LIBOSMOCORE_LIBS) $(LIBSCTP_LIBS)
10 libosmonetif_la_LIBADD = $(LIBOSMOCORE_LIBS) $(LIBSCTP_LIBS)
1311 libosmonetif_la_LDFLAGS = -version-info $(LIBVERSION) -no-undefined
1412
1513 libosmonetif_la_SOURCES = amr.c \
16 channel.c \
1714 datagram.c \
1815 ipa.c \
1916 ipa_unit.c \
+0
-1
src/channel/Makefile.am less more
0 SUBDIRS = abis
+0
-9
src/channel/abis/Makefile.am less more
0 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)
1 AM_CFLAGS= -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
2 AM_LDFLAGS = $(COVERAGE_LDFLAGS)
3
4 noinst_LTLIBRARIES = libosmonetif-abis.la
5
6 libosmonetif_abis_la_SOURCES = ipa_stream_server.c \
7 ipa_stream_client.c
8 libosmonetif_abis_la_LIBADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS)
+0
-309
src/channel/abis/ipa_stream_client.c less more
0 /* (C) 2012 by Pablo Neira Ayuso <pablo@gnumonks.org>
1 * All Rights Reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0+
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdlib.h>
20 #include <sys/types.h>
21 #include <netinet/in.h>
22 #include <netinet/tcp.h>
23 #include <sys/socket.h>
24 #include <errno.h>
25
26 #include <osmocom/core/talloc.h>
27 #include <osmocom/core/select.h>
28 #include <osmocom/core/msgb.h>
29 #include <osmocom/core/logging.h>
30
31 #include <osmocom/gsm/tlv.h>
32
33 #include <osmocom/netif/channel.h>
34 #include <osmocom/netif/stream.h>
35 #include <osmocom/netif/ipa.h>
36 #include <osmocom/netif/ipa_unit.h>
37
38 #define CHAN_SIGN_OML 0
39 #define CHAN_SIGN_RSL 1
40
41 /* default IPA cli ports. */
42 #define IPA_TCP_PORT_OML 3002
43 #define IPA_TCP_PORT_RSL 3003
44
45 static void *abis_ipa_cli_tall;
46
47 struct chan_abis_ipa_cli {
48 struct osmo_ipa_unit *unit;
49
50 struct osmo_stream_cli *oml;
51 struct osmo_stream_cli *rsl;
52
53 void (*signal_msg)(struct msgb *msg, int type);
54 };
55
56 static int oml_read_cb(struct osmo_stream_cli *conn);
57 static int rsl_read_cb(struct osmo_stream_cli *conn);
58
59 static int chan_abis_ipa_cli_create(struct osmo_chan *chan)
60 {
61 struct chan_abis_ipa_cli *c = (struct chan_abis_ipa_cli *)chan->data;
62
63 c->unit = osmo_ipa_unit_alloc(0);
64 if (c->unit == NULL)
65 goto err;
66
67 c->oml = osmo_stream_cli_create(abis_ipa_cli_tall);
68 if (c->oml == NULL)
69 goto err_oml;
70
71 /* default address and port for OML. */
72 osmo_stream_cli_set_addr(c->oml, "0.0.0.0");
73 osmo_stream_cli_set_port(c->oml, IPA_TCP_PORT_OML);
74 osmo_stream_cli_set_read_cb(c->oml, oml_read_cb);
75 osmo_stream_cli_set_data(c->oml, chan);
76
77 c->rsl = osmo_stream_cli_create(abis_ipa_cli_tall);
78 if (c->rsl == NULL)
79 goto err_rsl;
80
81 /* default address and port for RSL. */
82 osmo_stream_cli_set_addr(c->rsl, "0.0.0.0");
83 osmo_stream_cli_set_port(c->rsl, IPA_TCP_PORT_RSL);
84 osmo_stream_cli_set_read_cb(c->rsl, rsl_read_cb);
85 osmo_stream_cli_set_data(c->rsl, chan);
86
87 return 0;
88 err_rsl:
89 osmo_stream_cli_destroy(c->oml);
90 err_oml:
91 osmo_ipa_unit_free(c->unit);
92 err:
93 return -1;
94 }
95
96 static void chan_abis_ipa_cli_destroy(struct osmo_chan *chan)
97 {
98 struct chan_abis_ipa_cli *c = (struct chan_abis_ipa_cli *)chan->data;
99
100 osmo_ipa_unit_free(c->unit);
101 talloc_free(c->rsl);
102 talloc_free(c->oml);
103 }
104
105 static int chan_abis_ipa_cli_open(struct osmo_chan *chan)
106 {
107 struct chan_abis_ipa_cli *c = (struct chan_abis_ipa_cli *)chan->data;
108 struct osmo_fd *ofd;
109 int ret, on = 1;
110
111 if (osmo_stream_cli_open(c->oml) < 0)
112 goto err;
113
114 ofd = osmo_stream_cli_get_ofd(c->oml);
115 ret = setsockopt(ofd->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
116 if (ret < 0)
117 goto err_oml;
118
119 if (osmo_stream_cli_open(c->rsl) < 0)
120 goto err_oml;
121
122 ofd = osmo_stream_cli_get_ofd(c->rsl);
123 ret = setsockopt(ofd->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
124 if (ret < 0)
125 goto err_rsl;
126
127 return 0;
128
129 err_rsl:
130 osmo_stream_cli_close(c->rsl);
131 err_oml:
132 osmo_stream_cli_close(c->oml);
133 err:
134 return -1;
135 }
136
137 static void chan_abis_ipa_cli_close(struct osmo_chan *chan)
138 {
139 struct chan_abis_ipa_cli *c = (struct chan_abis_ipa_cli *)chan->data;
140
141 osmo_stream_cli_close(c->oml);
142 osmo_stream_cli_close(c->rsl);
143 }
144
145 static int chan_abis_ipa_cli_enqueue(struct osmo_chan *c, struct msgb *msg)
146 {
147 osmo_stream_cli_send(msg->dst, msg);
148 return 0;
149 }
150
151 void osmo_abis_ipa_cli_set_oml_addr(struct osmo_chan *c, const char *addr)
152 {
153 struct chan_abis_ipa_cli *s = (struct chan_abis_ipa_cli *)&c->data;
154
155 osmo_stream_cli_set_addr(s->oml, addr);
156 }
157
158 void osmo_abis_ipa_cli_set_oml_port(struct osmo_chan *c, uint16_t port)
159 {
160 struct chan_abis_ipa_cli *s = (struct chan_abis_ipa_cli *)&c->data;
161
162 osmo_stream_cli_set_port(s->oml, port);
163 }
164
165 void osmo_abis_ipa_cli_set_rsl_addr(struct osmo_chan *c, const char *addr)
166 {
167 struct chan_abis_ipa_cli *s = (struct chan_abis_ipa_cli *)&c->data;
168
169 osmo_stream_cli_set_addr(s->rsl, addr);
170 }
171
172 void osmo_abis_ipa_cli_set_rsl_port(struct osmo_chan *c, uint16_t port)
173 {
174 struct chan_abis_ipa_cli *s = (struct chan_abis_ipa_cli *)&c->data;
175
176 osmo_stream_cli_set_port(s->rsl, port);
177 }
178
179 void osmo_abis_ipa_cli_set_unit(struct osmo_chan *c, struct osmo_ipa_unit *unit)
180 {
181 struct chan_abis_ipa_cli *s = (struct chan_abis_ipa_cli *)&c->data;
182
183 osmo_ipa_unit_free(s->unit);
184 s->unit = unit;
185 }
186
187 void osmo_abis_ipa_cli_set_cb_signalmsg(struct osmo_chan *c,
188 void (*signal_msg)(struct msgb *msg, int type))
189 {
190 struct chan_abis_ipa_cli *s = (struct chan_abis_ipa_cli *)&c->data;
191
192 s->signal_msg = signal_msg;
193 }
194
195 static int
196 abis_ipa_cli_rcvmsg(struct osmo_chan *c, struct osmo_stream_cli *conn,
197 struct msgb *msg, int type)
198 {
199 uint8_t msg_type = *(msg->l2h);
200 struct osmo_fd *ofd = osmo_stream_cli_get_ofd(conn);
201 struct chan_abis_ipa_cli *chan = (struct chan_abis_ipa_cli *)&c->data;
202 int ret;
203
204 /* Handle IPA PING, PONG and ID_ACK messages. */
205 if (osmo_ipa_rcvmsg_base(msg, ofd, 0)) /* XXX: 0 indicates client */
206 return 0;
207
208 if (msg_type == IPAC_MSGT_ID_GET) {
209 struct msgb *rmsg;
210 uint8_t *data = msgb_l2(msg);
211 int len = msgb_l2len(msg);
212
213 LOGP(DLINP, LOGL_NOTICE, "received ID get\n");
214
215 rmsg = ipa_cli_id_resp(chan->unit, data + 1, len - 1);
216 osmo_stream_cli_send(conn, rmsg);
217
218 /* send ID_ACK. */
219 rmsg = ipa_cli_id_ack();
220 osmo_stream_cli_send(conn, rmsg);
221 ret = 0;
222 } else {
223 LOGP(DLINP, LOGL_ERROR, "Unknown IPA message type\n");
224 ret = -EINVAL;
225 }
226 return ret;
227 }
228
229 static int read_cb(struct osmo_stream_cli *conn, int type)
230 {
231 int ret;
232 struct msgb *msg;
233 struct osmo_chan *chan = osmo_stream_cli_get_data(conn);
234 struct chan_abis_ipa_cli *s;
235 struct ipa_head *hh;
236
237 LOGP(DLINP, LOGL_DEBUG, "received message from stream\n");
238
239 msg = osmo_ipa_msg_alloc(0);
240 if (msg == NULL) {
241 LOGP(DLINP, LOGL_ERROR, "cannot allocate message\n");
242 return 0;
243 }
244 ret = osmo_stream_cli_recv(conn, msg);
245 if (ret < 0) {
246 LOGP(DLINP, LOGL_ERROR, "cannot receive message\n");
247 msgb_free(msg);
248 /* not the dummy connection, release it. */
249 return 0;
250 } else if (ret == 0) {
251 /* link has vanished, dead socket. */
252 LOGP(DLINP, LOGL_ERROR, "closed connection\n");
253 msgb_free(msg);
254 return 0;
255 }
256
257 if (osmo_ipa_process_msg(msg) < 0) {
258 LOGP(DLINP, LOGL_ERROR, "Bad IPA message\n");
259 msgb_free(msg);
260 return -EIO;
261 }
262
263 hh = (struct ipa_head *) msg->data;
264 if (hh->proto == IPAC_PROTO_IPACCESS) {
265 abis_ipa_cli_rcvmsg(chan, conn, msg, type);
266 msgb_free(msg);
267 return -EIO;
268 }
269
270 chan = osmo_stream_cli_get_data(conn);
271 if (chan == NULL) {
272 LOGP(DLINP, LOGL_ERROR, "no matching signalling link\n");
273 msgb_free(msg);
274 return -EIO;
275 }
276 if (hh->proto != IPAC_PROTO_OML && hh->proto != IPAC_PROTO_RSL) {
277 LOGP(DLINP, LOGL_ERROR, "wrong protocol\n");
278 return -EIO;
279 }
280 msg->dst = chan;
281
282 s = (struct chan_abis_ipa_cli *)chan->data;
283 s->signal_msg(msg, type);
284
285 return 0;
286 }
287
288 static int oml_read_cb(struct osmo_stream_cli *conn)
289 {
290 return read_cb(conn, CHAN_SIGN_OML);
291 }
292
293 static int rsl_read_cb(struct osmo_stream_cli *conn)
294 {
295 return read_cb(conn, CHAN_SIGN_RSL);
296 }
297
298 struct osmo_chan_type chan_abis_ipa_cli = {
299 .type = OSMO_CHAN_ABIS_IPA_CLI,
300 .subtype = OSMO_SUBCHAN_STREAM,
301 .name = "A-bis IPA client",
302 .datasiz = sizeof(struct chan_abis_ipa_cli),
303 .create = chan_abis_ipa_cli_create,
304 .destroy = chan_abis_ipa_cli_destroy,
305 .open = chan_abis_ipa_cli_open,
306 .close = chan_abis_ipa_cli_close,
307 .enqueue = chan_abis_ipa_cli_enqueue,
308 };
+0
-421
src/channel/abis/ipa_stream_server.c less more
0 /* (C) 2012 by Pablo Neira Ayuso <pablo@gnumonks.org>
1 * All Rights Reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0+
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdlib.h>
20 #include <sys/types.h>
21 #include <netinet/in.h>
22 #include <netinet/tcp.h>
23 #include <sys/socket.h>
24 #include <errno.h>
25
26 #include <osmocom/core/talloc.h>
27 #include <osmocom/core/select.h>
28 #include <osmocom/core/msgb.h>
29 #include <osmocom/core/logging.h>
30
31 #include <osmocom/gsm/tlv.h>
32
33 #include <osmocom/netif/channel.h>
34 #include <osmocom/netif/stream.h>
35 #include <osmocom/netif/ipa.h>
36 #include <osmocom/netif/ipa_unit.h>
37
38 #define CHAN_SIGN_OML 0
39 #define CHAN_SIGN_RSL 1
40
41 /* default IPA srv ports. */
42 #define IPA_TCP_PORT_OML 3002
43 #define IPA_TCP_PORT_RSL 3003
44
45 static void *abis_ipa_srv_tall;
46
47 static int oml_accept_cb(struct osmo_stream_srv_link *srv, int fd);
48 static int rsl_accept_cb(struct osmo_stream_srv_link *srv, int fd);
49
50 struct chan_abis_ipa_srv {
51 struct osmo_chan *chan;
52 struct osmo_stream_srv_link *oml;
53 struct osmo_stream_srv_link *rsl;
54
55 struct llist_head bts_list;
56
57 void (*signal_msg)(struct msgb *msg, int type);
58 };
59
60 struct chan_abis_ipa_srv_conn {
61 struct chan_abis_ipa_srv *master;
62
63 struct osmo_stream_srv *oml;
64 struct osmo_stream_srv *rsl;
65 };
66
67 static int chan_abis_ipa_srv_create(struct osmo_chan *chan)
68 {
69 struct chan_abis_ipa_srv *c = (struct chan_abis_ipa_srv *)chan->data;
70
71 c->oml = osmo_stream_srv_link_create(abis_ipa_srv_tall);
72 if (c->oml == NULL)
73 goto err_oml;
74
75 /* default address and port for OML. */
76 osmo_stream_srv_link_set_addr(c->oml, "0.0.0.0");
77 osmo_stream_srv_link_set_port(c->oml, IPA_TCP_PORT_OML);
78 osmo_stream_srv_link_set_accept_cb(c->oml, oml_accept_cb);
79 osmo_stream_srv_link_set_data(c->oml, c);
80
81 c->rsl = osmo_stream_srv_link_create(abis_ipa_srv_tall);
82 if (c->rsl == NULL)
83 goto err_rsl;
84
85 /* default address and port for RSL. */
86 osmo_stream_srv_link_set_addr(c->rsl, "0.0.0.0");
87 osmo_stream_srv_link_set_port(c->rsl, IPA_TCP_PORT_RSL);
88 osmo_stream_srv_link_set_accept_cb(c->rsl, rsl_accept_cb);
89 osmo_stream_srv_link_set_data(c->rsl, c);
90
91 INIT_LLIST_HEAD(&c->bts_list);
92
93 return 0;
94 err_rsl:
95 osmo_stream_srv_link_destroy(c->oml);
96 err_oml:
97 return -1;
98 }
99
100 static void chan_abis_ipa_srv_destroy(struct osmo_chan *chan)
101 {
102 struct chan_abis_ipa_srv *c = (struct chan_abis_ipa_srv *)chan->data;
103
104 osmo_stream_srv_link_destroy(c->rsl);
105 osmo_stream_srv_link_destroy(c->oml);
106 }
107
108 static int chan_abis_ipa_srv_open(struct osmo_chan *chan)
109 {
110 struct chan_abis_ipa_srv *c = (struct chan_abis_ipa_srv *)chan->data;
111 struct osmo_fd *ofd;
112 int ret, on = 1;
113
114 if (osmo_stream_srv_link_open(c->oml) < 0)
115 goto err;
116
117 ofd = osmo_stream_srv_link_get_ofd(c->oml);
118 ret = setsockopt(ofd->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
119 if (ret < 0)
120 goto err_oml;
121
122 if (osmo_stream_srv_link_open(c->rsl) < 0)
123 goto err_oml;
124
125 ofd = osmo_stream_srv_link_get_ofd(c->rsl);
126 ret = setsockopt(ofd->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
127 if (ret < 0)
128 goto err_rsl;
129
130 return 0;
131
132 err_rsl:
133 osmo_stream_srv_link_close(c->rsl);
134 err_oml:
135 osmo_stream_srv_link_close(c->oml);
136 err:
137 return -1;
138 }
139
140 static void chan_abis_ipa_srv_close(struct osmo_chan *chan)
141 {
142 struct chan_abis_ipa_srv *c = (struct chan_abis_ipa_srv *)chan->data;
143
144 osmo_stream_srv_link_close(c->oml);
145 osmo_stream_srv_link_close(c->rsl);
146 }
147
148 static int chan_abis_ipa_srv_enqueue(struct osmo_chan *c, struct msgb *msg)
149 {
150 osmo_stream_srv_send(msg->dst, msg);
151 return 0;
152 }
153
154 void osmo_abis_ipa_srv_set_oml_addr(struct osmo_chan *c, const char *addr)
155 {
156 struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data;
157
158 osmo_stream_srv_link_set_addr(s->oml, addr);
159 }
160
161 void osmo_abis_ipa_srv_set_oml_port(struct osmo_chan *c, uint16_t port)
162 {
163 struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data;
164
165 osmo_stream_srv_link_set_port(s->oml, port);
166 }
167
168 void osmo_abis_ipa_srv_set_rsl_addr(struct osmo_chan *c, const char *addr)
169 {
170 struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data;
171
172 osmo_stream_srv_link_set_addr(s->rsl, addr);
173 }
174
175 void osmo_abis_ipa_srv_set_rsl_port(struct osmo_chan *c, uint16_t port)
176 {
177 struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data;
178
179 osmo_stream_srv_link_set_port(s->rsl, port);
180 }
181
182 void osmo_abis_ipa_srv_set_cb_signalmsg(struct osmo_chan *c,
183 void (*signal_msg)(struct msgb *msg, int type))
184 {
185 struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data;
186
187 s->signal_msg = signal_msg;
188 }
189
190 int
191 osmo_abis_ipa_unit_add(struct osmo_chan *c, uint16_t site_id, uint16_t bts_id)
192 {
193 struct osmo_ipa_unit *unit;
194 struct chan_abis_ipa_srv *s = (struct chan_abis_ipa_srv *)&c->data;
195 struct chan_abis_ipa_srv_conn *inst;
196
197 unit = osmo_ipa_unit_alloc(sizeof(struct chan_abis_ipa_srv_conn));
198 if (unit == NULL)
199 return -1;
200
201 osmo_ipa_unit_set_site_id(unit, site_id);
202 osmo_ipa_unit_set_bts_id(unit, bts_id);
203 osmo_ipa_unit_add(&s->bts_list, unit);
204
205 inst = osmo_ipa_unit_get_data(unit);
206 inst->master = s;
207
208 return 0;
209 }
210
211 static int oml_read_cb(struct osmo_stream_srv *conn);
212
213 static int oml_accept_cb(struct osmo_stream_srv_link *srv, int fd)
214 {
215 struct osmo_stream_srv *conn;
216 struct osmo_fd *ofd;
217
218 conn = osmo_stream_srv_create(abis_ipa_srv_tall,
219 srv, fd, oml_read_cb, NULL, NULL);
220 if (conn == NULL) {
221 LOGP(DLINP, LOGL_ERROR, "error while creating connection\n");
222 return -1;
223 }
224
225 ofd = osmo_stream_srv_get_ofd(conn);
226
227 /* XXX: better use chan_abis_ipa_srv_enqueue. */
228 ipaccess_send_id_req(ofd->fd);
229
230 return 0;
231 }
232
233 static int rsl_read_cb(struct osmo_stream_srv *conn);
234
235 static int rsl_accept_cb(struct osmo_stream_srv_link *srv, int fd)
236 {
237 struct osmo_stream_srv *conn;
238 struct osmo_fd *ofd;
239
240 conn = osmo_stream_srv_create(abis_ipa_srv_tall, srv, fd,
241 rsl_read_cb, NULL, NULL);
242 if (conn == NULL) {
243 LOGP(DLINP, LOGL_ERROR, "error while creating connection\n");
244 return -1;
245 }
246
247 ofd = osmo_stream_srv_get_ofd(conn);
248
249 /* XXX: better use chan_abis_ipa_srv_enqueue. */
250 ipaccess_send_id_req(ofd->fd);
251
252 return 0;
253 }
254
255 static void abis_ipa_put(struct osmo_ipa_unit *unit)
256 {
257 struct chan_abis_ipa_srv_conn *inst = osmo_ipa_unit_get_data(unit);
258
259 osmo_stream_srv_destroy(inst->oml);
260 osmo_stream_srv_destroy(inst->rsl);
261 inst->oml = NULL;
262 inst->rsl = NULL;
263 }
264
265 static int
266 abis_ipa_srv_rcvmsg(struct osmo_stream_srv *conn, struct msgb *msg, int type)
267 {
268 uint8_t msg_type = *(msg->l2h);
269 struct osmo_fd *ofd = osmo_stream_srv_get_ofd(conn);
270 struct osmo_stream_srv_link *link = osmo_stream_srv_get_master(conn);
271 struct chan_abis_ipa_srv *s = osmo_stream_srv_link_get_data(link);
272 struct chan_abis_ipa_srv_conn *inst;
273 int ret;
274
275 /* Handle IPA PING, PONG and ID_ACK messages */
276 if (osmo_ipa_rcvmsg_base(msg, ofd, 1)) /* XXX: 1 indicates server */
277 return 0;
278
279 if (msg_type == IPAC_MSGT_ID_RESP) {
280 struct osmo_ipa_unit *unit;
281 struct ipaccess_unit unit_data;
282
283 if (osmo_ipa_parse_msg_id_resp(msg, &unit_data) < 0) {
284 LOGP(DLINP, LOGL_ERROR, "bad ID RESP message\n");
285 return -EIO;
286 }
287
288 unit = osmo_ipa_unit_find(&s->bts_list, unit_data.site_id,
289 unit_data.bts_id);
290
291 if (unit == NULL) {
292 LOGP(DLINP, LOGL_ERROR, "Unable to find BTS "
293 "configuration for %u/%u/%u, disconnecting\n",
294 unit_data.site_id, unit_data.bts_id,
295 unit_data.trx_id);
296 return 0;
297 }
298 DEBUGP(DLINP, "Identified BTS %u/%u/%u\n",
299 unit_data.site_id, unit_data.bts_id,
300 unit_data.trx_id);
301
302 inst = osmo_ipa_unit_get_data(unit);
303
304 if (type == CHAN_SIGN_OML) {
305 if (inst->oml) {
306 /* link already exists, kill it. */
307 osmo_stream_srv_destroy(inst->oml);
308 return 0;
309 }
310 inst->oml = conn;
311 } else if (type == CHAN_SIGN_RSL) {
312 if (!inst->oml) {
313 /* no OML link? Restart from scratch. */
314 abis_ipa_put(unit);
315 return 0;
316 }
317 if (inst->rsl) {
318 /* RSL link already exists, kill it. */
319 osmo_stream_srv_destroy(inst->rsl);
320 return 0;
321 }
322 inst->rsl = conn;
323 }
324 osmo_stream_srv_set_data(conn, unit);
325 ret = 0;
326 } else {
327 LOGP(DLINP, LOGL_ERROR, "Unknown IPA message type\n");
328 ret = -EINVAL;
329 }
330 return ret;
331 }
332
333 static int read_cb(struct osmo_stream_srv *conn, int type)
334 {
335 int ret;
336 struct msgb *msg;
337 struct osmo_ipa_unit *unit = osmo_stream_srv_get_data(conn);
338 struct chan_abis_ipa_srv_conn *inst;
339 struct ipa_head *hh;
340
341 LOGP(DLINP, LOGL_DEBUG, "received message from stream\n");
342
343 msg = osmo_ipa_msg_alloc(0);
344 if (msg == NULL) {
345 LOGP(DLINP, LOGL_ERROR, "cannot allocate message\n");
346 return 0;
347 }
348 ret = osmo_stream_srv_recv(conn, msg);
349 if (ret < 0) {
350 LOGP(DLINP, LOGL_ERROR, "cannot receive message\n");
351 msgb_free(msg);
352 if (unit != NULL)
353 abis_ipa_put(unit);
354 else
355 osmo_stream_srv_destroy(conn);
356
357 return 0;
358 } else if (ret == 0) {
359 /* link has vanished, dead socket. */
360 LOGP(DLINP, LOGL_ERROR, "closed connection\n");
361 msgb_free(msg);
362 if (unit != NULL)
363 abis_ipa_put(unit);
364 else
365 osmo_stream_srv_destroy(conn);
366
367 return 0;
368 }
369 ret = osmo_ipa_process_msg(msg);
370 if (ret < 0) {
371 LOGP(DLINP, LOGL_ERROR, "invalid IPA message\n");
372 msgb_free(msg);
373 }
374
375 hh = (struct ipa_head *) msg->data;
376 if (hh->proto == IPAC_PROTO_IPACCESS) {
377 abis_ipa_srv_rcvmsg(conn, msg, type);
378 msgb_free(msg);
379 return -EIO;
380 }
381
382 if (unit == NULL) {
383 LOGP(DLINP, LOGL_ERROR, "no IPA unit associated to this "
384 "connection\n");
385 return -EIO;
386 }
387 inst = osmo_ipa_unit_get_data(unit);
388
389 if (hh->proto != IPAC_PROTO_OML && hh->proto != IPAC_PROTO_RSL) {
390 LOGP(DLINP, LOGL_ERROR, "wrong protocol\n");
391 return -EIO;
392 }
393 msg->dst = conn;
394
395 inst->master->signal_msg(msg, type);
396
397 return 0;
398 }
399
400 static int oml_read_cb(struct osmo_stream_srv *conn)
401 {
402 return read_cb(conn, CHAN_SIGN_OML);
403 }
404
405 static int rsl_read_cb(struct osmo_stream_srv *conn)
406 {
407 return read_cb(conn, CHAN_SIGN_RSL);
408 }
409
410 struct osmo_chan_type chan_abis_ipa_srv = {
411 .type = OSMO_CHAN_ABIS_IPA_SRV,
412 .subtype = OSMO_SUBCHAN_STREAM,
413 .name = "A-bis IPA server",
414 .datasiz = sizeof(struct chan_abis_ipa_srv),
415 .create = chan_abis_ipa_srv_create,
416 .destroy = chan_abis_ipa_srv_destroy,
417 .open = chan_abis_ipa_srv_open,
418 .close = chan_abis_ipa_srv_close,
419 .enqueue = chan_abis_ipa_srv_enqueue,
420 };
+0
-116
src/channel.c less more
0 /* (C) 2011-2012 by Pablo Neira Ayuso <pablo@gnumonks.org>
1 * All Rights Reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0+
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19 #include <osmocom/core/talloc.h>
20 #include <osmocom/core/msgb.h>
21 #include <osmocom/core/logging.h>
22 #include <osmocom/core/linuxlist.h>
23
24 #include <osmocom/netif/channel.h>
25
26 static LLIST_HEAD(channel_list);
27
28 extern struct osmo_chan_type chan_abis_ipa_srv;
29 extern struct osmo_chan_type chan_abis_ipa_cli;
30
31 static void *osmo_chan_ctx;
32
33 void osmo_chan_init(void *ctx)
34 {
35 osmo_chan_ctx = ctx;
36 llist_add(&chan_abis_ipa_srv.head, &channel_list);
37 llist_add(&chan_abis_ipa_cli.head, &channel_list);
38 /* add your new channel type here */
39 }
40
41 struct osmo_chan *osmo_chan_create(int type_id, int subtype_id)
42 {
43 struct osmo_chan_type *cur = NULL;
44 int found = 0, found_partial = 0;
45 struct osmo_chan *c;
46
47 if (type_id > OSMO_CHAN_MAX) {
48 LOGP(DLINP, LOGL_ERROR, "unsupported channel type "
49 "number `%u'\n", type_id);
50 return NULL;
51 }
52 if (subtype_id > OSMO_SUBCHAN_MAX) {
53 LOGP(DLINP, LOGL_ERROR, "unsupported subchannel type "
54 "number `%u'\n", type_id);
55 return NULL;
56 }
57
58 llist_for_each_entry(cur, &channel_list, head) {
59 if (type_id == cur->type && subtype_id == cur->subtype) {
60 found = 1;
61 break;
62 } else if (type_id == cur->type) {
63 found_partial = 1;
64 break;
65 }
66 }
67
68 if (!found) {
69 LOGP(DLINP, LOGL_ERROR, "unsupported channel type `%s'\n",
70 cur->name);
71 return NULL;
72 }
73 if (found_partial) {
74 LOGP(DLINP, LOGL_ERROR, "Sorry, channel type `%s' does not "
75 "support subtype `%u'\n", cur->name, subtype_id);
76 return NULL;
77 }
78
79 c = talloc_zero_size(osmo_chan_ctx,
80 sizeof(struct osmo_chan) + cur->datasiz);
81 if (c == NULL) {
82 LOGP(DLINP, LOGL_ERROR, "cannot allocate channel data\n");
83 return NULL;
84 }
85
86 c->ops = cur;
87
88 if (c->ops->create(c) < 0) {
89 LOGP(DLINP, LOGL_ERROR, "cannot create channel\n");
90 talloc_free(c);
91 return NULL;
92 }
93 return c;
94 }
95
96 void osmo_chan_destroy(struct osmo_chan *c)
97 {
98 c->ops->destroy(c);
99 talloc_free(c);
100 }
101
102 int osmo_chan_open(struct osmo_chan *c)
103 {
104 return c->ops->open(c);
105 }
106
107 void osmo_chan_close(struct osmo_chan *c)
108 {
109 c->ops->close(c);
110 }
111
112 int osmo_chan_enqueue(struct osmo_chan *c, struct msgb *msg)
113 {
114 return c->ops->enqueue(c, msg);
115 }
3030
3131 #include <osmocom/gsm/tlv.h>
3232
33 #include <osmocom/netif/channel.h>
3433 #include <osmocom/netif/ipa.h>
3534 #include <osmocom/netif/ipa_unit.h>
3635
116116 /* we reached the end, add to the tail: */
117117 llist_add_tail(&msg->list, msg_list);
118118
119 }
120
121 static void enqueue_pkt(struct osmo_jibuf *jb, struct msgb *msg, bool is_syncpoint)
122 {
123 struct msgb *cur;
124 struct timeval *msg_ts;
125
126 if (!is_syncpoint) {
127 llist_add_sorted(msg, &jb->msg_list);
128 return;
129 }
130
131 /* syncpoints change the reference timings, and as such they can provoke
132 out of order enqueuing of this packet and its followups with regards
133 to the already stored packets which may be scheduled for later times.
134 We thus need to adapt dequeue time for the already stored pkts to be
135 dequeued before the syncpoint pkt. See OS#3262 for related scenarios.
136 */
137
138 msg_ts = msgb_scheduled_ts(msg);
139
140 llist_for_each_entry(cur, &jb->msg_list, list) {
141 struct timeval *cur_ts = msgb_scheduled_ts(cur);
142 if (timercmp(msg_ts, cur_ts, <))
143 *cur_ts = *msg_ts;
144 }
145 /* syncpoint goes always to the end since we moved all older packets
146 before it */
147 llist_add_tail(&msg->list, &jb->msg_list);
119148 }
120149
121150 static bool msg_get_marker(struct msgb *msg)
313342 {
314343 int rel_delay, delay;
315344 struct timeval delay_ts, sched_ts;
345 bool is_syncpoint;
316346
317347 clock_gettime_timeval(CLOCK_MONOTONIC, &jb->last_enqueue_time);
318348
319349 /* Check if it's time to sync, ie. start of talkspurt */
320 if (!jb->started || msg_is_syncpoint(jb, msg)) {
350 is_syncpoint = !jb->started || msg_is_syncpoint(jb, msg);
351 if (is_syncpoint) {
321352 jb->started = true;
322353 msg_set_as_reference(jb, msg);
323354 rel_delay = 0;
364395 jbcb->ts = sched_ts;
365396 jbcb->old_cb = old_cb;
366397
367 llist_add_sorted(msg, &jb->msg_list);
368
398 enqueue_pkt(jb, msg, is_syncpoint);
369399
370400 /* See if updating the timer is needed: */
371401 if (!osmo_timer_pending(&jb->timer) ||
355355 static int osmux_batch_enqueue(struct msgb *msg, struct osmux_circuit *circuit,
356356 uint8_t batch_factor)
357357 {
358 /* Too many messages per batch, discard it. The counter field of the
358 /* Validate amount of messages per batch. The counter field of the
359359 * osmux header is just 3 bits long, so make sure it doesn't overflow.
360360 */
361361 if (circuit->nmsgs >= batch_factor || circuit->nmsgs >= 8) {
365365 if (rtph == NULL)
366366 return -1;
367367
368 LOGP(DLMUX, LOGL_ERROR, "too many messages for this RTP "
368 LOGP(DLMUX, LOGL_DEBUG, "Batch is full for RTP "
369369 "ssrc=%u\n", rtph->ssrc);
370370 return -1;
371371 }
450450 ret = osmo_sock_init2(AF_INET, SOCK_STREAM, cli->proto,
451451 cli->local_addr, cli->local_port,
452452 cli->addr, cli->port,
453 OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_BIND);
453 OSMO_SOCK_F_CONNECT|OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);
454454 if (ret < 0) {
455455 if (reconnect)
456456 osmo_stream_cli_reconnect(cli);
618618 osmo_jibuf_delete(jb);
619619 }
620620
621 void test_rtp_out_of_sync(unsigned int time_inc_ms, uint16_t seq_nosync_inc, uint32_t ts_nosync_inc, bool expect_drop)
621 /* This test aims at testing scenarios described in OS#3262, in which syncpoint
622 packets can provoke a situation in which packets are stored out-of-order in
623 the queue. */
624 static void test_rtp_marker_queue_order()
625 {
626 int min_delay = 60;
627 struct msgb *msg;
628 struct rtp_hdr *rtph;
629
630 printf("===test_rtp_marker_queue_order===\n");
631
632 clock_override_enable(true);
633 clock_override_set(0, 0);
634 rtp_init(32, 400);
635 jb = osmo_jibuf_alloc(NULL);
636 osmo_jibuf_set_dequeue_cb(jb, dequeue_cb, NULL);
637 osmo_jibuf_set_min_delay(jb, min_delay);
638 osmo_jibuf_set_max_delay(jb, 200);
639
640 /* First rtp at t=0, should be scheduled in min_delay time */
641 clock_debug("enqueue 1st packet");
642 ENQUEUE_NEXT(jb);
643 clock_override_add(0, TIME_RTP_PKT_MS*1000);
644 clock_debug("enqueue 2nd packet");
645 ENQUEUE_NEXT(jb);
646 clock_override_add(0, TIME_RTP_PKT_MS*1000);
647 clock_debug("enqueue 3rd packet");
648 ENQUEUE_NEXT(jb);
649 clock_override_add(0, TIME_RTP_PKT_MS*1000);
650
651 /* We then emulate an scenario in which an Osmux queue in front of us
652 receives a new frame before expected time, which means the packets in
653 the osmux genreated rtp queue will be flushed and sent to jibuf
654 directly. On top, the first packet of the new frame has the RTP
655 Marker bit set. */
656 clock_debug("enqueue 3 packets instantly");
657 ENQUEUE_NEXT(jb); /* scheduled min_delay+0 */
658 ENQUEUE_NEXT(jb); /* a min_delay+TIME_RTP_PKT_MS */
659 ENQUEUE_NEXT(jb); /* scheduled min_delay+TIME_RTP_PKT_MS*2 */
660 clock_debug("enqueue pkt with marker=1 instantly");
661 msg = rtp_next();
662 rtph = osmo_rtp_get_hdr(msg);
663 rtph->marker = 1;
664 OSMO_ASSERT(osmo_jibuf_enqueue(jb, msg) == 0); /* syncpoint, scheduled in min_delay+0 */
665 osmo_select_main(0);
666
667 clock_override_add(0, TIME_RTP_PKT_MS*1000);
668 clock_debug("enqueue pkt after syncpoint");
669 ENQUEUE_NEXT(jb); /* scheduled min_delay+0 */
670
671 clock_debug("all packets dequeued");
672 clock_override_add(0, min_delay*1000);
673 osmo_select_main(0);
674
675 OSMO_ASSERT(osmo_jibuf_empty(jb));
676
677 osmo_jibuf_delete(jb);
678 }
679
680 static void test_rtp_out_of_sync(unsigned int time_inc_ms, uint16_t seq_nosync_inc, uint32_t ts_nosync_inc, bool expect_drop)
622681 {
623682 int min_delay = 60;
624683 struct msgb *msg;
685744 }
686745
687746
688 void test_skew(unsigned int skew_inc_us, bool skew_compensation) {
747 static void test_skew(unsigned int skew_inc_us, bool skew_compensation) {
689748 int min_delay = 40;
690749 unsigned int dropped = 0;
691750 struct msgb *msg;
753812 test_seq_wraparound();
754813 test_timestamp_wraparound();
755814 test_rtp_marker();
815 test_rtp_marker_queue_order();
756816 test_rtp_out_of_sync(80*TIME_RTP_PKT_MS, 5, 5*SAMPLES_PER_PKT, true);
757817 test_rtp_out_of_sync(80*TIME_RTP_PKT_MS, 6, 5*SAMPLES_PER_PKT, false);
758818 test_rtp_out_of_sync(80*TIME_RTP_PKT_MS, 5, 5*SAMPLES_PER_PKT + 3, false);
364364 sys={0.200000}, mono={0.200000}: clock_override_add
365365 sys={0.200000}, mono={0.200000}: dequeue: seq=35 ts=880 INTERMEDIATE
366366 sys={0.200000}, mono={0.200000}: dequeue: seq=36 ts=1040 LATEST
367 ===test_rtp_marker_queue_order===
368 sys={0.000000}, mono={0.000000}: clock_override_set
369 sys={0.000000}, mono={0.000000}: enqueue 1st packet
370 sys={0.020000}, mono={0.020000}: clock_override_add
371 sys={0.020000}, mono={0.020000}: enqueue 2nd packet
372 sys={0.040000}, mono={0.040000}: clock_override_add
373 sys={0.040000}, mono={0.040000}: enqueue 3rd packet
374 sys={0.060000}, mono={0.060000}: clock_override_add
375 sys={0.060000}, mono={0.060000}: enqueue 3 packets instantly
376 sys={0.060000}, mono={0.060000}: enqueue pkt with marker=1 instantly
377 sys={0.060000}, mono={0.060000}: dequeue: seq=33 ts=560 INTERMEDIATE
378 sys={0.080000}, mono={0.080000}: clock_override_add
379 sys={0.080000}, mono={0.080000}: enqueue pkt after syncpoint
380 sys={0.080000}, mono={0.080000}: all packets dequeued
381 sys={0.140000}, mono={0.140000}: clock_override_add
382 sys={0.140000}, mono={0.140000}: dequeue: seq=34 ts=720 INTERMEDIATE
383 sys={0.140000}, mono={0.140000}: dequeue: seq=35 ts=880 INTERMEDIATE
384 sys={0.140000}, mono={0.140000}: dequeue: seq=36 ts=1040 INTERMEDIATE
385 sys={0.140000}, mono={0.140000}: dequeue: seq=37 ts=1200 INTERMEDIATE
386 sys={0.140000}, mono={0.140000}: dequeue: seq=38 ts=1360 INTERMEDIATE
387 sys={0.140000}, mono={0.140000}: dequeue: seq=39 ts=1520 INTERMEDIATE
388 sys={0.140000}, mono={0.140000}: dequeue: seq=40 ts=1680 LATEST
367389 ===test_rtp_out_of_sync(1600, 5, 800, 1)===
368390 sys={0.000000}, mono={0.000000}: clock_override_set
369391 sys={0.000000}, mono={0.000000}: enqueue 1st packet (seq=33, ts=560)