arehbein has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-netif/+/33652 )
Change subject: ipa: Add segmentation callback ......................................................................
ipa: Add segmentation callback
Also: Add helper functions used in later commits
Related: OS#5753 Change-Id: I87ef4c7023126b783dd79e7ed47be31e1b76f975 --- M include/osmocom/netif/ipa.h M src/ipa.c 2 files changed, 101 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-netif refs/changes/52/33652/1
diff --git a/include/osmocom/netif/ipa.h b/include/osmocom/netif/ipa.h index 0d1085f..12358ba 100644 --- a/include/osmocom/netif/ipa.h +++ b/include/osmocom/netif/ipa.h @@ -19,6 +19,8 @@ } __attribute__ ((packed));
struct msgb *osmo_ipa_msg_alloc(int headroom); +struct msgb *osmo_ipa_ext_msg_alloc(int headroom); + void osmo_ipa_msg_push_header(struct msgb *msg, uint8_t proto);
int osmo_ipa_process_msg(struct msgb *msg); diff --git a/src/ipa.c b/src/ipa.c index 197a47f..33801af 100644 --- a/src/ipa.c +++ b/src/ipa.c @@ -33,6 +33,7 @@
#include <osmocom/netif/ipa.h> #include <osmocom/netif/ipa_unit.h> +#include <osmocom/netif/stream.h>
#define IPA_ALLOC_SIZE 1200
@@ -97,6 +98,11 @@ return msg; }
+struct msgb *osmo_ipa_ext_msg_alloc(int headroom) +{ + return osmo_ipa_msg_alloc(sizeof(struct ipa_head_ext) + headroom); +} + void osmo_ipa_msg_push_header(struct msgb *msg, uint8_t proto) { struct ipa_head *hh; @@ -366,3 +372,84 @@
return 0; } + +#define MSG_CB_IPA_PROTO_OFFSET 0 +/* Used in case of IPAC_PROTO_OSMO */ +#define MSG_CB_IPA_PROTO_EXT_IS_SET_OFFSET 1 +#define MSG_CB_IPA_PROTO_EXT_OFFSET 2 + +/* Check and remove headers (in case of p == IPAC_PROTO_OSMO, also the IPA extension header). + * Returns a negative number on error, otherwise zero */ +static inline int ipa_check_pull_headers(struct msgb *msg) +{ + int ret; + msg->l1h = msg->data; + struct ipa_head *ih = (struct ipa_head *)msg->data; + memset(msg->cb, 0, sizeof(msg->cb)); + msg->cb[MSG_CB_IPA_PROTO_OFFSET] = ih->proto; + if ((ret = osmo_ipa_process_msg(msg)) < 0) { + LOGP(DLINP, LOGL_ERROR, "Error processing IPA message\n"); + return -EIO; + } + msgb_pull(msg, sizeof(struct ipa_head)); + msg->l2h = msg->data; + msg->cb[MSG_CB_IPA_PROTO_EXT_IS_SET_OFFSET] = true; + msg->cb[MSG_CB_IPA_PROTO_EXT_OFFSET] = msg->data[0]; + if (ih->proto != IPAC_PROTO_OSMO) + return 0; + msgb_pull(msg, sizeof(struct ipa_head_ext)); + return 0; +} + +/*! Segmentation callback used by libosmo-netif streaming backend + * See definition of `struct osmo_io_ops` for callback semantics + * \param[out] msg Original `struct msgb` received via osmo_io + * \returns The total packet length indicated by the first header, + * otherwise + * -EAGAIN, if the header has not been read yet, + * -ENOBUFS, if the header declares a payload too large + */ +int osmo_ipa_segmentation_cb(struct msgb *msg) +{ + const struct ipaccess_head *hh = (const struct ipaccess_head *) msg->data; + size_t payload_len, total_len; + size_t available = msgb_length(msg) + msgb_tailroom(msg); + if (msgb_length(msg) < sizeof(*hh)) { + /* Haven't even read the entire header */ + return -EAGAIN; + } + payload_len = osmo_ntohs(hh->len); + total_len = sizeof(*hh) + payload_len; + if (OSMO_UNLIKELY(available < total_len)) { + LOGP(DLINP, LOGL_ERROR, "Not enough space left in message buffer. " + "Have %zu octets, but need %zu\n", + available, total_len); + return -ENOBUFS; + } + return total_len; +} + +/* Below: Helper functions for addition of send_ipa functionality in later commit */ +static inline enum ipaccess_proto msg_get_ipa_proto(struct msgb *msg) +{ + return msg->cb[MSG_CB_IPA_PROTO_OFFSET]; +} + +/* 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->cb[MSG_CB_IPA_PROTO_EXT_IS_SET_OFFSET]) + return -ENOPROTOOPT; + return msg->cb[MSG_CB_IPA_PROTO_EXT_OFFSET]; +} + +/* 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); +}