arehbein has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-netif/+/33201 )
Change subject: stream: Add IPA send function/IPA-mode read to srv ......................................................................
stream: Add IPA send function/IPA-mode read to srv
Also: Adapt the example to work with the new changes.
Related OS#5753, OS#5751
Change-Id: I61e1fe59166c46595efe8c1f32b8f2607cb6c529 --- M examples/ipa-stream-server.c M include/osmocom/netif/stream.h M src/stream.c M tests/stream/stream_test.c M tests/stream/stream_test.ok 5 files changed, 114 insertions(+), 21 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-netif refs/changes/01/33201/1
diff --git a/examples/ipa-stream-server.c b/examples/ipa-stream-server.c index df5c26c..3146e63 100644 --- a/examples/ipa-stream-server.c +++ b/examples/ipa-stream-server.c @@ -49,15 +49,9 @@
int read_cb(struct osmo_stream_srv *conn, struct msgb *msg) { - LOGP(DSTREAMTEST, LOGL_DEBUG, "received message from stream (len=%d)\n", msgb_length(msg)); + LOGP(DSTREAMTEST, LOGL_DEBUG, "received message from stream (payload len=%d)\n", msgb_length(msg));
- if (osmo_ipa_process_msg(msg) < 0) { - LOGP(DSTREAMTEST, LOGL_ERROR, "Bad IPA message\n"); - msgb_free(msg); - return 0; - } - - osmo_stream_srv_send(conn, msg); + osmo_stream_srv_send_ipa(conn, IPAC_PROTO_UNSPECIFIED, IPAC_PROTO_UNSPECIFIED, msg); return 0; }
diff --git a/include/osmocom/netif/stream.h b/include/osmocom/netif/stream.h index fa76d96..16940dc 100644 --- a/include/osmocom/netif/stream.h +++ b/include/osmocom/netif/stream.h @@ -4,6 +4,7 @@ #include <stdint.h>
#include <osmocom/core/msgb.h> +#include <osmocom/gsm/protocol/ipaccess.h>
/*! \addtogroup stream * @{ @@ -29,6 +30,8 @@ _NUM_OSMO_STREAM_PROTOS };
+#define IPAC_PROTO_UNSPECIFIED -1 + /*! \brief Shortcut for unsetting the stream protocol (gets rid of segmentation pertaining to stream protocol) */ #define osmo_stream_srv_link_unset_stream_proto(struct_osmo_stream_srv_link_ptr)\ osmo_stream_srv_link_set_stream_proto(struct_osmo_stream_srv_link_ptr, OSMO_STREAM_UNSPECIFIED) @@ -68,6 +71,8 @@ void osmo_stream_srv_set_data(struct osmo_stream_srv *conn, void *data);
void osmo_stream_srv_send(struct osmo_stream_srv *conn, struct msgb *msg); +void osmo_stream_srv_send_ipa(struct osmo_stream_srv *conn, int ipaccess_proto, + enum ipaccess_proto_ext pe, struct msgb *msg); int osmo_stream_srv_recv(struct osmo_stream_srv *conn, struct msgb *msg);
void osmo_stream_srv_clear_tx_queue(struct osmo_stream_srv *conn); diff --git a/src/stream.c b/src/stream.c index fbce7b4..396f344 100644 --- a/src/stream.c +++ b/src/stream.c @@ -44,6 +44,7 @@ #include <osmocom/core/talloc.h> #include <osmocom/core/socket.h>
+#include <osmocom/netif/ipa.h> #include <osmocom/netif/stream.h>
#include "config.h" @@ -628,6 +629,45 @@ cli->connect_cb(cli); }
+#define LOG_CLI_OR_SRV(cli, level, fmt, args...) do {\ + if (cli != NULL)\ + LOGSCLI(cli, level, fmt, ## args);\ + else\ + LOGP(DLINP, level, fmt, ## args);\ +} while (0) + +/* Check and remove headers, in case of p == IPAC_PROTO_OSMO also the IPA extension header. + * Returns a negative number on error, otherwise the number of header octets removed */ +static inline int ipa_check_pull_headers(struct msgb *msg, struct osmo_stream_cli *cli) +{ + int ret; + size_t octets_removed = 0; + msg->l1h = msg->data; + struct ipa_head *ih = (struct ipa_head *)msg->data; + if ((ret = osmo_ipa_process_msg(msg)) < 0) { + LOG_CLI_OR_SRV(cli, LOGL_ERROR, "Error processing IPA message\n"); + return ret; + } + msgb_pull(msg, sizeof(struct ipa_head)); + octets_removed += sizeof(struct ipa_head); + if (ih->proto != IPAC_PROTO_OSMO) /* No extensions expected */ + return octets_removed; + msg->l2h = msg->data; + msgb_pull(msg, sizeof(struct ipa_head_ext)); + octets_removed += sizeof(struct ipa_head_ext); + return octets_removed; +} + +/* Push IPA headers; if we have IPAC_PROTO_OSMO this also takes care of the + * extension header */ +static inline void ipa_push_headers(enum ipaccess_proto p, enum ipaccess_proto_ext pe, + struct msgb *msg) +{ + if (p == IPAC_PROTO_OSMO) + ipa_prepend_header_ext(msg, pe); + osmo_ipa_msg_push_header(msg, p); +} + static void stream_cli_iofd_read_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg) { struct osmo_stream_cli *cli = osmo_iofd_get_data(iofd); @@ -1419,6 +1459,8 @@ if (osmo_iofd_txqueue_len(iofd) == 0) osmo_stream_srv_destroy(conn); } else if (conn->iofd_read_cb) { + if (conn->srv->stream_proto == OSMO_STREAM_IPAC) + ipa_check_pull_headers(msg, NULL); conn->iofd_read_cb(conn, msg); // TODO: Handle return value? }
@@ -1883,6 +1925,46 @@ talloc_free(conn); }
+/* msgb_l1(msg) is expected to be set */ +static inline enum ipaccess_proto msg_get_ipa_proto(struct msgb *msg) +{ + struct ipa_head *ih = msgb_l1(msg); + OSMO_ASSERT(ih); + return ih->proto; +} + +/* msgb->l1h is expected to be set, msgb->l2h is expected to be set if + * we have IPAC_PROTO_OSMO specified in the header. + * Returns the protocol extension (enum ipaccess_proto) or -ENOPROTOOPT if + * we don't have IPAC_PROTO_OSMO specified in the IPA header */ +static inline int msg_get_ipa_proto_ext(struct msgb *msg) +{ + if (msg_get_ipa_proto(msg) != IPAC_PROTO_OSMO) + return -ENOPROTOOPT; + struct ipa_head_ext *ihe = msgb_l2(msg); + OSMO_ASSERT(ihe); + return ihe->proto; +} + +/*! \brief Enqueue IPA data to be sent via an Osmocom stream server + * \param[in] conn Stream Server through which we want to send + * \param[in] p Protocol transported by IPA. When set to IPAC_PROTO_UNSPECIFIED, the protocol will be + * read from the msgb structure's l1 and possibly l2 headers. + * \param[in] pe Ignored, unless p == IPAC_PROTO_OSMO, in which case this specifies the + * Osmocom protocol extension + * \param[in] msg Message buffer to enqueue in transmit queue */ +void osmo_stream_srv_send_ipa(struct osmo_stream_srv *conn, int ipaccess_proto, + enum ipaccess_proto_ext pe, struct msgb *msg) +{ + OSMO_ASSERT(msg); + if (ipaccess_proto == IPAC_PROTO_UNSPECIFIED) { + ipaccess_proto = msg_get_ipa_proto(msg); + pe = msg_get_ipa_proto_ext(msg); + } + ipa_push_headers(ipaccess_proto, pe, msg); + osmo_stream_srv_send(conn, msg); +} + /*! \brief Enqueue data to be sent via an Osmocom stream server * \param[in] conn Stream Server through which we want to send * \param[in] msg Message buffer to enqueue in transmit queue */ diff --git a/tests/stream/stream_test.c b/tests/stream/stream_test.c index b537d5e..4d0ad1e 100644 --- a/tests/stream/stream_test.c +++ b/tests/stream/stream_test.c @@ -553,23 +553,22 @@ { unsigned char *data; struct msgb *m; - uint8_t *msgt = msg->data + sizeof(struct ipa_head); - LOGSRV(conn, "[%u-srv] Received message from stream (len = %" PRIu16 ")\n", + uint8_t *msgt = msg->l2h; /* Octet right after IPA header */ + LOGSRV(conn, "[%u-srv] Received IPA message from stream (paylod len = %" PRIu16 ")\n", ++msgnum_srv, msgb_length(msg)); - msgb_pull(msg, sizeof(struct ipa_head)); LOGSRV(conn, "\tIPA data: %s\n", osmo_hexdump(msg->data, msg->len)); LOGSRV(conn, "\tType: %s\n", IPAC_MSG_TYPES[*msgt]); - LOGSRV(conn, "\t(msg dump: %s)\n", osmo_hexdump(msg->data - sizeof(struct ipa_head), - msg->len + sizeof(struct ipa_head))); + LOGSRV(conn, "\t(msg dump: %s)\n", osmo_hexdump(msg->l1h, msg->len + sizeof(struct ipa_head))); if (*msgt == IPAC_MSGT_ID_RESP) { /* */ LOGSRV(conn, "Send IPAC_MSGT_ID_GET to trigger client to send 2nd half\n\n"); - m = msgb_alloc_headroom(128, 0, "IPA messages"); + m = msgb_alloc_headroom(128, sizeof(struct ipa_head), "IPA messages"); if (m == NULL) { fprintf(stderr, "Cannot allocate message\n"); return -ENOMEM; } - put_ipa_msg(data, m, ipac_msg_idreq); - osmo_stream_srv_send(conn, m); + data = msgb_put(m, IPAC_MSG_ID_REQ_LEN); + memcpy(data, ipac_msg_idreq + sizeof(struct ipa_head), IPAC_MSG_ID_REQ_LEN); + osmo_stream_srv_send_ipa(conn, IPAC_PROTO_IPACCESS, -1, m); } else if (*msgt == IPAC_MSGT_ID_GET) { all_msgs_processed = true; } diff --git a/tests/stream/stream_test.ok b/tests/stream/stream_test.ok index 7763212..65a7478 100644 --- a/tests/stream/stream_test.ok +++ b/tests/stream/stream_test.ok @@ -62,19 +62,19 @@ {20.000020} [OK] Client's test_segm_cli_connect_cb(): Sending 4 1/2 messages as one: {20.000020} [OK] Client's test_segm_cli_connect_cb(): (msg dump: 00 01 fe 00 00 01 fe 01 00 01 fe 00 00 07 fe 05 01 01 de ad be ef 00 03 fe )
-{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [1-srv] Received message from stream (len = 4) +{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [1-srv] Received IPA message from stream (paylod len = 1) {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): IPA data: 00 {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): Type: IPAC_MSGT_PING {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): (msg dump: 00 01 fe 00 ) -{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [2-srv] Received message from stream (len = 4) +{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [2-srv] Received IPA message from stream (paylod len = 1) {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): IPA data: 01 {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): Type: IPAC_MSGT_PONG {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): (msg dump: 00 01 fe 01 ) -{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [3-srv] Received message from stream (len = 4) +{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [3-srv] Received IPA message from stream (paylod len = 1) {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): IPA data: 00 {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): Type: IPAC_MSGT_PING {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): (msg dump: 00 01 fe 00 ) -{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [4-srv] Received message from stream (len = 10) +{20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): [4-srv] Received IPA message from stream (paylod len = 7) {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): IPA data: 05 01 01 de ad be ef {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): Type: IPAC_MSGT_ID_RESP {20.000022} [NA|OK] Server's test_segm_stream_srv_read_cb(): (msg dump: 00 07 fe 05 01 01 de ad be ef ) @@ -86,7 +86,7 @@ {20.000024} [OK] Client's test_segm_stream_cli_read_cb(): [5-cli] Sending second half of IPAC_MSGT_ID_GET {20.000024} [OK] Client's test_segm_stream_cli_read_cb(): (msg dump: 04 01 01 )
-{20.000026} [NA|OK] Server's test_segm_stream_srv_read_cb(): [5-srv] Received message from stream (len = 6) +{20.000026} [NA|OK] Server's test_segm_stream_srv_read_cb(): [5-srv] Received IPA message from stream (paylod len = 3) {20.000026} [NA|OK] Server's test_segm_stream_srv_read_cb(): IPA data: 04 01 01 {20.000026} [NA|OK] Server's test_segm_stream_srv_read_cb(): Type: IPAC_MSGT_ID_GET {20.000026} [NA|OK] Server's test_segm_stream_srv_read_cb(): (msg dump: 00 03 fe 04 01 01 )